summaryrefslogtreecommitdiffstats
path: root/src/modules/alsa/alsa-source.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2009-06-05 19:05:42 +0200
committerLennart Poettering <lennart@poettering.net>2009-06-05 19:05:42 +0200
commit561c0af8518dd8a2bac07284d306b0970c304f9f (patch)
treeaffc1283f796d416b6ab24f36eef3ddef24df295 /src/modules/alsa/alsa-source.c
parent00797b8b6ea7978f862facb7181fb04895caf23c (diff)
alsa: monitor device reservation status and resume automatically when device becomes unused
Diffstat (limited to 'src/modules/alsa/alsa-source.c')
-rw-r--r--src/modules/alsa/alsa-source.c65
1 files changed, 62 insertions, 3 deletions
diff --git a/src/modules/alsa/alsa-source.c b/src/modules/alsa/alsa-source.c
index 68f697d2..277b1103 100644
--- a/src/modules/alsa/alsa-source.c
+++ b/src/modules/alsa/alsa-source.c
@@ -114,6 +114,8 @@ struct userdata {
pa_reserve_wrapper *reserve;
pa_hook_slot *reserve_slot;
+ pa_reserve_monitor_wrapper *monitor;
+ pa_hook_slot *monitor_slot;
};
static void userdata_free(struct userdata *u);
@@ -183,6 +185,57 @@ static int reserve_init(struct userdata *u, const char *dname) {
return 0;
}
+static pa_hook_result_t monitor_cb(pa_reserve_monitor_wrapper *w, void* busy, struct userdata *u) {
+ pa_bool_t b;
+
+ pa_assert(w);
+ pa_assert(u);
+
+ b = PA_PTR_TO_UINT(busy) && !u->reserve;
+
+ pa_source_suspend(u->source, b, PA_SUSPEND_APPLICATION);
+ return PA_HOOK_OK;
+}
+
+static void monitor_done(struct userdata *u) {
+ pa_assert(u);
+
+ if (u->monitor_slot) {
+ pa_hook_slot_free(u->monitor_slot);
+ u->monitor_slot = NULL;
+ }
+
+ if (u->monitor) {
+ pa_reserve_monitor_wrapper_unref(u->monitor);
+ u->monitor = NULL;
+ }
+}
+
+static int reserve_monitor_init(struct userdata *u, const char *dname) {
+ char *rname;
+
+ pa_assert(u);
+ pa_assert(dname);
+
+ if (pa_in_system_mode())
+ return 0;
+
+ /* We are resuming, try to lock the device */
+ if (!(rname = pa_alsa_get_reserve_name(dname)))
+ return 0;
+
+ u->monitor = pa_reserve_monitor_wrapper_get(u->core, rname);
+ pa_xfree(rname);
+
+ if (!(u->monitor))
+ return -1;
+
+ pa_assert(!u->monitor_slot);
+ u->monitor_slot = pa_hook_connect(pa_reserve_monitor_wrapper_hook(u->monitor), PA_HOOK_NORMAL, (pa_hook_cb_t) monitor_cb, u);
+
+ return 0;
+}
+
static void fix_min_sleep_wakeup(struct userdata *u) {
size_t max_use, max_use_2;
pa_assert(u);
@@ -1438,9 +1491,14 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
pa_rtclock_usec(),
FALSE);
- if (reserve_init(u, pa_modargs_get_value(
- ma, "device_id",
- pa_modargs_get_value(ma, "device", DEFAULT_DEVICE))) < 0)
+ dev_id = pa_modargs_get_value(
+ ma, "device_id",
+ pa_modargs_get_value(ma, "device", DEFAULT_DEVICE));
+
+ if (reserve_init(u, dev_id) < 0)
+ goto fail;
+
+ if (reserve_monitor_init(u, dev_id) < 0)
goto fail;
b = use_mmap;
@@ -1676,6 +1734,7 @@ static void userdata_free(struct userdata *u) {
pa_smoother_free(u->smoother);
reserve_done(u);
+ monitor_done(u);
pa_xfree(u->device_name);
pa_xfree(u);