[pulseaudio-discuss] [RFC v2 4/6] bluetooth: Automatic profile selection

Frédéric Dalleau frederic.dalleau at linux.intel.com
Fri Jan 27 02:08:26 PST 2012


---
 src/modules/bluetooth/module-bluetooth-policy.c |   60 ++++++++++++++++++++++-
 1 files changed, 59 insertions(+), 1 deletions(-)

diff --git a/src/modules/bluetooth/module-bluetooth-policy.c b/src/modules/bluetooth/module-bluetooth-policy.c
index e542d97..77ce387 100644
--- a/src/modules/bluetooth/module-bluetooth-policy.c
+++ b/src/modules/bluetooth/module-bluetooth-policy.c
@@ -33,6 +33,7 @@
 #include <pulsecore/core-util.h>
 
 #include "module-bluetooth-policy-symdef.h"
+#include "bluetooth-util.h"
 
 PA_MODULE_AUTHOR("Frédéric Dalleau");
 PA_MODULE_DESCRIPTION("When a sink/source is added, load module-loopback");
@@ -44,12 +45,15 @@ static const char* const valid_modargs[] = {
 };
 
 struct userdata {
+    pa_core *core;
     pa_hook_slot
         *sink_put_slot,
         *source_put_slot,
         *sink_unlink_slot,
-        *source_unlink_slot;
+        *source_unlink_slot,
+        *discovery_slot;
     pa_hashmap *hashmap;
+    pa_bluetooth_discovery *discovery;
 };
 
 /* When a sink is created, loopback default source (microphone) on it */
@@ -231,22 +235,71 @@ static pa_hook_result_t source_unlink_hook_callback(pa_core *c, pa_source *sourc
     return PA_HOOK_OK;
 }
 
+static pa_hook_result_t update_device_profile(pa_bluetooth_discovery *y, const pa_bluetooth_device *d, struct userdata *u) {
+    char *name, *s;
+    const char *profile;
+    pa_card *c;
+
+    pa_assert(u);
+    pa_assert(d);
+
+    pa_log_debug("%s: audio %d, hfp %d, hfgw %d, a2dp %d, a2dp_source %d", d->name, d->audio_state, d->headset_state, d->hfgw_state, d->audio_sink_state, d->audio_source_state);
+
+    name = pa_sprintf_malloc("bluez_card.%s", d->address);
+
+    for (s = name; *s; s++)
+        if (*s == ':')
+            *s = '_';
+
+    c = pa_namereg_get(u->core, name, PA_NAMEREG_CARD);
+    pa_xfree(name);
+
+    if (!c)
+        return PA_HOOK_OK;
+
+    if (d->hfgw_state > PA_BT_AUDIO_STATE_CONNECTED)
+        profile = "hfgw";
+    else if (d->headset_state > PA_BT_AUDIO_STATE_CONNECTED)
+        profile = "hfp";
+    else if (d->audio_source_state > PA_BT_AUDIO_STATE_CONNECTED)
+        profile = "a2dp_source";
+    else if (d->audio_sink_state > PA_BT_AUDIO_STATE_CONNECTED)
+        profile = "a2dp";
+    else
+        profile = "off";
+
+    if (pa_card_set_profile(c, profile, FALSE))
+        pa_log_debug("Failed to set card %s to profile %s", c->name, profile);
+
+    return PA_HOOK_OK;
+}
+
 int pa__init(pa_module*m) {
     struct userdata *u;
 
     pa_assert(m);
 
     m->userdata = u = pa_xnew0(struct userdata, 1);
+    u->core = m->core;
+
+    if (!(u->discovery = pa_bluetooth_discovery_get(m->core)))
+        goto fail;
 
     /* 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->sink_unlink_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_UNLINK], PA_HOOK_LATE+30, (pa_hook_cb_t) sink_unlink_hook_callback, u);
     u->source_unlink_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK], PA_HOOK_LATE+20, (pa_hook_cb_t) source_unlink_hook_callback, u);
+    u->discovery_slot = pa_hook_connect(pa_bluetooth_discovery_hook(u->discovery), PA_HOOK_NORMAL, (pa_hook_cb_t) update_device_profile, u);
 
     u->hashmap = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
 
     return 0;
+
+fail:
+    pa__done(m);
+
+    return -1;
 }
 
 void pa__done(pa_module*m) {
@@ -257,6 +310,8 @@ void pa__done(pa_module*m) {
     if (!(u = m->userdata))
         return;
 
+    if (u->discovery_slot)
+        pa_hook_slot_free(u->discovery_slot);
     if (u->sink_put_slot)
         pa_hook_slot_free(u->sink_put_slot);
     if (u->source_put_slot)
@@ -276,5 +331,8 @@ void pa__done(pa_module*m) {
         pa_hashmap_free(u->hashmap, NULL, NULL);
     }
 
+    if (u->discovery)
+        pa_bluetooth_discovery_unref(u->discovery);
+
     pa_xfree(u);
 }
-- 
1.7.5.4



More information about the pulseaudio-discuss mailing list