1 /*****************************************************************************
2 * rc.c : remote control stdin/stdout plugin for vlc
3 *****************************************************************************
4 * Copyright (C) 2001 VideoLAN
5 * $Id: rc.c,v 1.21 2002/07/15 20:09:31 sam Exp $
7 * Authors: Peter Surda <shurdeek@panorama.sth.ac.at>
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.
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.
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 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
27 #include <stdlib.h> /* malloc(), free() */
30 #include <errno.h> /* ENOMEM */
42 #ifdef HAVE_SYS_TIME_H
43 # include <sys/time.h>
45 #include <sys/types.h>
48 #include <winsock2.h> /* select() */
51 /*****************************************************************************
52 * intf_sys_t: description and status of rc interface
53 *****************************************************************************/
56 input_thread_t * p_input;
59 #define MAX_LINE_LENGTH 256
61 /*****************************************************************************
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 );
69 /*****************************************************************************
70 * Build configuration tree.
71 *****************************************************************************/
76 SET_DESCRIPTION( _("remote control interface module") )
77 ADD_CAPABILITY( INTF, 20 )
81 intf_getfunctions( &p_module->p_functions->intf );
84 MODULE_DEACTIVATE_START
85 MODULE_DEACTIVATE_STOP
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 )
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;
98 /*****************************************************************************
99 * intf_Open: initialize and create stuff
100 *****************************************************************************/
101 static int intf_Open( intf_thread_t *p_intf )
104 /* Check that stdin is a TTY */
107 msg_Warn( p_intf, "fd 0 is not a TTY" );
112 /* Non-buffered stdout */
113 setvbuf( stdout, (char *)NULL, _IOLBF, 0 );
115 /* Allocate instance and initialize some members */
116 p_intf->p_sys = (intf_sys_t *)malloc( sizeof( intf_sys_t ) );
117 if( p_intf->p_sys == NULL )
119 msg_Err( p_intf, "out of memory" );
125 freopen( "CONOUT$", "w", stdout );
126 freopen( "CONOUT$", "w", stderr );
127 freopen( "CONIN$", "r", stdin );
128 printf( VERSION_MESSAGE "\n" );
131 printf( "remote control interface initialized, `h' for help\n" );
135 /*****************************************************************************
136 * intf_Close: destroy interface stuff
137 *****************************************************************************/
138 static void intf_Close( intf_thread_t *p_intf )
140 /* Destroy structure */
141 free( p_intf->p_sys );
144 /*****************************************************************************
145 * intf_Run: rc thread
146 *****************************************************************************
147 * This part of the interface is in a separate thread so that we can call
148 * exec() from within it without annoying the rest of the program.
149 *****************************************************************************/
150 static void intf_Run( intf_thread_t *p_intf )
152 char p_buffer[ MAX_LINE_LENGTH + 1 ];
153 vlc_bool_t b_complete = 0;
158 fd_set fds; /* stdin changed? */
159 struct timeval tv; /* how long to wait */
163 p_intf->p_sys->p_input = NULL;
165 while( !p_intf->b_die )
173 FD_SET( STDIN_FILENO, &fds );
175 i_dummy = select( 32, &fds, NULL, NULL, &tv );
180 while( !p_intf->b_die
181 && i_size < MAX_LINE_LENGTH
182 && read( STDIN_FILENO, p_buffer + i_size, 1 ) > 0
183 && p_buffer[ i_size ] != '\r'
184 && p_buffer[ i_size ] != '\n' )
189 if( i_size == MAX_LINE_LENGTH
190 || p_buffer[ i_size ] == '\r'
191 || p_buffer[ i_size ] == '\n' )
193 p_buffer[ i_size ] = 0;
198 /* Manage the input part */
199 if( p_intf->p_sys->p_input == NULL )
201 p_intf->p_sys->p_input = vlc_object_find( p_intf, VLC_OBJECT_INPUT,
204 else if( p_intf->p_sys->p_input->b_dead )
206 vlc_object_release( p_intf->p_sys->p_input );
207 p_intf->p_sys->p_input = NULL;
210 if( p_intf->p_sys->p_input )
212 input_thread_t *p_input = p_intf->p_sys->p_input;
215 vlc_mutex_lock( &p_input->stream.stream_lock );
216 if( !p_input->b_die && p_input->stream.i_mux_rate )
218 #define A p_input->stream.p_selected_area
219 f_ratio = 1.0 / ( 50 * p_input->stream.i_mux_rate );
220 i_newpos = A->i_tell * f_ratio;
222 if( i_oldpos != i_newpos )
225 printf( "pos: %li s / %li s\n", (long int)i_newpos,
226 (long int)(f_ratio * A->i_size) );
230 vlc_mutex_unlock( &p_input->stream.stream_lock );
233 /* Is there something to do? */
234 if( b_complete == 1 )
236 char *p_cmd = p_buffer;
242 if( p_cmd[1] == ' ' )
244 playlist_t *p_playlist;
245 p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
249 playlist_Add( p_playlist, p_cmd + 2,
250 PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
251 vlc_object_release( p_playlist );
258 vlc_dumpstructure( p_intf->p_vlc );
263 if( p_intf->p_sys->p_input )
265 input_SetStatus( p_intf->p_sys->p_input,
266 INPUT_STATUS_PAUSE );
272 if( p_intf->p_sys->p_input )
274 vout_thread_t *p_vout;
275 p_vout = vlc_object_find( p_intf->p_sys->p_input,
276 VLC_OBJECT_VOUT, FIND_CHILD );
280 p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE;
281 vlc_object_release( p_vout );
293 p_intf->p_vlc->b_die = VLC_TRUE;
298 if( p_intf->p_sys->p_input )
301 i_dummy < MAX_LINE_LENGTH && p_cmd[ i_dummy ] >= '0'
302 && p_cmd[ i_dummy ] <= '9';
308 p_cmd[ i_dummy ] = 0;
309 input_Seek( p_intf->p_sys->p_input,
310 (off_t)atoi( p_cmd + 1 ),
311 INPUT_SEEK_SECONDS | INPUT_SEEK_SET );
312 /* rcreseek(f_cpos); */
319 printf( "help for remote control commands\n" );
320 printf( "h . . . . . . . . . . . . . . . . . . . . . help\n" );
321 printf( "a XYZ . . . . . . . . . . append XYZ to playlist\n" );
322 printf( "p . . . . . . . . . . . . . . . . . toggle pause\n" );
323 printf( "f . . . . . . . . . . . . . . toggle fullscreen\n" );
324 printf( "r X . . . seek in seconds, for instance `r 3.5'\n" );
325 printf( "q . . . . . . . . . . . . . . . . . . . . . quit\n" );
326 printf( "end of help\n" );
330 printf( "unknown command `%s'\n", p_cmd );
335 msleep( INTF_IDLE_SLEEP );
338 if( p_intf->p_sys->p_input )
340 vlc_object_release( p_intf->p_sys->p_input );
341 p_intf->p_sys->p_input = NULL;