From 9ec1b8a0275afa50e0f161b38932d2425970451b Mon Sep 17 00:00:00 2001 From: Sigmund Augdal Helberg Date: Sun, 26 Oct 2003 12:46:55 +0000 Subject: [PATCH] src/libvlc.c: * created a variable "key-pressed" in p_vlc that can be used to report or read key presses * allways try to start hotkeys interface in the background configure.ac, modules/control/Modules.am, modules/control/hotkeys.c: * a new control module that reads keypresses from "key-pressed" and performs an action depending on what is asosiated with this key. Also uses nice on screen messages to indicate what action was performed modules/video_filter/filter_common.h: * removed code to pass old style key reporting through filters modules/video_output/x11/xcommon.c: * report key-presses through the new mechanism. Incomplete, I need help with this. --- configure.ac | 4 +- modules/control/Modules.am | 1 + modules/control/hotkeys.c | 356 +++++++++++++++++++++++++++ modules/video_filter/filter_common.h | 8 +- modules/video_output/x11/xcommon.c | 119 ++++----- src/libvlc.c | 11 +- 6 files changed, 416 insertions(+), 83 deletions(-) create mode 100755 modules/control/hotkeys.c diff --git a/configure.ac b/configure.ac index 6c0a061ae0..37897fbdc3 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ dnl Autoconf settings for vlc -dnl $Id: configure.ac,v 1.94 2003/10/24 21:27:06 gbazin Exp $ +dnl $Id: configure.ac,v 1.95 2003/10/26 12:46:55 sigmunau Exp $ AC_INIT(vlc,0.6.3-cvs) @@ -844,7 +844,7 @@ test "${enable_cprof}" != "yes" && enable_cprof="no" dnl dnl default modules dnl -AX_ADD_PLUGINS([dummy rc logger gestures memcpy]) +AX_ADD_PLUGINS([dummy rc logger gestures memcpy hotkeys]) AX_ADD_PLUGINS([es mpga m4v mpeg_system ps ts avi asf aac mp4 rawdv]) AX_ADD_PLUGINS([spudec mpeg_audio lpcm a52 dts cinepak]) AX_ADD_PLUGINS([deinterlace invert adjust wall transform distort clone crop motionblur]) diff --git a/modules/control/Modules.am b/modules/control/Modules.am index 557cd52a01..8a1e55694a 100644 --- a/modules/control/Modules.am +++ b/modules/control/Modules.am @@ -2,3 +2,4 @@ SOURCES_gestures = gestures.c SOURCES_http = http.c SOURCES_ntservice = ntservice.c SOURCES_joystick = joystick.c +SOURCES_hotkeys = hotkeys.c diff --git a/modules/control/hotkeys.c b/modules/control/hotkeys.c new file mode 100755 index 0000000000..d52a69ec6e --- /dev/null +++ b/modules/control/hotkeys.c @@ -0,0 +1,356 @@ +/***************************************************************************** + * hotkeys.c: Hotkey handling for vlc + ***************************************************************************** + * Copyright (C) 2003 VideoLAN + * $Id: hotkeys.c,v 1.1 2003/10/26 12:46:55 sigmunau Exp $ + * + * Authors: Sigmund Augdal + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. + *****************************************************************************/ + +/***************************************************************************** + * Preamble + *****************************************************************************/ +#include /* malloc(), free() */ +#include + +#include +#include +#include +#include +#include + +#define BUFFER_SIZE 10 +/***************************************************************************** + * intf_sys_t: description and status of FB interface + *****************************************************************************/ +struct intf_sys_t +{ + vlc_mutex_t change_lock; /* mutex to keep the callback + * and the main loop from + * stepping on each others + * toes */ + int p_keys[ BUFFER_SIZE ]; /* buffer that contains + * keyevents */ + int i_size; /* number of events in buffer */ + input_thread_t * p_input; /* pointer to input */ + vout_thread_t * p_vout; /* pointer to vout object */ +}; + +/***************************************************************************** + * Local prototypes + *****************************************************************************/ +static int Open ( vlc_object_t * ); +static void Close ( vlc_object_t * ); +static void Run ( intf_thread_t * ); +static void Feedback( intf_thread_t *, char * ); +static int GetKey ( intf_thread_t *); +static int KeyEvent( vlc_object_t *, char const *, + vlc_value_t, vlc_value_t, void * ); + +/***************************************************************************** + * Module descriptor + *****************************************************************************/ +vlc_module_begin(); + set_description( _("hotkey interface") ); + set_capability( "interface", 0 ); + set_callbacks( Open, Close ); +vlc_module_end(); + +/***************************************************************************** + * Open: initialize interface + *****************************************************************************/ +static int Open( vlc_object_t *p_this ) +{ + intf_thread_t *p_intf = (intf_thread_t *)p_this; + + /* Allocate instance and initialize some members */ + p_intf->p_sys = malloc( sizeof( intf_sys_t ) ); + if( p_intf->p_sys == NULL ) + { + msg_Err( p_intf, "out of memory" ); + return 1; + } + vlc_mutex_init( p_intf, &p_intf->p_sys->change_lock ); + p_intf->p_sys->i_size = 0; + p_intf->pf_run = Run; + + p_intf->p_sys->p_input = NULL; + p_intf->p_sys->p_vout = NULL; + var_AddCallback( p_intf->p_vlc, "key-pressed", KeyEvent, p_intf ); + return 0; +} + +/***************************************************************************** + * Close: destroy interface + *****************************************************************************/ +static void Close( vlc_object_t *p_this ) +{ + intf_thread_t *p_intf = (intf_thread_t *)p_this; + + if( p_intf->p_sys->p_input ) + { + vlc_object_release( p_intf->p_sys->p_input ); + } + if( p_intf->p_sys->p_vout ) + { + vlc_object_release( p_intf->p_sys->p_vout ); + } + /* Destroy structure */ + free( p_intf->p_sys ); +} + +/***************************************************************************** + * Run: main loop + *****************************************************************************/ +static void Run( intf_thread_t *p_intf ) +{ + playlist_t *p_playlist; + input_thread_t *p_input; + vout_thread_t *p_vout = NULL; + int i_fullscreen = config_GetInt( p_intf, "fullscreen-key" ); + int i_quit = config_GetInt( p_intf, "quit-key" ); + int i_vol_up = config_GetInt( p_intf, "vol-up-key" ); + int i_vol_down = config_GetInt( p_intf, "vol-down-key" ); + int i_play_pause = config_GetInt( p_intf, "play-pause-key" ); + int i_play = config_GetInt( p_intf, "play-key" ); + int i_pause = config_GetInt( p_intf, "pause-key" ); + int i_stop = config_GetInt( p_intf, "stop-key" ); + int i_next = config_GetInt( p_intf, "next-key" ); + int i_prev = config_GetInt( p_intf, "prev-key" ); + int i_faster = config_GetInt( p_intf, "faster-key" ); + int i_slower = config_GetInt( p_intf, "slower-key" ); + int i_key = 0; + + while( !p_intf->b_die ) + { + /* Sleep a bit */ + msleep( INTF_IDLE_SLEEP ); + + /* Update the input */ + if( p_intf->p_sys->p_input == NULL ) + { + p_intf->p_sys->p_input = vlc_object_find( p_intf, VLC_OBJECT_INPUT, + FIND_ANYWHERE ); + } + else if( p_intf->p_sys->p_input->b_dead ) + { + vlc_object_release( p_intf->p_sys->p_input ); + p_intf->p_sys->p_input = NULL; + } + p_input = p_intf->p_sys->p_input; + + /* Update the vout */ + if( p_vout == NULL ) + { + p_vout = vlc_object_find( p_intf, VLC_OBJECT_VOUT, + FIND_ANYWHERE ); + p_intf->p_sys->p_vout = p_vout; + } + else if( p_vout->b_die ) + { + vlc_object_release( p_vout ); + p_vout = NULL; + p_intf->p_sys->p_vout = NULL; + } + + i_key = GetKey( p_intf ); + if ( !i_key ) + { + /* No key pressed, sleep a bit more */ + msleep( INTF_IDLE_SLEEP ); + continue; + } + if( i_key == i_quit ) + { + p_intf->p_vlc->b_die = VLC_TRUE; + Feedback( p_intf, _("Quit" ) ); + continue; + } + if( i_key == i_vol_up ) + { + audio_volume_t i_newvol; + char string[9]; + aout_VolumeUp( p_intf, 1, &i_newvol ); + sprintf( string, "Vol %%%d", i_newvol*100/AOUT_VOLUME_MAX ); + Feedback( p_intf, string ); + } + if( i_key == i_vol_down ) + { + audio_volume_t i_newvol; + char string[9]; + aout_VolumeDown( p_intf, 1, &i_newvol ); + sprintf( string, "Vol %%%d", i_newvol*100/AOUT_VOLUME_MAX ); + Feedback( p_intf, string ); + } + if( p_vout ) + { + if( i_key == i_fullscreen ) + { + p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE; + continue; + } + } + + if( i_key == i_play ) + { + p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, + FIND_ANYWHERE ); + if( p_playlist ) + { + vlc_mutex_lock( &p_playlist->object_lock ); + if( p_playlist->i_size ) + { + vlc_mutex_unlock( &p_playlist->object_lock ); + playlist_Play( p_playlist ); + vlc_object_release( p_playlist ); + } + } + continue; + } + + if( i_key == i_play_pause ) + { + if( p_input && + p_input->stream.control.i_status != PAUSE_S ) + { + Feedback( p_intf, _( "Pause" ) ); + input_SetStatus( p_input, INPUT_STATUS_PAUSE ); + } + else + { + p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, + FIND_ANYWHERE ); + if( p_playlist ) + { + vlc_mutex_lock( &p_playlist->object_lock ); + if( p_playlist->i_size ) + { + vlc_mutex_unlock( &p_playlist->object_lock ); + Feedback( p_intf, _( "Play" ) ); + playlist_Play( p_playlist ); + vlc_object_release( p_playlist ); + } + } + } + continue; + } + + else if( p_input ) + { + if( i_key == i_pause ) + { + Feedback( p_intf, _( "Pause" ) ); + input_SetStatus( p_input, INPUT_STATUS_PAUSE ); + } + else if( i_key == i_next ) + { + p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, + FIND_ANYWHERE ); + if( p_playlist ) + { + playlist_Next( p_playlist ); + vlc_object_release( p_playlist ); + } + } + else if( i_key == i_prev ) + { + p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, + FIND_ANYWHERE ); + if( p_playlist ) + { + playlist_Prev( p_playlist ); + vlc_object_release( p_playlist ); + } + } + else if( i_key == i_stop ) + { + p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, + FIND_ANYWHERE ); + if( p_playlist ) + { + playlist_Stop( p_playlist ); + vlc_object_release( p_playlist ); + } + } + else if( i_key == i_faster ) + { + input_SetStatus( p_input, INPUT_STATUS_FASTER ); + } + else if( i_key == i_slower ) + { + input_SetStatus( p_input, INPUT_STATUS_SLOWER ); + } + } + + } +} + +static void Feedback( intf_thread_t *p_intf, char *psz_string ) +{ + if ( p_intf->p_sys->p_vout ) + { + vout_ShowTextRelative( p_intf->p_sys->p_vout, psz_string, NULL, + OSD_ALIGN_TOP|OSD_ALIGN_RIGHT, 30,20,400000 ); + } +} + +static int GetKey ( intf_thread_t *p_intf) +{ + vlc_mutex_lock( &p_intf->p_sys->change_lock ); + if ( p_intf->p_sys->i_size == 0 ) + { + vlc_mutex_unlock( &p_intf->p_sys->change_lock ); + return 0; + } + else + { + int i_return = p_intf->p_sys->p_keys[ 0 ]; + int i; + p_intf->p_sys->i_size--; + for ( i = 0; i < BUFFER_SIZE - 1; i++) + { + p_intf->p_sys->p_keys[ i ] = p_intf->p_sys->p_keys[ i + 1 ]; + } + vlc_mutex_unlock( &p_intf->p_sys->change_lock ); + return i_return; + } +} + +/***************************************************************************** + * KeyEvent: callback for keyboard events + *****************************************************************************/ +static int KeyEvent( vlc_object_t *p_this, 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; + vlc_mutex_lock( &p_intf->p_sys->change_lock ); + if ( p_intf->p_sys->i_size == BUFFER_SIZE ) + { + msg_Warn( p_intf, "Event buffer full, dropping keypress" ); + vlc_mutex_unlock( &p_intf->p_sys->change_lock ); + return VLC_EGENERIC; + } + else + { + p_intf->p_sys->p_keys[ p_intf->p_sys->i_size ] = newval.i_int; + p_intf->p_sys->i_size++; + } + vlc_mutex_unlock( &p_intf->p_sys->change_lock ); + + return VLC_SUCCESS; +} + diff --git a/modules/video_filter/filter_common.h b/modules/video_filter/filter_common.h index 9785860854..e0f00d3c88 100644 --- a/modules/video_filter/filter_common.h +++ b/modules/video_filter/filter_common.h @@ -2,7 +2,7 @@ * filter_common.h: Common filter functions ***************************************************************************** * Copyright (C) 2001, 2002, 2003 VideoLAN - * $Id: filter_common.h,v 1.4 2003/10/24 21:27:06 gbazin Exp $ + * $Id: filter_common.h,v 1.5 2003/10/26 12:46:55 sigmunau Exp $ * * Authors: Samuel Hocevar * @@ -78,16 +78,14 @@ static int SetParentVal( vlc_object_t *p_this, char const *psz_var, var_AddCallback( newvout, "mouse-x", SendEvents, p_vout ); \ var_AddCallback( newvout, "mouse-y", SendEvents, p_vout ); \ var_AddCallback( newvout, "mouse-moved", SendEvents, p_vout ); \ - var_AddCallback( newvout, "mouse-clicked", SendEvents, p_vout ); \ - var_AddCallback( newvout, "key-pressed", SendEvents, p_vout ) + var_AddCallback( newvout, "mouse-clicked", SendEvents, p_vout ); #define DEL_CALLBACKS( newvout, handler ) \ var_DelCallback( newvout, "fullscreen", SetParentVal, p_vout ); \ var_DelCallback( newvout, "mouse-x", SendEvents, p_vout ); \ var_DelCallback( newvout, "mouse-y", SendEvents, p_vout ); \ var_DelCallback( newvout, "mouse-moved", SendEvents, p_vout ); \ - var_DelCallback( newvout, "mouse-clicked", SendEvents, p_vout ); \ - var_DelCallback( newvout, "key-pressed", SendEvents, p_vout ) + var_DelCallback( newvout, "mouse-clicked", SendEvents, p_vout ); #define ADD_PARENT_CALLBACKS( handler ) \ var_AddCallback( p_vout, "fullscreen", handler, NULL ); \ diff --git a/modules/video_output/x11/xcommon.c b/modules/video_output/x11/xcommon.c index 70da15cf2e..634979c114 100644 --- a/modules/video_output/x11/xcommon.c +++ b/modules/video_output/x11/xcommon.c @@ -2,7 +2,7 @@ * xcommon.c: Functions common to the X11 and XVideo plugins ***************************************************************************** * Copyright (C) 1998-2001 VideoLAN - * $Id: xcommon.c,v 1.33 2003/10/24 21:27:06 gbazin Exp $ + * $Id: xcommon.c,v 1.34 2003/10/26 12:46:55 sigmunau Exp $ * * Authors: Vincent Seguin * Samuel Hocevar @@ -34,6 +34,7 @@ #include #include #include +#include #ifdef HAVE_MACHINE_PARAM_H /* BSD */ @@ -517,92 +518,49 @@ static int ManageVideo( vout_thread_t *p_vout ) /* Keyboard event */ else if( xevent.type == KeyPress ) { + vlc_value_t val; + val.i_int = 0; /* We may have keys like F1 trough F12, ESC ... */ x_key_symbol = XKeycodeToKeysym( p_vout->p_sys->p_display, xevent.xkey.keycode, 0 ); switch( (int)x_key_symbol ) { + case XK_Return: + case XK_KP_Enter: + val.i_int = KEY_ENTER; + break; case XK_Escape: - if( p_vout->b_fullscreen ) - { - p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE; - } - else - { - /* the user wants to close the window */ - playlist_t * p_playlist = - (playlist_t *)vlc_object_find( p_vout, - VLC_OBJECT_PLAYLIST, - FIND_ANYWHERE ); - if( p_playlist != NULL ) - { - playlist_Stop( p_playlist ); - vlc_object_release( p_playlist ); - } - } + val.i_int = KEY_ESC; break; case XK_Menu: - { - intf_thread_t *p_intf; - playlist_t * p_playlist; - - p_intf = vlc_object_find( p_vout, VLC_OBJECT_INTF, - FIND_ANYWHERE ); - if( p_intf ) - { - p_intf->b_menu_change = 1; - vlc_object_release( p_intf ); - } - - p_playlist = vlc_object_find( p_vout, VLC_OBJECT_PLAYLIST, - FIND_ANYWHERE ); - if( p_playlist != NULL ) - { - vlc_value_t val; - var_Set( p_playlist, "intf-popupmenu", val ); - vlc_object_release( p_playlist ); - } - } + val.i_int = KEY_MENU; break; case XK_Left: -/* input_Seek( p_vout, -5, INPUT_SEEK_SECONDS | INPUT_SEEK_CUR ); */ - val.psz_string = "LEFT"; - var_Set( p_vout, "key-pressed", val ); + val.i_int = KEY_LEFT; break; case XK_Right: -/* input_Seek( p_vout, 5, INPUT_SEEK_SECONDS | INPUT_SEEK_CUR ); */ - val.psz_string = "RIGHT"; - var_Set( p_vout, "key-pressed", val ); + val.i_int = KEY_RIGHT; break; case XK_Up: -/* input_Seek( p_vout, 60, INPUT_SEEK_SECONDS | INPUT_SEEK_CUR ); */ - val.psz_string = "UP"; - var_Set( p_vout, "key-pressed", val ); + val.i_int = KEY_UP; break; case XK_Down: -/* input_Seek( p_vout, -60, INPUT_SEEK_SECONDS | INPUT_SEEK_CUR ); */ - val.psz_string = "DOWN"; - var_Set( p_vout, "key-pressed", val ); - break; - case XK_Return: - case XK_KP_Enter: - val.psz_string = "ENTER"; - var_Set( p_vout, "key-pressed", val ); + val.i_int = KEY_DOWN; break; case XK_Home: - input_Seek( p_vout, 0, INPUT_SEEK_BYTES | INPUT_SEEK_SET ); + val.i_int = KEY_HOME; break; case XK_End: - input_Seek( p_vout, 0, INPUT_SEEK_BYTES | INPUT_SEEK_END ); + val.i_int = KEY_END; break; case XK_Page_Up: - input_Seek( p_vout, 10, INPUT_SEEK_SECONDS | INPUT_SEEK_CUR ); + val.i_int = KEY_PAGEUP; break; case XK_Page_Down: - input_Seek( p_vout, -10, INPUT_SEEK_SECONDS | INPUT_SEEK_CUR ); + val.i_int = KEY_PAGEDOWN; break; case XK_space: - input_SetStatus( p_vout, INPUT_STATUS_PAUSE ); + val.i_int = KEY_SPACE; break; default: @@ -614,23 +572,34 @@ static int ManageVideo( vout_thread_t *p_vout ) if( XLookupString( &xevent.xkey, &i_key, 1, NULL, NULL ) ) { /* FIXME: handle stuff here */ - switch( i_key ) - { - case 'q': - case 'Q': - p_vout->p_vlc->b_die = 1; - break; - case 'f': - case 'F': - p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE; - break; - - default: - break; - } + val.i_int = i_key; } break; } + if ( val.i_int ) + { + if ( xevent.xkey.state & ShiftMask ) + { + val.i_int |= KEY_MODIFIER_SHIFT; + } + if ( xevent.xkey.state & ControlMask ) + { + msg_Dbg( p_vout, "control pressed, key value is %x", val.i_int ); + val.i_int |= KEY_MODIFIER_CTRL; + } + if ( xevent.xkey.state & Mod1Mask ) + { + val.i_int |= KEY_MODIFIER_ALT; + } + if ( val.i_int == config_GetInt( p_vout, "fullscreen-key" ) ) + { + p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE; + } + else + { + var_Set( p_vout->p_vlc, "key-pressed", val ); + } + } } /* Mouse click */ else if( xevent.type == ButtonPress ) diff --git a/src/libvlc.c b/src/libvlc.c index eb91cf416d..ac5142d45b 100644 --- a/src/libvlc.c +++ b/src/libvlc.c @@ -2,7 +2,7 @@ * libvlc.c: main libvlc source ***************************************************************************** * Copyright (C) 1998-2002 VideoLAN - * $Id: libvlc.c,v 1.98 2003/10/23 16:43:37 sam Exp $ + * $Id: libvlc.c,v 1.99 2003/10/26 12:46:55 sigmunau Exp $ * * Authors: Vincent Seguin * Samuel Hocevar @@ -564,6 +564,10 @@ int VLC_Init( int i_object, int i_argc, char *ppsz_argv[] ) p_vlc->pf_memset = memset; } + /* + * Initialize hotkey handling + */ + var_Create( p_vlc, "key-pressed", VLC_VAR_INTEGER ); /* * Initialize playlist and get commandline files */ @@ -608,6 +612,11 @@ int VLC_Init( int i_object, int i_argc, char *ppsz_argv[] ) free( psz_modules ); } + /* + * Allways load the hotkeys interface if it exists + */ + VLC_AddIntf( 0, "hotkeys,none", VLC_FALSE ); + /* * FIXME: kludge to use a p_vlc-local variable for the Mozilla plugin */ -- 2.39.2