static void ParseOption( input_thread_t *p_input, const char *psz_option );
static void DecodeUrl ( char * );
+static void MRLSplit( char *, char **, char **, char ** );
+
+static input_source_t *InputSourceNew( input_thread_t *);
+static int InputSourceInit( input_thread_t *, input_source_t *, char * );
+static void InputSourceClean( input_thread_t *, input_source_t * );
+
+static void SlaveDemux( input_thread_t *p_input );
+static void SlaveSeek( input_thread_t *p_input );
/*****************************************************************************
* input_CreateThread: creates a new input thread
p_input->input.b_eof = VLC_FALSE;
p_input->input.i_cr_average = 0;
+ /* No slave */
+ p_input->i_slave = 0;
+ p_input->slave = NULL;
+
/* Init control buffer */
vlc_mutex_init( p_input, &p_input->lock_control );
p_input->i_control = 0;
}
/* Main loop */
- while( !p_input->b_die && !p_input->b_error && !p_input->b_eof )
+ while( !p_input->b_die && !p_input->b_error && !p_input->input.b_eof )
{
vlc_bool_t b_force_update = VLC_FALSE;
int i_ret;
/* End of file - we do not set b_die because only the
* playlist is allowed to do so. */
msg_Dbg( p_input, "EOF reached" );
- p_input->b_eof = VLC_TRUE;
p_input->input.b_eof = VLC_TRUE;
}
else
{
p_input->b_error = VLC_TRUE;
}
+
+ if( i_ret > 0 && p_input->i_slave > 0 )
+ {
+ SlaveDemux( p_input );
+ }
}
else
{
}
}
- /* Wait we are asked to die */
- if( !p_input->b_die )
- {
- Error( p_input );
- }
-
- /* Clean up */
- End( p_input );
-
- return 0;
-
-#if 0
- while( !p_input->b_die && !p_input->b_error && !p_input->b_eof )
+ if( !p_input->b_eof && !p_input->b_error && p_input->input.b_eof )
{
- if( p_input->stream.p_selected_area->i_seek != NO_SEEK )
+ /* We have finish to demux data but not to play them */
+ while( !p_input->b_die )
{
- if( p_input->stream.p_selected_area->i_size > 0 )
- {
- unsigned int i;
- mtime_t i_time;
- double f = (double)p_input->stream.p_selected_area->i_seek /
- (double)p_input->stream.p_selected_area->i_size;
-
- vlc_mutex_unlock( &p_input->stream.stream_lock );
- demux_Control( p_input, DEMUX_SET_POSITION, f );
- vlc_mutex_lock( &p_input->stream.stream_lock );
-
- /* Escape all decoders for the stream discontinuity they
- * will encounter. */
- input_EscapeDiscontinuity( p_input );
-
- for( i = 0; i < p_input->stream.i_pgrm_number; i++ )
- {
- pgrm_descriptor_t * p_pgrm=p_input->stream.pp_programs[i];
-
- /* Reinitialize synchro. */
- p_pgrm->i_synchro_state = SYNCHRO_REINIT;
- }
-
- vlc_mutex_unlock( &p_input->stream.stream_lock );
- if( !demux_Control( p_input, DEMUX_GET_TIME, &i_time ) )
- {
- int i;
- vlc_value_t val;
-
- /* Help in bar display */
- val.i_time = i_time;
- var_Change( p_input, "time", VLC_VAR_SETVALUE, &val, NULL );
+ if( input_EsOutDecodersEmpty( p_input->p_es_out ) )
+ break;
+ msg_Dbg( p_input, "waiting decoder fifos to empty" );
- /* Seek subs */
- for( i = 0; i < p_input->p_sys->i_sub; i++ )
- {
- subtitle_Seek( p_input->p_sys->sub[i], i_time );
- }
- }
- if( !demux_Control( p_input, DEMUX_GET_POSITION, &f ) )
- {
- val.f_float = (float)f;
- var_Change( p_input, "position", VLC_VAR_SETVALUE, &val, NULL );
- }
- vlc_mutex_lock( &p_input->stream.stream_lock );
- }
- p_input->stream.p_selected_area->i_seek = NO_SEEK;
+ msleep( INPUT_IDLE_SLEEP );
}
- /* Read and demultiplex some data. */
- i_count = p_input->pf_demux( p_input );
-
- XXXXX
-
- if( !p_input->b_error && !p_input->b_eof && i_update_next < mdate() )
- {
- int i;
- mtime_t i_time;
- mtime_t i_length;
- double d_pos;
-
- /* update input status variables */
- if( !demux_Control( p_input, DEMUX_GET_POSITION, &d_pos ) )
- {
- val.f_float = (float)d_pos;
- var_Change( p_input, "position", VLC_VAR_SETVALUE, &val, NULL );
- }
- if( !demux_Control( p_input, DEMUX_GET_TIME, &i_time ) )
- {
- val.i_time = i_time;
- var_Change( p_input, "time", VLC_VAR_SETVALUE, &val, NULL );
- }
- if( !demux_Control( p_input, DEMUX_GET_LENGTH, &i_length ) )
- {
- vlc_value_t old_val;
- var_Get( p_input, "length", &old_val );
- val.i_time = i_length;
- var_Change( p_input, "length", VLC_VAR_SETVALUE, &val, NULL );
- if( old_val.i_time != val.i_time )
- {
- char psz_buffer[MSTRTIME_MAX_SIZE];
-
- vlc_mutex_lock( &p_input->p_item->lock );
- p_input->p_item->i_duration = i_length;
- vlc_mutex_unlock( &p_input->p_item->lock );
-
- input_Control( p_input, INPUT_ADD_INFO, _("General"), _("Duration"),
- msecstotimestr( psz_buffer, i_length / 1000 ) );
- }
- }
-
- /* Check stop-time */
- if( p_input->p_sys->i_stop_time > 0 && p_input->p_sys->i_stop_time < i_time )
- {
- msg_Warn( p_input, "EOF reached because of stop-time" );
- p_input->b_eof = 1;
- }
-
- /* update subs */
- for( i = 0; i < p_input->p_sys->i_sub; i++ )
- {
- subtitle_Demux( p_input->p_sys->sub[i], i_time );
- }
-
- i_update_next = mdate() + I64C(150000);
- }
+ /* We have finished */
+ p_input->b_eof = VLC_TRUE;
}
- if( p_input->b_error || p_input->b_eof )
+ /* Wait we are asked to die */
+ if( !p_input->b_die )
{
- ErrorThread( p_input );
+ Error( p_input );
}
- EndThread( p_input );
+ /* Clean up */
+ End( p_input );
return 0;
-#endif
}
/*****************************************************************************
*****************************************************************************/
static int Init( input_thread_t * p_input )
{
- char *psz_dup = strdup( p_input->input.p_item->psz_uri );
- char *psz_access = NULL;
- char *psz_demux = NULL;
- char *psz_path = NULL;
char *psz;
vlc_value_t val;
- /* Open access/stream/demux */
- psz = strchr( psz_dup, ':' );
-#if defined( WIN32 ) || defined( UNDER_CE )
- if( psz - psz_dup == 1 )
- {
- msg_Warn( p_input, "drive letter %c: found in source string", psz_dup[0] );
- psz_path = psz_dup;
- }
- else
-#endif
- if( psz )
- {
- *psz++ = '\0';
- if( psz[0] == '/' && psz[1] == '/' )
- psz += 2;
-
- psz_path = psz;
-
- psz = strchr( psz_dup, '/' );
- if( psz )
- {
- *psz++ = '\0';
- psz_demux = psz;
- }
-
- psz_access = psz_dup;
- }
- else
- {
- psz_path = psz_dup;
- }
-
- if( psz_access == NULL ) psz_access = "";
- if( psz_demux == NULL ) psz_demux = "";
- if( psz_path == NULL ) psz_path = "";
-
- msg_Dbg( p_input, "`%s' gives access `%s' demux `%s' path `%s'",
- p_input->input.p_item->psz_uri,
- psz_access, psz_demux, psz_path );
-
/* Initialize optional stream output. (before access/demuxer) */
psz = var_GetString( p_input, "sout" );
if( *psz )
{
msg_Err( p_input, "cannot start stream output instance, aborting" );
free( psz );
- free( psz_dup );
-
return VLC_EGENERIC;
}
}
es_out_Control( p_input->p_es_out, ES_OUT_SET_ACTIVE, VLC_FALSE );
es_out_Control( p_input->p_es_out, ES_OUT_SET_MODE, ES_OUT_MODE_NONE );
- /* Try access_demux if no demux given */
- if( *psz_access && *psz_demux == '\0' )
+ if( InputSourceInit( p_input, &p_input->input,
+ p_input->input.p_item->psz_uri ) )
{
- p_input->input.p_demux = demux2_New( p_input, psz_access, psz_demux, psz_path,
- NULL, p_input->p_es_out );
+ goto error;
}
- if( p_input->input.p_demux )
- {
- /* Get infos from access_demux */
- demux2_Control( p_input->input.p_demux,
- DEMUX_GET_PTS_DELAY, &p_input->i_pts_delay );
- p_input->input.b_title_demux = VLC_TRUE;
- if( demux2_Control( p_input->input.p_demux,
- DEMUX_GET_TITLE_INFO,
- &p_input->input.title, &p_input->input.i_title ) )
- {
- p_input->input.i_title = 0;
- p_input->input.title = NULL;
- }
- demux2_Control( p_input->input.p_demux, DEMUX_CAN_CONTROL_PACE,
- &p_input->input.b_can_pace_control );
- demux2_Control( p_input->input.p_demux, DEMUX_CAN_PAUSE,
- &p_input->input.b_can_pause );
-
- /* FIXME todo
- demux2_Control( p_input->input.p_demux, DEMUX_CAN_SEEK,
- &val.b_bool );
- */
- }
- else
+#if 0
{
- /* Now try a real access */
- p_input->input.p_access = access2_New( p_input, psz_access, psz_demux, psz_path );
+ input_source_t *extra;
+ char *psz_extra = "/home/fenrir/a.avi";
- /* Access failed, URL encoded ? */
- if( p_input->input.p_access == NULL && strchr( psz_path, '%' ) )
+ extra = InputSourceNew( p_input );
+ if( !InputSourceInit( p_input, extra, psz_extra ) )
{
- DecodeUrl( psz_path );
-
- msg_Dbg( p_input, "retying with access `%s' demux `%s' path `%s'",
- psz_access, psz_demux, psz_path );
-
- p_input->input.p_access = access2_New( p_input, psz_access, psz_demux, psz_path );
- }
-#ifndef WIN32 /* Remove this gross hack from the win32 build as colons
- * are forbidden in filenames on Win32. */
-
- /* Maybe we got something like: /Volumes/toto:titi/gabu.mpg */
- if( p_input->input.p_access == NULL &&
- *psz_access == '\0' && ( *psz_demux || *psz_path ) )
- {
- free( psz_dup );
- psz_dup = strdup( p_input->input.p_item->psz_uri );
- psz_access = "";
- psz_demux = "";
- psz_path = psz_dup;
-
- p_input->input.p_access = access2_New( p_input, psz_access, psz_demux, psz_path );
+ TAB_APPEND( p_input->i_slave, p_input->slave, extra );
}
+ }
#endif
- if( p_input->input.p_access == NULL )
- {
- msg_Err( p_input, "no suitable access module for `%s'",
- p_input->input.p_item->psz_uri );
- goto error;
- }
-
- /* Get infos from access */
- access2_Control( p_input->input.p_access,
- ACCESS_GET_PTS_DELAY, &p_input->i_pts_delay );
- p_input->input.b_title_demux = VLC_FALSE;
- if( access2_Control( p_input->input.p_access,
- ACCESS_GET_TITLE_INFO,
- &p_input->input.title, &p_input->input.i_title ) )
- {
- p_input->input.i_title = 0;
- p_input->input.title = NULL;
- }
- access2_Control( p_input->input.p_access, ACCESS_CAN_CONTROL_PACE,
- &p_input->input.b_can_pace_control );
- access2_Control( p_input->input.p_access, ACCESS_CAN_PAUSE,
- &p_input->input.b_can_pace_control );
- access2_Control( p_input->input.p_access, ACCESS_CAN_SEEK,
- &val.b_bool );
- var_Set( p_input, "seekable", val );
-
- /* Create the stream_t */
- p_input->input.p_stream = stream_AccessNew( p_input->input.p_access );
- if( p_input->input.p_stream == NULL )
- {
- msg_Warn( p_input, "cannot create a stream_t from access" );
- goto error;
- }
-
- /* Open a demuxer */
- if( *psz_demux == '\0' && *p_input->input.p_access->psz_demux )
- {
- psz_demux = p_input->input.p_access->psz_demux;
- }
- p_input->input.p_demux = demux2_New( p_input, psz_access, psz_demux, psz_path,
- p_input->input.p_stream,
- p_input->p_es_out );
- if( p_input->input.p_demux == NULL )
- {
- msg_Err( p_input, "no suitable demux module for `%s/%s://%s'",
- psz_access, psz_demux, psz_path );
- goto error;
- }
-
- /* TODO get title from demux */
- if( p_input->input.i_title <= 0 )
- {
- if( demux2_Control( p_input->input.p_demux, DEMUX_GET_TITLE_INFO,
- &p_input->input.title, &p_input->input.i_title ) )
- {
- p_input->input.i_title = 0;
- p_input->input.title = NULL;
- }
- else
- {
- p_input->input.b_title_demux = VLC_TRUE;
- }
- }
- }
- /* Create global title (for now, just a copy) */
+ /* Create global title (from master) */
p_input->i_title = p_input->input.i_title;
+ p_input->title = p_input->input.title;
if( p_input->i_title > 0 )
{
- int i;
- p_input->title = malloc( sizeof( input_title_t *) * p_input->i_title );
- for( i = 0; i < p_input->i_title; i++ )
- {
- p_input->title[i] = vlc_input_title_Duplicate( p_input->input.title[i] );
- }
-
/* Setup variables */
input_ControlVarNavigation( p_input );
input_ControlVarTitle( p_input, 0 );
}
+
/* Global flag */
p_input->b_can_pace_control = p_input->input.b_can_pace_control;
p_input->b_can_pause = p_input->input.b_can_pause;
/* TODO: get meta data from demuxer */
+ /* Load master infos */
/* Init length */
if( !demux2_Control( p_input->input.p_demux, DEMUX_GET_LENGTH, &val.i_time ) && val.i_time > 0 )
{
}
- /* TODO: do subtitle loading */
+ /* TODO: do subtitle loading (and slave) */
/* Set up es_out */
return VLC_SUCCESS;
error:
- if( p_input->input.p_demux )
- demux2_Delete( p_input->input.p_demux );
-
- if( p_input->input.p_stream )
- stream_AccessDelete( p_input->input.p_stream );
-
- if( p_input->input.p_access )
- access2_Delete( p_input->input.p_access );
-
if( p_input->p_es_out )
input_EsOutDelete( p_input->p_es_out );
static void End( input_thread_t * p_input )
{
vlc_value_t val;
+ int i;
msg_Dbg( p_input, "closing `%s'",
p_input->input.p_item->psz_uri );
/* Clean control variables */
input_ControlVarClean( p_input );
- /* Unload all modules */
- if( p_input->input.p_demux )
- demux2_Delete( p_input->input.p_demux );
-
- if( p_input->input.p_stream )
- stream_AccessDelete( p_input->input.p_stream );
+ /* Clean up master */
+ InputSourceClean( p_input, &p_input->input );
- if( p_input->input.p_access )
- access2_Delete( p_input->input.p_access );
+ /* Delete slave */
+ for( i = 0; i < p_input->i_slave; i++ )
+ {
+ InputSourceClean( p_input, p_input->slave[i] );
+ free( p_input->slave[i] );
+ }
+ if( p_input->slave ) free( p_input->slave );
+ /* Unload all modules */
if( p_input->p_es_out )
input_EsOutDelete( p_input->p_es_out );
}
else
{
+ if( p_input->i_slave > 0 )
+ SlaveSeek( p_input );
+
input_EsOutDiscontinuity( p_input->p_es_out, VLC_FALSE );
es_out_Control( p_input->p_es_out, ES_OUT_RESET_PCR );
b_force_update = VLC_TRUE;
}
else
{
+ if( p_input->i_slave > 0 )
+ SlaveSeek( p_input );
+
input_EsOutDiscontinuity( p_input->p_es_out, VLC_FALSE );
es_out_Control( p_input->p_es_out, ES_OUT_RESET_PCR );
p_access->info.i_update &= ~INPUT_UPDATE_SIZE;
}
+/*****************************************************************************
+ * InputSourceNew:
+ *****************************************************************************/
+static input_source_t *InputSourceNew( input_thread_t *p_input )
+{
+ input_source_t *in = malloc( sizeof( input_source_t ) );
+
+ in->p_item = NULL;
+ in->p_access = NULL;
+ in->p_stream = NULL;
+ in->p_demux = NULL;
+ in->b_title_demux = VLC_FALSE;
+ in->i_title = 0;
+ in->title = NULL;
+ in->b_can_pace_control = VLC_TRUE;
+ in->b_eof = VLC_FALSE;
+ in->i_cr_average = 0;
+
+ return in;
+}
+
+/*****************************************************************************
+ * InputSourceInit:
+ *****************************************************************************/
+static int InputSourceInit( input_thread_t *p_input,
+ input_source_t *in, char *psz_mrl )
+{
+ char *psz_dup = strdup( psz_mrl );
+ char *psz_access;
+ char *psz_demux;
+ char *psz_path;
+ vlc_value_t val;
+
+ /* Split uri */
+ MRLSplit( psz_dup, &psz_access, &psz_demux, &psz_path );
+
+ msg_Dbg( p_input, "`%s' gives access `%s' demux `%s' path `%s'",
+ psz_mrl, psz_access, psz_demux, psz_path );
+
+
+ /* Try access_demux if no demux given */
+ if( *psz_access && *psz_demux == '\0' )
+ {
+ in->p_demux = demux2_New( p_input, psz_access, psz_demux, psz_path,
+ NULL, p_input->p_es_out );
+ }
+
+ if( in->p_demux )
+ {
+ int64_t i_pts_delay;
+
+ /* Get infos from access_demux */
+ demux2_Control( in->p_demux,
+ DEMUX_GET_PTS_DELAY, &i_pts_delay );
+ p_input->i_pts_delay = __MAX( p_input->i_pts_delay, i_pts_delay );
+
+ in->b_title_demux = VLC_TRUE;
+ if( demux2_Control( in->p_demux,
+ DEMUX_GET_TITLE_INFO,
+ &in->title, &in->i_title ) )
+ {
+ in->i_title = 0;
+ in->title = NULL;
+ }
+ demux2_Control( in->p_demux, DEMUX_CAN_CONTROL_PACE,
+ &in->b_can_pace_control );
+ demux2_Control( in->p_demux, DEMUX_CAN_PAUSE,
+ &in->b_can_pause );
+
+ /* FIXME todo
+ demux2_Control( in->p_demux, DEMUX_CAN_SEEK,
+ &val.b_bool );
+ */
+ }
+ else
+ {
+ int64_t i_pts_delay;
+
+ /* Now try a real access */
+ in->p_access = access2_New( p_input, psz_access, psz_demux, psz_path );
+
+ /* Access failed, URL encoded ? */
+ if( in->p_access == NULL && strchr( psz_path, '%' ) )
+ {
+ DecodeUrl( psz_path );
+
+ msg_Dbg( p_input, "retying with access `%s' demux `%s' path `%s'",
+ psz_access, psz_demux, psz_path );
+
+ in->p_access = access2_New( p_input,
+ psz_access, psz_demux, psz_path );
+ }
+#ifndef WIN32 /* Remove this gross hack from the win32 build as colons
+ * are forbidden in filenames on Win32. */
+
+ /* Maybe we got something like: /Volumes/toto:titi/gabu.mpg */
+ if( in->p_access == NULL &&
+ *psz_access == '\0' && ( *psz_demux || *psz_path ) )
+ {
+ free( psz_dup );
+ psz_dup = strdup( in->p_item->psz_uri );
+ psz_access = "";
+ psz_demux = "";
+ psz_path = psz_dup;
+
+ in->p_access = access2_New( p_input,
+ psz_access, psz_demux, psz_path );
+ }
+#endif
+
+ if( in->p_access == NULL )
+ {
+ msg_Err( p_input, "no suitable access module for `%s'",
+ in->p_item->psz_uri );
+ goto error;
+ }
+
+ /* Get infos from access */
+ access2_Control( in->p_access,
+ ACCESS_GET_PTS_DELAY, &i_pts_delay );
+ p_input->i_pts_delay = __MAX( p_input->i_pts_delay, i_pts_delay );
+
+ in->b_title_demux = VLC_FALSE;
+ if( access2_Control( in->p_access,
+ ACCESS_GET_TITLE_INFO,
+ &in->title, &in->i_title ) )
+ {
+ in->i_title = 0;
+ in->title = NULL;
+ }
+ access2_Control( in->p_access, ACCESS_CAN_CONTROL_PACE,
+ &in->b_can_pace_control );
+ access2_Control( in->p_access, ACCESS_CAN_PAUSE,
+ &in->b_can_pause );
+ access2_Control( in->p_access, ACCESS_CAN_SEEK,
+ &val.b_bool );
+ var_Set( p_input, "seekable", val );
+
+ /* Create the stream_t */
+ in->p_stream = stream_AccessNew( in->p_access );
+ if( in->p_stream == NULL )
+ {
+ msg_Warn( p_input, "cannot create a stream_t from access" );
+ goto error;
+ }
+
+ /* Open a demuxer */
+ if( *psz_demux == '\0' && *in->p_access->psz_demux )
+ {
+ psz_demux = in->p_access->psz_demux;
+ }
+ in->p_demux = demux2_New( p_input, psz_access, psz_demux, psz_path,
+ in->p_stream, p_input->p_es_out );
+ if( in->p_demux == NULL )
+ {
+ msg_Err( p_input, "no suitable demux module for `%s/%s://%s'",
+ psz_access, psz_demux, psz_path );
+ goto error;
+ }
+
+ /* TODO get title from demux */
+ if( in->i_title <= 0 )
+ {
+ if( demux2_Control( in->p_demux, DEMUX_GET_TITLE_INFO,
+ &in->title, &in->i_title ) )
+ {
+ in->i_title = 0;
+ in->title = NULL;
+ }
+ else
+ {
+ in->b_title_demux = VLC_TRUE;
+ }
+ }
+ }
+ free( psz_dup );
+ return VLC_SUCCESS;
+
+error:
+ if( in->p_demux )
+ demux2_Delete( in->p_demux );
+
+ if( in->p_stream )
+ stream_AccessDelete( in->p_stream );
+
+ if( in->p_access )
+ access2_Delete( in->p_access );
+ free( psz_dup );
+
+ return VLC_EGENERIC;
+}
+
+/*****************************************************************************
+ * InputSourceClean:
+ *****************************************************************************/
+static void InputSourceClean( input_thread_t *p_input, input_source_t *in )
+{
+ if( in->p_demux )
+ demux2_Delete( in->p_demux );
+
+ if( in->p_stream )
+ stream_AccessDelete( in->p_stream );
+
+ if( in->p_access )
+ access2_Delete( in->p_access );
+
+ if( in->i_title > 0 )
+ {
+ int i;
+ for( i = 0; i < in->i_title; i++ )
+ {
+ vlc_input_title_Delete( in->title[i] );
+ }
+ free( in->title );
+ }
+}
+
+static void SlaveDemux( input_thread_t *p_input )
+{
+ int64_t i_time;
+ int i;
+ if( demux2_Control( p_input->input.p_demux, DEMUX_GET_TIME, &i_time ) )
+ {
+ msg_Err( p_input, "demux doesn't like DEMUX_GET_TIME" );
+ return;
+ }
+
+ for( i = 0; i < p_input->i_slave; i++ )
+ {
+ input_source_t *in = p_input->slave[i];
+ int i_ret = 1;
+
+ if( in->b_eof )
+ continue;
+
+ if( demux2_Control( in->p_demux, DEMUX_SET_NEXT_DEMUX_TIME, i_time ) )
+ {
+ for( ;; )
+ {
+ int64_t i_stime;
+ if( demux2_Control( in->p_demux, DEMUX_GET_TIME, &i_stime ) )
+ {
+ msg_Err( p_input, "slave[%d] doesn't like DEMUX_GET_TIME -> EOF", i );
+ i_ret = 0;
+ break;
+ }
+ msg_Dbg( p_input, "slave time=%lld input=%lld", i_stime, i_time );
+ if( i_stime >= i_time )
+ break;
+
+ if( ( i_ret = in->p_demux->pf_demux( in->p_demux ) ) <= 0 )
+ break;
+ }
+ }
+ else
+ {
+ i_ret = in->p_demux->pf_demux( in->p_demux );
+ }
+
+ if( i_ret <= 0 )
+ {
+ msg_Dbg( p_input, "slave %d EOF", i );
+ in->b_eof = VLC_TRUE;
+ }
+ }
+}
+
+static void SlaveSeek( input_thread_t *p_input )
+{
+ int64_t i_time;
+ int i;
+
+ if( demux2_Control( p_input->input.p_demux, DEMUX_GET_TIME, &i_time ) )
+ {
+ msg_Err( p_input, "demux doesn't like DEMUX_GET_TIME" );
+ return;
+ }
+
+ for( i = 0; i < p_input->i_slave; i++ )
+ {
+ input_source_t *in = p_input->slave[i];
+
+ if( demux2_Control( in->p_demux, DEMUX_SET_TIME, i_time ) )
+ {
+ msg_Err( p_input, "seek failed for slave %d -> EOF", i );
+ in->b_eof = VLC_TRUE;
+ }
+ }
+}
+
+
/*****************************************************************************
* DecodeUrl: decode a given encoded url
*****************************************************************************/
return;
}
+static void MRLSplit( char *psz_dup,
+ char **ppsz_access, char **ppsz_demux, char **ppsz_path )
+{
+ char *psz_access = NULL;
+ char *psz_demux = NULL;
+ char *psz_path = NULL;
+ char *psz;
+
+ psz = strchr( psz_dup, ':' );
+#if defined( WIN32 ) || defined( UNDER_CE )
+ if( psz - psz_dup == 1 )
+ {
+ msg_Warn( p_input, "drive letter %c: found in source string", psz_dup[0] );
+ psz_path = psz_dup;
+ }
+ else
+#endif
+ if( psz )
+ {
+ *psz++ = '\0';
+ if( psz[0] == '/' && psz[1] == '/' )
+ psz += 2;
+
+ psz_path = psz;
+
+ psz = strchr( psz_dup, '/' );
+ if( psz )
+ {
+ *psz++ = '\0';
+ psz_demux = psz;
+ }
+
+ psz_access = psz_dup;
+ }
+ else
+ {
+ psz_path = psz_dup;
+ }
+
+ if( psz_access == NULL )
+ *ppsz_access = "";
+ else
+ *ppsz_access = psz_access;
+
+ if( psz_demux == NULL )
+ *ppsz_demux = "";
+ else
+ *ppsz_demux = psz_demux;
+
+ if( psz_path == NULL )
+ *ppsz_path = "";
+ else
+ *ppsz_path = psz_path;
+}