This article describes how I built an audio server for home use. The system allows me to play MP3 files on any connected speakers. I can control (play, stop, next, prev, modify playlist, control volume) the system wirelessly from my GNU/Linux laptop, a Windows laptop, a Mac laptop and even from my Bluetooth enabled mobile phone running a Bemused client.

Created by Simon Josefsson on 2007-09-25. If you want to comment on this, please go to the blog entry.

Hardware

The hardware I used is not that important. The software is flexible and works with many different combinations of hardware. However, as it helps to make things concrete, here is my setup:

The NSLU2 is connected to my wireless base station, and is thus reachable within my home network.

The wiring may be a bit unpolished, but hey, it works.

Simon's Audio Server

Installing Debian on the NSLU2

I followed the instructions on Martin Michlmayr's Debian on NSLU2 page.

I used a 2GB USB memory stick as the root file system. To minimize file system writes to it, I added the noatime file system parameter to /etc/fstab:

LABEL=bean-root / ext3 defaults,noatime,errors=remount-ro 0 1

Another trick is to avoid having syslog write periodic markers to the syslog file. I modified /etc/default/syslogd to have syslogd start with the -m 0 parameter.

SYSLOGD="-m 0"

A trick to find out which processes is writing to your file system is to run the following:

echo 1 > /proc/sys/vm/block_dump

The kernel will dump file systems operations, and you can look at them by running

dmesg | grep dirtied

I have swap set up on the USB memory stick, and this is by far the biggest reason for write operations. I know it may be a bad idea to swap to a USB memory stick, but they are cheap, and I want to find out if there really is any truth to it.

I was lucky with the sound card, the first one I bought worked fine directly out of the box with GNU/Linux and on the NSLU2. I'm not particulary happy with the physical design of the Zalman USB sound card, since the analog audio connector seems to be of rather poor quality. Hopefully the digital output works better.

Installing Avahi mDNS/DNS-SD server

To simplify integration of the server in my network, I'm using Avahi. This allows me to use bean.local as the server name instead of the raw IP address. (The audio server hostname is bean.)

apt-get install avahi-daemon

It doesn't seem to need any configuration. Neat!

Installing Music Player Daemon

The Music Player Daemon was my first choice as server system. I did look at some others, like XMMS2 and Gmediaserver, but none appeared to have the same amount of cross-platform clients available. I installed it as follows:

apt-get install mpd

MPD is configured via /etc/mpd.conf. MPD uses a database of the MP3 files, and you build it using mpd —create-db. The details are below.

Connecting to remote MP3 archive via NFS

At home my MP3 archive is stored on a bigger server and exported via NFS. I added the following to /etc/fstab:

dopio.local:/mp3  /var/lib/mpd/music/     nfs    defaults,ro     0       0

MPD needs to have a database with the files. To avoid having to trash the USB memory stick, the network, and the NFS server when building the MPD database, I ran mpd —create-db on the NFS server (with the appropriate mount points set up temporarily) and then moved the MPD database into a hidden top-level sub-directory .mpd within the MP3 tree. To make MPD find it, I created a symbolic link on the system:

lrwxrwxrwx 1 root root 20 Sep 25 17:45 /var/lib/mpd/tag_cache -> music/.mpd/tag_cache

I could have modified /etc/mpd.conf as well, but I chose not to.

Connecting to local USB storage MP3 archive

At the summer house my MP3 archive is stored on a portable device (the Jobo Giga Vu Pro Evolution).

To make it mount automatically when I connect the device to the NSLU2, I installed hal:

apt-get install hal

I added a udev rule to invoke mount -a whenever a SCSI device is loaded, saved as /etc/udev/rules.d/z99_mount.rules:

KERNEL=="sd[a-z]*", RUN+="/bin/mount -a"

Then I added the following to /etc/fstab:

/dev/disk/by-label/gigavu   /giga   vfat   defaults,auto,ro        0 0

Finally, set up MPD to use data on the device, create the following symlinks:

lrwxrwxrwx 1 root root 20 Sep 25 17:45 /var/lib/mpd/tag_cache -> music/.mpd/tag_cache
lrwxrwxrwx 1 root root 15 Sep 25 19:34 /var/lib/mpd/music -> /giga/pc/Music/

As before, I store the MPD database on the device itself, in the .mtd sub-directory. Since this is a locally connected device, I run mtd —create-db on the device whenever I add/remove MP3's.

Control the server from GNOME

On my laptop, I use the Gnome Music Player Client. It is fast and works well, and there are Debian packages for it.

apt-get install gmpc

GNOME Music Player Client screenshot

Control the server from Windows

Right now I'm using the Windows port of GMPC, but it is not working very well: it doesn't remember the server settings between invocations. It is not high priority for me, and the problem will hopefully be solved in the future.

Control the server from Mac

Theremin is a Mac OS X MPD client,

Theremin screen shot

Control the server from a Mobile Phone via Bluetooth

This is mostly for nerd points.

Bemused client on Nokia 6233 playlist Bemused client on Nokia 6233 browser

First install Bluetooth on your audio server:

apt-get install bluetooth

Then you need to install the bemused - mpd bridge.

apt-get install mpd python-mpdclient python-bluez unzip
wget http://arton.cunst.net/mpd/pbmpcd-20070813.zip
unzip pbmpcd-20070813.zip
cp pbmpcd/pbmpcd.py /usr/local/bin/pbmpcd

Start the server manually to test that it is working properly:

bean:~# /usr/local/bin/pbmpcd
MPD connected at localhost:6600.
Waiting for connection on RFCOMM channel 1

To be able to discover the device, you must tell the bluetooth stack to be in the discoverable mode:

dbus-send --system --type=method_call --print-reply --dest=org.bluez /org/bluez/hci0 org.bluez.Adapter.SetMode string:discoverable

Simple, huh? Anyway, to check your current status, use:

# dbus-send --system --type=method_call --print-reply --dest=org.bluez /org/bluez/hci0 org.bluez.Adapter.GetMode
method return sender=:1.2 -> dest=:1.6
   string "connectable"

It reverts back to connectable from discoverable after some time.

Install a bemused client on your phone. I'm using the nice client that comes with pbmpcd. There is Java source code available (even under the GPL). You need to install it into your mobile phone somehow. Since I have set up mail on my phone, I find the simplest is the e-mail myself the URL to where the bemused.jad file can be found, and then click on it in the mail reader. Your phone should install it.

To save you the trouble of transfering the Bemused client to a web server, you could use the following URL:

http://josefsson.org/grisslan/bemused/

Click on Bemused.jad to install the client.

Once you have installed the bemused client, start the client and chose your bluetooth card (don't forget to put the card in discoverable mode again). The server should print:

Accepted connection from 00:12:34:56:78:9A
...

You should be able to control the server using the numeric keypad to select play, stop, next, pause, volume, etc.

Control the server from OpenMoko Neo1973

Coming up next…

The End

That's it!

Comments or feedback?.