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