diff options
-rw-r--r-- | src/modules/module-alsa-sink.c | 38 | ||||
-rw-r--r-- | src/modules/module-alsa-source.c | 39 |
2 files changed, 77 insertions, 0 deletions
diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c index 6f8f270d..3d9f7577 100644 --- a/src/modules/module-alsa-sink.c +++ b/src/modules/module-alsa-sink.c @@ -141,6 +141,33 @@ static int xrun_recovery(struct userdata *u) { return ret; } +static int suspend_recovery(struct userdata *u) { + int ret; + assert(u); + + pa_log_info("*** ALSA-SUSPEND (playback) ***"); + + if ((ret = snd_pcm_resume(u->pcm_handle)) < 0) { + if (ret == -EAGAIN) + return -1; + + if (ret != -ENOSYS) + pa_log("snd_pcm_resume() failed: %s", snd_strerror(-ret)); + else { + if ((ret = snd_pcm_prepare(u->pcm_handle)) < 0) + pa_log("snd_pcm_prepare() failed: %s", snd_strerror(-ret)); + } + + if (ret < 0) { + clear_up(u); + pa_module_unload_request(u->module); + return -1; + } + } + + return ret; +} + static void do_write(struct userdata *u) { assert(u); @@ -176,6 +203,13 @@ static void do_write(struct userdata *u) { continue; } + if (frames == -ESTRPIPE) { + if (suspend_recovery(u) < 0) + return; + + continue; + } + pa_log("snd_pcm_writei() failed: %s", snd_strerror(-frames)); clear_up(u); @@ -207,6 +241,10 @@ static void fdl_callback(void *userdata) { if (xrun_recovery(u) < 0) return; + if (snd_pcm_state(u->pcm_handle) == SND_PCM_STATE_SUSPENDED) + if (suspend_recovery(u) < 0) + return; + do_write(u); } diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c index 2ea551cb..4061d668 100644 --- a/src/modules/module-alsa-source.c +++ b/src/modules/module-alsa-source.c @@ -143,6 +143,34 @@ static int xrun_recovery(struct userdata *u) { return 0; } + +static int suspend_recovery(struct userdata *u) { + int ret; + assert(u); + + pa_log_info("*** ALSA-SUSPEND (capture) ***"); + + if ((ret = snd_pcm_resume(u->pcm_handle)) < 0) { + if (ret == -EAGAIN) + return -1; + + if (ret != -ENOSYS) + pa_log("snd_pcm_resume() failed: %s", snd_strerror(-ret)); + else { + if ((ret = snd_pcm_prepare(u->pcm_handle)) < 0) + pa_log("snd_pcm_prepare() failed: %s", snd_strerror(-ret)); + } + + if (ret < 0) { + clear_up(u); + pa_module_unload_request(u->module); + return -1; + } + } + + return ret; +} + static void do_read(struct userdata *u) { assert(u); @@ -175,6 +203,13 @@ static void do_read(struct userdata *u) { continue; } + if (frames == -ESTRPIPE) { + if (suspend_recovery(u) < 0) + return; + + continue; + } + pa_log("snd_pcm_readi() failed: %s", snd_strerror(-frames)); clear_up(u); @@ -210,6 +245,10 @@ static void fdl_callback(void *userdata) { if (xrun_recovery(u) < 0) return; + if (snd_pcm_state(u->pcm_handle) == SND_PCM_STATE_SUSPENDED) + if (suspend_recovery(u) < 0) + return; + do_read(u); } |