From 62baec1841af26106752cccdbc9da6811dc24949 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 4 Nov 2013 23:26:24 +0100 Subject: output/alsa: avoid endless loop in Raspberry Pi workaround See code comment. --- src/output/AlsaOutputPlugin.cxx | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'src/output') diff --git a/src/output/AlsaOutputPlugin.cxx b/src/output/AlsaOutputPlugin.cxx index 149ca507d..4877d3a46 100644 --- a/src/output/AlsaOutputPlugin.cxx +++ b/src/output/AlsaOutputPlugin.cxx @@ -105,6 +105,14 @@ struct AlsaOutput { */ snd_pcm_uframes_t period_position; + /** + * Set to non-zero when the Raspberry Pi workaround has been + * activated in alsa_recover(); decremented by each write. + * This will avoid activating it again, leading to an endless + * loop. This problem was observed with a "RME Digi9636/52". + */ + unsigned pi_workaround; + /** * This buffer gets allocated after opening the ALSA device. * It contains silence samples, enough to fill one period (see @@ -668,6 +676,8 @@ alsa_open(struct audio_output *ao, AudioFormat &audio_format, Error &error) { AlsaOutput *ad = (AlsaOutput *)ao; + ad->pi_workaround = 0; + int err = snd_pcm_open(&ad->pcm, alsa_device(ad), SND_PCM_STREAM_PLAYBACK, ad->mode); if (err < 0) { @@ -727,7 +737,7 @@ alsa_recover(AlsaOutput *ad, int err) ad->period_position = 0; err = snd_pcm_prepare(ad->pcm); - if (err == 0) { + if (err == 0 && ad->pi_workaround == 0) { /* this works around a driver bug observed on the Raspberry Pi: after snd_pcm_drop(), the whole ring buffer must be invalidated, but @@ -744,6 +754,9 @@ alsa_recover(AlsaOutput *ad, int err) silence, the driver seems to avoid the bug */ snd_pcm_reset(ad->pcm); + + /* disable the workaround for some time */ + ad->pi_workaround = 8; } break; @@ -821,6 +834,9 @@ alsa_play(struct audio_output *ao, const void *chunk, size_t size, ad->period_position = (ad->period_position + ret) % ad->period_frames; + if (ad->pi_workaround > 0) + --ad->pi_workaround; + size_t bytes_written = ret * ad->out_frame_size; return ad->pcm_export->CalcSourceSize(bytes_written); } -- cgit v1.2.3