[pulseaudio-discuss] [PATCH] bluetooth: Add support for automatic switch between hsp and a2dp profiles also for bluez5

Pali Rohár pali.rohar at gmail.com
Sun Sep 11 15:16:38 UTC 2016


Bluez5 uses different profile names as bluez4, so we need to check for
a2dp_sink and headset_head_unit too for bluez5 support.

Signed-off-by: Pali Rohár <pali.rohar at gmail.com>
---

I have not tested this patch yet, but there are people who already wanted
bluez5 support so I'm sending my patch. If there are any problems let me
know and I could try to fix them... Btw, same check for profile names is
already done in code for loading loopback module.

---
 src/modules/bluetooth/module-bluetooth-policy.c |   60 +++++++++++++----------
 1 file changed, 33 insertions(+), 27 deletions(-)

diff --git a/src/modules/bluetooth/module-bluetooth-policy.c b/src/modules/bluetooth/module-bluetooth-policy.c
index 3f085b8..bedf011 100644
--- a/src/modules/bluetooth/module-bluetooth-policy.c
+++ b/src/modules/bluetooth/module-bluetooth-policy.c
@@ -145,23 +145,29 @@ static pa_hook_result_t sink_put_hook_callback(pa_core *c, pa_sink *sink, void *
     return PA_HOOK_OK;
 }
 
-static void card_set_profile(struct userdata *u, pa_card *card, const char *to_profile, bool revert_to_a2dp)
+static void card_set_profile(struct userdata *u, pa_card *card, bool revert_to_a2dp)
 {
     pa_card_profile *profile;
     void *state;
 
-    /* Find available to_profile and activate it */
+    /* Find available profile and activate it */
     PA_HASHMAP_FOREACH(profile, card->profiles, state) {
-        if (!pa_streq(profile->name, to_profile))
-            continue;
-
         if (profile->available == PA_AVAILABLE_NO)
             continue;
 
-        pa_log_debug("Setting card '%s' to profile '%s'", card->name, to_profile);
+        /* Check for correct profile based on revert_to_a2dp */
+        if (revert_to_a2dp) {
+            if (!pa_streq(profile->name, "a2dp") && !pa_streq(profile->name, "a2dp_sink"))
+                continue;
+        } else {
+            if (!pa_streq(profile->name, "hsp") && !pa_streq(profile->name, "headset_head_unit"))
+                continue;
+        }
+
+        pa_log_debug("Setting card '%s' to profile '%s'", card->name, profile->name);
 
         if (pa_card_set_profile(card, profile, false) != 0) {
-            pa_log_warn("Could not set profile '%s'", to_profile);
+            pa_log_warn("Could not set profile '%s'", profile->name);
             continue;
         }
 
@@ -176,18 +182,8 @@ static void card_set_profile(struct userdata *u, pa_card *card, const char *to_p
 /* Switch profile for one card */
 static void switch_profile(pa_card *card, bool revert_to_a2dp, void *userdata) {
     struct userdata *u = userdata;
-    const char *from_profile;
-    const char *to_profile;
     const char *s;
 
-    if (revert_to_a2dp) {
-        from_profile = "hsp";
-        to_profile = "a2dp";
-    } else {
-        from_profile = "a2dp";
-        to_profile = "hsp";
-    }
-
     /* Only consider bluetooth cards */
     s = pa_proplist_gets(card->proplist, PA_PROP_DEVICE_BUS);
     if (!s || !pa_streq(s, "bluetooth"))
@@ -197,17 +193,25 @@ static void switch_profile(pa_card *card, bool revert_to_a2dp, void *userdata) {
         /* In revert_to_a2dp phase only consider cards with will_need_revert flag and remove it */
         if (!pa_hashmap_remove(u->will_need_revert_card_map, card))
             return;
-    }
 
-    /* Skip card if does not have active from_profile */
-    if (!pa_streq(card->active_profile->name, from_profile))
-        return;
+        /* Skip card if does not have active hsp profile */
+        if (!pa_streq(card->active_profile->name, "hsp") && !pa_streq(card->active_profile->name, "headset_head_unit"))
+            return;
 
-    /* Skip card if already has active profile to_profile */
-    if (pa_streq(card->active_profile->name, to_profile))
-        return;
+        /* Skip card if already has active a2dp profile */
+        if (pa_streq(card->active_profile->name, "a2dp") || pa_streq(card->active_profile->name, "a2dp_sink"))
+            return;
+    } else {
+        /* Skip card if does not have active a2dp profile */
+        if (!pa_streq(card->active_profile->name, "a2dp") && !pa_streq(card->active_profile->name, "a2dp_sink"))
+            return;
+
+        /* Skip card if already has active hsp profile */
+        if (pa_streq(card->active_profile->name, "hsp") || pa_streq(card->active_profile->name, "headset_head_unit"))
+            return;
+    }
 
-    card_set_profile(u, card, to_profile, revert_to_a2dp);
+    card_set_profile(u, card, revert_to_a2dp);
 }
 
 /* Return true if we should ignore this source output */
@@ -305,11 +309,13 @@ static pa_hook_result_t card_init_profile_hook_callback(pa_core *c, pa_card *car
         return PA_HOOK_OK;
 
     /* Ignore card if has already set other initial profile than a2dp */
-    if (card->active_profile && !pa_streq(card->active_profile->name, "a2dp"))
+    if (card->active_profile &&
+        !pa_streq(card->active_profile->name, "a2dp") &&
+        !pa_streq(card->active_profile->name, "a2dp_sink"))
         return PA_HOOK_OK;
 
     /* Set initial profile to hsp */
-    card_set_profile(u, card, "hsp", false);
+    card_set_profile(u, card, false);
 
     /* Flag this card for will_need_revert */
     pa_hashmap_put(u->will_need_revert_card_map, card, PA_INT_TO_PTR(1));
-- 
1.7.9.5



More information about the pulseaudio-discuss mailing list