11

I'm new to Linux and new to Bluetooth scripting too. What I have discovered so far is the following:

  1. Bluez is the default BT stack.
  2. BluezTools is a set of utilities you can use to more easily interact with Bluez
  3. DBus is the interface Bluez connects to while interacting directly with the hardware.
  4. PulseAudio is the subsystem responsible for producing audio on the system.

This makes sense. So let's say I have a set of BlueTooth headphones, what I would expect is (all after pairing and trusting), to be able to issue a command that can connect directly to a certain profile on the BT headphones.

The technical path I have in mind would be something like :

  1. Turn headphones on.
  2. Issue a BluezTools command - such as bt-audio -c
  3. Wait for the device to connect to the service I am after
  4. PulseAudio should now pick up a new output device
  5. Issue another command to change the audio from what it was to new output audio (the BT headphones).
  6. Enjoy a seamless listening experience.

This all seems logical, but the actual implementation is not like this, and I am looking for the WHY, so I can better understand the problem and try and fix it.

This is what actually happens:

  1. Turn headphones on.
  2. Issue a BluezTools command - such as bt-audio -c
  3. Wait for the device to connect to the service I am after
  4. PulseAudio should now pick up a new output device
  5. Issue a PulseAudio command to change the audio profile from telephone quality to high fidelity.

Let me expand on this a bit. The bluetooth headset offers 2 quality modes (telephone and high fidelity). Only 1 is really suitable for listening to music.

I would expect that the BT headphones expose each quality mode as a service, is this right? This assumption could be wrong, but I would expect something like

bt-audio -c highFidelityProfile

or

bt-audio -changeProfile highFidelityProfile

Instead it seems that Bluez just handles the RAW connection to the device, and from there you need to issue a : pacmd set-card-profile $INDEX a2dp

This just seems fundamentally wrong. Why is the quality control in the audio subsystem, hence requiring a different implementation for pulse or alsa, or any other sound sub system out there?

What am I missing? Why is it not possible to connect directly to a certain profile using Bluez / BluezTools etc?

2

A bluetooth connection has significant latency compared to simple wired headphones or speakers. What's more, the connection latency can vary, depending on the properties of the bluetooth receiver and maybe even radio signal strength as the user moves around.

The interface between an application and PulseAudio can be as simple as "here's some PCM audio data; play this." But it can also be more complicated; something like "Here's some PCM audio data; play this and tell me every 50 ms how far you've got, so that I can tell you to skip ahead if it looks like you're falling out of lip-synch with the video stream I'm playing. Oh, and you'll need to resample it too, since the data has a sample rate your hardware won't directly support." In the latter case, PulseAudio needs to be able to give the application some feedback from the audio device to correctly determine how far the audio data is actually been played at any given time.

As a result, it makes sense for PulseAudio to be fairly deeply involved in Bluetooth audio processing: the more intervening layers there are, the more possibilities for data to be buffered without maintaining accurate feedback, causing lip-synch to be lost.

In fact, before PulseAudio existed, there used to be an ALSA backend for Bluetooth audio, but it was deprecated. I think the problem was that ALSA's interfaces at that time were designed mainly for traditional sound cards, and dealing with a potentially variable audio latency of Bluetooth was difficult.

PulseAudio's interfaces were designed from the ground up to handle various sound devices and even switching audio streams between them while the stream is playing, so it seems to me it has a pretty advanced concept of audio latency built-in too.

Yes, it could have been implemented in BlueZ rather than as a PulseAudio module; but then, BlueZ would have had to present an audio interface for the applications. And since PulseAudio wants to handle "all" the audio on a system (in order to be able to transfer the audio you've currently playing from speakers to Bluetooth or vice versa on-the-fly), it would have to interface with PulseAudio somehow anyway.

2

I think I have finally found a solution (tested on two Linux Mint systems) though I have no idea why I need to follow these exact steps:

Initial Steps :

  1. Install blueman : sudo apt-get install blueman
  2. Edit Bluetooth file : sudo nano /etc/bluetooth/main.conf and add this line at the end : Disable=Headset

For each run :

  1. Restart bluetooth service : sudo service bluetooth restart
  2. Open Devices from blueman in system tray or type blueman-manager in terminal
  3. Search for your bluetooth audio device
  4. Right-click your device and connect as headset
  5. Go to sound from system settings
  6. Select your device by clicking on it once
  7. Now again go to blueman-manager
  8. Right-click your bluetooth device and set Audio profile to High Fidelity Playback (A2DP Sink)

If you miss any of the steps go to step 1 and try again. Let me know if this works.

Edit : In Linux Mint 19, the default bluetooth manager works perfectly with High Fidelity Playback, no configuration required at all !!

0

While it can vary of your configuration, here are some well tested commands.

You need to set the device as trustable. It can be done via the gui.

sdptool browse will give many details about available protocols and channels on the target device.

It's easier to set a bluetooth a2p audio sink when using simultaneous audio outputs, to setup it, see the tool paprefs.

sudo apt install bluetooth 
sudo apt install bluez bluez-tools
sudo apt install rfkill rfcomm

Start device, it should be hci0 anyway:

sudo hciconfig hci0 up

List remote devices:

sudo rfkill list

List bluetooth networks:

hcitool scan

Browse available protocols:

sdptool browse 43:23:00:02:23:A7

Connect a device:

sudo rfcomm connect hci0 43:23:00:02:23:A7

Send a file:

sudo bt-obex -p 43:23:00:02:23:A7 ~/images/tof.png

Receive a file:

sudo bt-obex -s /

Scan/wait for data on a channel (here channel 19), and write data's on a file called dump, in the home folder:

sudo apt install bluez-hcidump

hcidump -i hci0 -O 19 -w ~/dump

Alternative: sometimes useful for pairing:

sudo apt install bluetoothctl

bluetoothctl
power on
connect 43:23:00:02:23:A7
trust 43:23:00:02:23:A7
info 43:23:00:02:23:A7

[bluetooth]# agent on
[bluetooth]# default-agent
[bluetooth]# discoverable on
[bluetooth]# pairable on
[bluetooth]# scan on
[bluetooth]# pair 43:23:00:02:23:A7
[agent]PIN code: ####
[bluetooth]# trust 43:23:00:02:23:A7
[bluetooth]# connect 43:23:00:02:23:A7
[bluetooth]# info 43:23:00:02:23:A7

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.