]> git.sesse.net Git - vlc/blob - src/input/input.c
input: handle recursive parsing in preparser
[vlc] / src / input / input.c
1 /*****************************************************************************
2  * input.c: input thread
3  *****************************************************************************
4  * Copyright (C) 1998-2007 VLC authors and 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 it
11  * under the terms of the GNU Lesser General Public License as published by
12  * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public License
21  * along with this program; if not, write to the Free Software Foundation,
22  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #include <vlc_common.h>
33
34 #include <limits.h>
35 #include <assert.h>
36 #include <errno.h>
37 #include <math.h>
38 #include <sys/stat.h>
39
40 #include "input_internal.h"
41 #include "event.h"
42 #include "es_out.h"
43 #include "es_out_timeshift.h"
44 #include "access.h"
45 #include "demux.h"
46 #include "stream.h"
47 #include "item.h"
48 #include "resource.h"
49
50 #include <vlc_sout.h>
51 #include <vlc_dialog.h>
52 #include <vlc_url.h>
53 #include <vlc_charset.h>
54 #include <vlc_fs.h>
55 #include <vlc_strings.h>
56 #include <vlc_modules.h>
57
58 /*****************************************************************************
59  * Local prototypes
60  *****************************************************************************/
61 static void Destructor( input_thread_t * p_input );
62
63 static  void *Run            ( void * );
64
65 static input_thread_t * Create  ( vlc_object_t *, input_item_t *,
66                                   const char *, bool, input_resource_t * );
67 static  int             Init    ( input_thread_t *p_input );
68 static void             End     ( input_thread_t *p_input );
69 static void             MainLoop( input_thread_t *p_input, bool b_interactive );
70
71 static inline int ControlPop( input_thread_t *, int *, vlc_value_t *, mtime_t i_deadline, bool b_postpone_seek );
72 static void       ControlRelease( int i_type, vlc_value_t val );
73 static bool       ControlIsSeekRequest( int i_type );
74 static bool       Control( input_thread_t *, int, vlc_value_t );
75
76 static int  UpdateTitleSeekpointFromDemux( input_thread_t * );
77 static void UpdateGenericFromDemux( input_thread_t * );
78 static void UpdateTitleListfromDemux( input_thread_t * );
79
80 static void MRLSections( const char *, int *, int *, int *, int *);
81
82 static input_source_t *InputSourceNew( input_thread_t *);
83 static int  InputSourceInit( input_thread_t *, input_source_t *,
84                              const char *, const char *psz_forced_demux,
85                              bool b_in_can_fail );
86 static void InputSourceClean( input_source_t * );
87 static void InputSourceMeta( input_thread_t *, input_source_t *, vlc_meta_t * );
88
89 /* TODO */
90 //static void InputGetAttachments( input_thread_t *, input_source_t * );
91 static void SlaveDemux( input_thread_t *p_input );
92 static void SlaveSeek( input_thread_t *p_input );
93
94 static void InputMetaUser( input_thread_t *p_input, vlc_meta_t *p_meta );
95 static void InputUpdateMeta( input_thread_t *p_input, demux_t *p_demux );
96 static void InputGetExtraFiles( input_thread_t *p_input,
97                                 int *pi_list, char ***pppsz_list,
98                                 const char *psz_access, const char *psz_path );
99
100 static void AppendAttachment( int *pi_attachment, input_attachment_t ***ppp_attachment, demux_t ***ppp_attachment_demux,
101                               int i_new, input_attachment_t **pp_new, demux_t *p_demux );
102
103 enum {
104     SUB_NOFLAG = 0x00,
105     SUB_FORCED = 0x01,
106     SUB_CANFAIL = 0x02,
107 };
108
109 static void input_SubtitleAdd( input_thread_t *, const char *, unsigned );
110 static void input_SubtitleFileAdd( input_thread_t *, char *, unsigned );
111 static void input_ChangeState( input_thread_t *p_input, int i_state ); /* TODO fix name */
112
113 #undef input_Create
114 /**
115  * Create a new input_thread_t.
116  *
117  * You need to call input_Start on it when you are done
118  * adding callback on the variables/events you want to monitor.
119  *
120  * \param p_parent a vlc_object
121  * \param p_item an input item
122  * \param psz_log an optional prefix for this input logs
123  * \param p_resource an optional input ressource
124  * \return a pointer to the spawned input thread
125  */
126 input_thread_t *input_Create( vlc_object_t *p_parent,
127                               input_item_t *p_item,
128                               const char *psz_log, input_resource_t *p_resource )
129 {
130     return Create( p_parent, p_item, psz_log, false, p_resource );
131 }
132
133 #undef input_CreateAndStart
134 /**
135  * Create a new input_thread_t and start it.
136  *
137  * Provided for convenience.
138  *
139  * \see input_Create
140  */
141 input_thread_t *input_CreateAndStart( vlc_object_t *p_parent,
142                                       input_item_t *p_item, const char *psz_log )
143 {
144     input_thread_t *p_input = input_Create( p_parent, p_item, psz_log, NULL );
145
146     if( input_Start( p_input ) )
147     {
148         vlc_object_release( p_input );
149         return NULL;
150     }
151     return p_input;
152 }
153
154 #undef input_Read
155 /**
156  * Initialize an input thread and run it until it stops by itself.
157  *
158  * \param p_parent a vlc_object
159  * \param p_item an input item
160  * \return an error code, VLC_SUCCESS on success
161  */
162 int input_Read( vlc_object_t *p_parent, input_item_t *p_item )
163 {
164     input_thread_t *p_input = Create( p_parent, p_item, NULL, false, NULL );
165     if( !p_input )
166         return VLC_EGENERIC;
167
168     if( !Init( p_input ) )
169     {
170         MainLoop( p_input, false );
171         End( p_input );
172     }
173
174     vlc_object_release( p_input );
175     return VLC_SUCCESS;
176 }
177
178 /**
179  * Initialize an input and initialize it to preparse the item
180  * This function is blocking. It will only accept parsing regular files.
181  *
182  * \param p_parent a vlc_object_t
183  * \param p_item an input item
184  * \return VLC_SUCCESS or an error
185  */
186 int input_Preparse( vlc_object_t *p_parent, input_item_t *p_item )
187 {
188     input_thread_t *p_input;
189
190     /* Allocate descriptor */
191     p_input = Create( p_parent, p_item, NULL, true, NULL );
192     if( !p_input )
193         return VLC_EGENERIC;
194
195     if( !Init( p_input ) ) {
196         /* if the demux is a playlist, call Mainloop that will call
197          * demux_Demux in order to fetch sub items */
198         bool b_is_playlist = false;
199
200         if ( input_item_ShouldPreparseSubItems( p_item )
201           && demux_Control( p_input->p->input.p_demux,
202                             DEMUX_IS_PLAYLIST,
203                             &b_is_playlist ) )
204             b_is_playlist = false;
205         if( b_is_playlist )
206             MainLoop( p_input, false );
207         End( p_input );
208     }
209
210     vlc_object_release( p_input );
211
212     return VLC_SUCCESS;
213 }
214
215 /**
216  * Start a input_thread_t created by input_Create.
217  *
218  * You must not start an already running input_thread_t.
219  *
220  * \param the input thread to start
221  */
222 int input_Start( input_thread_t *p_input )
223 {
224     /* Create thread and wait for its readiness. */
225     p_input->p->is_running = !vlc_clone( &p_input->p->thread,
226                                          Run, p_input, VLC_THREAD_PRIORITY_INPUT );
227     if( !p_input->p->is_running )
228     {
229         input_ChangeState( p_input, ERROR_S );
230         msg_Err( p_input, "cannot create input thread" );
231         return VLC_EGENERIC;
232     }
233     return VLC_SUCCESS;
234 }
235
236 /**
237  * Request a running input thread to stop and die
238  *
239  * \param p_input the input thread to stop
240  */
241 void input_Stop( input_thread_t *p_input )
242 {
243     /* Set die for input and ALL of this childrens (even (grand-)grand-childrens)
244      * It is needed here even if it is done in INPUT_CONTROL_SET_DIE handler to
245      * unlock the control loop */
246     ObjectKillChildrens( VLC_OBJECT(p_input) );
247     input_ControlPush( p_input, INPUT_CONTROL_SET_DIE, NULL );
248 }
249
250 void input_Join( input_thread_t *p_input )
251 {
252     if( p_input->p->is_running )
253         vlc_join( p_input->p->thread, NULL );
254 }
255
256 void input_Release( input_thread_t *p_input )
257 {
258     vlc_object_release( p_input );
259 }
260
261 /**
262  * Close an input
263  *
264  * It does not call input_Stop itself.
265  */
266 void input_Close( input_thread_t *p_input )
267 {
268     input_Join( p_input );
269     input_Release( p_input );
270 }
271
272 /**
273  * Get the item from an input thread
274  * FIXME it does not increase ref count of the item.
275  * if it is used after p_input is destroyed nothing prevent it from
276  * being freed.
277  */
278 input_item_t *input_GetItem( input_thread_t *p_input )
279 {
280     assert( p_input && p_input->p );
281     return p_input->p->p_item;
282 }
283
284 /*****************************************************************************
285  * This function creates a new input, and returns a pointer
286  * to its description. On error, it returns NULL.
287  *
288  * XXX Do not forget to update vlc_input.h if you add new variables.
289  *****************************************************************************/
290 static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item,
291                                const char *psz_header, bool b_quick,
292                                input_resource_t *p_resource )
293 {
294     input_thread_t *p_input = NULL;                 /* thread descriptor */
295     int i;
296
297     /* Allocate descriptor */
298     p_input = vlc_custom_create( p_parent, sizeof( *p_input ), "input" );
299     if( p_input == NULL )
300         return NULL;
301
302     /* Construct a nice name for the input timer */
303     char psz_timer_name[255];
304     char * psz_name = input_item_GetName( p_item );
305     snprintf( psz_timer_name, sizeof(psz_timer_name),
306               "input launching for '%s'", psz_name );
307
308     msg_Dbg( p_input, "Creating an input for '%s'", psz_name);
309
310     free( psz_name );
311
312     p_input->p = calloc( 1, sizeof( input_thread_private_t ) );
313     if( !p_input->p )
314     {
315         vlc_object_release( p_input );
316         return NULL;
317     }
318
319     /* Parse input options */
320     vlc_mutex_lock( &p_item->lock );
321     assert( (int)p_item->optflagc == p_item->i_options );
322     for( i = 0; i < p_item->i_options; i++ )
323         var_OptionParse( VLC_OBJECT(p_input), p_item->ppsz_options[i],
324                          !!(p_item->optflagv[i] & VLC_INPUT_OPTION_TRUSTED) );
325     vlc_mutex_unlock( &p_item->lock );
326
327     p_input->b_preparsing = b_quick;
328     p_input->psz_header = psz_header ? strdup( psz_header ) : NULL;
329
330     /* Init Common fields */
331     p_input->b_eof = false;
332     p_input->p->b_can_pace_control = true;
333     p_input->p->i_start = 0;
334     p_input->p->i_time  = 0;
335     p_input->p->i_stop  = 0;
336     p_input->p->i_run   = 0;
337     p_input->p->i_title = 0;
338     p_input->p->title = NULL;
339     p_input->p->i_title_offset = p_input->p->i_seekpoint_offset = 0;
340     p_input->p->i_state = INIT_S;
341     p_input->p->i_rate = INPUT_RATE_DEFAULT;
342     p_input->p->b_recording = false;
343     memset( &p_input->p->bookmark, 0, sizeof(p_input->p->bookmark) );
344     TAB_INIT( p_input->p->i_bookmark, p_input->p->pp_bookmark );
345     TAB_INIT( p_input->p->i_attachment, p_input->p->attachment );
346     p_input->p->attachment_demux = NULL;
347     p_input->p->p_sout   = NULL;
348     p_input->p->b_out_pace_control = false;
349
350     vlc_gc_incref( p_item ); /* Released in Destructor() */
351     p_input->p->p_item = p_item;
352
353     /* Init Input fields */
354     p_input->p->input.p_demux  = NULL;
355     p_input->p->input.b_title_demux = false;
356     p_input->p->input.i_title  = 0;
357     p_input->p->input.title    = NULL;
358     p_input->p->input.i_title_offset = p_input->p->input.i_seekpoint_offset = 0;
359     p_input->p->input.b_can_pace_control = true;
360     p_input->p->input.b_can_rate_control = true;
361     p_input->p->input.b_rescale_ts = true;
362     p_input->p->input.b_eof = false;
363
364     vlc_mutex_lock( &p_item->lock );
365
366     if( !p_item->p_stats )
367         p_item->p_stats = stats_NewInputStats( p_input );
368
369     /* setup the preparse depth of the item
370      * if we are preparsing, use the i_preparse_depth of the parent item */
371     if( !p_input->b_preparsing )
372     {
373         char *psz_rec = var_InheritString( p_parent, "recursive" );
374
375         if( psz_rec != NULL )
376         {
377             if ( !strcasecmp( psz_rec, "none" ) )
378                 p_item->i_preparse_depth = 0;
379             else if ( !strcasecmp( psz_rec, "collapse" ) )
380                 p_item->i_preparse_depth = 1;
381             else
382                 p_item->i_preparse_depth = -1; /* default is expand */
383             free (psz_rec);
384         } else
385             p_item->i_preparse_depth = -1;
386     }
387
388     vlc_mutex_unlock( &p_item->lock );
389
390     /* No slave */
391     p_input->p->i_slave = 0;
392     p_input->p->slave   = NULL;
393
394     /* */
395     if( p_resource )
396     {
397         p_input->p->p_resource_private = NULL;
398         p_input->p->p_resource = input_resource_Hold( p_resource );
399     }
400     else
401     {
402         p_input->p->p_resource_private = input_resource_New( VLC_OBJECT( p_input ) );
403         p_input->p->p_resource = input_resource_Hold( p_input->p->p_resource_private );
404     }
405     input_resource_SetInput( p_input->p->p_resource, p_input );
406
407     /* Init control buffer */
408     vlc_mutex_init( &p_input->p->lock_control );
409     vlc_cond_init( &p_input->p->wait_control );
410     p_input->p->i_control = 0;
411     p_input->p->is_running = false;
412
413     /* Create Object Variables for private use only */
414     input_ConfigVarInit( p_input );
415
416     /* Create Objects variables for public Get and Set */
417     input_ControlVarInit( p_input );
418
419     /* */
420     if( !p_input->b_preparsing )
421     {
422         char *psz_bookmarks = var_GetNonEmptyString( p_input, "bookmarks" );
423         if( psz_bookmarks )
424         {
425             /* FIXME: have a common cfg parsing routine used by sout and others */
426             char *psz_parser, *psz_start, *psz_end;
427             psz_parser = psz_bookmarks;
428             while( (psz_start = strchr( psz_parser, '{' ) ) )
429             {
430                  seekpoint_t *p_seekpoint;
431                  char backup;
432                  psz_start++;
433                  psz_end = strchr( psz_start, '}' );
434                  if( !psz_end ) break;
435                  psz_parser = psz_end + 1;
436                  backup = *psz_parser;
437                  *psz_parser = 0;
438                  *psz_end = ',';
439
440                  p_seekpoint = vlc_seekpoint_New();
441                  while( (psz_end = strchr( psz_start, ',' ) ) )
442                  {
443                      *psz_end = 0;
444                      if( !strncmp( psz_start, "name=", 5 ) )
445                      {
446                          p_seekpoint->psz_name = strdup(psz_start + 5);
447                      }
448                      else if( !strncmp( psz_start, "bytes=", 6 ) )
449                      {
450                          p_seekpoint->i_byte_offset = atoll(psz_start + 6);
451                      }
452                      else if( !strncmp( psz_start, "time=", 5 ) )
453                      {
454                          p_seekpoint->i_time_offset = atoll(psz_start + 5) *
455                                                         CLOCK_FREQ;
456                      }
457                      psz_start = psz_end + 1;
458                 }
459                 msg_Dbg( p_input, "adding bookmark: %s, bytes=%"PRId64", time=%"PRId64,
460                                   p_seekpoint->psz_name, p_seekpoint->i_byte_offset,
461                                   p_seekpoint->i_time_offset );
462                 input_Control( p_input, INPUT_ADD_BOOKMARK, p_seekpoint );
463                 vlc_seekpoint_Delete( p_seekpoint );
464                 *psz_parser = backup;
465             }
466             free( psz_bookmarks );
467         }
468     }
469
470     /* Remove 'Now playing' info as it is probably outdated */
471     input_item_SetNowPlaying( p_item, NULL );
472     input_item_SetESNowPlaying( p_item, NULL );
473     input_SendEventMeta( p_input );
474
475     /* */
476     if( p_input->b_preparsing )
477         p_input->i_flags |= OBJECT_FLAGS_QUIET | OBJECT_FLAGS_NOINTERACT;
478
479     /* Make sure the interaction option is honored */
480     if( !var_InheritBool( p_input, "interact" ) )
481         p_input->i_flags |= OBJECT_FLAGS_NOINTERACT;
482
483     /* */
484     memset( &p_input->p->counters, 0, sizeof( p_input->p->counters ) );
485     vlc_mutex_init( &p_input->p->counters.counters_lock );
486
487     p_input->p->p_es_out_display = input_EsOutNew( p_input, p_input->p->i_rate );
488     p_input->p->p_es_out = NULL;
489
490     /* Set the destructor when we are sure we are initialized */
491     vlc_object_set_destructor( p_input, (vlc_destructor_t)Destructor );
492
493     return p_input;
494 }
495
496 /**
497  * Input destructor (called when the object's refcount reaches 0).
498  */
499 static void Destructor( input_thread_t * p_input )
500 {
501 #ifndef NDEBUG
502     char * psz_name = input_item_GetName( p_input->p->p_item );
503     msg_Dbg( p_input, "Destroying the input for '%s'", psz_name);
504     free( psz_name );
505 #endif
506
507     if( p_input->p->p_es_out_display )
508         es_out_Delete( p_input->p->p_es_out_display );
509
510     if( p_input->p->p_resource )
511         input_resource_Release( p_input->p->p_resource );
512     if( p_input->p->p_resource_private )
513         input_resource_Release( p_input->p->p_resource_private );
514
515     vlc_gc_decref( p_input->p->p_item );
516
517     vlc_mutex_destroy( &p_input->p->counters.counters_lock );
518
519     for( int i = 0; i < p_input->p->i_control; i++ )
520     {
521         input_control_t *p_ctrl = &p_input->p->control[i];
522         ControlRelease( p_ctrl->i_type, p_ctrl->val );
523     }
524
525     vlc_cond_destroy( &p_input->p->wait_control );
526     vlc_mutex_destroy( &p_input->p->lock_control );
527     free( p_input->p );
528 }
529
530 /*****************************************************************************
531  * Run: main thread loop
532  * This is the "normal" thread that spawns the input processing chain,
533  * reads the stream, cleans up and waits
534  *****************************************************************************/
535 static void *Run( void *obj )
536 {
537     input_thread_t *p_input = (input_thread_t *)obj;
538     const int canc = vlc_savecancel();
539
540     if( !Init( p_input ) )
541     {
542         MainLoop( p_input, true ); /* FIXME it can be wrong (like with VLM) */
543
544         /* Clean up */
545         End( p_input );
546     }
547
548     input_SendEventDead( p_input );
549
550     vlc_restorecancel( canc );
551     return NULL;
552 }
553
554 /*****************************************************************************
555  * Main loop: Fill buffers from access, and demux
556  *****************************************************************************/
557
558 /**
559  * MainLoopDemux
560  * It asks the demuxer to demux some data
561  */
562 static void MainLoopDemux( input_thread_t *p_input, bool *pb_changed, mtime_t i_start_mdate )
563 {
564     int i_ret;
565
566     *pb_changed = false;
567
568     if( ( p_input->p->i_stop > 0 && p_input->p->i_time >= p_input->p->i_stop ) ||
569         ( p_input->p->i_run > 0 && i_start_mdate+p_input->p->i_run < mdate() ) )
570         i_ret = 0; /* EOF */
571     else
572         i_ret = demux_Demux( p_input->p->input.p_demux );
573
574     if( i_ret > 0 )
575     {
576         if( p_input->p->input.p_demux->info.i_update )
577         {
578             if( p_input->p->input.p_demux->info.i_update & INPUT_UPDATE_TITLE_LIST )
579             {
580                 UpdateTitleListfromDemux( p_input );
581                 p_input->p->input.p_demux->info.i_update &= ~INPUT_UPDATE_TITLE_LIST;
582             }
583             if( p_input->p->input.b_title_demux )
584             {
585                 i_ret = UpdateTitleSeekpointFromDemux( p_input );
586                 *pb_changed = true;
587             }
588             UpdateGenericFromDemux( p_input );
589         }
590     }
591
592     if( i_ret == 0 )    /* EOF */
593     {
594         msg_Dbg( p_input, "EOF reached" );
595         p_input->p->input.b_eof = true;
596         es_out_Eos(p_input->p->p_es_out);
597     }
598     else if( i_ret < 0 )
599     {
600         input_ChangeState( p_input, ERROR_S );
601     }
602
603     if( i_ret > 0 && p_input->p->i_slave > 0 )
604         SlaveDemux( p_input );
605 }
606
607 static int MainLoopTryRepeat( input_thread_t *p_input, mtime_t *pi_start_mdate )
608 {
609     int i_repeat = var_GetInteger( p_input, "input-repeat" );
610     if( i_repeat == 0 )
611         return VLC_EGENERIC;
612
613     vlc_value_t val;
614
615     msg_Dbg( p_input, "repeating the same input (%d)", i_repeat );
616     if( i_repeat > 0 )
617     {
618         i_repeat--;
619         var_SetInteger( p_input, "input-repeat", i_repeat );
620     }
621
622     /* Seek to start title/seekpoint */
623     val.i_int = p_input->p->input.i_title_start -
624         p_input->p->input.i_title_offset;
625     if( val.i_int < 0 || val.i_int >= p_input->p->input.i_title )
626         val.i_int = 0;
627     input_ControlPush( p_input,
628                        INPUT_CONTROL_SET_TITLE, &val );
629
630     val.i_int = p_input->p->input.i_seekpoint_start -
631         p_input->p->input.i_seekpoint_offset;
632     if( val.i_int > 0 /* TODO: check upper boundary */ )
633         input_ControlPush( p_input,
634                            INPUT_CONTROL_SET_SEEKPOINT, &val );
635
636     /* Seek to start position */
637     if( p_input->p->i_start > 0 )
638     {
639         val.i_time = p_input->p->i_start;
640         input_ControlPush( p_input, INPUT_CONTROL_SET_TIME, &val );
641     }
642     else
643     {
644         val.f_float = 0.f;
645         input_ControlPush( p_input, INPUT_CONTROL_SET_POSITION, &val );
646     }
647
648     /* */
649     *pi_start_mdate = mdate();
650     return VLC_SUCCESS;
651 }
652
653 /**
654  * Update timing infos and statistics.
655  */
656 static void MainLoopStatistics( input_thread_t *p_input )
657 {
658     double f_position = 0.0;
659     mtime_t i_time = 0;
660     mtime_t i_length = 0;
661
662     /* update input status variables */
663     if( demux_Control( p_input->p->input.p_demux,
664                        DEMUX_GET_POSITION, &f_position ) )
665         f_position = 0.0;
666
667     if( demux_Control( p_input->p->input.p_demux,
668                        DEMUX_GET_TIME, &i_time ) )
669         i_time = 0;
670     p_input->p->i_time = i_time;
671
672     if( demux_Control( p_input->p->input.p_demux,
673                        DEMUX_GET_LENGTH, &i_length ) )
674         i_length = 0;
675
676     es_out_SetTimes( p_input->p->p_es_out, f_position, i_time, i_length );
677
678     /* update current bookmark */
679     vlc_mutex_lock( &p_input->p->p_item->lock );
680     p_input->p->bookmark.i_time_offset = i_time;
681     p_input->p->bookmark.i_byte_offset = -1;
682     vlc_mutex_unlock( &p_input->p->p_item->lock );
683
684     stats_ComputeInputStats( p_input, p_input->p->p_item->p_stats );
685     input_SendEventStatistics( p_input );
686 }
687
688 /**
689  * MainLoop
690  * The main input loop.
691  */
692 static void MainLoop( input_thread_t *p_input, bool b_interactive )
693 {
694     mtime_t i_start_mdate = mdate();
695     mtime_t i_intf_update = 0;
696     mtime_t i_last_seek_mdate = 0;
697     bool b_pause_after_eof = b_interactive &&
698                              var_CreateGetBool( p_input, "play-and-pause" );
699
700     while( vlc_object_alive( p_input ) && !p_input->b_error )
701     {
702         mtime_t i_wakeup = -1;
703         bool b_paused = p_input->p->i_state == PAUSE_S;
704         /* FIXME if p_input->p->i_state == PAUSE_S the access/access_demux
705          * is paused -> this may cause problem with some of them
706          * The same problem can be seen when seeking while paused */
707         if( b_paused )
708             b_paused = !es_out_GetBuffering( p_input->p->p_es_out ) || p_input->p->input.b_eof;
709
710         if( !b_paused )
711         {
712             if( !p_input->p->input.b_eof )
713             {
714                 bool b_force_update = false;
715
716                 MainLoopDemux( p_input, &b_force_update, i_start_mdate );
717                 i_wakeup = es_out_GetWakeup( p_input->p->p_es_out );
718
719                 if( b_force_update )
720                     i_intf_update = 0;
721             }
722             else if( !es_out_GetEmpty( p_input->p->p_es_out ) )
723             {
724                 msg_Dbg( p_input, "waiting decoder fifos to empty" );
725                 i_wakeup = mdate() + INPUT_IDLE_SLEEP;
726             }
727             /* Pause after eof only if the input is pausable.
728              * This way we won't trigger timeshifting for nothing */
729             else if( b_pause_after_eof && p_input->p->b_can_pause )
730             {
731                 vlc_value_t val = { .i_int = PAUSE_S };
732
733                 msg_Dbg( p_input, "pausing at EOF (pause after each)");
734                 Control( p_input, INPUT_CONTROL_SET_STATE, val );
735
736                 b_paused = true;
737             }
738             else
739             {
740                 if( MainLoopTryRepeat( p_input, &i_start_mdate ) )
741                     break;
742                 b_pause_after_eof = var_GetBool( p_input, "play-and-pause" );
743             }
744
745             /* Update interface and statistics */
746             mtime_t now = mdate();
747             if( now >= i_intf_update )
748             {
749                 MainLoopStatistics( p_input );
750                 i_intf_update = now + INT64_C(250000);
751             }
752         }
753
754         /* Handle control */
755         for( ;; )
756         {
757             mtime_t i_deadline = i_wakeup;
758
759             /* Postpone seeking until ES buffering is complete or at most
760              * 125 ms. */
761             bool b_postpone = es_out_GetBuffering( p_input->p->p_es_out )
762                             && !p_input->p->input.b_eof;
763             if( b_postpone )
764             {
765                 mtime_t now = mdate();
766
767                 /* Recheck ES buffer level every 20 ms when seeking */
768                 if( now < i_last_seek_mdate + INT64_C(125000)
769                  && (i_deadline < 0 || i_deadline > now + INT64_C(20000)) )
770                     i_deadline = now + INT64_C(20000);
771                 else
772                     b_postpone = false;
773             }
774
775             int i_type;
776             vlc_value_t val;
777
778             if( ControlPop( p_input, &i_type, &val, i_deadline, b_postpone ) )
779             {
780                 if( b_postpone )
781                     continue;
782                 break; /* Wake-up time reached */
783             }
784
785 #ifndef NDEBUG
786             msg_Dbg( p_input, "control type=%d", i_type );
787 #endif
788             if( Control( p_input, i_type, val ) )
789             {
790                 if( ControlIsSeekRequest( i_type ) )
791                     i_last_seek_mdate = mdate();
792                 i_intf_update = 0;
793             }
794
795             /* Update the wakeup time */
796             if( i_wakeup != 0 )
797                 i_wakeup = es_out_GetWakeup( p_input->p->p_es_out );
798         }
799     }
800
801     if( !p_input->b_error )
802         input_ChangeState( p_input, END_S );
803 }
804
805 static void InitStatistics( input_thread_t * p_input )
806 {
807     if( p_input->b_preparsing ) return;
808
809     /* Prepare statistics */
810 #define INIT_COUNTER( c, compute ) p_input->p->counters.p_##c = \
811  stats_CounterCreate( STATS_##compute);
812     if( libvlc_stats( p_input ) )
813     {
814         INIT_COUNTER( read_bytes, COUNTER );
815         INIT_COUNTER( read_packets, COUNTER );
816         INIT_COUNTER( demux_read, COUNTER );
817         INIT_COUNTER( input_bitrate, DERIVATIVE );
818         INIT_COUNTER( demux_bitrate, DERIVATIVE );
819         INIT_COUNTER( demux_corrupted, COUNTER );
820         INIT_COUNTER( demux_discontinuity, COUNTER );
821         INIT_COUNTER( played_abuffers, COUNTER );
822         INIT_COUNTER( lost_abuffers, COUNTER );
823         INIT_COUNTER( displayed_pictures, COUNTER );
824         INIT_COUNTER( lost_pictures, COUNTER );
825         INIT_COUNTER( decoded_audio, COUNTER );
826         INIT_COUNTER( decoded_video, COUNTER );
827         INIT_COUNTER( decoded_sub, COUNTER );
828         p_input->p->counters.p_sout_send_bitrate = NULL;
829         p_input->p->counters.p_sout_sent_packets = NULL;
830         p_input->p->counters.p_sout_sent_bytes = NULL;
831     }
832 }
833
834 #ifdef ENABLE_SOUT
835 static int InitSout( input_thread_t * p_input )
836 {
837     if( p_input->b_preparsing )
838         return VLC_SUCCESS;
839
840     /* Find a usable sout and attach it to p_input */
841     char *psz = var_GetNonEmptyString( p_input, "sout" );
842     if( psz && strncasecmp( p_input->p->p_item->psz_uri, "vlc:", 4 ) )
843     {
844         p_input->p->p_sout  = input_resource_RequestSout( p_input->p->p_resource, NULL, psz );
845         if( !p_input->p->p_sout )
846         {
847             input_ChangeState( p_input, ERROR_S );
848             msg_Err( p_input, "cannot start stream output instance, " \
849                               "aborting" );
850             free( psz );
851             return VLC_EGENERIC;
852         }
853         if( libvlc_stats( p_input ) )
854         {
855             INIT_COUNTER( sout_sent_packets, COUNTER );
856             INIT_COUNTER( sout_sent_bytes, COUNTER );
857             INIT_COUNTER( sout_send_bitrate, DERIVATIVE );
858         }
859     }
860     else
861     {
862         input_resource_RequestSout( p_input->p->p_resource, NULL, NULL );
863     }
864     free( psz );
865
866     return VLC_SUCCESS;
867 }
868 #endif
869
870 static void InitTitle( input_thread_t * p_input )
871 {
872     input_source_t *p_master = &p_input->p->input;
873
874     if( p_input->b_preparsing )
875         return;
876
877     vlc_mutex_lock( &p_input->p->p_item->lock );
878     /* Create global title (from master) */
879     p_input->p->i_title = p_master->i_title;
880     p_input->p->title   = p_master->title;
881     p_input->p->i_title_offset = p_master->i_title_offset;
882     p_input->p->i_seekpoint_offset = p_master->i_seekpoint_offset;
883     if( p_input->p->i_title > 0 )
884     {
885         /* Setup variables */
886         input_ControlVarNavigation( p_input );
887         input_SendEventTitle( p_input, 0 );
888     }
889
890     /* Global flag */
891     p_input->p->b_can_pace_control    = p_master->b_can_pace_control;
892     p_input->p->b_can_pause        = p_master->b_can_pause;
893     p_input->p->b_can_rate_control = p_master->b_can_rate_control;
894     vlc_mutex_unlock( &p_input->p->p_item->lock );
895 }
896
897 static void StartTitle( input_thread_t * p_input )
898 {
899     vlc_value_t val;
900
901     /* Start title/chapter */
902     val.i_int = p_input->p->input.i_title_start -
903                 p_input->p->input.i_title_offset;
904     if( val.i_int > 0 && val.i_int < p_input->p->input.i_title )
905         input_ControlPush( p_input, INPUT_CONTROL_SET_TITLE, &val );
906
907     val.i_int = p_input->p->input.i_seekpoint_start -
908                 p_input->p->input.i_seekpoint_offset;
909     if( val.i_int > 0 /* TODO: check upper boundary */ )
910         input_ControlPush( p_input, INPUT_CONTROL_SET_SEEKPOINT, &val );
911
912     /* Start/stop/run time */
913     p_input->p->i_start = llroundf(1000000.f
914                                      * var_GetFloat( p_input, "start-time" ));
915     p_input->p->i_stop  = llroundf(1000000.f
916                                      * var_GetFloat( p_input, "stop-time" ));
917     p_input->p->i_run   = llroundf(1000000.f
918                                      * var_GetFloat( p_input, "run-time" ));
919     if( p_input->p->i_run < 0 )
920     {
921         msg_Warn( p_input, "invalid run-time ignored" );
922         p_input->p->i_run = 0;
923     }
924
925     if( p_input->p->i_start > 0 )
926     {
927         vlc_value_t s;
928
929         msg_Dbg( p_input, "starting at time: %ds",
930                  (int)( p_input->p->i_start / CLOCK_FREQ ) );
931
932         s.i_time = p_input->p->i_start;
933         input_ControlPush( p_input, INPUT_CONTROL_SET_TIME, &s );
934     }
935     if( p_input->p->i_stop > 0 && p_input->p->i_stop <= p_input->p->i_start )
936     {
937         msg_Warn( p_input, "invalid stop-time ignored" );
938         p_input->p->i_stop = 0;
939     }
940     p_input->p->b_fast_seek = var_GetBool( p_input, "input-fast-seek" );
941 }
942
943 static void LoadSubtitles( input_thread_t *p_input )
944 {
945     /* Load subtitles */
946     /* Get fps and set it if not already set */
947     const float f_fps = p_input->p->f_fps;
948     if( f_fps > 1.f )
949     {
950         var_Create( p_input, "sub-original-fps", VLC_VAR_FLOAT );
951         var_SetFloat( p_input, "sub-original-fps", f_fps );
952
953         float f_requested_fps = var_CreateGetFloat( p_input, "sub-fps" );
954         if( f_requested_fps != f_fps )
955         {
956             var_Create( p_input, "sub-fps", VLC_VAR_FLOAT|
957                                             VLC_VAR_DOINHERIT );
958             var_SetFloat( p_input, "sub-fps", f_requested_fps );
959         }
960     }
961
962     const int i_delay = var_CreateGetInteger( p_input, "sub-delay" );
963     if( i_delay != 0 )
964         var_SetTime( p_input, "spu-delay", (mtime_t)i_delay * 100000 );
965
966     /* Look for and add subtitle files */
967     unsigned i_flags = SUB_FORCED;
968
969     char *psz_subtitle = var_GetNonEmptyString( p_input, "sub-file" );
970     if( psz_subtitle != NULL )
971     {
972         msg_Dbg( p_input, "forced subtitle: %s", psz_subtitle );
973         input_SubtitleFileAdd( p_input, psz_subtitle, i_flags );
974         i_flags = SUB_NOFLAG;
975     }
976
977     if( var_GetBool( p_input, "sub-autodetect-file" ) )
978     {
979         char *psz_autopath = var_GetNonEmptyString( p_input, "sub-autodetect-path" );
980         char **ppsz_subs = subtitles_Detect( p_input, psz_autopath,
981                                              p_input->p->p_item->psz_uri );
982         free( psz_autopath );
983
984         for( int i = 0; ppsz_subs && ppsz_subs[i]; i++ )
985         {
986             if( !psz_subtitle || strcmp( psz_subtitle, ppsz_subs[i] ) )
987             {
988                 i_flags |= SUB_CANFAIL;
989                 input_SubtitleFileAdd( p_input, ppsz_subs[i], i_flags );
990                 i_flags = SUB_NOFLAG;
991             }
992
993             free( ppsz_subs[i] );
994         }
995         free( ppsz_subs );
996     }
997     free( psz_subtitle );
998
999     /* Load subtitles from attachments */
1000     int i_attachment = 0;
1001     input_attachment_t **pp_attachment = NULL;
1002
1003     vlc_mutex_lock( &p_input->p->p_item->lock );
1004     for( int i = 0; i < p_input->p->i_attachment; i++ )
1005     {
1006         const input_attachment_t *a = p_input->p->attachment[i];
1007         if( !strcmp( a->psz_mime, "application/x-srt" ) )
1008             TAB_APPEND( i_attachment, pp_attachment,
1009                         vlc_input_attachment_New( a->psz_name, NULL,
1010                                                   a->psz_description, NULL, 0 ) );
1011     }
1012     vlc_mutex_unlock( &p_input->p->p_item->lock );
1013
1014     if( i_attachment > 0 )
1015         var_Create( p_input, "sub-description", VLC_VAR_STRING );
1016     for( int i = 0; i < i_attachment; i++ )
1017     {
1018         input_attachment_t *a = pp_attachment[i];
1019         if( !a )
1020             continue;
1021         char *psz_mrl;
1022         if( a->psz_name[i] &&
1023             asprintf( &psz_mrl, "attachment://%s", a->psz_name ) >= 0 )
1024         {
1025             var_SetString( p_input, "sub-description", a->psz_description ? a->psz_description : "");
1026
1027             input_SubtitleAdd( p_input, psz_mrl, i_flags );
1028
1029             i_flags = SUB_NOFLAG;
1030             free( psz_mrl );
1031         }
1032         vlc_input_attachment_Delete( a );
1033     }
1034     free( pp_attachment );
1035     if( i_attachment > 0 )
1036         var_Destroy( p_input, "sub-description" );
1037 }
1038
1039 static void LoadSlaves( input_thread_t *p_input )
1040 {
1041     char *psz = var_GetNonEmptyString( p_input, "input-slave" );
1042     if( !psz )
1043         return;
1044
1045     char *psz_org = psz;
1046     while( psz && *psz )
1047     {
1048         while( *psz == ' ' || *psz == '#' )
1049             psz++;
1050
1051         char *psz_delim = strchr( psz, '#' );
1052         if( psz_delim )
1053             *psz_delim++ = '\0';
1054
1055         if( *psz == 0 )
1056             break;
1057
1058         char *uri = strstr(psz, "://")
1059                                    ? strdup( psz ) : vlc_path2uri( psz, NULL );
1060         psz = psz_delim;
1061         if( uri == NULL )
1062             continue;
1063         msg_Dbg( p_input, "adding slave input '%s'", uri );
1064
1065         input_source_t *p_slave = InputSourceNew( p_input );
1066         if( p_slave && !InputSourceInit( p_input, p_slave, uri, NULL, false ) )
1067             TAB_APPEND( p_input->p->i_slave, p_input->p->slave, p_slave );
1068         else
1069             free( p_slave );
1070         free( uri );
1071     }
1072     free( psz_org );
1073 }
1074
1075 static void UpdatePtsDelay( input_thread_t *p_input )
1076 {
1077     input_thread_private_t *p_sys = p_input->p;
1078
1079     /* Get max pts delay from input source */
1080     mtime_t i_pts_delay = p_sys->input.i_pts_delay;
1081     for( int i = 0; i < p_sys->i_slave; i++ )
1082         i_pts_delay = __MAX( i_pts_delay, p_sys->slave[i]->i_pts_delay );
1083
1084     if( i_pts_delay < 0 )
1085         i_pts_delay = 0;
1086
1087     /* Take care of audio/spu delay */
1088     const mtime_t i_audio_delay = var_GetTime( p_input, "audio-delay" );
1089     const mtime_t i_spu_delay   = var_GetTime( p_input, "spu-delay" );
1090     const mtime_t i_extra_delay = __MIN( i_audio_delay, i_spu_delay );
1091     if( i_extra_delay < 0 )
1092         i_pts_delay -= i_extra_delay;
1093
1094     /* Update cr_average depending on the caching */
1095     const int i_cr_average = var_GetInteger( p_input, "cr-average" ) * i_pts_delay / DEFAULT_PTS_DELAY;
1096
1097     /* */
1098     es_out_SetDelay( p_input->p->p_es_out_display, AUDIO_ES, i_audio_delay );
1099     es_out_SetDelay( p_input->p->p_es_out_display, SPU_ES, i_spu_delay );
1100     es_out_SetJitter( p_input->p->p_es_out, i_pts_delay, 0, i_cr_average );
1101 }
1102
1103 static void InitPrograms( input_thread_t * p_input )
1104 {
1105     int i_es_out_mode;
1106     vlc_list_t list;
1107
1108     /* Compute correct pts_delay */
1109     UpdatePtsDelay( p_input );
1110
1111     /* Set up es_out */
1112     i_es_out_mode = ES_OUT_MODE_AUTO;
1113     if( p_input->p->p_sout )
1114     {
1115         char *prgms;
1116
1117         if( (prgms = var_GetNonEmptyString( p_input, "programs" )) != NULL )
1118         {
1119             char *buf;
1120
1121             TAB_INIT( list.i_count, list.p_values );
1122             for( const char *prgm = strtok_r( prgms, ",", &buf );
1123                  prgm != NULL;
1124                  prgm = strtok_r( NULL, ",", &buf ) )
1125             {
1126                 vlc_value_t val = { .i_int = atoi( prgm ) };
1127                 INSERT_ELEM( list.p_values, list.i_count, list.i_count, val );
1128             }
1129
1130             if( list.i_count > 0 )
1131                 i_es_out_mode = ES_OUT_MODE_PARTIAL;
1132                 /* Note : we should remove the "program" callback. */
1133
1134             free( prgms );
1135         }
1136         else if( var_GetBool( p_input, "sout-all" ) )
1137         {
1138             i_es_out_mode = ES_OUT_MODE_ALL;
1139         }
1140     }
1141     es_out_SetMode( p_input->p->p_es_out, i_es_out_mode );
1142
1143     /* Inform the demuxer about waited group (needed only for DVB) */
1144     if( i_es_out_mode == ES_OUT_MODE_ALL )
1145     {
1146         demux_Control( p_input->p->input.p_demux, DEMUX_SET_GROUP, -1, NULL );
1147     }
1148     else if( i_es_out_mode == ES_OUT_MODE_PARTIAL )
1149     {
1150         demux_Control( p_input->p->input.p_demux, DEMUX_SET_GROUP, -1,
1151                        &list );
1152         TAB_CLEAN( list.i_count, list.p_values );
1153     }
1154     else
1155     {
1156         demux_Control( p_input->p->input.p_demux, DEMUX_SET_GROUP,
1157                        es_out_GetGroupForced( p_input->p->p_es_out ), NULL );
1158     }
1159 }
1160
1161 static int Init( input_thread_t * p_input )
1162 {
1163     for( int i = 0; i < p_input->p->p_item->i_options; i++ )
1164     {
1165         if( !strncmp( p_input->p->p_item->ppsz_options[i], "meta-file", 9 ) )
1166         {
1167             msg_Dbg( p_input, "Input is a meta file: disabling unneeded options" );
1168             var_SetString( p_input, "sout", "" );
1169             var_SetBool( p_input, "sout-all", false );
1170             var_SetString( p_input, "input-slave", "" );
1171             var_SetInteger( p_input, "input-repeat", 0 );
1172             var_SetString( p_input, "sub-file", "" );
1173             var_SetBool( p_input, "sub-autodetect-file", false );
1174         }
1175     }
1176
1177     InitStatistics( p_input );
1178 #ifdef ENABLE_SOUT
1179     if( InitSout( p_input ) )
1180         goto error;
1181 #endif
1182
1183     /* Create es out */
1184     p_input->p->p_es_out = input_EsOutTimeshiftNew( p_input, p_input->p->p_es_out_display, p_input->p->i_rate );
1185
1186     /* */
1187     input_ChangeState( p_input, OPENING_S );
1188     input_SendEventCache( p_input, 0.0 );
1189
1190     /* */
1191     if( InputSourceInit( p_input, &p_input->p->input,
1192                          p_input->p->p_item->psz_uri, NULL, false ) )
1193     {
1194         goto error;
1195     }
1196
1197     InitTitle( p_input );
1198
1199     /* Load master infos */
1200     /* Init length */
1201     mtime_t i_length;
1202     if( demux_Control( p_input->p->input.p_demux, DEMUX_GET_LENGTH,
1203                          &i_length ) )
1204         i_length = 0;
1205     if( i_length <= 0 )
1206         i_length = input_item_GetDuration( p_input->p->p_item );
1207     input_SendEventLength( p_input, i_length );
1208
1209     input_SendEventPosition( p_input, 0.0, 0 );
1210
1211     if( !p_input->b_preparsing )
1212     {
1213         StartTitle( p_input );
1214         LoadSubtitles( p_input );
1215         LoadSlaves( p_input );
1216         InitPrograms( p_input );
1217
1218         double f_rate = var_InheritFloat( p_input, "rate" );
1219         if( f_rate != 0.0 && f_rate != 1.0 )
1220         {
1221             vlc_value_t val = { .i_int = INPUT_RATE_DEFAULT / f_rate };
1222             input_ControlPush( p_input, INPUT_CONTROL_SET_RATE, &val );
1223         }
1224     }
1225
1226     if( !p_input->b_preparsing && p_input->p->p_sout )
1227     {
1228         p_input->p->b_out_pace_control = (p_input->p->p_sout->i_out_pace_nocontrol > 0);
1229
1230         if( p_input->p->b_can_pace_control && p_input->p->b_out_pace_control )
1231         {
1232             /* We don't want a high input priority here or we'll
1233              * end-up sucking up all the CPU time */
1234             vlc_set_priority( p_input->p->thread, VLC_THREAD_PRIORITY_LOW );
1235         }
1236
1237         msg_Dbg( p_input, "starting in %s mode",
1238                  p_input->p->b_out_pace_control ? "async" : "sync" );
1239     }
1240
1241     vlc_meta_t *p_meta = vlc_meta_New();
1242     if( p_meta != NULL )
1243     {
1244         /* Get meta data from users */
1245         InputMetaUser( p_input, p_meta );
1246
1247         /* Get meta data from master input */
1248         InputSourceMeta( p_input, &p_input->p->input, p_meta );
1249
1250         /* And from slave */
1251         for( int i = 0; i < p_input->p->i_slave; i++ )
1252             InputSourceMeta( p_input, p_input->p->slave[i], p_meta );
1253
1254         es_out_ControlSetMeta( p_input->p->p_es_out, p_meta );
1255         vlc_meta_Delete( p_meta );
1256     }
1257
1258     msg_Dbg( p_input, "`%s' successfully opened",
1259              p_input->p->p_item->psz_uri );
1260
1261     /* initialization is complete */
1262     input_ChangeState( p_input, PLAYING_S );
1263
1264     return VLC_SUCCESS;
1265
1266 error:
1267     input_ChangeState( p_input, ERROR_S );
1268
1269     if( p_input->p->p_es_out )
1270         es_out_Delete( p_input->p->p_es_out );
1271     es_out_SetMode( p_input->p->p_es_out_display, ES_OUT_MODE_END );
1272     if( p_input->p->p_resource )
1273     {
1274         if( p_input->p->p_sout )
1275             input_resource_RequestSout( p_input->p->p_resource,
1276                                          p_input->p->p_sout, NULL );
1277         input_resource_SetInput( p_input->p->p_resource, NULL );
1278         if( p_input->p->p_resource_private )
1279             input_resource_Terminate( p_input->p->p_resource_private );
1280     }
1281
1282     if( !p_input->b_preparsing && libvlc_stats( p_input ) )
1283     {
1284 #define EXIT_COUNTER( c ) do { if( p_input->p->counters.p_##c ) \
1285                                    stats_CounterClean( p_input->p->counters.p_##c );\
1286                                p_input->p->counters.p_##c = NULL; } while(0)
1287         EXIT_COUNTER( read_bytes );
1288         EXIT_COUNTER( read_packets );
1289         EXIT_COUNTER( demux_read );
1290         EXIT_COUNTER( input_bitrate );
1291         EXIT_COUNTER( demux_bitrate );
1292         EXIT_COUNTER( demux_corrupted );
1293         EXIT_COUNTER( demux_discontinuity );
1294         EXIT_COUNTER( played_abuffers );
1295         EXIT_COUNTER( lost_abuffers );
1296         EXIT_COUNTER( displayed_pictures );
1297         EXIT_COUNTER( lost_pictures );
1298         EXIT_COUNTER( decoded_audio );
1299         EXIT_COUNTER( decoded_video );
1300         EXIT_COUNTER( decoded_sub );
1301
1302         if( p_input->p->p_sout )
1303         {
1304             EXIT_COUNTER( sout_sent_packets );
1305             EXIT_COUNTER( sout_sent_bytes );
1306             EXIT_COUNTER( sout_send_bitrate );
1307         }
1308 #undef EXIT_COUNTER
1309     }
1310
1311     /* Mark them deleted */
1312     p_input->p->input.p_demux = NULL;
1313     p_input->p->p_es_out = NULL;
1314     p_input->p->p_sout = NULL;
1315
1316     return VLC_EGENERIC;
1317 }
1318
1319 /*****************************************************************************
1320  * End: end the input thread
1321  *****************************************************************************/
1322 static void End( input_thread_t * p_input )
1323 {
1324     int i;
1325
1326     /* We are at the end */
1327     input_ChangeState( p_input, END_S );
1328
1329     /* Clean control variables */
1330     input_ControlVarStop( p_input );
1331
1332     /* Stop es out activity */
1333     es_out_SetMode( p_input->p->p_es_out, ES_OUT_MODE_NONE );
1334
1335     /* Clean up master */
1336     InputSourceClean( &p_input->p->input );
1337
1338     /* Delete slave */
1339     for( i = 0; i < p_input->p->i_slave; i++ )
1340     {
1341         InputSourceClean( p_input->p->slave[i] );
1342         free( p_input->p->slave[i] );
1343     }
1344     free( p_input->p->slave );
1345
1346     /* Unload all modules */
1347     if( p_input->p->p_es_out )
1348         es_out_Delete( p_input->p->p_es_out );
1349     es_out_SetMode( p_input->p->p_es_out_display, ES_OUT_MODE_END );
1350
1351     if( !p_input->b_preparsing )
1352     {
1353 #define CL_CO( c ) stats_CounterClean( p_input->p->counters.p_##c ); p_input->p->counters.p_##c = NULL;
1354         if( libvlc_stats( p_input ) )
1355         {
1356             /* make sure we are up to date */
1357             stats_ComputeInputStats( p_input, p_input->p->p_item->p_stats );
1358             CL_CO( read_bytes );
1359             CL_CO( read_packets );
1360             CL_CO( demux_read );
1361             CL_CO( input_bitrate );
1362             CL_CO( demux_bitrate );
1363             CL_CO( demux_corrupted );
1364             CL_CO( demux_discontinuity );
1365             CL_CO( played_abuffers );
1366             CL_CO( lost_abuffers );
1367             CL_CO( displayed_pictures );
1368             CL_CO( lost_pictures );
1369             CL_CO( decoded_audio) ;
1370             CL_CO( decoded_video );
1371             CL_CO( decoded_sub) ;
1372         }
1373
1374         /* Close optional stream output instance */
1375         if( p_input->p->p_sout )
1376         {
1377             CL_CO( sout_sent_packets );
1378             CL_CO( sout_sent_bytes );
1379             CL_CO( sout_send_bitrate );
1380         }
1381 #undef CL_CO
1382     }
1383
1384     vlc_mutex_lock( &p_input->p->p_item->lock );
1385     if( p_input->p->i_attachment > 0 )
1386     {
1387         for( i = 0; i < p_input->p->i_attachment; i++ )
1388             vlc_input_attachment_Delete( p_input->p->attachment[i] );
1389         TAB_CLEAN( p_input->p->i_attachment, p_input->p->attachment );
1390         free( p_input->p->attachment_demux);
1391         p_input->p->attachment_demux = NULL;
1392     }
1393     vlc_mutex_unlock( &p_input->p->p_item->lock );
1394
1395     /* */
1396     input_resource_RequestSout( p_input->p->p_resource,
1397                                  p_input->p->p_sout, NULL );
1398     input_resource_SetInput( p_input->p->p_resource, NULL );
1399     if( p_input->p->p_resource_private )
1400         input_resource_Terminate( p_input->p->p_resource_private );
1401 }
1402
1403 /*****************************************************************************
1404  * Control
1405  *****************************************************************************/
1406 void input_ControlPush( input_thread_t *p_input,
1407                         int i_type, vlc_value_t *p_val )
1408 {
1409     vlc_mutex_lock( &p_input->p->lock_control );
1410     if( i_type == INPUT_CONTROL_SET_DIE )
1411     {
1412         /* Special case, empty the control */
1413         for( int i = 0; i < p_input->p->i_control; i++ )
1414         {
1415             input_control_t *p_ctrl = &p_input->p->control[i];
1416             ControlRelease( p_ctrl->i_type, p_ctrl->val );
1417         }
1418         p_input->p->i_control = 0;
1419     }
1420
1421     if( p_input->p->i_control >= INPUT_CONTROL_FIFO_SIZE )
1422     {
1423         msg_Err( p_input, "input control fifo overflow, trashing type=%d",
1424                  i_type );
1425         if( p_val )
1426             ControlRelease( i_type, *p_val );
1427     }
1428     else
1429     {
1430         input_control_t c;
1431         c.i_type = i_type;
1432         if( p_val )
1433             c.val = *p_val;
1434         else
1435             memset( &c.val, 0, sizeof(c.val) );
1436
1437         p_input->p->control[p_input->p->i_control++] = c;
1438     }
1439     vlc_cond_signal( &p_input->p->wait_control );
1440     vlc_mutex_unlock( &p_input->p->lock_control );
1441 }
1442
1443 static int ControlGetReducedIndexLocked( input_thread_t *p_input )
1444 {
1445     const int i_lt = p_input->p->control[0].i_type;
1446     int i;
1447     for( i = 1; i < p_input->p->i_control; i++ )
1448     {
1449         const int i_ct = p_input->p->control[i].i_type;
1450
1451         if( i_lt == i_ct &&
1452             ( i_ct == INPUT_CONTROL_SET_STATE ||
1453               i_ct == INPUT_CONTROL_SET_RATE ||
1454               i_ct == INPUT_CONTROL_SET_POSITION ||
1455               i_ct == INPUT_CONTROL_SET_TIME ||
1456               i_ct == INPUT_CONTROL_SET_PROGRAM ||
1457               i_ct == INPUT_CONTROL_SET_TITLE ||
1458               i_ct == INPUT_CONTROL_SET_SEEKPOINT ||
1459               i_ct == INPUT_CONTROL_SET_BOOKMARK ) )
1460         {
1461             continue;
1462         }
1463         else
1464         {
1465             /* TODO but that's not that important
1466                 - merge SET_X with SET_X_CMD
1467                 - ignore SET_SEEKPOINT/SET_POSITION/SET_TIME before a SET_TITLE
1468                 - ignore SET_SEEKPOINT/SET_POSITION/SET_TIME before another among them
1469                 - ?
1470                 */
1471             break;
1472         }
1473     }
1474     return i - 1;
1475 }
1476
1477
1478 static inline int ControlPop( input_thread_t *p_input,
1479                               int *pi_type, vlc_value_t *p_val,
1480                               mtime_t i_deadline, bool b_postpone_seek )
1481 {
1482     input_thread_private_t *p_sys = p_input->p;
1483
1484     vlc_mutex_lock( &p_sys->lock_control );
1485     while( p_sys->i_control <= 0 ||
1486            ( b_postpone_seek && ControlIsSeekRequest( p_sys->control[0].i_type ) ) )
1487     {
1488         if( !vlc_object_alive( p_input ) )
1489         {
1490             vlc_mutex_unlock( &p_sys->lock_control );
1491             return VLC_EGENERIC;
1492         }
1493
1494         if( i_deadline >= 0 )
1495         {
1496             if( vlc_cond_timedwait( &p_sys->wait_control, &p_sys->lock_control,
1497                                     i_deadline ) )
1498             {
1499                 vlc_mutex_unlock( &p_sys->lock_control );
1500                 return VLC_EGENERIC;
1501             }
1502         }
1503         else
1504             vlc_cond_wait( &p_sys->wait_control, &p_sys->lock_control );
1505     }
1506
1507     /* */
1508     const int i_index = ControlGetReducedIndexLocked( p_input );
1509
1510     /* */
1511     *pi_type = p_sys->control[i_index].i_type;
1512     *p_val   = p_sys->control[i_index].val;
1513
1514     p_sys->i_control -= i_index + 1;
1515     if( p_sys->i_control > 0 )
1516         memmove( &p_sys->control[0], &p_sys->control[i_index+1],
1517                  sizeof(*p_sys->control) * p_sys->i_control );
1518     vlc_mutex_unlock( &p_sys->lock_control );
1519
1520     return VLC_SUCCESS;
1521 }
1522 static bool ControlIsSeekRequest( int i_type )
1523 {
1524     switch( i_type )
1525     {
1526     case INPUT_CONTROL_SET_POSITION:
1527     case INPUT_CONTROL_SET_TIME:
1528     case INPUT_CONTROL_SET_TITLE:
1529     case INPUT_CONTROL_SET_TITLE_NEXT:
1530     case INPUT_CONTROL_SET_TITLE_PREV:
1531     case INPUT_CONTROL_SET_SEEKPOINT:
1532     case INPUT_CONTROL_SET_SEEKPOINT_NEXT:
1533     case INPUT_CONTROL_SET_SEEKPOINT_PREV:
1534     case INPUT_CONTROL_SET_BOOKMARK:
1535     case INPUT_CONTROL_NAV_ACTIVATE:
1536     case INPUT_CONTROL_NAV_UP:
1537     case INPUT_CONTROL_NAV_DOWN:
1538     case INPUT_CONTROL_NAV_LEFT:
1539     case INPUT_CONTROL_NAV_RIGHT:
1540         return true;
1541     default:
1542         return false;
1543     }
1544 }
1545
1546 static void ControlRelease( int i_type, vlc_value_t val )
1547 {
1548     switch( i_type )
1549     {
1550     case INPUT_CONTROL_ADD_SUBTITLE:
1551     case INPUT_CONTROL_ADD_SLAVE:
1552         free( val.psz_string );
1553         break;
1554
1555     default:
1556         break;
1557     }
1558 }
1559
1560 /* Pause input */
1561 static void ControlPause( input_thread_t *p_input, mtime_t i_control_date )
1562 {
1563     int i_ret = VLC_SUCCESS;
1564     int i_state = PAUSE_S;
1565
1566     if( p_input->p->b_can_pause )
1567     {
1568         demux_t *p_demux = p_input->p->input.p_demux;
1569
1570         if( p_demux->s != NULL )
1571             i_ret = stream_Control( p_demux->s, STREAM_SET_PAUSE_STATE, true );
1572         else
1573             i_ret = demux_Control( p_demux, DEMUX_SET_PAUSE_STATE, true );
1574
1575         if( i_ret )
1576         {
1577             msg_Warn( p_input, "cannot set pause state" );
1578             return;
1579         }
1580     }
1581
1582     /* */
1583     i_ret = es_out_SetPauseState( p_input->p->p_es_out,
1584                                   p_input->p->b_can_pause, true,
1585                                   i_control_date );
1586     if( i_ret )
1587     {
1588         msg_Warn( p_input, "cannot set pause state at es_out level" );
1589         return;
1590     }
1591
1592     /* Switch to new state */
1593     input_ChangeState( p_input, i_state );
1594 }
1595
1596 static void ControlUnpause( input_thread_t *p_input, mtime_t i_control_date )
1597 {
1598     int i_ret = VLC_SUCCESS;
1599
1600     if( p_input->p->b_can_pause )
1601     {
1602         demux_t *p_demux = p_input->p->input.p_demux;
1603
1604         if( p_demux->s != NULL )
1605             i_ret = stream_Control( p_demux->s, STREAM_SET_PAUSE_STATE, false );
1606         else
1607             i_ret = demux_Control( p_demux, DEMUX_SET_PAUSE_STATE, false );
1608         if( i_ret )
1609         {
1610             /* FIXME What to do ? */
1611             msg_Warn( p_input, "cannot unset pause -> EOF" );
1612             input_ControlPush( p_input, INPUT_CONTROL_SET_DIE, NULL );
1613         }
1614     }
1615
1616     /* Switch to play */
1617     input_ChangeState( p_input, PLAYING_S );
1618
1619     /* */
1620     if( !i_ret )
1621         es_out_SetPauseState( p_input->p->p_es_out, false, false, i_control_date );
1622 }
1623
1624 static bool Control( input_thread_t *p_input,
1625                      int i_type, vlc_value_t val )
1626 {
1627     const mtime_t i_control_date = mdate();
1628     /* FIXME b_force_update is abused, it should be carefully checked */
1629     bool b_force_update = false;
1630
1631     if( !p_input )
1632         return b_force_update;
1633
1634     switch( i_type )
1635     {
1636         case INPUT_CONTROL_SET_DIE:
1637             msg_Dbg( p_input, "control: stopping input" );
1638
1639             /* Mark all submodules to die */
1640             ObjectKillChildrens( VLC_OBJECT(p_input) );
1641             break;
1642
1643         case INPUT_CONTROL_SET_POSITION:
1644         {
1645             if( p_input->p->b_recording )
1646             {
1647                 msg_Err( p_input, "INPUT_CONTROL_SET_POSITION(_OFFSET) ignored while recording" );
1648                 break;
1649             }
1650
1651             float f_pos = val.f_float;
1652             if( f_pos < 0.f )
1653                 f_pos = 0.f;
1654             else if( f_pos > 1.f )
1655                 f_pos = 1.f;
1656             /* Reset the decoders states and clock sync (before calling the demuxer */
1657             es_out_SetTime( p_input->p->p_es_out, -1 );
1658             if( demux_Control( p_input->p->input.p_demux, DEMUX_SET_POSITION,
1659                                (double) f_pos, !p_input->p->b_fast_seek ) )
1660             {
1661                 msg_Err( p_input, "INPUT_CONTROL_SET_POSITION(_OFFSET) "
1662                          "%2.1f%% failed", (double)(f_pos * 100.f) );
1663             }
1664             else
1665             {
1666                 if( p_input->p->i_slave > 0 )
1667                     SlaveSeek( p_input );
1668                 p_input->p->input.b_eof = false;
1669
1670                 b_force_update = true;
1671             }
1672             break;
1673         }
1674
1675         case INPUT_CONTROL_SET_TIME:
1676         {
1677             int64_t i_time;
1678             int i_ret;
1679
1680             if( p_input->p->b_recording )
1681             {
1682                 msg_Err( p_input, "INPUT_CONTROL_SET_TIME(_OFFSET) ignored while recording" );
1683                 break;
1684             }
1685
1686             i_time = val.i_time;
1687             if( i_time < 0 )
1688                 i_time = 0;
1689
1690             /* Reset the decoders states and clock sync (before calling the demuxer */
1691             es_out_SetTime( p_input->p->p_es_out, -1 );
1692
1693             i_ret = demux_Control( p_input->p->input.p_demux,
1694                                    DEMUX_SET_TIME, i_time,
1695                                    !p_input->p->b_fast_seek );
1696             if( i_ret )
1697             {
1698                 int64_t i_length;
1699
1700                 /* Emulate it with a SET_POS */
1701                 if( !demux_Control( p_input->p->input.p_demux,
1702                                     DEMUX_GET_LENGTH, &i_length ) && i_length > 0 )
1703                 {
1704                     double f_pos = (double)i_time / (double)i_length;
1705                     i_ret = demux_Control( p_input->p->input.p_demux,
1706                                             DEMUX_SET_POSITION, f_pos,
1707                                             !p_input->p->b_fast_seek );
1708                 }
1709             }
1710             if( i_ret )
1711             {
1712                 msg_Warn( p_input, "INPUT_CONTROL_SET_TIME(_OFFSET) %"PRId64
1713                          " failed or not possible", i_time );
1714             }
1715             else
1716             {
1717                 if( p_input->p->i_slave > 0 )
1718                     SlaveSeek( p_input );
1719                 p_input->p->input.b_eof = false;
1720
1721                 b_force_update = true;
1722             }
1723             break;
1724         }
1725
1726         case INPUT_CONTROL_SET_STATE:
1727             if( val.i_int != PLAYING_S && val.i_int != PAUSE_S )
1728                 msg_Err( p_input, "invalid state in INPUT_CONTROL_SET_STATE" );
1729             else if( p_input->p->i_state == PAUSE_S )
1730             {
1731                 ControlUnpause( p_input, i_control_date );
1732
1733                 b_force_update = true;
1734             }
1735             else if( val.i_int == PAUSE_S && p_input->p->i_state == PLAYING_S /* &&
1736                      p_input->p->b_can_pause */ )
1737             {
1738                 ControlPause( p_input, i_control_date );
1739
1740                 b_force_update = true;
1741             }
1742             else if( val.i_int == PAUSE_S && !p_input->p->b_can_pause && 0 )
1743             {
1744                 b_force_update = true;
1745
1746                 /* Correct "state" value */
1747                 input_ChangeState( p_input, p_input->p->i_state );
1748             }
1749             break;
1750
1751         case INPUT_CONTROL_SET_RATE:
1752         {
1753             /* Get rate and direction */
1754             int i_rate = abs( val.i_int );
1755             int i_rate_sign = val.i_int < 0 ? -1 : 1;
1756
1757             /* Check rate bound */
1758             if( i_rate < INPUT_RATE_MIN )
1759             {
1760                 msg_Dbg( p_input, "cannot set rate faster" );
1761                 i_rate = INPUT_RATE_MIN;
1762             }
1763             else if( i_rate > INPUT_RATE_MAX )
1764             {
1765                 msg_Dbg( p_input, "cannot set rate slower" );
1766                 i_rate = INPUT_RATE_MAX;
1767             }
1768
1769             /* Apply direction */
1770             if( i_rate_sign < 0 )
1771             {
1772                 if( p_input->p->input.b_rescale_ts )
1773                 {
1774                     msg_Dbg( p_input, "cannot set negative rate" );
1775                     i_rate = p_input->p->i_rate;
1776                     assert( i_rate > 0 );
1777                 }
1778                 else
1779                 {
1780                     i_rate *= i_rate_sign;
1781                 }
1782             }
1783
1784             if( i_rate != INPUT_RATE_DEFAULT &&
1785                 ( ( !p_input->p->b_can_rate_control && !p_input->p->input.b_rescale_ts ) ||
1786                   ( p_input->p->p_sout && !p_input->p->b_out_pace_control ) ) )
1787             {
1788                 msg_Dbg( p_input, "cannot change rate" );
1789                 i_rate = INPUT_RATE_DEFAULT;
1790             }
1791             if( i_rate != p_input->p->i_rate &&
1792                 !p_input->p->b_can_pace_control && p_input->p->b_can_rate_control )
1793             {
1794                 demux_t *p_demux = p_input->p->input.p_demux;
1795                 int i_ret = VLC_EGENERIC;
1796
1797                 if( p_demux->s == NULL )
1798                 {
1799                     if( !p_input->p->input.b_rescale_ts )
1800                         es_out_Control( p_input->p->p_es_out, ES_OUT_RESET_PCR );
1801
1802                     i_ret = demux_Control( p_input->p->input.p_demux,
1803                                             DEMUX_SET_RATE, &i_rate );
1804                 }
1805                 if( i_ret )
1806                 {
1807                     msg_Warn( p_input, "ACCESS/DEMUX_SET_RATE failed" );
1808                     i_rate = p_input->p->i_rate;
1809                 }
1810             }
1811
1812             /* */
1813             if( i_rate != p_input->p->i_rate )
1814             {
1815                 p_input->p->i_rate = i_rate;
1816                 input_SendEventRate( p_input, i_rate );
1817
1818                 if( p_input->p->input.b_rescale_ts )
1819                 {
1820                     const int i_rate_source = (p_input->p->b_can_pace_control || p_input->p->b_can_rate_control ) ? i_rate : INPUT_RATE_DEFAULT;
1821                     es_out_SetRate( p_input->p->p_es_out, i_rate_source, i_rate );
1822                 }
1823
1824                 b_force_update = true;
1825             }
1826             break;
1827         }
1828
1829         case INPUT_CONTROL_SET_PROGRAM:
1830             /* No need to force update, es_out does it if needed */
1831             es_out_Control( p_input->p->p_es_out,
1832                             ES_OUT_SET_GROUP, val.i_int );
1833
1834             demux_Control( p_input->p->input.p_demux, DEMUX_SET_GROUP, val.i_int,
1835                             NULL );
1836             break;
1837
1838         case INPUT_CONTROL_SET_ES:
1839             /* No need to force update, es_out does it if needed */
1840             es_out_Control( p_input->p->p_es_out_display,
1841                             ES_OUT_SET_ES_BY_ID, (int)val.i_int );
1842
1843             demux_Control( p_input->p->input.p_demux, DEMUX_SET_ES, (int)val.i_int );
1844             break;
1845
1846         case INPUT_CONTROL_RESTART_ES:
1847             es_out_Control( p_input->p->p_es_out_display,
1848                             ES_OUT_RESTART_ES_BY_ID, (int)val.i_int );
1849             break;
1850
1851         case INPUT_CONTROL_SET_AUDIO_DELAY:
1852             input_SendEventAudioDelay( p_input, val.i_time );
1853             UpdatePtsDelay( p_input );
1854             break;
1855
1856         case INPUT_CONTROL_SET_SPU_DELAY:
1857             input_SendEventSubtitleDelay( p_input, val.i_time );
1858             UpdatePtsDelay( p_input );
1859             break;
1860
1861         case INPUT_CONTROL_SET_TITLE:
1862         case INPUT_CONTROL_SET_TITLE_NEXT:
1863         case INPUT_CONTROL_SET_TITLE_PREV:
1864         {
1865             if( p_input->p->b_recording )
1866             {
1867                 msg_Err( p_input, "INPUT_CONTROL_SET_TITLE(*) ignored while recording" );
1868                 break;
1869             }
1870             if( p_input->p->input.i_title <= 0 )
1871                 break;
1872
1873             int i_title = p_input->p->input.p_demux->info.i_title;
1874             if( i_type == INPUT_CONTROL_SET_TITLE_PREV )
1875                 i_title--;
1876             else if( i_type == INPUT_CONTROL_SET_TITLE_NEXT )
1877                 i_title++;
1878             else
1879                 i_title = val.i_int;
1880             if( i_title < 0 || i_title >= p_input->p->input.i_title )
1881                 break;
1882
1883             es_out_SetTime( p_input->p->p_es_out, -1 );
1884             demux_Control( p_input->p->input.p_demux,
1885                            DEMUX_SET_TITLE, i_title );
1886             input_SendEventTitle( p_input, i_title );
1887             break;
1888         }
1889         case INPUT_CONTROL_SET_SEEKPOINT:
1890         case INPUT_CONTROL_SET_SEEKPOINT_NEXT:
1891         case INPUT_CONTROL_SET_SEEKPOINT_PREV:
1892         {
1893             if( p_input->p->b_recording )
1894             {
1895                 msg_Err( p_input, "INPUT_CONTROL_SET_SEEKPOINT(*) ignored while recording" );
1896                 break;
1897             }
1898             if( p_input->p->input.i_title <= 0 )
1899                 break;
1900
1901             demux_t *p_demux = p_input->p->input.p_demux;
1902
1903             int i_title = p_demux->info.i_title;
1904             int i_seekpoint = p_demux->info.i_seekpoint;
1905
1906             if( i_type == INPUT_CONTROL_SET_SEEKPOINT_PREV )
1907             {
1908                 int64_t i_seekpoint_time = p_input->p->input.title[i_title]->seekpoint[i_seekpoint]->i_time_offset;
1909                 int64_t i_input_time = var_GetTime( p_input, "time" );
1910                 if( i_seekpoint_time >= 0 && i_input_time >= 0 )
1911                 {
1912                     if( i_input_time < i_seekpoint_time + 3000000 )
1913                         i_seekpoint--;
1914                 }
1915                 else
1916                     i_seekpoint--;
1917             }
1918             else if( i_type == INPUT_CONTROL_SET_SEEKPOINT_NEXT )
1919                 i_seekpoint++;
1920             else
1921                 i_seekpoint = val.i_int;
1922             if( i_seekpoint < 0
1923              || i_seekpoint >= p_input->p->input.title[i_title]->i_seekpoint )
1924                 break;
1925
1926             es_out_SetTime( p_input->p->p_es_out, -1 );
1927             demux_Control( p_input->p->input.p_demux,
1928                            DEMUX_SET_SEEKPOINT, i_seekpoint );
1929             input_SendEventSeekpoint( p_input, i_title, i_seekpoint );
1930             break;
1931         }
1932
1933         case INPUT_CONTROL_ADD_SUBTITLE:
1934             if( val.psz_string )
1935                 input_SubtitleFileAdd( p_input, val.psz_string, true );
1936             break;
1937
1938         case INPUT_CONTROL_ADD_SLAVE:
1939             if( val.psz_string )
1940             {
1941                 const char *uri = val.psz_string;
1942                 input_source_t *slave = InputSourceNew( p_input );
1943
1944                 if( slave && !InputSourceInit( p_input, slave, uri, NULL, false ) )
1945                 {
1946                     int64_t i_time;
1947
1948                     /* Add the slave */
1949                     msg_Dbg( p_input, "adding %s as slave on the fly", uri );
1950
1951                     /* Set position */
1952                     if( demux_Control( p_input->p->input.p_demux,
1953                                         DEMUX_GET_TIME, &i_time ) )
1954                     {
1955                         msg_Err( p_input, "demux doesn't like DEMUX_GET_TIME" );
1956                         InputSourceClean( slave );
1957                         free( slave );
1958                         break;
1959                     }
1960                     if( demux_Control( slave->p_demux,
1961                                        DEMUX_SET_TIME, i_time, true ) )
1962                     {
1963                         msg_Err( p_input, "seek failed for new slave" );
1964                         InputSourceClean( slave );
1965                         free( slave );
1966                         break;
1967                     }
1968
1969                     /* Get meta (access and demux) */
1970                     InputUpdateMeta( p_input, slave->p_demux );
1971
1972                     TAB_APPEND( p_input->p->i_slave, p_input->p->slave, slave );
1973                 }
1974                 else
1975                 {
1976                     free( slave );
1977                     msg_Warn( p_input, "failed to add %s as slave", uri );
1978                 }
1979             }
1980             break;
1981
1982         case INPUT_CONTROL_SET_RECORD_STATE:
1983             if( !!p_input->p->b_recording != !!val.b_bool )
1984             {
1985                 if( p_input->p->input.b_can_stream_record )
1986                 {
1987                     if( demux_Control( p_input->p->input.p_demux,
1988                                        DEMUX_SET_RECORD_STATE, val.b_bool ) )
1989                         val.b_bool = false;
1990                 }
1991                 else
1992                 {
1993                     if( es_out_SetRecordState( p_input->p->p_es_out_display, val.b_bool ) )
1994                         val.b_bool = false;
1995                 }
1996                 p_input->p->b_recording = val.b_bool;
1997
1998                 input_SendEventRecord( p_input, val.b_bool );
1999
2000                 b_force_update = true;
2001             }
2002             break;
2003
2004         case INPUT_CONTROL_SET_FRAME_NEXT:
2005             if( p_input->p->i_state == PAUSE_S )
2006             {
2007                 es_out_SetFrameNext( p_input->p->p_es_out );
2008             }
2009             else if( p_input->p->i_state == PLAYING_S )
2010             {
2011                 ControlPause( p_input, i_control_date );
2012             }
2013             else
2014             {
2015                 msg_Err( p_input, "invalid state for frame next" );
2016             }
2017             b_force_update = true;
2018             break;
2019
2020         case INPUT_CONTROL_SET_BOOKMARK:
2021         {
2022             mtime_t time_offset = -1;
2023
2024             vlc_mutex_lock( &p_input->p->p_item->lock );
2025             if( val.i_int >= 0 && val.i_int < p_input->p->i_bookmark )
2026             {
2027                 const seekpoint_t *p_bookmark = p_input->p->pp_bookmark[val.i_int];
2028                 time_offset = p_bookmark->i_time_offset;
2029             }
2030             vlc_mutex_unlock( &p_input->p->p_item->lock );
2031
2032             if( time_offset < 0 )
2033             {
2034                 msg_Err( p_input, "invalid bookmark %"PRId64, val.i_int );
2035                 break;
2036             }
2037
2038             val.i_time = time_offset;
2039             b_force_update = Control( p_input, INPUT_CONTROL_SET_TIME, val );
2040             break;
2041         }
2042
2043         case INPUT_CONTROL_NAV_ACTIVATE:
2044         case INPUT_CONTROL_NAV_UP:
2045         case INPUT_CONTROL_NAV_DOWN:
2046         case INPUT_CONTROL_NAV_LEFT:
2047         case INPUT_CONTROL_NAV_RIGHT:
2048             demux_Control( p_input->p->input.p_demux, i_type
2049                            - INPUT_CONTROL_NAV_ACTIVATE + DEMUX_NAV_ACTIVATE );
2050             break;
2051
2052         default:
2053             msg_Err( p_input, "not yet implemented" );
2054             break;
2055     }
2056
2057     ControlRelease( i_type, val );
2058     return b_force_update;
2059 }
2060
2061 /*****************************************************************************
2062  * UpdateTitleSeekpoint
2063  *****************************************************************************/
2064 static int UpdateTitleSeekpoint( input_thread_t *p_input,
2065                                  int i_title, int i_seekpoint )
2066 {
2067     int i_title_end = p_input->p->input.i_title_end -
2068                         p_input->p->input.i_title_offset;
2069     int i_seekpoint_end = p_input->p->input.i_seekpoint_end -
2070                             p_input->p->input.i_seekpoint_offset;
2071
2072     if( i_title_end >= 0 && i_seekpoint_end >= 0 )
2073     {
2074         if( i_title > i_title_end ||
2075             ( i_title == i_title_end && i_seekpoint > i_seekpoint_end ) )
2076             return 0;
2077     }
2078     else if( i_seekpoint_end >= 0 )
2079     {
2080         if( i_seekpoint > i_seekpoint_end )
2081             return 0;
2082     }
2083     else if( i_title_end >= 0 )
2084     {
2085         if( i_title > i_title_end )
2086             return 0;
2087     }
2088     return 1;
2089 }
2090 /*****************************************************************************
2091  * Update*FromDemux:
2092  *****************************************************************************/
2093 static int UpdateTitleSeekpointFromDemux( input_thread_t *p_input )
2094 {
2095     demux_t *p_demux = p_input->p->input.p_demux;
2096
2097     /* TODO event-like */
2098     if( p_demux->info.i_update & INPUT_UPDATE_TITLE )
2099     {
2100         input_SendEventTitle( p_input, p_demux->info.i_title );
2101
2102         p_demux->info.i_update &= ~INPUT_UPDATE_TITLE;
2103     }
2104     if( p_demux->info.i_update & INPUT_UPDATE_SEEKPOINT )
2105     {
2106         input_SendEventSeekpoint( p_input,
2107                                   p_demux->info.i_title, p_demux->info.i_seekpoint );
2108
2109         p_demux->info.i_update &= ~INPUT_UPDATE_SEEKPOINT;
2110     }
2111
2112     /* Hmmm only works with master input */
2113     if( p_input->p->input.p_demux == p_demux )
2114         return UpdateTitleSeekpoint( p_input,
2115                                      p_demux->info.i_title,
2116                                      p_demux->info.i_seekpoint );
2117     return 1;
2118 }
2119
2120 static void UpdateGenericFromDemux( input_thread_t *p_input )
2121 {
2122     demux_t *p_demux = p_input->p->input.p_demux;
2123
2124     if( p_demux->info.i_update & INPUT_UPDATE_META )
2125     {
2126         InputUpdateMeta( p_input, p_demux );
2127         p_demux->info.i_update &= ~INPUT_UPDATE_META;
2128     }
2129     {
2130         double quality;
2131         double strength;
2132
2133         if( !demux_Control( p_demux, DEMUX_GET_SIGNAL, &quality, &strength ) )
2134             input_SendEventSignal( p_input, quality, strength );
2135     }
2136 }
2137
2138 static void UpdateTitleListfromDemux( input_thread_t *p_input )
2139 {
2140     input_source_t *in = &p_input->p->input;
2141
2142     /* Delete the preexisting titles */
2143     if( in->i_title > 0 )
2144     {
2145         for( int i = 0; i < in->i_title; i++ )
2146             vlc_input_title_Delete( in->title[i] );
2147         TAB_CLEAN( in->i_title, in->title );
2148         in->b_title_demux = false;
2149     }
2150
2151     /* Get the new title list */
2152     if( demux_Control( in->p_demux, DEMUX_GET_TITLE_INFO,
2153                        &in->title, &in->i_title,
2154                        &in->i_title_offset, &in->i_seekpoint_offset ) )
2155         TAB_INIT( in->i_title, in->title );
2156     else
2157         in->b_title_demux = true;
2158
2159     InitTitle( p_input );
2160 }
2161
2162
2163 /*****************************************************************************
2164  * InputSourceNew:
2165  *****************************************************************************/
2166 static input_source_t *InputSourceNew( input_thread_t *p_input )
2167 {
2168     VLC_UNUSED(p_input);
2169
2170     return calloc( 1,  sizeof( input_source_t ) );
2171 }
2172
2173 /*****************************************************************************
2174  * InputSourceInit:
2175  *****************************************************************************/
2176 static int InputSourceInit( input_thread_t *p_input,
2177                             input_source_t *in, const char *psz_mrl,
2178                             const char *psz_forced_demux, bool b_in_can_fail )
2179 {
2180     const char *psz_access, *psz_demux, *psz_path, *psz_anchor = NULL;
2181     char *psz_var_demux = NULL;
2182     double f_fps;
2183
2184     assert( psz_mrl );
2185     char *psz_dup = strdup( psz_mrl );
2186
2187     if( psz_dup == NULL )
2188         goto error;
2189
2190     /* Split uri */
2191     input_SplitMRL( &psz_access, &psz_demux, &psz_path, &psz_anchor, psz_dup );
2192
2193     msg_Dbg( p_input, "`%s' gives access `%s' demux `%s' path `%s'",
2194              psz_mrl, psz_access, psz_demux, psz_path );
2195     if( !p_input->b_preparsing )
2196     {
2197         /* Find optional titles and seekpoints */
2198         MRLSections( psz_anchor, &in->i_title_start, &in->i_title_end,
2199                      &in->i_seekpoint_start, &in->i_seekpoint_end );
2200         if( psz_forced_demux && *psz_forced_demux )
2201         {
2202             psz_demux = psz_forced_demux;
2203         }
2204         else if( *psz_demux == '\0' )
2205         {
2206             /* special hack for forcing a demuxer with --demux=module
2207              * (and do nothing with a list) */
2208             psz_var_demux = var_GetNonEmptyString( p_input, "demux" );
2209             psz_demux = psz_var_demux;
2210             msg_Dbg( p_input, "specified demux `%s'", psz_demux );
2211         }
2212
2213         /* Try access_demux first */
2214         in->p_demux = demux_New( p_input, p_input, psz_access, psz_demux,
2215                                  psz_path, NULL, p_input->p->p_es_out, false );
2216     }
2217     else
2218     {
2219         if( *psz_demux )
2220             goto error;
2221         msg_Dbg( p_input, "trying to pre-parse %s",  psz_path );
2222     }
2223
2224     mtime_t i_pts_delay;
2225
2226     if( in->p_demux )
2227     {
2228         /* Get infos from access_demux */
2229         in->b_title_demux = true;
2230         if( demux_Control( in->p_demux, DEMUX_GET_TITLE_INFO,
2231                             &in->title, &in->i_title,
2232                             &in->i_title_offset, &in->i_seekpoint_offset ) )
2233         {
2234             TAB_INIT( in->i_title, in->title );
2235         }
2236         if( demux_Control( in->p_demux, DEMUX_CAN_CONTROL_PACE,
2237                             &in->b_can_pace_control ) )
2238             in->b_can_pace_control = false;
2239
2240         assert( in->p_demux->pf_demux != NULL || !in->b_can_pace_control );
2241
2242         if( !in->b_can_pace_control )
2243         {
2244             if( demux_Control( in->p_demux, DEMUX_CAN_CONTROL_RATE,
2245                                 &in->b_can_rate_control, &in->b_rescale_ts ) )
2246             {
2247                 in->b_can_rate_control = false;
2248                 in->b_rescale_ts = true; /* not used */
2249             }
2250         }
2251         else
2252         {
2253             in->b_can_rate_control = true;
2254             in->b_rescale_ts = true;
2255         }
2256         if( demux_Control( in->p_demux, DEMUX_CAN_PAUSE,
2257                             &in->b_can_pause ) )
2258             in->b_can_pause = false;
2259         var_SetBool( p_input, "can-pause", in->b_can_pause || !in->b_can_pace_control ); /* XXX temporary because of es_out_timeshift*/
2260         var_SetBool( p_input, "can-rate", !in->b_can_pace_control || in->b_can_rate_control ); /* XXX temporary because of es_out_timeshift*/
2261         var_SetBool( p_input, "can-rewind", !in->b_rescale_ts && !in->b_can_pace_control && in->b_can_rate_control );
2262
2263         bool b_can_seek;
2264         if( demux_Control( in->p_demux, DEMUX_CAN_SEEK, &b_can_seek ) )
2265             b_can_seek = false;
2266         var_SetBool( p_input, "can-seek", b_can_seek );
2267     }
2268     else
2269     {   /* Now try a real access */
2270         access_t *p_access = access_New( p_input, p_input,
2271                                          psz_access, psz_demux, psz_path );
2272         if( p_access == NULL )
2273         {
2274             if( vlc_object_alive( p_input ) )
2275             {
2276                 msg_Err( p_input, "open of `%s' failed", psz_mrl );
2277                 if( !b_in_can_fail )
2278                     dialog_Fatal( p_input, _("Your input can't be opened"),
2279                                    _("VLC is unable to open the MRL '%s'."
2280                                      " Check the log for details."), psz_mrl );
2281             }
2282             goto error;
2283         }
2284
2285         /* Access-forced demuxer (PARENTAL ADVISORY: EXPLICIT HACK) */
2286         if( !psz_demux[0] || !strcasecmp( psz_demux, "any" ) )
2287             psz_demux = p_access->psz_demux;
2288
2289         /* */
2290         int  i_input_list;
2291         char **ppsz_input_list;
2292
2293         TAB_INIT( i_input_list, ppsz_input_list );
2294
2295         /* On master stream only, use input-list */
2296         if( &p_input->p->input == in )
2297         {
2298             char *psz_list;
2299             char *psz_parser;
2300
2301             psz_list =
2302             psz_parser = var_CreateGetNonEmptyString( p_input, "input-list" );
2303
2304             while( psz_parser && *psz_parser )
2305             {
2306                 char *p = strchr( psz_parser, ',' );
2307                 if( p )
2308                     *p++ = '\0';
2309
2310                 if( *psz_parser )
2311                 {
2312                     char *psz_name = strdup( psz_parser );
2313                     if( psz_name )
2314                         TAB_APPEND( i_input_list, ppsz_input_list, psz_name );
2315                 }
2316
2317                 psz_parser = p;
2318             }
2319             free( psz_list );
2320         }
2321         /* Autodetect extra files if none specified */
2322         if( i_input_list <= 0 )
2323         {
2324             InputGetExtraFiles( p_input, &i_input_list, &ppsz_input_list,
2325                                 psz_access, psz_path );
2326         }
2327         if( i_input_list > 0 )
2328             TAB_APPEND( i_input_list, ppsz_input_list, NULL );
2329
2330         /* Create the stream_t */
2331         stream_t *p_stream = stream_AccessNew( p_access, ppsz_input_list );
2332         if( ppsz_input_list )
2333         {
2334             for( int i = 0; ppsz_input_list[i] != NULL; i++ )
2335                 free( ppsz_input_list[i] );
2336             TAB_CLEAN( i_input_list, ppsz_input_list );
2337         }
2338
2339         if( p_stream == NULL )
2340         {
2341             msg_Warn( p_input, "cannot create a stream_t from access" );
2342             goto error;
2343         }
2344
2345         /* Add stream filters */
2346         char *psz_stream_filter = var_GetNonEmptyString( p_input,
2347                                                          "stream-filter" );
2348         p_stream = stream_FilterChainNew( p_stream, psz_stream_filter,
2349                                var_GetBool( p_input, "input-record-native" ) );
2350         free( psz_stream_filter );
2351
2352         if( !p_input->b_preparsing )
2353         {
2354             bool b;
2355
2356             stream_Control( p_stream, STREAM_CAN_CONTROL_PACE,
2357                             &in->b_can_pace_control );
2358             in->b_can_rate_control = in->b_can_pace_control;
2359             in->b_rescale_ts = true;
2360
2361             stream_Control( p_stream, STREAM_CAN_PAUSE, &in->b_can_pause );
2362             var_SetBool( p_input, "can-pause",
2363                          in->b_can_pause || !in->b_can_pace_control ); /* XXX temporary because of es_out_timeshift*/
2364             var_SetBool( p_input, "can-rate",
2365                          !in->b_can_pace_control || in->b_can_rate_control ); /* XXX temporary because of es_out_timeshift*/
2366             var_SetBool( p_input, "can-rewind",
2367                          !in->b_rescale_ts && !in->b_can_pace_control );
2368
2369             stream_Control( p_stream, STREAM_CAN_SEEK, &b );
2370             var_SetBool( p_input, "can-seek", b );
2371
2372             in->b_title_demux = false;
2373
2374             stream_Control( p_stream, STREAM_GET_PTS_DELAY, &i_pts_delay );
2375         }
2376
2377         in->p_demux = demux_New( p_input, p_input, psz_access, psz_demux,
2378                    /* Take access/stream redirections into account: */
2379                             p_stream->psz_path ? p_stream->psz_path : psz_path,
2380                                  p_stream, p_input->p->p_es_out,
2381                                  p_input->b_preparsing );
2382
2383         if( in->p_demux == NULL )
2384         {
2385             if( vlc_object_alive( p_input ) )
2386             {
2387                 msg_Err( p_input, "no suitable demux module for `%s/%s://%s'",
2388                          psz_access, psz_demux, psz_path );
2389                 if( !b_in_can_fail )
2390                     dialog_Fatal( VLC_OBJECT( p_input ),
2391                                   _("VLC can't recognize the input's format"),
2392                                   _("The format of '%s' cannot be detected. "
2393                                     "Have a look at the log for details."), psz_mrl );
2394             }
2395             stream_Delete( p_stream );
2396             goto error;
2397         }
2398         assert( in->p_demux->pf_demux != NULL );
2399
2400         /* Get title from demux */
2401         if( !p_input->b_preparsing && in->i_title <= 0 )
2402         {
2403             if( demux_Control( in->p_demux, DEMUX_GET_TITLE_INFO,
2404                                 &in->title, &in->i_title,
2405                                 &in->i_title_offset, &in->i_seekpoint_offset ))
2406             {
2407                 TAB_INIT( in->i_title, in->title );
2408             }
2409             else
2410             {
2411                 in->b_title_demux = true;
2412             }
2413         }
2414     }
2415
2416     free( psz_var_demux );
2417     free( psz_dup );
2418
2419     /* Set record capabilities */
2420     if( demux_Control( in->p_demux, DEMUX_CAN_RECORD, &in->b_can_stream_record ) )
2421         in->b_can_stream_record = false;
2422 #ifdef ENABLE_SOUT
2423     if( !var_GetBool( p_input, "input-record-native" ) )
2424         in->b_can_stream_record = false;
2425     var_SetBool( p_input, "can-record", true );
2426 #else
2427     var_SetBool( p_input, "can-record", in->b_can_stream_record );
2428 #endif
2429
2430     /* get attachment
2431      * FIXME improve for b_preparsing: move it after GET_META and check psz_arturl */
2432     if( !p_input->b_preparsing )
2433     {
2434         int i_attachment;
2435         input_attachment_t **attachment;
2436         if( !demux_Control( in->p_demux, DEMUX_GET_ATTACHMENTS,
2437                              &attachment, &i_attachment ) )
2438         {
2439             vlc_mutex_lock( &p_input->p->p_item->lock );
2440             AppendAttachment( &p_input->p->i_attachment, &p_input->p->attachment, &p_input->p->attachment_demux,
2441                               i_attachment, attachment, in->p_demux );
2442             vlc_mutex_unlock( &p_input->p->p_item->lock );
2443         }
2444
2445         /* PTS delay: request from demux first. This is required for
2446          * access_demux and some special cases like SDP demux. Otherwise,
2447          * fallback to access */
2448         if( demux_Control( in->p_demux, DEMUX_GET_PTS_DELAY,
2449                            &in->i_pts_delay ) )
2450             in->i_pts_delay = i_pts_delay;
2451         if( in->i_pts_delay > INPUT_PTS_DELAY_MAX )
2452             in->i_pts_delay = INPUT_PTS_DELAY_MAX;
2453         else if( in->i_pts_delay < 0 )
2454             in->i_pts_delay = 0;
2455     }
2456
2457     if( !demux_Control( in->p_demux, DEMUX_GET_FPS, &f_fps ) && f_fps > 0.0 )
2458     {
2459         vlc_mutex_lock( &p_input->p->p_item->lock );
2460         p_input->p->f_fps = f_fps;
2461         vlc_mutex_unlock( &p_input->p->p_item->lock );
2462     }
2463
2464     if( var_GetInteger( p_input, "clock-synchro" ) != -1 )
2465         in->b_can_pace_control = !var_GetInteger( p_input, "clock-synchro" );
2466
2467     return VLC_SUCCESS;
2468
2469 error:
2470     if( in->p_demux )
2471         demux_Delete( in->p_demux );
2472
2473     free( psz_var_demux );
2474     free( psz_dup );
2475
2476     return VLC_EGENERIC;
2477 }
2478
2479 /*****************************************************************************
2480  * InputSourceClean:
2481  *****************************************************************************/
2482 static void InputSourceClean( input_source_t *in )
2483 {
2484     int i;
2485
2486     if( in->p_demux )
2487         demux_Delete( in->p_demux );
2488
2489     if( in->i_title > 0 )
2490     {
2491         for( i = 0; i < in->i_title; i++ )
2492             vlc_input_title_Delete( in->title[i] );
2493         TAB_CLEAN( in->i_title, in->title );
2494     }
2495 }
2496
2497 /*****************************************************************************
2498  * InputSourceMeta:
2499  *****************************************************************************/
2500 static void InputSourceMeta( input_thread_t *p_input,
2501                              input_source_t *p_source, vlc_meta_t *p_meta )
2502 {
2503     demux_t *p_demux = p_source->p_demux;
2504
2505     /* XXX Remember that checking against p_item->p_meta->i_status & ITEM_PREPARSED
2506      * is a bad idea */
2507
2508     bool has_meta = false;
2509
2510     /* Read demux meta */
2511     if( !demux_Control( p_demux, DEMUX_GET_META, p_meta ) )
2512         has_meta = true;
2513
2514     bool has_unsupported;
2515     if( demux_Control( p_demux, DEMUX_HAS_UNSUPPORTED_META, &has_unsupported ) )
2516         has_unsupported = true;
2517
2518     /* If the demux report unsupported meta data, or if we don't have meta data
2519      * try an external "meta reader" */
2520     if( has_meta && !has_unsupported )
2521         return;
2522
2523     demux_meta_t *p_demux_meta =
2524         vlc_custom_create( p_demux, sizeof( *p_demux_meta ), "demux meta" );
2525     if( !p_demux_meta )
2526         return;
2527     p_demux_meta->p_demux = p_demux;
2528     p_demux_meta->p_item = p_input->p->p_item;
2529
2530     module_t *p_id3 = module_need( p_demux_meta, "meta reader", NULL, false );
2531     if( p_id3 )
2532     {
2533         if( p_demux_meta->p_meta )
2534         {
2535             vlc_meta_Merge( p_meta, p_demux_meta->p_meta );
2536             vlc_meta_Delete( p_demux_meta->p_meta );
2537         }
2538
2539         if( p_demux_meta->i_attachments > 0 )
2540         {
2541             vlc_mutex_lock( &p_input->p->p_item->lock );
2542             AppendAttachment( &p_input->p->i_attachment, &p_input->p->attachment, &p_input->p->attachment_demux,
2543                               p_demux_meta->i_attachments, p_demux_meta->attachments, p_demux);
2544             vlc_mutex_unlock( &p_input->p->p_item->lock );
2545         }
2546         module_unneed( p_demux, p_id3 );
2547     }
2548     vlc_object_release( p_demux_meta );
2549 }
2550
2551
2552 static void SlaveDemux( input_thread_t *p_input )
2553 {
2554     int64_t i_time;
2555     int i;
2556
2557     if( demux_Control( p_input->p->input.p_demux, DEMUX_GET_TIME, &i_time ) )
2558     {
2559         msg_Err( p_input, "demux doesn't like DEMUX_GET_TIME" );
2560         return;
2561     }
2562
2563     for( i = 0; i < p_input->p->i_slave; i++ )
2564     {
2565         input_source_t *in = p_input->p->slave[i];
2566         int i_ret;
2567
2568         if( in->b_eof )
2569             continue;
2570
2571         /* Call demux_Demux until we have read enough data */
2572         if( demux_Control( in->p_demux, DEMUX_SET_NEXT_DEMUX_TIME, i_time ) )
2573         {
2574             for( ;; )
2575             {
2576                 int64_t i_stime;
2577                 if( demux_Control( in->p_demux, DEMUX_GET_TIME, &i_stime ) )
2578                 {
2579                     msg_Err( p_input, "slave[%d] doesn't like "
2580                              "DEMUX_GET_TIME -> EOF", i );
2581                     i_ret = 0;
2582                     break;
2583                 }
2584
2585                 if( i_stime >= i_time )
2586                 {
2587                     i_ret = 1;
2588                     break;
2589                 }
2590
2591                 if( ( i_ret = demux_Demux( in->p_demux ) ) <= 0 )
2592                     break;
2593             }
2594         }
2595         else
2596         {
2597             i_ret = demux_Demux( in->p_demux );
2598         }
2599
2600         if( i_ret <= 0 )
2601         {
2602             msg_Dbg( p_input, "slave %d EOF", i );
2603             in->b_eof = true;
2604         }
2605     }
2606 }
2607
2608 static void SlaveSeek( input_thread_t *p_input )
2609 {
2610     int64_t i_time;
2611     int i;
2612
2613     if( demux_Control( p_input->p->input.p_demux, DEMUX_GET_TIME, &i_time ) )
2614     {
2615         msg_Err( p_input, "demux doesn't like DEMUX_GET_TIME" );
2616         return;
2617     }
2618
2619     for( i = 0; i < p_input->p->i_slave; i++ )
2620     {
2621         input_source_t *in = p_input->p->slave[i];
2622
2623         if( demux_Control( in->p_demux, DEMUX_SET_TIME, i_time, true ) )
2624         {
2625             if( !in->b_eof )
2626                 msg_Err( p_input, "seek failed for slave %d -> EOF", i );
2627             in->b_eof = true;
2628         }
2629         else
2630         {
2631             in->b_eof = false;
2632         }
2633     }
2634 }
2635
2636 /*****************************************************************************
2637  * InputMetaUser:
2638  *****************************************************************************/
2639 static void InputMetaUser( input_thread_t *p_input, vlc_meta_t *p_meta )
2640 {
2641     static const struct { int i_meta; const char *psz_name; } p_list[] = {
2642         { vlc_meta_Title,       "meta-title" },
2643         { vlc_meta_Artist,      "meta-artist" },
2644         { vlc_meta_Genre,       "meta-genre" },
2645         { vlc_meta_Copyright,   "meta-copyright" },
2646         { vlc_meta_Description, "meta-description" },
2647         { vlc_meta_Date,        "meta-date" },
2648         { vlc_meta_URL,         "meta-url" },
2649         { 0, NULL }
2650     };
2651
2652     /* Get meta information from user */
2653     for( int i = 0; p_list[i].psz_name; i++ )
2654     {
2655         char *psz_string = var_GetNonEmptyString( p_input, p_list[i].psz_name );
2656         if( !psz_string )
2657             continue;
2658
2659         EnsureUTF8( psz_string );
2660         vlc_meta_Set( p_meta, p_list[i].i_meta, psz_string );
2661         free( psz_string );
2662     }
2663 }
2664
2665 static void AppendAttachment( int *pi_attachment, input_attachment_t ***ppp_attachment, demux_t ***ppp_attachment_demux,
2666                               int i_new, input_attachment_t **pp_new, demux_t *p_demux )
2667 {
2668     int i_attachment = *pi_attachment;
2669     input_attachment_t **attachment = *ppp_attachment;
2670     demux_t **attachment_demux = *ppp_attachment_demux;
2671     int i;
2672
2673     attachment = xrealloc( attachment,
2674                     sizeof(*attachment) * ( i_attachment + i_new ) );
2675     attachment_demux = xrealloc( attachment_demux,
2676                     sizeof(*attachment_demux) * ( i_attachment + i_new ) );
2677     for( i = 0; i < i_new; i++ )
2678     {
2679         attachment[i_attachment] = pp_new[i];
2680         attachment_demux[i_attachment++] = p_demux;
2681     }
2682     free( pp_new );
2683
2684     /* */
2685     *pi_attachment = i_attachment;
2686     *ppp_attachment = attachment;
2687     *ppp_attachment_demux = attachment_demux;
2688 }
2689
2690 /*****************************************************************************
2691  * InputUpdateMeta: merge p_item meta data with p_meta taking care of
2692  * arturl and locking issue.
2693  *****************************************************************************/
2694 static void InputUpdateMeta( input_thread_t *p_input, demux_t *p_demux )
2695 {
2696     vlc_meta_t *p_meta = vlc_meta_New();
2697     if( unlikely(p_meta == NULL) )
2698         return;
2699
2700     demux_Control( p_demux, DEMUX_GET_META, p_meta );
2701
2702     /* If metadata changed, then the attachments might have changed.
2703        We need to update them in case they contain album art. */
2704     input_attachment_t **attachment;
2705     int i_attachment;
2706
2707     if( !demux_Control( p_demux, DEMUX_GET_ATTACHMENTS,
2708                         &attachment, &i_attachment ) )
2709     {
2710         vlc_mutex_lock( &p_input->p->p_item->lock );
2711         if( p_input->p->i_attachment > 0 )
2712         {
2713             int j = 0;
2714             for( int i = 0; i < p_input->p->i_attachment; i++ )
2715             {
2716                 if( p_input->p->attachment_demux[i] == p_demux )
2717                     vlc_input_attachment_Delete( p_input->p->attachment[i] );
2718                 else
2719                 {
2720                     p_input->p->attachment[j] = p_input->p->attachment[i];
2721                     p_input->p->attachment_demux[j] = p_input->p->attachment_demux[i];
2722                     j++;
2723                 }
2724             }
2725             p_input->p->i_attachment = j;
2726         }
2727         AppendAttachment( &p_input->p->i_attachment, &p_input->p->attachment, &p_input->p->attachment_demux,
2728                           i_attachment, attachment, p_demux );
2729         vlc_mutex_unlock( &p_input->p->p_item->lock );
2730     }
2731
2732     es_out_ControlSetMeta( p_input->p->p_es_out, p_meta );
2733     vlc_meta_Delete( p_meta );
2734 }
2735
2736 /*****************************************************************************
2737  * InputGetExtraFiles
2738  *  Autodetect extra input list
2739  *****************************************************************************/
2740 static void InputGetExtraFilesPattern( input_thread_t *p_input,
2741                                        int *pi_list, char ***pppsz_list,
2742                                        const char *psz_path,
2743                                        const char *psz_match,
2744                                        const char *psz_format,
2745                                        int i_start, int i_stop )
2746 {
2747     int i_list;
2748     char **ppsz_list;
2749
2750     TAB_INIT( i_list, ppsz_list );
2751
2752     char *psz_base = strdup( psz_path );
2753     if( !psz_base )
2754         goto exit;
2755
2756     /* Remove the extension */
2757     char *psz_end = &psz_base[strlen(psz_base)-strlen(psz_match)];
2758     assert( psz_end >= psz_base);
2759     *psz_end = '\0';
2760
2761     /* Try to list files */
2762     for( int i = i_start; i <= i_stop; i++ )
2763     {
2764         struct stat st;
2765         char *psz_file;
2766
2767         if( asprintf( &psz_file, psz_format, psz_base, i ) < 0 )
2768             break;
2769
2770         char *psz_tmp_path = get_path( psz_file );
2771
2772         if( vlc_stat( psz_tmp_path, &st ) || !S_ISREG( st.st_mode ) || !st.st_size )
2773         {
2774             free( psz_file );
2775             free( psz_tmp_path );
2776             break;
2777         }
2778
2779         msg_Dbg( p_input, "Detected extra file `%s'", psz_file );
2780         TAB_APPEND( i_list, ppsz_list, psz_file );
2781         free( psz_tmp_path );
2782     }
2783     free( psz_base );
2784 exit:
2785     *pi_list = i_list;
2786     *pppsz_list = ppsz_list;
2787 }
2788
2789 static void InputGetExtraFiles( input_thread_t *p_input,
2790                                 int *pi_list, char ***pppsz_list,
2791                                 const char *psz_access, const char *psz_path )
2792 {
2793     static const struct
2794     {
2795         const char *psz_match;
2796         const char *psz_format;
2797         int i_start;
2798         int i_stop;
2799     } p_pattern[] = {
2800         /* XXX the order is important */
2801         { ".001",         "%s.%.3d",        2, 999 },
2802         { NULL, NULL, 0, 0 }
2803     };
2804
2805     TAB_INIT( *pi_list, *pppsz_list );
2806
2807     if( ( psz_access && *psz_access && strcmp( psz_access, "file" ) ) || !psz_path )
2808         return;
2809
2810     const size_t i_path = strlen(psz_path);
2811
2812     for( int i = 0; p_pattern[i].psz_match != NULL; i++ )
2813     {
2814         const size_t i_ext = strlen(p_pattern[i].psz_match );
2815
2816         if( i_path < i_ext )
2817             continue;
2818         if( !strcmp( &psz_path[i_path-i_ext], p_pattern[i].psz_match ) )
2819         {
2820             InputGetExtraFilesPattern( p_input, pi_list, pppsz_list,
2821                                        psz_path,
2822                                        p_pattern[i].psz_match, p_pattern[i].psz_format,
2823                                        p_pattern[i].i_start, p_pattern[i].i_stop );
2824             return;
2825         }
2826     }
2827 }
2828
2829 /* */
2830 static void input_ChangeState( input_thread_t *p_input, int i_state )
2831 {
2832     const bool b_changed = p_input->p->i_state != i_state;
2833
2834     p_input->p->i_state = i_state;
2835     if( i_state == ERROR_S )
2836         p_input->b_error = true;
2837     else if( i_state == END_S )
2838         p_input->b_eof = true;
2839
2840     if( b_changed )
2841     {
2842         input_item_SetErrorWhenReading( p_input->p->p_item, p_input->b_error );
2843         input_SendEventState( p_input, i_state );
2844     }
2845 }
2846
2847
2848 /*****************************************************************************
2849  * MRLSplit: parse the access, demux and url part of the
2850  *           Media Resource Locator.
2851  *****************************************************************************/
2852 void input_SplitMRL( const char **access, const char **demux,
2853                      const char **path, const char **anchor, char *buf )
2854 {
2855     char *p;
2856
2857     /* Separate <path> from <access>[/<demux>]:// */
2858     p = strstr( buf, "://" );
2859     if( p != NULL )
2860     {
2861         *p = '\0';
2862         p += 3; /* skips "://" */
2863         *path = p;
2864
2865         /* Remove HTML anchor if present (not supported).
2866          * The hash symbol itself should be URI-encoded. */
2867         p = strchr( p, '#' );
2868         if( p != NULL )
2869         {
2870             *(p++) = '\0';
2871             *anchor = p;
2872         }
2873         else
2874             *anchor = "";
2875     }
2876     else
2877     {
2878 #ifndef NDEBUG
2879         fprintf( stderr, "%s(\"%s\") probably not a valid URI!\n", __func__,
2880                  buf );
2881 #endif
2882         /* Note: this is a valid non const pointer to "": */
2883         *path = buf + strlen( buf );
2884     }
2885
2886     /* Separate access from demux */
2887     p = strchr( buf, '/' );
2888     if( p != NULL )
2889     {
2890         *(p++) = '\0';
2891         if( p[0] == '$' )
2892             p++;
2893         *demux = p;
2894     }
2895     else
2896         *demux = "";
2897
2898     /* We really don't want module name substitution here! */
2899     p = buf;
2900     if( p[0] == '$' )
2901         p++;
2902     *access = p;
2903 }
2904
2905 static const char *MRLSeekPoint( const char *str, int *title, int *chapter )
2906 {
2907     char *end;
2908     unsigned long u;
2909
2910     /* Look for the title */
2911     u = strtoul( str, &end, 0 );
2912     *title = (str == end || u > (unsigned long)INT_MAX) ? -1 : (int)u;
2913     str = end;
2914
2915     /* Look for the chapter */
2916     if( *str == ':' )
2917     {
2918         str++;
2919         u = strtoul( str, &end, 0 );
2920         *chapter = (str == end || u > (unsigned long)INT_MAX) ? -1 : (int)u;
2921         str = end;
2922     }
2923     else
2924         *chapter = -1;
2925
2926     return str;
2927 }
2928
2929
2930 /*****************************************************************************
2931  * MRLSections: parse title and seekpoint info from the Media Resource Locator.
2932  *
2933  * Syntax:
2934  * [url][@[title_start][:chapter_start][-[title_end][:chapter_end]]]
2935  *****************************************************************************/
2936 static void MRLSections( const char *p,
2937                          int *pi_title_start, int *pi_title_end,
2938                          int *pi_chapter_start, int *pi_chapter_end )
2939 {
2940     *pi_title_start = *pi_title_end = *pi_chapter_start = *pi_chapter_end = -1;
2941
2942     int title_start, chapter_start, title_end, chapter_end;
2943
2944     if( !p )
2945         return;
2946
2947     if( *p != '-' )
2948         p = MRLSeekPoint( p, &title_start, &chapter_start );
2949     else
2950         title_start = chapter_start = -1;
2951
2952     if( *p == '-' )
2953         p = MRLSeekPoint( p + 1, &title_end, &chapter_end );
2954     else
2955         title_end = chapter_end = -1;
2956
2957     if( *p ) /* syntax error */
2958         return;
2959
2960     *pi_title_start = title_start;
2961     *pi_title_end = title_end;
2962     *pi_chapter_start = chapter_start;
2963     *pi_chapter_end = chapter_end;
2964 }
2965
2966 /*****************************************************************************
2967  * input_AddSubtitles: add a subtitle file and enable it
2968  *****************************************************************************/
2969 static void input_SubtitleAdd( input_thread_t *p_input,
2970                                const char *url, unsigned i_flags )
2971 {
2972     input_source_t *sub = InputSourceNew( p_input );
2973     if( sub == NULL )
2974         return;
2975
2976     vlc_value_t count;
2977
2978     var_Change( p_input, "spu-es", VLC_VAR_CHOICESCOUNT, &count, NULL );
2979
2980     if( InputSourceInit( p_input, sub, url, "subtitle",
2981                          (i_flags & SUB_CANFAIL) ) )
2982     {
2983         free( sub );
2984         return;
2985     }
2986     TAB_APPEND( p_input->p->i_slave, p_input->p->slave, sub );
2987
2988     if( !(i_flags & SUB_FORCED) )
2989         return;
2990
2991     /* Select the ES */
2992     vlc_value_t list;
2993
2994     if( var_Change( p_input, "spu-es", VLC_VAR_GETCHOICES, &list, NULL ) )
2995         return;
2996     if( count.i_int == 0 )
2997         count.i_int++;
2998     /* if it was first one, there is disable too */
2999
3000     if( count.i_int < list.p_list->i_count )
3001     {
3002         const int i_id = list.p_list->p_values[count.i_int].i_int;
3003
3004         es_out_Control( p_input->p->p_es_out_display, ES_OUT_SET_ES_DEFAULT_BY_ID, i_id );
3005         es_out_Control( p_input->p->p_es_out_display, ES_OUT_SET_ES_BY_ID, i_id );
3006     }
3007     var_FreeList( &list, NULL );
3008 }
3009
3010 static void input_SubtitleFileAdd( input_thread_t *p_input, char *psz_subtitle,
3011                                    unsigned i_flags )
3012 {
3013     /* if we are provided a subtitle.sub file,
3014      * see if we don't have a subtitle.idx and use it instead */
3015     char *psz_path = strdup( psz_subtitle );
3016     if( likely(psz_path != NULL) )
3017     {
3018         char *psz_extension = strrchr( psz_path, '.');
3019         if( psz_extension && strcmp( psz_extension, ".sub" ) == 0 )
3020         {
3021             struct stat st;
3022
3023             strcpy( psz_extension, ".idx" );
3024
3025             if( !vlc_stat( psz_path, &st ) && S_ISREG( st.st_mode ) )
3026             {
3027                 msg_Dbg( p_input, "using %s as subtitle file instead of %s",
3028                          psz_path, psz_subtitle );
3029                 strcpy( psz_subtitle, psz_path ); /* <- FIXME! constify */
3030             }
3031         }
3032         free( psz_path );
3033     }
3034
3035     char *url = vlc_path2uri( psz_subtitle, NULL );
3036     if( url == NULL )
3037         return;
3038
3039     input_SubtitleAdd( p_input, url, i_flags );
3040     free( url );
3041 }
3042
3043 /*****************************************************************************
3044  * Statistics
3045  *****************************************************************************/
3046 void input_UpdateStatistic( input_thread_t *p_input,
3047                             input_statistic_t i_type, int i_delta )
3048 {
3049     assert( p_input->p->i_state != INIT_S );
3050
3051     vlc_mutex_lock( &p_input->p->counters.counters_lock);
3052     switch( i_type )
3053     {
3054 #define I(c) stats_Update( p_input->p->counters.c, i_delta, NULL )
3055     case INPUT_STATISTIC_DECODED_VIDEO:
3056         I(p_decoded_video);
3057         break;
3058     case INPUT_STATISTIC_DECODED_AUDIO:
3059         I(p_decoded_audio);
3060         break;
3061     case INPUT_STATISTIC_DECODED_SUBTITLE:
3062         I(p_decoded_sub);
3063         break;
3064     case INPUT_STATISTIC_SENT_PACKET:
3065         I(p_sout_sent_packets);
3066         break;
3067 #undef I
3068     case INPUT_STATISTIC_SENT_BYTE:
3069     {
3070         uint64_t bytes;
3071
3072         stats_Update( p_input->p->counters.p_sout_sent_bytes, i_delta, &bytes );
3073         stats_Update( p_input->p->counters.p_sout_send_bitrate, bytes, NULL );
3074         break;
3075     }
3076     default:
3077         msg_Err( p_input, "Invalid statistic type %d (internal error)", i_type );
3078         break;
3079     }
3080     vlc_mutex_unlock( &p_input->p->counters.counters_lock);
3081 }
3082
3083 /**/
3084 /* TODO FIXME nearly the same logic that snapshot code */
3085 char *input_CreateFilename( input_thread_t *input, const char *psz_path, const char *psz_prefix, const char *psz_extension )
3086 {
3087     char *psz_file;
3088     DIR *path;
3089
3090     path = vlc_opendir( psz_path );
3091     if( path )
3092     {
3093         closedir( path );
3094
3095         char *psz_tmp = str_format( input, psz_prefix );
3096         if( !psz_tmp )
3097             return NULL;
3098
3099         filename_sanitize( psz_tmp );
3100
3101         if( asprintf( &psz_file, "%s"DIR_SEP"%s%s%s",
3102                       psz_path, psz_tmp,
3103                       psz_extension ? "." : "",
3104                       psz_extension ? psz_extension : "" ) < 0 )
3105             psz_file = NULL;
3106         free( psz_tmp );
3107         return psz_file;
3108     }
3109     else
3110     {
3111         psz_file = str_format( input, psz_path );
3112         path_sanitize( psz_file );
3113         return psz_file;
3114     }
3115 }