diff options
author | Max Kellermann <max@duempel.org> | 2013-11-04 23:26:24 +0100 |
---|---|---|
committer | Max Kellermann <max@duempel.org> | 2013-11-04 23:40:34 +0100 |
commit | 62baec1841af26106752cccdbc9da6811dc24949 (patch) | |
tree | 358b090b09cc142c63e3c456e8b449bf05ee6255 | |
parent | 7bca61f5bbacfdf19c9e143f3829aa157d22e003 (diff) | |
download | mpd-62baec1841af26106752cccdbc9da6811dc24949.tar.gz mpd-62baec1841af26106752cccdbc9da6811dc24949.tar.xz mpd-62baec1841af26106752cccdbc9da6811dc24949.zip |
output/alsa: avoid endless loop in Raspberry Pi workaround
See code comment.
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | src/output/AlsaOutputPlugin.cxx | 18 |
2 files changed, 19 insertions, 1 deletions
@@ -5,6 +5,8 @@ ver 0.18.1 (2013/11/??) - log UNIX domain path names instead of "localhost" - open listener sockets in the order they were configured - don't abort if IPv6 is not available +* output: + - alsa: avoid endless loop in Raspberry Pi workaround * filter: - autoconvert: fix "volume_normalization" with mp3 files * add missing files to source tarball 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 @@ -106,6 +106,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 * #period_frames). @@ -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); } |