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