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