]> git.sesse.net Git - vlc/blob - src/input/input.c
Allow on the fly change of equalizer config. Only restart aout when enabling/disablin...
[vlc] / src / input / input.c
1 /*****************************************************************************
2  * input.c: input thread
3  *****************************************************************************
4  * Copyright (C) 1998-2004 VideoLAN
5  * $Id$
6  *
7  * Authors: Christophe Massiot <massiot@via.ecp.fr>
8  *          Laurent Aimar <fenrir@via.ecp.fr>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
23  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28 #include <stdlib.h>
29
30 #include <vlc/vlc.h>
31 #include <vlc/input.h>
32 #include <vlc/decoder.h>
33 #include <vlc/vout.h>
34
35 #include "input_internal.h"
36
37 #include "stream_output.h"
38
39 #include "vlc_interface.h"
40 #include "vlc_meta.h"
41
42 /*****************************************************************************
43  * Local prototypes
44  *****************************************************************************/
45 static  int Run  ( input_thread_t *p_input );
46
47 static  int Init ( input_thread_t *p_input );
48 static void Error( input_thread_t *p_input );
49 static void End  ( input_thread_t *p_input );
50
51 static inline int ControlPopNoLock( input_thread_t *, int *, vlc_value_t * );
52 static void       ControlReduce( input_thread_t * );
53 static vlc_bool_t Control( input_thread_t *, int, vlc_value_t );
54
55
56 static void UpdateFromAccess( input_thread_t * );
57 static void UpdateFromDemux( input_thread_t * );
58
59 static void ParseOption( input_thread_t *p_input, const char *psz_option );
60
61 static void DecodeUrl  ( char * );
62 static void MRLSplit( input_thread_t *, char *, char **, char **, char ** );
63
64 static input_source_t *InputSourceNew( input_thread_t *);
65 static int  InputSourceInit( input_thread_t *, input_source_t *,
66                              char *, char *psz_forced_demux );
67 static void InputSourceClean( input_thread_t *, input_source_t * );
68
69 static void SlaveDemux( input_thread_t *p_input );
70 static void SlaveSeek( input_thread_t *p_input );
71
72 static vlc_meta_t *InputMetaUser( input_thread_t *p_input );
73
74 /*****************************************************************************
75  * input_CreateThread: creates a new input thread
76  *****************************************************************************
77  * This function creates a new input, and returns a pointer
78  * to its description. On error, it returns NULL.
79  *
80  * Variables for _public_ use:
81  * * Get and Set:
82  *  - state
83  *  - rate,rate-slower, rate-faster
84  *  - position, position-offset
85  *  - time, time-offset
86  *  - title,title-next,title-prev
87  *  - chapter,chapter-next, chapter-prev
88  *  - program, audio-es, video-es, spu-es
89  *  - audio-delay, spu-delay
90  *  - bookmark
91  * * Get only:
92  *  - length
93  *  - bookmarks
94  *  - seekable (if you can seek, it doesn't say if 'bar display' has be shown or not, for that check position != 0.0)
95  * * For intf callback upon changes
96  *  - intf-change
97  * TODO explain when Callback is called
98  * TODO complete this list (?)
99  *****************************************************************************/
100 input_thread_t *__input_CreateThread( vlc_object_t *p_parent,
101                                       input_item_t *p_item )
102
103 {
104     input_thread_t *p_input;                        /* thread descriptor */
105     int             i;
106
107     /* Allocate descriptor */
108     p_input = vlc_object_create( p_parent, VLC_OBJECT_INPUT );
109     if( p_input == NULL )
110     {
111         msg_Err( p_parent, "out of memory" );
112         return NULL;
113     }
114
115     /* Init Common fields */
116     p_input->b_eof = VLC_FALSE;
117     p_input->b_can_pace_control = VLC_TRUE;
118     p_input->i_start = 0;
119     p_input->i_time  = 0;
120     p_input->i_stop  = 0;
121     p_input->i_title = 0;
122     p_input->title   = NULL;
123     p_input->i_state = INIT_S;
124     p_input->i_rate  = INPUT_RATE_DEFAULT;
125     p_input->i_bookmark = 0;
126     p_input->bookmark = NULL;
127     p_input->p_es_out = NULL;
128     p_input->p_sout  = NULL;
129     p_input->b_out_pace_control = VLC_FALSE;
130     p_input->i_pts_delay = 0;
131
132
133     /* Init Input fields */
134     p_input->input.p_item = p_item;
135     p_input->input.p_access = NULL;
136     p_input->input.p_stream = NULL;
137     p_input->input.p_demux  = NULL;
138     p_input->input.b_title_demux = VLC_FALSE;
139     p_input->input.i_title  = 0;
140     p_input->input.title    = NULL;
141     p_input->input.b_can_pace_control = VLC_TRUE;
142     p_input->input.b_eof = VLC_FALSE;
143     p_input->input.i_cr_average = 0;
144
145     /* No slave */
146     p_input->i_slave = 0;
147     p_input->slave   = NULL;
148
149     /* Init control buffer */
150     vlc_mutex_init( p_input, &p_input->lock_control );
151     p_input->i_control = 0;
152
153     /* Parse input options */
154     vlc_mutex_lock( &p_item->lock );
155     for( i = 0; i < p_item->i_options; i++ )
156     {
157         msg_Dbg( p_input, "option: %s", p_item->ppsz_options[i] );
158         ParseOption( p_input, p_item->ppsz_options[i] );
159     }
160     vlc_mutex_unlock( &p_item->lock );
161
162     /* Create Object Variables for private use only */
163     input_ConfigVarInit( p_input );
164
165     /* Create Objects variables for public Get and Set */
166     input_ControlVarInit( p_input );
167     p_input->input.i_cr_average = var_GetInteger( p_input, "cr-average" );
168
169 #if 0
170     /* TODO */
171     var_Get( p_input, "bookmarks", &val );
172     if( val.psz_string )
173     {
174         /* FIXME: have a common cfg parsing routine used by sout and others */
175         char *psz_parser, *psz_start, *psz_end;
176         psz_parser = val.psz_string;
177         while( (psz_start = strchr( psz_parser, '{' ) ) )
178         {
179             seekpoint_t seekpoint;
180             char backup;
181             psz_start++;
182             psz_end = strchr( psz_start, '}' );
183             if( !psz_end ) break;
184             psz_parser = psz_end + 1;
185             backup = *psz_parser;
186             *psz_parser = 0;
187             *psz_end = ',';
188
189             seekpoint.psz_name = 0;
190             seekpoint.i_byte_offset = 0;
191             seekpoint.i_time_offset = 0;
192             while( (psz_end = strchr( psz_start, ',' ) ) )
193             {
194                 *psz_end = 0;
195                 if( !strncmp( psz_start, "name=", 5 ) )
196                 {
197                     seekpoint.psz_name = psz_start + 5;
198                 }
199                 else if( !strncmp( psz_start, "bytes=", 6 ) )
200                 {
201                     seekpoint.i_byte_offset = atoll(psz_start + 6);
202                 }
203                 else if( !strncmp( psz_start, "time=", 5 ) )
204                 {
205                     seekpoint.i_time_offset = atoll(psz_start + 5) * 1000000;
206                 }
207                 psz_start = psz_end + 1;
208             }
209             msg_Dbg( p_input, "adding bookmark: %s, bytes="I64Fd", time="I64Fd,
210                      seekpoint.psz_name, seekpoint.i_byte_offset,
211                      seekpoint.i_time_offset );
212             input_Control( p_input, INPUT_ADD_BOOKMARK, &seekpoint );
213             *psz_parser = backup;
214         }
215         free( val.psz_string );
216     }
217 #endif
218
219     /* Now we can attach our new input */
220     vlc_object_attach( p_input, p_parent );
221
222     /* Create thread and wait for its readiness. */
223     if( vlc_thread_create( p_input, "input", Run,
224                            VLC_THREAD_PRIORITY_INPUT, VLC_TRUE ) )
225     {
226         msg_Err( p_input, "cannot create input thread" );
227         vlc_object_detach( p_input );
228         vlc_object_destroy( p_input );
229         return NULL;
230     }
231
232     return p_input;
233 }
234
235 /*****************************************************************************
236  * input_StopThread: mark an input thread as zombie
237  *****************************************************************************
238  * This function should not return until the thread is effectively cancelled.
239  *****************************************************************************/
240 void input_StopThread( input_thread_t *p_input )
241 {
242     vlc_list_t *p_list;
243     int i;
244
245     /* Set die for input */
246     p_input->b_die = VLC_TRUE;
247
248     /* We cannot touch p_input fields directly (we can from another thread),
249      * so use the vlc_object_find way, it's perfectly safe */
250
251     /* Set die for all access */
252     p_list = vlc_list_find( p_input, VLC_OBJECT_ACCESS, FIND_CHILD );
253     for( i = 0; i < p_list->i_count; i++ )
254     {
255         p_list->p_values[i].p_object->b_die = VLC_TRUE;
256     }
257     vlc_list_release( p_list );
258
259     /* Set die for all stream */
260     p_list = vlc_list_find( p_input, VLC_OBJECT_STREAM, FIND_CHILD );
261     for( i = 0; i < p_list->i_count; i++ )
262     {
263         p_list->p_values[i].p_object->b_die = VLC_TRUE;
264     }
265     vlc_list_release( p_list );
266
267     /* Set die for all demux */
268     p_list = vlc_list_find( p_input, VLC_OBJECT_DEMUX, FIND_CHILD );
269     for( i = 0; i < p_list->i_count; i++ )
270     {
271         p_list->p_values[i].p_object->b_die = VLC_TRUE;
272     }
273     vlc_list_release( p_list );
274
275     input_ControlPush( p_input, INPUT_CONTROL_SET_DIE, NULL );
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     /* Delete input lock (only after thread joined) */
289     vlc_mutex_destroy( &p_input->lock_control );
290
291     /* TODO: maybe input_DestroyThread should also delete p_input instead
292      * of the playlist but I'm not sure if it's possible */
293 }
294
295 /*****************************************************************************
296  * Run: main thread loop
297  *****************************************************************************
298  * Thread in charge of processing the network packets and demultiplexing.
299  *
300  * TODO:
301  *  read subtitle support (XXX take care of spu-delay in the right way).
302  *  multi-input support (XXX may be done with subs)
303  *****************************************************************************/
304 static int Run( input_thread_t *p_input )
305 {
306     int64_t i_intf_update = 0;
307
308     /* Signal that the thread is launched */
309     vlc_thread_ready( p_input );
310
311     if( Init( p_input ) )
312     {
313         /* If we failed, wait before we are killed, and exit */
314         p_input->b_error = VLC_TRUE;
315
316         Error( p_input );
317
318         /* Tell we're dead */
319         p_input->b_dead = VLC_TRUE;
320
321         return 0;
322     }
323
324     /* Main loop */
325     while( !p_input->b_die && !p_input->b_error && !p_input->input.b_eof )
326     {
327         vlc_bool_t b_force_update = VLC_FALSE;
328         int i_ret;
329         int i_type;
330         vlc_value_t val;
331
332         /* Do the read */
333         if( p_input->i_state != PAUSE_S  )
334         {
335             if( p_input->i_stop <= 0 || p_input->i_time < p_input->i_stop )
336                 i_ret=p_input->input.p_demux->pf_demux(p_input->input.p_demux);
337             else
338                 i_ret = 0;  /* EOF */
339
340             if( i_ret > 0 )
341             {
342                 /* TODO */
343                 if( p_input->input.b_title_demux &&
344                     p_input->input.p_demux->info.i_update )
345                 {
346                     UpdateFromDemux( p_input );
347                     b_force_update = VLC_TRUE;
348                 }
349                 else if( !p_input->input.b_title_demux &&
350                           p_input->input.p_access &&
351                           p_input->input.p_access->info.i_update )
352                 {
353                     UpdateFromAccess( p_input );
354                     b_force_update = VLC_TRUE;
355                 }
356             }
357             else if( i_ret == 0 )    /* EOF */
358             {
359                 vlc_value_t repeat;
360
361                 var_Get( p_input, "input-repeat", &repeat );
362                 if( repeat.i_int == 0 )
363                 {
364                     /* End of file - we do not set b_die because only the
365                      * playlist is allowed to do so. */
366                     msg_Dbg( p_input, "EOF reached" );
367                     p_input->input.b_eof = VLC_TRUE;
368                 }
369                 else
370                 {
371                     msg_Dbg( p_input, "repeating the same input (%d)",
372                              repeat.i_int );
373                     if( repeat.i_int > 0 )
374                     {
375                         repeat.i_int--;
376                         var_Set( p_input, "input-repeat", repeat );
377                     }
378
379                     /* Seek to title 0 position 0(start) */
380                     val.i_int = 0;
381                     input_ControlPush( p_input, INPUT_CONTROL_SET_TITLE, &val );
382                     if( p_input->i_start > 0 )
383                     {
384                         val.i_time = p_input->i_start;
385                         input_ControlPush( p_input, INPUT_CONTROL_SET_TIME,
386                                            &val );
387                     }
388                     else
389                     {
390                         val.f_float = 0.0;
391                         input_ControlPush( p_input, INPUT_CONTROL_SET_POSITION,
392                                            &val );
393                     }
394                 }
395             }
396             else if( i_ret < 0 )
397             {
398                 p_input->b_error = VLC_TRUE;
399             }
400
401             if( i_ret > 0 && p_input->i_slave > 0 )
402             {
403                 SlaveDemux( p_input );
404             }
405         }
406         else
407         {
408             /* Small wait */
409             msleep( 10*1000 );
410         }
411
412         /* Handle control */
413         vlc_mutex_lock( &p_input->lock_control );
414         ControlReduce( p_input );
415         while( !ControlPopNoLock( p_input, &i_type, &val ) )
416         {
417             msg_Dbg( p_input, "control type=%d", i_type );
418             if( Control( p_input, i_type, val ) )
419                 b_force_update = VLC_TRUE;
420         }
421         vlc_mutex_unlock( &p_input->lock_control );
422
423         if( b_force_update ||
424             i_intf_update < mdate() )
425         {
426             vlc_value_t val;
427             double f_pos;
428             int64_t i_time, i_length;
429             /* update input status variables */
430             if( !demux2_Control( p_input->input.p_demux,
431                                  DEMUX_GET_POSITION, &f_pos ) )
432             {
433                 val.f_float = (float)f_pos;
434                 var_Change( p_input, "position", VLC_VAR_SETVALUE, &val, NULL );
435             }
436             if( !demux2_Control( p_input->input.p_demux,
437                                  DEMUX_GET_TIME, &i_time ) )
438             {
439                 p_input->i_time = i_time;
440                 val.i_time = i_time;
441                 var_Change( p_input, "time", VLC_VAR_SETVALUE, &val, NULL );
442             }
443             if( !demux2_Control( p_input->input.p_demux,
444                                  DEMUX_GET_LENGTH, &i_length ) )
445             {
446                 vlc_value_t old_val;
447                 var_Get( p_input, "length", &old_val );
448                 val.i_time = i_length;
449                 var_Change( p_input, "length", VLC_VAR_SETVALUE, &val, NULL );
450
451                 if( old_val.i_time != val.i_time )
452                 {
453                     char psz_buffer[MSTRTIME_MAX_SIZE];
454
455                     vlc_mutex_lock( &p_input->input.p_item->lock );
456                     p_input->input.p_item->i_duration = i_length;
457                     vlc_mutex_unlock( &p_input->input.p_item->lock );
458
459                     input_Control( p_input, INPUT_ADD_INFO,
460                                    _("General"), _("Duration"),
461                     msecstotimestr( psz_buffer, i_length / 1000 ) );
462                 }
463             }
464
465             var_SetBool( p_input, "intf-change", VLC_TRUE );
466             i_intf_update = mdate() + I64C(150000);
467         }
468     }
469
470     if( !p_input->b_eof && !p_input->b_error && p_input->input.b_eof )
471     {
472         /* We have finish to demux data but not to play them */
473         while( !p_input->b_die )
474         {
475             if( input_EsOutDecodersEmpty( p_input->p_es_out ) )
476                 break;
477
478             msg_Dbg( p_input, "waiting decoder fifos to empty" );
479
480             msleep( INPUT_IDLE_SLEEP );
481         }
482
483         /* We have finished */
484         p_input->b_eof = VLC_TRUE;
485     }
486
487     /* Wait we are asked to die */
488     if( !p_input->b_die )
489     {
490         Error( p_input );
491     }
492
493     /* Clean up */
494     End( p_input );
495
496     return 0;
497 }
498
499 /*****************************************************************************
500  * Init: init the input Thread
501  *****************************************************************************/
502 static int Init( input_thread_t * p_input )
503 {
504     char *psz;
505     char *psz_subtitle;
506     vlc_value_t val;
507     double f_fps;
508     vlc_meta_t *p_meta, *p_meta_user;
509     int i;
510
511     /* Initialize optional stream output. (before access/demuxer) */
512     psz = var_GetString( p_input, "sout" );
513     if( *psz )
514     {
515         p_input->p_sout = sout_NewInstance( p_input, psz );
516         if( p_input->p_sout == NULL )
517         {
518             msg_Err( p_input, "cannot start stream output instance, aborting" );
519             free( psz );
520             return VLC_EGENERIC;
521         }
522     }
523     free( psz );
524
525     /* Create es out */
526     p_input->p_es_out = input_EsOutNew( p_input );
527     es_out_Control( p_input->p_es_out, ES_OUT_SET_ACTIVE, VLC_FALSE );
528     es_out_Control( p_input->p_es_out, ES_OUT_SET_MODE, ES_OUT_MODE_NONE );
529
530     if( InputSourceInit( p_input, &p_input->input,
531                          p_input->input.p_item->psz_uri, NULL ) )
532     {
533         goto error;
534     }
535
536     /* Create global title (from master) */
537     p_input->i_title = p_input->input.i_title;
538     p_input->title   = p_input->input.title;
539     if( p_input->i_title > 0 )
540     {
541         /* Setup variables */
542         input_ControlVarNavigation( p_input );
543         input_ControlVarTitle( p_input, 0 );
544     }
545
546     /* Global flag */
547     p_input->b_can_pace_control = p_input->input.b_can_pace_control;
548     p_input->b_can_pause        = p_input->input.b_can_pause;
549
550     /* Fix pts delay */
551     if( p_input->i_pts_delay <= 0 )
552         p_input->i_pts_delay = DEFAULT_PTS_DELAY;
553
554     /* If the desynchronisation requested by the user is < 0, we need to
555      * cache more data. */
556     var_Get( p_input, "audio-desync", &val );
557     if( val.i_int < 0 )
558         p_input->i_pts_delay -= (val.i_int * 1000);
559
560     /* Load master infos */
561     /* Init length */
562     if( !demux2_Control( p_input->input.p_demux, DEMUX_GET_LENGTH,
563                          &val.i_time ) && val.i_time > 0 )
564     {
565         var_Change( p_input, "length", VLC_VAR_SETVALUE, &val, NULL );
566         /* TODO update playlist meta data */
567     }
568     /* Start time*/
569     /* Set start time */
570     p_input->i_start = (int64_t)var_GetInteger( p_input, "start-time" ) *
571                        I64C(1000000);
572     p_input->i_stop  = (int64_t)var_GetInteger( p_input, "stop-time" ) *
573                        I64C(1000000);
574
575     if( p_input->i_start > 0 )
576     {
577         if( p_input->i_start >= val.i_time )
578         {
579             msg_Warn( p_input, "invalid start-time ignored" );
580         }
581         else
582         {
583             vlc_value_t s;
584
585             msg_Dbg( p_input, "start-time: %ds",
586                      (int)( p_input->i_start / I64C(1000000) ) );
587
588             s.i_time = p_input->i_start;
589             input_ControlPush( p_input, INPUT_CONTROL_SET_TIME, &s );
590         }
591     }
592     if( p_input->i_stop > 0 && p_input->i_stop <= p_input->i_start )
593     {
594         msg_Warn( p_input, "invalid stop-time ignored" );
595         p_input->i_stop = 0;
596     }
597
598
599     /* Load subtitles */
600     /* Get fps and set it if not already set */
601     if( !demux2_Control( p_input->input.p_demux, DEMUX_GET_FPS, &f_fps ) &&
602         f_fps > 1.0 )
603     {
604         vlc_value_t fps;
605
606         if( var_Get( p_input, "sub-fps", &fps ) )
607         {
608             var_Create( p_input, "sub-fps", VLC_VAR_FLOAT| VLC_VAR_DOINHERIT );
609             var_SetFloat( p_input, "sub-fps", f_fps );
610         }
611     }
612
613     /* Look for and add subtitle files */
614     psz_subtitle = var_GetString( p_input, "sub-file" );
615     if( *psz_subtitle )
616     {
617         input_source_t *sub;
618         vlc_value_t count;
619         vlc_value_t list;
620
621         msg_Dbg( p_input, "forced subtitle: %s", psz_subtitle );
622
623         var_Change( p_input, "spu-es", VLC_VAR_CHOICESCOUNT, &count, NULL );
624
625         /* */
626         sub = InputSourceNew( p_input );
627         if( !InputSourceInit( p_input, sub, psz_subtitle, "subtitle" ) )
628         {
629             TAB_APPEND( p_input->i_slave, p_input->slave, sub );
630
631             /* Select the ES */
632             if( !var_Change( p_input, "spu-es", VLC_VAR_GETLIST, &list, NULL ) )
633             {
634                 if( count.i_int == 0 )
635                     count.i_int++;  /* if it was first one, there is disable too */
636
637                 if( count.i_int < list.p_list->i_count )
638                 {
639                     input_ControlPush( p_input, INPUT_CONTROL_SET_ES,
640                                        &list.p_list->p_values[count.i_int] );
641                 }
642                 var_Change( p_input, "spu-es", VLC_VAR_FREELIST, &list, NULL );
643             }
644         }
645     }
646
647     var_Get( p_input, "sub-autodetect-file", &val );
648     if( val.b_bool )
649     {
650         char *psz_autopath = var_GetString( p_input, "sub-autodetect-path" );
651         char **subs = subtitles_Detect( p_input, psz_autopath,
652                                         p_input->input.p_item->psz_uri );
653         input_source_t *sub;
654
655         for( i = 0; subs[i] != NULL; i++ )
656         {
657             if( strcmp( psz_subtitle, subs[i] ) )
658             {
659                 sub = InputSourceNew( p_input );
660                 if( !InputSourceInit( p_input, sub, subs[i], "subtitle" ) )
661                 {
662                     TAB_APPEND( p_input->i_slave, p_input->slave, sub );
663                 }
664             }
665             free( subs[i] );
666         }
667         free( subs );
668         free( psz_autopath );
669     }
670     free( psz_subtitle );
671
672     /* Look for slave */
673     psz = var_GetString( p_input, "input-slave" );
674     if( *psz )
675     {
676         char *psz_delim = strchr( psz, '#' );
677
678         for( ;; )
679         {
680             input_source_t *slave;
681
682             if( psz_delim )
683             {
684                 *psz_delim++ = '\0';
685             }
686
687             if( *psz == '\0' )
688             {
689                 if( psz_delim )
690                     continue;
691                 else
692                     break;
693             }
694
695             msg_Dbg( p_input, "adding slave '%s'", psz );
696             slave = InputSourceNew( p_input );
697             if( !InputSourceInit( p_input, slave, psz, NULL ) )
698             {
699                 TAB_APPEND( p_input->i_slave, p_input->slave, slave );
700             }
701             if( !psz_delim )
702                 break;
703         }
704     }
705     free( psz );
706
707     /* Set up es_out */
708     es_out_Control( p_input->p_es_out, ES_OUT_SET_ACTIVE, VLC_TRUE );
709     val.b_bool =  VLC_FALSE;
710     if( p_input->p_sout )
711     {
712         var_Get( p_input, "sout-all", &val );
713     }
714     es_out_Control( p_input->p_es_out, ES_OUT_SET_MODE,
715                     val.b_bool ? ES_OUT_MODE_ALL : ES_OUT_MODE_AUTO );
716
717     if( p_input->p_sout )
718     {
719         if( p_input->p_sout->i_out_pace_nocontrol > 0 )
720         {
721             p_input->b_out_pace_control = VLC_FALSE;
722         }
723         else
724         {
725             p_input->b_out_pace_control = VLC_TRUE;
726         }
727         msg_Dbg( p_input, "starting in %s mode",
728                  p_input->b_out_pace_control ? "asynch" : "synch" );
729     }
730
731     /* Get meta data from users */
732     p_meta_user = InputMetaUser( p_input );
733
734     /* Get meta data from master input */
735     if( demux2_Control( p_input->input.p_demux, DEMUX_GET_META, &p_meta ) )
736         p_meta = NULL;
737
738     /* Merge them */
739     if( p_meta == NULL )
740     {
741         p_meta = p_meta_user;
742     }
743     else if( p_meta_user )
744     {
745         vlc_meta_Merge( p_meta, p_meta_user );
746         vlc_meta_Delete( p_meta_user );
747     }
748
749     /* Get meta data from slave input */
750     for( i = 0; i < p_input->i_slave; i++ )
751     {
752         vlc_meta_t *p_meta_slave;
753
754         if( !demux2_Control( p_input->slave[i]->p_demux, DEMUX_GET_META, &p_meta_slave ) )
755         {
756             if( p_meta == NULL )
757             {
758                 p_meta = p_meta_slave;
759             }
760             else if( p_meta_slave )
761             {
762                 vlc_meta_Merge( p_meta, p_meta_slave );
763                 vlc_meta_Delete( p_meta_slave );
764             }
765         }
766     }
767
768     if( p_meta && p_meta->i_meta > 0 )
769     {
770         msg_Dbg( p_input, "meta informations:" );
771         for( i = 0; i < p_meta->i_meta; i++ )
772         {
773             msg_Dbg( p_input, "  - '%s' = '%s'",
774                     _(p_meta->name[i]), p_meta->value[i] );
775
776             if( !strcmp(p_meta->name[i], VLC_META_TITLE) && p_meta->value[i] )
777                 input_Control( p_input, INPUT_SET_NAME, p_meta->value[i] );
778
779             if( !strcmp( p_meta->name[i], VLC_META_AUTHOR ) )
780                 input_Control( p_input, INPUT_ADD_INFO, _("General"),
781                                _("Author"), p_meta->value[i] );
782
783             input_Control( p_input, INPUT_ADD_INFO, _("Meta-informations"),
784                           _(p_meta->name[i]), "%s", p_meta->value[i] );
785         }
786
787         for( i = 0; i < p_meta->i_track; i++ )
788         {
789             vlc_meta_t *tk = p_meta->track[i];
790             int j;
791
792             if( tk->i_meta > 0 )
793             {
794                 char *psz_cat = malloc( strlen(_("Stream")) + 10 );
795
796                 msg_Dbg( p_input, "  - track[%d]:", i );
797
798                 sprintf( psz_cat, "%s %d", _("Stream"), i );
799                 for( j = 0; j < tk->i_meta; j++ )
800                 {
801                     msg_Dbg( p_input, "     - '%s' = '%s'", _(tk->name[j]),
802                              tk->value[j] );
803
804                     input_Control( p_input, INPUT_ADD_INFO, psz_cat,
805                                    _(tk->name[j]), "%s", tk->value[j] );
806                 }
807             }
808         }
809
810         if( p_input->p_sout && p_input->p_sout->p_meta == NULL )
811         {
812             p_input->p_sout->p_meta = p_meta;
813         }
814         else
815         {
816             vlc_meta_Delete( p_meta );
817         }
818     }
819
820     msg_Dbg( p_input, "`%s' sucessfully opened",
821              p_input->input.p_item->psz_uri );
822
823     /* initialization is complete */
824     p_input->i_state = PLAYING_S;
825
826     val.i_int = PLAYING_S;
827     var_Change( p_input, "state", VLC_VAR_SETVALUE, &val, NULL );
828
829     return VLC_SUCCESS;
830
831 error:
832     if( p_input->p_es_out )
833         input_EsOutDelete( p_input->p_es_out );
834
835     if( p_input->p_sout )
836         sout_DeleteInstance( p_input->p_sout );
837
838     /* Mark them deleted */
839     p_input->input.p_demux = NULL;
840     p_input->input.p_stream = NULL;
841     p_input->input.p_access = NULL;
842     p_input->p_es_out = NULL;
843     p_input->p_sout = NULL;
844
845     return VLC_EGENERIC;
846 }
847
848 /*****************************************************************************
849  * Error: RunThread() error loop
850  *****************************************************************************
851  * This function is called when an error occured during thread main's loop.
852  *****************************************************************************/
853 static void Error( input_thread_t *p_input )
854 {
855     while( !p_input->b_die )
856     {
857         /* Sleep a while */
858         msleep( INPUT_IDLE_SLEEP );
859     }
860 }
861
862 /*****************************************************************************
863  * End: end the input thread
864  *****************************************************************************/
865 static void End( input_thread_t * p_input )
866 {
867     vlc_value_t val;
868     int i;
869
870     msg_Dbg( p_input, "closing `%s'",
871              p_input->input.p_item->psz_uri );
872
873     /* We are at the end */
874     p_input->i_state = END_S;
875
876     val.i_int = END_S;
877     var_Change( p_input, "state", VLC_VAR_SETVALUE, &val, NULL );
878
879     /* Clean control variables */
880     input_ControlVarClean( p_input );
881
882     /* Clean up master */
883     InputSourceClean( p_input, &p_input->input );
884
885     /* Delete slave */
886     for( i = 0; i < p_input->i_slave; i++ )
887     {
888         InputSourceClean( p_input, p_input->slave[i] );
889         free( p_input->slave[i] );
890     }
891     if( p_input->slave ) free( p_input->slave );
892
893     /* Unload all modules */
894     if( p_input->p_es_out )
895         input_EsOutDelete( p_input->p_es_out );
896
897     /* Close optional stream output instance */
898     if( p_input->p_sout )
899     {
900         vlc_object_t *p_pl =
901             vlc_object_find( p_input, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
902         vlc_value_t keep;
903
904         if( var_Get( p_input, "sout-keep", &keep ) >= 0 && keep.b_bool && p_pl )
905         {
906             /* attach sout to the playlist */
907             msg_Warn( p_input, "keeping sout" );
908             vlc_object_detach( p_input->p_sout );
909             vlc_object_attach( p_input->p_sout, p_pl );
910         }
911         else
912         {
913             msg_Warn( p_input, "destroying sout" );
914             sout_DeleteInstance( p_input->p_sout );
915         }
916         if( p_pl )
917             vlc_object_release( p_pl );
918     }
919
920     /* Tell we're dead */
921     p_input->b_dead = VLC_TRUE;
922 }
923
924 /*****************************************************************************
925  * Control
926  *****************************************************************************/
927 static inline int ControlPopNoLock( input_thread_t *p_input,
928                                     int *pi_type, vlc_value_t *p_val )
929 {
930     if( p_input->i_control <= 0 )
931     {
932         return VLC_EGENERIC;
933     }
934
935     *pi_type = p_input->control[0].i_type;
936     *p_val   = p_input->control[0].val;
937
938     p_input->i_control--;
939     if( p_input->i_control > 0 )
940     {
941         int i;
942
943         for( i = 0; i < p_input->i_control; i++ )
944         {
945             p_input->control[i].i_type = p_input->control[i+1].i_type;
946             p_input->control[i].val    = p_input->control[i+1].val;
947         }
948     }
949
950     return VLC_SUCCESS;
951 }
952
953 static void ControlReduce( input_thread_t *p_input )
954 {
955     int i;
956     for( i = 1; i < p_input->i_control; i++ )
957     {
958         const int i_lt = p_input->control[i-1].i_type;
959         const int i_ct = p_input->control[i].i_type;
960
961         /* XXX We can't merge INPUT_CONTROL_SET_ES */
962         msg_Dbg( p_input, "[%d/%d] l=%d c=%d", i, p_input->i_control,
963                  i_lt, i_ct );
964         if( i_lt == i_ct &&
965             ( i_ct == INPUT_CONTROL_SET_STATE ||
966               i_ct == INPUT_CONTROL_SET_RATE ||
967               i_ct == INPUT_CONTROL_SET_POSITION ||
968               i_ct == INPUT_CONTROL_SET_TIME ||
969               i_ct == INPUT_CONTROL_SET_PROGRAM ||
970               i_ct == INPUT_CONTROL_SET_TITLE ||
971               i_ct == INPUT_CONTROL_SET_SEEKPOINT ||
972               i_ct == INPUT_CONTROL_SET_BOOKMARK ) )
973         {
974             int j;
975             msg_Dbg( p_input, "merged at %d", i );
976             /* Remove the i-1 */
977             for( j = i; j <  p_input->i_control; j++ )
978                 p_input->control[j-1] = p_input->control[j];
979             p_input->i_control--;
980         }
981         else
982         {
983             /* TODO but that's not that important
984                 - merge SET_X with SET_X_CMD
985                 - remove SET_SEEKPOINT/SET_POSITION/SET_TIME before a SET_TITLE
986                 - remove SET_SEEKPOINT/SET_POSITION/SET_TIME before another among them
987                 - ?
988                 */
989         }
990     }
991 }
992
993 static vlc_bool_t Control( input_thread_t *p_input, int i_type,
994                            vlc_value_t val )
995 {
996     vlc_bool_t b_force_update = VLC_FALSE;
997
998     switch( i_type )
999     {
1000         case INPUT_CONTROL_SET_DIE:
1001             msg_Dbg( p_input, "control: INPUT_CONTROL_SET_DIE proceed" );
1002             /* Mark all submodules to die */
1003             if( p_input->input.p_access )
1004                 p_input->input.p_access->b_die = VLC_TRUE;
1005             if( p_input->input.p_stream )
1006                 p_input->input.p_stream->b_die = VLC_TRUE;
1007             p_input->input.p_demux->b_die = VLC_TRUE;
1008
1009             p_input->b_die = VLC_TRUE;
1010             break;
1011
1012         case INPUT_CONTROL_SET_POSITION:
1013         case INPUT_CONTROL_SET_POSITION_OFFSET:
1014         {
1015             double f_pos;
1016             if( i_type == INPUT_CONTROL_SET_POSITION )
1017             {
1018                 f_pos = val.f_float;
1019             }
1020             else
1021             {
1022                 /* Should not fail */
1023                 demux2_Control( p_input->input.p_demux,
1024                                 DEMUX_GET_POSITION, &f_pos );
1025                 f_pos += val.f_float;
1026             }
1027             if( f_pos < 0.0 ) f_pos = 0.0;
1028             if( f_pos > 1.0 ) f_pos = 1.0;
1029             if( demux2_Control( p_input->input.p_demux, DEMUX_SET_POSITION,
1030                                 f_pos ) )
1031             {
1032                 msg_Err( p_input, "INPUT_CONTROL_SET_POSITION(_OFFSET) "
1033                          "%2.1f%% failed", f_pos * 100 );
1034             }
1035             else
1036             {
1037                 if( p_input->i_slave > 0 )
1038                     SlaveSeek( p_input );
1039
1040                 input_EsOutDiscontinuity( p_input->p_es_out, VLC_FALSE );
1041                 es_out_Control( p_input->p_es_out, ES_OUT_RESET_PCR );
1042                 b_force_update = VLC_TRUE;
1043             }
1044             break;
1045         }
1046
1047         case INPUT_CONTROL_SET_TIME:
1048         case INPUT_CONTROL_SET_TIME_OFFSET:
1049         {
1050             int64_t i_time;
1051             int i_ret;
1052
1053             if( i_type == INPUT_CONTROL_SET_TIME )
1054             {
1055                 i_time = val.i_time;
1056             }
1057             else
1058             {
1059                 /* Should not fail */
1060                 demux2_Control( p_input->input.p_demux,
1061                                 DEMUX_GET_TIME, &i_time );
1062                 i_time += val.i_time;
1063             }
1064             if( i_time < 0 ) i_time = 0;
1065             i_ret = demux2_Control( p_input->input.p_demux,
1066                                     DEMUX_SET_TIME, i_time );
1067             if( i_ret )
1068             {
1069                 int64_t i_length;
1070                 /* Emulate it with a SET_POS */
1071
1072                 demux2_Control( p_input->input.p_demux,
1073                                 DEMUX_GET_LENGTH, &i_length );
1074                 if( i_length > 0 )
1075                 {
1076                     double f_pos = (double)i_time / (double)i_length;
1077                     i_ret = demux2_Control( p_input->input.p_demux,
1078                                             DEMUX_SET_POSITION, f_pos );
1079                 }
1080             }
1081             if( i_ret )
1082             {
1083                 msg_Err( p_input, "INPUT_CONTROL_SET_TIME(_OFFSET) "I64Fd
1084                          " failed", i_time );
1085             }
1086             else
1087             {
1088                 if( p_input->i_slave > 0 )
1089                     SlaveSeek( p_input );
1090
1091                 input_EsOutDiscontinuity( p_input->p_es_out, VLC_FALSE );
1092
1093                 es_out_Control( p_input->p_es_out, ES_OUT_RESET_PCR );
1094                 b_force_update = VLC_TRUE;
1095             }
1096             break;
1097         }
1098
1099         case INPUT_CONTROL_SET_STATE:
1100             if( ( val.i_int == PLAYING_S && p_input->i_state == PAUSE_S ) ||
1101                 ( val.i_int == PAUSE_S && p_input->i_state == PAUSE_S ) )
1102             {
1103                 int i_ret;
1104                 if( p_input->input.p_access )
1105                     i_ret = access2_Control( p_input->input.p_access,
1106                                              ACCESS_SET_PAUSE_STATE, VLC_FALSE );
1107                 else
1108                     i_ret = demux2_Control( p_input->input.p_demux,
1109                                             DEMUX_SET_PAUSE_STATE, VLC_FALSE );
1110
1111                 if( i_ret )
1112                 {
1113                     /* FIXME What to do ? */
1114                     msg_Warn( p_input, "cannot unset pause -> EOF" );
1115                     input_ControlPush( p_input, INPUT_CONTROL_SET_DIE, NULL );
1116                 }
1117
1118                 b_force_update = VLC_TRUE;
1119
1120                 /* Switch to play */
1121                 p_input->i_state = PLAYING_S;
1122                 val.i_int = PLAYING_S;
1123                 var_Change( p_input, "state", VLC_VAR_SETVALUE, &val, NULL );
1124
1125                 /* Reset clock */
1126                 es_out_Control( p_input->p_es_out, ES_OUT_RESET_PCR );
1127             }
1128             else if( val.i_int == PAUSE_S && p_input->i_state == PLAYING_S &&
1129                      p_input->b_can_pause )
1130             {
1131                 int i_ret;
1132                 if( p_input->input.p_access )
1133                     i_ret = access2_Control( p_input->input.p_access,
1134                                              ACCESS_SET_PAUSE_STATE, VLC_TRUE );
1135                 else
1136                     i_ret = demux2_Control( p_input->input.p_demux,
1137                                             DEMUX_SET_PAUSE_STATE, VLC_TRUE );
1138
1139                 b_force_update = VLC_TRUE;
1140
1141                 if( i_ret )
1142                 {
1143                     msg_Warn( p_input, "cannot set pause state" );
1144                     val.i_int = p_input->i_state;
1145                 }
1146                 else
1147                 {
1148                     val.i_int = PAUSE_S;
1149                 }
1150
1151                 /* Switch to new state */
1152                 p_input->i_state = val.i_int;
1153                 var_Change( p_input, "state", VLC_VAR_SETVALUE, &val, NULL );
1154             }
1155             else if( val.i_int == PAUSE_S && !p_input->b_can_pause )
1156             {
1157                 b_force_update = VLC_TRUE;
1158
1159                 /* Correct "state" value */
1160                 val.i_int = p_input->i_state;
1161                 var_Change( p_input, "state", VLC_VAR_SETVALUE, &val, NULL );
1162             }
1163             else if( val.i_int != PLAYING_S && val.i_int != PAUSE_S )
1164             {
1165                 msg_Err( p_input, "invalid state in INPUT_CONTROL_SET_STATE" );
1166             }
1167             break;
1168
1169         case INPUT_CONTROL_SET_RATE:
1170         case INPUT_CONTROL_SET_RATE_SLOWER:
1171         case INPUT_CONTROL_SET_RATE_FASTER:
1172         {
1173             int i_rate;
1174
1175             if( i_type == INPUT_CONTROL_SET_RATE_SLOWER )
1176                 i_rate = p_input->i_rate * 2;
1177             else if( i_type == INPUT_CONTROL_SET_RATE_FASTER )
1178                 i_rate = p_input->i_rate / 2;
1179             else
1180                 i_rate = val.i_int;
1181
1182             if( i_rate < INPUT_RATE_MIN )
1183             {
1184                 msg_Dbg( p_input, "cannot set rate faster" );
1185                 i_rate = INPUT_RATE_MIN;
1186             }
1187             else if( i_rate > INPUT_RATE_MAX )
1188             {
1189                 msg_Dbg( p_input, "cannot set rate slower" );
1190                 i_rate = INPUT_RATE_MAX;
1191             }
1192             if( i_rate != INPUT_RATE_DEFAULT &&
1193                 ( !p_input->b_can_pace_control ||
1194                   !p_input->b_out_pace_control ) )
1195             {
1196                 msg_Dbg( p_input, "cannot change rate" );
1197                 i_rate = INPUT_RATE_DEFAULT;
1198             }
1199             if( i_rate != p_input->i_rate )
1200             {
1201                 p_input->i_rate  = i_rate;
1202                 val.i_int = i_rate;
1203                 var_Change( p_input, "rate", VLC_VAR_SETVALUE, &val, NULL );
1204
1205                 /* We haven't send data to decoder when rate != default */
1206                 if( i_rate == INPUT_RATE_DEFAULT )
1207                     input_EsOutDiscontinuity( p_input->p_es_out, VLC_TRUE );
1208
1209                 /* Reset clock */
1210                 es_out_Control( p_input->p_es_out, ES_OUT_RESET_PCR );
1211
1212                 b_force_update = VLC_TRUE;
1213             }
1214             break;
1215         }
1216
1217         case INPUT_CONTROL_SET_PROGRAM:
1218             /* No need to force update, es_out does it if needed */
1219             es_out_Control( p_input->p_es_out,
1220                             ES_OUT_SET_GROUP, val.i_int );
1221             break;
1222
1223         case INPUT_CONTROL_SET_ES:
1224             /* No need to force update, es_out does it if needed */
1225             es_out_Control( p_input->p_es_out, ES_OUT_SET_ES,
1226                             input_EsOutGetFromID( p_input->p_es_out,
1227                                                   val.i_int ) );
1228             break;
1229
1230         case INPUT_CONTROL_SET_AUDIO_DELAY:
1231             input_EsOutSetDelay( p_input->p_es_out,
1232                                  AUDIO_ES, val.i_time );
1233             var_Change( p_input, "audio-delay", VLC_VAR_SETVALUE, &val, NULL );
1234             break;
1235
1236         case INPUT_CONTROL_SET_SPU_DELAY:
1237             input_EsOutSetDelay( p_input->p_es_out,
1238                                  SPU_ES, val.i_time );
1239             var_Change( p_input, "spu-delay", VLC_VAR_SETVALUE, &val, NULL );
1240             break;
1241
1242         case INPUT_CONTROL_SET_TITLE:
1243         case INPUT_CONTROL_SET_TITLE_NEXT:
1244         case INPUT_CONTROL_SET_TITLE_PREV:
1245             if( p_input->input.b_title_demux &&
1246                 p_input->input.i_title > 0 )
1247             {
1248                 /* TODO */
1249                 /* FIXME handle demux title */
1250                 demux_t *p_demux = p_input->input.p_demux;
1251                 int i_title;
1252
1253                 if( i_type == INPUT_CONTROL_SET_TITLE_PREV )
1254                     i_title = p_demux->info.i_title - 1;
1255                 else if( i_type == INPUT_CONTROL_SET_TITLE_NEXT )
1256                     i_title = p_demux->info.i_title + 1;
1257                 else
1258                     i_title = val.i_int;
1259
1260                 if( i_title >= 0 && i_title < p_input->input.i_title )
1261                 {
1262                     demux2_Control( p_demux, DEMUX_SET_TITLE, i_title );
1263
1264                     input_EsOutDiscontinuity( p_input->p_es_out, VLC_FALSE );
1265                     es_out_Control( p_input->p_es_out, ES_OUT_RESET_PCR );
1266
1267                     input_ControlVarTitle( p_input, i_title );
1268                 }
1269             }
1270             else if( p_input->input.i_title > 0 )
1271             {
1272                 access_t *p_access = p_input->input.p_access;
1273                 int i_title;
1274
1275                 if( i_type == INPUT_CONTROL_SET_TITLE_PREV )
1276                     i_title = p_access->info.i_title - 1;
1277                 else if( i_type == INPUT_CONTROL_SET_TITLE_NEXT )
1278                     i_title = p_access->info.i_title + 1;
1279                 else
1280                     i_title = val.i_int;
1281
1282                 if( i_title >= 0 && i_title < p_input->input.i_title )
1283                 {
1284                     access2_Control( p_access, ACCESS_SET_TITLE, i_title );
1285                     stream_AccessReset( p_input->input.p_stream );
1286
1287                     input_EsOutDiscontinuity( p_input->p_es_out, VLC_FALSE );
1288                     es_out_Control( p_input->p_es_out, ES_OUT_RESET_PCR );
1289                 }
1290             }
1291             break;
1292         case INPUT_CONTROL_SET_SEEKPOINT:
1293         case INPUT_CONTROL_SET_SEEKPOINT_NEXT:
1294         case INPUT_CONTROL_SET_SEEKPOINT_PREV:
1295             if( p_input->input.b_title_demux &&
1296                 p_input->input.i_title > 0 )
1297             {
1298                 demux_t *p_demux = p_input->input.p_demux;
1299                 int i_seekpoint;
1300
1301                 if( i_type == INPUT_CONTROL_SET_SEEKPOINT_PREV )
1302                     i_seekpoint = p_demux->info.i_seekpoint - 1;
1303                 else if( i_type == INPUT_CONTROL_SET_SEEKPOINT_NEXT )
1304                     i_seekpoint = p_demux->info.i_seekpoint + 1;
1305                 else
1306                     i_seekpoint = val.i_int;
1307
1308                 if( i_seekpoint >= 0 && i_seekpoint <
1309                     p_input->input.title[p_demux->info.i_title]->i_seekpoint )
1310                 {
1311                     demux2_Control( p_demux, DEMUX_SET_SEEKPOINT, i_seekpoint );
1312
1313                     input_EsOutDiscontinuity( p_input->p_es_out, VLC_FALSE );
1314                     es_out_Control( p_input->p_es_out, ES_OUT_RESET_PCR );
1315                 }
1316             }
1317             else if( p_input->input.i_title > 0 )
1318             {
1319                 access_t *p_access = p_input->input.p_access;
1320                 int i_seekpoint;
1321
1322                 if( i_type == INPUT_CONTROL_SET_SEEKPOINT_PREV )
1323                     i_seekpoint = p_access->info.i_seekpoint - 1;
1324                 else if( i_type == INPUT_CONTROL_SET_TITLE_NEXT )
1325                     i_seekpoint = p_access->info.i_seekpoint + 1;
1326                 else
1327                     i_seekpoint = val.i_int;
1328
1329                 if( i_seekpoint >= 0 && i_seekpoint <
1330                     p_input->input.title[p_access->info.i_title]->i_seekpoint )
1331                 {
1332                     access2_Control( p_access, ACCESS_SET_SEEKPOINT, i_seekpoint );
1333                     stream_AccessReset( p_input->input.p_stream );
1334
1335                     input_EsOutDiscontinuity( p_input->p_es_out, VLC_FALSE );
1336                     es_out_Control( p_input->p_es_out, ES_OUT_RESET_PCR );
1337                 }
1338             }
1339             break;
1340
1341         case INPUT_CONTROL_SET_BOOKMARK:
1342         default:
1343             msg_Err( p_input, "not yet implemented" );
1344             break;
1345     }
1346
1347     return b_force_update;
1348 }
1349
1350 /*****************************************************************************
1351  * UpdateFromDemux:
1352  *****************************************************************************/
1353 static void UpdateFromDemux( input_thread_t *p_input )
1354 {
1355     demux_t *p_demux = p_input->input.p_demux;
1356     vlc_value_t v;
1357
1358     if( p_demux->info.i_update & INPUT_UPDATE_TITLE )
1359     {
1360         v.i_int = p_demux->info.i_title;
1361         var_Change( p_input, "title", VLC_VAR_SETVALUE, &v, NULL );
1362
1363         input_ControlVarTitle( p_input, p_demux->info.i_title );
1364
1365         p_demux->info.i_update &= ~INPUT_UPDATE_TITLE;
1366     }
1367     if( p_demux->info.i_update & INPUT_UPDATE_SEEKPOINT )
1368     {
1369         v.i_int = p_demux->info.i_seekpoint;
1370         var_Change( p_input, "chapter", VLC_VAR_SETVALUE, &v, NULL);
1371
1372         p_demux->info.i_update &= ~INPUT_UPDATE_SEEKPOINT;
1373     }
1374     p_demux->info.i_update &= ~INPUT_UPDATE_SIZE;
1375 }
1376
1377 /*****************************************************************************
1378  * UpdateFromAccess:
1379  *****************************************************************************/
1380 static void UpdateFromAccess( input_thread_t *p_input )
1381 {
1382     access_t *p_access = p_input->input.p_access;
1383     vlc_value_t v;
1384
1385     if( p_access->info.i_update & INPUT_UPDATE_TITLE )
1386     {
1387         v.i_int = p_access->info.i_title;
1388         var_Change( p_input, "title", VLC_VAR_SETVALUE, &v, NULL );
1389
1390         input_ControlVarTitle( p_input, p_access->info.i_title );
1391
1392         p_access->info.i_update &= ~INPUT_UPDATE_TITLE;
1393     }
1394     if( p_access->info.i_update & INPUT_UPDATE_SEEKPOINT )
1395     {
1396         v.i_int = p_access->info.i_seekpoint;
1397         var_Change( p_input, "chapter", VLC_VAR_SETVALUE, &v, NULL);
1398
1399         p_access->info.i_update &= ~INPUT_UPDATE_SEEKPOINT;
1400     }
1401     p_access->info.i_update &= ~INPUT_UPDATE_SIZE;
1402 }
1403
1404 /*****************************************************************************
1405  * InputSourceNew:
1406  *****************************************************************************/
1407 static input_source_t *InputSourceNew( input_thread_t *p_input )
1408 {
1409     input_source_t *in = malloc( sizeof( input_source_t ) );
1410
1411     in->p_item   = NULL;
1412     in->p_access = NULL;
1413     in->p_stream = NULL;
1414     in->p_demux  = NULL;
1415     in->b_title_demux = VLC_FALSE;
1416     in->i_title  = 0;
1417     in->title    = NULL;
1418     in->b_can_pace_control = VLC_TRUE;
1419     in->b_eof = VLC_FALSE;
1420     in->i_cr_average = 0;
1421
1422     return in;
1423 }
1424
1425 /*****************************************************************************
1426  * InputSourceInit:
1427  *****************************************************************************/
1428 static int InputSourceInit( input_thread_t *p_input,
1429                             input_source_t *in, char *psz_mrl,
1430                             char *psz_forced_demux )
1431 {
1432     char *psz_dup = strdup( psz_mrl );
1433     char *psz_access;
1434     char *psz_demux;
1435     char *psz_path;
1436     vlc_value_t val;
1437
1438     /* Split uri */
1439     MRLSplit( p_input, psz_dup, &psz_access, &psz_demux, &psz_path );
1440
1441     msg_Dbg( p_input, "`%s' gives access `%s' demux `%s' path `%s'",
1442              psz_mrl, psz_access, psz_demux, psz_path );
1443
1444     if( psz_forced_demux && *psz_forced_demux )
1445         psz_demux = psz_forced_demux;
1446
1447     /* Try access_demux if no demux given */
1448     if( *psz_access && *psz_demux == '\0' )
1449     {
1450         in->p_demux = demux2_New( p_input, psz_access, psz_demux, psz_path,
1451                                   NULL, p_input->p_es_out );
1452     }
1453
1454     if( in->p_demux )
1455     {
1456         int64_t i_pts_delay;
1457
1458         /* Get infos from access_demux */
1459         demux2_Control( in->p_demux,
1460                         DEMUX_GET_PTS_DELAY, &i_pts_delay );
1461         p_input->i_pts_delay = __MAX( p_input->i_pts_delay, i_pts_delay );
1462
1463         in->b_title_demux = VLC_TRUE;
1464         if( demux2_Control( in->p_demux,
1465                             DEMUX_GET_TITLE_INFO,
1466                             &in->title, &in->i_title ) )
1467         {
1468             in->i_title = 0;
1469             in->title   = NULL;
1470         }
1471         demux2_Control( in->p_demux, DEMUX_CAN_CONTROL_PACE,
1472                         &in->b_can_pace_control );
1473         demux2_Control( in->p_demux, DEMUX_CAN_PAUSE,
1474                         &in->b_can_pause );
1475
1476         /* FIXME todo
1477         demux2_Control( in->p_demux, DEMUX_CAN_SEEK,
1478                         &val.b_bool );
1479         */
1480     }
1481     else
1482     {
1483         int64_t i_pts_delay;
1484
1485         /* Now try a real access */
1486         in->p_access = access2_New( p_input, psz_access, psz_demux, psz_path );
1487
1488         /* Access failed, URL encoded ? */
1489         if( in->p_access == NULL && strchr( psz_path, '%' ) )
1490         {
1491             DecodeUrl( psz_path );
1492
1493             msg_Dbg( p_input, "retying with access `%s' demux `%s' path `%s'",
1494                      psz_access, psz_demux, psz_path );
1495
1496             in->p_access = access2_New( p_input,
1497                                         psz_access, psz_demux, psz_path );
1498         }
1499 #ifndef WIN32      /* Remove this gross hack from the win32 build as colons
1500                         * are forbidden in filenames on Win32. */
1501
1502         /* Maybe we got something like: /Volumes/toto:titi/gabu.mpg */
1503         if( in->p_access == NULL &&
1504             *psz_access == '\0' && ( *psz_demux || *psz_path ) )
1505         {
1506             free( psz_dup );
1507             psz_dup = strdup( psz_mrl );
1508             psz_access = "";
1509             psz_demux = "";
1510             psz_path = psz_dup;
1511
1512             in->p_access = access2_New( p_input,
1513                                         psz_access, psz_demux, psz_path );
1514         }
1515 #endif
1516
1517         if( in->p_access == NULL )
1518         {
1519             msg_Err( p_input, "no suitable access module for `%s'", psz_mrl );
1520             goto error;
1521         }
1522
1523         /* Get infos from access */
1524         access2_Control( in->p_access,
1525                          ACCESS_GET_PTS_DELAY, &i_pts_delay );
1526         p_input->i_pts_delay = __MAX( p_input->i_pts_delay, i_pts_delay );
1527
1528         in->b_title_demux = VLC_FALSE;
1529         if( access2_Control( in->p_access,
1530                              ACCESS_GET_TITLE_INFO,
1531                              &in->title, &in->i_title ) )
1532         {
1533             in->i_title = 0;
1534             in->title   = NULL;
1535         }
1536         access2_Control( in->p_access, ACCESS_CAN_CONTROL_PACE,
1537                          &in->b_can_pace_control );
1538         access2_Control( in->p_access, ACCESS_CAN_PAUSE,
1539                          &in->b_can_pause );
1540         access2_Control( in->p_access, ACCESS_CAN_SEEK,
1541                          &val.b_bool );
1542         var_Set( p_input, "seekable", val );
1543
1544         /* Create the stream_t */
1545         in->p_stream = stream_AccessNew( in->p_access );
1546         if( in->p_stream == NULL )
1547         {
1548             msg_Warn( p_input, "cannot create a stream_t from access" );
1549             goto error;
1550         }
1551
1552         /* Open a demuxer */
1553         if( *psz_demux == '\0' && *in->p_access->psz_demux )
1554         {
1555             psz_demux = in->p_access->psz_demux;
1556         }
1557         in->p_demux = demux2_New( p_input, psz_access, psz_demux, psz_path,
1558                                   in->p_stream, p_input->p_es_out );
1559         if( in->p_demux == NULL )
1560         {
1561             msg_Err( p_input, "no suitable demux module for `%s/%s://%s'",
1562                      psz_access, psz_demux, psz_path );
1563             goto error;
1564         }
1565
1566         /* TODO get title from demux */
1567         if( in->i_title <= 0 )
1568         {
1569             if( demux2_Control( in->p_demux, DEMUX_GET_TITLE_INFO,
1570                                 &in->title, &in->i_title ) )
1571             {
1572                 in->i_title = 0;
1573                 in->title   = NULL;
1574             }
1575             else
1576             {
1577                 in->b_title_demux = VLC_TRUE;
1578             }
1579         }
1580     }
1581     free( psz_dup );
1582     return VLC_SUCCESS;
1583
1584 error:
1585     if( in->p_demux )
1586         demux2_Delete( in->p_demux );
1587
1588     if( in->p_stream )
1589         stream_AccessDelete( in->p_stream );
1590
1591     if( in->p_access )
1592         access2_Delete( in->p_access );
1593     free( psz_dup );
1594
1595     return VLC_EGENERIC;
1596 }
1597
1598 /*****************************************************************************
1599  * InputSourceClean:
1600  *****************************************************************************/
1601 static void InputSourceClean( input_thread_t *p_input, input_source_t *in )
1602 {
1603     if( in->p_demux )
1604         demux2_Delete( in->p_demux );
1605
1606     if( in->p_stream )
1607         stream_AccessDelete( in->p_stream );
1608
1609     if( in->p_access )
1610         access2_Delete( in->p_access );
1611
1612     if( in->i_title > 0 )
1613     {
1614         int i;
1615         for( i = 0; i < in->i_title; i++ )
1616         {
1617             vlc_input_title_Delete( in->title[i] );
1618         }
1619         free( in->title );
1620     }
1621 }
1622
1623 static void SlaveDemux( input_thread_t *p_input )
1624 {
1625     int64_t i_time;
1626     int i;
1627     if( demux2_Control( p_input->input.p_demux, DEMUX_GET_TIME, &i_time ) )
1628     {
1629         msg_Err( p_input, "demux doesn't like DEMUX_GET_TIME" );
1630         return;
1631     }
1632
1633     for( i = 0; i < p_input->i_slave; i++ )
1634     {
1635         input_source_t *in = p_input->slave[i];
1636         int i_ret = 1;
1637
1638         if( in->b_eof )
1639             continue;
1640
1641         if( demux2_Control( in->p_demux, DEMUX_SET_NEXT_DEMUX_TIME, i_time ) )
1642         {
1643             for( ;; )
1644             {
1645                 int64_t i_stime;
1646                 if( demux2_Control( in->p_demux, DEMUX_GET_TIME, &i_stime ) )
1647                 {
1648                     msg_Err( p_input, "slave[%d] doesn't like "
1649                              "DEMUX_GET_TIME -> EOF", i );
1650                     i_ret = 0;
1651                     break;
1652                 }
1653
1654                 if( i_stime >= i_time )
1655                     break;
1656
1657                 if( ( i_ret = in->p_demux->pf_demux( in->p_demux ) ) <= 0 )
1658                     break;
1659             }
1660         }
1661         else
1662         {
1663             i_ret = in->p_demux->pf_demux( in->p_demux );
1664         }
1665
1666         if( i_ret <= 0 )
1667         {
1668             msg_Dbg( p_input, "slave %d EOF", i );
1669             in->b_eof = VLC_TRUE;
1670         }
1671     }
1672 }
1673
1674 static void SlaveSeek( input_thread_t *p_input )
1675 {
1676     int64_t i_time;
1677     int i;
1678
1679     if( demux2_Control( p_input->input.p_demux, DEMUX_GET_TIME, &i_time ) )
1680     {
1681         msg_Err( p_input, "demux doesn't like DEMUX_GET_TIME" );
1682         return;
1683     }
1684
1685     for( i = 0; i < p_input->i_slave; i++ )
1686     {
1687         input_source_t *in = p_input->slave[i];
1688
1689         if( demux2_Control( in->p_demux, DEMUX_SET_TIME, i_time ) )
1690         {
1691             msg_Err( p_input, "seek failed for slave %d -> EOF", i );
1692             in->b_eof = VLC_TRUE;
1693         }
1694     }
1695 }
1696 /*****************************************************************************
1697  * InputMetaUser:
1698  *****************************************************************************/
1699 static vlc_meta_t *InputMetaUser( input_thread_t *p_input )
1700 {
1701     vlc_meta_t *p_meta;
1702     vlc_value_t val;
1703
1704     if( ( p_meta = vlc_meta_New() ) == NULL )
1705         return NULL;
1706
1707     /* Get meta information from user */
1708 #define GET_META( c, s ) \
1709     var_Get( p_input, (s), &val );  \
1710     if( *val.psz_string )       \
1711         vlc_meta_Add( p_meta, c, val.psz_string ); \
1712     free( val.psz_string )
1713
1714     GET_META( VLC_META_TITLE, "meta-title" );
1715     GET_META( VLC_META_AUTHOR, "meta-author" );
1716     GET_META( VLC_META_ARTIST, "meta-artist" );
1717     GET_META( VLC_META_GENRE, "meta-genre" );
1718     GET_META( VLC_META_COPYRIGHT, "meta-copyright" );
1719     GET_META( VLC_META_DESCRIPTION, "meta-description" );
1720     GET_META( VLC_META_DATE, "meta-date" );
1721     GET_META( VLC_META_URL, "meta-url" );
1722 #undef GET_META
1723
1724     return p_meta;
1725 }
1726
1727 /*****************************************************************************
1728  * DecodeUrl: decode a given encoded url
1729  *****************************************************************************/
1730 static void DecodeUrl( char *psz )
1731 {
1732     char *dup = strdup( psz );
1733     char *p = dup;
1734
1735     while( *p )
1736     {
1737         if( *p == '%' )
1738         {
1739             char val[3];
1740             p++;
1741             if( !*p )
1742             {
1743                 break;
1744             }
1745
1746             val[0] = *p++;
1747             val[1] = *p++;
1748             val[2] = '\0';
1749
1750             *psz++ = strtol( val, NULL, 16 );
1751         }
1752         else if( *p == '+' )
1753         {
1754             *psz++ = ' ';
1755             p++;
1756         }
1757         else
1758         {
1759             *psz++ = *p++;
1760         }
1761     }
1762     *psz++  ='\0';
1763     free( dup );
1764 }
1765
1766 /*****************************************************************************
1767  * ParseOption: parses the options for the input
1768  *****************************************************************************
1769  * This function parses the input (config) options and creates their associated
1770  * object variables.
1771  * Options are of the form "[no[-]]foo[=bar]" where foo is the option name and
1772  * bar is the value of the option.
1773  *****************************************************************************/
1774 static void ParseOption( input_thread_t *p_input, const char *psz_option )
1775 {
1776     char *psz_name = (char *)psz_option;
1777     char *psz_value = strchr( psz_option, '=' );
1778     int  i_name_len, i_type;
1779     vlc_bool_t b_isno = VLC_FALSE;
1780     vlc_value_t val;
1781
1782     if( psz_value ) i_name_len = psz_value - psz_option;
1783     else i_name_len = strlen( psz_option );
1784
1785     /* It's too much of an hassle to remove the ':' when we parse
1786      * the cmd line :) */
1787     if( i_name_len && *psz_name == ':' )
1788     {
1789         psz_name++;
1790         i_name_len--;
1791     }
1792
1793     if( i_name_len == 0 ) return;
1794
1795     psz_name = strndup( psz_name, i_name_len );
1796     if( psz_value ) psz_value++;
1797
1798     i_type = config_GetType( p_input, psz_name );
1799
1800     if( !i_type && !psz_value )
1801     {
1802         /* check for "no-foo" or "nofoo" */
1803         if( !strncmp( psz_name, "no-", 3 ) )
1804         {
1805             memmove( psz_name, psz_name + 3, strlen(psz_name) + 1 - 3 );
1806         }
1807         else if( !strncmp( psz_name, "no", 2 ) )
1808         {
1809             memmove( psz_name, psz_name + 2, strlen(psz_name) + 1 - 2 );
1810         }
1811         else goto cleanup;           /* Option doesn't exist */
1812
1813         b_isno = VLC_TRUE;
1814         i_type = config_GetType( p_input, psz_name );
1815
1816         if( !i_type ) goto cleanup;  /* Option doesn't exist */
1817     }
1818     else if( !i_type ) goto cleanup; /* Option doesn't exist */
1819
1820     if( ( i_type != VLC_VAR_BOOL ) &&
1821         ( !psz_value || !*psz_value ) ) goto cleanup; /* Invalid value */
1822
1823     /* Create the variable in the input object.
1824      * Children of the input object will be able to retreive this value
1825      * thanks to the inheritance property of the object variables. */
1826     var_Create( p_input, psz_name, i_type );
1827
1828     switch( i_type )
1829     {
1830     case VLC_VAR_BOOL:
1831         val.b_bool = !b_isno;
1832         break;
1833
1834     case VLC_VAR_INTEGER:
1835         val.i_int = atoi( psz_value );
1836         break;
1837
1838     case VLC_VAR_FLOAT:
1839         val.f_float = atof( psz_value );
1840         break;
1841
1842     case VLC_VAR_STRING:
1843     case VLC_VAR_MODULE:
1844     case VLC_VAR_FILE:
1845     case VLC_VAR_DIRECTORY:
1846         val.psz_string = psz_value;
1847         break;
1848
1849     default:
1850         goto cleanup;
1851         break;
1852     }
1853
1854     var_Set( p_input, psz_name, val );
1855
1856     msg_Dbg( p_input, "set input option: %s to %s", psz_name, psz_value );
1857
1858   cleanup:
1859     if( psz_name ) free( psz_name );
1860     return;
1861 }
1862
1863 static void MRLSplit( input_thread_t *p_input, char *psz_dup,
1864                       char **ppsz_access, char **ppsz_demux, char **ppsz_path )
1865 {
1866     char *psz_access = NULL;
1867     char *psz_demux  = NULL;
1868     char *psz_path   = NULL;
1869     char *psz;
1870
1871     psz = strchr( psz_dup, ':' );
1872
1873 #if defined( WIN32 ) || defined( UNDER_CE )
1874     if( psz - psz_dup == 1 )
1875     {
1876         msg_Warn( p_input, "drive letter %c: found in source string",
1877                   psz_dup[0] );
1878         psz_path = psz_dup;
1879     }
1880     else
1881 #endif
1882
1883     if( psz )
1884     {
1885         *psz++ = '\0';
1886         if( psz[0] == '/' && psz[1] == '/' )
1887             psz += 2;
1888
1889         psz_path = psz;
1890
1891         psz = strchr( psz_dup, '/' );
1892         if( psz )
1893         {
1894             *psz++ = '\0';
1895             psz_demux = psz;
1896         }
1897
1898         psz_access = psz_dup;
1899     }
1900     else
1901     {
1902         psz_path = psz_dup;
1903     }
1904
1905     if( psz_access == NULL )
1906         *ppsz_access = "";
1907     else
1908         *ppsz_access = psz_access;
1909
1910     if( psz_demux == NULL )
1911         *ppsz_demux = "";
1912     else
1913         *ppsz_demux = psz_demux;
1914
1915     if( psz_path == NULL )
1916         *ppsz_path = "";
1917     else
1918         *ppsz_path = psz_path;
1919 }