diff options
author | Takashi Iwai <tiwai@suse.de> | 2007-12-14 15:25:46 +0100 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2007-12-14 15:25:46 +0100 |
commit | 660e0f16145167a966e9b8387e9a8e08274a8f7c (patch) | |
tree | d2e80b28d113fca9c1fd1ca2e7b7530d8f6a6848 | |
parent | 327e169964b0a5bdcffb46eb49a305f3aabaeab4 (diff) |
PulseAudio plugin: report XRUN state back to application
From: Lennart Poettering <mznyfn@0pointer.de>
It adds support to report back XRUN to the application if one
happens. This is required to make some applications work on top of the
pulse plugin. One being XMMS, which checks if a song finished to play
by waiting for an XRUN (yes, I don't argue that XMMS shouldn't do
that, but nonetheless it is a good thing if XRUNs are reported
properly.)
-rw-r--r-- | pulse/pcm_pulse.c | 23 |
1 files changed, 22 insertions, 1 deletions
diff --git a/pulse/pcm_pulse.c b/pulse/pcm_pulse.c index da15792..b6d5b46 100644 --- a/pulse/pcm_pulse.c +++ b/pulse/pcm_pulse.c @@ -36,6 +36,7 @@ typedef struct snd_pcm_pulse { /* Since ALSA expects a ring buffer we must do some voodoo. */ size_t last_size; size_t ptr; + int underrun; size_t offset; @@ -90,7 +91,9 @@ static int pulse_start(snd_pcm_ioplug_t *io) if (err < 0) { err = -EIO; goto finish; - } + } else + pcm->underrun = 0; + finish: pa_threaded_mainloop_unlock(pcm->p->mainloop); @@ -200,6 +203,9 @@ static snd_pcm_sframes_t pulse_pointer(snd_pcm_ioplug_t *io) err = snd_pcm_bytes_to_frames(io->pcm, pcm->ptr); + if (pcm->underrun) + err = -EPIPE; + finish: pa_threaded_mainloop_unlock(pcm->p->mainloop); @@ -231,6 +237,9 @@ static int pulse_delay(snd_pcm_ioplug_t *io, *delayp = snd_pcm_bytes_to_frames(io->pcm, pa_usec_to_bytes(lat, &pcm->ss)); + if (pcm->underrun && pcm->io.state == SND_PCM_STATE_RUNNING) + snd_pcm_ioplug_set_state(io, SND_PCM_STATE_XRUN); + finish: pa_threaded_mainloop_unlock(pcm->p->mainloop); @@ -273,6 +282,7 @@ static snd_pcm_sframes_t pulse_write(snd_pcm_ioplug_t *io, pulse_poll_deactivate(pcm->p); err = size; + pcm->underrun = 0; finish: pa_threaded_mainloop_unlock(pcm->p->mainloop); @@ -354,6 +364,15 @@ static void stream_request_cb(pa_stream *p, size_t length, void *userdata) pulse_poll_activate(pcm->p); } +static void stream_underrun_cb(pa_stream *p, void *userdata) { + snd_pcm_pulse_t *pcm = userdata; + + assert(pcm); + assert(pcm->p); + + pcm->underrun = 1; +} + static int pulse_pcm_poll_descriptors_count(snd_pcm_ioplug_t *io) { snd_pcm_pulse_t *pcm = io->private_data; @@ -461,6 +480,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); + pa_stream_set_underflow_callback(pcm->stream, stream_underrun_cb, pcm); pa_stream_connect_playback(pcm->stream, pcm->device, &pcm->buffer_attr, PA_STREAM_AUTO_TIMING_UPDATE | PA_STREAM_INTERPOLATE_TIMING, NULL, NULL); } else { @@ -480,6 +500,7 @@ static int pulse_prepare(snd_pcm_ioplug_t *io) pcm->last_size = 0; pcm->ptr = 0; pcm->offset = 0; + pcm->underrun = 0; finish: pa_threaded_mainloop_unlock(pcm->p->mainloop); |