[PATCH] alsa-plugins: Pulse: only underrun if no more data has been written
If more data has already been written after the underrun, the underrun will automatically end and therefore we should not report it or restart the stream.
Signed-off-by: David Henningsson david.henningsson@canonical.com --- pulse/pcm_pulse.c | 36 ++++++++++++++++++++++++++++++++++-- 1 files changed, 34 insertions(+), 2 deletions(-)
diff --git a/pulse/pcm_pulse.c b/pulse/pcm_pulse.c index d6c6792..92f4777 100644 --- a/pulse/pcm_pulse.c +++ b/pulse/pcm_pulse.c @@ -40,8 +40,10 @@ typedef struct snd_pcm_pulse { size_t ptr; int underrun; int handle_underrun; + int handle_underrun_detect;
size_t offset; + int64_t written;
pa_stream *stream;
@@ -460,6 +462,7 @@ static snd_pcm_sframes_t pulse_write(snd_pcm_ioplug_t * io,
/* Make sure the buffer pointer is in sync */ pcm->last_size -= writebytes; + pcm->written += writebytes; ret = update_ptr(pcm); if (ret < 0) goto finish; @@ -585,6 +588,23 @@ static void stream_request_cb(pa_stream * p, size_t length, void *userdata) update_active(pcm); }
+#if defined(PA_CHECK_VERSION) && PA_CHECK_VERSION(0,99,0) + +#define has_underrun_detect 1 + +static inline int do_underrun_detect(snd_pcm_pulse_t *pcm, pa_stream *p) +{ + return pcm->handle_underrun_detect && + pcm->written <= pa_stream_get_underflow_index(p); +} + +#else + +#define has_underrun_detect 0 +#define do_underrun_detect(pcm, p) 0 + +#endif + static void stream_underrun_cb(pa_stream * p, void *userdata) { snd_pcm_pulse_t *pcm = userdata; @@ -594,7 +614,8 @@ static void stream_underrun_cb(pa_stream * p, void *userdata) if (!pcm->p) return;
- pcm->underrun = 1; + if (pcm->handle_underrun || do_underrun_detect(pcm, p)) + pcm->underrun = 1; }
static void stream_latency_cb(pa_stream *p, void *userdata) { @@ -697,7 +718,7 @@ static int pulse_prepare(snd_pcm_ioplug_t * io) if (io->stream == SND_PCM_STREAM_PLAYBACK) { pa_stream_set_write_callback(pcm->stream, stream_request_cb, pcm); - if (pcm->handle_underrun) + if (pcm->handle_underrun_detect || pcm->handle_underrun) pa_stream_set_underflow_callback(pcm->stream, stream_underrun_cb, pcm); r = pa_stream_connect_playback(pcm->stream, pcm->device, @@ -739,6 +760,7 @@ static int pulse_prepare(snd_pcm_ioplug_t * io)
pcm->offset = 0; pcm->underrun = 0; + pcm->written = 0;
/* Reset fake ringbuffer */ pcm->last_size = 0; @@ -984,6 +1006,7 @@ SND_PCM_PLUGIN_DEFINE_FUNC(pulse) const char *device = NULL; const char *fallback_name = NULL; int handle_underrun = 0; + int handle_underrun_detect = 1; int err; snd_pcm_pulse_t *pcm;
@@ -1017,6 +1040,14 @@ SND_PCM_PLUGIN_DEFINE_FUNC(pulse) handle_underrun = err; continue; } + if (strcmp(id, "handle_underrun_detect") == 0) { + if ((err = snd_config_get_bool(n)) < 0) { + SNDERR("Invalid value for %s", id); + return -EINVAL; + } + handle_underrun_detect = err; + continue; + } if (strcmp(id, "fallback") == 0) { if (snd_config_get_string(n, &fallback_name) < 0) { SNDERR("Invalid value for %s", id); @@ -1051,6 +1082,7 @@ SND_PCM_PLUGIN_DEFINE_FUNC(pulse) }
pcm->handle_underrun = handle_underrun; + pcm->handle_underrun_detect = has_underrun_detect && handle_underrun_detect;
err = pulse_connect(pcm->p, server, fallback_name != NULL); if (err < 0)
participants (1)
-
David Henningsson