X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fcontrol%2Fhotkeys.c;h=4ed3ee58f9d9f8045c09ea95d918e0ec383d2d75;hb=aeb8c2d53f7fc22c8651f2a435b04f4cece00452;hp=1ba99797482934928454d90163b92b2fd3bf239d;hpb=171934abd5615437ea05522e727e8c77bf1b07c8;p=vlc diff --git a/modules/control/hotkeys.c b/modules/control/hotkeys.c index 1ba9979748..4ed3ee58f9 100644 --- a/modules/control/hotkeys.c +++ b/modules/control/hotkeys.c @@ -1,7 +1,7 @@ /***************************************************************************** * hotkeys.c: Hotkey handling for vlc ***************************************************************************** - * Copyright (C) 2005 the VideoLAN team + * Copyright (C) 2005-2009 the VideoLAN team * $Id$ * * Authors: Sigmund Augdal Helberg @@ -39,6 +39,7 @@ #include #include #include "vlc_keys.h" +#include "math.h" #define BUFFER_SIZE 10 @@ -47,6 +48,7 @@ #define VOLUME_WIDGET_CHAN p_intf->p_sys->p_channels[ 1 ] #define POSITION_TEXT_CHAN p_intf->p_sys->p_channels[ 2 ] #define POSITION_WIDGET_CHAN p_intf->p_sys->p_channels[ 3 ] + /***************************************************************************** * intf_sys_t: description and status of FB interface *****************************************************************************/ @@ -59,6 +61,9 @@ struct intf_sys_t * channel IDs */ input_thread_t * p_input; /* pointer to input */ vout_thread_t * p_vout; /* pointer to vout object */ + vlc_mutex_t lock; /* callback lock */ + vlc_cond_t wait; /* callback event */ + int i_mousewheel_mode; }; /***************************************************************************** @@ -81,24 +86,32 @@ static void ClearChannels ( intf_thread_t *, vout_thread_t * ); /***************************************************************************** * Module descriptor *****************************************************************************/ -#define BOOKMARK1_TEXT N_("Playlist bookmark 1") -#define BOOKMARK2_TEXT N_("Playlist bookmark 2") -#define BOOKMARK3_TEXT N_("Playlist bookmark 3") -#define BOOKMARK4_TEXT N_("Playlist bookmark 4") -#define BOOKMARK5_TEXT N_("Playlist bookmark 5") -#define BOOKMARK6_TEXT N_("Playlist bookmark 6") -#define BOOKMARK7_TEXT N_("Playlist bookmark 7") -#define BOOKMARK8_TEXT N_("Playlist bookmark 8") -#define BOOKMARK9_TEXT N_("Playlist bookmark 9") -#define BOOKMARK10_TEXT N_("Playlist bookmark 10") -#define BOOKMARK_LONGTEXT N_("Define playlist bookmarks.") - -vlc_module_begin(); - set_shortname( N_("Hotkeys") ); - set_description( N_("Hotkeys management interface") ); - set_capability( "interface", 0 ); - set_callbacks( Open, Close ); -vlc_module_end(); + +enum{ + MOUSEWHEEL_VOLUME, + MOUSEWHEEL_POSITION, + NO_MOUSEWHEEL, +}; + +static const int i_mode_list[] = + { MOUSEWHEEL_VOLUME, MOUSEWHEEL_POSITION, NO_MOUSEWHEEL }; + +static const char *const psz_mode_list_text[] = + { N_("Volume Control"), N_("Position Control"), N_("Ignore") }; + +vlc_module_begin () + set_shortname( N_("Hotkeys") ) + set_description( N_("Hotkeys management interface") ) + set_capability( "interface", 0 ) + set_callbacks( Open, Close ) + + add_integer( "hotkeys-mousewheel-mode", MOUSEWHEEL_VOLUME, NULL, + N_("MouseWheel x-axis Control"), + N_("MouseWheel x-axis can control volume, position or " + "mousewheel event can be ignored"), false ) + change_integer_list( i_mode_list, psz_mode_list_text, NULL ) + +vlc_module_end () /***************************************************************************** * Open: initialize interface @@ -106,11 +119,20 @@ vlc_module_end(); static int Open( vlc_object_t *p_this ) { intf_thread_t *p_intf = (intf_thread_t *)p_this; - MALLOC_ERR( p_intf->p_sys, intf_sys_t ); + intf_sys_t *p_sys; + p_sys = malloc( sizeof( intf_sys_t ) ); + if( !p_sys ) + return VLC_ENOMEM; - p_intf->p_sys->i_size = 0; + p_intf->p_sys = p_sys; p_intf->pf_run = Run; + p_sys->i_size = 0; + vlc_mutex_init( &p_sys->lock ); + vlc_cond_init( &p_sys->wait ); + p_intf->p_sys->i_mousewheel_mode = + config_GetInt( p_intf, "hotkeys-mousewheel-mode" ); + var_AddCallback( p_intf->p_libvlc, "key-pressed", SpecialKeyEvent, p_intf ); var_AddCallback( p_intf->p_libvlc, "key-action", ActionEvent, p_intf ); return VLC_SUCCESS; @@ -122,10 +144,14 @@ static int Open( vlc_object_t *p_this ) 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( p_intf->p_libvlc, "key-action", ActionEvent, p_intf ); var_DelCallback( p_intf->p_libvlc, "key-pressed", SpecialKeyEvent, p_intf ); + vlc_cond_destroy( &p_sys->wait ); + vlc_mutex_destroy( &p_sys->lock ); + /* Destroy structure */ free( p_intf->p_sys ); } @@ -137,8 +163,10 @@ static void Run( intf_thread_t *p_intf ) { vout_thread_t *p_vout = NULL; vlc_value_t val; - int i; - playlist_t *p_playlist = pl_Yield( p_intf ); + playlist_t *p_playlist = pl_Hold( p_intf ); + int canc = vlc_savecancel(); + + vlc_cleanup_push( __pl_Release, p_intf ); /* Initialize hotkey structure */ for( struct hotkey *p_hotkey = p_intf->p_libvlc->p_hotkeys; @@ -152,25 +180,24 @@ static void Run( intf_thread_t *p_intf ) { input_thread_t *p_input; vout_thread_t *p_last_vout; - int i_action = GetAction( p_intf ); + int i_action; - if( i_action == -1 ) - break; /* die */ + vlc_restorecancel( canc ); + i_action = GetAction( p_intf ); + + canc = vlc_savecancel(); /* Update the input */ - PL_LOCK; - p_input = p_playlist->p_input; - if( p_input ) - vlc_object_yield( p_input ); - PL_UNLOCK; + p_input = playlist_CurrentInput( p_playlist ); /* Update the vout */ p_last_vout = p_vout; - p_vout = vlc_object_find( p_intf, VLC_OBJECT_VOUT, FIND_ANYWHERE ); + p_vout = p_input ? input_GetVout( p_input ) : NULL; /* Register OSD channels */ if( p_vout && p_vout != p_last_vout ) { + int i; for( i = 0; i < CHANNELS_NUMBER; i++ ) { spu_Control( p_vout->p_spu, SPU_CHANNEL_REGISTER, @@ -181,10 +208,8 @@ static void Run( intf_thread_t *p_intf ) /* Quit */ if( i_action == ACTIONID_QUIT ) { - if( p_playlist ) - playlist_Stop( p_playlist ); - vlc_object_kill( p_intf->p_libvlc ); - vlc_object_kill( p_intf ); + libvlc_Quit( p_intf->p_libvlc ); + ClearChannels( p_intf, p_vout ); vout_OSDMessage( p_intf, DEFAULT_CHAN, _( "Quit" ) ); if( p_vout ) @@ -232,7 +257,7 @@ static void Run( intf_thread_t *p_intf ) /* Video Output actions */ else if( i_action == ACTIONID_SNAPSHOT ) { - if( p_vout ) vout_Control( p_vout, VOUT_SNAPSHOT ); + if( p_vout ) var_TriggerCallback( p_vout, "video-snapshot" ); } else if( i_action == ACTIONID_TOGGLE_FULLSCREEN ) { @@ -397,11 +422,7 @@ static void Run( intf_thread_t *p_intf ) /* Input options */ else if( p_input ) { - /* FIXME --fenrir - * How to get a valid value ? - * That's not that easy with some special stream - */ - bool b_seekable = true; + bool b_seekable = var_GetBool( p_input, "can-seek" ); int i_interval =0; if( i_action == ACTIONID_PAUSE ) @@ -481,22 +502,13 @@ static void Run( intf_thread_t *p_intf ) { msg_Warn( p_input, "invalid current audio track, selecting 0" ); - var_Set( p_input, "audio-es", - list.p_list->p_values[0] ); i = 0; } else if( i == i_count - 1 ) - { - var_Set( p_input, "audio-es", - list.p_list->p_values[1] ); i = 1; - } else - { - var_Set( p_input, "audio-es", - list.p_list->p_values[i+1] ); i++; - } + var_Set( p_input, "audio-es", list.p_list->p_values[i] ); vout_OSDMessage( VLC_OBJECT(p_input), DEFAULT_CHAN, _("Audio track: %s"), list2.p_list->p_values[i].psz_string ); @@ -528,19 +540,13 @@ static void Run( intf_thread_t *p_intf ) { msg_Warn( p_input, "invalid current subtitle track, selecting 0" ); - var_Set( p_input, "spu-es", list.p_list->p_values[0] ); i = 0; } else if( i == i_count - 1 ) - { - var_Set( p_input, "spu-es", list.p_list->p_values[0] ); i = 0; - } else - { - var_Set( p_input, "spu-es", list.p_list->p_values[i+1] ); - i = i + 1; - } + i++; + var_Set( p_input, "spu-es", list.p_list->p_values[i] ); vout_OSDMessage( VLC_OBJECT(p_input), DEFAULT_CHAN, _("Subtitle track: %s"), list2.p_list->p_values[i].psz_string ); @@ -601,6 +607,45 @@ static void Run( intf_thread_t *p_intf ) } free( val.psz_string ); } + else if( i_action == ACTIONID_TOGGLE_AUTOSCALE && p_vout ) + { + float f_scalefactor = var_GetFloat( p_vout, "scale" ); + if ( f_scalefactor != 1.0 ) + { + var_SetFloat( p_vout, "scale", 1.0 ); + vout_OSDMessage( VLC_OBJECT(p_input), DEFAULT_CHAN, + _("Zooming reset") ); + } + else + { + bool b_autoscale = !var_GetBool( p_vout, "autoscale" ); + var_SetBool( p_vout, "autoscale", b_autoscale ); + if( b_autoscale ) + vout_OSDMessage( VLC_OBJECT(p_input), DEFAULT_CHAN, + _("Scaled to screen") ); + else + vout_OSDMessage( VLC_OBJECT(p_input), DEFAULT_CHAN, + _("Original Size") ); + } + } + else if( i_action == ACTIONID_SCALE_UP && p_vout ) + { + float f_scalefactor; + + f_scalefactor = var_GetFloat( p_vout, "scale" ); + if( f_scalefactor < 10. ) + f_scalefactor += .1; + var_SetFloat( p_vout, "scale", f_scalefactor ); + } + else if( i_action == ACTIONID_SCALE_DOWN && p_vout ) + { + float f_scalefactor; + + f_scalefactor = var_GetFloat( p_vout, "scale" ); + if( f_scalefactor > .3 ) + f_scalefactor -= .1; + var_SetFloat( p_vout, "scale", f_scalefactor ); + } else if( i_action == ACTIONID_DEINTERLACE && p_vout ) { vlc_value_t val={0}, val_list, text_list; @@ -692,6 +737,12 @@ static void Run( intf_thread_t *p_intf ) { playlist_Stop( p_playlist ); } + else if( i_action == ACTIONID_FRAME_NEXT ) + { + var_SetVoid( p_input, "frame-next" ); + vout_OSDMessage( VLC_OBJECT(p_input), DEFAULT_CHAN, + _("Next frame") ); + } else if( i_action == ACTIONID_FASTER ) { var_SetVoid( p_input, "rate-faster" ); @@ -704,6 +755,39 @@ static void Run( intf_thread_t *p_intf ) vout_OSDMessage( VLC_OBJECT(p_input), DEFAULT_CHAN, _("Slower") ); } + else if( i_action == ACTIONID_RATE_NORMAL ) + { + var_SetInteger( p_input, "rate", INPUT_RATE_DEFAULT ); + vout_OSDMessage( VLC_OBJECT(p_input), DEFAULT_CHAN, + _("1.00x") ); + } + else if( i_action == ACTIONID_RATE_FASTER_FINE || + i_action == ACTIONID_RATE_SLOWER_FINE ) + { + /* The playback rate is defined by INPUT_RATE_DEFAULT / "rate" + * and we want to increase/decrease it by 0.1 while making sure + * that the resulting playback rate is a multiple of 0.1 + */ + int i_rate = var_GetInteger( p_input, "rate" ); + if( i_rate == 0 ) + i_rate = INPUT_RATE_MIN; + int i_sign = i_rate < 0 ? -1 : 1; + const int i_dir = i_action == ACTIONID_RATE_FASTER_FINE ? 1 : -1; + + const double f_speed = floor( ( (double)INPUT_RATE_DEFAULT / abs(i_rate) + 0.05 ) / 0.1 + i_dir ) * 0.1; + if( f_speed <= (double)INPUT_RATE_DEFAULT / INPUT_RATE_MAX ) /* Needed to avoid infinity */ + i_rate = INPUT_RATE_MAX; + else + i_rate = INPUT_RATE_DEFAULT / f_speed + 0.5; + + i_rate = i_sign * __MIN( __MAX( i_rate, INPUT_RATE_MIN ), INPUT_RATE_MAX ); + + var_SetInteger( p_input, "rate", i_rate ); + + char psz_msg[7+1]; + snprintf( psz_msg, sizeof(psz_msg), _("%.2fx"), (double)INPUT_RATE_DEFAULT / i_rate ); + vout_OSDMessage( VLC_OBJECT(p_input), DEFAULT_CHAN, psz_msg ); + } else if( i_action == ACTIONID_POSITION && b_seekable ) { DisplayPosition( p_intf, p_vout, p_input ); @@ -814,35 +898,48 @@ static void Run( intf_thread_t *p_intf ) { osd_MenuActivate( VLC_OBJECT(p_intf) ); } + else if( i_action == ACTIONID_RECORD ) + { + if( var_GetBool( p_input, "can-record" ) ) + { + const bool b_record = !var_GetBool( p_input, "record" ); + + if( b_record ) + vout_OSDMessage( p_intf, DEFAULT_CHAN, _("Recording") ); + else + vout_OSDMessage( p_intf, DEFAULT_CHAN, _("Recording done") ); + var_SetBool( p_input, "record", b_record ); + } + } } if( p_vout ) vlc_object_release( p_vout ); if( p_input ) vlc_object_release( p_input ); } - pl_Release( p_intf ); + + /* dead code */ + abort(); + vlc_cleanup_pop(); } static int GetAction( intf_thread_t *p_intf ) { intf_sys_t *p_sys = p_intf->p_sys; - int i_ret = -1; + int i_ret; + + vlc_mutex_lock( &p_sys->lock ); + mutex_cleanup_push( &p_sys->lock ); - vlc_object_lock( p_intf ); while( p_sys->i_size == 0 ) - { - if( !vlc_object_alive( p_intf ) ) - goto out; - vlc_object_wait( p_intf ); - } + vlc_cond_wait( &p_sys->wait, &p_sys->lock ); i_ret = p_sys->p_actions[ 0 ]; p_sys->i_size--; for( int i = 0; i < p_sys->i_size; i++ ) p_sys->p_actions[i] = p_sys->p_actions[i + 1]; -out: - vlc_object_unlock( p_intf ); + vlc_cleanup_run(); return i_ret; } @@ -851,14 +948,14 @@ static int PutAction( intf_thread_t *p_intf, int i_action ) intf_sys_t *p_sys = p_intf->p_sys; int i_ret = VLC_EGENERIC; - vlc_object_lock( p_intf ); + vlc_mutex_lock( &p_sys->lock ); if ( p_sys->i_size >= BUFFER_SIZE ) msg_Warn( p_intf, "event buffer full, dropping key actions" ); else p_sys->p_actions[p_sys->i_size++] = i_action; - vlc_object_signal_unlocked( p_intf ); - vlc_object_unlock( p_intf ); + vlc_cond_signal( &p_sys->wait ); + vlc_mutex_unlock( &p_sys->lock ); return i_ret; } @@ -870,35 +967,46 @@ static int SpecialKeyEvent( vlc_object_t *libvlc, char const *psz_var, void *p_data ) { intf_thread_t *p_intf = (intf_thread_t *)p_data; - int i_action; + int i_action = 0; - (void)libvlc; (void)psz_var; (void)oldval; + int i_mode = p_intf->p_sys->i_mousewheel_mode; + /* Special action for mouse event */ - /* FIXME: This should probably be configurable */ /* FIXME: rework hotkeys handling to allow more than 1 event * to trigger one same action */ switch (newval.i_int & KEY_SPECIAL) { case KEY_MOUSEWHEELUP: - i_action = ACTIONID_VOL_UP; + i_action = (i_mode == MOUSEWHEEL_VOLUME ) ? ACTIONID_VOL_UP + : ACTIONID_JUMP_FORWARD_EXTRASHORT; break; case KEY_MOUSEWHEELDOWN: - i_action = ACTIONID_VOL_DOWN; + i_action = (i_mode == MOUSEWHEEL_VOLUME ) ? ACTIONID_VOL_DOWN + : ACTIONID_JUMP_BACKWARD_EXTRASHORT; break; case KEY_MOUSEWHEELLEFT: - i_action = ACTIONID_JUMP_BACKWARD_EXTRASHORT; + i_action = (i_mode == MOUSEWHEEL_VOLUME ) ? + ACTIONID_JUMP_BACKWARD_EXTRASHORT : ACTIONID_VOL_DOWN; break; case KEY_MOUSEWHEELRIGHT: - i_action = ACTIONID_JUMP_FORWARD_EXTRASHORT; + i_action = (i_mode == MOUSEWHEEL_VOLUME ) ? + ACTIONID_JUMP_FORWARD_EXTRASHORT : ACTIONID_VOL_UP; + break; + case KEY_MENU: + var_SetBool( libvlc, "intf-popupmenu", true ); break; default: return VLC_SUCCESS; } - return PutAction( p_intf, i_action ); + if( i_mode == NO_MOUSEWHEEL ) return VLC_SUCCESS; + + if( i_action ) + return PutAction( p_intf, i_action ); + return VLC_SUCCESS; } /***************************************************************************** @@ -918,15 +1026,13 @@ static int ActionEvent( vlc_object_t *libvlc, char const *psz_var, static void PlayBookmark( intf_thread_t *p_intf, int i_num ) { - vlc_value_t val; - char psz_bookmark_name[11]; - playlist_t *p_playlist = pl_Yield( p_intf ); + char *psz_bookmark_name; + if( asprintf( &psz_bookmark_name, "bookmark%i", i_num ) == -1 ) + return; - sprintf( psz_bookmark_name, "bookmark%i", i_num ); - var_Create( p_intf, psz_bookmark_name, VLC_VAR_STRING|VLC_VAR_DOINHERIT ); - var_Get( p_intf, psz_bookmark_name, &val ); + playlist_t *p_playlist = pl_Hold( p_intf ); + char *psz_bookmark = var_CreateGetString( p_intf, psz_bookmark_name ); - char *psz_bookmark = strdup( val.psz_string ); PL_LOCK; FOREACH_ARRAY( playlist_item_t *p_item, p_playlist->items ) char *psz_uri = input_item_GetURI( p_item->p_input ); @@ -941,25 +1047,33 @@ static void PlayBookmark( intf_thread_t *p_intf, int i_num ) free( psz_uri ); FOREACH_END(); PL_UNLOCK; - vlc_object_release( p_playlist ); + + free( psz_bookmark ); + free( psz_bookmark_name ); + pl_Release( p_intf ); } static void SetBookmark( intf_thread_t *p_intf, int i_num ) { - playlist_t *p_playlist = pl_Yield( p_intf ); - char psz_bookmark_name[11]; - sprintf( psz_bookmark_name, "bookmark%i", i_num ); + char *psz_bookmark_name; + if( asprintf( &psz_bookmark_name, "bookmark%i", i_num ) == -1 ) + return; + + playlist_t *p_playlist = pl_Hold( p_intf ); var_Create( p_intf, psz_bookmark_name, VLC_VAR_STRING|VLC_VAR_DOINHERIT ); - if( p_playlist->status.p_item ) + playlist_item_t * p_item = playlist_CurrentPlayingItem( p_playlist ); + if( p_item ) { - char *psz_uri = input_item_GetURI( p_playlist->status.p_item->p_input ); + char *psz_uri = input_item_GetURI( p_item->p_input ); config_PutPsz( p_intf, psz_bookmark_name, psz_uri); msg_Info( p_intf, "setting playlist bookmark %i to %s", i_num, psz_uri); free( psz_uri ); config_SaveConfigFile( p_intf, "hotkeys" ); } + pl_Release( p_intf ); + free( psz_bookmark_name ); } static void DisplayPosition( intf_thread_t *p_intf, vout_thread_t *p_vout, @@ -982,15 +1096,15 @@ static void DisplayPosition( intf_thread_t *p_intf, vout_thread_t *p_vout, if( time.i_time > 0 ) { secstotimestr( psz_duration, time.i_time / 1000000 ); - vout_OSDMessage( p_input, POSITION_TEXT_CHAN, (char *) "%s / %s", + vout_OSDMessage( p_input, POSITION_TEXT_CHAN, "%s / %s", psz_time, psz_duration ); } else if( i_seconds > 0 ) { - vout_OSDMessage( p_input, POSITION_TEXT_CHAN, psz_time ); + vout_OSDMessage( p_input, POSITION_TEXT_CHAN, "%s", psz_time ); } - if( !p_vout->p_window || p_vout->b_fullscreen ) + if( p_vout->b_fullscreen ) { var_Get( p_input, "position", &pos ); vout_OSDSlider( VLC_OBJECT( p_input ), POSITION_WIDGET_CHAN, @@ -1007,7 +1121,7 @@ static void DisplayVolume( intf_thread_t *p_intf, vout_thread_t *p_vout, } ClearChannels( p_intf, p_vout ); - if( !p_vout->p_window || p_vout->b_fullscreen ) + if( p_vout->b_fullscreen ) { vout_OSDSlider( VLC_OBJECT( p_vout ), VOLUME_WIDGET_CHAN, i_vol*100/AOUT_VOLUME_MAX, OSD_VERT_SLIDER );