changeset 3191:a65f440cbed3

alsa-ng: Fix possible race conditions, sluggish pause and seek.
author John Lindgren <john.lindgren@tds.net>
date Mon, 22 Jun 2009 16:05:57 -0400
parents 2f5be25204f3
children d1d9b159801a
files src/alsa-ng/alsa-core.c
diffstat 1 files changed, 22 insertions(+), 34 deletions(-) [+]
line wrap: on
line diff
--- a/src/alsa-ng/alsa-core.c	Fri Jun 19 09:30:27 2009 -0500
+++ b/src/alsa-ng/alsa-core.c	Mon Jun 22 16:05:57 2009 -0400
@@ -31,8 +31,8 @@
 
 static gint flush_request, paused;
 
-static GMutex *pcm_pause_mutex, *pcm_state_mutex;
-static GCond *pcm_pause_cond, *pcm_state_cond, *pcm_flush_cond;
+static GMutex * pcm_state_mutex;
+static GCond * pcm_state_cond, * pcm_flush_cond;
 
 /********************************************************************************
  * ALSA Mixer setting functions.                                                *
@@ -213,11 +213,15 @@
 alsaplug_loop(gpointer unused)
 {
     guchar buf[2048];
+    int size;
 
     while (pcm_going)
     {
+        g_mutex_lock (pcm_state_mutex);
+
         if (flush_request != -1)
         {
+            alsaplug_ringbuffer_reset (& pcm_ringbuf);
             snd_pcm_drop(pcm_handle);
             snd_pcm_prepare(pcm_handle);
             wr_total = flush_request * (long long) bps / 1000;
@@ -226,26 +230,21 @@
             g_cond_broadcast(pcm_flush_cond);
         }
 
-        if (alsaplug_ringbuffer_read(&pcm_ringbuf, buf, 2048) == -1)
+        size = alsaplug_ringbuffer_used (& pcm_ringbuf);
+
+        if (size == 0 || paused)
         {
-            /* less than 2048 bytes to go...? */
-            gint remain = alsaplug_ringbuffer_used(&pcm_ringbuf);
-            if (remain <= 2048 && remain > 0)
-            {
-                alsaplug_ringbuffer_read(&pcm_ringbuf, buf, remain);
-                alsaplug_write_buffer(buf, remain);
-            }
-            else
-            {
-                g_mutex_lock(pcm_state_mutex);
-                g_cond_wait(pcm_state_cond, pcm_state_mutex);
-                g_mutex_unlock(pcm_state_mutex);
-            }
-
+            g_cond_wait (pcm_state_cond, pcm_state_mutex);
+            g_mutex_unlock (pcm_state_mutex);
             continue;
         }
 
-        alsaplug_write_buffer(buf, 2048);
+        if (size > sizeof buf)
+            size = sizeof buf;
+
+        alsaplug_ringbuffer_read (& pcm_ringbuf, buf, size);
+        g_mutex_unlock (pcm_state_mutex);
+        alsaplug_write_buffer (buf, size);
     }
 
     snd_pcm_drain(pcm_handle);
@@ -266,9 +265,6 @@
 {
     gint card = -1;
 
-    pcm_pause_mutex = g_mutex_new();
-    pcm_pause_cond = g_cond_new();
-
     pcm_state_mutex = g_mutex_new();
     pcm_state_cond = g_cond_new();
     pcm_flush_cond = g_cond_new();
@@ -341,8 +337,8 @@
     wr_hwframes = 0;
     bps = 0;
 
+    g_cond_broadcast (pcm_state_cond);
     g_mutex_unlock(pcm_state_mutex);
-    g_cond_broadcast(pcm_state_cond);
 
     if (audio_thread != NULL)
         g_thread_join(audio_thread);
@@ -353,19 +349,11 @@
 static void
 alsaplug_write_audio(gpointer data, gint length)
 {
-    /* software pause... snd_pcm_pause() is not safe. --nenolod */
-    if (paused)
-    {
-        g_mutex_lock(pcm_pause_mutex);
-        g_cond_wait(pcm_pause_cond, pcm_pause_mutex);
-        g_mutex_unlock(pcm_pause_mutex);
-    }
-
     g_mutex_lock(pcm_state_mutex);
     wr_total += length;
     alsaplug_ringbuffer_write(&pcm_ringbuf, data, length);
+    g_cond_broadcast (pcm_state_cond);
     g_mutex_unlock(pcm_state_mutex);
-    g_cond_broadcast(pcm_state_cond);
 }
 
 static gint
@@ -462,10 +450,10 @@
 static void
 alsaplug_pause(short p)
 {
-    g_mutex_lock(pcm_pause_mutex);
+    g_mutex_lock (pcm_state_mutex);
     paused = p;
-    g_mutex_unlock(pcm_pause_mutex);
-    g_cond_broadcast(pcm_pause_cond);
+    g_cond_broadcast (pcm_state_cond);
+    g_mutex_unlock (pcm_state_mutex);
 }
 
 /********************************************************************************