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 --- configure.in | 7 +++++++ pulse/pcm_pulse.c | 28 ++++++++++++++++++++++++++-- 2 files changed, 33 insertions(+), 2 deletions(-)
diff --git a/configure.in b/configure.in index ccf59ba..f6886b1 100644 --- a/configure.in +++ b/configure.in @@ -31,8 +31,14 @@ AC_ARG_ENABLE([pulseaudio],
if test "x$enable_pulseaudio" != "xno"; then PKG_CHECK_MODULES(pulseaudio, [libpulse >= 0.9.11], [HAVE_PULSE=yes], [HAVE_PULSE=no]) + PKG_CHECK_MODULES(pulseaudio_099, [libpulse >= 0.99.1], + [HAVE_PULSE_UNDERRUN_INDEX=yes], [HAVE_PULSE_UNDERRUN_INDEX=no]) + fi AM_CONDITIONAL(HAVE_PULSE, test x$HAVE_PULSE = xyes) +if test "$HAVE_PULSE_UNDERRUN_INDEX" = "yes"; then + AC_DEFINE([HAVE_PULSE_UNDERRUN_INDEX], 1, Pulseaudio underrun index available) +fi
AC_ARG_ENABLE([samplerate], AS_HELP_STRING([--disable-samplerate], [Disable building of samplerate plugin])) @@ -185,6 +191,7 @@ echo "Pulseaudio plugin: $HAVE_PULSE" if test "$HAVE_PULSE" = "yes"; then echo " pulseaudio_CFLAGS: $pulseaudio_CFLAGS" echo " pulseaudio_LIBS: $pulseaudio_LIBS" + echo " pulseaudio underrun index: $HAVE_PULSE_UNDERRUN_INDEX" fi echo "Samplerate plugin: $HAVE_SAMPLERATE" if test "$HAVE_SAMPLERATE" = "yes"; then diff --git a/pulse/pcm_pulse.c b/pulse/pcm_pulse.c index d6c6792..61f1c0c 100644 --- a/pulse/pcm_pulse.c +++ b/pulse/pcm_pulse.c @@ -26,6 +26,10 @@ #include <alsa/asoundlib.h> #include <alsa/pcm_external.h>
+#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + #include "pulse.h"
typedef struct snd_pcm_pulse { @@ -39,9 +43,10 @@ typedef struct snd_pcm_pulse { size_t last_size; size_t ptr; int underrun; - int handle_underrun; + int handle_underrun; /* can be 0=never, 1=always or 2,3=only if more data has not been written */
size_t offset; + int64_t written;
pa_stream *stream;
@@ -459,6 +464,7 @@ static snd_pcm_sframes_t pulse_write(snd_pcm_ioplug_t * io, }
/* Make sure the buffer pointer is in sync */ + pcm->written += writebytes; pcm->last_size -= writebytes; ret = update_ptr(pcm); if (ret < 0) @@ -594,7 +600,12 @@ static void stream_underrun_cb(pa_stream * p, void *userdata) if (!pcm->p) return;
- pcm->underrun = 1; + if (pcm->handle_underrun == 1 +#ifdef HAVE_PULSE_UNDERRUN_INDEX + || pcm->written <= pa_stream_get_underflow_index(p) +#endif + ) + pcm->underrun = 1; }
static void stream_latency_cb(pa_stream *p, void *userdata) { @@ -691,6 +702,7 @@ static int pulse_prepare(snd_pcm_ioplug_t * io) goto finish; }
+ pcm->written = 0; pa_stream_set_state_callback(pcm->stream, stream_state_cb, pcm); pa_stream_set_latency_update_callback(pcm->stream, stream_latency_cb, pcm);
@@ -983,7 +995,11 @@ SND_PCM_PLUGIN_DEFINE_FUNC(pulse) const char *server = NULL; const char *device = NULL; const char *fallback_name = NULL; +#ifdef HAVE_PULSE_UNDERRUN_INDEX + int handle_underrun = 2; +#else int handle_underrun = 0; +#endif int err; snd_pcm_pulse_t *pcm;
@@ -1017,6 +1033,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 = err ? handle_underrun | 2 : handle_underrun & ~2; + continue; + } if (strcmp(id, "fallback") == 0) { if (snd_config_get_string(n, &fallback_name) < 0) { SNDERR("Invalid value for %s", id);