* modules/*: sanitization of the modules description strings.
[vlc.git] / modules / control / lirc / lirc.c
1 /*****************************************************************************
2  * lirc.c : lirc plugin for vlc
3  *****************************************************************************
4  * Copyright (C) 2002 VideoLAN
5  * $Id: lirc.c,v 1.6 2003/03/30 18:14:37 gbazin 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 <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 static void Feedback( intf_thread_t *, char * );
59
60 /*****************************************************************************
61  * Module descriptor
62  *****************************************************************************/
63 vlc_module_begin();
64     set_description( _("infrared remote control interface") );
65     set_capability( "interface", 0 );
66     set_callbacks( Open, Close );
67 vlc_module_end();
68
69 /*****************************************************************************
70  * Open: initialize interface
71  *****************************************************************************/
72 static int Open( vlc_object_t *p_this )
73 {
74     intf_thread_t *p_intf = (intf_thread_t *)p_this;
75     int i_fd;
76
77     /* Allocate instance and initialize some members */
78     p_intf->p_sys = malloc( sizeof( intf_sys_t ) );
79     if( p_intf->p_sys == NULL )
80     {
81         msg_Err( p_intf, "out of memory" );
82         return 1;
83     }
84
85     p_intf->pf_run = Run;
86
87     i_fd = lirc_init( "vlc", 1 );
88     if( i_fd == -1 )
89     {
90         msg_Err( p_intf, "lirc_init failed" );
91         free( p_intf->p_sys );
92         return 1;
93     }
94
95     /* We want polling */
96     fcntl( i_fd, F_SETFL, fcntl( i_fd, F_GETFL ) | O_NONBLOCK );
97
98     if( lirc_readconfig( NULL, &p_intf->p_sys->config, NULL ) != 0 )
99     {
100         msg_Err( p_intf, "lirc_readconfig failed" );
101         lirc_deinit();
102         free( p_intf->p_sys );
103         return 1;
104     }
105
106     p_intf->p_sys->p_input = NULL;
107
108     return 0;
109 }
110
111 /*****************************************************************************
112  * Close: destroy interface
113  *****************************************************************************/
114 static void Close( vlc_object_t *p_this )
115 {
116     intf_thread_t *p_intf = (intf_thread_t *)p_this;
117
118     if( p_intf->p_sys->p_input )
119     {
120         vlc_object_release( p_intf->p_sys->p_input );
121     }
122     if( p_intf->p_sys->p_vout )
123     {
124         vlc_object_release( p_intf->p_sys->p_vout );
125     }
126     /* Destroy structure */
127     lirc_freeconfig( p_intf->p_sys->config );
128     lirc_deinit();
129     free( p_intf->p_sys );
130 }
131
132 /*****************************************************************************
133  * Run: main loop
134  *****************************************************************************/
135 static void Run( intf_thread_t *p_intf )
136 {
137     char *code, *c;
138     playlist_t *p_playlist;
139     input_thread_t *p_input;
140     vout_thread_t *p_vout = NULL;
141     
142     while( !p_intf->b_die )
143     {
144         /* Sleep a bit */
145         msleep( INTF_IDLE_SLEEP );
146
147         /* Update the input */
148         if( p_intf->p_sys->p_input == NULL )
149         {
150             p_intf->p_sys->p_input = vlc_object_find( p_intf, VLC_OBJECT_INPUT,
151                                                               FIND_ANYWHERE );
152         }
153         else if( p_intf->p_sys->p_input->b_dead )
154         {
155             vlc_object_release( p_intf->p_sys->p_input );
156             p_intf->p_sys->p_input = NULL;
157         }
158         p_input = p_intf->p_sys->p_input;
159
160         /* Update the vout */
161         if( p_vout == NULL )
162         {
163             p_vout = vlc_object_find( p_intf, VLC_OBJECT_VOUT,
164                                       FIND_ANYWHERE );
165             p_intf->p_sys->p_vout = p_vout;
166         }
167         else if( p_vout->b_die )
168         {
169             vlc_object_release( p_vout );
170             p_vout = NULL;
171             p_intf->p_sys->p_vout = NULL;
172         }
173
174         /* We poll the lircsocket */
175         if( lirc_nextcode(&code) != 0 )
176         {
177             break;
178         }
179
180         if( code == NULL )
181         {
182             continue;
183         }
184
185         while( !p_intf->b_die 
186                 && lirc_code2char( p_intf->p_sys->config, code, &c ) == 0
187                 && c != NULL )
188         {
189             
190             if( !strcmp( c, "QUIT" ) )
191             {
192                 p_intf->p_vlc->b_die = VLC_TRUE;
193                 Feedback( p_intf, _("Quit" ) );
194                 continue;
195             }
196             if( !strcmp( c, "VOL_UP" ) )
197             {
198                 audio_volume_t i_newvol;
199                 char string[9];
200                 aout_VolumeUp( p_intf, 1, &i_newvol );
201                 sprintf( string, "Vol %%%d", i_newvol*100/AOUT_VOLUME_MAX );
202                 Feedback( p_intf, string );
203             }
204             if( !strcmp( c, "VOL_DOWN" ) )
205             {
206                 audio_volume_t i_newvol;
207                 char string[9];
208                 aout_VolumeDown( p_intf, 1, &i_newvol );
209                 sprintf( string, "Vol %%%d", i_newvol*100/AOUT_VOLUME_MAX );
210                 Feedback( p_intf, string );
211             }
212             if( p_vout )
213             {
214                 if( !strcmp( c, "FULLSCREEN" ) )
215                 {
216                     p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE;
217                     continue;
218                 }
219                 if( !strcmp( c, "ACTIVATE" ) )
220                 {
221                     vlc_value_t val;
222                     val.psz_string = "ENTER";
223                     if (var_Set( p_vout, "key-pressed", val ) != VLC_SUCCESS)
224                     {
225                         msg_Warn( p_intf, "key-press failed" );
226                     }
227                     continue;
228                 }
229
230                 if( !strcmp( c, "LEFT" ) )
231                 {
232                     vlc_value_t val;
233                     val.psz_string = "LEFT";
234                     if (var_Set( p_vout, "key-pressed", val ) != VLC_SUCCESS)
235                     {
236                         msg_Warn( p_intf, "key-press failed" );
237                     }
238                     continue;
239                 }
240
241                 if( !strcmp( c, "RIGHT" ) )
242                 {
243                     vlc_value_t val;
244                     val.psz_string = "RIGHT";
245                     if (var_Set( p_vout, "key-pressed", val ) != VLC_SUCCESS)
246                     {
247                         msg_Warn( p_intf, "key-press failed" );
248                     }
249                     continue;
250                 }
251
252                 if( !strcmp( c, "UP" ) )
253                 {
254                     vlc_value_t val;
255                     val.psz_string = "UP";
256                     if (var_Set( p_vout, "key-pressed", val ) != VLC_SUCCESS)
257                     {
258                         msg_Warn( p_intf, "key-press failed" );
259                     }
260                     continue;
261                 }
262
263                 if( !strcmp( c, "DOWN" ) )
264                 {
265                     vlc_value_t val;
266                     val.psz_string = "DOWN";
267                     if (var_Set( p_vout, "key-pressed", val ) != VLC_SUCCESS)
268                     {
269                         msg_Warn( p_intf, "key-press failed" );
270                     }
271                     continue;
272                 }
273             }
274             
275             if( !strcmp( c, "PLAY" ) )
276             {
277                 p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
278                                                       FIND_ANYWHERE );
279                 if( p_playlist )
280                 {
281                     vlc_mutex_lock( &p_playlist->object_lock );
282                     if( p_playlist->i_size )
283                     {
284                         vlc_mutex_unlock( &p_playlist->object_lock );
285                         playlist_Play( p_playlist );
286                         vlc_object_release( p_playlist );
287                     }
288                 }
289                 continue;
290             }
291             
292             if( !strcmp( c, "PLAYPAUSE" ) )
293             {
294                 if( p_input &&
295                     p_input->stream.control.i_status != PAUSE_S )
296                 {
297                     Feedback( p_intf, _( "Pause" ) );
298                     input_SetStatus( p_input, INPUT_STATUS_PAUSE );
299                 }
300                 else
301                 {
302                     p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
303                                                   FIND_ANYWHERE );
304                     if( p_playlist )
305                     {
306                         vlc_mutex_lock( &p_playlist->object_lock );
307                         if( p_playlist->i_size )
308                         {
309                             vlc_mutex_unlock( &p_playlist->object_lock );
310                             Feedback( p_intf, _( "Play" ) );
311                             playlist_Play( p_playlist );
312                             vlc_object_release( p_playlist );
313                         }
314                     }
315                 }                    
316                 continue;
317             }
318             
319             else if( p_input )
320             {
321                 if( !strcmp( c, "PAUSE" ) )
322                 {
323                     Feedback( p_intf, _( "Pause" ) );
324                     input_SetStatus( p_input, INPUT_STATUS_PAUSE );
325                 }
326                 else if( !strcmp( c, "NEXT" ) )
327                 {
328                     p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
329                                                           FIND_ANYWHERE );
330                     if( p_playlist )
331                     {
332                         playlist_Next( p_playlist );
333                         vlc_object_release( p_playlist );
334                     }
335                 }
336                 else if( !strcmp( c, "PREV" ) )
337                 {
338                     p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
339                                                           FIND_ANYWHERE );
340                     if( p_playlist )
341                     {
342                         playlist_Prev( p_playlist );
343                         vlc_object_release( p_playlist );
344                     }
345                 }
346                 else if( !strcmp( c, "STOP" ) )
347                 {
348                     p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
349                                                           FIND_ANYWHERE );
350                     if( p_playlist )
351                     {
352                         playlist_Stop( p_playlist );
353                         vlc_object_release( p_playlist );
354                     }
355                 }
356                 else if( !strcmp( c, "FAST" ) )
357                 {
358                     input_SetStatus( p_input, INPUT_STATUS_FASTER );
359                 }
360                 else if( !strcmp( c, "SLOW" ) )
361                 {
362                     input_SetStatus( p_input, INPUT_STATUS_SLOWER );
363                 }
364             }
365         }
366
367         free( code );
368     }
369 }
370
371 static void Feedback( intf_thread_t *p_intf, char *psz_string )
372 {
373         vlc_value_t val, lockval;
374     if ( p_intf->p_sys->p_vout
375          && var_Get( p_intf->p_sys->p_vout, "lock", &lockval ) == VLC_SUCCESS )
376     {
377         vlc_mutex_lock( lockval.p_address );
378         val.i_int = OSD_ALIGN_RIGHT|OSD_ALIGN_BOTTOM;
379         var_Set( p_intf->p_sys->p_vout, "flags", val ); 
380         val.i_int = 400000;
381         var_Set( p_intf->p_sys->p_vout, "duration", val ); 
382         val.i_int = 30;
383         var_Set( p_intf->p_sys->p_vout, "x-margin", val ); 
384         val.i_int = 20;
385         var_Set( p_intf->p_sys->p_vout, "y-margin", val );
386         val.psz_string = psz_string;
387         var_Set( p_intf->p_sys->p_vout, "string", val );
388         vlc_mutex_unlock( lockval.p_address );
389     }
390     else
391     {
392         msg_Dbg( p_intf, psz_string );
393     }
394 }