[pulseaudio-discuss] [PATCH] profile-switcher: Deal with new Bluetooth cards

Arun Raghavan arun.raghavan at collabora.co.uk
Thu Feb 9 05:43:17 PST 2012


This makes sure that when a new Bluetooth device turns up, we set it to
the appropriate profile depending on the current list of streams.
---
 src/modules/module-profile-switcher.c |   48 ++++++++++++++++++++++++++++++++-
 1 files changed, 47 insertions(+), 1 deletions(-)

diff --git a/src/modules/module-profile-switcher.c b/src/modules/module-profile-switcher.c
index 4607ac6..56bc2c1 100644
--- a/src/modules/module-profile-switcher.c
+++ b/src/modules/module-profile-switcher.c
@@ -32,6 +32,7 @@
 #include <pulsecore/sink.h>
 #include <pulsecore/sink-input.h>
 #include <pulsecore/source-output.h>
+#include <pulsecore/card.h>
 #include <pulsecore/modargs.h>
 #include <pulsecore/log.h>
 
@@ -50,7 +51,8 @@ struct userdata {
     pa_hook_slot
         *sink_input_put_slot,
         *sink_input_unlink_post_slot,
-        *source_output_unlink_post_slot;
+        *source_output_unlink_post_slot,
+        *card_new_slot;
 };
 
 #define GET_ROLE(i) \
@@ -189,6 +191,47 @@ static pa_hook_result_t source_output_unlink_post_cb(pa_core *c, pa_source_outpu
     return PA_HOOK_OK;
 }
 
+/* Set the inital profile for the card based on currently available
+ * sink-inputs and source-outputs. */
+static pa_hook_result_t card_new_cb(pa_core *c, pa_card_new_data *data, void *userdata) {
+    const char *device_api;
+    pa_sink_input *input;
+    pa_source_output *output;
+    pa_bool_t use_a2dp = TRUE;
+    uint32_t idx;
+
+    device_api = pa_proplist_gets(data->proplist, PA_PROP_DEVICE_API);
+    if (!device_api || !pa_streq(device_api, "bluez"))
+        return PA_HOOK_OK;
+
+    PA_IDXSET_FOREACH(input, c->sink_inputs, idx) {
+        if (pa_streq(GET_ROLE(input), "phone")) {
+            use_a2dp = FALSE;
+            goto done;
+        }
+    }
+
+    PA_IDXSET_FOREACH(output, c->source_outputs, idx) {
+        if (pa_streq(GET_ROLE(output), "phone")) {
+            use_a2dp = FALSE;
+            break;
+        }
+    }
+
+done:
+    if (use_a2dp) {
+        pa_log_info("No phone streams, switching card '%s' to A2DP profile", data->name);
+        pa_card_new_data_set_profile(data, "a2dp");
+        data->save_profile = FALSE;
+    } else {
+        pa_log_info("Have a phone stream, switching card '%s' to HSP/HFP profile", data->name);
+        pa_card_new_data_set_profile(data, "hsp");
+        data->save_profile = FALSE;
+    }
+
+    return PA_HOOK_OK;
+}
+
 int pa__init(pa_module*m) {
     pa_modargs *ma;
     struct userdata *u;
@@ -206,6 +249,7 @@ int pa__init(pa_module*m) {
     u->sink_input_put_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_PUT], PA_HOOK_EARLY, (pa_hook_cb_t) sink_input_put_cb, u);
     u->sink_input_unlink_post_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_UNLINK_POST], PA_HOOK_EARLY, (pa_hook_cb_t) sink_input_unlink_post_cb, u);
     u->source_output_unlink_post_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_UNLINK_POST], PA_HOOK_EARLY, (pa_hook_cb_t) source_output_unlink_post_cb, u);
+    u->card_new_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_CARD_NEW], PA_HOOK_EARLY, (pa_hook_cb_t) card_new_cb, u);
 
     pa_modargs_free(ma);
     return 0;
@@ -225,6 +269,8 @@ void pa__done(pa_module*m) {
         pa_hook_slot_free(u->sink_input_unlink_post_slot);
     if (u->source_output_unlink_post_slot)
         pa_hook_slot_free(u->source_output_unlink_post_slot);
+    if (u->card_new_slot)
+        pa_hook_slot_free(u->card_new_slot);
 
     pa_xfree(u);
 }
-- 
1.7.8.4



More information about the pulseaudio-discuss mailing list