]> git.sesse.net Git - vlc/blob - modules/control/hotkeys.c
d52a69ec6ecc89407033725eda8494c403c4b984
[vlc] / modules / control / hotkeys.c
1 /*****************************************************************************
2  * hotkeys.c: Hotkey handling for vlc
3  *****************************************************************************
4  * Copyright (C) 2003 VideoLAN
5  * $Id: hotkeys.c,v 1.1 2003/10/26 12:46:55 sigmunau Exp $
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 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include <stdlib.h>                                      /* malloc(), free() */
28 #include <string.h>
29
30 #include <vlc/vlc.h>
31 #include <vlc/intf.h>
32 #include <vlc/vout.h>
33 #include <vlc/aout.h>
34 #include <osd.h>
35
36 #define BUFFER_SIZE 10
37 /*****************************************************************************
38  * intf_sys_t: description and status of FB interface
39  *****************************************************************************/
40 struct intf_sys_t
41 {
42     vlc_mutex_t         change_lock;  /* mutex to keep the callback
43                                        * and the main loop from
44                                        * stepping on each others
45                                        * toes */
46     int                 p_keys[ BUFFER_SIZE ]; /* buffer that contains
47                                                 * keyevents */
48     int                 i_size;        /* number of events in buffer */
49     input_thread_t *    p_input;       /* pointer to input */
50     vout_thread_t *     p_vout;        /* pointer to vout object */
51 };
52
53 /*****************************************************************************
54  * Local prototypes
55  *****************************************************************************/
56 static int  Open    ( vlc_object_t * );
57 static void Close   ( vlc_object_t * );
58 static void Run     ( intf_thread_t * );
59 static void Feedback( intf_thread_t *, char * );
60 static int  GetKey  ( intf_thread_t *);
61 static int  KeyEvent( vlc_object_t *, char const *,
62                       vlc_value_t, vlc_value_t, void * );
63
64 /*****************************************************************************
65  * Module descriptor
66  *****************************************************************************/
67 vlc_module_begin();
68     set_description( _("hotkey interface") );
69     set_capability( "interface", 0 );
70     set_callbacks( Open, Close );
71 vlc_module_end();
72
73 /*****************************************************************************
74  * Open: initialize interface
75  *****************************************************************************/
76 static int Open( vlc_object_t *p_this )
77 {
78     intf_thread_t *p_intf = (intf_thread_t *)p_this;
79
80     /* Allocate instance and initialize some members */
81     p_intf->p_sys = malloc( sizeof( intf_sys_t ) );
82     if( p_intf->p_sys == NULL )
83     {
84         msg_Err( p_intf, "out of memory" );
85         return 1;
86     }
87     vlc_mutex_init( p_intf, &p_intf->p_sys->change_lock );
88     p_intf->p_sys->i_size = 0;
89     p_intf->pf_run = Run;
90
91     p_intf->p_sys->p_input = NULL;
92     p_intf->p_sys->p_vout = NULL;
93     var_AddCallback( p_intf->p_vlc, "key-pressed", KeyEvent, p_intf );
94     return 0;
95 }
96
97 /*****************************************************************************
98  * Close: destroy interface
99  *****************************************************************************/
100 static void Close( vlc_object_t *p_this )
101 {
102     intf_thread_t *p_intf = (intf_thread_t *)p_this;
103
104     if( p_intf->p_sys->p_input )
105     {
106         vlc_object_release( p_intf->p_sys->p_input );
107     }
108     if( p_intf->p_sys->p_vout )
109     {
110         vlc_object_release( p_intf->p_sys->p_vout );
111     }
112     /* Destroy structure */
113     free( p_intf->p_sys );
114 }
115
116 /*****************************************************************************
117  * Run: main loop
118  *****************************************************************************/
119 static void Run( intf_thread_t *p_intf )
120 {
121     playlist_t *p_playlist;
122     input_thread_t *p_input;
123     vout_thread_t *p_vout = NULL;
124     int i_fullscreen = config_GetInt( p_intf, "fullscreen-key" );
125     int i_quit = config_GetInt( p_intf, "quit-key" );
126     int i_vol_up = config_GetInt( p_intf, "vol-up-key" );
127     int i_vol_down = config_GetInt( p_intf, "vol-down-key" );
128     int i_play_pause = config_GetInt( p_intf, "play-pause-key" );    
129     int i_play = config_GetInt( p_intf, "play-key" );    
130     int i_pause = config_GetInt( p_intf, "pause-key" );    
131     int i_stop = config_GetInt( p_intf, "stop-key" );
132     int i_next = config_GetInt( p_intf, "next-key" );
133     int i_prev = config_GetInt( p_intf, "prev-key" );
134     int i_faster = config_GetInt( p_intf, "faster-key" );
135     int i_slower = config_GetInt( p_intf, "slower-key" );
136     int i_key = 0;
137     
138     while( !p_intf->b_die )
139     {
140         /* Sleep a bit */
141         msleep( INTF_IDLE_SLEEP );
142
143         /* Update the input */
144         if( p_intf->p_sys->p_input == NULL )
145         {
146             p_intf->p_sys->p_input = vlc_object_find( p_intf, VLC_OBJECT_INPUT,
147                                                       FIND_ANYWHERE );
148         }
149         else if( p_intf->p_sys->p_input->b_dead )
150         {
151             vlc_object_release( p_intf->p_sys->p_input );
152             p_intf->p_sys->p_input = NULL;
153         }
154         p_input = p_intf->p_sys->p_input;
155
156         /* Update the vout */
157         if( p_vout == NULL )
158         {
159             p_vout = vlc_object_find( p_intf, VLC_OBJECT_VOUT,
160                                       FIND_ANYWHERE );
161             p_intf->p_sys->p_vout = p_vout;
162         }
163         else if( p_vout->b_die )
164         {
165             vlc_object_release( p_vout );
166             p_vout = NULL;
167             p_intf->p_sys->p_vout = NULL;
168         }
169
170         i_key = GetKey( p_intf );
171         if ( !i_key )
172         {
173             /* No key pressed, sleep a bit more */
174             msleep( INTF_IDLE_SLEEP );
175             continue;
176         }
177         if( i_key == i_quit )
178         {
179             p_intf->p_vlc->b_die = VLC_TRUE;
180             Feedback( p_intf, _("Quit" ) );
181             continue;
182         }
183         if( i_key == i_vol_up )
184         {
185             audio_volume_t i_newvol;
186             char string[9];
187             aout_VolumeUp( p_intf, 1, &i_newvol );
188             sprintf( string, "Vol %%%d", i_newvol*100/AOUT_VOLUME_MAX );
189             Feedback( p_intf, string );
190         }
191         if( i_key == i_vol_down )
192         {
193             audio_volume_t i_newvol;
194             char string[9];
195             aout_VolumeDown( p_intf, 1, &i_newvol );
196             sprintf( string, "Vol %%%d", i_newvol*100/AOUT_VOLUME_MAX );
197             Feedback( p_intf, string );
198         }
199         if( p_vout )
200         {
201             if( i_key == i_fullscreen )
202             {
203                 p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE;
204                 continue;
205             }
206         }
207             
208         if( i_key == i_play )
209         {
210             p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
211                                           FIND_ANYWHERE );
212             if( p_playlist )
213             {
214                 vlc_mutex_lock( &p_playlist->object_lock );
215                 if( p_playlist->i_size )
216                 {
217                     vlc_mutex_unlock( &p_playlist->object_lock );
218                     playlist_Play( p_playlist );
219                     vlc_object_release( p_playlist );
220                 }
221             }
222             continue;
223         }
224             
225         if( i_key == i_play_pause )
226         {
227             if( p_input &&
228                 p_input->stream.control.i_status != PAUSE_S )
229             {
230                 Feedback( p_intf, _( "Pause" ) );
231                 input_SetStatus( p_input, INPUT_STATUS_PAUSE );
232             }
233             else
234             {
235                 p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
236                                               FIND_ANYWHERE );
237                 if( p_playlist )
238                 {
239                     vlc_mutex_lock( &p_playlist->object_lock );
240                     if( p_playlist->i_size )
241                     {
242                         vlc_mutex_unlock( &p_playlist->object_lock );
243                         Feedback( p_intf, _( "Play" ) );
244                         playlist_Play( p_playlist );
245                         vlc_object_release( p_playlist );
246                     }
247                 }
248             }                    
249             continue;
250         }
251             
252         else if( p_input )
253         {
254             if( i_key == i_pause )
255             {
256                 Feedback( p_intf, _( "Pause" ) );
257                 input_SetStatus( p_input, INPUT_STATUS_PAUSE );
258             }
259             else if( i_key == i_next )
260             {
261                 p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
262                                               FIND_ANYWHERE );
263                 if( p_playlist )
264                 {
265                     playlist_Next( p_playlist );
266                     vlc_object_release( p_playlist );
267                 }
268             }
269             else if( i_key == i_prev )
270             {
271                 p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
272                                               FIND_ANYWHERE );
273                 if( p_playlist )
274                 {
275                     playlist_Prev( p_playlist );
276                     vlc_object_release( p_playlist );
277                 }
278             }
279             else if( i_key == i_stop )
280             {
281                 p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
282                                               FIND_ANYWHERE );
283                 if( p_playlist )
284                 {
285                     playlist_Stop( p_playlist );
286                     vlc_object_release( p_playlist );
287                 }
288             }
289             else if( i_key == i_faster )
290             {
291                 input_SetStatus( p_input, INPUT_STATUS_FASTER );
292             }
293             else if( i_key == i_slower )
294             {
295                 input_SetStatus( p_input, INPUT_STATUS_SLOWER );
296             }
297         }
298
299     }
300 }
301
302 static void Feedback( intf_thread_t *p_intf, char *psz_string )
303 {
304     if ( p_intf->p_sys->p_vout )
305     {
306         vout_ShowTextRelative( p_intf->p_sys->p_vout, psz_string, NULL, 
307                                  OSD_ALIGN_TOP|OSD_ALIGN_RIGHT, 30,20,400000 );
308     }
309 }
310
311 static int  GetKey  ( intf_thread_t *p_intf)
312 {
313     vlc_mutex_lock( &p_intf->p_sys->change_lock );
314     if ( p_intf->p_sys->i_size == 0 )
315     {
316         vlc_mutex_unlock( &p_intf->p_sys->change_lock );
317         return 0;
318     }
319     else
320     {
321         int i_return = p_intf->p_sys->p_keys[ 0 ];
322         int i;
323         p_intf->p_sys->i_size--;
324         for ( i = 0; i < BUFFER_SIZE - 1; i++)
325         {
326             p_intf->p_sys->p_keys[ i ] = p_intf->p_sys->p_keys[ i + 1 ];
327         }
328         vlc_mutex_unlock( &p_intf->p_sys->change_lock );
329         return i_return;
330     }
331 }
332
333 /*****************************************************************************
334  * KeyEvent: callback for keyboard events
335  *****************************************************************************/
336 static int KeyEvent( vlc_object_t *p_this, char const *psz_var,
337                        vlc_value_t oldval, vlc_value_t newval, void *p_data )
338 {
339     intf_thread_t *p_intf = (intf_thread_t *)p_data;
340     vlc_mutex_lock( &p_intf->p_sys->change_lock );
341     if ( p_intf->p_sys->i_size == BUFFER_SIZE )
342     {
343         msg_Warn( p_intf, "Event buffer full, dropping keypress" );
344         vlc_mutex_unlock( &p_intf->p_sys->change_lock );
345         return VLC_EGENERIC;
346     }
347     else
348     {
349         p_intf->p_sys->p_keys[ p_intf->p_sys->i_size ] = newval.i_int;
350         p_intf->p_sys->i_size++;
351     }            
352     vlc_mutex_unlock( &p_intf->p_sys->change_lock );
353
354     return VLC_SUCCESS;
355 }
356