[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