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