[pulseaudio-discuss] [PATCH 06/11] Make module-switch-on-connect listen to port changes

David Henningsson david.henningsson at canonical.com
Tue Aug 30 12:24:59 PDT 2011


Signed-off-by: David Henningsson <david.henningsson at canonical.com>
---
 src/modules/module-switch-on-connect.c |   68 +++++++++++++++++++++++++++++++-
 1 files changed, 67 insertions(+), 1 deletions(-)

diff --git a/src/modules/module-switch-on-connect.c b/src/modules/module-switch-on-connect.c
index 86eadd7..c99d8a3 100644
--- a/src/modules/module-switch-on-connect.c
+++ b/src/modules/module-switch-on-connect.c
@@ -49,7 +49,8 @@ static const char* const valid_modargs[] = {
 struct userdata {
     pa_hook_slot
         *sink_put_slot,
-        *source_put_slot;
+        *source_put_slot,
+        *port_available_slot;
 };
 
 static pa_hook_result_t sink_put_hook_callback(pa_core *c, pa_sink *sink, void* userdata) {
@@ -154,6 +155,68 @@ static pa_hook_result_t source_put_hook_callback(pa_core *c, pa_source *source,
     return PA_HOOK_OK;
 }
 
+static pa_device_port* find_best_port(pa_hashmap *ports) {
+    void *state;
+    pa_device_port* port, *result = NULL;
+    unsigned prio = 0;
+
+    PA_HASHMAP_FOREACH(port, ports, state) {
+        if (result == NULL || (port->available != PA_PORT_AVAILABLE_NO && port->priority > prio)) {
+            result = port;
+            prio = port->priority;
+        }
+    }
+    pa_assert(result != NULL);
+    return result;
+}
+
+static pa_hook_result_t port_available_hook_callback(pa_core *c, pa_device_port *port, void* userdata) {
+    uint32_t state;
+    pa_card* card;
+    pa_sink* sink;
+    pa_source* source;
+    pa_bool_t /* is_active_profile, */ is_active_port;
+
+    pa_log_debug("finding port %s", port->name);
+    PA_IDXSET_FOREACH(card, c->cards, state)
+        if (card->ports && port == pa_hashmap_get(card->ports, port->name))
+            break;
+
+    if (!card) {
+        pa_log_warn("Did not find port %s in array of cards", port->name);
+        return PA_HOOK_OK;
+    }
+
+    PA_IDXSET_FOREACH(source, card->sources, state)
+        if (source->ports && port == pa_hashmap_get(source->ports, port->name))
+            break;
+    PA_IDXSET_FOREACH(sink, card->sinks, state)
+        if (sink->ports && port == pa_hashmap_get(sink->ports, port->name))
+            break;
+
+    /* is_active_profile = port->profiles && card->active_profile &&
+        card->active_profile == pa_hashmap_get(port->profiles, card->active_profile->name); */
+    is_active_port = (sink && sink->active_port == port) || (source && source->active_port == port);
+
+    /* TODO: Switch profiles as well, if necessary */
+
+    if (port->available == PA_PORT_AVAILABLE_YES && !is_active_port) {
+        if (sink)
+            pa_sink_set_port(sink, port->name, FALSE);
+        if (source)
+            pa_source_set_port(source, port->name, FALSE);
+    }
+
+    if (port->available == PA_PORT_AVAILABLE_NO && is_active_port) {
+        if (sink)
+            pa_sink_set_port(sink, find_best_port(sink->ports)->name, FALSE);
+        if (source)
+            pa_source_set_port(source, find_best_port(source->ports)->name, FALSE);
+    }
+
+    return PA_HOOK_OK;
+}
+
 int pa__init(pa_module*m) {
     pa_modargs *ma;
     struct userdata *u;
@@ -170,6 +233,7 @@ int pa__init(pa_module*m) {
     /* A little bit later than module-rescue-streams... */
     u->sink_put_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_PUT], PA_HOOK_LATE+30, (pa_hook_cb_t) sink_put_hook_callback, u);
     u->source_put_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_PUT], PA_HOOK_LATE+20, (pa_hook_cb_t) source_put_hook_callback, u);
+    u->port_available_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_PORT_AVAILABLE_CHANGED], PA_HOOK_LATE+20, (pa_hook_cb_t) port_available_hook_callback, u);
 
     pa_modargs_free(ma);
     return 0;
@@ -183,6 +247,8 @@ void pa__done(pa_module*m) {
     if (!(u = m->userdata))
         return;
 
+    if (u->port_available_slot)
+        pa_hook_slot_free(u->port_available_slot);
     if (u->sink_put_slot)
         pa_hook_slot_free(u->sink_put_slot);
     if (u->source_put_slot)
-- 
1.7.5.4



More information about the pulseaudio-discuss mailing list