Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
A2DP Sink on Ubuntu Linux with bluez (streaming bluetooth stereo audio from smartphone to pc)

Howto Enable and Use A2DP Sink on Ubuntu Linux with Bluez

  1. Add Enable=Source to /etc/bluetooth/audio.conf right after [General].

  2. Find address in form XX:XX:XX:XX:XX:XX of phone with hcitool scan.

  3. Pair and trust smartphone with sudo bluez-simple-agent hci0 XX:XX:XX:XX:XX:XX and sudo bluez-test-device trusted XX:XX:XX:XX:XX:XX yes.

  4. Create loopback in pulseaudio connection bluetooth a2dp source with alsa sink:

pactl load-module module-loopback \
source=bluez_source.XX_XX_XX_XX_XX_XX \
sink=alsa_output.pci-0000_00_1b.0.analog-stereo

You can find your own values for source and sink with pacmd list-sources and pacmd list-sinks.

@Marneus68

This comment has been minimized.

Copy link

Marneus68 commented Jan 29, 2013

Thank you a lot for this little Gist. It worked immediatly on my Ubuntu 12.04 setup at work ! All the other tutorials and documentations on the subject failed on my machine.

@domenpk

This comment has been minimized.

Copy link

domenpk commented Mar 21, 2013

To automatically do #4, when device is connected, I have this script running (before connecting, it needs to receive the event).

#!/usr/bin/python

# based on monitor-bluetooth
# Changes by Domen Puncer <domen@cba.si>

import gobject
import dbus
import dbus.mainloop.glib
import os


# we want this event: {AudioSource.PropertyChanged} [/org/bluez/16797/hci0/dev_00_24_7E_51_F7_52] State = playing
# and when that happens: pactl load-module module-loopback source=bluez_source.00_24_7E_51_F7_52 sink=alsa_output.pci-0000_00_1b.0.analog-stereo
def property_changed(name, value, path, interface):
    iface = interface[interface.rfind(".") + 1:]
    val = str(value)
    print "{%s.PropertyChanged} [%s] %s = %s" % (iface, path, name, val)
    if iface == "AudioSource" and name == "State" and val == "playing":
        bt_addr = "_".join(path.split('/')[-1].split('_')[1:])
        cmd = "pactl load-module module-loopback source=bluez_source.%s sink=alsa_output.pci-0000_00_1b.0.analog-stereo" % bt_addr
        os.system(cmd)


def object_signal(value, path, interface, member):
    iface = interface[interface.rfind(".") + 1:]
    val = str(value)
    print "{%s.%s} [%s] Path = %s" % (iface, member, path, val)

if __name__ == '__main__':
    dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)

    bus = dbus.SystemBus()

    bus.add_signal_receiver(property_changed, bus_name="org.bluez", signal_name = "PropertyChanged", path_keyword="path", interface_keyword="interface")

    mainloop = gobject.MainLoop()
    mainloop.run()
@Toasty27

This comment has been minimized.

Copy link

Toasty27 commented Jan 13, 2014

@domenpuncer I've modified your python script to remove the loopback module when the device disconnects. If the module is kept loaded, it can cause some nasty feedback.

Gist is here: https://gist.github.com/Toasty27/8406352

Unfortunately I'm not very familiar with python, or dbus's python interface, so my solution is a bit of a hack. It just checks for a dbus message which consistently pops up when the device connects, and runs a shell command that removes all loopback modules for that device. Kind of ugly, but it seems to work reliably for me.

@Toasty27

This comment has been minimized.

Copy link

Toasty27 commented Feb 3, 2014

I updated the script with a fix for the issue where multiple loopback modules would get loaded with successive pausing/playing of an audio stream.

@H7O

This comment has been minimized.

Copy link

H7O commented Apr 18, 2014

Is it possible to change the code in a way that will allow streaming audio from iPhone to Linux?

When I ran this code on Ubuntu 14.04, and connected an iPhone via bluetooth to the Ubuntu box, I got the following two lines:
{HandsfreeGateway.PropertyChanged} [/org/bluez/27095/hci0/dev_00_34_5E_22_F5_61] State = connecting
{HandsfreeGateway.PropertyChanged} [/org/bluez/27095/hci0/dev_00_34_5E_22_F5_61] State = disconnected

@boulund

This comment has been minimized.

Copy link

boulund commented Oct 12, 2014

Thanks so mcuh for this script and thanks domenpuncer and Toasty27 for your improvements!
I wrote my own little Gist (https://gist.github.com/boulund/8949499e17493e1c00db) explaining all the steps I had to take to get it working on my Debian server (mainly for my own memory, should I ever need to redo it).

@murwiz

This comment has been minimized.

Copy link

murwiz commented Nov 10, 2014

When I tried this, I found the following two sinks:

$ pacmd list-sinks | grep name:
name: <alsa_output.pci-0000_01_00.1.hdmi-stereo>
name: <alsa_output.pci-0000_00_1b.0.iec958-stereo>

However, both failed the same way:

$ pactl load-module module-loopback source=bluez_source.7C:6D:62:6B:85:68 sink=alsa_output.pci-0000_01_00.1.hdmi-stereo
Failure: Module initialization failed

What am I missing?

@progmars

This comment has been minimized.

Copy link

progmars commented Mar 20, 2016

How would I pair automatically? Example - I want to run the system on a HTPC device, so it should pretend to be A2DP headphones and start playback from any phone which asks for connection.

@csvan

This comment has been minimized.

Copy link

csvan commented Dec 6, 2016

I get Failure: Module initialization failed when running this on 16.10 unfortunately.

@fregmented

This comment has been minimized.

Copy link

fregmented commented Dec 13, 2016

@csvan check your pactl list. alsa module name is changed.
In my case, I using sink=alsa_output.pci-0000_00_1f.4.analog-stereo.

pactl list | grep Name:
...
Name: alsa_output.pci-0000_00_1f.4.analog-stereo
...
@abstatic

This comment has been minimized.

Copy link

abstatic commented Dec 14, 2017

Worked like a charm on my arch i3 box!! Thanks a lot for this!

@axe312ger

This comment has been minimized.

Copy link

axe312ger commented Dec 30, 2017

Thanks a lot, also working on my zotac zbox with kaby lake processor and ubuntu 16.04 LTS :)

@aracrypto

This comment has been minimized.

Copy link

aracrypto commented Feb 16, 2018

It did not work with me on raspberry pi

@sonvirgo

This comment has been minimized.

Copy link

sonvirgo commented Feb 27, 2018

If this is for Streaming Audio from Ubuntu -> pulse -> bluetooth -> Phone?
Then it not work on Ubuntu 17.04:
pactl load-module module-loopback source=bluez_source.10_2F_6B_6E_14_06 sink=alsa_output.pci-0000_00_1f.3.analog-stereo
Failure: Module initialization failed

@ShonkyCH

This comment has been minimized.

Copy link

ShonkyCH commented Mar 12, 2018

What does " pacmd list-sources | grep name: " produce?

Does your bluez source have .a2dp_source on the end of the name? I think there's a typo in the original post although things may have changed since then. My machine gives:

test@test:~$ pacmd list-sources | grep name:
        name: <alsa_output.pci-0000_00_05.0.analog-stereo.monitor>
        name: <alsa_input.pci-0000_00_05.0.analog-stereo>
        name: <bluez_source.94_7B_E7_XX_XX_XX.a2dp_source>

So I need

pactl load-module module-loopback source=bluez_source.94_7B_E7_XX_XX_XX.a2dp_source sink=alsa_output.pci-0000_00_05.0.analog-stereo

I'm not getting output but at least the loopback loads without error.

Edit: This worked for me:
https://gist.github.com/oleq/24e09112b07464acbda1#gistcomment-2175574

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.