X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Finput%2Finput.c;h=971284bcf013e2a7d7b96438c8549eeeee4ea63e;hb=dc06ad9ff8c25518ebbc81463b2ec85d8fd874c2;hp=ad162a985e80fb00628541c63a20964a633f6d2a;hpb=42a0d047849f391a75432dfdf5d71523d6ec08c7;p=vlc diff --git a/src/input/input.c b/src/input/input.c index ad162a985e..971284bcf0 100644 --- a/src/input/input.c +++ b/src/input/input.c @@ -29,7 +29,7 @@ # include "config.h" #endif -#include +#include #include #include @@ -43,7 +43,6 @@ #include #include #include -#include #ifdef HAVE_SYS_STAT_H # include @@ -54,13 +53,13 @@ *****************************************************************************/ static void Destructor( input_thread_t * p_input ); -static int Run ( input_thread_t *p_input ); -static int RunAndDestroy ( input_thread_t *p_input ); +static void* Run ( vlc_object_t *p_this ); +static void* RunAndDestroy ( vlc_object_t *p_this ); static input_thread_t * Create ( vlc_object_t *, input_item_t *, const char *, bool, sout_instance_t * ); static int Init ( input_thread_t *p_input ); -static void Error ( input_thread_t *p_input ); +static void WaitDie ( input_thread_t *p_input ); static void End ( input_thread_t *p_input ); static void MainLoop( input_thread_t *p_input ); @@ -87,9 +86,6 @@ static void SlaveSeek( input_thread_t *p_input ); static void InputMetaUser( input_thread_t *p_input, vlc_meta_t *p_meta ); static void InputUpdateMeta( input_thread_t *p_input, vlc_meta_t *p_meta ); -static sout_instance_t *SoutFind( vlc_object_t *p_parent, input_item_t *p_item, bool * ); -static void SoutKeep( sout_instance_t * ); - static void DemuxMeta( input_thread_t *p_input, vlc_meta_t *p_meta, demux_t *p_demux ); static void AccessMeta( input_thread_t * p_input, vlc_meta_t *p_meta ); static void AppendAttachment( int *pi_attachment, input_attachment_t ***ppp_attachment, @@ -116,6 +112,7 @@ static void AppendAttachment( int *pi_attachment, input_attachment_t ***ppp_atta * - seekable (if you can seek, it doesn't say if 'bar display' has be shown * or not, for that check position != 0.0) * - can-pause + * - teletext-es to get the index of spu track that is teletext --1 if no teletext) * * For intf callback upon changes * - intf-change * - rate-change for when playback rate changes @@ -135,16 +132,16 @@ static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item, p_input = vlc_custom_create( p_parent, sizeof( *p_input ), VLC_OBJECT_INPUT, input_name ); if( p_input == NULL ) - { - msg_Err( p_parent, "out of memory" ); return NULL; - } /* Construct a nice name for the input timer */ char psz_timer_name[255]; char * psz_name = input_item_GetName( p_item ); snprintf( psz_timer_name, sizeof(psz_timer_name), "input launching for '%s'", psz_name ); + + msg_Dbg( p_input, "Creating an input for '%s'", psz_name); + free( psz_name ); /* Start a timer to mesure how long it takes @@ -153,22 +150,28 @@ static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item, STATS_TIMER_INPUT_LAUNCHING ); MALLOC_NULL( p_input->p, input_thread_private_t ); + memset( p_input->p, 0, sizeof( input_thread_private_t ) ); /* One "randomly" selected input thread is responsible for computing * the global stats. Check if there is already someone doing this */ if( p_input->p_libvlc->p_stats && !b_quick ) { + libvlc_priv_t *priv = libvlc_priv (p_input->p_libvlc); vlc_mutex_lock( &p_input->p_libvlc->p_stats->lock ); - if( p_input->p_libvlc->p_stats_computer == NULL ) - { - p_input->p_libvlc->p_stats_computer = p_input; - } + if( priv->p_stats_computer == NULL ) + priv->p_stats_computer = p_input; vlc_mutex_unlock( &p_input->p_libvlc->p_stats->lock ); } p_input->b_preparsing = b_quick; p_input->psz_header = psz_header ? strdup( psz_header ) : NULL; + /* Init events */ + vlc_event_manager_t * p_em = &p_input->p->event_manager; + vlc_event_manager_init_with_vlc_object( p_em, p_input ); + vlc_event_manager_register_event_type( p_em, vlc_InputStateChanged ); + vlc_event_manager_register_event_type( p_em, vlc_InputSelectedStreamChanged ); + /* Init Common fields */ p_input->b_eof = false; p_input->b_can_pace_control = true; @@ -185,8 +188,6 @@ static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item, TAB_INIT( p_input->p->i_attachment, p_input->p->attachment ); p_input->p->p_es_out = NULL; p_input->p->p_sout = NULL; - p_input->p->b_owns_its_sout = true; - p_input->p->b_sout_keep = false; p_input->p->b_out_pace_control = false; p_input->i_pts_delay = 0; @@ -217,12 +218,12 @@ static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item, p_input->p->slave = NULL; /* Init control buffer */ - vlc_mutex_init( p_input, &p_input->p->lock_control ); + vlc_mutex_init( &p_input->p->lock_control ); p_input->p->i_control = 0; /* Parse input options */ vlc_mutex_lock( &p_item->lock ); - assert( p_item->optflagc == p_item->i_options ); + 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) ); @@ -273,7 +274,7 @@ static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item, } psz_start = psz_end + 1; } - msg_Dbg( p_input, "adding bookmark: %s, bytes="I64Fd", time="I64Fd, + msg_Dbg( p_input, "adding bookmark: %s, bytes=%"PRId64", time=%"PRId64, p_seekpoint->psz_name, p_seekpoint->i_byte_offset, p_seekpoint->i_time_offset ); input_Control( p_input, INPUT_ADD_BOOKMARK, p_seekpoint ); @@ -285,9 +286,6 @@ static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item, } /* Remove 'Now playing' info as it is probably outdated */ - input_Control( p_input, INPUT_DEL_INFO, - _(VLC_META_INFO_CAT), - _(VLC_META_NOW_PLAYING) ); input_item_SetNowPlaying( p_item, NULL ); /* */ @@ -296,20 +294,17 @@ static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item, /* */ if( p_sout ) - { p_input->p->p_sout = p_sout; - p_input->p->b_owns_its_sout = false; - } memset( &p_input->p->counters, 0, sizeof( p_input->p->counters ) ); - vlc_mutex_init( p_input, &p_input->p->counters.counters_lock ); - - /* Attach only once we are ready */ - vlc_object_attach( p_input, p_parent ); + vlc_mutex_init( &p_input->p->counters.counters_lock ); /* Set the destructor when we are sure we are initialized */ vlc_object_set_destructor( p_input, (vlc_destructor_t)Destructor ); + /* Attach only once we are ready */ + vlc_object_attach( p_input, p_parent ); + return p_input; } @@ -320,17 +315,20 @@ static void Destructor( input_thread_t * p_input ) { input_thread_private_t *priv = p_input->p; - stats_TimerDump( p_input, STATS_TIMER_INPUT_LAUNCHING ); - stats_TimerClean( p_input, STATS_TIMER_INPUT_LAUNCHING ); +#ifndef NDEBUG + char * psz_name = input_item_GetName( p_input->p->input.p_item ); + msg_Dbg( p_input, "Destroying the input for '%s'", psz_name); + free( psz_name ); +#endif - if( priv->b_owns_its_sout && priv->p_sout ) - { - if( priv->b_sout_keep ) - SoutKeep( priv->p_sout ); - else - sout_DeleteInstance( priv->p_sout ); - } + vlc_event_manager_fini( &p_input->p->event_manager ); + stats_TimerDump( p_input, STATS_TIMER_INPUT_LAUNCHING ); + stats_TimerClean( p_input, STATS_TIMER_INPUT_LAUNCHING ); +#ifdef ENABLE_SOUT + if( priv->p_sout ) + sout_DeleteInstance( priv->p_sout ); +#endif vlc_gc_decref( p_input->p->input.p_item ); vlc_mutex_destroy( &p_input->p->counters.counters_lock ); @@ -350,15 +348,7 @@ static void Destructor( input_thread_t * p_input ) input_thread_t *__input_CreateThread( vlc_object_t *p_parent, input_item_t *p_item ) { - bool b_sout_keep; - sout_instance_t *p_sout = SoutFind( p_parent, p_item, &b_sout_keep ); - input_thread_t *p_input = __input_CreateThreadExtended( p_parent, p_item, NULL, p_sout ); - - if( !p_input && p_sout ) - SoutKeep( p_sout ); - - p_input->p->b_sout_keep = b_sout_keep; - return p_input; + return __input_CreateThreadExtended( p_parent, p_item, NULL, NULL ); } /* */ @@ -387,7 +377,7 @@ input_thread_t *__input_CreateThreadExtended( vlc_object_t *p_parent, } /** - * Initialize an input thread and run it. This thread will clean after himself, + * Initialize an input thread and run it. This thread will clean after itself, * you can forget about it. It can work either in blocking or non-blocking mode * * \param p_parent a vlc_object @@ -398,21 +388,15 @@ input_thread_t *__input_CreateThreadExtended( vlc_object_t *p_parent, int __input_Read( vlc_object_t *p_parent, input_item_t *p_item, bool b_block ) { - bool b_sout_keep; - sout_instance_t *p_sout = SoutFind( p_parent, p_item, &b_sout_keep ); input_thread_t *p_input; - p_input = Create( p_parent, p_item, NULL, false, p_sout ); - if( !p_input && p_sout ) - { - SoutKeep( p_sout ); + p_input = Create( p_parent, p_item, NULL, false, NULL ); + if( !p_input ) return VLC_EGENERIC; - } - p_input->p->b_sout_keep = b_sout_keep; if( b_block ) { - RunAndDestroy( p_input ); + RunAndDestroy( VLC_OBJECT(p_input) ); return VLC_SUCCESS; } else @@ -460,49 +444,39 @@ int __input_Preparse( vlc_object_t *p_parent, input_item_t *p_item ) * * \param the input thread to stop */ -void input_StopThread( input_thread_t *p_input ) +static void ObjectKillChildrens( input_thread_t *p_input, vlc_object_t *p_obj ) { vlc_list_t *p_list; int i; - /* Set die for input */ - vlc_object_kill( p_input ); - /* FIXME: seems to be duplicated in ControlPush(INPUT_CONTROL_SET_DIE) */ + if( p_obj->i_object_type == VLC_OBJECT_VOUT || + p_obj->i_object_type == VLC_OBJECT_AOUT || + p_obj == VLC_OBJECT(p_input->p->p_sout) ) + return; - /* We cannot touch p_input fields directly (we come from another thread), - * so use the vlc_object_find way, it's perfectly safe */ + vlc_object_kill( p_obj ); - /* Set die for all access */ - p_list = vlc_list_find( p_input, VLC_OBJECT_ACCESS, FIND_CHILD ); + p_list = vlc_list_children( p_obj ); for( i = 0; i < p_list->i_count; i++ ) - { - vlc_object_kill( p_list->p_values[i].p_object ); - } - vlc_list_release( p_list ); - - /* Set die for all stream */ - p_list = vlc_list_find( p_input, VLC_OBJECT_STREAM, FIND_CHILD ); - for( i = 0; i < p_list->i_count; i++ ) - { - vlc_object_kill( p_list->p_values[i].p_object ); - } - vlc_list_release( p_list ); - - /* Set die for all demux */ - p_list = vlc_list_find( p_input, VLC_OBJECT_DEMUX, FIND_CHILD ); - for( i = 0; i < p_list->i_count; i++ ) - { - vlc_object_kill( p_list->p_values[i].p_object ); - } + ObjectKillChildrens( p_input, p_list->p_values[i].p_object ); vlc_list_release( p_list ); +} +void input_StopThread( input_thread_t *p_input ) +{ + /* Set die for input and ALL of this childrens (even (grand-)grand-childrens) + * It is needed here even if it is done in INPUT_CONTROL_SET_DIE handler to + * unlock the control loop */ + ObjectKillChildrens( p_input, VLC_OBJECT(p_input) ); input_ControlPush( p_input, INPUT_CONTROL_SET_DIE, NULL ); } sout_instance_t * input_DetachSout( input_thread_t *p_input ) { - p_input->p->b_owns_its_sout = false; - return p_input->p->p_sout; + sout_instance_t *p_sout = p_input->p->p_sout; + vlc_object_detach( p_sout ); + p_input->p->p_sout = NULL; + return p_sout; } /***************************************************************************** @@ -510,8 +484,9 @@ sout_instance_t * input_DetachSout( input_thread_t *p_input ) * This is the "normal" thread that spawns the input processing chain, * reads the stream, cleans up and waits *****************************************************************************/ -static int Run( input_thread_t *p_input ) +static void* Run( vlc_object_t *p_this ) { + input_thread_t *p_input = (input_thread_t *)p_this; /* Signal that the thread is launched */ vlc_thread_ready( p_input ); @@ -520,21 +495,12 @@ static int Run( input_thread_t *p_input ) /* If we failed, wait before we are killed, and exit */ p_input->b_error = true; - /* FIXME: we don't want to depend on the playlist */ - playlist_t * p_playlist = vlc_object_find( p_input, - VLC_OBJECT_PLAYLIST, FIND_PARENT ); - if( p_playlist ) - { - playlist_Signal( p_playlist ); - vlc_object_release( p_playlist ); - } - - Error( p_input ); + WaitDie( p_input ); /* Tell we're dead */ p_input->b_dead = true; - return 0; + return NULL; } MainLoop( p_input ); @@ -554,19 +520,19 @@ static int Run( input_thread_t *p_input ) /* We have finished */ p_input->b_eof = true; - playlist_Signal( pl_Get( p_input ) ); + input_ChangeState( p_input, END_S ); } /* Wait until we are asked to die */ if( !p_input->b_die ) { - Error( p_input ); + WaitDie( p_input ); } /* Clean up */ End( p_input ); - return 0; + return NULL; } /***************************************************************************** @@ -574,8 +540,9 @@ static int Run( input_thread_t *p_input ) * This is the "just forget me" thread that spawns the input processing chain, * reads the stream, cleans up and releases memory *****************************************************************************/ -static int RunAndDestroy( input_thread_t *p_input ) +static void* RunAndDestroy( vlc_object_t *p_this ) { + input_thread_t *p_input = (input_thread_t *)p_this; /* Signal that the thread is launched */ vlc_thread_ready( p_input ); @@ -665,7 +632,6 @@ static void MainLoop( input_thread_t *p_input ) { /* End of file - we do not set b_die because only the * playlist is allowed to do so. */ - input_ChangeState( p_input, END_S ); msg_Dbg( p_input, "EOF reached" ); p_input->p->input.b_eof = true; } @@ -772,17 +738,17 @@ static void MainLoop( input_thread_t *p_input ) } var_SetBool( p_input, "intf-change", true ); - i_intf_update = mdate() + I64C(150000); + i_intf_update = mdate() + INT64_C(150000); } /* 150ms * 8 = ~ 1 second */ if( ++i_updates % 8 == 0 ) { stats_ComputeInputStats( p_input, p_input->p->input.p_item->p_stats ); /* Are we the thread responsible for computing global stats ? */ - if( p_input->p_libvlc->p_stats_computer == p_input ) + if( libvlc_priv (p_input->p_libvlc)->p_stats_computer == p_input ) { stats_ComputeGlobalStats( p_input->p_libvlc, - p_input->p_libvlc->p_stats ); + p_input->p_libvlc->p_stats ); } } } @@ -795,7 +761,7 @@ static void InitStatistics( input_thread_t * p_input ) /* Prepare statistics */ #define INIT_COUNTER( c, type, compute ) p_input->p->counters.p_##c = \ stats_CounterCreate( p_input, VLC_VAR_##type, STATS_##compute); - if( p_input->p_libvlc->b_stats ) + if( libvlc_stats (p_input) ) { INIT_COUNTER( read_bytes, INTEGER, COUNTER ); INIT_COUNTER( read_packets, INTEGER, COUNTER ); @@ -819,6 +785,7 @@ static void InitStatistics( input_thread_t * p_input ) } } +#ifdef ENABLE_SOUT static int InitSout( input_thread_t * p_input ) { char *psz; @@ -862,7 +829,7 @@ static int InitSout( input_thread_t * p_input ) return VLC_EGENERIC; } } - if( p_input->p_libvlc->b_stats ) + if( libvlc_stats (p_input) ) { INIT_COUNTER( sout_sent_packets, INTEGER, COUNTER ); INIT_COUNTER (sout_sent_bytes, INTEGER, COUNTER ); @@ -883,6 +850,7 @@ static int InitSout( input_thread_t * p_input ) return VLC_SUCCESS; } +#endif static void InitTitle( input_thread_t * p_input ) { @@ -929,6 +897,7 @@ static void StartTitle( input_thread_t * p_input ) int i, i_delay; char *psz; char *psz_subtitle; + int64_t i_length; /* Start title/chapter */ @@ -949,9 +918,10 @@ static void StartTitle( input_thread_t * p_input ) /* Start time*/ /* Set start time */ - p_input->p->i_start = I64C(1000000) * var_GetInteger( p_input, "start-time" ); - p_input->p->i_stop = I64C(1000000) * var_GetInteger( p_input, "stop-time" ); - p_input->p->i_run = I64C(1000000) * var_GetInteger( p_input, "run-time" ); + p_input->p->i_start = INT64_C(1000000) * var_GetInteger( p_input, "start-time" ); + p_input->p->i_stop = INT64_C(1000000) * var_GetInteger( p_input, "stop-time" ); + p_input->p->i_run = INT64_C(1000000) * var_GetInteger( p_input, "run-time" ); + i_length = var_GetTime( p_input, "length" ); if( p_input->p->i_run < 0 ) { msg_Warn( p_input, "invalid run-time ignored" ); @@ -960,7 +930,7 @@ static void StartTitle( input_thread_t * p_input ) if( p_input->p->i_start > 0 ) { - if( p_input->p->i_start >= val.i_time ) + if( p_input->p->i_start >= i_length ) { msg_Warn( p_input, "invalid start-time ignored" ); } @@ -969,7 +939,7 @@ static void StartTitle( input_thread_t * p_input ) vlc_value_t s; msg_Dbg( p_input, "starting at time: %ds", - (int)( p_input->p->i_start / I64C(1000000) ) ); + (int)( p_input->p->i_start / INT64_C(1000000) ) ); s.i_time = p_input->p->i_start; input_ControlPush( p_input, INPUT_CONTROL_SET_TIME, &s ); @@ -1159,10 +1129,11 @@ static int Init( input_thread_t * p_input ) } InitStatistics( p_input ); +#ifdef ENABLE_SOUT ret = InitSout( p_input ); - if( ret != VLC_SUCCESS ) return ret; /* FIXME: goto error; should be better here */ +#endif /* Create es out */ p_input->p->p_es_out = input_EsOutNew( p_input, p_input->p->i_rate ); @@ -1247,15 +1218,15 @@ error: if( p_input->p->p_es_out ) input_EsOutDelete( p_input->p->p_es_out ); - +#ifdef ENABLE_SOUT if( p_input->p->p_sout ) { vlc_object_detach( p_input->p->p_sout ); sout_DeleteInstance( p_input->p->p_sout ); } +#endif - - if( !p_input->b_preparsing && p_input->p_libvlc->b_stats ) + if( !p_input->b_preparsing && libvlc_stats (p_input) ) { #define EXIT_COUNTER( c ) do { if( p_input->p->counters.p_##c ) \ stats_CounterClean( p_input->p->counters.p_##c );\ @@ -1293,13 +1264,13 @@ error: } /***************************************************************************** - * Error: RunThread() error loop + * WaitDie: Wait until we are asked to die. ***************************************************************************** * This function is called when an error occurred during thread main's loop. *****************************************************************************/ -static void Error( input_thread_t *p_input ) +static void WaitDie( input_thread_t *p_input ) { - input_ChangeState( p_input, ERROR_S ); + input_ChangeState( p_input, p_input->b_error ? ERROR_S : END_S ); while( !p_input->b_die ) { /* Sleep a while */ @@ -1318,7 +1289,7 @@ static void End( input_thread_t * p_input ) input_ChangeState( p_input, END_S ); /* Clean control variables */ - input_ControlVarClean( p_input ); + input_ControlVarStop( p_input ); /* Clean up master */ InputSourceClean( &p_input->p->input ); @@ -1338,15 +1309,17 @@ static void End( input_thread_t * p_input ) if( !p_input->b_preparsing ) { #define CL_CO( c ) stats_CounterClean( p_input->p->counters.p_##c ); p_input->p->counters.p_##c = NULL; - if( p_input->p_libvlc->b_stats ) + if( libvlc_stats (p_input) ) { + libvlc_priv_t *priv = libvlc_priv (p_input->p_libvlc); + /* make sure we are up to date */ stats_ComputeInputStats( p_input, p_input->p->input.p_item->p_stats ); - if( p_input->p_libvlc->p_stats_computer == p_input ) + if( priv->p_stats_computer == p_input ) { stats_ComputeGlobalStats( p_input->p_libvlc, p_input->p_libvlc->p_stats ); - p_input->p_libvlc->p_stats_computer = NULL; + priv->p_stats_computer = NULL; } CL_CO( read_bytes ); CL_CO( read_packets ); @@ -1385,63 +1358,6 @@ static void End( input_thread_t * p_input ) p_input->b_dead = true; } -static sout_instance_t *SoutFind( vlc_object_t *p_parent, input_item_t *p_item, bool *pb_sout_keep ) -{ - bool b_keep_sout = var_CreateGetBool( p_parent, "sout-keep" ); - sout_instance_t *p_sout = NULL; - int i; - - /* Search sout-keep options - * XXX it has to be done here, but it is duplicated work :( */ - vlc_mutex_lock( &p_item->lock ); - for( i = 0; i < p_item->i_options; i++ ) - { - const char *psz_option = p_item->ppsz_options[i]; - if( !psz_option ) - continue; - if( *psz_option == ':' ) - psz_option++; - - if( !strcmp( psz_option, "sout-keep" ) ) - b_keep_sout = true; - else if( !strcmp( psz_option, "no-sout-keep" ) || !strcmp( psz_option, "nosout-keep" ) ) - b_keep_sout = false; - } - vlc_mutex_unlock( &p_item->lock ); - - /* Find a potential sout to reuse - * XXX it might be unusable but this will be checked later */ - if( b_keep_sout ) - { - p_sout = vlc_object_find( p_parent->p_libvlc, VLC_OBJECT_SOUT, - FIND_CHILD ); - if( p_sout ) - { - if( p_sout->p_parent != VLC_OBJECT( p_sout->p_libvlc ) ) - { - vlc_object_release( p_sout ); - p_sout = NULL; - } - else - { - vlc_object_detach( p_sout ); /* Remove it from the GC */ - vlc_object_release( p_sout ); - } - } - } - - if( pb_sout_keep ) - *pb_sout_keep = b_keep_sout; - - return p_sout; -} - -static void SoutKeep( sout_instance_t *p_sout ) -{ - msg_Dbg( p_sout, "sout has been kept" ); - vlc_object_attach( p_sout, p_sout->p_libvlc ); -} - /***************************************************************************** * Control *****************************************************************************/ @@ -1527,14 +1443,9 @@ static bool Control( input_thread_t *p_input, int i_type, { case INPUT_CONTROL_SET_DIE: msg_Dbg( p_input, "control: stopping input" ); - /* Mark all submodules to die */ - if( p_input->p->input.p_access ) - vlc_object_kill( p_input->p->input.p_access ); - if( p_input->p->input.p_stream ) - vlc_object_kill( p_input->p->input.p_stream ); - vlc_object_kill( p_input->p->input.p_demux ); - vlc_object_kill( p_input ); + /* Mark all submodules to die */ + ObjectKillChildrens( p_input, VLC_OBJECT(p_input) ); break; case INPUT_CONTROL_SET_POSITION: @@ -1612,7 +1523,7 @@ static bool Control( input_thread_t *p_input, int i_type, } if( i_ret ) { - msg_Warn( p_input, "INPUT_CONTROL_SET_TIME(_OFFSET) "I64Fd + msg_Warn( p_input, "INPUT_CONTROL_SET_TIME(_OFFSET) %"PRId64 " failed or not possible", i_time ); } else @@ -1649,9 +1560,7 @@ static bool Control( input_thread_t *p_input, int i_type, b_force_update = true; /* Switch to play */ - p_input->i_state = PLAYING_S; - val.i_int = PLAYING_S; - var_Change( p_input, "state", VLC_VAR_SETVALUE, &val, NULL ); + input_ChangeStateWithVarCallback( p_input, PLAYING_S, false ); /* */ if( !i_ret ) @@ -1660,7 +1569,7 @@ static bool Control( input_thread_t *p_input, int i_type, else if( val.i_int == PAUSE_S && p_input->i_state == PLAYING_S && p_input->p->b_can_pause ) { - int i_ret; + int i_ret, state; if( p_input->p->input.p_access ) i_ret = access_Control( p_input->p->input.p_access, ACCESS_SET_PAUSE_STATE, true ); @@ -1673,16 +1582,15 @@ static bool Control( input_thread_t *p_input, int i_type, if( i_ret ) { msg_Warn( p_input, "cannot set pause state" ); - val.i_int = p_input->i_state; + state = p_input->i_state; } else { - val.i_int = PAUSE_S; + state = PAUSE_S; } /* Switch to new state */ - p_input->i_state = val.i_int; - var_Change( p_input, "state", VLC_VAR_SETVALUE, &val, NULL ); + input_ChangeStateWithVarCallback( p_input, state, false ); /* */ if( !i_ret ) @@ -1693,8 +1601,7 @@ static bool Control( input_thread_t *p_input, int i_type, b_force_update = true; /* Correct "state" value */ - val.i_int = p_input->i_state; - var_Change( p_input, "state", VLC_VAR_SETVALUE, &val, NULL ); + input_ChangeStateWithVarCallback( p_input, p_input->i_state, false ); } else if( val.i_int != PLAYING_S && val.i_int != PAUSE_S ) { @@ -2104,7 +2011,6 @@ static int UpdateFromAccess( input_thread_t *p_input ) vlc_meta_t *p_meta = vlc_meta_New(); access_Control( p_input->p->input.p_access,ACCESS_GET_META, p_meta ); InputUpdateMeta( p_input, p_meta ); - var_SetInteger( pl_Get( p_input ), "item-change", p_input->p->input.p_item->i_id ); p_access->info.i_update &= ~INPUT_UPDATE_META; } @@ -2143,14 +2049,6 @@ static int UpdateFromAccess( input_thread_t *p_input ) static void UpdateItemLength( input_thread_t *p_input, int64_t i_length ) { input_item_SetDuration( p_input->p->input.p_item, (mtime_t) i_length ); - - if( !p_input->b_preparsing ) - { - pl_Yield( p_input ); - var_SetInteger( pl_Get( p_input ), "item-change", - p_input->p->input.p_item->i_id ); - pl_Release( p_input ); - } } /***************************************************************************** @@ -2158,28 +2056,10 @@ static void UpdateItemLength( input_thread_t *p_input, int64_t i_length ) *****************************************************************************/ static input_source_t *InputSourceNew( input_thread_t *p_input ) { + (void)p_input; input_source_t *in = (input_source_t*) malloc( sizeof( input_source_t ) ); - - if( !in ) - { - msg_Err( p_input, "out of memory for new input source" ); - return NULL; - } - - in->p_item = NULL; - in->p_access = NULL; - in->p_stream = NULL; - in->p_demux = NULL; - in->b_title_demux = false; - TAB_INIT( in->i_title, in->title ); - in->b_can_pause = true; - in->b_can_pace_control = true; - in->b_can_rate_control = true; - in->b_rescale_ts = true; - in->b_eof = false; - in->f_fps = 0.0; - in->i_cr_average = 0; - + if( in ) + memset( in, 0, sizeof( input_source_t ) ); return in; } @@ -2205,7 +2085,7 @@ static int InputSourceInit( input_thread_t *p_input, if( !p_input ) return VLC_EGENERIC; /* Split uri */ - MRLSplit( psz_dup, &psz_access, &psz_demux, &psz_path ); + input_SplitMRL( &psz_access, &psz_demux, &psz_path, psz_dup ); msg_Dbg( p_input, "`%s' gives access `%s' demux `%s' path `%s'", psz_mrl, psz_access, psz_demux, psz_path ); @@ -2412,7 +2292,7 @@ static int InputSourceInit( input_thread_t *p_input, { const char *psz_a, *psz_d; psz_buf = strdup( in->p_access->psz_path ); - MRLSplit( psz_buf, &psz_a, &psz_d, &psz_real_path ); + input_SplitMRL( &psz_a, &psz_d, &psz_real_path, psz_buf ); } else { @@ -2630,7 +2510,6 @@ static void InputUpdateMeta( input_thread_t *p_input, vlc_meta_t *p_meta ) input_item_t *p_item = p_input->p->input.p_item; char * psz_arturl = NULL; char *psz_title = NULL; - int i; int i_arturl_event = false; if( !p_meta ) @@ -2694,19 +2573,6 @@ static void InputUpdateMeta( input_thread_t *p_input, vlc_meta_t *p_meta ) free( psz_title ); } - if( p_meta ) - { - char ** ppsz_all_keys = vlc_dictionary_all_keys( &p_meta->extra_tags ); - for( i = 0; ppsz_all_keys[i]; i++ ) - { - input_Control( p_input, INPUT_ADD_INFO, _(VLC_META_INFO_CAT), _(ppsz_all_keys[i]), - vlc_dictionary_value_for_key( &p_meta->extra_tags, ppsz_all_keys[i] ) ); - free( ppsz_all_keys[i] ); - } - free( ppsz_all_keys ); - vlc_meta_Delete( p_meta ); - } - /** \todo handle sout meta */ } @@ -2808,8 +2674,8 @@ static void DemuxMeta( input_thread_t *p_input, vlc_meta_t *p_meta, demux_t *p_d * MRLSplit: parse the access, demux and url part of the * Media Resource Locator. *****************************************************************************/ -void MRLSplit( char *psz_dup, const char **ppsz_access, const char **ppsz_demux, - char **ppsz_path ) +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; @@ -2828,15 +2694,34 @@ void MRLSplit( char *psz_dup, const char **ppsz_access, const char **ppsz_demux, 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++; } else { psz_path = psz_dup; } + *ppsz_access = psz_access ? psz_access : (char*)""; + *ppsz_demux = psz_demux ? psz_demux : (char*)""; + *ppsz_path = psz_path; +} - *ppsz_access = psz_access ? psz_access : ""; - *ppsz_demux = psz_demux ? psz_demux : ""; - *ppsz_path = psz_path ? psz_path : ""; +static inline bool next(char ** src) +{ + char *end; + errno = 0; + long result = strtol( *src, &end, 0 ); + if( errno != 0 || result >= LONG_MAX || result <= LONG_MIN || + end == *src ) + { + return false; + } + *src = end; + return true; } /***************************************************************************** @@ -2857,19 +2742,30 @@ static void MRLSections( input_thread_t *p_input, char *psz_source, /* Start by parsing titles and chapters */ if( !psz_source || !( psz = strrchr( psz_source, '@' ) ) ) return; + /* Check we are really dealing with a title/chapter section */ psz_check = psz + 1; if( !*psz_check ) return; - if( isdigit(*psz_check) ) strtol( psz_check, &psz_check, 0 ); + if( isdigit(*psz_check) ) + if(!next(&psz_check)) return; if( *psz_check != ':' && *psz_check != '-' && *psz_check ) return; if( *psz_check == ':' && ++psz_check ) - if( isdigit(*psz_check) ) strtol( psz_check, &psz_check, 0 ); + { + if( isdigit(*psz_check) ) + if(!next(&psz_check)) return; + } if( *psz_check != '-' && *psz_check ) return; if( *psz_check == '-' && ++psz_check ) - if( isdigit(*psz_check) ) strtol( psz_check, &psz_check, 0 ); + { + if( isdigit(*psz_check) ) + if(!next(&psz_check)) return; + } if( *psz_check != ':' && *psz_check ) return; if( *psz_check == ':' && ++psz_check ) - if( isdigit(*psz_check) ) strtol( psz_check, &psz_check, 0 ); + { + if( isdigit(*psz_check) ) + if(!next(&psz_check)) return; + } if( *psz_check ) return; /* Separate start and end */ @@ -2971,3 +2867,11 @@ bool input_AddSubtitles( input_thread_t *p_input, char *psz_subtitle, return true; } + +/***************************************************************************** + * input_get_event_manager + *****************************************************************************/ +vlc_event_manager_t *input_get_event_manager( input_thread_t *p_input ) +{ + return &p_input->p->event_manager; +}