Fixed a playlist race condition on input events.
The playlist was loosing state events from input. And thus it may not
always be able to detect (by itself) the end of a stream (It happens
easily with small playlist files).
playlist_preparse_t *p_preparse; /**< Preparser object */
playlist_fetcher_t *p_fetcher;/**< Meta and art fetcher object */
playlist_preparse_t *p_preparse; /**< Preparser object */
playlist_fetcher_t *p_fetcher;/**< Meta and art fetcher object */
- vlc_mutex_t gc_lock; /**< Lock to protect the garbage collection */
-
struct {
/* Current status. These fields are readonly, only the playlist
* main loop can touch it*/
struct {
/* Current status. These fields are readonly, only the playlist
* main loop can touch it*/
VariablesInit( p_playlist );
/* Initialise data structures */
VariablesInit( p_playlist );
/* Initialise data structures */
- vlc_mutex_init( &p_playlist->gc_lock );
p_playlist->i_last_playlist_id = 0;
p_playlist->p_input = NULL;
p_playlist->i_last_playlist_id = 0;
p_playlist->p_input = NULL;
- vlc_mutex_lock( &p_playlist->gc_lock );
p_playlist->b_cant_sleep = false;
p_playlist->b_cant_sleep = false;
- vlc_mutex_unlock( &p_playlist->gc_lock );
- * Main loop for the playlist
+ * 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
*/
* \param p_playlist the playlist object
* \return nothing
*/
{
playlist_item_t *p_item = NULL;
bool b_playexit = var_GetBool( p_playlist, "play-and-exit" );
{
playlist_item_t *p_item = NULL;
bool b_playexit = var_GetBool( p_playlist, "play-and-exit" );
if( p_playlist->b_reset_currently_playing &&
mdate() - p_playlist->last_rebuild_date > 30000 ) // 30 ms
if( p_playlist->b_reset_currently_playing &&
mdate() - p_playlist->last_rebuild_date > 30000 ) // 30 ms
}
else if( p_playlist->p_input->i_state != INIT_S )
{
}
else if( p_playlist->p_input->i_state != INIT_S )
{
ObjectGarbageCollector( p_playlist, false );
ObjectGarbageCollector( p_playlist, false );
{
msg_Dbg( p_playlist, "nothing to play" );
p_playlist->status.i_status = PLAYLIST_STOPPED;
{
msg_Dbg( p_playlist, "nothing to play" );
p_playlist->status.i_status = PLAYLIST_STOPPED;
if( b_playexit == true )
{
if( b_playexit == true )
{
return;
}
playlist_PlayItem( p_playlist, p_item );
return;
}
playlist_PlayItem( p_playlist, p_item );
+ /* playlist_PlayItem loose input event, we need to recheck */
+ //if( !p_playlist->b_cant_sleep )
+ goto check_input;
p_playlist->status.i_status = PLAYLIST_STOPPED;
/* Collect garbage */
p_playlist->status.i_status = PLAYLIST_STOPPED;
/* Collect garbage */
ObjectGarbageCollector( p_playlist, b_gc_forced );
ObjectGarbageCollector( p_playlist, b_gc_forced );
vlc_object_lock( p_playlist );
while( vlc_object_alive( p_playlist ) )
{
vlc_object_lock( p_playlist );
while( vlc_object_alive( p_playlist ) )
{
playlist_MainLoop( p_playlist );
playlist_MainLoop( p_playlist );
/* The playlist lock has been unlocked, so we can't tell if
* someone has killed us in the meantime. Check now. */
/* The playlist lock has been unlocked, so we can't tell if
* someone has killed us in the meantime. Check now. */
if( p_playlist->b_cant_sleep )
{
/* 100 ms is an acceptable delay for playlist operations */
if( p_playlist->b_cant_sleep )
{
/* 100 ms is an acceptable delay for playlist operations */
+ vlc_object_unlock( p_playlist );
+
msleep( INTF_IDLE_SLEEP*2 );
msleep( INTF_IDLE_SLEEP*2 );
+
+ vlc_object_lock( p_playlist );