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