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