[pulseaudio-discuss] [PATCH 2/2] device-restore: Restore volumes on port change.

Colin Guthrie colin at mageia.org
Wed Aug 24 14:58:44 PDT 2011


This will allow for volumes to be saved separately for e.g. Headphones vs. Speakers.

At present it is possible that no volume will be saved for the device prior to the port
switch. In this case the volume will not change from the value set under the other port.
In an ideal world we would save the volume before switching port, but that would require
a new hook.
---
 src/modules/module-device-restore.c |   89 +++++++++++++++++++++++++++++++++++
 1 files changed, 89 insertions(+), 0 deletions(-)

diff --git a/src/modules/module-device-restore.c b/src/modules/module-device-restore.c
index b76f748..cb23832 100644
--- a/src/modules/module-device-restore.c
+++ b/src/modules/module-device-restore.c
@@ -83,9 +83,11 @@ struct userdata {
     pa_hook_slot
         *sink_new_hook_slot,
         *sink_fixate_hook_slot,
+        *sink_port_hook_slot,
         *sink_put_hook_slot,
         *source_new_hook_slot,
         *source_fixate_hook_slot,
+        *source_port_hook_slot,
         *connection_unlink_hook_slot;
     pa_time_event *save_time_event;
     pa_database *database;
@@ -804,6 +806,46 @@ static pa_hook_result_t sink_fixate_hook_callback(pa_core *c, pa_sink_new_data *
     return PA_HOOK_OK;
 }
 
+static pa_hook_result_t sink_port_hook_callback(pa_core *c, pa_sink *sink, struct userdata *u) {
+    char *name;
+    struct perportentry *e;
+
+    pa_assert(c);
+    pa_assert(sink);
+    pa_assert(u);
+    pa_assert(u->restore_volume || u->restore_muted);
+
+    name = pa_sprintf_malloc("sink:%s:%s", sink->name, (sink->active_port ? sink->active_port->name : "null"));
+
+    if ((e = perportentry_read(u, name))) {
+
+        if (u->restore_volume && e->volume_valid) {
+
+            pa_cvolume v;
+
+            pa_log_info("Restoring volume for sink %s.", sink->name);
+
+            v = e->volume;
+            pa_cvolume_remap(&v, &e->channel_map, &sink->channel_map);
+            pa_sink_set_volume(sink, &v, TRUE, FALSE);
+            sink->save_volume = TRUE;
+        }
+
+        if (u->restore_muted && e->muted_valid) {
+
+            pa_log_info("Restoring mute state for sink %s.", sink->name);
+            pa_sink_set_mute(sink, e->muted, FALSE);
+            sink->save_muted = TRUE;
+        }
+
+        perportentry_free(e);
+    }
+
+    pa_xfree(name);
+
+    return PA_HOOK_OK;
+}
+
 static pa_hook_result_t sink_put_hook_callback(pa_core *c, pa_sink *sink, struct userdata *u) {
     char *name;
     struct perportentry *e;
@@ -905,6 +947,46 @@ static pa_hook_result_t source_fixate_hook_callback(pa_core *c, pa_source_new_da
     return PA_HOOK_OK;
 }
 
+static pa_hook_result_t source_port_hook_callback(pa_core *c, pa_source *source, struct userdata *u) {
+    char *name;
+    struct perportentry *e;
+
+    pa_assert(c);
+    pa_assert(source);
+    pa_assert(u);
+    pa_assert(u->restore_volume || u->restore_muted);
+
+    name = pa_sprintf_malloc("source:%s:%s", source->name, (source->active_port ? source->active_port->name : "null"));
+
+    if ((e = perportentry_read(u, name))) {
+
+        if (u->restore_volume && e->volume_valid) {
+
+            pa_cvolume v;
+
+            pa_log_info("Restoring volume for source %s.", source->name);
+
+            v = e->volume;
+            pa_cvolume_remap(&v, &e->channel_map, &source->channel_map);
+            pa_source_set_volume(source, &v, TRUE, FALSE);
+            source->save_volume = TRUE;
+        }
+
+        if (u->restore_muted && e->muted_valid) {
+
+            pa_log_info("Restoring mute state for source %s.", source->name);
+            pa_source_set_mute(source, e->muted, FALSE);
+            source->save_muted = TRUE;
+        }
+
+        perportentry_free(e);
+    }
+
+    pa_xfree(name);
+
+    return PA_HOOK_OK;
+}
+
 #define EXT_VERSION 1
 
 static void read_sink_format_reply(struct userdata *u, pa_tagstruct *reply, pa_sink *sink) {
@@ -1170,6 +1252,9 @@ int pa__init(pa_module*m) {
     if (restore_muted || restore_volume) {
         u->sink_fixate_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_FIXATE], PA_HOOK_EARLY, (pa_hook_cb_t) sink_fixate_hook_callback, u);
         u->source_fixate_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_FIXATE], PA_HOOK_EARLY, (pa_hook_cb_t) source_fixate_hook_callback, u);
+
+        u->sink_port_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_PORT_CHANGED], PA_HOOK_EARLY, (pa_hook_cb_t) sink_port_hook_callback, u);
+        u->source_port_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_PORT_CHANGED], PA_HOOK_EARLY, (pa_hook_cb_t) source_port_hook_callback, u);
     }
 
     if (restore_formats)
@@ -1224,6 +1309,10 @@ void pa__done(pa_module*m) {
         pa_hook_slot_free(u->sink_new_hook_slot);
     if (u->source_new_hook_slot)
         pa_hook_slot_free(u->source_new_hook_slot);
+    if (u->sink_port_hook_slot)
+        pa_hook_slot_free(u->sink_port_hook_slot);
+    if (u->source_port_hook_slot)
+        pa_hook_slot_free(u->source_port_hook_slot);
     if (u->sink_put_hook_slot)
         pa_hook_slot_free(u->sink_put_hook_slot);
 
-- 
1.7.6



More information about the pulseaudio-discuss mailing list