[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