Commit 41b93de1 authored by Laurent Aimar's avatar Laurent Aimar

* input.c: fixed play/pause + cosmetics.

parent 48ec5870
......@@ -59,6 +59,14 @@ static void UpdateFromDemux( input_thread_t * );
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
......@@ -131,6 +139,10 @@ input_thread_t *__input_CreateThread( vlc_object_t *p_parent,
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;
......@@ -308,7 +320,7 @@ static int Run( input_thread_t *p_input )
}
/* 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;
......@@ -350,7 +362,6 @@ static int Run( input_thread_t *p_input )
/* 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
......@@ -383,6 +394,11 @@ static int Run( input_thread_t *p_input )
{
p_input->b_error = VLC_TRUE;
}
if( i_ret > 0 && p_input->i_slave > 0 )
{
SlaveDemux( p_input );
}
}
else
{
......@@ -447,139 +463,32 @@ static int Run( input_thread_t *p_input )
}
}
/* 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
}
/*****************************************************************************
......@@ -587,53 +496,9 @@ static int Run( input_thread_t *p_input )
*****************************************************************************/
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 )
......@@ -643,8 +508,6 @@ static int Init( input_thread_t * p_input )
{
msg_Err( p_input, "cannot start stream output instance, aborting" );
free( psz );
free( psz_dup );
return VLC_EGENERIC;
}
}
......@@ -655,147 +518,35 @@ static int Init( input_thread_t * p_input )
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;
......@@ -819,6 +570,7 @@ static int Init( input_thread_t * p_input )
/* 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 )
{
......@@ -856,7 +608,7 @@ static int Init( input_thread_t * p_input )
}
/* TODO: do subtitle loading */
/* TODO: do subtitle loading (and slave) */
/* Set up es_out */
......@@ -904,15 +656,6 @@ static int Init( input_thread_t * p_input )
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 );
......@@ -1176,6 +919,7 @@ static void Error( input_thread_t *p_input )
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 );
......@@ -1189,16 +933,18 @@ static void End( input_thread_t * p_input )
/* 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 );
......@@ -1358,6 +1104,9 @@ static vlc_bool_t Control( input_thread_t *p_input, int i_type, vlc_value_t val
}
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;
......@@ -1406,6 +1155,9 @@ static vlc_bool_t Control( input_thread_t *p_input, int i_type, vlc_value_t val
}
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 );
......@@ -1716,6 +1468,297 @@ static void UpdateFromAccess( input_thread_t *p_input )
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 );