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