1 /*****************************************************************************
2 * hotkeys.c: Hotkey handling for vlc
3 *****************************************************************************
4 * Copyright (C) 2005 the VideoLAN team
7 * Authors: Sigmund Augdal <sigmunau@idi.ntnu.no>
8 * Jean-Paul Saman <jpsaman #_at_# m2x.nl>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
23 *****************************************************************************/
25 /*****************************************************************************
27 *****************************************************************************/
28 #include <stdlib.h> /* malloc(), free() */
33 #include <vlc/input.h>
40 #define BUFFER_SIZE 10
42 #define CHANNELS_NUMBER 4
43 #define VOLUME_TEXT_CHAN p_intf->p_sys->p_channels[ 0 ]
44 #define VOLUME_WIDGET_CHAN p_intf->p_sys->p_channels[ 1 ]
45 #define POSITION_TEXT_CHAN p_intf->p_sys->p_channels[ 2 ]
46 #define POSITION_WIDGET_CHAN p_intf->p_sys->p_channels[ 3 ]
47 /*****************************************************************************
48 * intf_sys_t: description and status of FB interface
49 *****************************************************************************/
52 vlc_mutex_t change_lock; /* mutex to keep the callback
53 * and the main loop from
54 * stepping on each others
56 int p_keys[ BUFFER_SIZE ]; /* buffer that contains
58 int i_size; /* number of events in buffer */
59 int p_channels[ CHANNELS_NUMBER ]; /* contains registered
61 input_thread_t * p_input; /* pointer to input */
62 vout_thread_t * p_vout; /* pointer to vout object */
65 /*****************************************************************************
67 *****************************************************************************/
68 static int Open ( vlc_object_t * );
69 static void Close ( vlc_object_t * );
70 static void Run ( intf_thread_t * );
71 static int GetKey ( intf_thread_t *);
72 static int KeyEvent( vlc_object_t *, char const *,
73 vlc_value_t, vlc_value_t, void * );
74 static int ActionKeyCB( vlc_object_t *, char const *,
75 vlc_value_t, vlc_value_t, void * );
76 static void PlayBookmark( intf_thread_t *, int );
77 static void SetBookmark ( intf_thread_t *, int );
78 static void DisplayPosition( intf_thread_t *, vout_thread_t *, input_thread_t * );
79 static void DisplayVolume ( intf_thread_t *, vout_thread_t *, audio_volume_t );
80 static void ClearChannels ( intf_thread_t *, vout_thread_t * );
82 /*****************************************************************************
84 *****************************************************************************/
85 #define BOOKMARK1_TEXT N_("Playlist bookmark 1")
86 #define BOOKMARK2_TEXT N_("Playlist bookmark 2")
87 #define BOOKMARK3_TEXT N_("Playlist bookmark 3")
88 #define BOOKMARK4_TEXT N_("Playlist bookmark 4")
89 #define BOOKMARK5_TEXT N_("Playlist bookmark 5")
90 #define BOOKMARK6_TEXT N_("Playlist bookmark 6")
91 #define BOOKMARK7_TEXT N_("Playlist bookmark 7")
92 #define BOOKMARK8_TEXT N_("Playlist bookmark 8")
93 #define BOOKMARK9_TEXT N_("Playlist bookmark 9")
94 #define BOOKMARK10_TEXT N_("Playlist bookmark 10")
95 #define BOOKMARK_LONGTEXT N_( \
96 "This option allows you to define playlist bookmarks.")
99 set_description( _("Hotkeys management interface") );
100 add_string( "bookmark1", NULL, NULL,
101 BOOKMARK1_TEXT, BOOKMARK_LONGTEXT, VLC_FALSE );
102 add_string( "bookmark2", NULL, NULL,
103 BOOKMARK2_TEXT, BOOKMARK_LONGTEXT, VLC_FALSE );
104 add_string( "bookmark3", NULL, NULL,
105 BOOKMARK3_TEXT, BOOKMARK_LONGTEXT, VLC_FALSE );
106 add_string( "bookmark4", NULL, NULL,
107 BOOKMARK4_TEXT, BOOKMARK_LONGTEXT, VLC_FALSE );
108 add_string( "bookmark5", NULL, NULL,
109 BOOKMARK5_TEXT, BOOKMARK_LONGTEXT, VLC_FALSE );
110 add_string( "bookmark6", NULL, NULL,
111 BOOKMARK6_TEXT, BOOKMARK_LONGTEXT, VLC_FALSE );
112 add_string( "bookmark7", NULL, NULL,
113 BOOKMARK7_TEXT, BOOKMARK_LONGTEXT, VLC_FALSE );
114 add_string( "bookmark8", NULL, NULL,
115 BOOKMARK8_TEXT, BOOKMARK_LONGTEXT, VLC_FALSE );
116 add_string( "bookmark9", NULL, NULL,
117 BOOKMARK9_TEXT, BOOKMARK_LONGTEXT, VLC_FALSE );
118 add_string( "bookmark10", NULL, NULL,
119 BOOKMARK10_TEXT, BOOKMARK_LONGTEXT, VLC_FALSE );
121 set_capability( "interface", 0 );
122 set_callbacks( Open, Close );
125 /*****************************************************************************
126 * Open: initialize interface
127 *****************************************************************************/
128 static int Open( vlc_object_t *p_this )
130 intf_thread_t *p_intf = (intf_thread_t *)p_this;
132 /* Allocate instance and initialize some members */
133 p_intf->p_sys = malloc( sizeof( intf_sys_t ) );
134 if( p_intf->p_sys == NULL )
136 msg_Err( p_intf, "out of memory" );
139 vlc_mutex_init( p_intf, &p_intf->p_sys->change_lock );
140 p_intf->p_sys->i_size = 0;
141 p_intf->pf_run = Run;
143 p_intf->p_sys->p_input = NULL;
144 p_intf->p_sys->p_vout = NULL;
146 var_AddCallback( p_intf->p_vlc, "key-pressed", KeyEvent, p_intf );
150 /*****************************************************************************
151 * Close: destroy interface
152 *****************************************************************************/
153 static void Close( vlc_object_t *p_this )
155 intf_thread_t *p_intf = (intf_thread_t *)p_this;
157 var_DelCallback( p_intf->p_vlc, "key-pressed", KeyEvent, p_intf );
158 if( p_intf->p_sys->p_input )
160 vlc_object_release( p_intf->p_sys->p_input );
162 if( p_intf->p_sys->p_vout )
164 vlc_object_release( p_intf->p_sys->p_vout );
166 /* Destroy structure */
167 free( p_intf->p_sys );
170 /*****************************************************************************
172 *****************************************************************************/
173 static void Run( intf_thread_t *p_intf )
175 playlist_t *p_playlist = NULL;
176 input_thread_t *p_input = NULL;
177 vout_thread_t *p_vout = NULL;
178 vout_thread_t *p_last_vout = NULL;
179 struct hotkey *p_hotkeys = p_intf->p_vlc->p_hotkeys;
183 /* Initialize hotkey structure */
184 for( i = 0; p_hotkeys[i].psz_action != NULL; i++ )
186 var_Create( p_intf->p_vlc, p_hotkeys[i].psz_action,
187 VLC_VAR_HOTKEY | VLC_VAR_DOINHERIT );
189 var_AddCallback( p_intf->p_vlc, p_hotkeys[i].psz_action,
191 var_Get( p_intf->p_vlc, p_hotkeys[i].psz_action, &val );
192 var_Set( p_intf->p_vlc, p_hotkeys[i].psz_action, val );
195 while( !p_intf->b_die )
201 msleep( INTF_IDLE_SLEEP );
203 /* Update the input */
204 if( p_intf->p_sys->p_input == NULL )
206 p_intf->p_sys->p_input = vlc_object_find( p_intf, VLC_OBJECT_INPUT,
209 else if( p_intf->p_sys->p_input->b_dead )
211 vlc_object_release( p_intf->p_sys->p_input );
212 p_intf->p_sys->p_input = NULL;
214 p_input = p_intf->p_sys->p_input;
216 /* Update the vout */
217 p_last_vout = p_intf->p_sys->p_vout;
220 p_vout = vlc_object_find( p_intf, VLC_OBJECT_VOUT, FIND_ANYWHERE );
221 p_intf->p_sys->p_vout = p_vout;
223 else if( p_vout->b_die )
225 vlc_object_release( p_vout );
227 p_intf->p_sys->p_vout = NULL;
230 /* Register OSD channels */
231 if( p_vout && p_vout != p_last_vout )
233 for( i = 0; i < CHANNELS_NUMBER; i++ )
235 spu_Control( p_vout->p_spu, SPU_CHANNEL_REGISTER,
236 &p_intf->p_sys->p_channels[ i ] );
240 /* Find action triggered by hotkey */
242 i_key = GetKey( p_intf );
243 for( i = 0; i_key != -1 && p_hotkeys[i].psz_action != NULL; i++ )
245 if( p_hotkeys[i].i_key == i_key )
247 i_action = p_hotkeys[i].i_action;
248 i_times = p_hotkeys[i].i_times; /* times key pressed within max. delta time */
249 p_hotkeys[i].i_times = 0;
255 /* No key pressed, sleep a bit more */
256 msleep( INTF_IDLE_SLEEP );
260 if( i_action == ACTIONID_QUIT )
262 p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
266 playlist_Stop( p_playlist );
267 vlc_object_release( p_playlist );
269 /* Playlist is stopped now kill vlc. */
270 p_intf->p_vlc->b_die = VLC_TRUE;
271 ClearChannels( p_intf, p_vout );
272 vout_OSDMessage( p_intf, DEFAULT_CHAN, _( "Quit" ) );
275 else if( i_action == ACTIONID_VOL_UP )
277 audio_volume_t i_newvol;
278 aout_VolumeUp( p_intf, 1, &i_newvol );
279 DisplayVolume( p_intf, p_vout, i_newvol );
281 else if( i_action == ACTIONID_VOL_DOWN )
283 audio_volume_t i_newvol;
284 aout_VolumeDown( p_intf, 1, &i_newvol );
285 DisplayVolume( p_intf, p_vout, i_newvol );
287 else if( i_action == ACTIONID_VOL_MUTE )
289 audio_volume_t i_newvol = -1;
290 aout_VolumeMute( p_intf, &i_newvol );
295 ClearChannels( p_intf, p_vout );
296 vout_OSDIcon( VLC_OBJECT( p_intf ), DEFAULT_CHAN,
301 DisplayVolume( p_intf, p_vout, i_newvol );
305 else if( i_action == ACTIONID_INTF_SHOW )
307 val.b_bool = VLC_TRUE;
308 p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
312 var_Set( p_playlist, "intf-show", val );
313 vlc_object_release( p_playlist );
316 else if( i_action == ACTIONID_INTF_HIDE )
318 val.b_bool = VLC_FALSE;
319 p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
323 var_Set( p_playlist, "intf-show", val );
324 vlc_object_release( p_playlist );
327 else if( i_action == ACTIONID_SNAPSHOT )
329 if( p_vout ) vout_Control( p_vout, VOUT_SNAPSHOT );
331 else if( i_action == ACTIONID_SUBDELAY_DOWN )
333 int64_t i_delay = var_GetTime( p_input, "spu-delay" );
335 i_delay -= 50000; /* 50 ms */
337 var_SetTime( p_input, "spu-delay", i_delay );
338 ClearChannels( p_intf, p_vout );
339 vout_OSDMessage( p_intf, DEFAULT_CHAN, "Subtitle delay %i ms",
340 (int)(i_delay/1000) );
342 else if( i_action == ACTIONID_SUBDELAY_UP )
344 int64_t i_delay = var_GetTime( p_input, "spu-delay" );
346 i_delay += 50000; /* 50 ms */
348 var_SetTime( p_input, "spu-delay", i_delay );
349 ClearChannels( p_intf, p_vout );
350 vout_OSDMessage( p_intf, DEFAULT_CHAN, "Subtitle delay %i ms",
351 (int)(i_delay/1000) );
353 else if( i_action == ACTIONID_AUDIODELAY_DOWN )
355 int64_t i_delay = var_GetTime( p_input, "audio-delay" );
357 i_delay -= 50000; /* 50 ms */
359 var_SetTime( p_input, "audio-delay", i_delay );
360 ClearChannels( p_intf, p_vout );
361 vout_OSDMessage( p_intf, DEFAULT_CHAN, "Audio delay %i ms",
362 (int)(i_delay/1000) );
364 else if( i_action == ACTIONID_AUDIODELAY_UP )
366 int64_t i_delay = var_GetTime( p_input, "audio-delay" );
368 i_delay += 50000; /* 50 ms */
370 var_SetTime( p_input, "audio-delay", i_delay );
371 ClearChannels( p_intf, p_vout );
372 vout_OSDMessage( p_intf, DEFAULT_CHAN, "Audio delay %i ms",
373 (int)(i_delay/1000) );
375 else if( i_action == ACTIONID_FULLSCREEN )
379 var_Get( p_vout, "fullscreen", &val ); val.b_bool = !val.b_bool;
380 var_Set( p_vout, "fullscreen", val );
384 p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
388 var_Get( p_playlist, "fullscreen", &val ); val.b_bool = !val.b_bool;
389 var_Set( p_playlist, "fullscreen", val );
390 vlc_object_release( p_playlist );
394 else if( i_action == ACTIONID_PLAY )
396 p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
400 var_Get( p_input, "rate", &val );
401 msg_Dbg( p_input, "rate %d", val.i_int );
402 if( val.i_int != INPUT_RATE_DEFAULT )
404 /* Return to normal speed */
405 val.i_int = INPUT_RATE_DEFAULT;
406 var_Set( p_input, "rate", val );
410 ClearChannels( p_intf, p_vout );
411 vout_OSDIcon( VLC_OBJECT( p_intf ), DEFAULT_CHAN,
413 playlist_Play( p_playlist );
415 vlc_object_release( p_playlist );
419 else if( i_action == ACTIONID_PLAY_PAUSE )
421 val.i_int = PLAYING_S;
424 var_Get( p_input, "state", &val );
426 if( p_input && val.i_int != PAUSE_S )
428 ClearChannels( p_intf, p_vout );
429 vout_OSDIcon( VLC_OBJECT( p_intf ), DEFAULT_CHAN,
432 var_Set( p_input, "state", val );
436 p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
440 ClearChannels( p_intf, p_vout );
441 vout_OSDIcon( VLC_OBJECT( p_intf ), DEFAULT_CHAN,
443 playlist_Play( p_playlist );
444 vlc_object_release( p_playlist );
451 * How to get a valid value ?
452 * That's not that easy with some special stream
454 vlc_bool_t b_seekable = VLC_TRUE;
456 if( i_action == ACTIONID_PAUSE )
458 ClearChannels( p_intf, p_vout );
459 vout_OSDIcon( VLC_OBJECT( p_intf ), DEFAULT_CHAN,
462 var_Set( p_input, "state", val );
464 else if( i_action == ACTIONID_JUMP_BACKWARD_3SEC && b_seekable )
466 val.i_time = (-3000000 * ((mtime_t)pow(2,i_times)));
467 var_Set( p_input, "time-offset", val );
468 DisplayPosition( p_intf, p_vout, p_input );
470 else if( i_action == ACTIONID_JUMP_FORWARD_3SEC && b_seekable )
472 val.i_time = (3000000 * ((mtime_t)pow(2,i_times)));
473 var_Set( p_input, "time-offset", val );
474 DisplayPosition( p_intf, p_vout, p_input );
476 else if( i_action == ACTIONID_JUMP_BACKWARD_10SEC && b_seekable )
478 val.i_time = (-10000000 * ((mtime_t)pow(2,i_times)));
479 var_Set( p_input, "time-offset", val );
480 DisplayPosition( p_intf, p_vout, p_input );
482 else if( i_action == ACTIONID_JUMP_FORWARD_10SEC && b_seekable )
484 val.i_time = (10000000 * ((mtime_t)pow(2,i_times)));
485 var_Set( p_input, "time-offset", val );
486 DisplayPosition( p_intf, p_vout, p_input );
488 else if( i_action == ACTIONID_JUMP_BACKWARD_1MIN && b_seekable )
490 val.i_time = (-60000000 * ((mtime_t)pow(2,i_times)));
491 var_Set( p_input, "time-offset", val );
492 DisplayPosition( p_intf, p_vout, p_input );
494 else if( i_action == ACTIONID_JUMP_FORWARD_1MIN && b_seekable )
496 val.i_time = (60000000 * ((mtime_t)pow(2,i_times)));
497 var_Set( p_input, "time-offset", val );
498 DisplayPosition( p_intf, p_vout, p_input );
500 else if( i_action == ACTIONID_JUMP_BACKWARD_5MIN && b_seekable )
502 val.i_time = (-300000000 * ((mtime_t)pow(2,i_times)));
503 var_Set( p_input, "time-offset", val );
504 DisplayPosition( p_intf, p_vout, p_input );
506 else if( i_action == ACTIONID_JUMP_FORWARD_5MIN && b_seekable )
508 val.i_time = (300000000 * ((mtime_t)pow(2,i_times)));
509 var_Set( p_input, "time-offset", val );
510 DisplayPosition( p_intf, p_vout, p_input );
512 else if( i_action == ACTIONID_AUDIO_TRACK )
514 vlc_value_t val, list, list2;
516 var_Get( p_input, "audio-es", &val );
517 var_Change( p_input, "audio-es", VLC_VAR_GETCHOICES,
519 i_count = list.p_list->i_count;
524 for( i = 0; i < i_count; i++ )
526 if( val.i_int == list.p_list->p_values[i].i_int )
531 /* value of audio-es was not in choices list */
535 "invalid current audio track, selecting 0" );
536 var_Set( p_input, "audio-es",
537 list.p_list->p_values[0] );
540 else if( i == i_count - 1 )
542 var_Set( p_input, "audio-es",
543 list.p_list->p_values[1] );
548 var_Set( p_input, "audio-es",
549 list.p_list->p_values[i+1] );
552 vout_OSDMessage( VLC_OBJECT(p_input), DEFAULT_CHAN,
553 _("Audio track: %s"),
554 list2.p_list->p_values[i].psz_string );
556 else if( i_action == ACTIONID_SUBTITLE_TRACK )
558 vlc_value_t val, list, list2;
560 var_Get( p_input, "spu-es", &val );
562 var_Change( p_input, "spu-es", VLC_VAR_GETCHOICES,
564 i_count = list.p_list->i_count;
567 vout_OSDMessage( VLC_OBJECT(p_input), DEFAULT_CHAN, _("Subtitle track: %s"), _("N/A") );
570 for( i = 0; i < i_count; i++ )
572 if( val.i_int == list.p_list->p_values[i].i_int )
577 /* value of spu-es was not in choices list */
580 msg_Warn( p_input, "invalid current subtitle track, selecting 0" );
581 var_Set( p_input, "spu-es", list.p_list->p_values[0] );
584 else if( i == i_count - 1 )
586 var_Set( p_input, "spu-es", list.p_list->p_values[0] );
591 var_Set( p_input, "spu-es", list.p_list->p_values[i+1] );
594 vout_OSDMessage( VLC_OBJECT(p_input), DEFAULT_CHAN,
595 _("Subtitle track: %s"),
596 list2.p_list->p_values[i].psz_string );
598 else if( i_action == ACTIONID_NEXT )
600 p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
604 vout_OSDMessage( VLC_OBJECT(p_input), DEFAULT_CHAN, _("Next") );
605 playlist_Next( p_playlist );
606 vlc_object_release( p_playlist );
609 else if( i_action == ACTIONID_PREV )
611 p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
615 vout_OSDMessage( VLC_OBJECT(p_input), DEFAULT_CHAN, _("Previous") );
616 playlist_Prev( p_playlist );
617 vlc_object_release( p_playlist );
620 else if( i_action == ACTIONID_STOP )
622 p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
626 playlist_Stop( p_playlist );
627 vlc_object_release( p_playlist );
630 else if( i_action == ACTIONID_FASTER )
633 val.b_bool = VLC_TRUE;
634 var_Set( p_input, "rate-faster", val );
635 vout_OSDMessage( VLC_OBJECT(p_input), DEFAULT_CHAN, _("Faster") );
637 else if( i_action == ACTIONID_SLOWER )
640 val.b_bool = VLC_TRUE;
641 var_Set( p_input, "rate-slower", val );
642 vout_OSDMessage( VLC_OBJECT(p_input), DEFAULT_CHAN, _("Slower") );
644 else if( i_action == ACTIONID_POSITION && b_seekable )
646 DisplayPosition( p_intf, p_vout, p_input );
648 else if( i_action >= ACTIONID_PLAY_BOOKMARK1 &&
649 i_action <= ACTIONID_PLAY_BOOKMARK10 )
651 PlayBookmark( p_intf, i_action - ACTIONID_PLAY_BOOKMARK1 + 1 );
653 else if( i_action >= ACTIONID_SET_BOOKMARK1 &&
654 i_action <= ACTIONID_SET_BOOKMARK10 )
656 SetBookmark( p_intf, i_action - ACTIONID_SET_BOOKMARK1 + 1 );
658 /* Only makes sense with DVD */
659 else if( i_action == ACTIONID_TITLE_PREV )
661 val.b_bool = VLC_TRUE;
662 var_Set( p_input, "prev-title", val );
664 else if( i_action == ACTIONID_TITLE_NEXT )
666 val.b_bool = VLC_TRUE;
667 var_Set( p_input, "next-title", val );
669 else if( i_action == ACTIONID_CHAPTER_PREV )
671 val.b_bool = VLC_TRUE;
672 var_Set( p_input, "prev-chapter", val );
674 else if( i_action == ACTIONID_CHAPTER_NEXT )
676 val.b_bool = VLC_TRUE;
677 var_Set( p_input, "next-chapter", val );
683 static int GetKey( intf_thread_t *p_intf)
685 vlc_mutex_lock( &p_intf->p_sys->change_lock );
686 if ( p_intf->p_sys->i_size == 0 )
688 vlc_mutex_unlock( &p_intf->p_sys->change_lock );
693 int i_return = p_intf->p_sys->p_keys[ 0 ];
695 p_intf->p_sys->i_size--;
696 for ( i = 0; i < BUFFER_SIZE - 1; i++)
698 p_intf->p_sys->p_keys[ i ] = p_intf->p_sys->p_keys[ i + 1 ];
700 vlc_mutex_unlock( &p_intf->p_sys->change_lock );
705 /*****************************************************************************
706 * KeyEvent: callback for keyboard events
707 *****************************************************************************/
708 static int KeyEvent( vlc_object_t *p_this, char const *psz_var,
709 vlc_value_t oldval, vlc_value_t newval, void *p_data )
711 intf_thread_t *p_intf = (intf_thread_t *)p_data;
712 vlc_mutex_lock( &p_intf->p_sys->change_lock );
713 if ( p_intf->p_sys->i_size == BUFFER_SIZE )
715 msg_Warn( p_intf, "event buffer full, dropping keypress" );
716 vlc_mutex_unlock( &p_intf->p_sys->change_lock );
721 p_intf->p_sys->p_keys[ p_intf->p_sys->i_size ] = newval.i_int;
722 p_intf->p_sys->i_size++;
724 vlc_mutex_unlock( &p_intf->p_sys->change_lock );
729 static int ActionKeyCB( vlc_object_t *p_this, char const *psz_var,
730 vlc_value_t oldval, vlc_value_t newval, void *p_data )
732 vlc_t *p_vlc = (vlc_t *)p_this;
733 struct hotkey *p_hotkeys = p_vlc->p_hotkeys;
737 for( i = 0; p_hotkeys[i].psz_action != NULL; i++ )
739 if( !strcmp( p_hotkeys[i].psz_action, psz_var ) )
741 p_hotkeys[i].i_key = newval.i_int;
742 /* do hotkey accounting */
744 if( (p_hotkeys[i].i_delta_date > 0) &&
745 (p_hotkeys[i].i_delta_date <= (i_date - p_hotkeys[i].i_last_date) ) )
746 p_hotkeys[i].i_times = 0;
748 p_hotkeys[i].i_times++;
749 p_hotkeys[i].i_last_date = i_date;
756 static void PlayBookmark( intf_thread_t *p_intf, int i_num )
760 char psz_bookmark_name[11];
761 playlist_t *p_playlist =
762 vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
764 sprintf( psz_bookmark_name, "bookmark%i", i_num );
765 var_Create( p_intf, psz_bookmark_name, VLC_VAR_STRING|VLC_VAR_DOINHERIT );
766 var_Get( p_intf, psz_bookmark_name, &val );
770 char *psz_bookmark = strdup( val.psz_string );
771 for( i_position = 0; i_position < p_playlist->i_size; i_position++)
773 if( !strcmp( psz_bookmark,
774 p_playlist->pp_items[i_position]->input.psz_uri ) )
776 playlist_Goto( p_playlist, i_position );
780 vlc_object_release( p_playlist );
784 static void SetBookmark( intf_thread_t *p_intf, int i_num )
786 playlist_t *p_playlist =
787 vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
790 char psz_bookmark_name[11];
791 sprintf( psz_bookmark_name, "bookmark%i", i_num );
792 var_Create( p_intf, psz_bookmark_name,
793 VLC_VAR_STRING|VLC_VAR_DOINHERIT );
794 if( p_playlist->status.p_item )
796 config_PutPsz( p_intf, psz_bookmark_name,
797 p_playlist->status.p_item->input.psz_uri);
798 msg_Info( p_intf, "setting playlist bookmark %i to %s", i_num,
799 p_playlist->status.p_item->input.psz_uri);
800 config_SaveConfigFile( p_intf, "hotkeys" );
802 vlc_object_release( p_playlist );
806 static void DisplayPosition( intf_thread_t *p_intf, vout_thread_t *p_vout,
807 input_thread_t *p_input )
809 char psz_duration[MSTRTIME_MAX_SIZE];
810 char psz_time[MSTRTIME_MAX_SIZE];
811 vlc_value_t time, pos;
818 ClearChannels( p_intf, p_vout );
820 var_Get( p_input, "time", &time );
821 i_seconds = time.i_time / 1000000;
822 secstotimestr ( psz_time, i_seconds );
824 var_Get( p_input, "length", &time );
825 if( time.i_time > 0 )
827 secstotimestr( psz_duration, time.i_time / 1000000 );
828 vout_OSDMessage( p_input, POSITION_TEXT_CHAN, "%s / %s",
829 psz_time, psz_duration );
831 else if( i_seconds > 0 )
833 vout_OSDMessage( p_input, POSITION_TEXT_CHAN, psz_time );
836 if( !p_vout->p_parent_intf || p_vout->b_fullscreen )
838 var_Get( p_input, "position", &pos );
839 vout_OSDSlider( VLC_OBJECT( p_input ), POSITION_WIDGET_CHAN,
840 pos.f_float * 100, OSD_HOR_SLIDER );
844 static void DisplayVolume( intf_thread_t *p_intf, vout_thread_t *p_vout,
845 audio_volume_t i_vol )
851 ClearChannels( p_intf, p_vout );
853 if( !p_vout->p_parent_intf || p_vout->b_fullscreen )
855 vout_OSDSlider( VLC_OBJECT( p_vout ), VOLUME_WIDGET_CHAN,
856 i_vol*100/AOUT_VOLUME_MAX, OSD_VERT_SLIDER );
860 vout_OSDMessage( p_vout, VOLUME_TEXT_CHAN, "Volume %d%%",
861 i_vol*400/AOUT_VOLUME_MAX );
865 static void ClearChannels( intf_thread_t *p_intf, vout_thread_t *p_vout )
871 spu_Control( p_vout->p_spu, SPU_CHANNEL_CLEAR, DEFAULT_CHAN );
872 for( i = 0; i < CHANNELS_NUMBER; i++ )
874 spu_Control( p_vout->p_spu, SPU_CHANNEL_CLEAR,
875 p_intf->p_sys->p_channels[ i ] );