[vlc-devel] [PATCH 1/3] hotkeys: listen to new inputs and new vouts

Steve Lhomme robux4 at gmail.com
Thu Nov 17 17:11:28 CET 2016


On Thu, Nov 17, 2016 at 4:50 PM, Thomas Guillem <thomas at gllm.fr> wrote:
> Listen to playlist "input-current" to update the current input_thead_t, and
> listen to input "intf-event" to update the current vout. The vout/input don't
> need to be fetched when processing an action, this removes one FIXME, but this
> adds more lock complexity.
>
> This will be mainly needed for the next commit, in order to listen to mouse
> events from the vout.
> ---
>  modules/control/hotkeys.c | 189 ++++++++++++++++++++++++++++++++++------------
>  1 file changed, 140 insertions(+), 49 deletions(-)
>
> diff --git a/modules/control/hotkeys.c b/modules/control/hotkeys.c
> index 40b9672..b7cfb63 100644
> --- a/modules/control/hotkeys.c
> +++ b/modules/control/hotkeys.c
> @@ -42,12 +42,16 @@
>  #include <vlc_keys.h>
>  #include "math.h"
>
> +#include <assert.h>
> +
>  /*****************************************************************************
>   * intf_sys_t: description and status of FB interface
>   *****************************************************************************/
>  struct intf_sys_t
>  {
> -    vout_thread_t      *p_last_vout;
> +    vlc_mutex_t         lock;
> +    vout_thread_t      *p_vout;
> +    input_thread_t     *p_input;
>      int slider_chan;
>
>      /*subtitle_delaybookmarks: placeholder for storing subtitle sync timestamps*/
> @@ -67,11 +71,11 @@ static int  ActionEvent( vlc_object_t *, char const *,
>                           vlc_value_t, vlc_value_t, void * );
>  static void PlayBookmark( intf_thread_t *, int );
>  static void SetBookmark ( intf_thread_t *, int );
> -static void DisplayPosition( intf_thread_t *, vout_thread_t *, input_thread_t * );
> -static void DisplayVolume( intf_thread_t *, vout_thread_t *, float );
> +static void DisplayPosition( vout_thread_t *, int,  input_thread_t * );
> +static void DisplayVolume( vout_thread_t *, int, float );
>  static void DisplayRate ( vout_thread_t *, float );
>  static float AdjustRateFine( vlc_object_t *, const int );
> -static void ClearChannels  ( intf_thread_t *, vout_thread_t * );
> +static void ClearChannels  ( vout_thread_t *, int );
>
>  #define DisplayMessage(vout, ...) \
>      do { \
> @@ -95,6 +99,83 @@ vlc_module_begin ()
>
>  vlc_module_end ()
>
> +static void ChangeVout( intf_thread_t *p_intf, vout_thread_t *p_vout )
> +{
> +    intf_sys_t *p_sys = p_intf->p_sys;
> +
> +    int slider_chan;
> +    if( p_vout != NULL )
> +        slider_chan = vout_RegisterSubpictureChannel( p_vout );

Is there a reason you don't do that in the lock ?

> +
> +    vlc_mutex_lock( &p_sys->lock );
> +    vout_thread_t *p_old_vout = p_sys->p_vout;
> +    p_sys->p_vout = p_vout;
> +    if( p_vout != NULL )
> +        p_sys->slider_chan = slider_chan;
> +    vlc_mutex_unlock( &p_sys->lock );
> +
> +    if( p_old_vout != NULL )
> +        vlc_object_release( p_old_vout );
> +}
> +
> +static int InputEvent( vlc_object_t *p_this, char const *psz_var,
> +                       vlc_value_t oldval, vlc_value_t val, void *p_data )
> +{
> +    input_thread_t *p_input = (input_thread_t *)p_this;
> +    intf_thread_t *p_intf = p_data;
> +
> +    (void) psz_var; (void) oldval;
> +
> +    if( val.i_int == INPUT_EVENT_VOUT )
> +        ChangeVout( p_intf, input_GetVout( p_input ) );
> +
> +    return VLC_SUCCESS;
> +}
> +
> +static void ChangeInput( intf_thread_t *p_intf, input_thread_t *p_input )
> +{
> +    intf_sys_t *p_sys = p_intf->p_sys;
> +
> +    if( p_sys->p_input != NULL )
> +    {
> +        /* First, remove callbacks from previous input. It's safe to access it
> +         * unlocked, since it's written from this thread */
> +        var_DelCallback( p_sys->p_input, "intf-event", InputEvent, p_intf );
> +    }
> +
> +    /* Replace input and vout locked */
> +    vlc_mutex_lock( &p_sys->lock );
> +    input_thread_t *p_old_input = p_sys->p_input;
> +    vout_thread_t *p_old_vout = p_sys->p_vout;
> +    p_sys->p_input = p_input ? vlc_object_hold( p_input ) : NULL;
> +    p_sys->p_vout = NULL;

Maybe call ChangeVout( p_intf, NULL) ? You won't have to release the vout below.

> +    vlc_mutex_unlock( &p_sys->lock );
> +
> +    /* Release old input and vout objects unlocked */
> +    if( p_old_input != NULL )
> +    {
> +        if( p_old_vout != NULL )
> +            vlc_object_release( p_old_vout );
> +        vlc_object_release( p_old_input );
> +    }
> +
> +    /* Register input events */
> +    if( p_input != NULL )
> +        var_AddCallback( p_input, "intf-event", InputEvent, p_intf );
> +}
> +
> +static int PlaylistEvent( vlc_object_t *p_this, char const *psz_var,
> +                          vlc_value_t oldval, vlc_value_t val, void *p_data )
> +{
> +    intf_thread_t *p_intf = p_data;
> +
> +    (void) p_this; (void) psz_var; (void) oldval;
> +
> +    ChangeInput( p_intf, val.p_address );
> +
> +    return VLC_SUCCESS;
> +}
> +
>  /*****************************************************************************
>   * Open: initialize interface
>   *****************************************************************************/
> @@ -108,11 +189,17 @@ static int Open( vlc_object_t *p_this )
>
>      p_intf->p_sys = p_sys;
>
> -    p_sys->p_last_vout = NULL;
> +    p_sys->p_vout = NULL;
> +    p_sys->p_input = NULL;
>      p_sys->subtitle_delaybookmarks.i_time_audio = 0;
>      p_sys->subtitle_delaybookmarks.i_time_subtitle = 0;
>
> +    vlc_mutex_init( &p_sys->lock );
> +
>      var_AddCallback( p_intf->obj.libvlc, "key-action", ActionEvent, p_intf );
> +
> +    var_AddCallback( pl_Get(p_intf), "input-current", PlaylistEvent, p_intf );
> +
>      return VLC_SUCCESS;
>  }
>
> @@ -124,31 +211,24 @@ static void Close( vlc_object_t *p_this )
>      intf_thread_t *p_intf = (intf_thread_t *)p_this;
>      intf_sys_t *p_sys = p_intf->p_sys;
>
> +    var_DelCallback( pl_Get(p_intf), "input-current", PlaylistEvent, p_intf );
> +
>      var_DelCallback( p_intf->obj.libvlc, "key-action", ActionEvent, p_intf );
>
> +    ChangeInput( p_intf, NULL );
> +
> +    vlc_mutex_destroy( &p_sys->lock );
> +
>      /* Destroy structure */
>      free( p_sys );
>  }
>
> -static int PutAction( intf_thread_t *p_intf, int i_action )
> +static int PutAction( intf_thread_t *p_intf, input_thread_t *p_input,
> +                      vout_thread_t *p_vout, int slider_chan, int i_action )
>  {
>      intf_sys_t *p_sys = p_intf->p_sys;
>      playlist_t *p_playlist = pl_Get( p_intf );
>
> -    /* Update the input */
> -    input_thread_t *p_input = playlist_CurrentInput( p_playlist );
> -
> -    /* Update the vout */
> -    vout_thread_t *p_vout = p_input ? input_GetVout( p_input ) : NULL;
> -
> -    /* Register OSD channels */
> -    /* FIXME: this check can fail if the new vout is reallocated at the same
> -     * address as the old one... We should rather listen to vout events.
> -     * Alternatively, we should keep a reference to the vout thread. */
> -    if( p_vout && p_vout != p_sys->p_last_vout )
> -        p_sys->slider_chan = vout_RegisterSubpictureChannel( p_vout );
> -    p_sys->p_last_vout = p_vout;
> -
>      /* Quit */
>      switch( i_action )
>      {
> @@ -156,7 +236,7 @@ static int PutAction( intf_thread_t *p_intf, int i_action )
>          case ACTIONID_QUIT:
>              libvlc_Quit( p_intf->obj.libvlc );
>
> -            ClearChannels( p_intf, p_vout );
> +            ClearChannels( p_vout, slider_chan );
>              DisplayMessage( p_vout, _( "Quit" ) );
>              break;
>
> @@ -276,14 +356,14 @@ static int PutAction( intf_thread_t *p_intf, int i_action )
>          {
>              float vol;
>              if( playlist_VolumeUp( p_playlist, 1, &vol ) == 0 )
> -                DisplayVolume( p_intf, p_vout, vol );
> +                DisplayVolume( p_vout, slider_chan, vol );
>              break;
>          }
>          case ACTIONID_VOL_DOWN:
>          {
>              float vol;
>              if( playlist_VolumeDown( p_playlist, 1, &vol ) == 0 )
> -                DisplayVolume( p_intf, p_vout, vol );
> +                DisplayVolume( p_vout, slider_chan, vol );
>              break;
>          }
>          case ACTIONID_VOL_MUTE:
> @@ -298,11 +378,11 @@ static int PutAction( intf_thread_t *p_intf, int i_action )
>              float vol = playlist_VolumeGet( p_playlist );
>              if( mute || vol == 0.f )
>              {
> -                ClearChannels( p_intf, p_vout );
> +                ClearChannels( p_vout, slider_chan );
>                  DisplayIcon( p_vout, OSD_MUTE_ICON );
>              }
>              else
> -                DisplayVolume( p_intf, p_vout, vol );
> +                DisplayVolume( p_vout, slider_chan, vol );
>              break;
>          }
>
> @@ -346,7 +426,7 @@ static int PutAction( intf_thread_t *p_intf, int i_action )
>          case ACTIONID_PLAY_PAUSE:
>              if( p_input )
>              {
> -                ClearChannels( p_intf, p_vout );
> +                ClearChannels( p_vout, slider_chan );
>
>                  int state = var_GetInteger( p_input, "state" );
>                  DisplayIcon( p_vout, state != PAUSE_S ? OSD_PAUSE_ICON : OSD_PLAY_ICON );
> @@ -360,7 +440,7 @@ static int PutAction( intf_thread_t *p_intf, int i_action )
>                  var_SetFloat( p_input, "rate", 1.f );
>              else
>              {
> -                ClearChannels( p_intf, p_vout );
> +                ClearChannels( p_vout, slider_chan );
>                  DisplayIcon( p_vout, OSD_PLAY_ICON );
>                  playlist_Play( p_playlist );
>              }
> @@ -379,7 +459,7 @@ static int PutAction( intf_thread_t *p_intf, int i_action )
>          case ACTIONID_PAUSE:
>              if( p_input && var_GetInteger( p_input, "state" ) != PAUSE_S )
>              {
> -                ClearChannels( p_intf, p_vout );
> +                ClearChannels( p_vout, slider_chan );
>                  DisplayIcon( p_vout, OSD_PAUSE_ICON );
>                  var_SetInteger( p_input, "state", PAUSE_S );
>              }
> @@ -454,7 +534,7 @@ static int PutAction( intf_thread_t *p_intf, int i_action )
>                      int64_t i_additional_subdelay = p_sys->subtitle_delaybookmarks.i_time_audio - p_sys->subtitle_delaybookmarks.i_time_subtitle;
>                      int64_t i_total_subdelay = i_current_subdelay + i_additional_subdelay;
>                      var_SetInteger( p_input, "spu-delay", i_total_subdelay);
> -                    ClearChannels( p_intf, p_vout );
> +                    ClearChannels( p_vout, slider_chan );
>                      DisplayMessage( p_vout, _( "Sub sync: corrected %i ms (total delay = %i ms)" ),
>                                              (int)(i_additional_subdelay / 1000),
>                                              (int)(i_total_subdelay / 1000) );
> @@ -467,7 +547,7 @@ static int PutAction( intf_thread_t *p_intf, int i_action )
>          case ACTIONID_SUBSYNC_RESET:
>          {
>              var_SetInteger( p_input, "spu-delay", 0);
> -            ClearChannels( p_intf, p_vout );
> +            ClearChannels( p_vout, slider_chan );
>              DisplayMessage( p_vout, _( "Sub sync: delay reset" ) );
>              p_sys->subtitle_delaybookmarks.i_time_audio = 0;
>              p_sys->subtitle_delaybookmarks.i_time_subtitle = 0;
> @@ -496,7 +576,7 @@ static int PutAction( intf_thread_t *p_intf, int i_action )
>                  int64_t i_delay = var_GetInteger( p_input, "spu-delay" ) + diff;
>
>                  var_SetInteger( p_input, "spu-delay", i_delay );
> -                ClearChannels( p_intf, p_vout );
> +                ClearChannels( p_vout, slider_chan );
>                  DisplayMessage( p_vout, _( "Subtitle delay %i ms" ),
>                                  (int)(i_delay/1000) );
>                  var_FreeList( &list, &list2 );
> @@ -513,7 +593,7 @@ static int PutAction( intf_thread_t *p_intf, int i_action )
>                                    + diff;
>
>                  var_SetInteger( p_input, "audio-delay", i_delay );
> -                ClearChannels( p_intf, p_vout );
> +                ClearChannels( p_vout, slider_chan );
>                  DisplayMessage( p_vout, _( "Audio delay %i ms" ),
>                                   (int)(i_delay/1000) );
>              }
> @@ -741,7 +821,7 @@ static int PutAction( intf_thread_t *p_intf, int i_action )
>              if( it < 0 )
>                  break;
>              var_SetInteger( p_input, "time-offset", it * sign * CLOCK_FREQ );
> -            DisplayPosition( p_intf, p_vout, p_input );
> +            DisplayPosition( p_vout, slider_chan, p_input );
>              break;
>          }
>
> @@ -1151,7 +1231,7 @@ static int PutAction( intf_thread_t *p_intf, int i_action )
>                  else
>                      i_pos = var_IncInteger( p_vout, "sub-margin" );
>
> -                ClearChannels( p_intf, p_vout );
> +                ClearChannels( p_vout, slider_chan );
>                  DisplayMessage( p_vout, _( "Subtitle position %d px" ), i_pos );
>                  var_FreeList( &list, &list2 );
>              }
> @@ -1183,14 +1263,10 @@ static int PutAction( intf_thread_t *p_intf, int i_action )
>          /* Input + video output */
>          case ACTIONID_POSITION:
>              if( p_vout && vout_OSDEpg( p_vout, input_GetItem( p_input ) ) )
> -                DisplayPosition( p_intf, p_vout, p_input );
> +                DisplayPosition( p_vout, slider_chan, p_input );
>              break;
>      }
>
> -    if( p_vout )
> -        vlc_object_release( p_vout );
> -    if( p_input )
> -        vlc_object_release( p_input );
>      return VLC_SUCCESS;
>  }
>
> @@ -1201,12 +1277,28 @@ static int ActionEvent( vlc_object_t *libvlc, char const *psz_var,
>                          vlc_value_t oldval, vlc_value_t newval, void *p_data )
>  {
>      intf_thread_t *p_intf = (intf_thread_t *)p_data;
> +    intf_sys_t *p_sys = p_intf->p_sys;
>
>      (void)libvlc;
>      (void)psz_var;
>      (void)oldval;
>
> -    return PutAction( p_intf, newval.i_int );
> +    vlc_mutex_lock( &p_intf->p_sys->lock );
> +    input_thread_t *p_input = p_sys->p_input ? vlc_object_hold( p_sys->p_input )
> +                                             : NULL;
> +    vout_thread_t *p_vout = p_sys->p_vout ? vlc_object_hold( p_sys->p_vout )
> +                                          : NULL;
> +    int slider_chan = p_sys->slider_chan;
> +    vlc_mutex_unlock( &p_intf->p_sys->lock );
> +
> +    int i_ret = PutAction( p_intf, p_input, p_vout, slider_chan, newval.i_int );
> +
> +    if( p_input != NULL )
> +        vlc_object_release( p_input );
> +    if( p_vout != NULL )
> +        vlc_object_release( p_vout );
> +
> +    return i_ret;
>  }
>
>  static void PlayBookmark( intf_thread_t *p_intf, int i_num )
> @@ -1263,7 +1355,7 @@ static void SetBookmark( intf_thread_t *p_intf, int i_num )
>      free( psz_bookmark_name );
>  }
>
> -static void DisplayPosition( intf_thread_t *p_intf, vout_thread_t *p_vout,
> +static void DisplayPosition( vout_thread_t *p_vout, int slider_chan,
>                               input_thread_t *p_input )
>  {
>      char psz_duration[MSTRTIME_MAX_SIZE];
> @@ -1271,7 +1363,7 @@ static void DisplayPosition( intf_thread_t *p_intf, vout_thread_t *p_vout,
>
>      if( p_vout == NULL ) return;
>
> -    ClearChannels( p_intf, p_vout );
> +    ClearChannels( p_vout, slider_chan );
>
>      int64_t t = var_GetInteger( p_input, "time" ) / CLOCK_FREQ;
>      int64_t l = var_GetInteger( p_input, "length" ) / CLOCK_FREQ;
> @@ -1292,20 +1384,19 @@ static void DisplayPosition( intf_thread_t *p_intf, vout_thread_t *p_vout,
>      {
>          vlc_value_t pos;
>          var_Get( p_input, "position", &pos );
> -        vout_OSDSlider( p_vout, p_intf->p_sys->slider_chan,
> +        vout_OSDSlider( p_vout, slider_chan,
>                          pos.f_float * 100, OSD_HOR_SLIDER );
>      }
>  }
>
> -static void DisplayVolume( intf_thread_t *p_intf, vout_thread_t *p_vout,
> -                           float vol )
> +static void DisplayVolume( vout_thread_t *p_vout, int slider_chan, float vol )
>  {
>      if( p_vout == NULL )
>          return;
> -    ClearChannels( p_intf, p_vout );
> +    ClearChannels( p_vout, slider_chan );
>
>      if( var_GetBool( p_vout, "fullscreen" ) )
> -        vout_OSDSlider( p_vout, p_intf->p_sys->slider_chan,
> +        vout_OSDSlider( p_vout, slider_chan,
>                          lroundf(vol * 100.f), OSD_VERT_SLIDER );
>      DisplayMessage( p_vout, _( "Volume %ld%%" ), lroundf(vol * 100.f) );
>  }
> @@ -1334,11 +1425,11 @@ static float AdjustRateFine( vlc_object_t *p_obj, const int i_dir )
>      return f_rate;
>  }
>
> -static void ClearChannels( intf_thread_t *p_intf, vout_thread_t *p_vout )
> +static void ClearChannels( vout_thread_t *p_vout, int slider_chan )
>  {
>      if( p_vout )
>      {
>          vout_FlushSubpictureChannel( p_vout, SPU_DEFAULT_CHANNEL );
> -        vout_FlushSubpictureChannel( p_vout, p_intf->p_sys->slider_chan );
> +        vout_FlushSubpictureChannel( p_vout, slider_chan );
>      }
>  }
> --
> 2.9.3
>
> _______________________________________________
> vlc-devel mailing list
> To unsubscribe or modify your subscription options:
> https://mailman.videolan.org/listinfo/vlc-devel


More information about the vlc-devel mailing list