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