From 10d59f5c9016fba5c7b2cfa6d1ee8cdbce2bbf24 Mon Sep 17 00:00:00 2001 From: Rinat Ibragimov Date: Tue, 18 Apr 2017 18:17:44 +0300 Subject: [PATCH 1/2] stream: add thorough state handling after pcm recovery --- src/apulse-stream.c | 58 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/src/apulse-stream.c b/src/apulse-stream.c index 56e458e..24b7d69 100644 --- a/src/apulse-stream.c +++ b/src/apulse-stream.c @@ -91,6 +91,64 @@ data_available_for_stream(pa_mainloop_api *a, pa_io_event *ioe, int fd, pa_io_ev ret = snd_pcm_recover(s->ph, frame_count, 1); } while (ret == -1 && errno == EINTR && cnt < 5); + switch (snd_pcm_state(s->ph)) { + case SND_PCM_STATE_OPEN: + // Highly unlikely device will be here in this state. But if it is, there is nothing + // can be done. + trace_error( + "Stream '%s' of context '%s' have its associated PCM device in " + "SND_PCM_STATE_OPEN state. Reconfiguration is required, but is not possible at " + "the moment. Giving up.", + s->name ? s->name : "", s->c->name ? s->c->name : ""); + break; + + case SND_PCM_STATE_SETUP: + // There is configuration, but device is not prepared and not started. + snd_pcm_prepare(s->ph); + snd_pcm_start(s->ph); + break; + + case SND_PCM_STATE_PREPARED: + // Device prepared, but not started. + snd_pcm_start(s->ph); + break; + + case SND_PCM_STATE_RUNNING: + // That's the expected state. + break; + + case SND_PCM_STATE_XRUN: + trace_error( + "Stream '%s' of context '%s' have its associated device in SND_PCM_STATE_XRUN " + "state even after xrun recovery.", + s->name ? s->name : "", s->c->name ? s->c->name : ""); + break; + + case SND_PCM_STATE_DRAINING: + trace_error( + "Stream '%s' of context '%s' have its associated device in " + "SND_PCM_STATE_DRAINING state, which is highly unusual.", + s->name ? s->name : "", s->c->name ? s->c->name : ""); + break; + + case SND_PCM_STATE_PAUSED: + // Resume from paused state. + snd_pcm_pause(s->ph, 0); + break; + + case SND_PCM_STATE_SUSPENDED: + // Resume from suspended state. + snd_pcm_resume(s->ph); + break; + + case SND_PCM_STATE_DISCONNECTED: + trace_error( + "Stream '%s' of context '%s' have its associated device in " + "SND_PCM_STATE_DISCONNECTED state. Giving up.", + s->name ? s->name : "", s->c->name ? s->c->name : ""); + break; + } + #if HAVE_SND_PCM_AVAIL frame_count = snd_pcm_avail(s->ph); #else From e59f74b34e9c970dca75ef22496035d8ff25ea38 Mon Sep 17 00:00:00 2001 From: Rinat Ibragimov Date: Tue, 18 Apr 2017 18:21:41 +0300 Subject: [PATCH 2/2] stream: ensure that buffer size is at least four times larger that period --- src/apulse-stream.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/apulse-stream.c b/src/apulse-stream.c index 24b7d69..c244958 100644 --- a/src/apulse-stream.c +++ b/src/apulse-stream.c @@ -340,8 +340,9 @@ do_connect_pcm(pa_stream *s, snd_pcm_stream_t stream_direction) trace_info_f("%s: requested period size of %d frames, got %d frames for %s\n", __func__, (int)requested_period_size, (int)period_size, device_description); + // Set up buffer size. Ensure it's at least four times larger than a period size. snd_pcm_uframes_t requested_buffer_size = s->buffer_attr.tlength / frame_size; - snd_pcm_uframes_t buffer_size = requested_buffer_size; + snd_pcm_uframes_t buffer_size = MAX(requested_buffer_size, 4 * period_size); errcode = snd_pcm_hw_params_set_buffer_size_near(s->ph, hw_params, &buffer_size); if (errcode != 0) { trace_error(