Commit 2d3be24e authored by Clément Stenac's avatar Clément Stenac

Don't loop continuously the playlist thread, use cond.

Not tested heavily yet ...

For interaction implementers: you need to call playlist_Signal after changing the status of a dialog. Please see the diff for qt4/dialogs/interaction.cpp
parent 0f382e74
......@@ -137,8 +137,8 @@ struct playlist_t
* with the current item */
int i_sort; /**< Last sorting applied to the playlist */
int i_order; /**< Last ordering applied to the playlist */
mtime_t i_vout_destroyed_date;
mtime_t i_sout_destroyed_date;
mtime_t gc_date;
vlc_bool_t b_cant_sleep;
playlist_preparse_t *p_preparse; /**< Preparser object */
playlist_secondary_preparse_t *p_secondary_preparse;/**< Preparser object */
......@@ -433,6 +433,14 @@ static inline vlc_bool_t playlist_IsEmpty( playlist_t * p_playlist )
return( b_empty );
}
/** Ask the playlist to do some work */
static inline void playlist_Signal( playlist_t *p_playlist )
{
PL_LOCK;
vlc_cond_signal( &p_playlist->object_wait );
PL_UNLOCK;
}
/**
* @}
*/
......
......@@ -195,4 +195,5 @@ void InteractionDialog::Finish( int i_ret )
p_dialog->i_return = i_ret;
hide();
vlc_mutex_unlock( &p_dialog->p_interaction->object_lock );
playlist_Signal( THEPL );
}
......@@ -380,7 +380,7 @@ void input_StopThread( input_thread_t *p_input )
/* Set die for input */
p_input->b_die = VLC_TRUE;
/* We cannot touch p_input fields directly (we can from another thread),
/* We cannot touch p_input fields directly (we come from another thread),
* so use the vlc_object_find way, it's perfectly safe */
/* Set die for all access */
......@@ -442,6 +442,7 @@ static int Run( input_thread_t *p_input )
{
/* If we failed, wait before we are killed, and exit */
p_input->b_error = VLC_TRUE;
playlist_Signal( pl_Get( p_input ) );
Error( p_input );
......@@ -468,6 +469,7 @@ static int Run( input_thread_t *p_input )
/* We have finished */
p_input->b_eof = VLC_TRUE;
playlist_Signal( pl_Get( p_input ) );
}
/* Wait until we are asked to die */
......
......@@ -102,19 +102,13 @@ void intf_InteractionManage( playlist_t *p_playlist )
// Pretend we have hidden and destroyed it
if( p_dialog->i_status == HIDDEN_DIALOG )
{
p_dialog->i_status = DESTROYED_DIALOG;
}
else
{
p_dialog->i_status = HIDING_DIALOG;
}
}
}
else
{
vlc_object_yield( p_interaction->p_intf );
}
for( i_index = 0 ; i_index < p_interaction->i_dialogs; i_index ++ )
{
......@@ -525,11 +519,11 @@ static interaction_dialog_t *DialogGetById( interaction_t *p_interaction,
/* Destroy a dialog */
static void DialogDestroy( interaction_dialog_t *p_dialog )
{
FREENULL( p_dialog->psz_title );
FREENULL( p_dialog->psz_description );
FREENULL( p_dialog->psz_default_button );
FREENULL( p_dialog->psz_alternate_button );
FREENULL( p_dialog->psz_other_button );
free( p_dialog->psz_title );
free( p_dialog->psz_description );
free( p_dialog->psz_default_button );
free( p_dialog->psz_alternate_button );
free( p_dialog->psz_other_button );
free( p_dialog );
}
......@@ -575,6 +569,7 @@ static int DialogSend( vlc_object_t *p_this, interaction_dialog_t *p_dialog )
if( p_dialog->i_type == INTERACT_DIALOG_TWOWAY ) // Wait for answer
{
playlist_Signal( pl_Get(p_this) );
while( p_dialog->i_status != ANSWERED_DIALOG &&
p_dialog->i_status != HIDING_DIALOG &&
p_dialog->i_status != HIDDEN_DIALOG &&
......@@ -591,6 +586,7 @@ static int DialogSend( vlc_object_t *p_this, interaction_dialog_t *p_dialog )
}
p_dialog->i_flags |= DIALOG_GOT_ANSWER;
vlc_mutex_unlock( &p_interaction->object_lock );
playlist_Signal( pl_Get(p_this) );
return p_dialog->i_return;
}
else
......@@ -598,6 +594,7 @@ static int DialogSend( vlc_object_t *p_this, interaction_dialog_t *p_dialog )
// Pretend we already retrieved the "answer"
p_dialog->i_flags |= DIALOG_GOT_ANSWER;
vlc_mutex_unlock( &p_interaction->object_lock );
playlist_Signal( pl_Get(p_this) );
return VLC_SUCCESS;
}
}
......
......@@ -179,6 +179,7 @@ int PlaylistVAControl( playlist_t * p_playlist, int i_query, va_list args )
return VLC_EBADVAR;
break;
}
vlc_cond_signal( &p_playlist->object_wait );
return VLC_SUCCESS;
}
......
......@@ -70,8 +70,8 @@ playlist_t * playlist_Create( vlc_object_t *p_parent )
p_playlist->i_last_input_id = 0;
p_playlist->p_input = NULL;
p_playlist->i_vout_destroyed_date = 0;
p_playlist->i_sout_destroyed_date = 0;
p_playlist->gc_date = 0;
p_playlist->b_cant_sleep = VLC_FALSE;
ARRAY_INIT( p_playlist->items );
ARRAY_INIT( p_playlist->all_items );
......@@ -194,46 +194,47 @@ void playlist_Destroy( playlist_t *p_playlist )
vlc_object_destroy( p_playlist );
}
/* Destroy remaining objects */
static mtime_t ObjectGarbageCollector( playlist_t *p_playlist, int i_type,
mtime_t destroy_date )
static void ObjectGarbageCollector( playlist_t *p_playlist )
{
vlc_object_t *p_obj;
if( destroy_date > mdate() ) return destroy_date;
if( destroy_date == 0 )
if( mdate() - p_playlist->gc_date < 1000000 )
{
/* give a little time */
return mdate() + I64C(1000000);
p_playlist->b_cant_sleep = VLC_TRUE;
return;
}
else
{
else if( p_playlist->gc_date == 0 )
return;
vlc_mutex_lock( &p_playlist->gc_lock );
while( ( p_obj = vlc_object_find( p_playlist, i_type, FIND_CHILD ) ) )
while( ( p_obj = vlc_object_find( p_playlist, VLC_OBJECT_VOUT,
FIND_CHILD ) ) )
{
if( p_obj->p_parent != (vlc_object_t*)p_playlist )
{
/* only first child (ie unused) */
vlc_object_release( p_obj );
break;
}
if( i_type == VLC_OBJECT_VOUT )
{
msg_Dbg( p_playlist, "garbage collector destroying 1 vout" );
vlc_object_detach( p_obj );
vlc_object_release( p_obj );
vout_Destroy( (vout_thread_t *)p_obj );
}
else if( i_type == VLC_OBJECT_SOUT )
while( ( p_obj = vlc_object_find( p_playlist, VLC_OBJECT_SOUT,
FIND_CHILD ) ) )
{
if( p_obj->p_parent != (vlc_object_t*)p_playlist )
{
vlc_object_release( p_obj );
sout_DeleteInstance( (sout_instance_t*)p_obj );
break;
}
vlc_object_release( p_obj );
sout_DeleteInstance( (sout_instance_t*)p_obj );
}
p_playlist->b_cant_sleep = VLC_FALSE;
vlc_mutex_unlock( &p_playlist->gc_lock );
return 0;
}
}
/** Main loop for the playlist */
......@@ -244,7 +245,6 @@ void playlist_MainLoop( playlist_t *p_playlist )
PL_LOCK;
/* First, check if we have something to do */
/* FIXME : this can be called several times */
if( p_playlist->request.b_request )
{
/* Stop the existing input */
......@@ -254,7 +254,7 @@ void playlist_MainLoop( playlist_t *p_playlist )
input_StopThread( p_playlist->p_input );
}
}
check_input:
/* If there is an input, check that it doesn't need to die. */
if( p_playlist->p_input )
{
......@@ -282,8 +282,10 @@ void playlist_MainLoop( playlist_t *p_playlist )
/* Destroy object */
vlc_object_destroy( p_input );
p_playlist->i_vout_destroyed_date = 0;
p_playlist->i_sout_destroyed_date = 0;
PL_LOCK;
p_playlist->gc_date = mdate();
p_playlist->b_cant_sleep = VLC_TRUE;
if( p_playlist->status.p_item->i_flags
& PLAYLIST_REMOVE_FLAG )
......@@ -299,13 +301,14 @@ void playlist_MainLoop( playlist_t *p_playlist )
i_activity= var_GetInteger( p_playlist, "activity") ;
var_SetInteger( p_playlist, "activity", i_activity -
DEFAULT_INPUT_ACTIVITY );
return;
goto check_input;
}
/* This input is dying, let it do */
else if( p_playlist->p_input->b_die )
{
PL_DEBUG( "dying input" );
msleep( 25000 ); // 25 ms
goto check_input;
}
/* This input has finished, ask it to die ! */
else if( p_playlist->p_input->b_error
......@@ -313,20 +316,14 @@ void playlist_MainLoop( playlist_t *p_playlist )
{
PL_DEBUG( "finished input" );
input_StopThread( p_playlist->p_input );
/* Select the next playlist item */
PL_UNLOCK
return;
/* No need to wait here, we'll wait in the p_input->b_die case */
goto check_input;
}
else if( p_playlist->p_input->i_state != INIT_S )
{
PL_UNLOCK;
p_playlist->i_vout_destroyed_date =
ObjectGarbageCollector( p_playlist, VLC_OBJECT_VOUT,
p_playlist->i_vout_destroyed_date );
p_playlist->i_sout_destroyed_date =
ObjectGarbageCollector( p_playlist, VLC_OBJECT_SOUT,
p_playlist->i_sout_destroyed_date );
PL_LOCK
ObjectGarbageCollector( p_playlist );
PL_LOCK;
}
}
else
......@@ -374,12 +371,9 @@ void playlist_MainLoop( playlist_t *p_playlist )
}
/* Collect garbage */
PL_UNLOCK
p_playlist->i_sout_destroyed_date =
ObjectGarbageCollector( p_playlist, VLC_OBJECT_SOUT, mdate() );
p_playlist->i_vout_destroyed_date =
ObjectGarbageCollector( p_playlist, VLC_OBJECT_VOUT, mdate() );
PL_LOCK
PL_UNLOCK;
ObjectGarbageCollector( p_playlist );
PL_LOCK;
}
}
PL_UNLOCK
......
......@@ -594,10 +594,9 @@ void GoAndPreparse( playlist_t *p_playlist, int i_mode,
p_playlist->request.i_skip = 0;
p_playlist->request.p_item = p_toplay;
if( p_playlist->p_input )
{
input_StopThread( p_playlist->p_input );
}
p_playlist->request.i_status = PLAYLIST_RUNNING;
vlc_cond_signal( &p_playlist->object_wait );
}
if( i_mode & PLAYLIST_PREPARSE &&
var_CreateGetBool( p_playlist, "auto-preparse" ) )
......@@ -666,6 +665,7 @@ int DeleteInner( playlist_t * p_playlist, playlist_item_t *p_item,
p_playlist->request.b_request = VLC_TRUE;
p_playlist->request.p_item = NULL;
msg_Info( p_playlist, "stopping playback" );
vlc_cond_signal( &p_playlist->object_wait );
}
b_flag = VLC_TRUE;
}
......
......@@ -142,6 +142,7 @@ void __playlist_ThreadCreate( vlc_object_t *p_parent )
int playlist_ThreadDestroy( playlist_t * p_playlist )
{
p_playlist->b_die = VLC_TRUE;
playlist_Signal( p_playlist );
if( p_playlist->p_preparse )
{
vlc_cond_signal( &p_playlist->p_preparse->object_wait );
......@@ -175,10 +176,18 @@ static void RunControlThread ( playlist_t *p_playlist )
HandleInteraction( p_playlist );
HandlePlaylist( p_playlist );
if( p_playlist->b_cant_sleep )
{
/* 100 ms is an acceptable delay for playlist operations */
msleep( INTF_IDLE_SLEEP*2 );
}
else
{
PL_LOCK;
vlc_cond_wait( &p_playlist->object_wait, &p_playlist->object_lock );
PL_UNLOCK;
}
}
EndPlaylist( p_playlist );
}
......
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