Last Updated: 26 Mar 2018
Installing AirPlay on Tomato - 2018 Edition
It's possible to make your Tomato Router run an AirPlay daemon, allowing you to stream music from iTunes, your iOS devices, etc.
Qui Hong wrote an excellent blog post in 2012 about how to do this. A lot has changed since then – most of the packages he used are no longer maintained, but others have forked the originals and are maintaining new versions.
I've built on his work, and written an updated tutorial for 2018.
What you'll need
To get AirPlay working, you'll need a couple things:
- A USB audio device. I used the Turtle Beach Audio Advantage Micro II USB Analog & Digital Audio Adapter, but just about any USB audio adapter should do.
- A USB flash memory stick. It doesn't have to be big; even an old 256MB unit will do.
- A pair of headphones for testing.
Step 1: Install Tomato
If you haven't done so already, you'll need to install Tomato on your router, and configure Tomato for your network. The details of getting Tomato on your router is beyond the scope of this tutorial, but you'll find plenty of links to great tutorials on the Advanced Tomato download page.
Make sure you use the VPN version of Tomato, and NOT the 'All In One' (AIO) version. The VPN version contains some kernel headers that allow a couple of the necessary modules to load; as of this writing the AIO version didn't.
Step 2: Enable USB Support
Make sure USB support is enabled. In the Tomato admin interface, under 'USB & NAS > USB Support', make sure the following are checked:
- Core USB Support
- USB 2.0 Support
- USB 1.1 Support OHCI (I'm not sure why, but this seemed to be required, even though I was using a fairly modern soundcard)
- USB Storage Support
Everything except USB 1.1 support will probably be checked by default; you really only need 1.1 support if you're using an old USB 1.X device, but it doesn't hurt to have it turned on.
Step 3: Format your USB Stick & Install Entware
Now comes the fun part. Login to your router via SSH, and get to a command prompt. You should see something like this (note your IP will probably be different):
MBP:~ dordal$ ssh -l root 192.168.50.1 email@example.com's password: Tomato v1.28.0000 MIPSR2-3.2-137 K26 USB VPN ======================================================== Welcome to the Asus RT-N16 [TomatoUSB] Uptime: 23:43:30 up 1:10 Load average: 0.45, 0.22, 0.18 Mem usage: 13.0% (used 16.13 of 123.94 MB) WAN1: XXX.XXX.XXX.XXX/24 @ AA:AA:AA:AA:AA:AA LAN : XXX.XXX.XXX.XXX/24 @ DHCP: XXX.XXX.XXX.XXX - XXX.XXX.XXX.XXX WL0 : 2,4GHz @ network @ channel: 6 @ AA:AA:AA:AA:AA:AA ======================================================== root@unknown:/tmp/home/root#
Now, create a new partition on your USB stick:
# Create a partition umount /dev/sda1 fdisk /dev/sda
Then type in the following commands:
# p # list current partitions # o # to delete all partitions # n # new partition # p # primary partition # 1 (one) # first partition # <enter> # default start block # <enter> # default end block #use the whole flash drive # w # write new partition to disk
Now format the new partition:
# umount /dev/sda1 incase it was automounted umount /dev/sda1 # format newly created partition # label disk as 'entware' case sensitive mke2fs -j -L entware /dev/sda1 # mount the new disk partition mount /dev/sda1 /opt # Make sure /opt is properly mounted on a reboot. echo "LABEL=entware /opt ext3 defaults 1 1" >> /etc/fstab nvram setfile2nvram /etc/fstab nvram commit
Finally, install entware-ng. Entware is a package repo for embedded devices, and what you'll use to install everything from here on out:
# Install entware-ng cd /opt wget -qO - http://pkg.entware.net/binaries/mipsel/installer/installer.sh | sh
Step 4: Install shairport-sync and other needed software
# install dbus, avahi (aka bonjour), shairport-sync opkg install dbus avahi-daemon avahi-utils shairport-sync-openssl alsa-utils
Next download the extra kernel modules you need.
WARNING WARNING WARNING. Depending on your version of Tomato, the link below may be different. You may not be on build 140, and/or you may not be on a K26 router. Check Shibby's firmware download directory to find the right link.
# download extra kernel modules. cd /tmp # NOTE THE LINK BELOW MAY BE DIFFERENT FOR YOUR ROUTER wget http://tomato.groov.pl/download/K26/build5x-140-MultiWAN/extras-mips2.tar.gz mkdir /opt/extras cd /opt/extras tar xvzf /tmp/extras-mips2.tar.gz # load sound modules. if you get an error on the last three modules, make sure you've # flashed the 'VPN' version of Tomato, not the 'AIO' version. insmod /opt/extras/soundcore insmod /opt/extras/snd insmod /opt/extras/snd-hwdep insmod /opt/extras/snd-page-alloc insmod /opt/extras/snd-timer insmod /opt/extras/snd-pcm insmod /opt/extras/snd-seq-device insmod /opt/extras/snd-seq insmod /opt/extras/snd-rawmidi insmod /opt/extras/snd-seq-midi-event insmod /opt/extras/snd-seq-midi insmod /opt/extras/snd-mixer-oss insmod /opt/extras/snd-pcm-oss insmod /opt/extras/snd-usb-lib insmod /opt/extras/snd-usb-audio insmod /opt/extras/input-core insmod /opt/extras/hid insmod /opt/extras/usbhid
Now you have to pull the config file for shairport-sync, as the package doesn't install it. The new one is on Github.
wget https://raw.githubusercontent.com/mikebrady/shairport-sync/master/scripts/shairport-sync.conf /opt/etc/shairport-sync.conf
NOTE: If you get a 'connection reset by peer' message, you'll have to manually download this file via your browser, and upload it to your router (e.g. by pasting it into vi)
Step 5: Setup Your Soundcard & Test Your Sound
Install the setup script for the sound devices:
mkdir -p /opt/src/alsa cd /opt/src/alsa opkg install bzip2 wget ftp://ftp.alsa-project.org/pub/driver/alsa-driver-1.0.25.tar.bz2 bzip2 -d alsa-driver-1.0.25.tar.bz2 tar xvf alsa-driver-1.0.25.tar
Run that to configure sound devices:
Now init ASLA:
Make sure ALSA sees your USB card:
# aplay -l **** List of PLAYBACK Hardware Devices **** card 0: default [USB Sound Device ], device 0: USB Audio [USB Audio] Subdevices: 1/1 Subdevice #0: subdevice #0
Now test your sound. Plug your headphones in; THIS MAY BE LOUD.
mkdir -p /opt/test cd /opt/test wget http://www.kozco.com/tech/LRMonoPhase4.wav aplay -v LRMonoPhase4.wav
You should hear sound from both channels. If you don't, go back and retrace your steps.
If you do, onward:
Step 6: Startup Shairport
Run through this process to startup shairport-sync, and play audio.
# delete orphan pid files in case they exist. You may get an error if they don't; that's OK. rm /opt/var/run/dbus.pid rm /opt/var/run/avahi-daemon/pid # required to start avahi-daemon echo "nogroup:x:2:" >> /tmp/etc/group echo "nogroup:x:2:2:avahi daemon:/opt/sbin/avahi-daemon:/bin/false" >> /tmp/etc/passwd echo "audio:x:555:" >> /tmp/etc/group # start dbus first before avahi /opt/etc/init.d/S20dbus start # start avahi-daemon avahi-daemon -D # start shairport shairport-sync -v
Woohoo! You should now be able to AirPlay music to your router! Look for an AirPlay device that says something like 'Shairport Sync on unknown', and send your music to it. (To change this name, edit the config file in /opt/etc/shairport-sync.conf )
If it didn't work, look at the output from the shairport-sync command for clues. You can also try running in verbose debug mode with:
Step 7: Make it work on startup
You'll probably want to enable shairport on router startup, so you don't have to manually go start the process each time. To do that, you'll need to copy/paste two scripts into your router. Look in USB & NAS > USB Support > Run after mounting.
Startup Script: Run after mounting:
# initial sleep for tomato to startup. unless I put this in, I get corrupt audio sleep 30s # load sound modules insmod /opt/extras/soundcore insmod /opt/extras/snd insmod /opt/extras/snd-hwdep insmod /opt/extras/snd-page-alloc insmod /opt/extras/snd-timer insmod /opt/extras/snd-pcm insmod /opt/extras/snd-seq-device insmod /opt/extras/snd-seq insmod /opt/extras/snd-rawmidi insmod /opt/extras/snd-seq-midi-event insmod /opt/extras/snd-seq-midi insmod /opt/extras/snd-mixer-oss insmod /opt/extras/snd-pcm-oss insmod /opt/extras/snd-usb-lib insmod /opt/extras/snd-usb-audio insmod /opt/extras/input-core insmod /opt/extras/hid insmod /opt/extras/usbhid # create sound devices /opt/src/alsa/alsa-driver-1.0.25/snddevices alsactl init # delete orphan pid files in case they exist rm /opt/var/run/dbus.pid rm /opt/var/run/avahi-daemon/pid # required to start avahi-daemon echo "nogroup:x:2:" >> /tmp/etc/group echo "nogroup:x:2:2:avahi daemon:/opt/sbin/avahi-daemon:/bin/false" >> /tmp/etc/passwd echo "audio:x:555:" >> /tmp/etc/group # sleep before daemon startup sleep 1s # start dbus first before avahi /opt/etc/init.d/S20dbus start # sleep for 5s so dbus can startup sleep 5s # start avahi-daemon avahi-daemon -D # sleep for 3s so avahi can startup sleep 3s # start shairport as a daemon shairport-sync -d # done
Shutdown script (run after unmounting):
# run before umount killall shairport-sync avahi-daemon -k /opt/etc/init.d/S20dbus stop # done
If you have trouble, here are a couple tips.
Run shairport-sync in debug mode
The first thing to do is login to the router and run shairport-sync manually:
killall shairport-sync shairport-sync -v # (or -vv)
Look for errors, and then go forth and Google. :)
Check if you're broadcasting
avahi-browse allows you to see what you're broadcasting:
Disable WMM in Tomato
If you get error messages like:
Buffers exhausted. Buffers exhausted. Error -- ALSA device in incorrect state (4) for play. Lost sync with source for 4 consecutive packets -- flushing and resyncing. Error: 9368. First packet is late! It should have played before now. Flushing 0.1 seconds Buffers exhausted. Buffers exhausted.
you might try disabling WMM in Tomato. (Advanced Settings → Wireless). WMM stands for Wifi Multimedia, and apparently implements some sort of QoS for multimedia data over wifi. I found it also interfered with shairport-sync; disabling it seemed to fix the problem with no other ill effects.