a52ce4d0eb3457aa3ad0f251cba1455450d34a74
[vlc.git] / modules / control / rc / rc.c
1 /*****************************************************************************
2  * rc.c : remote control stdin/stdout plugin for vlc
3  *****************************************************************************
4  * Copyright (C) 2001 VideoLAN
5  * $Id: rc.c,v 1.2 2002/08/13 13:15:14 sigmunau Exp $
6  *
7  * Authors: Peter Surda <shurdeek@panorama.sth.ac.at>
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 <errno.h>                                                 /* ENOMEM */
31 #include <stdio.h>
32 #include <ctype.h>
33
34 #include <vlc/vlc.h>
35 #include <vlc/intf.h>
36 #include <vlc/vout.h>
37
38 #ifdef HAVE_UNISTD_H
39 #    include <unistd.h>
40 #endif
41
42 #ifdef HAVE_SYS_TIME_H
43 #    include <sys/time.h>
44 #endif
45 #include <sys/types.h>
46
47 #if defined( WIN32 )
48 #include <winsock2.h>                                            /* select() */
49 #endif
50
51 #define MAX_LINE_LENGTH 256
52
53 /*****************************************************************************
54  * Local prototypes
55  *****************************************************************************/
56 static int  Activate     ( vlc_object_t * );
57 static void Run          ( intf_thread_t *p_intf );
58
59 /*****************************************************************************
60  * Module descriptor
61  *****************************************************************************/
62 vlc_module_begin();
63     set_description( _("remote control interface module") );
64     set_capability( "interface", 20 );
65     set_callbacks( Activate, NULL );
66 vlc_module_end();
67
68 /*****************************************************************************
69  * Activate: initialize and create stuff
70  *****************************************************************************/
71 static int Activate( vlc_object_t *p_this )
72 {
73     intf_thread_t *p_intf = (intf_thread_t*)p_this;
74
75 #ifdef HAVE_ISATTY
76     /* Check that stdin is a TTY */
77     if( !isatty( 0 ) )
78     {
79         msg_Warn( p_intf, "fd 0 is not a TTY" );
80         return 1;
81     }
82 #endif
83
84     /* Non-buffered stdout */
85     setvbuf( stdout, (char *)NULL, _IOLBF, 0 );
86
87     p_intf->pf_run = Run;
88
89 #ifdef WIN32
90     AllocConsole();
91     freopen( "CONOUT$", "w", stdout );
92     freopen( "CONOUT$", "w", stderr );
93     freopen( "CONIN$", "r", stdin );
94     printf( VERSION_MESSAGE "\n" );
95 #endif
96
97     printf( "remote control interface initialized, `h' for help\n" );
98     return 0;
99 }
100
101 /*****************************************************************************
102  * Run: rc thread
103  *****************************************************************************
104  * This part of the interface is in a separate thread so that we can call
105  * exec() from within it without annoying the rest of the program.
106  *****************************************************************************/
107 static void Run( intf_thread_t *p_intf )
108 {
109     input_thread_t * p_input;
110
111     char       p_buffer[ MAX_LINE_LENGTH + 1 ];
112     vlc_bool_t b_complete = 0;
113     input_info_category_t * p_category;
114     input_info_t * p_info;
115
116     int        i_dummy;
117     off_t      i_oldpos = 0;
118     off_t      i_newpos;
119     fd_set     fds;                                        /* stdin changed? */
120     struct timeval tv;                                   /* how long to wait */
121
122     double     f_ratio = 1;
123     char       psz_dashes[81];
124
125     memset(psz_dashes, '-', 80);
126     psz_dashes[80] = '\0';
127     
128     p_input = NULL;
129
130     while( !p_intf->b_die )
131     {
132         b_complete = 0;
133
134         /* Check stdin */
135         tv.tv_sec = 0;
136         tv.tv_usec = 50000;
137         FD_ZERO( &fds );
138         FD_SET( STDIN_FILENO, &fds );
139
140         i_dummy = select( 32, &fds, NULL, NULL, &tv );
141         if( i_dummy > 0 )
142         {
143             int i_size = 0;
144
145             while( !p_intf->b_die
146                     && i_size < MAX_LINE_LENGTH
147                     && read( STDIN_FILENO, p_buffer + i_size, 1 ) > 0
148                     && p_buffer[ i_size ] != '\r'
149                     && p_buffer[ i_size ] != '\n' )
150             {
151                 i_size++;
152             }
153
154             if( i_size == MAX_LINE_LENGTH
155                  || p_buffer[ i_size ] == '\r'
156                  || p_buffer[ i_size ] == '\n' )
157             {
158                 p_buffer[ i_size ] = 0;
159                 b_complete = 1;
160             }
161         }
162
163         /* Manage the input part */
164         if( p_input == NULL )
165         {
166             p_input = vlc_object_find( p_intf, VLC_OBJECT_INPUT,
167                                                FIND_ANYWHERE );
168         }
169         else if( p_input->b_dead )
170         {
171             vlc_object_release( p_input );
172             p_input = NULL;
173         }
174
175         if( p_input )
176         {
177             /* Get position */
178             vlc_mutex_lock( &p_input->stream.stream_lock );
179             if( !p_input->b_die && p_input->stream.i_mux_rate )
180             {
181 #define A p_input->stream.p_selected_area
182                 f_ratio = 1.0 / ( 50 * p_input->stream.i_mux_rate );
183                 i_newpos = A->i_tell * f_ratio;
184
185                 if( i_oldpos != i_newpos )
186                 {
187                     i_oldpos = i_newpos;
188                     printf( "pos: %li s / %li s\n", (long int)i_newpos,
189                             (long int)(f_ratio * A->i_size) );
190                 }
191 #undef S
192             }
193             vlc_mutex_unlock( &p_input->stream.stream_lock );
194         }
195
196         /* Is there something to do? */
197         if( b_complete == 1 )
198         {
199             char *p_cmd = p_buffer;
200
201             switch( p_cmd[0] )
202             {
203             case 'a':
204             case 'A':
205                 if( p_cmd[1] == ' ' )
206                 {
207                     playlist_t *p_playlist;
208                     p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
209                                                           FIND_ANYWHERE );
210                     if( p_playlist )
211                     {
212                         playlist_Add( p_playlist, p_cmd + 2,
213                                 PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
214                         vlc_object_release( p_playlist );
215                     }
216                 }
217                 break;
218
219             case 'd':
220             case 'D':
221                 vlc_dumpstructure( p_intf->p_vlc );
222                 break;
223
224             case 'p':
225             case 'P':
226                 if( p_input )
227                 {
228                     input_SetStatus( p_input, INPUT_STATUS_PAUSE );
229                 }
230                 break;
231
232             case 'f':
233             case 'F':
234                 if( p_input )
235                 {
236                     vout_thread_t *p_vout;
237                     p_vout = vlc_object_find( p_input,
238                                               VLC_OBJECT_VOUT, FIND_CHILD );
239
240                     if( p_vout )
241                     {
242                         p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE;
243                         vlc_object_release( p_vout );
244                     }
245                 }
246                 break;
247
248             case 's':
249             case 'S':
250                 ;
251                 break;
252
253             case 'q':
254             case 'Q':
255                 p_intf->p_vlc->b_die = VLC_TRUE;
256                 break;
257
258             case 'r':
259             case 'R':
260                 if( p_input )
261                 {
262                     for( i_dummy = 1;
263                          i_dummy < MAX_LINE_LENGTH && p_cmd[ i_dummy ] >= '0'
264                                                    && p_cmd[ i_dummy ] <= '9';
265                          i_dummy++ )
266                     {
267                         ;
268                     }
269
270                     p_cmd[ i_dummy ] = 0;
271                     input_Seek( p_input, (off_t)atoi( p_cmd + 1 ),
272                                 INPUT_SEEK_SECONDS | INPUT_SEEK_SET );
273                     /* rcreseek(f_cpos); */
274                 }
275                 break;
276
277             case '?':
278             case 'h':
279             case 'H':
280                 printf( "help for remote control commands\n" );
281                 printf( "h . . . . . . . . . . . . . . . . . . . . . help\n" );
282                 printf( "a XYZ . . . . . . . . . . append XYZ to playlist\n" );
283                 printf( "p . . . . . . . . . . . . . . . . . toggle pause\n" );
284                 printf( "f . . . . . . . . . . . . . . toggle  fullscreen\n" );
285                 printf( "r X . . . seek in seconds,  for instance `r 3.5'\n" );
286                 printf( "q . . . . . . . . . . . . . . . . . . . . . quit\n" );
287                 printf( "end of help\n" );
288                 break;
289             case 'i':
290             case 'I':
291                 if ( p_input ) {
292                     printf( "Dumping stream info\n" );
293                     vlc_mutex_lock( &p_input->stream.stream_lock );
294                     p_category = p_input->stream.p_info;
295                     while ( p_category )
296                     {
297                         psz_dashes[72 - strlen(p_category->psz_name) ] = '\0';
298                         printf( "+--| %s |%s+\n", p_category->psz_name, psz_dashes);
299                         psz_dashes[72 - strlen(p_category->psz_name) ] = '-';
300                         p_info = p_category->p_info;
301                         while ( p_info )
302                         {
303                             printf( "| %s: %s\n", p_info->psz_name,
304                                     p_info->psz_value );
305                             p_info = p_info->p_next;
306                         }
307                         printf("|\n");
308                         p_category = p_category->p_next;
309                     }
310                     psz_dashes[78] = '\0';
311                     printf( "+%s+\n", psz_dashes );
312                     vlc_mutex_unlock( &p_input->stream.stream_lock );
313                 }
314                 else
315                 {
316                     printf( "no input" );
317                 }
318                 break;
319             case '\0':
320                 /* Ignore empty lines */
321                 break;
322             default:
323                 printf( "unknown command `%s'\n", p_cmd );
324                 break;
325             }
326         }
327
328         msleep( INTF_IDLE_SLEEP );
329     }
330
331     if( p_input )
332     {
333         vlc_object_release( p_input );
334         p_input = NULL;
335     }
336 }
337