Commit 600e2cd5 authored by Laurent Aimar's avatar Laurent Aimar

Changed input_DestroyThread to take care of detaching, cleaning and destroying input.

(This way it matches input_CreateThread and fixes a memleak)
Control variables are now created even for preparse, only callback are not added.
(This fix use of uninitialized variables)
parent 9886e26b
......@@ -200,8 +200,6 @@ static void Close( vlc_object_t *p_this )
{
input_StopThread( p_sd->p_sys->pp_input[i] );
input_DestroyThread( p_sd->p_sys->pp_input[i] );
vlc_object_detach( p_sd->p_sys->pp_input[i] );
vlc_object_destroy( p_sd->p_sys->pp_input[i] );
p_sd->p_sys->pp_input[i] = NULL;
}
}
......@@ -233,8 +231,6 @@ static void Run( services_discovery_t *p_sd )
{
input_StopThread( p_sd->p_sys->pp_input[i] );
input_DestroyThread( p_sd->p_sys->pp_input[i] );
vlc_object_detach( p_sd->p_sys->pp_input[i] );
vlc_object_destroy( p_sd->p_sys->pp_input[i] );
p_sd->p_sys->pp_input[i] = NULL;
}
}
......
......@@ -49,7 +49,7 @@
* Local prototypes
*****************************************************************************/
static int Run ( input_thread_t *p_input );
static int RunAndClean ( input_thread_t *p_input );
static int RunAndDestroy ( input_thread_t *p_input );
static input_thread_t * Create ( vlc_object_t *, input_item_t *,
const char *, vlc_bool_t );
......@@ -197,8 +197,7 @@ static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item,
input_ConfigVarInit( p_input );
/* Create Objects variables for public Get and Set */
if( !p_input->b_preparsing )
input_ControlVarInit( p_input );
input_ControlVarInit( p_input );
p_input->p->input.i_cr_average = var_GetInteger( p_input, "cr-average" );
......@@ -254,9 +253,25 @@ static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item,
input_Control( p_input, INPUT_DEL_INFO, _(VLC_META_INFO_CAT),
VLC_META_NOW_PLAYING ); /* ? Don't translate as it might has been copied ? */
/* */
if( p_input->b_preparsing )
p_input->i_flags |= OBJECT_FLAGS_QUIET | OBJECT_FLAGS_NOINTERACT;
/* Attach only once we are ready */
vlc_object_attach( p_input, p_parent );
return p_input;
}
static void Destroy( input_thread_t *p_input )
{
vlc_object_detach( p_input );
vlc_mutex_destroy( &p_input->p->lock_control );
free( p_input->p );
vlc_object_destroy( p_input );
}
/**
* Initialize an input thread and run it. You will need to monitor the
* thread to clean up after it is done
......@@ -282,18 +297,13 @@ input_thread_t *__input_CreateThread2( vlc_object_t *p_parent,
if( !p_input )
return NULL;
/* Now we can attach our new input */
vlc_object_attach( p_input, p_parent );
/* Create thread and wait for its readiness. */
if( vlc_thread_create( p_input, "input", Run,
VLC_THREAD_PRIORITY_INPUT, VLC_TRUE ) )
{
input_ChangeState( p_input, ERROR_S );
msg_Err( p_input, "cannot create input thread" );
vlc_object_detach( p_input );
free( p_input->p );
vlc_object_destroy( p_input );
Destroy( p_input );
return NULL;
}
......@@ -318,24 +328,19 @@ int __input_Read( vlc_object_t *p_parent, input_item_t *p_item,
if( !p_input )
return VLC_EGENERIC;
/* Now we can attach our new input */
vlc_object_attach( p_input, p_parent );
if( b_block )
{
RunAndClean( p_input );
RunAndDestroy( p_input );
return VLC_SUCCESS;
}
else
{
if( vlc_thread_create( p_input, "input", RunAndClean,
if( vlc_thread_create( p_input, "input", RunAndDestroy,
VLC_THREAD_PRIORITY_INPUT, VLC_TRUE ) )
{
input_ChangeState( p_input, ERROR_S );
msg_Err( p_input, "cannot create input thread" );
vlc_object_detach( p_input );
free( p_input->p );
vlc_object_destroy( p_input );
Destroy( p_input );
return VLC_EGENERIC;
}
}
......@@ -359,23 +364,17 @@ int __input_Preparse( vlc_object_t *p_parent, input_item_t *p_item )
if( !p_input )
return VLC_EGENERIC;
p_input->i_flags |= OBJECT_FLAGS_QUIET;
p_input->i_flags |= OBJECT_FLAGS_NOINTERACT;
/* Now we can attach our new input */
vlc_object_attach( p_input, p_parent );
Init( p_input );
/* Clean up master */
InputSourceClean( p_input, &p_input->p->input );
/* FIXME shouldn't we call End() to ? */
/* Unload all modules */
if( p_input->p->p_es_out ) input_EsOutDelete( p_input->p->p_es_out );
vlc_object_detach( p_input );
free( p_input->p );
vlc_object_destroy( p_input );
Destroy( p_input );
return VLC_SUCCESS;
}
......@@ -434,11 +433,8 @@ void input_DestroyThread( input_thread_t *p_input )
/* Join the thread */
vlc_thread_join( p_input );
/* Delete input lock (only after thread joined) */
vlc_mutex_destroy( &p_input->p->lock_control );
/* TODO: maybe input_DestroyThread should also delete p_input instead
* of the playlist but I'm not sure if it's possible */
/* */
Destroy( p_input );
}
/*****************************************************************************
......@@ -498,20 +494,17 @@ static int Run( input_thread_t *p_input )
}
/*****************************************************************************
* RunAndClean: main thread loop
* RunAndDestroy: main thread loop
* This is the "just forget me" thread that spawns the input processing chain,
* reads the stream, cleans up and releases memory
*****************************************************************************/
static int RunAndClean( input_thread_t *p_input )
static int RunAndDestroy( input_thread_t *p_input )
{
/* Signal that the thread is launched */
vlc_thread_ready( p_input );
if( Init( p_input ) )
{
/* If we failed, just exit */
return 0;
}
goto exit;
MainLoop( p_input );
......@@ -535,11 +528,9 @@ static int RunAndClean( input_thread_t *p_input )
/* Clean up */
End( p_input );
exit:
/* Release memory */
vlc_object_detach( p_input );
free( p_input->p );
vlc_object_destroy( p_input );
Destroy( p_input );
return 0;
}
......@@ -1143,14 +1134,11 @@ static void End( input_thread_t * p_input )
{
int i;
msg_Dbg( p_input, "closing input" );
/* We are at the end */
input_ChangeState( p_input, END_S );
/* Clean control variables */
if( !p_input->b_preparsing )
input_ControlVarClean( p_input );
input_ControlVarClean( p_input );
/* Clean up master */
InputSourceClean( p_input, &p_input->p->input );
......
......@@ -75,46 +75,49 @@ void input_ControlVarInit ( input_thread_t *p_input )
{
vlc_value_t val, text;
/* XXX we put callback only in non preparsing mode. We need to create the variable
* unless someone want to check all var_Get/var_Change return value ... */
#define ADD_CALLBACK( name, callback ) do { if( !p_input->b_preparsing ) { var_AddCallback( p_input, name, callback, NULL ); } } while(0)
/* State */
var_Create( p_input, "state", VLC_VAR_INTEGER );
val.i_int = p_input->i_state;
var_Change( p_input, "state", VLC_VAR_SETVALUE, &val, NULL );
var_AddCallback( p_input, "state", StateCallback, NULL );
ADD_CALLBACK( "state", StateCallback );
/* Rate */
var_Create( p_input, "rate", VLC_VAR_INTEGER );
val.i_int = p_input->p->i_rate;
var_Change( p_input, "rate", VLC_VAR_SETVALUE, &val, NULL );
var_AddCallback( p_input, "rate", RateCallback, NULL );
ADD_CALLBACK( "rate", RateCallback );
var_Create( p_input, "rate-slower", VLC_VAR_VOID );
var_AddCallback( p_input, "rate-slower", RateCallback, NULL );
ADD_CALLBACK( "rate-slower", RateCallback );
var_Create( p_input, "rate-faster", VLC_VAR_VOID );
var_AddCallback( p_input, "rate-faster", RateCallback, NULL );
ADD_CALLBACK( "rate-faster", RateCallback );
/* Position */
var_Create( p_input, "position", VLC_VAR_FLOAT );
var_Create( p_input, "position-offset", VLC_VAR_FLOAT );
val.f_float = 0.0;
var_Change( p_input, "position", VLC_VAR_SETVALUE, &val, NULL );
var_AddCallback( p_input, "position", PositionCallback, NULL );
var_AddCallback( p_input, "position-offset", PositionCallback, NULL );
ADD_CALLBACK( "position", PositionCallback );
ADD_CALLBACK( "position-offset", PositionCallback );
/* Time */
var_Create( p_input, "time", VLC_VAR_TIME );
var_Create( p_input, "time-offset", VLC_VAR_TIME ); /* relative */
val.i_time = 0;
var_Change( p_input, "time", VLC_VAR_SETVALUE, &val, NULL );
var_AddCallback( p_input, "time", TimeCallback, NULL );
var_AddCallback( p_input, "time-offset", TimeCallback, NULL );
ADD_CALLBACK( "time", TimeCallback );
ADD_CALLBACK( "time-offset", TimeCallback );
/* Bookmark */
var_Create( p_input, "bookmark", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE |
VLC_VAR_ISCOMMAND );
val.psz_string = _("Bookmark");
var_Change( p_input, "bookmark", VLC_VAR_SETTEXT, &val, NULL );
var_AddCallback( p_input, "bookmark", BookmarkCallback, NULL );
ADD_CALLBACK( "bookmark", BookmarkCallback );
/* Program */
var_Create( p_input, "program", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE |
......@@ -124,7 +127,7 @@ void input_ControlVarInit ( input_thread_t *p_input )
var_Change( p_input, "program", VLC_VAR_DELCHOICE, &val, NULL );
text.psz_string = _("Program");
var_Change( p_input, "program", VLC_VAR_SETTEXT, &text, NULL );
var_AddCallback( p_input, "program", ProgramCallback, NULL );
ADD_CALLBACK( "program", ProgramCallback );
/* Programs */
var_Create( p_input, "programs", VLC_VAR_LIST | VLC_VAR_DOINHERIT );
......@@ -135,13 +138,13 @@ void input_ControlVarInit ( input_thread_t *p_input )
var_Create( p_input, "title", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE );
text.psz_string = _("Title");
var_Change( p_input, "title", VLC_VAR_SETTEXT, &text, NULL );
var_AddCallback( p_input, "title", TitleCallback, NULL );
ADD_CALLBACK( "title", TitleCallback );
/* Chapter */
var_Create( p_input, "chapter", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE );
text.psz_string = _("Chapter");
var_Change( p_input, "chapter", VLC_VAR_SETTEXT, &text, NULL );
var_AddCallback( p_input, "chapter", SeekpointCallback, NULL );
ADD_CALLBACK( "chapter", SeekpointCallback );
/* Navigation The callback is added after */
var_Create( p_input, "navigation", VLC_VAR_VARIABLE | VLC_VAR_HASCHOICE );
......@@ -152,29 +155,29 @@ void input_ControlVarInit ( input_thread_t *p_input )
var_Create( p_input, "audio-delay", VLC_VAR_TIME );
val.i_time = 0;
var_Change( p_input, "audio-delay", VLC_VAR_SETVALUE, &val, NULL );
var_AddCallback( p_input, "audio-delay", EsDelayCallback, NULL );
ADD_CALLBACK( "audio-delay", EsDelayCallback );
var_Create( p_input, "spu-delay", VLC_VAR_TIME );
val.i_time = 0;
var_Change( p_input, "spu-delay", VLC_VAR_SETVALUE, &val, NULL );
var_AddCallback( p_input, "spu-delay", EsDelayCallback, NULL );
ADD_CALLBACK( "spu-delay", EsDelayCallback );
/* Video ES */
var_Create( p_input, "video-es", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE );
text.psz_string = _("Video Track");
var_Change( p_input, "video-es", VLC_VAR_SETTEXT, &text, NULL );
var_AddCallback( p_input, "video-es", ESCallback, NULL );
ADD_CALLBACK( "video-es", ESCallback );
/* Audio ES */
var_Create( p_input, "audio-es", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE );
text.psz_string = _("Audio Track");
var_Change( p_input, "audio-es", VLC_VAR_SETTEXT, &text, NULL );
var_AddCallback( p_input, "audio-es", ESCallback, NULL );
ADD_CALLBACK( "audio-es", ESCallback );
/* Spu ES */
var_Create( p_input, "spu-es", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE );
text.psz_string = _("Subtitles Track");
var_Change( p_input, "spu-es", VLC_VAR_SETTEXT, &text, NULL );
var_AddCallback( p_input, "spu-es", ESCallback, NULL );
ADD_CALLBACK( "spu-es", ESCallback );
/* Special read only objects variables for intf */
var_Create( p_input, "bookmarks", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
......@@ -183,14 +186,18 @@ void input_ControlVarInit ( input_thread_t *p_input )
val.i_time = 0;
var_Change( p_input, "length", VLC_VAR_SETVALUE, &val, NULL );
/* Special "intf-change" variable, it allows intf to set up a callback
* to be notified of some changes.
* TODO list all changes warn by this callbacks */
var_Create( p_input, "intf-change", VLC_VAR_BOOL );
var_SetBool( p_input, "intf-change", VLC_TRUE );
/* item-change variable */
var_Create( p_input, "item-change", VLC_VAR_INTEGER );
if( !p_input->b_preparsing )
{
/* Special "intf-change" variable, it allows intf to set up a callback
* to be notified of some changes.
* TODO list all changes warn by this callbacks */
var_Create( p_input, "intf-change", VLC_VAR_BOOL );
var_SetBool( p_input, "intf-change", VLC_TRUE );
/* item-change variable */
var_Create( p_input, "item-change", VLC_VAR_INTEGER );
}
#undef ADD_CALLBACK
}
/*****************************************************************************
......
......@@ -1147,8 +1147,6 @@ int vlm_MediaSetup( vlm_t *vlm, vlm_media_t *media, const char *psz_cmd,
input_StopThread( p_input );
input_DestroyThread( p_input );
vlc_object_detach( p_input );
vlc_object_destroy( p_input );
}
free( psz_output );
free( psz_header );
......@@ -1241,8 +1239,6 @@ int vlm_MediaControl( vlm_t *vlm, vlm_media_t *media, const char *psz_id,
{
input_StopThread( p_instance->p_input );
input_DestroyThread( p_instance->p_input );
vlc_object_detach( p_instance->p_input );
vlc_object_destroy( p_instance->p_input );
}
asprintf( &psz_header, _("Media: %s"), media->psz_name );
......@@ -1362,8 +1358,6 @@ int vlm_MediaControl( vlm_t *vlm, vlm_media_t *media, const char *psz_id,
{
input_StopThread( p_instance->p_input );
input_DestroyThread( p_instance->p_input );
vlc_object_detach( p_instance->p_input );
vlc_object_destroy( p_instance->p_input );
}
input_ItemClean( &p_instance->item );
......@@ -2497,8 +2491,6 @@ static int Manage( vlc_object_t* p_object )
input_StopThread( p_instance->p_input );
input_DestroyThread( p_instance->p_input );
vlc_object_detach( p_instance->p_input );
vlc_object_destroy( p_instance->p_input );
p_instance->i_index++;
if( p_instance->i_index == p_media->i_input &&
......
......@@ -259,13 +259,6 @@ check_input:
/* Destroy input */
input_DestroyThread( p_input );
/* Unlink current input
* (_after_ input_DestroyThread for vout garbage collector) */
vlc_object_detach( p_input );
/* Destroy object */
vlc_object_destroy( p_input );
PL_LOCK;
p_playlist->gc_date = mdate();
......@@ -389,12 +382,6 @@ void playlist_LastLoop( playlist_t *p_playlist )
/* Destroy input */
input_DestroyThread( p_input );
/* Unlink current input (_after_ input_DestroyThread for vout
* garbage collector)*/
vlc_object_detach( p_input );
/* Destroy object */
vlc_object_destroy( p_input );
continue;
}
else if( p_playlist->p_input->b_die )
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment