Shairport is back

Three years back when I tried to find concurrent open-source solutions to Apple's Airport Express system to listen to audio remotely, the offer was pretty limited. Apart from shairport and some other incomplete repos, there was nothing really.

shairport was kind of working, but not with all versions of iOS or macOS, and it was quite complicated to install on an embedded systems. You would need to tinker with PulseAudio and Avahi, and it was not always a great success.

At some point I made it work on a Pi but it was one of the first generation of Pis, that had problems with audio and USB ports (so my audio DAC would deliver a very very noisy output) — the result was working but far from perfect and not really what I needed.

I abandoned the project.

Now that I find myself looking at remote audio solutions again, I had a look to see if shairport had been updated. No chance, https://github.com/abrasive/shairport is not maintained anymore, and doesn't list any efficient alternative...

But one of the fork caught my attention : shairport-sync by Mike Brady.

It's a fork that has much more capabilities and is very robust. It does allow for multi-room too, which is nice. Overall, it installs in a breeze and just works right out of the box.

It outputs metadata to a pipe too, which is quite convenient.

When testing it, the latency is virtually non-existent (apart from the usual 2-secs lag to synchronize audio between rooms, which is part of the protocole anyway), the audio is clear and the CPU usage very low. The system is very resilient when you change source, pause, unpause, change source again, etc ...

So I decided to create a small visual metadata reader so I can see what song is being played right now on my simili-Airplay device.

Technology-wise, I settled on a simple C++ application and the Qt framework. Not a very obvious choice (I could have gone with node and a web page for instance) but I liked the idea of having a full-screen standalone application that could run practically anywhere. And it was a great opportunity to learn a bit more what Qt is and how the API works.

Luckily enough I had some Pi 3 and a 3.2" screen to use for this project, I'll break down the software and (very easy) hardware below.

Hardware

I used a Raspberry Pi B 3 and 4DPi-32 Primary display from 4D Systems :

It's quite an 'old' display and it's not fully compatible with the touch events on the RPi3 with Jessie, but it can display stuff, and I had one laying around so I decided to go with that nevertheless.

The audio output of the Raspberry is of really bad quality, so I found a cheap (~$20) Aureon DUAL USB from Terratec :

It's a bit cumbersome but it does the job, and the audio quality is really nice (for this price, of course).

Prepare the SD card

I start off with a standard Raspbian image that you can download form the Raspberry Pi website : https://www.raspberrypi.org/downloads/raspbian/

I use the Raspbian Jessie with PIXEL, and not the LITE version, since it's a pain to reinstall all the packages to make X work correctly.

To burn a sd card directly on your Mac for instance:

sudo dd if=~/Downloads/2016-09-23-raspbian-jessie.img of=/dev/rdiskX

Where rdiskX is the actual disk number of your sd card (use diskutil list).

Boot up the Pi

NB : If you have the same screen as I do, do not sudo apt-get upgrade! As soon as I did that, the screen stopped working, so I guess the latest kernel is not compatible ...

Next, disable the Serial interface and Enable SPI in raspi-config :

Install the 4DPi screen driver :

Download the latest driver for the screen :

wget http://www.4dsystems.com.au/downloads/4DPi/All/4d-hats_4-4-21_v1.0.tar.gz

NB : This might change depending on the screen you use

Then

sudo tar -xzvf 4d-hats_4-4-21_v1.0.tar.gz -C /

And finally, edit sudo nano /boot/config.txt and uncomment the following line:

dtoverlay=4dpi-32

Screen configuration

You might want to stop the screen from sleeping :

sudo nano /etc/lightdm/lightdm.conf

Add the following lines to the [SeatDefaults] section:

# don't sleep the screen
xserver-command=X -s 0 dpms

If you want to change the display orientation, simply edit the /boot/cmdline.txt file and add this line at the end:

4dpi.rotate = 0
// And change this to have the value of 0, 90, 180 or 270.

Install the required packages for shairport-sync

sudo apt-get update
sudo apt-get install build-essential git autoconf automake libtool libdaemon-dev libasound2-dev libpopt-dev libconfig-dev avahi-daemon libavahi-client-dev libssl-dev

Clone the source :

git clone https://github.com/mikebrady/shairport-sync.git
cd shairport-sync
autoreconf -i -f

Configure and make :

 ./configure --sysconfdir=/etc --with-alsa --with-avahi --with-ssl=openssl --with-metadata --with-systemd
make

Ensure the group exists :

getent group shairport-sync &>/dev/null || sudo groupadd -r shairport-sync >/dev/null
getent passwd shairport-sync &> /dev/null || sudo useradd -r -M -g shairport-sync -s /usr/bin/nologin -G audio shairport-sync >/dev/null

And finally install and start at boot :

sudo make install
sudo systemctl enable shairport-sync

You have to configure shairport to emit metadatas in /etc/shairport-sync.conf :

metadata =
{
        enabled = "yes";
        include_cover_art = "yes";
}

Install the UI (at last !)

Clone the repo:

git clone https://github.com/tchapi/shairport-sync-ui

To compile on the Pi, you need the QT tools :

sudo apt-get install qt4-default

You can then use the compile script (basically a qmake && make combo) :

./compile.sh && ./run-gui.sh

The UI in itself is pretty straightforward :

It shows the actual song name, artist and album, along with the cover image if any.

Autostart

If you want the UI to autstart with the Pi :

sudo nano ~/.config/lxsession/LXDE-pi/autostart

Add (before @screensaver) :

@/home/pi/shairport-sync-ui/build/release/shairport-sync-ui 

Casing

As usual, a bit of CATIA and we have a nice box that is not Apple-design grade but that does the job.

Printing in progress (prototype color) :

I use 4 M2 nuts that I melt in the printed plastic with an iron to have a flush backpanel :

The cover is held in place not very tightly with two or three points of glue on the rim — this is the easiest I found, since the device is not going to move. The headers of the screen help it keep in place, too.

Here is the final device in its environment :


Attached to it is the Aureon Dual USB DAC, and the power, on the top


And so it works perfectly !

I also had the opportunity to test shairport-sync with other third-party applications that provide AirPlay-like functionnality, like AirAudio for Android, and it does work and the metadata are here too.

If you have an unused Raspberry at home and a screen, that's a neat little project to do !