From 80684e7846b29534eab9d1844e77516efbc42055 Mon Sep 17 00:00:00 2001 From: Laurent Aimar Date: Fri, 8 May 2009 02:03:05 +0200 Subject: [PATCH] Fixed a race condition with input creation and events. input_CreateThread* have been splitted in two functions: - input_Create - input_Start to allow attaching to input events and creating settings/variables before starting the input thread. For consistency, input_StopThread has been renamed input_Stop. Initial report from Hugo Beauzee-Luyssen. --- include/vlc_input.h | 67 ++--- modules/services_discovery/podcast.c | 28 ++- src/control/media_player.c | 14 +- src/input/input.c | 362 ++++++++++++++------------- src/input/input_interface.h | 7 - src/input/vlm.c | 17 +- src/libvlccore.sym | 6 +- src/playlist/item.c | 2 +- src/playlist/thread.c | 15 +- 9 files changed, 283 insertions(+), 235 deletions(-) diff --git a/include/vlc_input.h b/include/vlc_input.h index f7fc5f700c..06f6fc2bf3 100644 --- a/include/vlc_input.h +++ b/include/vlc_input.h @@ -248,14 +248,16 @@ static inline void vlc_input_attachment_Delete( input_attachment_t *a ) #define INPUT_UPDATE_META 0x0040 #define INPUT_UPDATE_SIGNAL 0x0080 -/** Get the input item for an input thread - * FIXME see src/input/item.c but is is unsafe unless - * you hold p_input +/** + * This defines private core storage for an input. */ -VLC_EXPORT(input_item_t*, input_GetItem, (input_thread_t*)); - typedef struct input_thread_private_t input_thread_private_t; +/** + * This defines an opaque input resource handler. + */ +typedef struct input_resource_t input_resource_t; + /** * Main structure representing an input thread. This structure is mostly * private. The only public fields are READ-ONLY. You must use the helpers @@ -431,32 +433,9 @@ typedef enum input_event_type_e } input_event_type_e; -/** @}*/ - -/***************************************************************************** - * Prototypes - *****************************************************************************/ - /** - * It will create a new input thread. - * - * You must call input_StopThread() on it and then vlc_object_release(). + * Input queries */ -#define input_CreateThread(a,b) __input_CreateThread(VLC_OBJECT(a),b) -VLC_EXPORT( input_thread_t *, __input_CreateThread, ( vlc_object_t *, input_item_t * ) ); - -/** - * It will ask a input_thread_t to stop. - * - * b_abort must be true when a user stop is requested and not because you have - * detected an error or an eof. It will be used to properly send the - * INPUT_EVENT_ABORT event. - */ -VLC_EXPORT( void, input_StopThread, ( input_thread_t *, bool b_abort ) ); - -#define input_Read(a,b,c) __input_Read(VLC_OBJECT(a),b, c) -VLC_EXPORT( int, __input_Read, ( vlc_object_t *, input_item_t *, bool ) ); - enum input_query_e { /* input variable "position" */ @@ -526,9 +505,37 @@ enum input_query_e INPUT_GET_VOUTS, /* arg1=vout_thread_t ***, int * res=can fail */ }; +/** @}*/ + +/***************************************************************************** + * Prototypes + *****************************************************************************/ + +#define input_Create(a,b,c,d) __input_Create(VLC_OBJECT(a),b,c,d) +VLC_EXPORT( input_thread_t *, __input_Create, ( vlc_object_t *p_parent, input_item_t *, const char *psz_log, input_resource_t * ) ); + +#define input_CreateAndStart(a,b,c) __input_CreateAndStart(VLC_OBJECT(a),b,c) +VLC_EXPORT( input_thread_t *, __input_CreateAndStart, ( vlc_object_t *p_parent, input_item_t *, const char *psz_log ) ); + +VLC_EXPORT( int, input_Start, ( input_thread_t * ) ); + +VLC_EXPORT( void, input_Stop, ( input_thread_t *, bool b_abort ) ); + +#define input_Read(a,b,c) __input_Read(VLC_OBJECT(a),b, c) +VLC_EXPORT( int, __input_Read, ( vlc_object_t *, input_item_t *, bool ) ); + VLC_EXPORT( int, input_vaControl,( input_thread_t *, int i_query, va_list ) ); + VLC_EXPORT( int, input_Control, ( input_thread_t *, int i_query, ... ) ); +/** + * Get the input item for an input thread + * + * You have to keep a reference to the input or to the input_item_t until + * you do not need it anymore. + */ +VLC_EXPORT( input_item_t*, input_GetItem, ( input_thread_t * ) ); + /** * It will return the current state of the input. * Provided for convenience. @@ -567,7 +574,7 @@ static inline vout_thread_t *input_GetVout( input_thread_t *p_input ) vlc_object_release( (vlc_object_t *)(pp_vout[i]) ); p_vout = (i_vout >= 1) ? pp_vout[0] : NULL; - free (pp_vout); + free( pp_vout ); return p_vout; } diff --git a/modules/services_discovery/podcast.c b/modules/services_discovery/podcast.c index 021ca45fc4..83c92c12bf 100644 --- a/modules/services_discovery/podcast.c +++ b/modules/services_discovery/podcast.c @@ -159,12 +159,15 @@ static void Close( vlc_object_t *p_this ) for( i = 0; i < p_sys->i_input; i++ ) { - if( p_sd->p_sys->pp_input[i] ) - { - input_StopThread( p_sd->p_sys->pp_input[i], true ); - vlc_object_release( p_sd->p_sys->pp_input[i] ); - p_sd->p_sys->pp_input[i] = NULL; - } + input_thread_t *p_input = p_sd->p_sys->pp_input[i]; + if( !p_input ) + continue; + + input_Stop( p_input, true ); + vlc_thread_join( p_input ); + vlc_object_release( p_input ); + + p_sd->p_sys->pp_input[i] = NULL; } free( p_sd->p_sys->pp_input ); for( i = 0; i < p_sys->i_urls; i++ ) free( p_sys->ppsz_urls[i] ); @@ -197,11 +200,14 @@ static void *Run( void *data ) for( int i = 0; i < p_sd->p_sys->i_input; i++ ) { - if( p_sd->p_sys->pp_input[i]->b_eof - || p_sd->p_sys->pp_input[i]->b_error ) + input_thread_t *p_input = p_sd->p_sys->pp_input[i]; + + if( p_input->b_eof || p_input->b_error ) { - input_StopThread( p_sd->p_sys->pp_input[i], false ); - vlc_object_release( p_sd->p_sys->pp_input[i] ); + input_Stop( p_input, false ); + vlc_thread_join( p_input ); + vlc_object_release( p_input ); + p_sd->p_sys->pp_input[i] = NULL; REMOVE_ELEM( p_sys->pp_input, p_sys->i_input, i ); i--; @@ -253,7 +259,7 @@ static void ParseUrls( services_discovery_t *p_sd, char *psz_urls ) services_discovery_AddItem( p_sd, p_input, NULL /* no cat */ ); vlc_gc_decref( p_input ); INSERT_ELEM( p_sys->pp_input, p_sys->i_input, p_sys->i_input, - input_CreateThread( p_sd, p_input ) ); + input_CreateAndStart( p_sd, p_input, NULL ) ); } if( psz_tok ) psz_urls = psz_tok+1; else return; diff --git a/src/control/media_player.c b/src/control/media_player.c index 3eb1c1e94a..19dd794043 100644 --- a/src/control/media_player.c +++ b/src/control/media_player.c @@ -89,7 +89,7 @@ static void release_input_thread( libvlc_media_player_t *p_mi, bool b_input_abor input_event_changed, p_mi ); /* We owned this one */ - input_StopThread( p_input_thread, b_input_abort ); + input_Stop( p_input_thread, b_input_abort ); vlc_thread_join( p_input_thread ); var_Destroy( p_input_thread, "drawable-hwnd" ); @@ -606,8 +606,8 @@ void libvlc_media_player_play( libvlc_media_player_t *p_mi, return; } - p_mi->p_input_thread = input_CreateThread( - p_mi->p_libvlc_instance->p_libvlc_int, p_mi->p_md->p_input_item ); + p_mi->p_input_thread = input_Create( p_mi->p_libvlc_instance->p_libvlc_int, + p_mi->p_md->p_input_item, NULL, NULL ); if( !p_mi->p_input_thread ) { @@ -643,6 +643,12 @@ void libvlc_media_player_play( libvlc_media_player_t *p_mi, var_AddCallback( p_input_thread, "can-pause", input_pausable_changed, p_mi ); var_AddCallback( p_input_thread, "intf-event", input_event_changed, p_mi ); + if( input_Start( p_input_thread ) ) + { + vlc_object_release( p_input_thread ); + p_mi->p_input_thread = NULL; + } + vlc_mutex_unlock( &p_mi->object_lock ); } @@ -717,7 +723,7 @@ void libvlc_media_player_stop( libvlc_media_player_t *p_mi, if( !p_input_thread ) return; - input_StopThread( p_input_thread, true ); + input_Stop( p_input_thread, true ); vlc_object_release( p_input_thread ); p_mi->p_input_thread = NULL; } diff --git a/src/input/input.c b/src/input/input.c index 3f51cf58b6..396994b267 100644 --- a/src/input/input.c +++ b/src/input/input.c @@ -113,6 +113,200 @@ static void input_ChangeState( input_thread_t *p_input, int i_state ); /* TODO f /* Do not let a pts_delay from access/demux go beyong 60s */ #define INPUT_PTS_DELAY_MAX INT64_C(60000000) +/** + * Create a new input_thread_t. + * + * You need to call input_Start on it when you are done + * adding callback on the variables/events you want to monitor. + * + * \param p_parent a vlc_object + * \param p_item an input item + * \param psz_log an optional prefix for this input logs + * \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 ) +{ + + return Create( p_parent, p_item, psz_log, false, p_resource ); +} + +/** + * Create a new input_thread_t and start it. + * + * Provided for convenience. + * + * \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 *p_input = __input_Create( p_parent, p_item, psz_log, NULL ); + + if( input_Start( p_input ) ) + { + vlc_object_release( p_input ); + return NULL; + } + return p_input; +} + +/** + * 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 + * \param p_item an input item + * \param b_block should we block until read is finished ? + * \return an error code, VLC_SUCCESS on success + */ +int __input_Read( vlc_object_t *p_parent, input_item_t *p_item, + bool b_block ) +{ + input_thread_t *p_input; + + p_input = Create( p_parent, p_item, NULL, false, NULL ); + if( !p_input ) + return VLC_EGENERIC; + + if( b_block ) + { + RunAndDestroy( VLC_OBJECT(p_input) ); + return VLC_SUCCESS; + } + else + { + if( vlc_thread_create( p_input, "input", RunAndDestroy, + VLC_THREAD_PRIORITY_INPUT ) ) + { + input_ChangeState( p_input, ERROR_S ); + msg_Err( p_input, "cannot create input thread" ); + vlc_object_release( p_input ); + return VLC_EGENERIC; + } + } + return VLC_SUCCESS; +} + +/** + * Initialize an input and initialize it to preparse the item + * This function is blocking. It will only accept parsing regular files. + * + * \param p_parent a vlc_object_t + * \param p_item an input item + * \return VLC_SUCCESS or an error + */ +int input_Preparse( vlc_object_t *p_parent, input_item_t *p_item ) +{ + input_thread_t *p_input; + + /* Allocate descriptor */ + p_input = Create( p_parent, p_item, NULL, true, NULL ); + if( !p_input ) + return VLC_EGENERIC; + + if( !Init( p_input ) ) + End( p_input ); + + vlc_object_release( p_input ); + + return VLC_SUCCESS; +} + +/** + * Start a input_thread_t created by input_Create. + * + * You must not start an already running input_thread_t. + * + * \param the input thread to start + */ +int input_Start( input_thread_t *p_input ) +{ + /* Create thread and wait for its readiness. */ + if( vlc_thread_create( p_input, "input", Run, + VLC_THREAD_PRIORITY_INPUT ) ) + { + input_ChangeState( p_input, ERROR_S ); + msg_Err( p_input, "cannot create input thread" ); + return VLC_EGENERIC; + } + return VLC_SUCCESS; +} + +/** + * Request a running input thread to stop and die + * + * b_abort must be true when a user stop is requested and not because you have + * detected an error or an eof. It will be used to properly send the + * INPUT_EVENT_ABORT event. + * + * \param p_input the input thread to stop + * \param b_abort true if the input has been aborted by a user request + */ +void input_Stop( input_thread_t *p_input, bool b_abort ) +{ + /* 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) ); + + vlc_mutex_lock( &p_input->p->lock_control ); + p_input->p->b_abort |= b_abort; + vlc_mutex_unlock( &p_input->p->lock_control ); + + input_ControlPush( p_input, INPUT_CONTROL_SET_DIE, NULL ); +} + +input_resource_t *input_DetachResource( input_thread_t *p_input ) +{ + assert( p_input->b_dead ); + + input_resource_SetInput( p_input->p->p_resource, NULL ); + + input_resource_t *p_resource = input_resource_Detach( p_input->p->p_resource ); + p_input->p->p_sout = NULL; + + return p_resource; +} + +/** + * Get the item from an input thread + * FIXME it does not increase ref count of the item. + * if it is used after p_input is destroyed nothing prevent it from + * being freed. + */ +input_item_t *input_GetItem( input_thread_t *p_input ) +{ + assert( p_input && p_input->p ); + return p_input->p->p_item; +} + +/***************************************************************************** + * ObjectKillChildrens + *****************************************************************************/ +static void ObjectKillChildrens( input_thread_t *p_input, vlc_object_t *p_obj ) +{ + vlc_list_t *p_list; + int i; + + /* FIXME ObjectKillChildrens seems a very bad idea in fact */ + i = vlc_internals( p_obj )->i_object_type; + if( i == VLC_OBJECT_VOUT ||i == VLC_OBJECT_AOUT || + p_obj == VLC_OBJECT(p_input->p->p_sout) || + i == VLC_OBJECT_DECODER || i == VLC_OBJECT_PACKETIZER ) + return; + + vlc_object_kill( p_obj ); + + p_list = vlc_list_children( p_obj ); + for( i = 0; i < p_list->i_count; i++ ) + ObjectKillChildrens( p_input, p_list->p_values[i].p_object ); + vlc_list_release( p_list ); +} + /***************************************************************************** * This function creates a new input, and returns a pointer * to its description. On error, it returns NULL. @@ -333,174 +527,6 @@ static void Destructor( input_thread_t * p_input ) free( p_input->p ); } -/** - * Initialize an input thread and run it. You will need to monitor the - * thread to clean up after it is done - * - * \param p_parent a vlc_object - * \param p_item an input item - * \return a pointer to the spawned input thread - */ -input_thread_t *__input_CreateThread( vlc_object_t *p_parent, - input_item_t *p_item ) -{ - return __input_CreateThreadExtended( p_parent, p_item, NULL, NULL ); -} - -/* */ -input_thread_t *__input_CreateThreadExtended( vlc_object_t *p_parent, - input_item_t *p_item, - const char *psz_log, input_resource_t *p_resource ) -{ - input_thread_t *p_input; - - p_input = Create( p_parent, p_item, psz_log, false, p_resource ); - if( !p_input ) - return NULL; - - /* Create thread and wait for its readiness. */ - if( vlc_thread_create( p_input, "input", Run, - VLC_THREAD_PRIORITY_INPUT ) ) - { - input_ChangeState( p_input, ERROR_S ); - msg_Err( p_input, "cannot create input thread" ); - vlc_object_detach( p_input ); - vlc_object_release( p_input ); - return NULL; - } - - return p_input; -} - -/** - * 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 - * \param p_item an input item - * \param b_block should we block until read is finished ? - * \return an error code, VLC_SUCCESS on success - */ -int __input_Read( vlc_object_t *p_parent, input_item_t *p_item, - bool b_block ) -{ - input_thread_t *p_input; - - p_input = Create( p_parent, p_item, NULL, false, NULL ); - if( !p_input ) - return VLC_EGENERIC; - - if( b_block ) - { - RunAndDestroy( VLC_OBJECT(p_input) ); - return VLC_SUCCESS; - } - else - { - if( vlc_thread_create( p_input, "input", RunAndDestroy, - VLC_THREAD_PRIORITY_INPUT ) ) - { - input_ChangeState( p_input, ERROR_S ); - msg_Err( p_input, "cannot create input thread" ); - vlc_object_release( p_input ); - return VLC_EGENERIC; - } - } - return VLC_SUCCESS; -} - -/** - * Initialize an input and initialize it to preparse the item - * This function is blocking. It will only accept parsing regular files. - * - * \param p_parent a vlc_object_t - * \param p_item an input item - * \return VLC_SUCCESS or an error - */ -int input_Preparse( vlc_object_t *p_parent, input_item_t *p_item ) -{ - input_thread_t *p_input; - - /* Allocate descriptor */ - p_input = Create( p_parent, p_item, NULL, true, NULL ); - if( !p_input ) - return VLC_EGENERIC; - - if( !Init( p_input ) ) - End( p_input ); - - vlc_object_detach( p_input ); - vlc_object_release( p_input ); - - return VLC_SUCCESS; -} - -/** - * Request a running input thread to stop and die - * - * \param the input thread to stop - */ -void input_StopThread( input_thread_t *p_input, bool b_abort ) -{ - /* 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) ); - - vlc_mutex_lock( &p_input->p->lock_control ); - p_input->p->b_abort |= b_abort; - vlc_mutex_unlock( &p_input->p->lock_control ); - - input_ControlPush( p_input, INPUT_CONTROL_SET_DIE, NULL ); -} - -input_resource_t *input_DetachResource( input_thread_t *p_input ) -{ - assert( p_input->b_dead ); - - input_resource_SetInput( p_input->p->p_resource, NULL ); - - input_resource_t *p_resource = input_resource_Detach( p_input->p->p_resource ); - p_input->p->p_sout = NULL; - - return p_resource; -} - -/** - * Get the item from an input thread - * FIXME it does not increase ref count of the item. - * if it is used after p_input is destroyed nothing prevent it from - * being freed. - */ -input_item_t *input_GetItem( input_thread_t *p_input ) -{ - assert( p_input && p_input->p ); - return p_input->p->p_item; -} - -/***************************************************************************** - * ObjectKillChildrens - *****************************************************************************/ -static void ObjectKillChildrens( input_thread_t *p_input, vlc_object_t *p_obj ) -{ - vlc_list_t *p_list; - int i; - - /* FIXME ObjectKillChildrens seems a very bad idea in fact */ - i = vlc_internals( p_obj )->i_object_type; - if( i == VLC_OBJECT_VOUT ||i == VLC_OBJECT_AOUT || - p_obj == VLC_OBJECT(p_input->p->p_sout) || - i == VLC_OBJECT_DECODER || i == VLC_OBJECT_PACKETIZER ) - return; - - vlc_object_kill( p_obj ); - - p_list = vlc_list_children( p_obj ); - for( i = 0; i < p_list->i_count; i++ ) - ObjectKillChildrens( p_input, p_list->p_values[i].p_object ); - vlc_list_release( p_list ); -} - /***************************************************************************** * Run: main thread loop * This is the "normal" thread that spawns the input processing chain, diff --git a/src/input/input_interface.h b/src/input/input_interface.h index dc43bb1b51..b7cde94803 100644 --- a/src/input/input_interface.h +++ b/src/input/input_interface.h @@ -46,11 +46,6 @@ int input_Preparse( vlc_object_t *, input_item_t * ); * FIXME it should NOT be defined here or not coded in misc/stats.c */ input_stats_t *stats_NewInputStats( input_thread_t *p_input ); -/** - * This defines an opaque input resource handler. - */ -typedef struct input_resource_t input_resource_t; - /** * This function releases an input_resource_t and all associated resources. */ @@ -74,8 +69,6 @@ void input_resource_TerminateVout( input_resource_t *p_resource ); bool input_resource_HasVout( input_resource_t *p_resource ); /* input.c */ -#define input_CreateThreadExtended(a,b,c,d) __input_CreateThreadExtended(VLC_OBJECT(a),b,c,d) -input_thread_t *__input_CreateThreadExtended ( vlc_object_t *, input_item_t *, const char *, input_resource_t * ); /** * This function detaches resources from a dead input. diff --git a/src/input/vlm.c b/src/input/vlm.c index a3baba0df7..c7cf2693c7 100644 --- a/src/input/vlm.c +++ b/src/input/vlm.c @@ -531,12 +531,12 @@ static int vlm_OnMediaUpdate( vlm_t *p_vlm, vlm_media_sys_t *p_media ) if( asprintf( &psz_header, _("Media: %s"), p_cfg->psz_name ) == -1 ) psz_header = NULL; - if( (p_input = input_CreateThreadExtended( p_vlm->p_libvlc, p_media->vod.p_item, psz_header, NULL ) ) ) + if( (p_input = input_CreateAndStart( p_vlm->p_libvlc, p_media->vod.p_item, psz_header ) ) ) { while( !p_input->b_eof && !p_input->b_error ) msleep( 100000 ); - input_StopThread( p_input, false ); + input_Stop( p_input, false ); vlc_thread_join( p_input ); vlc_object_release( p_input ); } @@ -778,7 +778,7 @@ static void vlm_MediaInstanceDelete( vlm_t *p_vlm, int64_t id, vlm_media_instanc { input_resource_t *p_resource; - input_StopThread( p_input, true ); + input_Stop( p_input, true ); vlc_thread_join( p_input ); p_resource = input_DetachResource( p_input ); @@ -861,7 +861,7 @@ static int vlm_ControlMediaInstanceStart( vlm_t *p_vlm, int64_t id, const char * return VLC_SUCCESS; } - input_StopThread( p_input, !p_input->b_eof && !p_input->b_error ); + input_Stop( p_input, !p_input->b_eof && !p_input->b_error ); vlc_thread_join( p_input ); p_instance->p_input_resource = input_DetachResource( p_input ); @@ -881,8 +881,13 @@ static int vlm_ControlMediaInstanceStart( vlm_t *p_vlm, int64_t id, const char * if( asprintf( &psz_log, _("Media: %s"), p_media->cfg.psz_name ) != -1 ) { - p_instance->p_input = input_CreateThreadExtended( p_vlm->p_libvlc, p_instance->p_item, - psz_log, p_instance->p_input_resource ); + p_instance->p_input = input_Create( p_vlm->p_libvlc, p_instance->p_item, + psz_log, p_instance->p_input_resource ); + if( p_instance->p_input && input_Start( p_instance->p_input ) ) + { + vlc_object_release( p_instance->p_input ); + p_instance->p_input = NULL; + } p_instance->p_input_resource = NULL; if( !p_instance->p_input ) diff --git a/src/libvlccore.sym b/src/libvlccore.sym index 9f7c950c86..ac68b0e2e3 100644 --- a/src/libvlccore.sym +++ b/src/libvlccore.sym @@ -169,8 +169,9 @@ image_Mime2Fourcc image_Type2Fourcc InitMD5 input_Control +__input_Create +__input_CreateAndStart input_CreateFilename -__input_CreateThread input_DecoderDecode input_DecoderDelete input_DecoderNew @@ -199,7 +200,8 @@ input_item_SetURI input_MetaTypeToLocalizedString __input_Read input_SplitMRL -input_StopThread +input_Start +input_Stop input_vaControl __intf_Create __intf_Eject diff --git a/src/playlist/item.c b/src/playlist/item.c index a993b79251..122411e067 100644 --- a/src/playlist/item.c +++ b/src/playlist/item.c @@ -823,7 +823,7 @@ static void GoAndPreparse( playlist_t *p_playlist, int i_mode, pl_priv(p_playlist)->request.i_skip = 0; pl_priv(p_playlist)->request.p_item = p_toplay; if( pl_priv(p_playlist)->p_input ) - input_StopThread( pl_priv(p_playlist)->p_input, true ); + input_Stop( pl_priv(p_playlist)->p_input, true ); pl_priv(p_playlist)->request.i_status = PLAYLIST_RUNNING; vlc_cond_signal( &pl_priv(p_playlist)->signal ); } diff --git a/src/playlist/thread.c b/src/playlist/thread.c index 62e1d74861..eacfd379f3 100644 --- a/src/playlist/thread.c +++ b/src/playlist/thread.c @@ -251,14 +251,17 @@ static int PlayItem( playlist_t *p_playlist, playlist_item_t *p_item ) assert( p_sys->p_input == NULL ); - input_thread_t *p_input_thread = - input_CreateThreadExtended( p_playlist, p_input, NULL, p_sys->p_input_resource ); - + input_thread_t *p_input_thread = input_Create( p_playlist, p_input, NULL, p_sys->p_input_resource ); if( p_input_thread ) { p_sys->p_input = p_input_thread; - var_AddCallback( p_input_thread, "intf-event", InputEvent, p_playlist ); + + if( input_Start( p_sys->p_input ) ) + { + vlc_object_release( p_input_thread ); + p_sys->p_input = p_input_thread = NULL; + } } p_sys->p_input_resource = NULL; @@ -473,7 +476,7 @@ static int LoopInput( playlist_t *p_playlist ) if( ( p_sys->request.b_request || !vlc_object_alive( p_playlist ) ) && !p_input->b_die ) { PL_DEBUG( "incoming request - stopping current input" ); - input_StopThread( p_input, true ); + input_Stop( p_input, true ); } /* This input is dead. Remove it ! */ @@ -514,7 +517,7 @@ static int LoopInput( playlist_t *p_playlist ) else if( p_input->b_error || p_input->b_eof ) { PL_DEBUG( "finished input" ); - input_StopThread( p_input, false ); + input_Stop( p_input, false ); } return VLC_SUCCESS; } -- 2.39.5