bluetoothraspbianbluezspeaker

bluez endpoints not working for an audio source


I am trying to play audio from Raspbian to a bluetooth speaker using A2DP.

From looking at test/simple-endpoint in the bluez source, it appears that running it without arguments should register an endpoint with the A2DP_SOURCE_UUID of 0000110A-0000-1000-8000-00805F9B34FB. However, I don't see any of the endpoint's callback methods being called (SelectConfiguration/SetConfiguration) when using bluetoothctl to connect to a bluetooth speaker. I tried with two different types of bluetooth speakers.

If I instead run simple-endpoint in "sbcsink" mode, and then connect my phone to it, I do see the endpoint's methods called (SelectConfiguration/SetConfiguration). So endpoints appear to be working for the A2DP sink uuid, but not the source one.

I'm able to find a org.bluez.MediaTransport1 corresponding to the bluetooth speaker by iterating through dbus managed objects:

import dbus

bus = dbus.SystemBus()
manager = dbus.Interface(bus.get_object('org.bluez', '/'), 'org.freedesktop.DBus.ObjectManager')
for path, ifaces in manager.GetManagedObjects().items():
    transport = ifaces.get('org.bluez.MediaTransport1')
    if transport is None:
        continue
    transport_obj = dbus.Interface(bus.get_object('org.bluez', path), 'org.bluez.MediaTransport1')
    (fd, read_mtu, write_mtu) = transport_obj.Acquire('w')
    taken_fd = fd.take()
    print(path, fd, taken_fd, read_mtu, write_mtu)

I'm able to write to the transport's file descriptor taken_fd, but I can't control the audio configuration like I think I would if the transport had been acquired via a org.bluez.MediaEndpoint1. Also this seems kinda hacky, I'm not sure this transport is meant for me to access in this way. I would expect to get access to the transport via MediaEndpoint1's SetConfiguration.

I observed this behavior with bluez 5.43 on Rasbian Stretch. I also tried updating to the latest bluez 5.50 and saw the same behavior.

What is the expected way to use bluez as an audio source?


Solution

  • I figured out the problem by running bluetoothd in debug mode, and found that SetConfiguration/SetConfiguration was being called on a previously registered endpoint with a path of /A2DP/SBC/Source/1. Searching online for this path led me to discover that it was associated with bluealsa, which was registering the endpoint on system startup, and then was receiving the media endpoint callbacks instead of my endpoint. After killing bluealsa, my audio source endpoint was then able to receive the media endpoint callbacks as expected.