changeset 3319:d4f6507cded3 trunk

added a system that allows input plugins to signal to the core (actually, they MUST do it) that they're ready for playback and it's safe to call their stop function; this fixes a nasty race condition that triggered on fast track-switching
author Giacomo Lozito <james@develia.org>
date Fri, 10 Aug 2007 21:58:19 +0200
parents 6e3ae4fd65f1
children 3a3f43afd9a0 b01c8d41d35b
files src/audacious/playback.c src/audacious/plugin.h
diffstat 2 files changed, 47 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/src/audacious/playback.c	Fri Aug 10 12:52:15 2007 -0500
+++ b/src/audacious/playback.c	Fri Aug 10 21:58:19 2007 +0200
@@ -61,6 +61,27 @@
 
 static int song_info_timeout_source = 0;
 
+
+static gint
+playback_set_pb_ready(InputPlayback *playback)
+{
+    g_mutex_lock(playback->pb_ready_mutex);
+    playback->pb_ready_val = 1;
+    g_cond_signal(playback->pb_ready_cond);
+    g_mutex_unlock(playback->pb_ready_mutex);
+    return 0;
+}
+
+static gint
+playback_wait_for_pb_ready(InputPlayback *playback)
+{
+    g_mutex_lock(playback->pb_ready_mutex);
+    while (playback->pb_ready_val != 1)
+        g_cond_wait(playback->pb_ready_cond, playback->pb_ready_mutex);
+    g_mutex_unlock(playback->pb_ready_mutex);
+    return 0;
+}
+
 void
 playback_eof(void)
 {
@@ -186,6 +207,10 @@
 
     if (ip_data.playing)
     {
+        /* wait for plugin to signal it has reached
+           the 'playback safe state' before stopping */
+        playback_wait_for_pb_ready(playback);
+
         if (playback_get_paused() == TRUE)
         {
             if (get_written_time() > 0)
@@ -193,7 +218,7 @@
             playback_pause();
         }
 
-        ip_data.playing = FALSE; 
+        ip_data.playing = FALSE;
 
         if (playback->plugin->stop)
             playback->plugin->stop(playback);
@@ -204,9 +229,14 @@
         free_vis_data();
         ip_data.paused = FALSE;
 
-	g_free(playback->filename);
-	g_free(playback);
-	set_current_input_playback(NULL);
+        if (playback->pb_ready_mutex)
+            g_mutex_free(playback->pb_ready_mutex);
+        if (playback->pb_ready_cond)
+            g_cond_free(playback->pb_ready_cond);
+
+        g_free(playback->filename);
+        g_free(playback);
+        set_current_input_playback(NULL);
     }
 
     ip_data.buffering = FALSE;
@@ -245,6 +275,10 @@
 
     playback->plugin->play_file(playback);
 
+    /* if play_file has not reached the 'safe state' before returning (an error
+       occurred), set the playback ready value to 1 now, to allow for proper stop */
+    playback_set_pb_ready(playback);
+
     if (!playback->error && ip_data.playing)
         playback_eof();
     else if (playback->error)
@@ -301,6 +335,10 @@
     playback->output = &psuedo_output_plugin;
     playback->filename = g_strdup(entry->filename);
     playback->thread = g_thread_self();
+    playback->pb_ready_mutex = g_mutex_new();
+    playback->pb_ready_cond = g_cond_new();
+    playback->pb_ready_val = 0;
+    playback->set_pb_ready = playback_set_pb_ready;
     
     set_current_input_playback(playback);
 
--- a/src/audacious/plugin.h	Fri Aug 10 12:52:15 2007 -0500
+++ b/src/audacious/plugin.h	Fri Aug 10 21:58:19 2007 +0200
@@ -214,6 +214,11 @@
     gboolean eof;
 
     GThread *thread;
+    
+    GMutex *pb_ready_mutex;
+    GCond *pb_ready_cond;
+    gint pb_ready_val;    
+    gint (*set_pb_ready) (InputPlayback*);
 };
 
 struct _InputPlugin {