]> git.sesse.net Git - vlc/blob - plugins/text/rc.c
* ALL: got rid of p_object->p_this which is now useless.
[vlc] / plugins / text / 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.16 2002/06/01 18:04:49 sam 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 /*****************************************************************************
52  * intf_sys_t: description and status of rc interface
53  *****************************************************************************/
54 struct intf_sys_s
55 {
56     vlc_mutex_t         change_lock;
57 };
58
59 #define MAX_LINE_LENGTH 256
60
61 /*****************************************************************************
62  * Local prototypes.
63  *****************************************************************************/
64 static void intf_getfunctions ( function_list_t * p_function_list );
65 static int  intf_Open         ( intf_thread_t *p_intf );
66 static void intf_Close        ( intf_thread_t *p_intf );
67 static void intf_Run          ( intf_thread_t *p_intf );
68
69 /*****************************************************************************
70  * Build configuration tree.
71  *****************************************************************************/
72 MODULE_CONFIG_START
73 MODULE_CONFIG_STOP
74
75 MODULE_INIT_START
76     SET_DESCRIPTION( _("remote control interface module") )
77     ADD_CAPABILITY( INTF, 20 )
78 MODULE_INIT_STOP
79
80 MODULE_ACTIVATE_START
81     intf_getfunctions( &p_module->p_functions->intf );
82 MODULE_ACTIVATE_STOP
83
84 MODULE_DEACTIVATE_START
85 MODULE_DEACTIVATE_STOP
86
87 /*****************************************************************************
88  * Functions exported as capabilities. They are declared as static so that
89  * we don't pollute the namespace too much.
90  *****************************************************************************/
91 static void intf_getfunctions( function_list_t * p_function_list )
92 {
93     p_function_list->functions.intf.pf_open  = intf_Open;
94     p_function_list->functions.intf.pf_close = intf_Close;
95     p_function_list->functions.intf.pf_run   = intf_Run;
96 }
97
98 /*****************************************************************************
99  * intf_Open: initialize and create stuff
100  *****************************************************************************/
101 static int intf_Open( intf_thread_t *p_intf )
102 {
103     /* Non-buffered stdout */
104     setvbuf( stdout, (char *)NULL, _IOLBF, 0 );
105
106     /* Allocate instance and initialize some members */
107     p_intf->p_sys = (intf_sys_t *)malloc( sizeof( intf_sys_t ) );
108     if( p_intf->p_sys == NULL )
109     {
110         msg_Err( p_intf, "out of memory" );
111         return( 1 );
112     }
113
114 #ifdef WIN32
115     AllocConsole();
116     freopen( "CONOUT$", "w", stdout );
117     freopen( "CONOUT$", "w", stderr );
118     freopen( "CONIN$", "r", stdin );
119     printf( VERSION_MESSAGE "\n" );
120 #endif
121
122     printf( "remote control interface initialized, `h' for help\n" );
123     return( 0 );
124 }
125
126 /*****************************************************************************
127  * intf_Close: destroy interface stuff
128  *****************************************************************************/
129 static void intf_Close( intf_thread_t *p_intf )
130 {
131     /* Destroy structure */
132     free( p_intf->p_sys );
133 }
134
135 /*****************************************************************************
136  * intf_Run: rc thread
137  *****************************************************************************
138  * This part of the interface is in a separate thread so that we can call
139  * exec() from within it without annoying the rest of the program.
140  *****************************************************************************/
141 static void intf_Run( intf_thread_t *p_intf )
142 {
143     char       p_buffer[ MAX_LINE_LENGTH + 1 ];
144     vlc_bool_t b_complete = 0;
145
146     int        i_dummy;
147     off_t      i_oldpos = 0;
148     off_t      i_newpos;
149     fd_set     fds;                                        /* stdin changed? */
150     struct timeval tv;                                   /* how long to wait */
151
152     double     f_ratio = 1;
153
154     input_thread_t *p_input;
155
156     while( !p_intf->b_die )
157     {
158         b_complete = 0;
159
160         /* Check stdin */
161         tv.tv_sec = 0;
162         tv.tv_usec = 50000;
163         FD_ZERO( &fds );
164         FD_SET( STDIN_FILENO, &fds );
165
166         i_dummy = select( 32, &fds, NULL, NULL, &tv );
167         if( i_dummy > 0 )
168         {
169             int i_size = 0;
170
171             while( !p_intf->b_die
172                     && i_size < MAX_LINE_LENGTH
173                     && read( STDIN_FILENO, p_buffer + i_size, 1 ) > 0
174                     && p_buffer[ i_size ] != '\r'
175                     && p_buffer[ i_size ] != '\n' )
176             {
177                 i_size++;
178             }
179
180             if( i_size == MAX_LINE_LENGTH
181                  || p_buffer[ i_size ] == '\r'
182                  || p_buffer[ i_size ] == '\n' )
183             {
184                 p_buffer[ i_size ] = 0;
185                 b_complete = 1;
186             }
187         }
188
189         /* Manage the input part */
190         p_input = vlc_object_find( p_intf->p_vlc,
191                                    VLC_OBJECT_INPUT, FIND_CHILD );
192
193         if( p_input )
194         {
195             /* Get position */
196             vlc_mutex_lock( &p_input->stream.stream_lock );
197             if( !p_input->b_die && p_input->stream.i_mux_rate )
198             {
199 #define A p_input->stream.p_selected_area
200                 f_ratio = 1.0 / ( 50 * p_input->stream.i_mux_rate );
201                 i_newpos = A->i_tell * f_ratio;
202
203                 if( i_oldpos != i_newpos )
204                 {
205                     i_oldpos = i_newpos;
206                     printf( "pos: %li s / %li s\n", (long int)i_newpos,
207                             (long int)(f_ratio * A->i_size) );
208                 }
209 #undef S
210             }
211             vlc_mutex_unlock( &p_input->stream.stream_lock );
212         }
213
214         /* Is there something to do? */
215         if( b_complete == 1 )
216         {
217             char *p_cmd = p_buffer;
218
219             switch( p_cmd[0] )
220             {
221             case 'a':
222             case 'A':
223                 if( p_cmd[1] == ' ' )
224                 {
225 //                    playlist_Add( p_intf, PLAYLIST_END, p_cmd + 2 );
226 //                    playlist_Jumpto( p_intf->p_vlc->p_playlist,
227 //                                     p_intf->p_vlc->p_playlist->i_size-2 );
228                 }
229                 break;
230
231             case 'd':
232             case 'D':
233                 vlc_dumpstructure( p_intf->p_vlc );
234                 break;
235
236             case 'p':
237             case 'P':
238                 if( p_input )
239                 {
240                     input_SetStatus( p_input, INPUT_STATUS_PAUSE );
241                 }
242                 break;
243
244             case 'f':
245             case 'F':
246                 if( p_input )
247                 {
248                     vout_thread_t *p_vout;
249                     p_vout = vlc_object_find( p_input,
250                                               VLC_OBJECT_VOUT, FIND_CHILD );
251
252                     if( p_vout )
253                     {
254                         p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE;
255                         vlc_object_release( p_vout );
256                     }
257                 }
258                 break;
259
260             case 's':
261             case 'S':
262                 ;
263                 break;
264
265             case 'q':
266             case 'Q':
267                 p_intf->p_vlc->b_die = 1;
268                 break;
269
270             case 'r':
271             case 'R':
272                 if( p_input )
273                 {
274                     for( i_dummy = 1;
275                          i_dummy < MAX_LINE_LENGTH && p_cmd[ i_dummy ] >= '0'
276                                                    && p_cmd[ i_dummy ] <= '9';
277                          i_dummy++ )
278                     {
279                         ;
280                     }
281
282                     p_cmd[ i_dummy ] = 0;
283                     input_Seek( p_input, (off_t)atoi( p_cmd + 1 ),
284                                 INPUT_SEEK_SECONDS | INPUT_SEEK_SET );
285                     /* rcreseek(f_cpos); */
286                 }
287                 break;
288
289             case '?':
290             case 'h':
291             case 'H':
292                 printf( "help for remote control commands\n" );
293                 printf( "h . . . . . . . . . . . . . . . . . . . . . help\n" );
294                 printf( "a XYZ . . . . . . . . . . append XYZ to playlist\n" );
295                 printf( "p . . . . . . . . . . . . . . . . . toggle pause\n" );
296                 printf( "f . . . . . . . . . . . . . . toggle  fullscreen\n" );
297                 printf( "r X . . . seek in seconds,  for instance `r 3.5'\n" );
298                 printf( "q . . . . . . . . . . . . . . . . . . . . . quit\n" );
299                 printf( "end of help\n" );
300                 break;
301
302             default:
303                 printf( "unknown command `%s'\n", p_cmd );
304                 break;
305             }
306         }
307
308         if( p_input )
309         {
310             vlc_object_release( p_input );
311         }
312
313         msleep( INTF_IDLE_SLEEP );
314     }
315 }
316