Don't loop continuously the playlist thread, use cond.
authorClément Stenac <zorglub@videolan.org>
Sat, 21 Oct 2006 13:33:06 +0000 (13:33 +0000)
committerClément Stenac <zorglub@videolan.org>
Sat, 21 Oct 2006 13:33:06 +0000 (13:33 +0000)
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

include/vlc_playlist.h
modules/gui/qt4/dialogs/interaction.cpp
src/input/input.c
src/interface/interaction.c
src/playlist/control.c
src/playlist/engine.c
src/playlist/item.c
src/playlist/thread.c

index ec33ee3..9acba26 100644 (file)
@@ -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;
+}
+
 /**
  * @}
  */
index 2859a56..0f814aa 100644 (file)
@@ -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 );
 }
index bce9236..484d776 100644 (file)
@@ -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 */
index 8d32327..0f44a5a 100644 (file)
@@ -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;
         }
     }
index 6543bfd..735f58d 100644 (file)
@@ -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;
 }
index f7ba590..adc1616 100644 (file)
@@ -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( mdate() - p_playlist->gc_date < 1000000 )
+    {
+        p_playlist->b_cant_sleep = VLC_TRUE;
+        return;
+    }
+    else if( p_playlist->gc_date == 0 )
+        return;
 
-    if( destroy_date == 0 )
+    vlc_mutex_lock( &p_playlist->gc_lock );
+    while( ( p_obj = vlc_object_find( p_playlist, VLC_OBJECT_VOUT,
+                                                  FIND_CHILD ) ) )
     {
-        /* give a little time */
-        return mdate() + I64C(1000000);
+        if( p_obj->p_parent != (vlc_object_t*)p_playlist )
+        {
+            vlc_object_release( p_obj );
+            break;
+        }
+        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
+    while( ( p_obj = vlc_object_find( p_playlist, VLC_OBJECT_SOUT,
+                                                  FIND_CHILD ) ) )
     {
-        vlc_mutex_lock( &p_playlist->gc_lock );
-        while( ( p_obj = vlc_object_find( p_playlist, i_type, FIND_CHILD ) ) )
+        if( p_obj->p_parent != (vlc_object_t*)p_playlist )
         {
-            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 )
-            {
-                vlc_object_release( p_obj );
-                sout_DeleteInstance( (sout_instance_t*)p_obj );
-            }
+            vlc_object_release( p_obj );
+            break;
         }
-        vlc_mutex_unlock( &p_playlist->gc_lock );
-        return 0;
+        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 );
 }
 
 /** 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
@@ -364,23 +361,20 @@ void playlist_MainLoop( playlist_t *p_playlist )
          }
          else
          {
-             p_playlist->status.i_status = PLAYLIST_STOPPED;
-             if( p_playlist->status.p_item &&
-                 p_playlist->status.p_item->i_flags & PLAYLIST_REMOVE_FLAG )
-             {
-                 PL_DEBUG( "deleting item marked for deletion" );
-                 playlist_ItemDelete( p_playlist->status.p_item );
-                 p_playlist->status.p_item = NULL;
-             }
+            p_playlist->status.i_status = PLAYLIST_STOPPED;
+            if( p_playlist->status.p_item &&
+                p_playlist->status.p_item->i_flags & PLAYLIST_REMOVE_FLAG )
+            {
+                PL_DEBUG( "deleting item marked for deletion" );
+                playlist_ItemDelete( p_playlist->status.p_item );
+                p_playlist->status.p_item = NULL;
+            }
 
-             /* 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
-         }
+            /* Collect garbage */
+            PL_UNLOCK;
+            ObjectGarbageCollector( p_playlist );
+            PL_LOCK;
+        }
     }
     PL_UNLOCK
 }
index 45f394e..3a610f7 100644 (file)
@@ -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;
     }
index 725751a..65759bf 100644 (file)
@@ -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,9 +176,17 @@ static void RunControlThread ( playlist_t *p_playlist )
 
         HandleInteraction( p_playlist );
         HandlePlaylist( p_playlist );
-
-        /* 100 ms is an acceptable delay for playlist operations */
-        msleep( INTF_IDLE_SLEEP*2 );
+        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 );