[HowTo] Connect 3 bluetooth headsets to OSMC Rpi mediacenter

It is explained how to connect simultaneously three Bluetooth headsets to the OSMC on raspberry Pi 3 mediacenter. I will explain what have I tried, what were the problem, and how I solved it. Maybe it is not the simplest method, but the only one how I managed it. (btw: It’s my firs tutorial so be forgiving :wink:

My hardwere:

  • 3x JBL 300 Kids Bluetooth headsets
  • 3x bluetooth 4.0 USB dongles (I believe manufacturer is not important, because, as I noticed, there are only two chipsets on market - CSR and Broadcomm). I have 2x Ugreen and 1x noname
  • USB passive hub - not necessary due to 4 USB on raspberry pi (I have some other thongs connected). * Some USB cables - It is good to separate USB dongles with some space to prevent interferation (I placed them behind TV, so there is ca.50cm distance between them.

It is very probably You get Bluetooth dongles with the same MAC addresses (due to same chipset). I found script to change addresses:
Change your bluetooth device mac-address - petrilopia.net
It is still working, and as I noticed on CSR chipsets it is permanently. I did not investigate topic, but I had no problems after reboots. I changed them to 11:11:11:11:11:11, 22:22:22:22:22:22, 33:33:33:33:33:33 to easy distinguish them

Version 1: With BlueAlsa
First I tried to achieve it with BlueAlsa.
I tripled BlueAlsa and Bluealsa-aplay services. Than made appropriate changes in d-bus. I also written rc-local script to create dynamic bluealsa.conf (It is possible that each restart hci order changes, so You have to assign MAC addresses to hci devices). It was very hard to get it work, and I get following problems:

  • very long and complicated asound.rc config file, where devices are sometimes not seen by Kodi (It was very frustrating because I found it almost random - have no further clue)
  • the BT devices are used as one multichannel device, so when one of the has poor connection (child goes out of room) others starts to choppy.

Version 2: …and than I apologized Pulseaudio

Step 1: Install Pulseaudio
it was not so easy as it supposed to be. There is something wrong with 2020.10-1 OSMC version and stack Pulseaudio. The Pulseaudio not see soundcard properly - it sees mono (?). I have found no simple solution so I build it from source. There is a lat of tutorials how to do that, so I believe One can find some. The important things are the configs:

  • You have to run Pulseaudio as root (system wide service)
    My Pulseaudio.service:

[Unit]
Description=PulseAudio system server

[Service]
ExecStart=/usr/bin/pulseaudio --system --disallow-exit --log-target=journal
ExecReload=/bin/kill -HUP $MAINPID

[Install]
WantedBy=multi-user.target

Add two lines to system.pa

load-module module-combine-sink sink_name=combined
set-default-sink combined

I believe changes in daemon.conf are not necessary because the are overridden by ExecStart command parameters
You have to create “pulse” user and group "pulse"and group “pulse-access”. Add root and osmc to “pulse-access” group.

Reload systemd daemon or restart system.

Step 2: Allow root to manage BT devices:

My etc/bus-1/system.d/pulseaudio-system.conf

<busconfig>

  <!-- System-wide PulseAudio runs as 'pulse' user. This fragment is
       not necessary for user PulseAudio instances. -->

  <policy user="pulse">
    <allow own="org.pulseaudio.Server"/>
                <allow send_destination="org.bluez"/>
                <allow send_interface="org.bluez.Manager"/>
  </policy>
    <policy user="root">
	<allow own="org.pulseaudio.Server"/>
                <allow send_destination="org.bluez"/>
                <allow send_interface="org.bluez.Manager"/>
    </policy>
    <policy context="default">
                <deny own="org.pulseaudio.Server"/>
                <deny send_destination="org.bluez"/>
                <deny send_interface="org.bluez.Manager"/>
    </policy>

</busconfig>

Step 3: Pair devices
There should be no problems with pairing devices with bluetoothctl command. Remember to run it as root. Sometimes, after reboot, some hci devices are off, so I added lines to rc.local:

hciconfig hci0 up
hciconfig hci1 up
hciconfig hci2 up
hciconfig hci3 up

Step 4: ALSA suport for Pulseaudio
Create /etc/asound.conf

pcm.pulse {
type pulse
hint {
show on
description “Pulseaudio”
}
}

ctl.pulse {
type pulse
}

and check If KODI sees Pulseaudio sound output

Step 5: Audio profiles
Depending on Your sound configuration You may need some changes in it after headsets are connected. I achieve it via Audioprofiles addon. I created two profiles:

  • HDMI - normal output via HDMI -> amplitumer, with pass-trough
  • PulseAudio - output to Pulseaudio (remember to turn off audio pass-trough)

Step 6: Script to execute while BT headsets are connected
create udev rules:
It is very different and depends of headset You are using. I my case I decided to create common rule for any BT device connected, but You can use MAC address of each headphones.
50-my_bluetooth_rule.rules:

ACTION==“add” , SUBSYSTEM==“bluetooth”, RUN+="/home/osmc/pasink_BT.bash on"
RUN+="/home/osmc/pasink_BT.bash"
ACTION==“remove” , SUBSYSTEM==“bluetooth”, RUN+="/home/osmc/pasink_BT.bash off"

the script in home folder pasink_BT.bash:

#!/bin/bash

sleep 3 # is needed to get some time for creation do PA sink for connected device

sink1=$(pactl list sinks short | awk ‘{print $2}’ | grep blue | awk ‘NR==1’)
sink2=$(pactl list sinks short | awk ‘{print $2}’ | grep blue | awk ‘NR==2’)
sink3=$(pactl list sinks short | awk ‘{print $2}’ | grep blue | awk ‘NR==3’)
status="$1"

if [ -n “$sink1” -a -z “$sink2” -a -z “$sink3” ]; then
if [ $status = “on” ]; then

curl -X POST -H “Content-Type: application/json” -d ‘{“jsonrpc”:“2.0”,“method”:“Addons.ExecuteAddon”, “params”:{ “wait”: true, “addonid”: “script.audio.profiles” , “params”: [“2”] } , “id”: 1}’ http://osmc:osmc@10.0.0.13:80/jsonrpc http://osmc:osmc@10.0.0.1
curl -X POST -H “Content-Type: application/json” -d ‘{“jsonrpc”:“2.0”,“method”:“GUI.ShowNotification”,“params”:{“title”:"’“Headset BT”’",“message”:"’“Connected - profile Pulseaudio”’", “displaytime”:10000},“id”:1}’ http://osmc:osmc@10.0.0.13:80/jsonrpc
fi
elif [ -z “$sink1” -a -z “$sink2” -a -z “$sink3” ]; then

curl -X POST -H “Content-Type: application/json” -d ‘{“jsonrpc”:“2.0”,“method”:“Addons.ExecuteAddon”, “params”:{ “wait”: true, “addonid”: “script.audio.profiles” , “params”: [“1”] } , “id”: 1}’ http://osmc:osmc@10.0.0.13:80/jsonrpc http://osmc:osmc@10.0.0.1
curl -X POST -H “Content-Type: application/json” -d ‘{“jsonrpc”:“2.0”,“method”:“GUI.ShowNotification”,“params”:{“title”:"’“Headset BT”’",“message”:"’“All disconnested - profile HDMI”’", “displaytime”:10000},“id”:1}’ http://osmc:osmc@10.0.0.13:80/jsonrpc

fi

Script sends commands do KODI via JSON so You have to enable web access. It changes audioprofiles via audioprofile addon and shows notification when first headset are connected or when all of them is disconnected. You have to change login and IP data according to Your network settings. Rest is done by Pulseaudio. After each headset is connected the new sink is created. The audio is propagated to all active sinks via “module-combine-sink”

Problems
I’m using this solution for about one moth and noticed almost no problems. It is quite stable (but I fear of any OSMC update). It is not secure for sure: root - pulseaudio, root - bluetooth ;-). As far I use it only in my local network I,m ok with it. But be careful when Your machine is exposed somewhere.
Audio quality is very good as headphones uses a2dp. I have not tried with aptX - no such need for me.

  • The problem is when the headphones does not want to autoconnect (I happens sometime when battery is low or something else). Than I have to login via ssh and connect them manually by “bluetoothctl”. I would like to do it by one keypress on my remote (some script - for example “Connect BT”). The problem I found it that bluetoothctl has it own shell so there is no one command for connect. I even tried “expect” script, but I found it very unreliable. Any help appreciated.
  • The second thing are the loud short “crack” noise during menu walking or changing audio profiles. I think the problem is between KODI and Pulseaudio (not BT), or my amplituner. It is related to “silent noise” for keeping amplituner “on”. Turning it off solves problem completely (but my amplitunes shows every time KODI makes “bing” it found new audio stream ;-/ - so I have to turn off interface sounds)
1 Like

I’m glad you got it going! And thanks for the pointers as we move forward with our BT audio implementation.

As you know, we are not keen on Pulseaudio but it’s nice to know it can work for these special situations. Did you still have to mess with d-bus for the Pulseaudio solution, or did it ‘just work’?

I edited the main post to complete tutorial.

Yes - You have to mess with d-bus to allow root use BT (at least I understand it so ;-D)

OK. Not for the feint-hearted, then! But thanks for sharing.

Hmm, the only reason to run Pulseaudio in system wide mode is KODI (mediacenter service) itself. I do not understand it user construction. Mediacenter tries to connect to pulseaudio server as root, not osmc user.
Even the pulseaudio is started by osmc user (and therefore accessible by it), mediacenter can not access it.
If kodi could connect to pulseaudio as osmc user, everything would be simplest and no changes in d-bus would be necessary.