Introduction: Enhance Raspberry Pi Media Center With Bluetooth A2DP (OSMC)
Having Bluetooth connectivity and enabling Raspberry Pi to behave as A2DP source is nothing new (see a general tutorial on Instructables), but the problem I had thus far was making that work on my media center Pi which was running Raspbmc. As I found out through numerous attempts to make it work, the problem was with Raspbmc suffering a bit too much from "weight loss" it forced upon itself, so the modules that work as expected on Raspbian were failing on Raspbmc:
$ pactl list sources short Assertion 'l' failed at pulsecore/flist.c:168, function pa_flist_pop(). Aborting.Aborted
When I learned that Raspbmc was not going to be developed any longer and that its successor -- OSMC -- will be based on Debian distro that was not butchered to fit on 2 GB SD card, I immediately planned to give that a try :-)
What I found out when I started setting up A2DP on OSMC on my Raspberry Pi 2 is that OSMC is no longer based (as its predecessor was and as Raspbian is) on Debian Wheezy, but that it is based on Debian Jessie. That means bye-bye SysVinit and hello Systemd. And that change of service manager (making all "A2DP on Rasberry Pi" available tutorials obsolete or at least not easily replicable by novice users) is the real reason for this tutorial.
Step 1: Requirements
- Raspberry Pi
- 4GB+ SD card with installed OSMC (Release Candidate or newer)
- Bluetooth v4.0+ USB adapter
- a headphones or speaker system connected to 3.5 mm phones port
- an Internet connection (for package updates)
- either LAN connection for SSH or an USB keyboard
A note regarding the Bluetooth v4.0+ USB adapter:
Even though I've used IOGEAR GBU521, any similar adapter should sufice, but best check the verified/supported hardware list before buying!
Step 2: Log in to a Terminal
Boot the Pi.
1) Variant: Remote terminal (SSH)
If you've a LAN connection to the Pi, the easiest way to go through this tutorial is to use SSH -- they you can copy/paste commands instead of typing them :-)
Find what your Pis IP address is and SSH into it with your favorite telnet client.
2) Variant: Local terminal
In this case, connect your keyboard, go to Power menu in XBMC and choose Exit. XMBC will close in a few seconds, but will restart immediately again. To enter the terminal, make sure you press the ESC key after you've choosen the Exit and while the OSMC screen is still showing. That will stop XBMC from staring again ad you'll have a terminal prompt with login in front of you.
Either way, the default credentials for OSMC are:
Username: osmc
Password: osmc
Step 3: Install the Necessary Packages
To get the state of repositories up-to-date, first execute:
sudo apt-get update
Optional: if you want, you can upgrade the outdated packages with:
sudo apt-get upgrade
Note: OSMC uses its own apt-get repository (http://apt.osmc.tv) for updating the system, which is a welcome change from Raspbmc, so not only does 'upgrade' upgrades the linux distro and installed 3rd party packages, it also upgrades the OSMC (media center and its packages).
After it finishes, execute this to install the necessary packages:
sudo apt-get install alsa-utils bluez bluez-tools pulseaudio-module-bluetooth python-gobject python-gobject-2
Image courtesy of: Keep Calm Network Ltd.
Step 4: Audio Configuration
Enable and load the sound module:
echo 'snd_bcm2835' | sudo tee -a /etc/modules echo 'snd-bcm2835' | sudo tee -a /etc/modules sudo modprobe snd_bcm2835 snd-bcm2835
Add users to pulse audio groups:
sudo usermod -a -G lp osmc
sudo usermod -a -G pulse-access,audio root sudo adduser osmc pulse-access
Heads-up: from this point forward, the tutorial uses GNU nano as terminal text editor, but you can easily use the one you prefer.
Open the configuration file for the PulseAudio daemon:
sudo nano /etc/pulse/daemon.conf
And find (press Ctrl+W, then type 'float') the line that reads:
resample-method = speex-float-1
and change it so:
; resample-method = speex-float-1 resample-method = trivial
Because we'll be running PulseAudio deamon in system mode, loading additional modules will not be possible once the deamon is started, so we need to configure their inclusion in the PulseAudio startup script for system mode:
sudo nano /etc/pulse/system.pa
and add the following lines (which check for existance and enable various modules):
.ifexists module-bluetooth-policy.so load-module module-bluetooth-policy .endif
.ifexists module-bluetooth-discover.so load-module module-bluetooth-discover .endif
.ifexists module-bluez5-device.so load-module module-bluez5-device .endif
.ifexists module-bluez5-discover.so load-module module-bluez5-discover .endif
We also need to create the service starting script:
sudo nano /etc/systemd/system/pulseaudio.service
and edit it like so:
[Unit] Description=Pulse Audio [Service] Type=simple ExecStart=/usr/bin/pulseaudio --system --disallow-exit --disallow-module-loading --disable-shm --daemonize [Install] WantedBy=multi-user.target
Execute these two commands to scan for new/changed units and to restart the PulseAudio service:
sudo systemctl daemon-reload sudo systemctl enable pulseaudio.service sudo systemctl start pulseaudio.service
All that is left to do for audio is to enable output to a prefered connector (0=auto,1=headphones,2=hdmi):
amixer cset numid=3 1
and, as volume will be controlled by the client, to set the volume level on the server side to 100 percent:
amixer set Master 100% pacmd set-sink-volume 0 65535
Step 5: Bluetooth Configuration
To make sure A2DP audio sinks are allowed, open the config file:
sudo nano /etc/bluetooth/audio.conf
and place these three lines under [General] heading:
[General] Enable=Source,Sink,Media,Socket HFP=true Class=0x20041C
Next, open another config file:
sudo nano /etc/bluetooth/main.conf
and place these lines under [General] heading:
[General] Name = osmc Class = 0x20041C
Next, list the BT adapter config:
sudo hciconfig -a
and note the MAC address (in form of XX:XX:XX:XX:XX:XX). You will need to specify it here:
sudo nano /var/lib/bluetooth/XX:XX:XX:XX:XX:XX/settings
where you should paste these lines:
[General] Discoverable=true Alias=osmc Class=0x20041C
Bring up the BT:
connmanctl enable bluetooth sudo hciconfig hci0 up
and in the BT control shell:
bluetoothctl
Then, execute the following commands to enable the agent and start the scan:
agent on default-agent discoverable on scan on
That should display a list of visible BT clients (if not, execute 'devices' command). Next, execute the following to pair/trust your client device(s):
pair XX:XX:XX:XX:XX:XX Request confirmation [agent] Confirm passkey 503116 (yes/no): yes trust XX:XX:XX:XX:XX:XX
Note: repeat the pair & trust commands for each device you want to allow to connect.
With this the Bluetooth part of the configuration is done.
Step 6: Fix for Automatic Audio After Reboot
When the past steps in the tutorial are all done, we can immediately see the effect -- the client and the Pi are connected and the client can stream audio via BT.
Woohoo! That's it!...Or, is it?
The problem comes when the Pi is restarted. Then, until someone is logged into console, PulseAudio will not work.
One solution is to enable auto-login into console.
sudo cp /lib/systemd/system/getty@.service /etc/systemd/system/autologin@.service
Next, we symlink that autologin@.service to the getty service for the tty on which we want to autologin, for example for tty1:
sudo mkdir /etc/systemd/system/getty.target.wants sudo ln -s /etc/systemd/system/autologin@.service /etc/systemd/system/getty.target.wants/getty@tty1.service
Up to now, this is still the same as the usual getty@.service file, but the most important part is to modify the autologin@.service to actually log you in automatically. To do that, you only need to change the ExecStart line to read:
ExecStart=-/sbin/agetty -a osmc %I 38400
That's it. After this you'll briefly see the login prompt when the OSMC boots up, but it will allow PulseAudio to run even without you logged in.
reboot
Step 7: Conclusion and Tips
My main goal was to reuse the always-on devices (media centar Raspberry Pi and Android phones/tablets) to stream online subscription music (namely Google Play Music) without needing to have PC turned on or the client device jacked in.
Naturally, the setup can be used to stream all sorts of audio through Pi. For example, gaming on tablet sounds pretty sweet when played on home stereo :)
Tip:
- What I encountered occasionally on the phone was that sometimes it doesn't automatically reconnect to the Pi and that, when Pi (osmc) is pressed in BT phone settings, it immediately disconnects. The solution for this seems to be to turn BT on the phone off and then back on. After that (BT "reset") the phone again automatically connects to the Pi.
Nota bene:
- I was writing down each step I applied while I was investigating how goal in this tutorial can be achieved, but when I started to verify the tutorial (on a clean OSMC install) some weeks later, the version of the OSMC was incremented and I didn't manage to reproduce it exactly step by step, so if you find some parts are off, feel free to suggest improvements in the comments (and I will hopefully update the tutorial).
Principal source of information: ArchLinux Wiki.
Honorable mention: inspired by a tutorial from dantheman_213.
85 Comments
8 years ago on Introduction
Hello,
I'd like to thank you for this guide. It is really straight forward and it worked great for me.
Now I want to share something I added, which will allow your friends to be able to pair and play music too, without having to configure anything on your PI.
First you have to download the bluez source code and untar it.
Then you have to modify bluez/test/simple-agent file replacing the following section:
nano /usr/src/bluez-5.23/test/simple-agent
def RequestPinCode(self, device):
print("RequestPinCode (%s)" % (device))
set_trusted(device)
return “1234"
Then I created a script to switch to discoverable mode, disable secure simple pairing and finally start this agent.
nano /usr/bin/btscript.sh
#!/bin/sh
result=`ps aux | grep -i "simple-agent" | grep -v "grep" | wc -l`
if [ $result -ge 0 ];
then
sudo hciconfig hci0 piscan
sudo hciconfig hci0 sspmode 0
sudo /usr/bin/python /usr/src/bluez-5.23/test/simple-agent &
else
echo "BT Agent already started"
fi
Finally to start the script on autologon:
chmod +x /usr/bin/btscript.sh
nano /etc/rc.local
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.
/usr/bin/btscript.sh
exit 0
Now just reboot and that’s it! You will be able to pair and play music from any bluetooth devices using the code PIN you defined in your agent (here “1234”).
Source: http://www.linuxquestions.org/questions/linux-wireless-networking-41/setting-up-bluez-with-a-passkey-pin-to-be-used-as-headset-for-iphone-816003/
Reply 7 years ago
Hello, I have tried to do this, but I can't find /usr/src/bluez-5.23/test/simple-agent
Reply 7 years ago
@anmorfe: possibly you skipped this step:
So, something like this should work for you:
wget http://www.kernel.org/pub/linux/bluetooth/bluez-5.35.tar.xz
tar xf bluez-5.35.tar.xz
cd bluez-5.35
Reply 7 years ago
I had somewhat mixed feelings about mixing versions, so preferred to download the sources of the version that was also installed via apt-get:
1. If the line "deb-src ..." starts with a # (is a comment) remove the #. If it's not commented out, continue with 3
2. sudo apt-get update
3. cd /usr/src
4. sudo apt-get source bluez
This was the only missing part of pubbb's addition.
Thank you Robert and pubbb for your description, it's literally the only one out there for jessie-based distros.
Reply 7 years ago
Forgot to mention:
Step 0: Open apt sources file: sudo nano /etc/apt/sources.list
Reply 8 years ago on Introduction
Nice enhancement :)
Thanks!
8 years ago on Introduction
Thank you for sharing this informations. And made it and ... it works!!!
As I use a Hifi Digi+ sound card, I did not make the first 2 parts of step 4, also did not type the command
# amixer cset numid=3 1
# amixer set Master 100%
# pacmd set-sink-volume 0 6553
Also I do not need the 6th step (OSMC RC2).
Thank you again.
Reply 8 years ago on Introduction
Thanks for confirming :)
Much appreciated!
7 years ago
Okay, I've tried my best to blend together both the instructions above and the suggestions below and still cannot get any audio output.
I'm using a R Pi 1 Model B while I wait for a dedicated model 3 to arrive with the OSCM July 1st image. I'm starting to wonder if something has changed in the bluetooth architecture because the folder '/etc/bluetooth' is not there and the file 'main.conf' does not exist either. I went ahead and did a 'mkdir /etc/bluetooth' and created the main.conf file with the contents suggested but that doesn't seem to have fixed the issue.
I've also tried changing the Audio Out settings in OSMC and none of them will produce the bluetooth audio either...
Does anyone have any ideas?
Reply 6 years ago
Hi together,
I have exact the same problem with my Pi 1 Model B.
I use a fresh OSMC installation and I followed the instructions step by step, till I have to add something to the folder /etc/bluethooth. This folder does not exist.
Is this only a problem of Pi 1?
Torsten
6 years ago
Hello Robert,
Thanks for the great instructions. Went through them step by step and everything works! Now.. I'm interested in another addition which I think might be very much welcome by other users as well - have the BT connect event trigger an HDMI CEC message to the connected AVR / TV and get it to turn on...
My existing RPi2 + OSMC does exactly that when turned on (including AVR input change) but when I connect to its BT from a client and stream audio it doesn't..
Any thoughts on how to achieve that?
Thanks again!
O,
Reply 6 years ago
Thanks.
No idea how to do that, but seems it could be interresting for others, too. Maybe when you succeed you can post a followup.
6 years ago
Hi,
I tried to install my bluetooth adapter according to the intstruction but failed.
Now
my oscm installation is not starting anymore. I have still access to
console. hope someone can help me in checking the logs below what is
happening, thus I am not that experienced with unix...
http://paste.osmc.io/baquyicuwi
http://paste.osmc.io/tohacacexe
greets ingo
7 years ago
what FANTASTIC work!
well done, sir.
I hope this gets pulled upstream into OSMC or OpenELEC for native support
7 years ago
I have installed but sound from my bluetooth speaker last only for 10 sec then no sound. My speakers still connected but no sound after 5-10 sec.
How do I get continues sound?
Thanks
7 years ago
I have successfully installed on my OSMC and I can hear the sound from my Bluetooth speaker but it is only for 10 sec and then no sound.
Also, I noticed that when I play You tube video, I can hear the sound with video.
Any idea?
7 years ago
I thought that enabling Raspberry Pi as A2DP source means to send data to be played on an A2DP sink such a bluetooth headset or speakers. But step 1 says I must connect headphones or speakers to the 3.5mm port. What is this tutorial for?
7 years ago
Thank you very much for your guide.
It work great for me, I just need to set pulse audio in OSMC audio parameter instead of HDMI.
Thank you very much one more time.
Bye.
8 years ago on Introduction
Thanks for the tutorial!
For me it worked when reverting from RC3 to RC, but after restarting the device(pi) is not detected as a ad2p speaker but rather a normal Bluetooth device(with no label). When tryign to connect to it the connection would drop after less than a second.
I believe it may be the ad2p configs are not taking effect, but am unsure as I followed the guide exactly.
Reply 7 years ago
Hi, I am having the same problem. It used to work fine for a couple of days, then when the pi rebooted, my bluetooth device is now Class 0x00041C and cannot be connected to anymore.
The file /var/lib/bluetooth/XX:XX:XX:XX:XX/settings seems to get overwritten at boottime where the line Class = 0x20041C gets erased.
I can manually set the device class back to 0x20041C using
"hciconfig hci0 class 0x20041C" but I have to do this after every reboot.
Any suggestion on where to fix this?