Commit 8f0f6c74 authored by Laurent Aimar's avatar Laurent Aimar

Clean up main playlist thread.

No useless wake up and simplify.
Fix a few race conditions with deactivation.
parent b2efc40a
...@@ -190,7 +190,10 @@ int playlist_PreparseEnqueue( playlist_t *p_playlist, ...@@ -190,7 +190,10 @@ int playlist_PreparseEnqueue( playlist_t *p_playlist,
{ {
playlist_private_t *p_sys = pl_priv(p_playlist); playlist_private_t *p_sys = pl_priv(p_playlist);
playlist_preparser_Push( p_sys->p_preparser, p_item ); PL_LOCK;
if( p_sys->p_preparser )
playlist_preparser_Push( p_sys->p_preparser, p_item );
PL_UNLOCK;
return VLC_SUCCESS; return VLC_SUCCESS;
} }
...@@ -200,7 +203,10 @@ int playlist_AskForArtEnqueue( playlist_t *p_playlist, ...@@ -200,7 +203,10 @@ int playlist_AskForArtEnqueue( playlist_t *p_playlist,
{ {
playlist_private_t *p_sys = pl_priv(p_playlist); playlist_private_t *p_sys = pl_priv(p_playlist);
playlist_fetcher_Push( p_sys->p_fetcher, p_item ); PL_LOCK;
if( p_sys->p_fetcher )
playlist_fetcher_Push( p_sys->p_fetcher, p_item );
PL_UNLOCK;
return VLC_SUCCESS; return VLC_SUCCESS;
} }
......
...@@ -174,11 +174,12 @@ static void playlist_Destructor( vlc_object_t * p_this ) ...@@ -174,11 +174,12 @@ static void playlist_Destructor( vlc_object_t * p_this )
playlist_t *p_playlist = (playlist_t *)p_this; playlist_t *p_playlist = (playlist_t *)p_this;
playlist_private_t *p_sys = pl_priv(p_playlist); playlist_private_t *p_sys = pl_priv(p_playlist);
assert( !p_sys->p_input );
assert( !p_sys->p_sout ); assert( !p_sys->p_sout );
assert( !p_sys->p_preparser ); assert( !p_sys->p_preparser );
assert( !p_sys->p_fetcher ); assert( !p_sys->p_fetcher );
msg_Err( p_this, "Destroyed" ); msg_Dbg( p_this, "Destroyed" );
} }
/** Get current playing input. /** Get current playing input.
......
...@@ -85,14 +85,23 @@ void playlist_Deactivate( playlist_t *p_playlist ) ...@@ -85,14 +85,23 @@ void playlist_Deactivate( playlist_t *p_playlist )
vlc_thread_join( p_playlist ); vlc_thread_join( p_playlist );
assert( !p_sys->p_input ); assert( !p_sys->p_input );
if( p_sys->p_preparser ) PL_LOCK;
playlist_preparser_Delete( p_sys->p_preparser ); playlist_preparser_t *p_preparser = p_sys->p_preparser;
if( p_sys->p_fetcher ) playlist_fetcher_t *p_fetcher = p_sys->p_fetcher;
playlist_fetcher_Delete( p_sys->p_fetcher );
p_sys->p_preparser = NULL;
p_sys->p_fetcher = NULL;
PL_UNLOCK;
if( p_preparser )
playlist_preparser_Delete( p_preparser );
if( p_fetcher )
playlist_fetcher_Delete( p_fetcher );
/* close the remaining sout-keep */ /* close the remaining sout-keep */
if( p_sys->p_sout ) if( p_sys->p_sout )
sout_DeleteInstance( p_sys->p_sout ); sout_DeleteInstance( p_sys->p_sout );
p_sys->p_sout = NULL;
/* */ /* */
playlist_MLDump( p_playlist ); playlist_MLDump( p_playlist );
...@@ -111,22 +120,18 @@ void playlist_Deactivate( playlist_t *p_playlist ) ...@@ -111,22 +120,18 @@ void playlist_Deactivate( playlist_t *p_playlist )
free( p_del ); free( p_del );
FOREACH_END(); FOREACH_END();
ARRAY_RESET( p_playlist->all_items ); ARRAY_RESET( p_playlist->all_items );
FOREACH_ARRAY( playlist_item_t *p_del, pl_priv(p_playlist)->items_to_delete ) FOREACH_ARRAY( playlist_item_t *p_del, p_sys->items_to_delete )
free( p_del->pp_children ); free( p_del->pp_children );
vlc_gc_decref( p_del->p_input ); vlc_gc_decref( p_del->p_input );
free( p_del ); free( p_del );
FOREACH_END(); FOREACH_END();
ARRAY_RESET( pl_priv(p_playlist)->items_to_delete ); ARRAY_RESET( p_sys->items_to_delete );
ARRAY_RESET( p_playlist->items ); ARRAY_RESET( p_playlist->items );
ARRAY_RESET( p_playlist->current ); ARRAY_RESET( p_playlist->current );
PL_UNLOCK; PL_UNLOCK;
/* The NULL are there only to assert in playlist destructor */
p_sys->p_sout = NULL;
p_sys->p_preparser = NULL;
p_sys->p_fetcher = NULL;
msg_Dbg( p_playlist, "Deactivated" ); msg_Dbg( p_playlist, "Deactivated" );
} }
...@@ -140,7 +145,7 @@ static int InputEvent( vlc_object_t *p_this, char const *psz_cmd, ...@@ -140,7 +145,7 @@ static int InputEvent( vlc_object_t *p_this, char const *psz_cmd,
playlist_t *p_playlist = p_data; playlist_t *p_playlist = p_data;
if( newval.i_int != INPUT_EVENT_STATE && if( newval.i_int != INPUT_EVENT_STATE &&
newval.i_int != INPUT_EVENT_ES ) newval.i_int != INPUT_EVENT_DEAD )
return VLC_SUCCESS; return VLC_SUCCESS;
PL_LOCK; PL_LOCK;
...@@ -151,6 +156,14 @@ static int InputEvent( vlc_object_t *p_this, char const *psz_cmd, ...@@ -151,6 +156,14 @@ static int InputEvent( vlc_object_t *p_this, char const *psz_cmd,
return VLC_SUCCESS; return VLC_SUCCESS;
} }
static void UpdateActivity( playlist_t *p_playlist, int i_delta )
{
PL_ASSERT_LOCKED;
const int i_activity = var_GetInteger( p_playlist, "activity" ) ;
var_SetInteger( p_playlist, "activity", i_activity + i_delta );
}
/** /**
* Synchronise the current index of the playlist * Synchronise the current index of the playlist
* to match the index of the current item. * to match the index of the current item.
...@@ -161,53 +174,55 @@ static int InputEvent( vlc_object_t *p_this, char const *psz_cmd, ...@@ -161,53 +174,55 @@ static int InputEvent( vlc_object_t *p_this, char const *psz_cmd,
*/ */
static void ResyncCurrentIndex( playlist_t *p_playlist, playlist_item_t *p_cur ) static void ResyncCurrentIndex( playlist_t *p_playlist, playlist_item_t *p_cur )
{ {
PL_DEBUG( "resyncing on %s", PLI_NAME( p_cur ) ); PL_ASSERT_LOCKED;
/* Simply resync index */
int i; PL_DEBUG( "resyncing on %s", PLI_NAME( p_cur ) );
p_playlist->i_current_index = -1; /* Simply resync index */
for( i = 0 ; i< p_playlist->current.i_size; i++ ) int i;
{ p_playlist->i_current_index = -1;
if( ARRAY_VAL( p_playlist->current, i ) == p_cur ) for( i = 0 ; i< p_playlist->current.i_size; i++ )
{ {
p_playlist->i_current_index = i; if( ARRAY_VAL( p_playlist->current, i ) == p_cur )
break; {
} p_playlist->i_current_index = i;
} break;
PL_DEBUG( "%s is at %i", PLI_NAME( p_cur ), p_playlist->i_current_index ); }
}
PL_DEBUG( "%s is at %i", PLI_NAME( p_cur ), p_playlist->i_current_index );
} }
static void ResetCurrentlyPlaying( playlist_t *p_playlist, bool b_random, static void ResetCurrentlyPlaying( playlist_t *p_playlist,
playlist_item_t *p_cur ) playlist_item_t *p_cur )
{ {
playlist_item_t *p_next = NULL; playlist_private_t *p_sys = pl_priv(p_playlist);
stats_TimerStart( p_playlist, "Items array build", stats_TimerStart( p_playlist, "Items array build",
STATS_TIMER_PLAYLIST_BUILD ); STATS_TIMER_PLAYLIST_BUILD );
PL_DEBUG( "rebuilding array of current - root %s", PL_DEBUG( "rebuilding array of current - root %s",
PLI_NAME( pl_priv(p_playlist)->status.p_node ) ); PLI_NAME( p_sys->status.p_node ) );
ARRAY_RESET( p_playlist->current ); ARRAY_RESET( p_playlist->current );
p_playlist->i_current_index = -1; p_playlist->i_current_index = -1;
while( 1 ) for( playlist_item_t *p_next = NULL; ; )
{ {
/** FIXME: this is *slow* */ /** FIXME: this is *slow* */
p_next = playlist_GetNextLeaf( p_playlist, p_next = playlist_GetNextLeaf( p_playlist,
pl_priv(p_playlist)->status.p_node, p_sys->status.p_node,
p_next, true, false ); p_next, true, false );
if( p_next ) if( !p_next )
{ break;
if( p_next == p_cur )
p_playlist->i_current_index = p_playlist->current.i_size; if( p_next == p_cur )
ARRAY_APPEND( p_playlist->current, p_next); p_playlist->i_current_index = p_playlist->current.i_size;
} ARRAY_APPEND( p_playlist->current, p_next);
else break;
} }
PL_DEBUG("rebuild done - %i items, index %i", p_playlist->current.i_size, PL_DEBUG("rebuild done - %i items, index %i", p_playlist->current.i_size,
p_playlist->i_current_index); p_playlist->i_current_index);
if( b_random )
if( var_GetBool( p_playlist, "random" ) )
{ {
/* Shuffle the array */ /* Shuffle the array */
srand( (unsigned int)mdate() ); srand( (unsigned int)mdate() );
int j; for( int j = p_playlist->current.i_size - 1; j > 0; j-- )
for( j = p_playlist->current.i_size - 1; j > 0; j-- )
{ {
int i = rand() % (j+1); /* between 0 and j */ int i = rand() % (j+1); /* between 0 and j */
playlist_item_t *p_tmp; playlist_item_t *p_tmp;
...@@ -217,7 +232,7 @@ static void ResetCurrentlyPlaying( playlist_t *p_playlist, bool b_random, ...@@ -217,7 +232,7 @@ static void ResetCurrentlyPlaying( playlist_t *p_playlist, bool b_random,
ARRAY_VAL(p_playlist->current,j) = p_tmp; ARRAY_VAL(p_playlist->current,j) = p_tmp;
} }
} }
pl_priv(p_playlist)->b_reset_currently_playing = false; p_sys->b_reset_currently_playing = false;
stats_TimerStop( p_playlist, STATS_TIMER_PLAYLIST_BUILD ); stats_TimerStop( p_playlist, STATS_TIMER_PLAYLIST_BUILD );
} }
...@@ -231,9 +246,8 @@ static void ResetCurrentlyPlaying( playlist_t *p_playlist, bool b_random, ...@@ -231,9 +246,8 @@ static void ResetCurrentlyPlaying( playlist_t *p_playlist, bool b_random,
*/ */
static int PlayItem( playlist_t *p_playlist, playlist_item_t *p_item ) static int PlayItem( playlist_t *p_playlist, playlist_item_t *p_item )
{ {
playlist_private_t *p_sys = pl_priv(p_playlist);
input_item_t *p_input = p_item->p_input; input_item_t *p_input = p_item->p_input;
sout_instance_t **pp_sout = &pl_priv(p_playlist)->p_sout;
int i_activity = var_GetInteger( p_playlist, "activity" ) ;
PL_ASSERT_LOCKED; PL_ASSERT_LOCKED;
...@@ -242,24 +256,23 @@ static int PlayItem( playlist_t *p_playlist, playlist_item_t *p_item ) ...@@ -242,24 +256,23 @@ static int PlayItem( playlist_t *p_playlist, playlist_item_t *p_item )
p_input->i_nb_played++; p_input->i_nb_played++;
set_current_status_item( p_playlist, p_item ); set_current_status_item( p_playlist, p_item );
pl_priv(p_playlist)->status.i_status = PLAYLIST_RUNNING; p_sys->status.i_status = PLAYLIST_RUNNING;
var_SetInteger( p_playlist, "activity", i_activity + UpdateActivity( p_playlist, DEFAULT_INPUT_ACTIVITY );
DEFAULT_INPUT_ACTIVITY );
assert( pl_priv(p_playlist)->p_input == NULL ); assert( p_sys->p_input == NULL );
input_thread_t *p_input_thread = input_thread_t *p_input_thread =
input_CreateThreadExtended( p_playlist, p_input, NULL, *pp_sout ); input_CreateThreadExtended( p_playlist, p_input, NULL, p_sys->p_sout );
if( p_input_thread ) if( p_input_thread )
{ {
pl_priv(p_playlist)->p_input = p_input_thread; p_sys->p_input = p_input_thread;
var_AddCallback( p_input_thread, "intf-event", InputEvent, p_playlist ); var_AddCallback( p_input_thread, "intf-event", InputEvent, p_playlist );
} }
*pp_sout = NULL; p_sys->p_sout = NULL;
char *psz_uri = input_item_GetURI( p_item->p_input ); char *psz_uri = input_item_GetURI( p_item->p_input );
if( psz_uri && ( !strncmp( psz_uri, "directory:", 10 ) || if( psz_uri && ( !strncmp( psz_uri, "directory:", 10 ) ||
...@@ -307,13 +320,8 @@ static int PlayItem( playlist_t *p_playlist, playlist_item_t *p_item ) ...@@ -307,13 +320,8 @@ static int PlayItem( playlist_t *p_playlist, playlist_item_t *p_item )
*/ */
static playlist_item_t *NextItem( playlist_t *p_playlist ) static playlist_item_t *NextItem( playlist_t *p_playlist )
{ {
playlist_private_t *p_sys = pl_priv(p_playlist);
playlist_item_t *p_new = NULL; playlist_item_t *p_new = NULL;
int i_skip = 0, i;
bool b_loop = var_GetBool( p_playlist, "loop" );
bool b_random = var_GetBool( p_playlist, "random" );
bool b_repeat = var_GetBool( p_playlist, "repeat" );
bool b_playstop = var_GetBool( p_playlist, "play-and-stop" );
/* Handle quickly a few special cases */ /* Handle quickly a few special cases */
/* No items to play */ /* No items to play */
...@@ -323,50 +331,22 @@ static playlist_item_t *NextItem( playlist_t *p_playlist ) ...@@ -323,50 +331,22 @@ static playlist_item_t *NextItem( playlist_t *p_playlist )
return NULL; return NULL;
} }
/* Repeat and play/stop */
if( !pl_priv(p_playlist)->request.b_request && b_repeat == true &&
get_current_status_item( p_playlist ) )
{
msg_Dbg( p_playlist,"repeating item" );
return get_current_status_item( p_playlist );
}
if( !pl_priv(p_playlist)->request.b_request && b_playstop == true )
{
msg_Dbg( p_playlist,"stopping (play and stop)" );
return NULL;
}
if( !pl_priv(p_playlist)->request.b_request &&
get_current_status_item( p_playlist ) )
{
playlist_item_t *p_parent = get_current_status_item( p_playlist );
while( p_parent )
{
if( p_parent->i_flags & PLAYLIST_SKIP_FLAG )
{
msg_Dbg( p_playlist, "blocking item, stopping") ;
return NULL;
}
p_parent = p_parent->p_parent;
}
}
/* Start the real work */ /* Start the real work */
if( pl_priv(p_playlist)->request.b_request ) if( p_sys->request.b_request )
{ {
p_new = pl_priv(p_playlist)->request.p_item; p_new = p_sys->request.p_item;
i_skip = pl_priv(p_playlist)->request.i_skip; int i_skip = p_sys->request.i_skip;
PL_DEBUG( "processing request item %s node %s skip %i", PL_DEBUG( "processing request item %s node %s skip %i",
PLI_NAME( pl_priv(p_playlist)->request.p_item ), PLI_NAME( p_sys->request.p_item ),
PLI_NAME( pl_priv(p_playlist)->request.p_node ), i_skip ); PLI_NAME( p_sys->request.p_node ), i_skip );
if( pl_priv(p_playlist)->request.p_node && if( p_sys->request.p_node &&
pl_priv(p_playlist)->request.p_node != get_current_status_node( p_playlist ) ) p_sys->request.p_node != get_current_status_node( p_playlist ) )
{ {
set_current_status_node( p_playlist, pl_priv(p_playlist)->request.p_node ); set_current_status_node( p_playlist, p_sys->request.p_node );
pl_priv(p_playlist)->request.p_node = NULL; p_sys->request.p_node = NULL;
pl_priv(p_playlist)->b_reset_currently_playing = true; p_sys->b_reset_currently_playing = true;
} }
/* If we are asked for a node, go to it's first child */ /* If we are asked for a node, go to it's first child */
...@@ -376,7 +356,7 @@ static playlist_item_t *NextItem( playlist_t *p_playlist ) ...@@ -376,7 +356,7 @@ static playlist_item_t *NextItem( playlist_t *p_playlist )
if( p_new != NULL ) if( p_new != NULL )
{ {
p_new = playlist_GetNextLeaf( p_playlist, p_new, NULL, true, false ); p_new = playlist_GetNextLeaf( p_playlist, p_new, NULL, true, false );
for( i = 0; i < p_playlist->current.i_size; i++ ) for( int i = 0; i < p_playlist->current.i_size; i++ )
{ {
if( p_new == ARRAY_VAL( p_playlist->current, i ) ) if( p_new == ARRAY_VAL( p_playlist->current, i ) )
{ {
...@@ -387,9 +367,9 @@ static playlist_item_t *NextItem( playlist_t *p_playlist ) ...@@ -387,9 +367,9 @@ static playlist_item_t *NextItem( playlist_t *p_playlist )
} }
} }
if( pl_priv(p_playlist)->b_reset_currently_playing ) if( p_sys->b_reset_currently_playing )
/* A bit too bad to reset twice ... */ /* A bit too bad to reset twice ... */
ResetCurrentlyPlaying( p_playlist, b_random, p_new ); ResetCurrentlyPlaying( p_playlist, p_new );
else if( p_new ) else if( p_new )
ResyncCurrentIndex( p_playlist, p_new ); ResyncCurrentIndex( p_playlist, p_new );
else else
...@@ -399,7 +379,7 @@ static playlist_item_t *NextItem( playlist_t *p_playlist ) ...@@ -399,7 +379,7 @@ static playlist_item_t *NextItem( playlist_t *p_playlist )
{ {
if( p_playlist->i_current_index < -1 ) if( p_playlist->i_current_index < -1 )
p_playlist->i_current_index = -1; p_playlist->i_current_index = -1;
for( i = i_skip; i > 0 ; i-- ) for( int i = i_skip; i > 0 ; i-- )
{ {
p_playlist->i_current_index++; p_playlist->i_current_index++;
if( p_playlist->i_current_index >= p_playlist->current.i_size ) if( p_playlist->i_current_index >= p_playlist->current.i_size )
...@@ -413,7 +393,7 @@ static playlist_item_t *NextItem( playlist_t *p_playlist ) ...@@ -413,7 +393,7 @@ static playlist_item_t *NextItem( playlist_t *p_playlist )
} }
else if( p_playlist->current.i_size && (i_skip < 0) ) else if( p_playlist->current.i_size && (i_skip < 0) )
{ {
for( i = i_skip; i < 0 ; i++ ) for( int i = i_skip; i < 0 ; i++ )
{ {
p_playlist->i_current_index--; p_playlist->i_current_index--;
if( p_playlist->i_current_index <= -1 ) if( p_playlist->i_current_index <= -1 )
...@@ -426,11 +406,42 @@ static playlist_item_t *NextItem( playlist_t *p_playlist ) ...@@ -426,11 +406,42 @@ static playlist_item_t *NextItem( playlist_t *p_playlist )
p_playlist->i_current_index ); p_playlist->i_current_index );
} }
/* Clear the request */ /* Clear the request */
pl_priv(p_playlist)->request.b_request = false; p_sys->request.b_request = false;
} }
/* "Automatic" item change ( next ) */ /* "Automatic" item change ( next ) */
else else
{ {
bool b_loop = var_GetBool( p_playlist, "loop" );
bool b_repeat = var_GetBool( p_playlist, "repeat" );
bool b_playstop = var_GetBool( p_playlist, "play-and-stop" );
/* Repeat and play/stop */
if( b_repeat && get_current_status_item( p_playlist ) )
{
msg_Dbg( p_playlist,"repeating item" );
return get_current_status_item( p_playlist );
}
if( b_playstop )
{
msg_Dbg( p_playlist,"stopping (play and stop)" );
return NULL;
}
/* */
if( get_current_status_item( p_playlist ) )
{
playlist_item_t *p_parent = get_current_status_item( p_playlist );
while( p_parent )
{
if( p_parent->i_flags & PLAYLIST_SKIP_FLAG )
{
msg_Dbg( p_playlist, "blocking item, stopping") ;
return NULL;
}
p_parent = p_parent->p_parent;
}
}
PL_DEBUG( "changing item without a request (current %i/%i)", PL_DEBUG( "changing item without a request (current %i/%i)",
p_playlist->i_current_index, p_playlist->current.i_size ); p_playlist->i_current_index, p_playlist->current.i_size );
/* Cant go to next from current item */ /* Cant go to next from current item */
...@@ -438,19 +449,21 @@ static playlist_item_t *NextItem( playlist_t *p_playlist ) ...@@ -438,19 +449,21 @@ static playlist_item_t *NextItem( playlist_t *p_playlist )
get_current_status_item( p_playlist )->i_flags & PLAYLIST_SKIP_FLAG ) get_current_status_item( p_playlist )->i_flags & PLAYLIST_SKIP_FLAG )
return NULL; return NULL;
if( pl_priv(p_playlist)->b_reset_currently_playing ) if( p_sys->b_reset_currently_playing )
ResetCurrentlyPlaying( p_playlist, b_random, ResetCurrentlyPlaying( p_playlist,
get_current_status_item( p_playlist ) ); get_current_status_item( p_playlist ) );
p_playlist->i_current_index++; p_playlist->i_current_index++;
assert( p_playlist->i_current_index <= p_playlist->current.i_size ); assert( p_playlist->i_current_index <= p_playlist->current.i_size );
if( p_playlist->i_current_index == p_playlist->current.i_size ) if( p_playlist->i_current_index == p_playlist->current.i_size )
{ {
if( !b_loop || p_playlist->current.i_size == 0 ) return NULL; if( !b_loop || p_playlist->current.i_size == 0 )
return NULL;
p_playlist->i_current_index = 0; p_playlist->i_current_index = 0;
} }
PL_DEBUG( "using item %i", p_playlist->i_current_index ); PL_DEBUG( "using item %i", p_playlist->i_current_index );
if ( p_playlist->current.i_size == 0 ) return NULL; if ( p_playlist->current.i_size == 0 )
return NULL;
p_new = ARRAY_VAL( p_playlist->current, p_playlist->i_current_index ); p_new = ARRAY_VAL( p_playlist->current, p_playlist->i_current_index );
/* The new item can't be autoselected */ /* The new item can't be autoselected */
...@@ -460,120 +473,95 @@ static playlist_item_t *NextItem( playlist_t *p_playlist ) ...@@ -460,120 +473,95 @@ static playlist_item_t *NextItem( playlist_t *p_playlist )
return p_new; return p_new;
} }
/** static int LoopInput( playlist_t *p_playlist )
* Main loop
*
* Main loop for the playlist. It should be entered with the
* playlist lock (otherwise input event may be lost)
* \param p_playlist the playlist object
* \return nothing
*/
static void Loop( playlist_t *p_playlist )
{ {
bool b_playexit = var_GetBool( p_playlist, "play-and-exit" ); playlist_private_t *p_sys = pl_priv(p_playlist);
input_thread_t *p_input = p_sys->p_input;
PL_ASSERT_LOCKED; if( !p_input )
return VLC_EGENERIC;
if( pl_priv(p_playlist)->b_reset_currently_playing && if( ( p_sys->request.b_request || !vlc_object_alive( p_playlist ) ) && !p_input->b_die )
mdate() - pl_priv(p_playlist)->last_rebuild_date > 30000 ) // 30 ms
{ {
ResetCurrentlyPlaying( p_playlist, var_GetBool( p_playlist, "random" ), PL_DEBUG( "incoming request - stopping current input" );
get_current_status_item( p_playlist ) ); input_StopThread( p_input );
pl_priv(p_playlist)->last_rebuild_date = mdate();
} }
check_input: /* This input is dead. Remove it ! */
/* If there is an input, check that it doesn't need to die. */ if( p_input->b_dead )
if( pl_priv(p_playlist)->p_input )
{ {
input_thread_t *p_input = pl_priv(p_playlist)->p_input; PL_DEBUG( "dead input" );
if( pl_priv(p_playlist)->request.b_request && !p_input->b_die ) assert( p_sys->p_sout == NULL );
{ if( var_CreateGetBool( p_input, "sout-keep" ) )
PL_DEBUG( "incoming request - stopping current input" ); p_sys->p_sout = input_DetachSout( p_input );
input_StopThread( p_input );
}
/* This input is dead. Remove it ! */ /* The DelCallback must be issued without playlist lock
if( p_input->b_dead ) * It is not a problem as we return VLC_EGENERIC */
{ PL_UNLOCK;
sout_instance_t **pp_sout = &pl_priv(p_playlist)->p_sout; var_DelCallback( p_input, "intf-event", InputEvent, p_playlist );
PL_LOCK;
PL_DEBUG( "dead input" ); p_sys->p_input = NULL;
vlc_thread_join( p_input );
vlc_object_release( p_input );
assert( *pp_sout == NULL ); UpdateActivity( p_playlist, -DEFAULT_INPUT_ACTIVITY );
if( var_CreateGetBool( p_input, "sout-keep" ) )
*pp_sout = input_DetachSout( p_input );
/* Destroy input */ return VLC_EGENERIC;
var_DelCallback( p_input, "intf-event", InputEvent, p_playlist ); }
pl_priv(p_playlist)->p_input = NULL; /* This input is dying, let it do */
else if( p_input->b_die )
{
PL_DEBUG( "dying input" );
}
/* This input has finished, ask it to die ! */
else if( p_input->b_error || p_input->b_eof )
{
PL_DEBUG( "finished input" );
input_StopThread( p_input );
}
return VLC_SUCCESS;
}
/* Release the playlist lock, because we may get stuck static void LoopRequest( playlist_t *p_playlist )
* in vlc_object_release() for some time. */ {
PL_UNLOCK; playlist_private_t *p_sys = pl_priv(p_playlist);
vlc_thread_join( p_input ); assert( !p_sys->p_input );
vlc_object_release( p_input );
PL_LOCK;
int i_activity= var_GetInteger( p_playlist, "activity" ); /* No input. Several cases
var_SetInteger( p_playlist, "activity", * - No request, running status -> start new item
i_activity - DEFAULT_INPUT_ACTIVITY ); * - No request, stopped status -> collect garbage
goto check_input; * - Request, running requested -> start new item
} * - Request, stopped requested -> collect garbage
/* This input is dying, let it do */ */
else if( p_input->b_die ) const int i_status = p_sys->request.b_request ?
{ p_sys->request.i_status : p_sys->status.i_status;
PL_DEBUG( "dying input" );
PL_UNLOCK; if( i_status == PLAYLIST_STOPPED )
msleep( INTF_IDLE_SLEEP ); {
PL_LOCK; p_sys->status.i_status = PLAYLIST_STOPPED;
goto check_input;
} if( vlc_object_alive( p_playlist ) )
/* This input has finished, ask it to die ! */ vlc_object_wait( p_playlist );
else if( p_input->b_error || p_input->b_eof ) return;
{
PL_DEBUG( "finished input" );
input_StopThread( p_input );
/* No need to wait here, we'll wait in the p_input->b_die case */
goto check_input;
}
} }
else
playlist_item_t *p_item = NextItem( p_playlist );
if( p_item )
{ {
/* No input. Several cases msg_Dbg( p_playlist, "starting new item" );
* - No request, running status -> start new item PlayItem( p_playlist, p_item );
* - No request, stopped status -> collect garbage return;
* - Request, running requested -> start new item }
* - Request, stopped requested -> collect garbage
*/
int i_status = pl_priv(p_playlist)->request.b_request ?
pl_p