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