input.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:107k
源码类别:

midi

开发平台:

Unix_Linux

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