hotkeys.c
上传用户:riyaled888
上传日期:2009-03-27
资源大小:7338k
文件大小:27k
源码类别:

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * hotkeys.c: Hotkey handling for vlc
  3.  *****************************************************************************
  4.  * Copyright (C) 2004 VideoLAN
  5.  * $Id: hotkeys.c 8966 2004-10-10 10:08:44Z ipkiss $
  6.  *
  7.  * Authors: Sigmund Augdal <sigmunau@idi.ntnu.no>
  8.  *
  9.  * This program is free software; you can redistribute it and/or modify
  10.  * it under the terms of the GNU General Public License as published by
  11.  * the Free Software Foundation; either version 2 of the License, or
  12.  * (at your option) any later version.
  13.  *
  14.  * This program is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  * GNU General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with this program; if not, write to the Free Software
  21.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  22.  *****************************************************************************/
  23. /*****************************************************************************
  24.  * Preamble
  25.  *****************************************************************************/
  26. #include <stdlib.h>                                      /* malloc(), free() */
  27. #include <vlc/vlc.h>
  28. #include <vlc/intf.h>
  29. #include <vlc/input.h>
  30. #include <vlc/vout.h>
  31. #include <vlc/aout.h>
  32. #include <osd.h>
  33. #include "vlc_keys.h"
  34. #define BUFFER_SIZE 10
  35. #define CHANNELS_NUMBER 4
  36. #define VOLUME_TEXT_CHAN     p_intf->p_sys->p_channels[ 0 ]
  37. #define VOLUME_WIDGET_CHAN   p_intf->p_sys->p_channels[ 1 ]
  38. #define POSITION_TEXT_CHAN   p_intf->p_sys->p_channels[ 2 ]
  39. #define POSITION_WIDGET_CHAN p_intf->p_sys->p_channels[ 3 ]
  40. /*****************************************************************************
  41.  * intf_sys_t: description and status of FB interface
  42.  *****************************************************************************/
  43. struct intf_sys_t
  44. {
  45.     vlc_mutex_t         change_lock;  /* mutex to keep the callback
  46.                                        * and the main loop from
  47.                                        * stepping on each others
  48.                                        * toes */
  49.     int                 p_keys[ BUFFER_SIZE ]; /* buffer that contains
  50.                                                 * keyevents */
  51.     int                 i_size;        /* number of events in buffer */
  52.     int                 p_channels[ CHANNELS_NUMBER ]; /* contains registered
  53.                                                         * channel IDs */
  54.     input_thread_t *    p_input;       /* pointer to input */
  55.     vout_thread_t *     p_vout;        /* pointer to vout object */
  56. };
  57. /*****************************************************************************
  58.  * Local prototypes
  59.  *****************************************************************************/
  60. static int  Open    ( vlc_object_t * );
  61. static void Close   ( vlc_object_t * );
  62. static void Run     ( intf_thread_t * );
  63. static int  GetKey  ( intf_thread_t *);
  64. static int  KeyEvent( vlc_object_t *, char const *,
  65.                       vlc_value_t, vlc_value_t, void * );
  66. static int  ActionKeyCB( vlc_object_t *, char const *,
  67.                          vlc_value_t, vlc_value_t, void * );
  68. static void PlayBookmark( intf_thread_t *, int );
  69. static void SetBookmark ( intf_thread_t *, int );
  70. static void DisplayPosition( intf_thread_t *, vout_thread_t *, input_thread_t * );
  71. static void DisplayVolume  ( intf_thread_t *, vout_thread_t *, audio_volume_t );
  72. static void ClearChannels  ( intf_thread_t *, vout_thread_t * );
  73. /*****************************************************************************
  74.  * Module descriptor
  75.  *****************************************************************************/
  76. #define BOOKMARK1_TEXT N_("Playlist bookmark 1")
  77. #define BOOKMARK2_TEXT N_("Playlist bookmark 2")
  78. #define BOOKMARK3_TEXT N_("Playlist bookmark 3")
  79. #define BOOKMARK4_TEXT N_("Playlist bookmark 4")
  80. #define BOOKMARK5_TEXT N_("Playlist bookmark 5")
  81. #define BOOKMARK6_TEXT N_("Playlist bookmark 6")
  82. #define BOOKMARK7_TEXT N_("Playlist bookmark 7")
  83. #define BOOKMARK8_TEXT N_("Playlist bookmark 8")
  84. #define BOOKMARK9_TEXT N_("Playlist bookmark 9")
  85. #define BOOKMARK10_TEXT N_("Playlist bookmark 10")
  86. #define BOOKMARK_LONGTEXT N_( 
  87.     "This option allows you to define playlist bookmarks.")
  88. vlc_module_begin();
  89.     set_description( _("Hotkeys management interface") );
  90.     add_string( "bookmark1", NULL, NULL,
  91.                 BOOKMARK1_TEXT, BOOKMARK_LONGTEXT, VLC_FALSE );
  92.     add_string( "bookmark2", NULL, NULL,
  93.                 BOOKMARK2_TEXT, BOOKMARK_LONGTEXT, VLC_FALSE );
  94.     add_string( "bookmark3", NULL, NULL,
  95.                 BOOKMARK3_TEXT, BOOKMARK_LONGTEXT, VLC_FALSE );
  96.     add_string( "bookmark4", NULL, NULL,
  97.                 BOOKMARK4_TEXT, BOOKMARK_LONGTEXT, VLC_FALSE );
  98.     add_string( "bookmark5", NULL, NULL,
  99.                 BOOKMARK5_TEXT, BOOKMARK_LONGTEXT, VLC_FALSE );
  100.     add_string( "bookmark6", NULL, NULL,
  101.                 BOOKMARK6_TEXT, BOOKMARK_LONGTEXT, VLC_FALSE );
  102.     add_string( "bookmark7", NULL, NULL,
  103.                 BOOKMARK7_TEXT, BOOKMARK_LONGTEXT, VLC_FALSE );
  104.     add_string( "bookmark8", NULL, NULL,
  105.                 BOOKMARK8_TEXT, BOOKMARK_LONGTEXT, VLC_FALSE );
  106.     add_string( "bookmark9", NULL, NULL,
  107.                 BOOKMARK9_TEXT, BOOKMARK_LONGTEXT, VLC_FALSE );
  108.     add_string( "bookmark10", NULL, NULL,
  109.                 BOOKMARK10_TEXT, BOOKMARK_LONGTEXT, VLC_FALSE );
  110.     set_capability( "interface", 0 );
  111.     set_callbacks( Open, Close );
  112. vlc_module_end();
  113. /*****************************************************************************
  114.  * Open: initialize interface
  115.  *****************************************************************************/
  116. static int Open( vlc_object_t *p_this )
  117. {
  118.     intf_thread_t *p_intf = (intf_thread_t *)p_this;
  119.     /* Allocate instance and initialize some members */
  120.     p_intf->p_sys = malloc( sizeof( intf_sys_t ) );
  121.     if( p_intf->p_sys == NULL )
  122.     {
  123.         msg_Err( p_intf, "out of memory" );
  124.         return 1;
  125.     }
  126.     vlc_mutex_init( p_intf, &p_intf->p_sys->change_lock );
  127.     p_intf->p_sys->i_size = 0;
  128.     p_intf->pf_run = Run;
  129.     p_intf->p_sys->p_input = NULL;
  130.     p_intf->p_sys->p_vout = NULL;
  131.     var_AddCallback( p_intf->p_vlc, "key-pressed", KeyEvent, p_intf );
  132.     return 0;
  133. }
  134. /*****************************************************************************
  135.  * Close: destroy interface
  136.  *****************************************************************************/
  137. static void Close( vlc_object_t *p_this )
  138. {
  139.     intf_thread_t *p_intf = (intf_thread_t *)p_this;
  140.     if( p_intf->p_sys->p_input )
  141.     {
  142.         vlc_object_release( p_intf->p_sys->p_input );
  143.     }
  144.     if( p_intf->p_sys->p_vout )
  145.     {
  146.         vlc_object_release( p_intf->p_sys->p_vout );
  147.     }
  148.     /* Destroy structure */
  149.     free( p_intf->p_sys );
  150. }
  151. /*****************************************************************************
  152.  * Run: main loop
  153.  *****************************************************************************/
  154. static void Run( intf_thread_t *p_intf )
  155. {
  156.     playlist_t *p_playlist;
  157.     input_thread_t *p_input;
  158.     vout_thread_t *p_vout = NULL;
  159.     vout_thread_t *p_last_vout;
  160.     struct hotkey *p_hotkeys = p_intf->p_vlc->p_hotkeys;
  161.     vlc_value_t val;
  162.     int i;
  163.     /* Initialize hotkey structure */
  164.     for( i = 0; p_hotkeys[i].psz_action != NULL; i++ )
  165.     {
  166.         var_Create( p_intf->p_vlc, p_hotkeys[i].psz_action,
  167.                     VLC_VAR_HOTKEY | VLC_VAR_DOINHERIT );
  168.         var_AddCallback( p_intf->p_vlc, p_hotkeys[i].psz_action,
  169.                          ActionKeyCB, NULL );
  170.         var_Get( p_intf->p_vlc, p_hotkeys[i].psz_action, &val );
  171.         var_Set( p_intf->p_vlc, p_hotkeys[i].psz_action, val );
  172.     }
  173.     while( !p_intf->b_die )
  174.     {
  175.         int i_key, i_action;
  176.         /* Sleep a bit */
  177.         msleep( INTF_IDLE_SLEEP );
  178.         /* Update the input */
  179.         if( p_intf->p_sys->p_input == NULL )
  180.         {
  181.             p_intf->p_sys->p_input = vlc_object_find( p_intf, VLC_OBJECT_INPUT,
  182.                                                       FIND_ANYWHERE );
  183.         }
  184.         else if( p_intf->p_sys->p_input->b_dead )
  185.         {
  186.             vlc_object_release( p_intf->p_sys->p_input );
  187.             p_intf->p_sys->p_input = NULL;
  188.         }
  189.         p_input = p_intf->p_sys->p_input;
  190.         /* Update the vout */
  191.         p_last_vout = p_intf->p_sys->p_vout;
  192.         if( p_vout == NULL )
  193.         {
  194.             p_vout = vlc_object_find( p_intf, VLC_OBJECT_VOUT, FIND_ANYWHERE );
  195.             p_intf->p_sys->p_vout = p_vout;
  196.         }
  197.         else if( p_vout->b_die )
  198.         {
  199.             vlc_object_release( p_vout );
  200.             p_vout = NULL;
  201.             p_intf->p_sys->p_vout = NULL;
  202.         }
  203.         /* Register OSD channels */
  204.         if( p_vout && p_vout != p_last_vout )
  205.         {
  206.             for( i = 0; i < CHANNELS_NUMBER; i++ )
  207.             {
  208.                 spu_Control( p_vout->p_spu, SPU_CHANNEL_REGISTER,
  209.                              &p_intf->p_sys->p_channels[ i ] );
  210.             }
  211.         }
  212.         /* Find action triggered by hotkey */
  213.         i_action = 0;
  214.         i_key = GetKey( p_intf );
  215.         for( i = 0; p_hotkeys[i].psz_action != NULL; i++ )
  216.         {
  217.             if( p_hotkeys[i].i_key == i_key )
  218.             {
  219.                  i_action = p_hotkeys[i].i_action;
  220.             }
  221.         }
  222.         if( !i_action )
  223.         {
  224.             /* No key pressed, sleep a bit more */
  225.             msleep( INTF_IDLE_SLEEP );
  226.             continue;
  227.         }
  228.         if( i_action == ACTIONID_QUIT )
  229.         {
  230.             p_intf->p_vlc->b_die = VLC_TRUE;
  231.             ClearChannels( p_intf, p_vout );
  232.             vout_OSDMessage( p_intf, DEFAULT_CHAN, _( "Quit" ) );
  233.             continue;
  234.         }
  235.         else if( i_action == ACTIONID_VOL_UP )
  236.         {
  237.             audio_volume_t i_newvol;
  238.             aout_VolumeUp( p_intf, 1, &i_newvol );
  239.             DisplayVolume( p_intf, p_vout, i_newvol );
  240.         }
  241.         else if( i_action == ACTIONID_VOL_DOWN )
  242.         {
  243.             audio_volume_t i_newvol;
  244.             aout_VolumeDown( p_intf, 1, &i_newvol );
  245.             DisplayVolume( p_intf, p_vout, i_newvol );
  246.         }
  247.         else if( i_action == ACTIONID_VOL_MUTE )
  248.         {
  249.             audio_volume_t i_newvol = -1;
  250.             aout_VolumeMute( p_intf, &i_newvol );
  251.             if( p_vout )
  252.             {
  253.                 if( i_newvol == 0 )
  254.                 {
  255.                     ClearChannels( p_intf, p_vout );
  256.                     vout_OSDIcon( VLC_OBJECT( p_intf ), DEFAULT_CHAN,
  257.                                   OSD_MUTE_ICON );
  258.                 }
  259.                 else
  260.                 {
  261.                     DisplayVolume( p_intf, p_vout, i_newvol );
  262.                 }
  263.             }
  264.         }
  265.         else if( i_action == ACTIONID_INTF_SHOW )
  266.         {
  267.             val.b_bool = VLC_TRUE;
  268.             p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
  269.                                           FIND_ANYWHERE );
  270.             if( p_playlist )
  271.             {
  272.                 var_Set( p_playlist, "intf-show", val );
  273.                 vlc_object_release( p_playlist );
  274.             }
  275.         }
  276.         else if( i_action == ACTIONID_SUBDELAY_DOWN )
  277.         {
  278.             int64_t i_delay = var_GetTime( p_input, "spu-delay" );
  279.             i_delay -= 50000;    /* 50 ms */
  280.             var_SetTime( p_input, "spu-delay", i_delay );
  281.             ClearChannels( p_intf, p_vout );
  282.             vout_OSDMessage( p_intf, DEFAULT_CHAN, "Subtitle delay %i ms",
  283.                                  (int)(i_delay/1000) );
  284.         }
  285.         else if( i_action == ACTIONID_SUBDELAY_UP )
  286.         {
  287.             int64_t i_delay = var_GetTime( p_input, "spu-delay" );
  288.             i_delay += 50000;    /* 50 ms */
  289.             var_SetTime( p_input, "spu-delay", i_delay );
  290.             ClearChannels( p_intf, p_vout );
  291.             vout_OSDMessage( p_intf, DEFAULT_CHAN, "Subtitle delay %i ms",
  292.                                  (int)(i_delay/1000) );
  293.         }
  294.         else if( i_action == ACTIONID_FULLSCREEN )
  295.         {
  296.             if( p_vout )
  297.             {
  298.                 var_Get( p_vout, "fullscreen", &val ); val.b_bool = !val.b_bool;
  299.                 var_Set( p_vout, "fullscreen", val );
  300.             }
  301.             else
  302.             {
  303.                 p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
  304.                                           FIND_ANYWHERE );
  305.                 if( p_playlist )
  306.                 {
  307.                     var_Get( p_playlist, "fullscreen", &val ); val.b_bool = !val.b_bool;
  308.                     var_Set( p_playlist, "fullscreen", val );
  309.                     vlc_object_release( p_playlist );
  310.                 }
  311.             }
  312.         }
  313.         else if( i_action == ACTIONID_PLAY )
  314.         {
  315.             p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
  316.                                           FIND_ANYWHERE );
  317.             if( p_playlist )
  318.             {
  319.                 ClearChannels( p_intf, p_vout );
  320.                 vout_OSDIcon( VLC_OBJECT( p_intf ), DEFAULT_CHAN,
  321.                               OSD_PAUSE_ICON );
  322.                 playlist_Play( p_playlist );
  323.                 vlc_object_release( p_playlist );
  324.             }
  325.         }
  326.         else if( i_action == ACTIONID_PLAY_PAUSE )
  327.         {
  328.             val.i_int = PLAYING_S;
  329.             if( p_input )
  330.             {
  331.                 var_Get( p_input, "state", &val );
  332.             }
  333.             if( p_input && val.i_int != PAUSE_S )
  334.             {
  335.                 ClearChannels( p_intf, p_vout );
  336.                 vout_OSDIcon( VLC_OBJECT( p_intf ), DEFAULT_CHAN,
  337.                               OSD_PAUSE_ICON );
  338.                 val.i_int = PAUSE_S;
  339.                 var_Set( p_input, "state", val );
  340.             }
  341.             else
  342.             {
  343.                 p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
  344.                                               FIND_ANYWHERE );
  345.                 if( p_playlist )
  346.                 {
  347.                     ClearChannels( p_intf, p_vout );
  348.                     vout_OSDIcon( VLC_OBJECT( p_intf ), DEFAULT_CHAN,
  349.                                   OSD_PLAY_ICON );
  350.                     playlist_Play( p_playlist );
  351.                     vlc_object_release( p_playlist );
  352.                 }
  353.             }
  354.         }
  355.         else if( p_input )
  356.         {
  357.             /* FIXME --fenrir
  358.              * How to get a valid value ?
  359.              * That's not that easy with some special stream
  360.              */
  361.             vlc_bool_t b_seekable = VLC_TRUE;
  362.             if( i_action == ACTIONID_PAUSE )
  363.             {
  364.                 ClearChannels( p_intf, p_vout );
  365.                 vout_OSDIcon( VLC_OBJECT( p_intf ), DEFAULT_CHAN,
  366.                               OSD_PAUSE_ICON );
  367.                 val.i_int = PAUSE_S;
  368.                 var_Set( p_input, "state", val );
  369.             }
  370.             else if( i_action == ACTIONID_JUMP_BACKWARD_10SEC && b_seekable )
  371.             {
  372.                 val.i_time = -10000000;
  373.                 var_Set( p_input, "time-offset", val );
  374.                 DisplayPosition( p_intf, p_vout, p_input );
  375.             }
  376.             else if( i_action == ACTIONID_JUMP_FORWARD_10SEC && b_seekable )
  377.             {
  378.                 val.i_time = 10000000;
  379.                 var_Set( p_input, "time-offset", val );
  380.                 DisplayPosition( p_intf, p_vout, p_input );
  381.             }
  382.             else if( i_action == ACTIONID_JUMP_BACKWARD_1MIN && b_seekable )
  383.             {
  384.                 val.i_time = -60000000;
  385.                 var_Set( p_input, "time-offset", val );
  386.                 DisplayPosition( p_intf, p_vout, p_input );
  387.             }
  388.             else if( i_action == ACTIONID_JUMP_FORWARD_1MIN && b_seekable )
  389.             {
  390.                 val.i_time = 60000000;
  391.                 var_Set( p_input, "time-offset", val );
  392.                 DisplayPosition( p_intf, p_vout, p_input );
  393.             }
  394.             else if( i_action == ACTIONID_JUMP_BACKWARD_5MIN && b_seekable )
  395.             {
  396.                 val.i_time = -300000000;
  397.                 var_Set( p_input, "time-offset", val );
  398.                 DisplayPosition( p_intf, p_vout, p_input );
  399.             }
  400.             else if( i_action == ACTIONID_JUMP_FORWARD_5MIN && b_seekable )
  401.             {
  402.                 val.i_time = 300000000;
  403.                 var_Set( p_input, "time-offset", val );
  404.                 DisplayPosition( p_intf, p_vout, p_input );
  405.             }
  406.             else if( i_action == ACTIONID_AUDIO_TRACK )
  407.             {
  408.                 vlc_value_t val, list, list2;
  409.                 int i_count, i;
  410.                 var_Get( p_input, "audio-es", &val );
  411.                 var_Change( p_input, "audio-es", VLC_VAR_GETCHOICES,
  412.                             &list, &list2 );
  413.                 i_count = list.p_list->i_count;
  414.                 if( i_count <= 1 )
  415.                 {
  416.                     continue;
  417.                 }
  418.                 for( i = 0; i < i_count; i++ )
  419.                 {
  420.                     if( val.i_int == list.p_list->p_values[i].i_int )
  421.                     {
  422.                         break;
  423.                     }
  424.                 }
  425.                 /* value of audio-es was not in choices list */
  426.                 if( i == i_count )
  427.                 {
  428.                     msg_Warn( p_input,
  429.                               "invalid current audio track, selecting 0" );
  430.                     var_Set( p_input, "audio-es",
  431.                              list.p_list->p_values[0] );
  432.                     i = 0;
  433.                 }
  434.                 else if( i == i_count - 1 )
  435.                 {
  436.                     var_Set( p_input, "audio-es",
  437.                              list.p_list->p_values[1] );
  438.                     i = 1;
  439.                 }
  440.                 else
  441.                 {
  442.                     var_Set( p_input, "audio-es",
  443.                              list.p_list->p_values[i+1] );
  444.                     i++;
  445.                 }
  446.                 vout_OSDMessage( VLC_OBJECT(p_input), DEFAULT_CHAN,
  447.                                  _("Audio track: %s"),
  448.                                  list2.p_list->p_values[i].psz_string );
  449.             }
  450.             else if( i_action == ACTIONID_SUBTITLE_TRACK )
  451.             {
  452.                 vlc_value_t val, list, list2;
  453.                 int i_count, i;
  454.                 var_Get( p_input, "spu-es", &val );
  455.                 
  456.                 var_Change( p_input, "spu-es", VLC_VAR_GETCHOICES,
  457.                             &list, &list2 );
  458.                 i_count = list.p_list->i_count;
  459.                 if( i_count <= 1 )
  460.                 {
  461.                     vout_OSDMessage( VLC_OBJECT(p_input), DEFAULT_CHAN, _("Subtitle track: %s"), _("N/A") );
  462.                     continue;
  463.                 }
  464.                 for( i = 0; i < i_count; i++ )
  465.                 {
  466.                     if( val.i_int == list.p_list->p_values[i].i_int )
  467.                     {
  468.                         break;
  469.                     }
  470.                 }
  471.                 /* value of spu-es was not in choices list */
  472.                 if( i == i_count )
  473.                 {
  474.                     msg_Warn( p_input, "invalid current subtitle track, selecting 0" );
  475.                     var_Set( p_input, "spu-es", list.p_list->p_values[0] );
  476.                     i = 0;
  477.                 }
  478.                 else if( i == i_count - 1 )
  479.                 {
  480.                     var_Set( p_input, "spu-es", list.p_list->p_values[0] );
  481.                     i = 0;
  482.                 }
  483.                 else
  484.                 {
  485.                     var_Set( p_input, "spu-es", list.p_list->p_values[i+1] );
  486.                     i = i + 1;
  487.                 }
  488.                 vout_OSDMessage( VLC_OBJECT(p_input), DEFAULT_CHAN,
  489.                                  _("Subtitle track: %s"),
  490.                                  list2.p_list->p_values[i].psz_string );
  491.             }
  492.             else if( i_action == ACTIONID_NEXT )
  493.             {
  494.                 p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
  495.                                               FIND_ANYWHERE );
  496.                 if( p_playlist )
  497.                 {
  498.                     vout_OSDMessage( VLC_OBJECT(p_input), DEFAULT_CHAN, _("Next") );
  499.                     playlist_Next( p_playlist );
  500.                     vlc_object_release( p_playlist );
  501.                 }
  502.             }
  503.             else if( i_action == ACTIONID_PREV )
  504.             {
  505.                 p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
  506.                                               FIND_ANYWHERE );
  507.                 if( p_playlist )
  508.                 {
  509.                     vout_OSDMessage( VLC_OBJECT(p_input), DEFAULT_CHAN, _("Previous") );
  510.                     playlist_Prev( p_playlist );
  511.                     vlc_object_release( p_playlist );
  512.                 }
  513.             }
  514.             else if( i_action == ACTIONID_STOP )
  515.             {
  516.                 p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
  517.                                               FIND_ANYWHERE );
  518.                 if( p_playlist )
  519.                 {
  520.                     playlist_Stop( p_playlist );
  521.                     vlc_object_release( p_playlist );
  522.                 }
  523.             }
  524.             else if( i_action == ACTIONID_FASTER )
  525.             {
  526.                 vlc_value_t val; val.b_bool = VLC_TRUE;
  527.                 var_Set( p_input, "rate-faster", val );
  528.                 vout_OSDMessage( VLC_OBJECT(p_input), DEFAULT_CHAN, _("Faster") );
  529.             }
  530.             else if( i_action == ACTIONID_SLOWER )
  531.             {
  532.                 vlc_value_t val; val.b_bool = VLC_TRUE;
  533.                 var_Set( p_input, "rate-slower", val );
  534.                 vout_OSDMessage( VLC_OBJECT(p_input), DEFAULT_CHAN, _("Slower") );
  535.             }
  536.             else if( i_action == ACTIONID_POSITION && b_seekable )
  537.             {
  538.                 DisplayPosition( p_intf, p_vout, p_input );
  539.             }
  540.             else if( i_action >= ACTIONID_PLAY_BOOKMARK1 &&
  541.                      i_action <= ACTIONID_PLAY_BOOKMARK10 )
  542.             {
  543.                 PlayBookmark( p_intf, i_action - ACTIONID_PLAY_BOOKMARK1 + 1 );
  544.             }
  545.             else if( i_action >= ACTIONID_SET_BOOKMARK1 &&
  546.                      i_action <= ACTIONID_SET_BOOKMARK10 )
  547.             {
  548.                 SetBookmark( p_intf, i_action - ACTIONID_SET_BOOKMARK1 + 1 );
  549.             }
  550.         }
  551.     }
  552. }
  553. static int GetKey( intf_thread_t *p_intf)
  554. {
  555.     vlc_mutex_lock( &p_intf->p_sys->change_lock );
  556.     if ( p_intf->p_sys->i_size == 0 )
  557.     {
  558.         vlc_mutex_unlock( &p_intf->p_sys->change_lock );
  559.         return -1;
  560.     }
  561.     else
  562.     {
  563.         int i_return = p_intf->p_sys->p_keys[ 0 ];
  564.         int i;
  565.         p_intf->p_sys->i_size--;
  566.         for ( i = 0; i < BUFFER_SIZE - 1; i++)
  567.         {
  568.             p_intf->p_sys->p_keys[ i ] = p_intf->p_sys->p_keys[ i + 1 ];
  569.         }
  570.         vlc_mutex_unlock( &p_intf->p_sys->change_lock );
  571.         return i_return;
  572.     }
  573. }
  574. /*****************************************************************************
  575.  * KeyEvent: callback for keyboard events
  576.  *****************************************************************************/
  577. static int KeyEvent( vlc_object_t *p_this, char const *psz_var,
  578.                      vlc_value_t oldval, vlc_value_t newval, void *p_data )
  579. {
  580.     intf_thread_t *p_intf = (intf_thread_t *)p_data;
  581.     vlc_mutex_lock( &p_intf->p_sys->change_lock );
  582.     if ( p_intf->p_sys->i_size == BUFFER_SIZE )
  583.     {
  584.         msg_Warn( p_intf, "event buffer full, dropping keypress" );
  585.         vlc_mutex_unlock( &p_intf->p_sys->change_lock );
  586.         return VLC_EGENERIC;
  587.     }
  588.     else
  589.     {
  590.         p_intf->p_sys->p_keys[ p_intf->p_sys->i_size ] = newval.i_int;
  591.         p_intf->p_sys->i_size++;
  592.     }
  593.     vlc_mutex_unlock( &p_intf->p_sys->change_lock );
  594.     return VLC_SUCCESS;
  595. }
  596. static int ActionKeyCB( vlc_object_t *p_this, char const *psz_var,
  597.                         vlc_value_t oldval, vlc_value_t newval, void *p_data )
  598. {
  599.     vlc_t *p_vlc = (vlc_t *)p_this;
  600.     struct hotkey *p_hotkeys = p_vlc->p_hotkeys;
  601.     int i;
  602.     for( i = 0; p_hotkeys[i].psz_action != NULL; i++ )
  603.     {
  604.         if( !strcmp( p_hotkeys[i].psz_action, psz_var ) )
  605.         {
  606.             p_hotkeys[i].i_key = newval.i_int;
  607.         }
  608.     }
  609.     return VLC_SUCCESS;
  610. }
  611. static void PlayBookmark( intf_thread_t *p_intf, int i_num )
  612. {
  613.     vlc_value_t val;
  614.     int i_position;
  615.     char psz_bookmark_name[11];
  616.     playlist_t *p_playlist =
  617.         vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
  618.     sprintf( psz_bookmark_name, "bookmark%i", i_num );
  619.     var_Create( p_intf, psz_bookmark_name, VLC_VAR_STRING|VLC_VAR_DOINHERIT );
  620.     var_Get( p_intf, psz_bookmark_name, &val );
  621.     if( p_playlist )
  622.     {
  623.         char *psz_bookmark = strdup( val.psz_string );
  624.         for( i_position = 0; i_position < p_playlist->i_size; i_position++)
  625.         {
  626.             if( !strcmp( psz_bookmark,
  627.                          p_playlist->pp_items[i_position]->input.psz_uri ) )
  628.             {
  629.                 playlist_Goto( p_playlist, i_position );
  630.                 break;
  631.             }
  632.         }
  633.         vlc_object_release( p_playlist );
  634.     }
  635. }
  636. static void SetBookmark( intf_thread_t *p_intf, int i_num )
  637. {
  638.     vlc_value_t val;
  639.     playlist_t *p_playlist =
  640.         vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
  641.     if( p_playlist )
  642.     {
  643.         char psz_bookmark_name[11];
  644.         sprintf( psz_bookmark_name, "bookmark%i", i_num );
  645.         var_Create( p_intf, psz_bookmark_name,
  646.                     VLC_VAR_STRING|VLC_VAR_DOINHERIT );
  647.         val.psz_string = strdup( p_playlist->pp_items[p_playlist->i_index]->input.psz_uri );
  648.         var_Set( p_intf, psz_bookmark_name, val );
  649.         msg_Info( p_intf, "setting playlist bookmark %i to %s", i_num,
  650.                   val.psz_string );
  651.         vlc_object_release( p_playlist );
  652.     }
  653. }
  654. static void DisplayPosition( intf_thread_t *p_intf, vout_thread_t *p_vout,
  655.                              input_thread_t *p_input )
  656. {
  657.     char psz_duration[MSTRTIME_MAX_SIZE];
  658.     char psz_time[MSTRTIME_MAX_SIZE];
  659.     vlc_value_t time, pos;
  660.     mtime_t i_seconds;
  661.     if( p_vout == NULL )
  662.     {
  663.         return;
  664.     }
  665.     ClearChannels( p_intf, p_vout );
  666.     var_Get( p_input, "time", &time );
  667.     i_seconds = time.i_time / 1000000;
  668.     secstotimestr ( psz_time, i_seconds );
  669.     var_Get( p_input, "length", &time );
  670.     if( time.i_time > 0 )
  671.     {
  672.         secstotimestr( psz_duration, time.i_time / 1000000 );
  673.         vout_OSDMessage( p_input, POSITION_TEXT_CHAN, "%s / %s",
  674.                          psz_time, psz_duration );
  675.     }
  676.     else if( i_seconds > 0 )
  677.     {
  678.         vout_OSDMessage( p_input, POSITION_TEXT_CHAN, psz_time );
  679.     }
  680.     if( !p_vout->p_parent_intf || p_vout->b_fullscreen )
  681.     {
  682.         var_Get( p_input, "position", &pos );
  683.         vout_OSDSlider( VLC_OBJECT( p_input ), POSITION_WIDGET_CHAN,
  684.                         pos.f_float * 100, OSD_HOR_SLIDER );
  685.     }
  686. }
  687. static void DisplayVolume( intf_thread_t *p_intf, vout_thread_t *p_vout,
  688.                            audio_volume_t i_vol )
  689. {
  690.     if( p_vout == NULL )
  691.     {
  692.         return;
  693.     }
  694.     ClearChannels( p_intf, p_vout );
  695.     if( !p_vout->p_parent_intf || p_vout->b_fullscreen )
  696.     {
  697.         vout_OSDSlider( VLC_OBJECT( p_vout ), VOLUME_WIDGET_CHAN,
  698.             i_vol*100/AOUT_VOLUME_MAX, OSD_VERT_SLIDER );
  699.     }
  700.     else
  701.     {
  702.         vout_OSDMessage( p_vout, VOLUME_TEXT_CHAN, "Vol %d%%",
  703.                          2*i_vol*100/AOUT_VOLUME_MAX );
  704.     }
  705. }
  706. static void ClearChannels( intf_thread_t *p_intf, vout_thread_t *p_vout )
  707. {
  708.     int i;
  709.     if( p_vout )
  710.     {
  711.         spu_Control( p_vout->p_spu, SPU_CHANNEL_CLEAR, DEFAULT_CHAN );
  712.         for( i = 0; i < CHANNELS_NUMBER; i++ )
  713.         {
  714.             spu_Control( p_vout->p_spu, SPU_CHANNEL_CLEAR,
  715.                          p_intf->p_sys->p_channels[ i ] );
  716.         }
  717.     }
  718. }