#include <vlc_dialog.h>
#include <vlc_url.h>
#include <vlc_charset.h>
+#include <vlc_fs.h>
#include <vlc_strings.h>
#ifdef HAVE_SYS_STAT_H
static void input_ChangeState( input_thread_t *p_input, int i_state ); /* TODO fix name */
-/* Do not let a pts_delay from access/demux go beyong 60s */
-#define INPUT_PTS_DELAY_MAX INT64_C(60000000)
-
+#undef input_Create
/**
* Create a new input_thread_t.
*
* \param p_resource an optional input ressource
* \return a pointer to the spawned input thread
*/
-
-input_thread_t *__input_Create( vlc_object_t *p_parent,
- input_item_t *p_item,
- const char *psz_log, input_resource_t *p_resource )
+input_thread_t *input_Create( vlc_object_t *p_parent,
+ input_item_t *p_item,
+ const char *psz_log, input_resource_t *p_resource )
{
-
return Create( p_parent, p_item, psz_log, false, p_resource );
}
+#undef input_CreateAndStart
/**
* Create a new input_thread_t and start it.
*
*
* \see input_Create
*/
-input_thread_t *__input_CreateAndStart( vlc_object_t *p_parent,
- input_item_t *p_item, const char *psz_log )
+input_thread_t *input_CreateAndStart( vlc_object_t *p_parent,
+ input_item_t *p_item, const char *psz_log )
{
- input_thread_t *p_input = __input_Create( p_parent, p_item, psz_log, NULL );
+ input_thread_t *p_input = input_Create( p_parent, p_item, psz_log, NULL );
if( input_Start( p_input ) )
{
return p_input;
}
+#undef input_Read
/**
* Initialize an input thread and run it until it stops by itself.
*
* \param p_item an input item
* \return an error code, VLC_SUCCESS on success
*/
-int __input_Read( vlc_object_t *p_parent, input_item_t *p_item )
+int input_Read( vlc_object_t *p_parent, input_item_t *p_item )
{
input_thread_t *p_input = Create( p_parent, p_item, NULL, false, NULL );
if( !p_input )
if( !p_input->p )
return NULL;
+ /* Parse input options */
+ vlc_mutex_lock( &p_item->lock );
+ assert( (int)p_item->optflagc == p_item->i_options );
+ for( i = 0; i < p_item->i_options; i++ )
+ var_OptionParse( VLC_OBJECT(p_input), p_item->ppsz_options[i],
+ !!(p_item->optflagv[i] & VLC_INPUT_OPTION_TRUSTED) );
+ vlc_mutex_unlock( &p_item->lock );
+
p_input->b_preparsing = b_quick;
p_input->psz_header = psz_header ? strdup( psz_header ) : NULL;
p_input->p->title = NULL;
p_input->p->i_title_offset = p_input->p->i_seekpoint_offset = 0;
p_input->p->i_state = INIT_S;
- p_input->p->i_rate = INPUT_RATE_DEFAULT
- / var_CreateGetFloat( p_input, "rate" );
- /* Currently, the input rate variable is an integer. So we need to destroy
- * the float variable inherited from the configuration. */
- var_Destroy( p_input, "rate" );
+ double f_rate = var_InheritFloat( p_input, "rate" );
+ if( f_rate <= 0. )
+ {
+ msg_Warn( p_input, "Negative or zero rate values are forbidden" );
+ f_rate = 1.;
+ }
+ p_input->p->i_rate = INPUT_RATE_DEFAULT / f_rate;
p_input->p->b_recording = false;
memset( &p_input->p->bookmark, 0, sizeof(p_input->p->bookmark) );
TAB_INIT( p_input->p->i_bookmark, p_input->p->pp_bookmark );
TAB_INIT( p_input->p->i_attachment, p_input->p->attachment );
- p_input->p->p_es_out_display = NULL;
- p_input->p->p_es_out = NULL;
p_input->p->p_sout = NULL;
p_input->p->b_out_pace_control = false;
p_input->p->i_control = 0;
p_input->p->b_abort = false;
- /* Parse input options */
- vlc_mutex_lock( &p_item->lock );
- assert( (int)p_item->optflagc == p_item->i_options );
- for( i = 0; i < p_item->i_options; i++ )
- var_OptionParse( VLC_OBJECT(p_input), p_item->ppsz_options[i],
- !!(p_item->optflagv[i] & VLC_INPUT_OPTION_TRUSTED) );
- vlc_mutex_unlock( &p_item->lock );
-
/* Create Object Variables for private use only */
input_ConfigVarInit( p_input );
if( p_input->b_preparsing )
p_input->i_flags |= OBJECT_FLAGS_QUIET | OBJECT_FLAGS_NOINTERACT;
+ /* Make sure the interaction option is honored */
+ if( !var_InheritBool( p_input, "interact" ) )
+ p_input->i_flags |= OBJECT_FLAGS_NOINTERACT;
+
/* */
memset( &p_input->p->counters, 0, sizeof( p_input->p->counters ) );
vlc_mutex_init( &p_input->p->counters.counters_lock );
+ p_input->p->p_es_out_display = input_EsOutNew( p_input, p_input->p->i_rate );
+ p_input->p->p_es_out = NULL;
+
/* Set the destructor when we are sure we are initialized */
vlc_object_set_destructor( p_input, (vlc_destructor_t)Destructor );
stats_TimerDump( p_input, STATS_TIMER_INPUT_LAUNCHING );
stats_TimerClean( p_input, STATS_TIMER_INPUT_LAUNCHING );
+ if( p_input->p->p_es_out_display )
+ es_out_Delete( p_input->p->p_es_out_display );
+
if( p_input->p->p_resource )
input_resource_Delete( p_input->p->p_resource );
const int i_cr_average = var_GetInteger( p_input, "cr-average" ) * i_pts_delay / DEFAULT_PTS_DELAY;
/* */
- es_out_SetJitter( p_input->p->p_es_out, i_pts_delay, i_cr_average );
+ es_out_SetDelay( p_input->p->p_es_out_display, AUDIO_ES, i_audio_delay );
+ es_out_SetDelay( p_input->p->p_es_out_display, SPU_ES, i_spu_delay );
+ es_out_SetJitter( p_input->p->p_es_out, i_pts_delay, 0, i_cr_average );
}
static void InitPrograms( input_thread_t * p_input )
UpdatePtsDelay( p_input );
/* Set up es_out */
- es_out_Control( p_input->p->p_es_out, ES_OUT_SET_ACTIVE, true );
i_es_out_mode = ES_OUT_MODE_AUTO;
if( p_input->p->p_sout )
{
}
}
}
- es_out_Control( p_input->p->p_es_out, ES_OUT_SET_MODE, i_es_out_mode );
+ es_out_SetMode( p_input->p->p_es_out, i_es_out_mode );
/* Inform the demuxer about waited group (needed only for DVB) */
if( i_es_out_mode == ES_OUT_MODE_ALL )
static int Init( input_thread_t * p_input )
{
vlc_meta_t *p_meta;
- int i, ret;
+ int i;
for( i = 0; i < p_input->p->p_item->i_options; i++ )
{
InitStatistics( p_input );
#ifdef ENABLE_SOUT
- ret = InitSout( p_input );
- if( ret != VLC_SUCCESS )
- goto error_stats;
+ if( InitSout( p_input ) )
+ goto error;
#endif
/* Create es out */
- p_input->p->p_es_out_display = input_EsOutNew( p_input, p_input->p->i_rate );
- p_input->p->p_es_out = input_EsOutTimeshiftNew( p_input, p_input->p->p_es_out_display, p_input->p->i_rate );
- es_out_Control( p_input->p->p_es_out, ES_OUT_SET_ACTIVE, false );
- es_out_Control( p_input->p->p_es_out, ES_OUT_SET_MODE, ES_OUT_MODE_NONE );
+ p_input->p->p_es_out = input_EsOutTimeshiftNew( p_input, p_input->p->p_es_out_display, p_input->p->i_rate );
/* */
input_ChangeState( p_input, OPENING_S );
if( p_input->p->p_es_out )
es_out_Delete( p_input->p->p_es_out );
- if( p_input->p->p_es_out_display )
- es_out_Delete( p_input->p->p_es_out_display );
+ es_out_SetMode( p_input->p->p_es_out_display, ES_OUT_MODE_END );
if( p_input->p->p_resource )
{
if( p_input->p->p_sout )
input_resource_SetInput( p_input->p->p_resource, NULL );
}
-#ifdef ENABLE_SOUT
-error_stats:
-#endif
if( !p_input->b_preparsing && libvlc_stats( p_input ) )
{
#define EXIT_COUNTER( c ) do { if( p_input->p->counters.p_##c ) \
p_input->p->input.p_stream = NULL;
p_input->p->input.p_access = NULL;
p_input->p->p_es_out = NULL;
- p_input->p->p_es_out_display = NULL;
p_input->p->p_sout = NULL;
return VLC_EGENERIC;
input_ControlVarStop( p_input );
/* Stop es out activity */
- es_out_Control( p_input->p->p_es_out, ES_OUT_SET_ACTIVE, false );
- es_out_Control( p_input->p->p_es_out, ES_OUT_SET_MODE, ES_OUT_MODE_NONE );
+ es_out_SetMode( p_input->p->p_es_out, ES_OUT_MODE_NONE );
/* Clean up master */
InputSourceClean( &p_input->p->input );
/* Unload all modules */
if( p_input->p->p_es_out )
es_out_Delete( p_input->p->p_es_out );
- if( p_input->p->p_es_out_display )
- es_out_Delete( p_input->p->p_es_out_display );
+ es_out_SetMode( p_input->p->p_es_out_display, ES_OUT_MODE_END );
if( !p_input->b_preparsing )
{
break;
case INPUT_CONTROL_SET_RATE:
- case INPUT_CONTROL_SET_RATE_SLOWER:
- case INPUT_CONTROL_SET_RATE_FASTER:
{
- int i_rate;
- int i_rate_sign;
-
/* Get rate and direction */
- if( i_type == INPUT_CONTROL_SET_RATE )
- {
- i_rate = abs( val.i_int );
- i_rate_sign = val.i_int < 0 ? -1 : 1;
- }
- else
- {
- static const int ppi_factor[][2] = {
- {1,64}, {1,32}, {1,16}, {1,8}, {1,4}, {1,3}, {1,2}, {2,3},
- {1,1},
- {3,2}, {2,1}, {3,1}, {4,1}, {8,1}, {16,1}, {32,1}, {64,1},
- {0,0}
- };
- int i_error;
- int i_idx;
- int i;
-
- i_rate_sign = p_input->p->i_rate < 0 ? -1 : 1;
-
- i_error = INT_MAX;
- i_idx = -1;
- for( i = 0; ppi_factor[i][0] != 0; i++ )
- {
- const int i_test_r = INPUT_RATE_DEFAULT * ppi_factor[i][0] / ppi_factor[i][1];
- const int i_test_e = abs( abs( p_input->p->i_rate ) - i_test_r );
- if( i_test_e < i_error )
- {
- i_idx = i;
- i_error = i_test_e;
- }
- }
-
- assert( i_idx >= 0 && ppi_factor[i_idx][0] != 0 );
-
- if( i_type == INPUT_CONTROL_SET_RATE_SLOWER )
- {
- if( ppi_factor[i_idx+1][0] > 0 )
- i_rate = INPUT_RATE_DEFAULT * ppi_factor[i_idx+1][0] / ppi_factor[i_idx+1][1];
- else
- i_rate = INPUT_RATE_MAX+1;
- }
- else
- {
- assert( i_type == INPUT_CONTROL_SET_RATE_FASTER );
- if( i_idx > 0 )
- i_rate = INPUT_RATE_DEFAULT * ppi_factor[i_idx-1][0] / ppi_factor[i_idx-1][1];
- else
- i_rate = INPUT_RATE_MIN-1;
- }
- }
+ int i_rate = abs( val.i_int );
+ int i_rate_sign = val.i_int < 0 ? -1 : 1;
/* Check rate bound */
if( i_rate < INPUT_RATE_MIN )
break;
case INPUT_CONTROL_SET_AUDIO_DELAY:
- if( !es_out_SetDelay( p_input->p->p_es_out_display, AUDIO_ES, val.i_time ) )
- {
- input_SendEventAudioDelay( p_input, val.i_time );
- UpdatePtsDelay( p_input );
- }
+ input_SendEventAudioDelay( p_input, val.i_time );
+ UpdatePtsDelay( p_input );
break;
case INPUT_CONTROL_SET_SPU_DELAY:
- if( !es_out_SetDelay( p_input->p->p_es_out_display, SPU_ES, val.i_time ) )
- {
- input_SendEventSubtitleDelay( p_input, val.i_time );
- UpdatePtsDelay( p_input );
- }
+ input_SendEventSubtitleDelay( p_input, val.i_time );
+ UpdatePtsDelay( p_input );
break;
case INPUT_CONTROL_SET_TITLE:
/* Split uri */
input_SplitMRL( &psz_access, &psz_demux, &psz_path, psz_dup );
- /* FIXME: file:// handling plugins do not support URIs properly...
- * So we pre-decode the URI to a path for them. Note that we do not do it
- * for non-standard VLC-specific schemes. */
- if( !strcmp( psz_access, "file" ) )
- {
- if( psz_path[0] != '/'
-#if (DIR_SEP_CHAR != '/')
- /* We accept invalid URIs too. */
- && psz_path[0] != DIR_SEP_CHAR
-#endif
- )
- { /* host specified -> only localhost is supported */
- static const size_t i_localhost = sizeof("localhost")-1;
- if( strncmp( psz_path, "localhost/", i_localhost + 1) != 0 )
- {
- msg_Err( p_input, "cannot open remote file `%s://%s'",
- psz_access, psz_path );
- msg_Info( p_input, "Did you mean `%s:///%s'?",
- psz_access, psz_path );
- goto error;
- }
- psz_path += i_localhost;
- }
- /* Remove HTML anchor if present (not supported). */
- char *p = strchr( psz_path, '#' );
- if( p )
- *p = '\0';
- /* Then URI-decode the path. */
- decode_URI( psz_path );
-#if defined( WIN32 ) && !defined( UNDER_CE )
- /* Strip leading slash in front of the drive letter */
- psz_path++;
-#endif
-#if (DIR_SEP_CHAR != '/')
- /* Turn slashes into anti-slashes */
- for( char *s = strchr( psz_path, '/' ); s; s = strchr( s + 1, '/' ) )
- *s = DIR_SEP_CHAR;
-#endif
- }
-
msg_Dbg( p_input, "`%s' gives access `%s' demux `%s' path `%s'",
psz_mrl, psz_access, psz_demux, psz_path );
if( !p_input->b_preparsing )
psz_demux = in->p_access->psz_demux;
}
- {
- /* Take access/stream redirections into account */
- char *psz_real_path;
- char *psz_buf = NULL;
- if( in->p_stream->psz_path )
- {
- const char *psz_a, *psz_d;
- psz_buf = strdup( in->p_stream->psz_path );
- input_SplitMRL( &psz_a, &psz_d, &psz_real_path, psz_buf );
- }
- else
- {
- psz_real_path = psz_path;
- }
- in->p_demux = demux_New( p_input, p_input, psz_access, psz_demux,
- psz_real_path,
- in->p_stream, p_input->p->p_es_out,
- p_input->b_preparsing );
- free( psz_buf );
- }
+ in->p_demux = demux_New( p_input, p_input, psz_access, psz_demux,
+ /* Take access/stream redirections into account: */
+ in->p_stream->psz_path ? in->p_stream->psz_path : psz_path,
+ in->p_stream, p_input->p->p_es_out,
+ p_input->b_preparsing );
if( in->p_demux == NULL )
{
VLC_OBJECT_GENERIC, "demux meta" );
if( !p_demux_meta )
return;
+ vlc_object_attach( p_demux_meta, p_demux );
p_demux_meta->p_demux = p_demux;
p_demux_meta->p_item = p_input->p->p_item;
if( asprintf( &psz_file, psz_format, psz_base, i ) < 0 )
break;
- if( utf8_stat( psz_file, &st ) || !S_ISREG( st.st_mode ) || !st.st_size )
+ if( vlc_stat( psz_file, &st ) || !S_ISREG( st.st_mode ) || !st.st_size )
{
free( psz_file );
break;
* MRLSplit: parse the access, demux and url part of the
* Media Resource Locator.
*****************************************************************************/
-void input_SplitMRL( const char **ppsz_access, const char **ppsz_demux, char **ppsz_path,
- char *psz_dup )
+void input_SplitMRL( const char **ppsz_access, const char **ppsz_demux,
+ char **ppsz_path, char *psz_dup )
{
- char *psz_access = NULL;
- char *psz_demux = NULL;
+ const char *psz_access;
+ const char *psz_demux = "";
char *psz_path;
/* Either there is an access/demux specification before ://
*psz_path = '\0';
psz_path += 3; /* skips "://" */
- /* Separate access from demux (<access>/<demux>://<path>) */
psz_access = psz_dup;
- psz_demux = strchr( psz_access, '/' );
- if( psz_demux )
- *psz_demux++ = '\0';
-
/* We really don't want module name substitution here! */
if( psz_access[0] == '$' )
psz_access++;
- if( psz_demux && psz_demux[0] == '$' )
- psz_demux++;
+
+ /* Separate access from demux (<access>/<demux>://<path>) */
+ char *p = strchr( psz_access, '/' );
+ if( p )
+ {
+ *p = '\0';
+ psz_demux = p + 1;
+ if( psz_demux[0] == '$' )
+ psz_demux++;
+ }
+
+ /* Remove HTML anchor if present (not supported).
+ * The hash symbol itself should be URI-encoded. */
+ p = strchr( psz_path, '#' );
+ if( p )
+ *p = '\0';
}
else
{
+#ifndef NDEBUG
+ fprintf( stderr, "%s(\"%s\"): not a valid URI!\n", __func__,
+ psz_dup );
+#endif
psz_path = psz_dup;
+ psz_access = "";
}
- *ppsz_access = psz_access ? psz_access : "";
- *ppsz_demux = psz_demux ? psz_demux : "";
+
+ *ppsz_access = psz_access;
+ *ppsz_demux = psz_demux;
*ppsz_path = psz_path;
}
strcpy( psz_extension, ".idx" );
- if( !utf8_stat( psz_path, &st ) && S_ISREG( st.st_mode ) )
+ if( !vlc_stat( psz_path, &st ) && S_ISREG( st.st_mode ) )
{
msg_Dbg( p_input, "using %s subtitles file instead of %s",
psz_path, psz_subtitle );
free( psz_path );
}
+ char *url = make_URI( psz_subtitle );
+
var_Change( p_input, "spu-es", VLC_VAR_CHOICESCOUNT, &count, NULL );
sub = InputSourceNew( p_input );
- if( !sub || InputSourceInit( p_input, sub, psz_subtitle, "subtitle" ) )
+ if( !sub || !url
+ || InputSourceInit( p_input, sub, url, "subtitle" ) )
{
free( sub );
+ free( url );
return;
}
+ free( url );
TAB_APPEND( p_input->p->i_slave, p_input->p->slave, sub );
/* Select the ES */
char *psz_file;
DIR *path;
- path = utf8_opendir( psz_path );
+ path = vlc_opendir( psz_path );
if( path )
{
closedir( path );
if( !psz_tmp )
return NULL;
- char *psz_tmp2 = filename_sanitize( psz_tmp );
- free( psz_tmp );
+ filename_sanitize( psz_tmp );
- if( !psz_tmp2 ||
- asprintf( &psz_file, "%s"DIR_SEP"%s%s%s",
- psz_path, psz_tmp2,
+ if( asprintf( &psz_file, "%s"DIR_SEP"%s%s%s",
+ psz_path, psz_tmp,
psz_extension ? "." : "",
psz_extension ? psz_extension : "" ) < 0 )
psz_file = NULL;
- free( psz_tmp2 );
+ free( psz_tmp );
return psz_file;
}
else