summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/modules/module-alsa-sink.c38
-rw-r--r--src/modules/module-alsa-source.c39
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);
}