# HG changeset patch # User William Pitcock # Date 1242363767 18000 # Node ID 8cbf077ba5d05981f02d1aab2d0f5afd691206d1 # Parent 087abc78516e3c19b30cd1363eb0f1e9de875cad alsa-ng: Software pause, so we don't have to use snd_pcm_pause(), which is not part of the safe ALSA subset. Also, make heavy use of thread signalling to remove crap like: while (condition != true && pcm_going) g_usleep(10000); That's... so XMMS. diff -r 087abc78516e -r 8cbf077ba5d0 src/alsa-ng/alsa-core.c --- a/src/alsa-ng/alsa-core.c Thu May 14 23:14:50 2009 -0500 +++ b/src/alsa-ng/alsa-core.c Fri May 15 00:02:47 2009 -0500 @@ -29,8 +29,10 @@ static gsize wr_total = 0; static gsize wr_hwframes = 0; -static gint flush_request, pause_request, paused; -static gboolean can_pause; +static gint flush_request, paused; + +static GMutex *pcm_pause_mutex, *pcm_state_mutex; +static GCond *pcm_pause_cond, *pcm_state_cond; /******************************************************************************** * ALSA Mixer setting functions. * @@ -80,24 +82,25 @@ snd_pcm_prepare(pcm_handle); wr_total = flush_request * (bps / 1000); flush_request = -1; - } - if (pause_request != paused) - { - snd_pcm_pause(pcm_handle, pause_request); - paused = pause_request; - continue; + g_cond_broadcast(pcm_state_cond); } if (alsaplug_ringbuffer_read(&pcm_ringbuf, buf, 2048) == -1) { /* less than 2048 bytes to go...? */ gint remain = alsaplug_ringbuffer_used(&pcm_ringbuf); - if (remain <= 2048) + 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); + } continue; } @@ -108,6 +111,7 @@ snd_pcm_drain(pcm_handle); snd_pcm_close(pcm_handle); pcm_handle = NULL; + alsaplug_ringbuffer_destroy(&pcm_ringbuf); return NULL; } @@ -121,6 +125,12 @@ { 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(); + if (snd_card_next(&card) != 0) return OUTPUT_PLUGIN_INIT_NO_DEVICES; @@ -157,7 +167,6 @@ return -1; } - can_pause = snd_pcm_hw_params_can_pause(hwparams); bitwidth = snd_pcm_format_physical_width(afmt); bps = (rate * bitwidth * nch) >> 3; ringbuf_size = aud_cfg->output_buffer_size * bps / 1000; @@ -172,7 +181,10 @@ static void alsaplug_close_audio(void) { + g_mutex_lock(pcm_state_mutex); pcm_going = FALSE; + g_mutex_unlock(pcm_state_mutex); + g_cond_broadcast(pcm_state_cond); g_thread_join(audio_thread); audio_thread = NULL; @@ -180,14 +192,21 @@ wr_total = 0; wr_hwframes = 0; bps = 0; - alsaplug_ringbuffer_destroy(&pcm_ringbuf); } static void alsaplug_write_audio(gpointer data, gint length) { + if (paused) + { + g_mutex_lock(pcm_pause_mutex); + g_cond_wait(pcm_pause_cond, pcm_pause_mutex); + g_mutex_unlock(pcm_pause_mutex); + } + wr_total += length; alsaplug_ringbuffer_write(&pcm_ringbuf, data, length); + g_cond_broadcast(pcm_state_cond); } static gint @@ -231,9 +250,16 @@ static void alsaplug_flush(gint time) { + /* make the request... */ + g_mutex_lock(pcm_state_mutex); flush_request = time; - while (flush_request != -1 && pcm_going) - g_usleep(10000); + g_mutex_unlock(pcm_state_mutex); + g_cond_broadcast(pcm_state_cond); + + /* ...then wait for the transaction to complete. */ + g_mutex_lock(pcm_state_mutex); + g_cond_wait(pcm_state_cond, pcm_state_mutex); + g_mutex_unlock(pcm_state_mutex); } static gint @@ -245,7 +271,10 @@ static void alsaplug_pause(short p) { - pause_request = p; + g_mutex_lock(pcm_pause_mutex); + paused = p; + g_mutex_unlock(pcm_pause_mutex); + g_cond_broadcast(pcm_pause_cond); } /********************************************************************************