[pulseaudio-discuss] [PATCH v2] sink/source: Initialize port before fixate hook (fixes volume/mute not saved)

David Henningsson david.henningsson at canonical.com
Tue Mar 25 00:05:25 PDT 2014


In case a port has not yet been saved, which is e g often the case
if a sink/source has only one port, reading volume/mute will be done
without port, whereas writing volume/mute will be done with port.

Work around this by setting a default port before the fixate hook,
so module-device-restore can read volume/mute for the correct port.

BugLink: https://bugs.launchpad.net/bugs/1289515
Signed-off-by: David Henningsson <david.henningsson at canonical.com>
---
 src/pulsecore/device-port.c |   27 +++++++++++++++++++++++++++
 src/pulsecore/device-port.h |    2 ++
 src/pulsecore/sink.c        |   27 ++++++++++-----------------
 src/pulsecore/source.c      |   28 ++++++++++------------------
 4 files changed, 49 insertions(+), 35 deletions(-)

diff --git a/src/pulsecore/device-port.c b/src/pulsecore/device-port.c
index 0b65d5c..8cfb117 100644
--- a/src/pulsecore/device-port.c
+++ b/src/pulsecore/device-port.c
@@ -176,3 +176,30 @@ void pa_device_port_set_latency_offset(pa_device_port *p, int64_t offset) {
     pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_CARD|PA_SUBSCRIPTION_EVENT_CHANGE, p->card->index);
     pa_hook_fire(&core->hooks[PA_CORE_HOOK_PORT_LATENCY_OFFSET_CHANGED], p);
 }
+
+pa_device_port *pa_device_port_find_best(pa_hashmap *ports)
+{
+    void *state;
+    pa_device_port *p, *best = NULL;
+
+    if (!ports)
+        return NULL;
+
+    /* First run: skip unavailable ports */
+    PA_HASHMAP_FOREACH(p, ports, state) {
+        if (p->available == PA_AVAILABLE_NO)
+            continue;
+
+        if (!best || p->priority > best->priority)
+            best = p;
+    }
+
+    /* Second run: if only unavailable ports exist, still suggest a port */
+    if (!best) {
+        PA_HASHMAP_FOREACH(p, ports, state)
+            if (!best || p->priority > best->priority)
+                best = p;
+    }
+
+    return best;
+}
diff --git a/src/pulsecore/device-port.h b/src/pulsecore/device-port.h
index b10d554..ef700ac 100644
--- a/src/pulsecore/device-port.h
+++ b/src/pulsecore/device-port.h
@@ -83,4 +83,6 @@ void pa_device_port_set_available(pa_device_port *p, pa_available_t available);
 
 void pa_device_port_set_latency_offset(pa_device_port *p, int64_t offset);
 
+pa_device_port *pa_device_port_find_best(pa_hashmap *ports);
+
 #endif
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 08143e9..872d447 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -235,6 +235,12 @@ pa_sink* pa_sink_new(
     pa_device_init_icon(data->proplist, true);
     pa_device_init_intended_roles(data->proplist);
 
+    if (!data->active_port) {
+        pa_device_port *p = pa_device_port_find_best(data->ports);
+        if (p)
+            pa_sink_new_data_set_port(data, p->name);
+    }
+
     if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_FIXATE], data) < 0) {
         pa_xfree(s);
         pa_namereg_unregister(core, name);
@@ -300,23 +306,10 @@ pa_sink* pa_sink_new(
         if ((s->active_port = pa_hashmap_get(s->ports, data->active_port)))
             s->save_port = data->save_port;
 
-    if (!s->active_port) {
-        void *state;
-        pa_device_port *p;
-
-        PA_HASHMAP_FOREACH(p, s->ports, state) {
-            if (p->available == PA_AVAILABLE_NO)
-                continue;
-
-            if (!s->active_port || p->priority > s->active_port->priority)
-                s->active_port = p;
-        }
-        if (!s->active_port) {
-            PA_HASHMAP_FOREACH(p, s->ports, state)
-                if (!s->active_port || p->priority > s->active_port->priority)
-                    s->active_port = p;
-        }
-    }
+    /* Hopefully the active port has already been assigned in the previous call
+       to pa_device_port_find_best, but better safe than sorry */
+    if (!s->active_port)
+        s->active_port = pa_device_port_find_best(s->ports);
 
     if (s->active_port)
         s->latency_offset = s->active_port->latency_offset;
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index 2a600e2..a592506 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -222,6 +222,12 @@ pa_source* pa_source_new(
     pa_device_init_icon(data->proplist, false);
     pa_device_init_intended_roles(data->proplist);
 
+    if (!data->active_port) {
+        pa_device_port *p = pa_device_port_find_best(data->ports);
+        if (p)
+            pa_source_new_data_set_port(data, p->name);
+    }
+
     if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SOURCE_FIXATE], data) < 0) {
         pa_xfree(s);
         pa_namereg_unregister(core, name);
@@ -288,24 +294,10 @@ pa_source* pa_source_new(
         if ((s->active_port = pa_hashmap_get(s->ports, data->active_port)))
             s->save_port = data->save_port;
 
-    if (!s->active_port) {
-        void *state;
-        pa_device_port *p;
-
-        PA_HASHMAP_FOREACH(p, s->ports, state) {
-            if (p->available == PA_AVAILABLE_NO)
-                continue;
-
-            if (!s->active_port || p->priority > s->active_port->priority)
-                s->active_port = p;
-        }
-
-        if (!s->active_port) {
-            PA_HASHMAP_FOREACH(p, s->ports, state)
-                if (!s->active_port || p->priority > s->active_port->priority)
-                    s->active_port = p;
-        }
-    }
+    /* Hopefully the active port has already been assigned in the previous call
+       to pa_device_port_find_best, but better safe than sorry */
+    if (!s->active_port)
+        s->active_port = pa_device_port_find_best(s->ports);
 
     if (s->active_port)
         s->latency_offset = s->active_port->latency_offset;
-- 
1.7.9.5



More information about the pulseaudio-discuss mailing list