]> git.sesse.net Git - vlc/blob - modules/control/lirc.c
* modules/video_filter/*: implemented a forwarding vout_vaControl().
[vlc] / modules / control / lirc.c
1 /*****************************************************************************
2  * lirc.c : lirc module for vlc
3  *****************************************************************************
4  * Copyright (C) 2004 VideoLAN
5  * $Id: lirc.c,v 1.11 2004/02/15 19:40:41 sigmunau Exp $
6  *
7  * Author: 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 <fcntl.h>
31
32 #include <vlc/vlc.h>
33 #include <vlc/intf.h>
34 #include <vlc/vout.h>
35 #include <vlc/aout.h>
36 #include <osd.h>
37
38 #include <lirc/lirc_client.h>
39
40 /*****************************************************************************
41  * intf_sys_t: description and status of FB interface
42  *****************************************************************************/
43 struct intf_sys_t
44 {
45     struct lirc_config *config;
46     vlc_mutex_t         change_lock;
47
48     input_thread_t *    p_input;
49     vout_thread_t *     p_vout;
50 };
51
52 /*****************************************************************************
53  * Local prototypes
54  *****************************************************************************/
55 static int  Open    ( vlc_object_t * );
56 static void Close   ( vlc_object_t * );
57 static void Run     ( intf_thread_t * );
58
59 /*****************************************************************************
60  * Module descriptor
61  *****************************************************************************/
62 vlc_module_begin();
63     set_description( _("Infrared remote control interface") );
64     set_capability( "interface", 0 );
65     set_callbacks( Open, Close );
66 vlc_module_end();
67
68 /*****************************************************************************
69  * Open: initialize interface
70  *****************************************************************************/
71 static int Open( vlc_object_t *p_this )
72 {
73     intf_thread_t *p_intf = (intf_thread_t *)p_this;
74     int i_fd;
75
76     /* Allocate instance and initialize some members */
77     p_intf->p_sys = malloc( sizeof( intf_sys_t ) );
78     if( p_intf->p_sys == NULL )
79     {
80         msg_Err( p_intf, "out of memory" );
81         return 1;
82     }
83
84     p_intf->pf_run = Run;
85
86     i_fd = lirc_init( "vlc", 1 );
87     if( i_fd == -1 )
88     {
89         msg_Err( p_intf, "lirc_init failed" );
90         free( p_intf->p_sys );
91         return 1;
92     }
93
94     /* We want polling */
95     fcntl( i_fd, F_SETFL, fcntl( i_fd, F_GETFL ) | O_NONBLOCK );
96
97     if( lirc_readconfig( NULL, &p_intf->p_sys->config, NULL ) != 0 )
98     {
99         msg_Err( p_intf, "lirc_readconfig failed" );
100         lirc_deinit();
101         free( p_intf->p_sys );
102         return 1;
103     }
104
105     p_intf->p_sys->p_input = NULL;
106
107     return 0;
108 }
109
110 /*****************************************************************************
111  * Close: destroy interface
112  *****************************************************************************/
113 static void Close( vlc_object_t *p_this )
114 {
115     intf_thread_t *p_intf = (intf_thread_t *)p_this;
116
117     if( p_intf->p_sys->p_input )
118     {
119         vlc_object_release( p_intf->p_sys->p_input );
120     }
121     if( p_intf->p_sys->p_vout )
122     {
123         vlc_object_release( p_intf->p_sys->p_vout );
124     }
125     /* Destroy structure */
126     lirc_freeconfig( p_intf->p_sys->config );
127     lirc_deinit();
128     free( p_intf->p_sys );
129 }
130
131 /*****************************************************************************
132  * Run: main loop
133  *****************************************************************************/
134 static void Run( intf_thread_t *p_intf )
135 {
136     char *code, *c;
137     playlist_t *p_playlist;
138     input_thread_t *p_input;
139     vout_thread_t *p_vout = NULL;
140
141     while( !p_intf->b_die )
142     {
143         /* Sleep a bit */
144         msleep( INTF_IDLE_SLEEP );
145
146         /* Update the input */
147         if( p_intf->p_sys->p_input == NULL )
148         {
149             p_intf->p_sys->p_input = vlc_object_find( p_intf, VLC_OBJECT_INPUT,
150                                                               FIND_ANYWHERE );
151         }
152         else if( p_intf->p_sys->p_input->b_dead )
153         {
154             vlc_object_release( p_intf->p_sys->p_input );
155             p_intf->p_sys->p_input = NULL;
156         }
157         p_input = p_intf->p_sys->p_input;
158
159         /* Update the vout */
160         if( p_vout == NULL )
161         {
162             p_vout = vlc_object_find( p_intf, VLC_OBJECT_VOUT,
163                                       FIND_ANYWHERE );
164             p_intf->p_sys->p_vout = p_vout;
165         }
166         else if( p_vout->b_die )
167         {
168             vlc_object_release( p_vout );
169             p_vout = NULL;
170             p_intf->p_sys->p_vout = NULL;
171         }
172
173         /* We poll the lircsocket */
174         if( lirc_nextcode(&code) != 0 )
175         {
176             break;
177         }
178
179         if( code == NULL )
180         {
181             continue;
182         }
183
184         while( !p_intf->b_die
185                 && lirc_code2char( p_intf->p_sys->config, code, &c ) == 0
186                 && c != NULL )
187         {
188
189             if( !strcmp( c, "QUIT" ) )
190             {
191                 p_intf->p_vlc->b_die = VLC_TRUE;
192                 vout_OSDMessage( p_intf, _("Quit" ) );
193                 continue;
194             }
195             else if( !strcmp( c, "VOL_UP" ) )
196             {
197                 audio_volume_t i_newvol;
198                 aout_VolumeUp( p_intf, 1, &i_newvol );
199                 vout_OSDMessage( p_intf, _("Vol %%%d"), i_newvol*100/AOUT_VOLUME_MAX );
200             }
201             else if( !strcmp( c, "VOL_DOWN" ) )
202             {
203                 audio_volume_t i_newvol;
204                 aout_VolumeDown( p_intf, 1, &i_newvol );
205                 vout_OSDMessage( p_intf, _("Vol %%%d"), i_newvol*100/AOUT_VOLUME_MAX );
206             }
207             else if( !strcmp( c, "MUTE" ) )
208             {
209                 audio_volume_t i_newvol = -1;
210                 aout_VolumeMute( p_intf, &i_newvol );
211                 if( i_newvol == 0 )
212                 {
213                     vout_OSDMessage( p_intf, _( "Mute" ) );
214                 }
215                 else
216                 {
217                     vout_OSDMessage( p_intf, _("Vol %d%%"), i_newvol*100/AOUT_VOLUME_MAX );
218                 }
219             }
220             if( p_vout )
221             {
222                 if( !strcmp( c, "FULLSCREEN" ) )
223                 {
224                     p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE;
225                     continue;
226                 }
227                 if( !strcmp( c, "ACTIVATE" ) )
228                 {
229                     vlc_value_t val;
230                     val.psz_string = "ENTER";
231                     if (var_Set( p_vout, "key-pressed", val ) != VLC_SUCCESS)
232                     {
233                         msg_Warn( p_intf, "key-press failed" );
234                     }
235                     continue;
236                 }
237
238                 if( !strcmp( c, "LEFT" ) )
239                 {
240                     vlc_value_t val;
241                     val.psz_string = "LEFT";
242                     if (var_Set( p_vout, "key-pressed", val ) != VLC_SUCCESS)
243                     {
244                         msg_Warn( p_intf, "key-press failed" );
245                     }
246                     continue;
247                 }
248
249                 if( !strcmp( c, "RIGHT" ) )
250                 {
251                     vlc_value_t val;
252                     val.psz_string = "RIGHT";
253                     if (var_Set( p_vout, "key-pressed", val ) != VLC_SUCCESS)
254                     {
255                         msg_Warn( p_intf, "key-press failed" );
256                     }
257                     continue;
258                 }
259
260                 if( !strcmp( c, "UP" ) )
261                 {
262                     vlc_value_t val;
263                     val.psz_string = "UP";
264                     if (var_Set( p_vout, "key-pressed", val ) != VLC_SUCCESS)
265                     {
266                         msg_Warn( p_intf, "key-press failed" );
267                     }
268                     continue;
269                 }
270
271                 if( !strcmp( c, "DOWN" ) )
272                 {
273                     vlc_value_t val;
274                     val.psz_string = "DOWN";
275                     if (var_Set( p_vout, "key-pressed", val ) != VLC_SUCCESS)
276                     {
277                         msg_Warn( p_intf, "key-press failed" );
278                     }
279                     continue;
280                 }
281             }
282
283             if( !strcmp( c, "PLAY" ) )
284             {
285                 p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
286                                                       FIND_ANYWHERE );
287                 if( p_playlist )
288                 {
289                     vlc_mutex_lock( &p_playlist->object_lock );
290                     if( p_playlist->i_size )
291                     {
292                         vlc_mutex_unlock( &p_playlist->object_lock );
293                         playlist_Play( p_playlist );
294                         vlc_object_release( p_playlist );
295                     }
296                 }
297                 continue;
298             }
299
300             if( !strcmp( c, "PLAYPAUSE" ) )
301             {
302                 vlc_value_t val;
303                 val.i_int = PLAYING_S;
304                 if( p_input )
305                 {
306                     var_Get( p_input, "state", &val );
307                 }
308                 if( p_input && val.i_int != PAUSE_S )
309                 {
310                     vout_OSDMessage( VLC_OBJECT(p_intf), _( "Pause" ) );
311                     val.i_int = PAUSE_S;
312                     var_Set( p_input, "state", val );
313                 }
314                 else
315                 {
316                     p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
317                                                   FIND_ANYWHERE );
318                     if( p_playlist )
319                     {
320                         vlc_mutex_lock( &p_playlist->object_lock );
321                         if( p_playlist->i_size )
322                         {
323                             vlc_mutex_unlock( &p_playlist->object_lock );
324                             vout_OSDMessage( p_intf, _( "Play" ) );
325                             playlist_Play( p_playlist );
326                             vlc_object_release( p_playlist );
327                         }
328                     }
329                 }
330                 continue;
331             }
332
333             else if( p_input )
334             {
335                 if( !strcmp( c, "AUDIO_TRACK" ) )
336                 {
337                     vlc_value_t val,list,list2;
338                     int i_count, i;
339                     var_Get( p_input, "audio-es", &val );
340                     var_Change( p_input, "audio-es", VLC_VAR_GETCHOICES, &list, &list2 );
341                     i_count = list.p_list->i_count;
342                     for( i = 0; i < i_count; i++ )
343                     {
344                         if( val.i_int == list.p_list->p_values[i].i_int )
345                         {
346                             break;
347                         }
348                     }
349                     /* value of audio-es was not in choices list */
350                     if( i == i_count )
351                     {
352                         msg_Warn( p_input, "invalid current audio track, selecting 0" );
353                         var_Set( p_input, "audio-es", list.p_list->p_values[0] );
354                         i = 0;
355                     }
356                     else if( i == i_count - 1 )
357                     {
358                         var_Set( p_input, "audio-es", list.p_list->p_values[0] );
359                         i = 0;
360                     }
361                     else
362                     {
363                         var_Set( p_input, "audio-es", list.p_list->p_values[i+1] );
364                         i = i + 1;
365                     }
366                     vout_OSDMessage( VLC_OBJECT(p_input), _("Audio track: %s"), list2.p_list->p_values[i].psz_string );
367                 }
368                 else if( !strcmp( c, "SUBTITLE_TRACK" ) )
369                 {
370                     vlc_value_t val,list,list2;
371                     int i_count, i;
372                     var_Get( p_input, "spu-es", &val );
373                     var_Change( p_input, "spu-es", VLC_VAR_GETCHOICES, &list, &list2 );
374                     i_count = list.p_list->i_count;
375                     for( i = 0; i < i_count; i++ )
376                     {
377                         if( val.i_int == list.p_list->p_values[i].i_int )
378                         {
379                             break;
380                         }
381                     }
382                     /* value of audio-es was not in choices list */
383                     if( i == i_count )
384                     {
385                         msg_Warn( p_input, "invalid current subtitle track, selecting 0" );
386                         var_Set( p_input, "spu-es", list.p_list->p_values[0] );
387                         i = 0;
388                     }
389                     else if( i == i_count - 1 )
390                     {
391                         var_Set( p_input, "spu-es", list.p_list->p_values[0] );
392                         i = 0;
393                     }
394                     else
395                     {
396                         var_Set( p_input, "spu-es", list.p_list->p_values[i+1] );
397                         i = i + 1;
398                     }
399                     vout_OSDMessage( VLC_OBJECT(p_input), _("Subtitle track: %s"), list2.p_list->p_values[i].psz_string );
400                 }
401                 else if( !strcmp( c, "PAUSE" ) )
402                 {
403                     vlc_value_t val;
404                     vout_OSDMessage( p_intf, _( "Pause" ) );
405                     val.i_int = PAUSE_S;
406                     var_Set( p_input, "state", val );
407                 }
408                 else if( !strcmp( c, "NEXT" ) )
409                 {
410                     p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
411                                                           FIND_ANYWHERE );
412                     if( p_playlist )
413                     {
414                         playlist_Next( p_playlist );
415                         vlc_object_release( p_playlist );
416                     }
417                 }
418                 else if( !strcmp( c, "PREV" ) )
419                 {
420                     p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
421                                                           FIND_ANYWHERE );
422                     if( p_playlist )
423                     {
424                         playlist_Prev( p_playlist );
425                         vlc_object_release( p_playlist );
426                     }
427                 }
428                 else if( !strcmp( c, "STOP" ) )
429                 {
430                     p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
431                                                           FIND_ANYWHERE );
432                     if( p_playlist )
433                     {
434                         playlist_Stop( p_playlist );
435                         vlc_object_release( p_playlist );
436                     }
437                 }
438                 else if( !strcmp( c, "FAST" ) )
439                 {
440                     vlc_value_t val; val.b_bool = VLC_TRUE;
441                     var_Set( p_input, "rate-faster", val );
442                 }
443                 else if( !strcmp( c, "SLOW" ) )
444                 {
445                     vlc_value_t val; val.b_bool = VLC_TRUE;
446                     var_Set( p_input, "rate-slower", val );
447                 }
448 /* beginning of modifications by stephane Thu Jun 19 15:29:49 CEST 2003 */
449                 else if ( !strcmp(c, "CHAPTER_N" ) ||
450                           !strcmp( c, "CHAPTER_P" ) )
451                 {
452                     unsigned int i_chapter = 0;
453
454                     if( !strcmp( c, "CHAPTER_N" ) )
455                     {
456                         vlc_mutex_lock( &p_input->stream.stream_lock );
457                         i_chapter = p_input->stream.p_selected_area->i_part + 1;
458                         vlc_mutex_unlock( &p_input->stream.stream_lock );
459                     }
460                     else if( !strcmp( c, "CHAPTER_P" ) )
461                     {
462                         vlc_mutex_lock( &p_input->stream.stream_lock );
463                         i_chapter = p_input->stream.p_selected_area->i_part - 1;
464                         vlc_mutex_unlock( &p_input->stream.stream_lock );
465                     }
466
467                     vlc_mutex_lock( &p_input->stream.stream_lock );
468                     if( ( i_chapter > 0 ) && ( i_chapter <
469                                                p_input->stream.p_selected_area->i_part_nb ) )
470                     {
471                         input_area_t *p_area = p_input->stream.p_selected_area;
472                         p_input->stream.p_selected_area->i_part = i_chapter;
473                         vlc_mutex_unlock( &p_input->stream.stream_lock );
474                         input_ChangeArea( p_input, p_area );
475                         input_SetStatus( p_input, INPUT_STATUS_PLAY );
476                         vlc_mutex_lock( &p_input->stream.stream_lock );
477                     }
478                     vlc_mutex_unlock( &p_input->stream.stream_lock );
479                 }
480 /* end of modification by stephane Thu Jun 19 15:29:49 CEST 2003 */
481             }
482         }
483
484         free( code );
485     }
486 }