[PATCH] bluetooth: Let PulseAudio always handle the transition to SINK_STATE_PLAYING.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Some A2DP audio devices initiate audio sink state transitions over the
Audio/Video Remote Control (AVRCP) profile. Specifically, trying to
switch the A2DP sink into PLAYING state is problematic, because the
Bluetooth device has no way of knowing when streaming is ready to start
on the host side. If it is detected that the A2DP audio sink has already
been set to PLAYING state by Bluez when PulseAudio is starting to
transition the sink from IDLE to PLAYING, the transport will be released
and re-acquired (in effect, making PulseAudio the initiator again.)
This prevents audio loss at least with Jabra SP700.
---
 src/modules/bluetooth/module-bluetooth-device.c |   27 +++++++++++++++++++++-
 1 files changed, 25 insertions(+), 2 deletions(-)

diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index b7945ed..e86c745 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -2356,7 +2356,30 @@ static int bt_transport_config(struct userdata *u) {
 }
 
 /* Run from main thread */
-static int bt_transport_open(struct userdata *u) {
+/* This function is only called when a Bluetooth profile is initialized */
+static int bt_transport_initialize(struct userdata *u, const pa_bluetooth_device *device) {
+    pa_assert(u);
+    pa_assert(device);
+
+    /* Some A2DP audio devices initiate audio sink state transitions over the
+     * Audio/Video Remote Control (AVRCP) profile. Specifically, trying to
+     * switch the A2DP sink into PLAYING state is problematic, because the
+     * Bluetooth device has no way of knowing when streaming is ready to start
+     * on the host side. If it is detected that the A2DP audio sink has already
+     * been set to PLAYING state by Bluez when PulseAudio is starting to
+     * transition the sink from IDLE to PLAYING, the transport will be released
+     * and re-acquired (in effect, making PulseAudio the initiator again.)
+     * This prevents audio loss at least with Jabra SP700. */
+    if (u->profile == PROFILE_A2DP && device->audio_sink_state == PA_BT_AUDIO_STATE_PLAYING) {
+        pa_log_debug("The audio sink of device %s is already in PLAYING state. Release and re-acquire transport.",
+                     device->name);
+
+        if (bt_transport_acquire(u, FALSE) < 0)
+            return -1;
+        else
+            bt_transport_release(u);
+    }
+
     if (bt_transport_acquire(u, FALSE) < 0)
         return -1;
 
@@ -2406,7 +2429,7 @@ static int setup_bt(struct userdata *u) {
     t = pa_bluetooth_device_get_transport(d, u->profile);
     if (t) {
         u->transport = pa_xstrdup(t->path);
-        return bt_transport_open(u);
+        return bt_transport_initialize(u, d);
     }
 
     if (get_caps(u, 0) < 0)
-- 
1.7.0.4



[Index of Archives]     [Linux Audio Users]     [AMD Graphics]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux