]> git.sesse.net Git - vlc/blob - src/input/input.c
* input.c: don't add subtitle track twice when using --sub-file and
[vlc] / src / input / input.c
1 /*****************************************************************************
2  * input.c: input thread
3  * Read a stream, demultiplex and parse it before sending it to
4  * decoders.
5  *****************************************************************************
6  * Copyright (C) 1998-2004 VideoLAN
7  * $Id: input.c,v 1.288 2004/02/08 17:21:50 fenrir Exp $
8  *
9  * Authors: Christophe Massiot <massiot@via.ecp.fr>
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
24  *****************************************************************************/
25
26 /*****************************************************************************
27  * Preamble
28  *****************************************************************************/
29 #include <stdlib.h>
30
31 #include <vlc/vlc.h>
32 #include <vlc/input.h>
33 #include <vlc/decoder.h>
34 #include <vlc/vout.h>
35
36 #ifdef HAVE_SYS_TIMES_H
37 #   include <sys/times.h>
38 #endif
39
40 #include "vlc_playlist.h"
41
42 #include "stream_output.h"
43
44 #include "vlc_interface.h"
45 #include "codecs.h"
46 #include "vlc_meta.h"
47 #include "../../modules/demux/util/sub.h"
48
49 /*****************************************************************************
50  * Local prototypes
51  *****************************************************************************/
52 struct input_thread_sys_t
53 {
54     /* subtitles */
55     int              i_sub;
56     subtitle_demux_t **sub;
57 };
58
59 static  int RunThread       ( input_thread_t *p_input );
60 static  int InitThread      ( input_thread_t *p_input );
61 static void ErrorThread     ( input_thread_t *p_input );
62 static void EndThread       ( input_thread_t *p_input );
63
64 static void ParseOption     ( input_thread_t *p_input,
65                               const char *psz_option );
66
67 /*****************************************************************************
68  * Callbacks
69  *****************************************************************************/
70 static int PositionCallback( vlc_object_t *p_this, char const *psz_cmd,
71                              vlc_value_t oldval, vlc_value_t newval, void *p_data );
72 static int TimeCallback    ( vlc_object_t *p_this, char const *psz_cmd,
73                              vlc_value_t oldval, vlc_value_t newval, void *p_data );
74 static int StateCallback   ( vlc_object_t *p_this, char const *psz_cmd,
75                              vlc_value_t oldval, vlc_value_t newval, void *p_data );
76 static int RateCallback    ( vlc_object_t *p_this, char const *psz_cmd,
77                              vlc_value_t oldval, vlc_value_t newval, void *p_data );
78
79 /*****************************************************************************
80  * input_CreateThread: creates a new input thread
81  *****************************************************************************
82  * This function creates a new input, and returns a pointer
83  * to its description. On error, it returns NULL.
84  *****************************************************************************/
85 input_thread_t *__input_CreateThread( vlc_object_t *p_parent, char *psz_uri,
86                                       char **ppsz_options, int i_options )
87
88 {
89     input_thread_t *    p_input;                        /* thread descriptor */
90     vlc_value_t val;
91     int i;
92
93     /* Allocate descriptor */
94     p_input = vlc_object_create( p_parent, VLC_OBJECT_INPUT );
95     if( p_input == NULL )
96     {
97         msg_Err( p_parent, "out of memory" );
98         return NULL;
99     }
100
101     /* Parse input options */
102     for( i = 0; i < i_options; i++ )
103     {
104         msg_Dbg( p_input, "option: %s", ppsz_options[i] );
105         ParseOption( p_input, ppsz_options[i] );
106     }
107
108     /* Create a few object variables we'll need later on */
109     var_Create( p_input, "video", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
110     var_Create( p_input, "audio", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
111     var_Create( p_input, "audio-channel", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
112     var_Create( p_input, "spu-channel", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
113     var_Create( p_input, "sub-file", VLC_VAR_FILE | VLC_VAR_DOINHERIT );
114     var_Create( p_input, "sub-autodetect-file", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
115     var_Create( p_input, "sub-autodetect-fuzzy", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
116
117     var_Create( p_input, "sout", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
118     var_Create( p_input, "sout-all",   VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
119     var_Create( p_input, "sout-audio", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
120     var_Create( p_input, "sout-video", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
121     var_Create( p_input, "sout-keep",  VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
122
123     /* decoders */
124     var_Create( p_input, "minimize-threads", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
125
126     /* play status */
127
128     /* position variable */
129     var_Create( p_input, "position",  VLC_VAR_FLOAT );  /* position 0.0->1.0 */
130     var_Create( p_input, "position-offset",  VLC_VAR_FLOAT );  /* relative */
131     val.f_float = 0.0;
132     var_Change( p_input, "position", VLC_VAR_SETVALUE, &val, NULL );
133     var_AddCallback( p_input, "position", PositionCallback, NULL );
134     var_AddCallback( p_input, "position-offset", PositionCallback, NULL );
135
136     /* time variable */
137     var_Create( p_input, "time",  VLC_VAR_TIME );
138     var_Create( p_input, "time-offset",  VLC_VAR_TIME );    /* relative */
139     val.i_time = 0;
140     var_Change( p_input, "time", VLC_VAR_SETVALUE, &val, NULL );
141     var_AddCallback( p_input, "time", TimeCallback, NULL );
142     var_AddCallback( p_input, "time-offset", TimeCallback, NULL );
143
144     /* length variable */
145     var_Create( p_input, "length",  VLC_VAR_TIME );
146     val.i_time = 0;
147     var_Change( p_input, "length", VLC_VAR_SETVALUE, &val, NULL );
148
149     /* rate variable */
150     var_Create( p_input, "rate", VLC_VAR_INTEGER );
151     var_Create( p_input, "rate-slower", VLC_VAR_VOID );
152     var_Create( p_input, "rate-faster", VLC_VAR_VOID );
153     val.i_int = DEFAULT_RATE;
154     var_Change( p_input, "rate", VLC_VAR_SETVALUE, &val, NULL );
155     var_AddCallback( p_input, "rate", RateCallback, NULL );
156     var_AddCallback( p_input, "rate-slower", RateCallback, NULL );
157     var_AddCallback( p_input, "rate-faster", RateCallback, NULL );
158
159     /* state variable */
160     var_Create( p_input, "state", VLC_VAR_INTEGER );
161     val.i_int = INIT_S;
162     var_Change( p_input, "state", VLC_VAR_SETVALUE, &val, NULL );
163     var_AddCallback( p_input, "state", StateCallback, NULL );
164
165     /* state variable */
166     var_Create( p_input, "demuxed-id3", VLC_VAR_BOOL );
167     val.b_bool = VLC_FALSE;
168     var_Change( p_input, "demuxed-id3", VLC_VAR_SETVALUE, &val, NULL );
169
170     /* Initialize thread properties */
171     p_input->b_eof      = 0;
172     p_input->p_sys      = NULL;
173
174     /* Set target */
175     p_input->psz_source = strdup( psz_uri );
176
177     /* Stream */
178     p_input->s = NULL;
179
180     /* es out */
181     p_input->p_es_out = NULL;
182
183     /* Demux */
184     p_input->p_demux   = NULL;
185     p_input->pf_demux  = NULL;
186     p_input->pf_rewind = NULL;
187     p_input->pf_demux_control = NULL;
188     p_input->i_cr_average = config_GetInt( p_input, "cr-average" );
189
190     /* Access */
191     p_input->p_access = NULL;
192
193     p_input->i_bufsize = 0;
194     p_input->i_mtu = 0;
195     p_input->i_pts_delay = DEFAULT_PTS_DELAY;
196
197     /* Initialize statistics */
198     p_input->c_loops                    = 0;
199     p_input->stream.c_packets_read      = 0;
200     p_input->stream.c_packets_trashed   = 0;
201
202     /* Set locks. */
203     vlc_mutex_init( p_input, &p_input->stream.stream_lock );
204     vlc_cond_init( p_input, &p_input->stream.stream_wait );
205     vlc_mutex_init( p_input, &p_input->stream.control.control_lock );
206
207     /* Initialize stream description */
208     p_input->stream.b_changed = 0;
209     p_input->stream.i_es_number = 0;
210     p_input->stream.i_selected_es_number = 0;
211     p_input->stream.i_pgrm_number = 0;
212     p_input->stream.i_new_status = p_input->stream.i_new_rate = 0;
213     p_input->stream.b_new_mute = MUTE_NO_CHANGE;
214     p_input->stream.i_mux_rate = 0;
215     p_input->stream.b_seekable = 0;
216     p_input->stream.p_sout = NULL;
217
218     /* no stream, no program, no area, no es */
219     p_input->stream.p_new_program = NULL;
220
221     p_input->stream.i_area_nb = 0;
222     p_input->stream.pp_areas = NULL;
223     p_input->stream.p_selected_area = NULL;
224     p_input->stream.p_new_area = NULL;
225
226     p_input->stream.pp_selected_es = NULL;
227     p_input->stream.p_removed_es = NULL;
228     p_input->stream.p_newly_selected_es = NULL;
229
230     /* By default there is one area in a stream */
231     input_AddArea( p_input, 0, 1 );
232     p_input->stream.p_selected_area = p_input->stream.pp_areas[0];
233
234     /* Initialize stream control properties. */
235     p_input->stream.control.i_status = INIT_S;
236     p_input->stream.control.i_rate = DEFAULT_RATE;
237     p_input->stream.control.b_mute = 0;
238     p_input->stream.control.b_grayscale = config_GetInt( p_input, "grayscale");
239
240     msg_Info( p_input, "playlist item `%s'", p_input->psz_source );
241
242     /* Initialize input info */
243     p_input->stream.p_info = NULL;
244     p_input->stream.p_info = input_InfoCategory( p_input, _("General") );
245     input_AddInfo( p_input->stream.p_info, _("Playlist Item"),
246                    p_input->psz_source );
247     vlc_object_attach( p_input, p_parent );
248
249     /* Create thread and wait for its readiness. */
250     if( vlc_thread_create( p_input, "input", RunThread,
251                            VLC_THREAD_PRIORITY_INPUT, VLC_TRUE ) )
252     {
253         msg_Err( p_input, "cannot create input thread" );
254         input_DelInfo( p_input );
255         free( p_input );
256         return NULL;
257     }
258
259     return p_input;
260 }
261
262 /*****************************************************************************
263  * input_StopThread: mark an input thread as zombie
264  *****************************************************************************
265  * This function should not return until the thread is effectively cancelled.
266  *****************************************************************************/
267 void input_StopThread( input_thread_t *p_input )
268 {
269     /* Make the thread exit from a possible vlc_cond_wait() */
270     vlc_mutex_lock( &p_input->stream.stream_lock );
271     /* Request thread destruction */
272     p_input->b_die = 1;
273
274     vlc_cond_signal( &p_input->stream.stream_wait );
275     vlc_mutex_unlock( &p_input->stream.stream_lock );
276 }
277
278 /*****************************************************************************
279  * input_DestroyThread: mark an input thread as zombie
280  *****************************************************************************
281  * This function should not return until the thread is effectively cancelled.
282  *****************************************************************************/
283 void input_DestroyThread( input_thread_t *p_input )
284 {
285     /* Join the thread */
286     vlc_thread_join( p_input );
287
288     /* Destroy Mutex locks */
289     vlc_mutex_destroy( &p_input->stream.control.control_lock );
290     vlc_cond_destroy( &p_input->stream.stream_wait );
291     vlc_mutex_destroy( &p_input->stream.stream_lock );
292 }
293
294 /*****************************************************************************
295  * RunThread: main thread loop
296  *****************************************************************************
297  * Thread in charge of processing the network packets and demultiplexing.
298  *****************************************************************************/
299 static int RunThread( input_thread_t *p_input )
300 {
301     vlc_value_t  val;
302     mtime_t      i_update_next = -1;
303
304     /* Signal right now, otherwise we'll get stuck in a peek */
305     vlc_thread_ready( p_input );
306
307     if( InitThread( p_input ) )
308     {
309         /* If we failed, wait before we are killed, and exit */
310         p_input->b_error = 1;
311
312         ErrorThread( p_input );
313
314         /* Tell we're dead */
315         p_input->b_dead = 1;
316
317         input_DelInfo( p_input );
318
319         return 0;
320     }
321
322     /* initialization is complete */
323     vlc_mutex_lock( &p_input->stream.stream_lock );
324     p_input->stream.b_changed        = 1;
325     p_input->stream.control.i_status = PLAYING_S;
326     vlc_mutex_unlock( &p_input->stream.stream_lock );
327
328     val.i_int = PLAYING_S;
329     var_Change( p_input, "state", VLC_VAR_SETVALUE, &val, NULL );
330
331     while( !p_input->b_die && !p_input->b_error && !p_input->b_eof )
332     {
333         unsigned int i, i_count;
334
335         p_input->c_loops++;
336
337         vlc_mutex_lock( &p_input->stream.stream_lock );
338
339         if( p_input->stream.p_new_program )
340         {
341             if( p_input->pf_set_program != NULL )
342             {
343
344                 /* Reinitialize buffer manager. */
345                 input_AccessReinit( p_input );
346
347                 p_input->pf_set_program( p_input,
348                                          p_input->stream.p_new_program );
349
350                 /* Escape all decoders for the stream discontinuity they
351                  * will encounter. */
352                 input_EscapeDiscontinuity( p_input );
353
354                 for( i = 0; i < p_input->stream.i_pgrm_number; i++ )
355                 {
356                     pgrm_descriptor_t * p_pgrm
357                                             = p_input->stream.pp_programs[i];
358
359                     /* Reinitialize synchro. */
360                     p_pgrm->i_synchro_state = SYNCHRO_REINIT;
361                 }
362             }
363             p_input->stream.p_new_program = NULL;
364         }
365
366         if( p_input->stream.p_new_area )
367         {
368             if( p_input->stream.b_seekable && p_input->pf_set_area != NULL )
369             {
370                 input_AccessReinit( p_input );
371
372                 p_input->pf_set_area( p_input, p_input->stream.p_new_area );
373
374                 /* Escape all decoders for the stream discontinuity they
375                  * will encounter. */
376                 input_EscapeDiscontinuity( p_input );
377
378                 for( i = 0; i < p_input->stream.i_pgrm_number; i++ )
379                 {
380                     pgrm_descriptor_t * p_pgrm
381                                             = p_input->stream.pp_programs[i];
382
383                     /* Reinitialize synchro. */
384                     p_pgrm->i_synchro_state = SYNCHRO_REINIT;
385                 }
386             }
387             p_input->stream.p_new_area = NULL;
388         }
389
390         if( p_input->stream.p_selected_area->i_seek != NO_SEEK )
391         {
392             if( p_input->stream.p_selected_area->i_size > 0 )
393             {
394                 unsigned int i;
395                 mtime_t      i_time;
396                 double f = (double)p_input->stream.p_selected_area->i_seek /
397                            (double)p_input->stream.p_selected_area->i_size;
398
399                 vlc_mutex_unlock( &p_input->stream.stream_lock );
400                 demux_Control( p_input, DEMUX_SET_POSITION, f );
401                 vlc_mutex_lock( &p_input->stream.stream_lock );
402
403                 /* Escape all decoders for the stream discontinuity they
404                  * will encounter. */
405                 input_EscapeDiscontinuity( p_input );
406
407                 for( i = 0; i < p_input->stream.i_pgrm_number; i++ )
408                 {
409                     pgrm_descriptor_t * p_pgrm=p_input->stream.pp_programs[i];
410
411                     /* Reinitialize synchro. */
412                     p_pgrm->i_synchro_state = SYNCHRO_REINIT;
413                 }
414
415                 vlc_mutex_unlock( &p_input->stream.stream_lock );
416                 if( !demux_Control( p_input, DEMUX_GET_TIME, &i_time ) )
417                 {
418                     int i;
419                     vlc_value_t val;
420
421                     /* Help in bar display */
422                     val.i_time = i_time;
423                     var_Change( p_input, "time", VLC_VAR_SETVALUE, &val, NULL );
424
425                     /* Seek subs */
426                     for( i = 0; i < p_input->p_sys->i_sub; i++ )
427                     {
428                         subtitle_Seek( p_input->p_sys->sub[i], i_time );
429                     }
430                 }
431                 vlc_mutex_lock( &p_input->stream.stream_lock );
432             }
433             p_input->stream.p_selected_area->i_seek = NO_SEEK;
434         }
435
436         if( p_input->stream.p_removed_es )
437         {
438             input_UnselectES( p_input, p_input->stream.p_removed_es );
439             p_input->stream.p_removed_es = NULL;
440         }
441
442         if( p_input->stream.p_newly_selected_es )
443         {
444             input_SelectES( p_input, p_input->stream.p_newly_selected_es );
445             p_input->stream.p_newly_selected_es = NULL;
446         }
447
448         if( p_input->stream.b_new_mute != MUTE_NO_CHANGE )
449         {
450             if( p_input->stream.b_new_mute )
451             {
452                 input_EscapeAudioDiscontinuity( p_input );
453             }
454
455             vlc_mutex_lock( &p_input->stream.control.control_lock );
456             p_input->stream.control.b_mute = p_input->stream.b_new_mute;
457             vlc_mutex_unlock( &p_input->stream.control.control_lock );
458
459             p_input->stream.b_new_mute = MUTE_NO_CHANGE;
460         }
461
462         vlc_mutex_unlock( &p_input->stream.stream_lock );
463
464         /* Read and demultiplex some data. */
465         i_count = p_input->pf_demux( p_input );
466
467         if( i_count == 0 )
468         {
469             /* End of file - we do not set b_die because only the
470              * playlist is allowed to do so. */
471             msg_Info( p_input, "EOF reached" );
472             p_input->b_eof = 1;
473         }
474         else if( i_count < 0 )
475         {
476             p_input->b_error = 1;
477         }
478
479         if( !p_input->b_error && !p_input->b_eof && i_update_next < mdate() )
480         {
481             int i;
482             mtime_t i_time;
483             mtime_t i_length;
484             double  d_pos;
485
486             /* update input status variables */
487             if( !demux_Control( p_input, DEMUX_GET_POSITION, &d_pos ) )
488             {
489                 val.f_float = (float)d_pos;
490                 var_Change( p_input, "position", VLC_VAR_SETVALUE, &val, NULL );
491             }
492             if( !demux_Control( p_input, DEMUX_GET_TIME, &i_time ) )
493             {
494                 val.i_time = i_time;
495                 var_Change( p_input, "time", VLC_VAR_SETVALUE, &val, NULL );
496             }
497             if( !demux_Control( p_input, DEMUX_GET_LENGTH, &i_length ) )
498             {
499                 val.i_time = i_length;
500                 var_Change( p_input, "length", VLC_VAR_SETVALUE, &val, NULL );
501             }
502
503             /* update subs */
504             for( i = 0; i < p_input->p_sys->i_sub; i++ )
505             {
506                 subtitle_Demux( p_input->p_sys->sub[i], i_time );
507             }
508
509             i_update_next = mdate() + I64C(150000);
510         }
511     }
512
513     if( p_input->b_error || p_input->b_eof )
514     {
515         ErrorThread( p_input );
516     }
517
518     EndThread( p_input );
519
520     return 0;
521 }
522
523 /*****************************************************************************
524  * InitThread: init the input Thread
525  *****************************************************************************/
526 static int InitThread( input_thread_t * p_input )
527 {
528     vlc_meta_t *meta;
529     float f_fps;
530     playlist_t *p_playlist;
531     mtime_t i_length;
532
533     /* Parse source string. Syntax : [[<access>][/<demux>]:][<source>] */
534     char * psz_parser = p_input->psz_dupsource = strdup(p_input->psz_source);
535     vlc_value_t val;
536     int64_t i_microsecondperframe;
537
538     subtitle_demux_t *p_sub_toselect = NULL;
539     char             *psz_sub_file = NULL;
540
541     /* Skip the plug-in names */
542     while( *psz_parser && *psz_parser != ':' )
543     {
544         psz_parser++;
545     }
546 #if defined( WIN32 ) || defined( UNDER_CE )
547     if( psz_parser - p_input->psz_dupsource == 1 )
548     {
549         msg_Warn( p_input, "drive letter %c: found in source string",
550                            p_input->psz_dupsource[0] ) ;
551         psz_parser = "";
552     }
553 #endif
554
555     if( !*psz_parser )
556     {
557         p_input->psz_access = p_input->psz_demux = "";
558         p_input->psz_name = p_input->psz_source;
559         free( p_input->psz_dupsource );
560         p_input->psz_dupsource = NULL;
561     }
562     else
563     {
564         *psz_parser++ = '\0';
565
566         /* let's skip '//' */
567         if( psz_parser[0] == '/' && psz_parser[1] == '/' )
568         {
569             psz_parser += 2 ;
570         }
571
572         p_input->psz_name = psz_parser ;
573
574         /* Come back to parse the access and demux plug-ins */
575         psz_parser = p_input->psz_dupsource;
576
577         if( !*psz_parser )
578         {
579             /* No access */
580             p_input->psz_access = "";
581         }
582         else if( *psz_parser == '/' )
583         {
584             /* No access */
585             p_input->psz_access = "";
586             psz_parser++;
587         }
588         else
589         {
590             p_input->psz_access = psz_parser;
591
592             while( *psz_parser && *psz_parser != '/' )
593             {
594                 psz_parser++;
595             }
596
597             if( *psz_parser == '/' )
598             {
599                 *psz_parser++ = '\0';
600             }
601         }
602
603         if( !*psz_parser )
604         {
605             /* No demux */
606             p_input->psz_demux = "";
607         }
608         else
609         {
610             p_input->psz_demux = psz_parser;
611         }
612     }
613
614     msg_Dbg( p_input, "access `%s', demux `%s', name `%s'",
615              p_input->psz_access, p_input->psz_demux, p_input->psz_name );
616
617     if( input_AccessInit( p_input ) == -1 )
618     {
619         free( p_input->psz_source );
620         if( p_input->psz_dupsource != NULL )
621         {
622             free( p_input->psz_dupsource );
623         }
624
625         return VLC_EGENERIC;
626     }
627
628     /* Initialize optional stream output. (before demuxer)*/
629     var_Get( p_input, "sout", &val );
630     if( val.psz_string != NULL )
631     {
632         if ( *val.psz_string && (p_input->stream.p_sout =
633              sout_NewInstance( p_input, val.psz_string )) == NULL )
634         {
635             msg_Err( p_input, "cannot start stream output instance, aborting" );
636             free( val.psz_string );
637
638             input_AccessEnd( p_input );
639             free( p_input->psz_source );
640             if( p_input->psz_dupsource != NULL )
641             {
642                 free( p_input->psz_dupsource );
643             }
644             return VLC_EGENERIC;
645         }
646         free( val.psz_string );
647     }
648
649     p_input->p_es_out = input_EsOutNew( p_input );
650     es_out_Control( p_input->p_es_out, ES_OUT_SET_ACTIVE, VLC_FALSE );
651     es_out_Control( p_input->p_es_out, ES_OUT_SET_MODE, ES_OUT_MODE_NONE );
652
653     /* Find and open appropriate access module */
654     p_input->p_access = module_Need( p_input, "access",
655                                      p_input->psz_access );
656
657 #ifndef WIN32      /* Remove this gross hack from the win32 build as colons
658                     * are forbidden in filenames on Win32. */
659
660     /* Maybe we got something like: /Volumes/toto:titi/gabu.mpg */
661     if ( p_input->p_access == NULL
662           && (*p_input->psz_demux || *p_input->psz_access) )
663     {
664         p_input->psz_access = p_input->psz_demux = "";
665         p_input->psz_name = p_input->psz_source;
666         free( p_input->psz_dupsource);
667         p_input->psz_dupsource = NULL;
668
669         p_input->p_access = module_Need( p_input, "access",
670                                          p_input->psz_access );
671     }
672 #endif
673
674     if( p_input->p_access == NULL )
675     {
676         msg_Err( p_input, "no suitable access module for `%s/%s://%s'",
677                  p_input->psz_access, p_input->psz_demux, p_input->psz_name );
678         if ( p_input->stream.p_sout != NULL )
679         {
680             sout_DeleteInstance( p_input->stream.p_sout );
681         }
682
683         input_AccessEnd( p_input );
684         free( p_input->psz_source );
685         if( p_input->psz_dupsource != NULL )
686         {
687             free( p_input->psz_dupsource );
688         }
689         input_EsOutDelete( p_input->p_es_out );
690         return VLC_EGENERIC;
691     }
692
693     /* Waiting for stream. */
694     if( p_input->i_mtu )
695     {
696         p_input->i_bufsize = p_input->i_mtu;
697     }
698     else
699     {
700         p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE;
701     }
702
703     /* If the desynchronisation requested by the user is < 0, we need to
704      * cache more data. */
705     var_Create( p_input, "audio-desync", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
706     var_Get( p_input, "audio-desync", &val );
707     if( val.i_int < 0 )
708         p_input->i_pts_delay -= (val.i_int * 1000);
709
710     if( p_input->p_current_data == NULL && p_input->pf_read != NULL )
711     {
712         while( !input_FillBuffer( p_input ) )
713         {
714             if( p_input->b_die || p_input->b_error || p_input->b_eof )
715             {
716                 module_Unneed( p_input, p_input->p_access );
717                 if ( p_input->stream.p_sout != NULL )
718                 {
719                     sout_DeleteInstance( p_input->stream.p_sout );
720                 }
721                 input_AccessEnd( p_input );
722                 free( p_input->psz_source );
723                 if( p_input->psz_dupsource != NULL )
724                 {
725                     free( p_input->psz_dupsource );
726                 }
727                 input_EsOutDelete( p_input->p_es_out );
728                 return VLC_EGENERIC;
729             }
730         }
731     }
732
733     /* Create the stream_t facilities */
734     p_input->s = input_StreamNew( p_input );
735     if( p_input->s == NULL )
736     {
737         /* should never occur yet */
738
739         msg_Err( p_input, "cannot create stream_t" );
740
741         module_Unneed( p_input, p_input->p_access );
742         if ( p_input->stream.p_sout != NULL )
743         {
744             sout_DeleteInstance( p_input->stream.p_sout );
745         }
746         input_AccessEnd( p_input );
747         free( p_input->psz_source );
748         if( p_input->psz_dupsource != NULL )
749         {
750             free( p_input->psz_dupsource );
751         }
752         input_EsOutDelete( p_input->p_es_out );
753         return VLC_EGENERIC;
754     }
755
756     /* Find and open appropriate demux module */
757     p_input->p_demux =
758         module_Need( p_input, "demux",
759                      (p_input->psz_demux && *p_input->psz_demux) ?
760                      p_input->psz_demux : "$demux" );
761
762     if( p_input->p_demux == NULL )
763     {
764         msg_Err( p_input, "no suitable demux module for `%s/%s://%s'",
765                  p_input->psz_access, p_input->psz_demux, p_input->psz_name );
766
767         input_StreamDelete( p_input->s );
768         module_Unneed( p_input, p_input->p_access );
769         if ( p_input->stream.p_sout != NULL )
770         {
771             sout_DeleteInstance( p_input->stream.p_sout );
772         }
773         input_AccessEnd( p_input );
774         free( p_input->psz_source );
775         if( p_input->psz_dupsource != NULL )
776         {
777             free( p_input->psz_dupsource );
778         }
779         input_EsOutDelete( p_input->p_es_out );
780         return VLC_EGENERIC;
781     }
782
783     /* Init input_thread_sys_t */
784     p_input->p_sys = malloc( sizeof( input_thread_sys_t ) );
785     p_input->p_sys->i_sub = 0;
786     p_input->p_sys->sub   = NULL;
787
788     /* get meta informations */
789     if( !demux_Control( p_input, DEMUX_GET_META, &meta ) )
790     {
791         playlist_t *p_playlist = (playlist_t *)vlc_object_find( p_input,
792                                          VLC_OBJECT_PLAYLIST,  FIND_PARENT);
793         playlist_item_t *p_item = NULL;
794         input_info_category_t *p_cat;
795         int i;
796
797         if( p_playlist )
798         {
799             vlc_mutex_lock( &p_playlist->object_lock );
800             p_item = playlist_ItemGetByPos( p_playlist, -1 );
801             if( p_item )
802             {
803                 vlc_mutex_lock( &p_item->lock );
804             }
805             vlc_mutex_unlock( &p_playlist->object_lock );
806         }
807
808         msg_Dbg( p_input, "meta informations:" );
809         if( meta->i_meta > 0 )
810         {
811             p_cat = input_InfoCategory( p_input, _("File") );
812             for( i = 0; i < meta->i_meta; i++ )
813             {
814                 msg_Dbg( p_input, "  - '%s' = '%s'", _(meta->name[i]), meta->value[i] );
815                 input_AddInfo( p_cat, _(meta->name[i]), "%s", meta->value[i] );
816                 if( p_item )
817                 {
818                     playlist_ItemAddInfo( p_item, _("File"),
819                                           _(meta->name[i]), "%s", meta->value[i] );
820                 }
821             }
822         }
823         for( i = 0; i < meta->i_track; i++ )
824         {
825             vlc_meta_t *tk = meta->track[i];
826             int j;
827
828             msg_Dbg( p_input, "  - track[%d]:", i );
829             if( tk->i_meta > 0 )
830             {
831                 char *psz_cat = malloc( strlen(_("Stream")) + 10 );
832                 sprintf( psz_cat, "%s %d", _("Stream"), i );
833                 p_cat = input_InfoCategory( p_input, psz_cat );
834
835                 for( j = 0; j < tk->i_meta; j++ )
836                 {
837                     msg_Dbg( p_input, "     - '%s' = '%s'", _(tk->name[j]), tk->value[j] );
838                     input_AddInfo( p_cat, _(tk->name[j]), "%s", tk->value[j] );
839                     if( p_item )
840                     {
841                         playlist_ItemAddInfo( p_item, psz_cat,
842                                               _(tk->name[j]), "%s", tk->value[j] );
843                     }
844                 }
845             }
846         }
847
848         if( p_item )
849         {
850             vlc_mutex_unlock( &p_item->lock );
851         }
852         if( p_playlist ) vlc_object_release( p_playlist );
853
854         vlc_meta_Delete( meta );
855     }
856
857     /* get length */
858     if( !demux_Control( p_input, DEMUX_GET_LENGTH, &i_length ) && i_length > 0 )
859     {
860         p_playlist = (playlist_t*)vlc_object_find( p_input,
861                                                    VLC_OBJECT_PLAYLIST,
862                                                    FIND_PARENT );
863         if( p_playlist )
864         {
865             playlist_SetDuration( p_playlist, -1 , i_length );
866             val.b_bool = p_playlist->i_index;
867             var_Set( p_playlist, "item-change", val );
868             vlc_object_release( p_playlist );
869         }
870     }
871
872
873     /* get fps */
874     if( demux_Control( p_input, DEMUX_GET_FPS, &f_fps ) || f_fps < 0.1 )
875     {
876         i_microsecondperframe = 0;
877     }
878     else
879     {
880         i_microsecondperframe = (int64_t)( (double)1000000.0 / (double)f_fps );
881     }
882
883     /* Look for and add subtitle files */
884     var_Get( p_input, "sub-file", &val );
885     if( val.psz_string && *val.psz_string )
886     {
887         subtitle_demux_t *p_sub;
888
889         msg_Dbg( p_input, "force subtitle: %s", val.psz_string );
890         if( ( p_sub = subtitle_New( p_input, strdup(val.psz_string),
891                                     i_microsecondperframe ) ) )
892         {
893             p_sub_toselect = p_sub;
894             TAB_APPEND( p_input->p_sys->i_sub, p_input->p_sys->sub, p_sub );
895         }
896     }
897     psz_sub_file = val.psz_string;
898
899     var_Get( p_input, "sub-autodetect-file", &val );
900     if( val.b_bool )
901     {
902         subtitle_demux_t *p_sub;
903         int i;
904         char **tmp = subtitles_Detect( p_input, "", p_input->psz_name );
905         char **tmp2 = tmp;
906         for( i = 0; *tmp2 != NULL; i++ )
907         {
908             if( psz_sub_file == NULL || strcmp( psz_sub_file, *tmp2 ) )
909             {
910                 if( ( p_sub = subtitle_New( p_input, *tmp2,
911                                             i_microsecondperframe ) ) )
912                 {
913                     TAB_APPEND( p_input->p_sys->i_sub, p_input->p_sys->sub, p_sub );
914                 }
915             }
916             free( *tmp2++ );
917         }
918         free( tmp );
919     }
920     if( psz_sub_file ) free( psz_sub_file );
921
922     es_out_Control( p_input->p_es_out, ES_OUT_SET_ACTIVE, VLC_TRUE );
923     val.b_bool =  VLC_FALSE;
924     if( p_input->stream.p_sout )
925     {
926         var_Get( p_input, "sout-all", &val );
927     }
928     es_out_Control( p_input->p_es_out, ES_OUT_SET_MODE,
929                     val.b_bool ? ES_OUT_MODE_ALL : ES_OUT_MODE_AUTO );
930     if( p_sub_toselect )
931     {
932         es_out_Control( p_input->p_es_out, ES_OUT_SET_ES,
933                         p_sub_toselect->p_es, VLC_TRUE );
934     }
935
936     return VLC_SUCCESS;
937 }
938
939 /*****************************************************************************
940  * ErrorThread: RunThread() error loop
941  *****************************************************************************
942  * This function is called when an error occured during thread main's loop.
943  *****************************************************************************/
944 static void ErrorThread( input_thread_t *p_input )
945 {
946     while( !p_input->b_die )
947     {
948         /* Sleep a while */
949         msleep( INPUT_IDLE_SLEEP );
950     }
951 }
952
953 /*****************************************************************************
954  * EndThread: end the input thread
955  *****************************************************************************/
956 static void EndThread( input_thread_t * p_input )
957 {
958     int i;
959 #ifdef HAVE_SYS_TIMES_H
960     /* Display statistics */
961     struct tms  cpu_usage;
962     times( &cpu_usage );
963
964     msg_Dbg( p_input, "%ld loops consuming user: %ld, system: %ld",
965              p_input->c_loops, cpu_usage.tms_utime, cpu_usage.tms_stime );
966 #else
967     msg_Dbg( p_input, "%ld loops", p_input->c_loops );
968 #endif
969
970     input_DumpStream( p_input );
971
972     /* Free demultiplexer's data */
973     if( p_input->p_demux ) module_Unneed( p_input, p_input->p_demux );
974
975     /* Free all ES and destroy all decoder threads */
976     input_EndStream( p_input );
977
978     /* Close optional stream output instance */
979     if( p_input->stream.p_sout )
980     {
981         vlc_object_t *p_pl =
982             vlc_object_find( p_input, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
983         vlc_value_t keep;
984
985         if( var_Get( p_input, "sout-keep", &keep ) >= 0 && keep.b_bool && p_pl )
986         {
987             /* attach sout to the playlist */
988             msg_Warn( p_input, "keeping sout" );
989             vlc_object_detach( p_input->stream.p_sout );
990             vlc_object_attach( p_input->stream.p_sout, p_pl );
991         }
992         else
993         {
994             msg_Warn( p_input, "destroying sout" );
995             sout_DeleteInstance( p_input->stream.p_sout );
996         }
997         if( p_pl )
998         {
999             vlc_object_release( p_pl );
1000         }
1001     }
1002
1003     /* Destroy subtitles demuxers */
1004     if( p_input->p_sys )
1005     {
1006         for( i = 0; i < p_input->p_sys->i_sub; i++ )
1007         {
1008             subtitle_Close( p_input->p_sys->sub[i] );
1009         }
1010         if( p_input->p_sys->i_sub > 0 )
1011         {
1012             free( p_input->p_sys->sub );
1013         }
1014
1015         /* Free input_thread_sys_t */
1016         free( p_input->p_sys );
1017     }
1018
1019     /* Destroy the stream_t facilities */
1020     if( p_input->s ) input_StreamDelete( p_input->s );
1021
1022     /* Destroy es out */
1023     if( p_input->p_es_out ) input_EsOutDelete( p_input->p_es_out );
1024
1025     /* Close the access plug-in */
1026     if( p_input->p_access ) module_Unneed( p_input, p_input->p_access );
1027
1028     input_AccessEnd( p_input );
1029
1030     /* Free info structures XXX destroy es before 'cause vorbis */
1031     msg_Dbg( p_input, "freeing info structures...");
1032     input_DelInfo( p_input );
1033
1034     free( p_input->psz_source );
1035     if( p_input->psz_dupsource != NULL ) free( p_input->psz_dupsource );
1036
1037     /* Tell we're dead */
1038     p_input->b_dead = 1;
1039 }
1040
1041 /*****************************************************************************
1042  * ParseOption: parses the options for the input
1043  *****************************************************************************
1044  * This function parses the input (config) options and creates their associated
1045  * object variables.
1046  * Options are of the form "[no[-]]foo[=bar]" where foo is the option name and
1047  * bar is the value of the option.
1048  *****************************************************************************/
1049 static void ParseOption( input_thread_t *p_input, const char *psz_option )
1050 {
1051     char *psz_name = (char *)psz_option;
1052     char *psz_value = strchr( psz_option, '=' );
1053     int  i_name_len, i_type;
1054     vlc_bool_t b_isno = VLC_FALSE;
1055     vlc_value_t val;
1056
1057     if( psz_value ) i_name_len = psz_value - psz_option;
1058     else i_name_len = strlen( psz_option );
1059
1060     /* It's too much of an hassle to remove the ':' when we parse
1061      * the cmd line :) */
1062     if( i_name_len && *psz_name == ':' )
1063     {
1064         psz_name++;
1065         i_name_len--;
1066     }
1067
1068     if( i_name_len == 0 ) return;
1069
1070     psz_name = strndup( psz_name, i_name_len );
1071     if( psz_value ) psz_value++;
1072
1073     i_type = config_GetType( p_input, psz_name );
1074
1075     if( !i_type && !psz_value )
1076     {
1077         /* check for "no-foo" or "nofoo" */
1078         if( !strncmp( psz_name, "no-", 3 ) )
1079         {
1080             memmove( psz_name, psz_name + 3, strlen(psz_name) + 1 - 3 );
1081         }
1082         else if( !strncmp( psz_name, "no", 2 ) )
1083         {
1084             memmove( psz_name, psz_name + 2, strlen(psz_name) + 1 - 2 );
1085         }
1086         else goto cleanup;           /* Option doesn't exist */
1087
1088         b_isno = VLC_TRUE;
1089         i_type = config_GetType( p_input, psz_name );
1090
1091         if( !i_type ) goto cleanup;  /* Option doesn't exist */
1092     }
1093     else if( !i_type ) goto cleanup; /* Option doesn't exist */
1094
1095     if( ( i_type != VLC_VAR_BOOL ) &&
1096         ( !psz_value || !*psz_value ) ) goto cleanup; /* Invalid value */
1097
1098     /* Create the variable in the input object.
1099      * Children of the input object will be able to retreive this value
1100      * thanks to the inheritance property of the object variables. */
1101     var_Create( p_input, psz_name, i_type );
1102
1103     switch( i_type )
1104     {
1105     case VLC_VAR_BOOL:
1106         val.b_bool = !b_isno;
1107         break;
1108
1109     case VLC_VAR_INTEGER:
1110         val.i_int = atoi( psz_value );
1111         break;
1112
1113     case VLC_VAR_FLOAT:
1114         val.f_float = atof( psz_value );
1115         break;
1116
1117     case VLC_VAR_STRING:
1118     case VLC_VAR_MODULE:
1119     case VLC_VAR_FILE:
1120     case VLC_VAR_DIRECTORY:
1121         val.psz_string = psz_value;
1122         break;
1123
1124     default:
1125         goto cleanup;
1126         break;
1127     }
1128
1129     var_Set( p_input, psz_name, val );
1130
1131     msg_Dbg( p_input, "set input option: %s to %s", psz_name, psz_value );
1132
1133   cleanup:
1134     if( psz_name ) free( psz_name );
1135     return;
1136 }
1137
1138 /*****************************************************************************
1139  * Callbacks  (position, time, state, rate )
1140  *****************************************************************************/
1141 static int PositionCallback( vlc_object_t *p_this, char const *psz_cmd,
1142                              vlc_value_t oldval, vlc_value_t newval,
1143                              void *p_data )
1144 {
1145     input_thread_t *p_input = (input_thread_t *)p_this;
1146
1147     msg_Dbg( p_input, "cmd=%s old=%f new=%f", psz_cmd,
1148              oldval.f_float, newval.f_float );
1149
1150     if( !strcmp( psz_cmd, "position-offset" ) )
1151     {
1152         vlc_value_t val;
1153         var_Get( p_input, "position", &val );
1154
1155         newval.f_float += val.f_float;
1156     }
1157
1158     vlc_mutex_lock( &p_input->stream.stream_lock );
1159     p_input->stream.p_selected_area->i_seek =
1160         (int64_t)( newval.f_float *
1161                    (double)p_input->stream.p_selected_area->i_size );
1162
1163     if( p_input->stream.p_selected_area->i_seek < 0 )
1164     {
1165         p_input->stream.p_selected_area->i_seek = 0;
1166     }
1167     vlc_mutex_unlock( &p_input->stream.stream_lock );
1168
1169     return VLC_SUCCESS;
1170 }
1171
1172 static int TimeCallback( vlc_object_t *p_this, char const *psz_cmd,
1173                          vlc_value_t oldval, vlc_value_t newval, void *p_data )
1174 {
1175     input_thread_t *p_input = (input_thread_t *)p_this;
1176     vlc_value_t     val;
1177
1178     /* FIXME TODO FIXME */
1179     msg_Dbg( p_input, "cmd=%s old=%lld new=%lld", psz_cmd,
1180              oldval.i_time, newval.i_time );
1181
1182     var_Get( p_input, "length", &val );
1183     if( val.i_time > 0 )
1184     {
1185         val.f_float = (double)newval.i_time / (double)val.i_time;
1186         if( !strcmp( psz_cmd, "time-offset" ) )
1187         {
1188             var_Set( p_input, "position-offset", val );
1189         }
1190         else
1191         {
1192             var_Set( p_input, "position", val );
1193         }
1194     }
1195     else
1196     {
1197         msg_Warn( p_input, "TimeCallback: length <= 0 -> can't seek" );
1198     }
1199     return VLC_SUCCESS;
1200 }
1201
1202 static int StateCallback( vlc_object_t *p_this, char const *psz_cmd,
1203                           vlc_value_t oldval, vlc_value_t newval,
1204                           void *p_data )
1205 {
1206     input_thread_t *p_input = (input_thread_t *)p_this;
1207
1208     msg_Dbg( p_input, "cmd=%s old=%d new=%d",
1209              psz_cmd, oldval.i_int, newval.i_int );
1210
1211     switch( newval.i_int )
1212     {
1213         case PLAYING_S:
1214             input_SetStatus( p_input, INPUT_STATUS_PLAY );
1215             return VLC_SUCCESS;
1216         case PAUSE_S:
1217             input_SetStatus( p_input, INPUT_STATUS_PAUSE );
1218             return VLC_SUCCESS;
1219         case END_S:
1220             input_SetStatus( p_input, INPUT_STATUS_END );
1221             return VLC_SUCCESS;
1222         default:
1223             msg_Err( p_input, "cannot set new state (invalid)" );
1224             return VLC_EGENERIC;
1225     }
1226 }
1227
1228 static int RateCallback( vlc_object_t *p_this, char const *psz_cmd,
1229                          vlc_value_t oldval, vlc_value_t newval, void *p_data )
1230 {
1231     input_thread_t *p_input = (input_thread_t *)p_this;
1232
1233     if( !strcmp( psz_cmd, "rate-slower" ) )
1234     {
1235         input_SetStatus( p_input, INPUT_STATUS_SLOWER );
1236     }
1237     else if( !strcmp( psz_cmd, "rate-faster" ) )
1238     {
1239         input_SetStatus( p_input, INPUT_STATUS_FASTER );
1240     }
1241     else
1242     {
1243         msg_Dbg( p_input, "cmd=%s old=%d new=%d",
1244                  psz_cmd, oldval.i_int, newval.i_int );
1245         input_SetRate( p_input, newval.i_int );
1246     }
1247     return VLC_SUCCESS;
1248 }