Hosting provided by

The Wireless Music Player

Do-it-yourself remotely managed music player

By Nathan True (musicap@fartysss.co.uk@natjavoFlayingspayneutercontrolpetpopulationetrue.com)

UPDATE: I appeared and presented my wireless music player on Gear Live's Bleeding Edge video podcast show: Check it out! (I'm 17 minutes in)

Prologue

It's a problem many of us are familiar with. We have an extensive music library on our computers and iPods/portable music players, and we would like to listen to it at home, but our computers are too far from the stereo, or the rest of the family wants to listen to music while you go out with your iPod. Or perhaps you'd like to listen to Shoutcast radio stations on your stereo at home (something portable music players are at the moment largely incapable of).

These are all very sensible reasons for wanting a networked music player. Now many companies have products for sale that fill this need, but this page is not about buying things. This page is about hacking a do-it-yourself wireless networked music player for less than half the cost of a retail model, and with (potentially) more features.

The Mission

When I began this project, I knew I could not settle for anything less than:

Leveraging an old PC for the task was out of the question, as I had no spare PCs to toy with, and in general PCs are loud power hogs if you aren't buying specifically for quietude and power economy (and that drives the prices up).

Once again I turn to an old friend of an operating system, OpenWrt, only this time on a new hardware platform, the excellent Netgear WGT634U. Unfortunately Netgear has discontinued this router because of the flaky software they wrote for it (or other business reasons). Luckily this means that refurbished WGT634U units go for about $40 (or they did, until supply ran out just a few days before this article was published). (UPDATE: Justdeals.com seems to get them in and out of stock sometimes) What's so great about these routers is that they have a USB 2.0 port on the back, allowing connection of any number of accessories, the most important of which in this case is the generic USB audio device.

USB audio

I wanted the best audio quality for my dollar. So naturally, I headed over to eBay and found the cheapest USB audio adapter I could find. (As a side comment, don't be afraid of eBay for the cheap sub-$50 stuff. No one scams you for such small amounts of money.) Fortunately USB audio devices are standardized, so pretty much every USB audio device you can get your hands on should work great with the Advanced Linux Sound Architecture (ALSA). The little green one I got ended up having a C-Media chipset, and actually has excellent sound quality. In order to hear the background noise typical of a desktop computer system, I have to set the volume down to 5 (out of 100) and use my in-ear headphones. It might also help that the Netgear router's power supply doesn't have things like clicking hard drives to inject noise into it. I'm quite satisfied with this little green adapter - despite the garish color its sound quality and price ($8) are superb.

The LCD song display

I had wanted to play with LCDs for a while now, but I had never really done in-depth searching for a cheap serial-based LCD module. $40 and up was just too much to pay. But for this project I really wanted to have the music player display its current song and artist information. I remembered that electronics kits are always cheaper than their prebuilt counterparts. So I fired up the good ol' eBay search again (for "serial lcd kit") and lo and behold, a kit from Hong Kong for about $12. If you're afraid you'll screw it up (like I did at first), you might want to go with non-kit LCDs. Note that the kit I bought ("Serial 1 pin LCD Ready Kit for Basic Stamp, ATMEL, PIC") only included a perfboard, a bag of parts, and a schematic. This would perhaps be too advanced for a beginner kit builder.

The visibility on the little display is great. The backlight is very bright and the display is trans-reflective, so it's viewable even in direct sunlight and so on.

Here I've loosely affixed the LCD to the router with a large rubber band (though I could easily have used magnets) for a simple, easy, non-permanent bond. The firmware inside the Atmel chip provided with the kit provides a very simple interface - there are numbered commands that can be entered even with a keyboard (for example, "1 [enter]" means clear the display). A couple simple shell scripts provided a quick interface to the LCD:

File: /usr/sbin/lcdinit rwx
#!/bin/sh
setbaud /dev/tts/1 9600  # Set the baud rate to 9600
lcdcmd 1 7 0 "Hello"     # Clear the display, hide the cursor, 
                         #  and say Hello

File: /usr/sbin/lcdcmd rwx
#!/bin/sh
while test -n "$1"              # While we have commands left
do                              # Loop
 echo -ne "$1\\r" > /dev/tts/1; #  Echo the command and a Carriage Return
 shift                          #  Move to the next command
 done                           # End loop
As a test of my skills at commanding this new device, I made a small LCD text show to force it to sing my allegiance.
File: /usr/sbin/lcdshow rwx
#!/bin/sh
lcdcmd 1 7 0 "Nate is awesome " 0 "Clap your hands"
usleep 500000
lcdcmd 3 0   " and you know it" 0 " Clap your hands"
usleep 500000
scrollright () {
 lcdcmd 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
 }
scrollright
usleep 750000
lcdcmd 1 0 "Nate is awesome " 0 "Clap your hands"
usleep 500000
lcdcmd 3 0   " and you know it" 0 " Clap your hands"
usleep 500000
scrollright
usleep 750000
lcdcmd 1 0 "Nate is awesome"
usleep 500000
lcdcmd 1 3 0 " and you know it"
usleep 500000
lcdcmd 1 0 "And he's not af-"
usleep 100000
lcdcmd 3 0 " raid to show it"
usleep 900000
lcdcmd 1 0 "Nate is awesome " 0 "Crap your pants"
usleep 500000
lcdcmd 3 0 " and you know it" 0 " Clap your hands"
usleep 500000
scrollright
I don't care what anyone else says. You don't control anything until you can make it sing for you.

The speakers

While not a necessary part of this project, I figured I'd mention the speakers I'm using. These are Virgin Boomtube speakers which I got off of Woot for something like $20. They are of course no longer available through Woot but eBay has a few.

These speakers have excellent sound quality. The internal bass boost really makes the small speakers kick, and the fact that you can pop 4 AA batteries in the center unit and take the speakers anywhere is just plain awesome.

They are, of course, no replacement for a large 5.1 surround setup in your home. If you want true big sound, that's definitely the way to go.

Hackin' it up

While the connection for the USB audio adapter is obvious (for the slower among you, it goes into the USB port in the back of the router), the serial LCD takes a little more finesse. Next to the serial console port on the WGT634U, there is a headerless second serial port to which the LCD must be attached.

For power, I piggybacked the LCD power supply onto the USB port supply which is always at 5 volts. The LCD draws about 120mA with backlight on (20mA without), but the WGT634U doesn't mind and has no trouble powering both the USB audio adapter and the LCD at once. Here the wires are running down below the circuit board and are soldered to the pins on the USB connector.

The software

What good is a great hardware hack without software to back it up? Well, it's still great, but it's even better with good software.

Enter OpenWrt, the fabulicious Linux distribution designed to run on Broadcom-based routers. The latest version, codenamed Kamikaze, is as yet unreleased and still considered unstable, however the build I'm running (r3186) is working superbly. For USB-audio support, make sure to build the kmod-usb-core, kmod-usb-ohci, kmod-alsa, and kmod-soundcore kernel modules (see below for other modules you'll need), as well as mpd, the music player daemon. Watch out for kmod-usb-ehci - it adds USB2 support but can get buggy when you're trying to run the USB audio device through a USB hub.

The Music Player Daemon

Software for this hack relies extensively on the excellent music player package, mpd. It runs as a server which accepts commands that manipulate and play playlists. With a great many command-line, GUI, and web-based clients, mpd is sure to meet your remote playability needs. I was thinking about creating an AJAXy frontend for mpd to run on the router (since PHP is too heavyweight for such a tiny router), and I might still do it in the future.

A few useful scripts

Creating the scripts for the Mobile Wi-Fi Access Point really gave me a chance to hone my shell scripting skills. And while I can't say I'm one of the bash elite (hell, I'm far from it), it is quite easy for me now to create small useful scripts. In addition to the three scripts for initializing/displaying/singing on the LCD display, I've made a few others:

The command interface

This one sends a single command to mpd and waits for a reply. It's much much simpler than any of the clients listed at musicpd.org and suits my purposes just fine. Thanks to Stefano Cazzulani for his connection-closing fix.

File: /usr/sbin/mpc rwx
#!/bin/sh
echo -e "$*\nclose" | nc 127.0.0.1 6600

# Usage: mpc (command) (parameters)
#  For example: mpc play
#               mpc stop
#               mpc add music.mp3
#               mpc load playlist
#               mpc setvol 100

The song display

This is an important one. It can display up to 40 characters of song title and artist, one on each line. Overflow is handled by scrolling left and right.

File: /usr/sbin/lcdsong rwx
#!/bin/sh
spaces="                                  "
while test 1
do
 art="`mpc currentsong | grep Artist | sed 's/Artist: //g'`"
 if [ -z "$art" ]; then art="No Artist"; fi
 ttl="`mpc currentsong | grep Title | sed 's/Title: //g'`"
 if [ -z "$ttl" ]; then ttl="No Title"; fi
 if [ ${#ttl} -gt 40 ]; then ttl=`echo "$ttl" | sed 's/ //g'`; fi
 art="`expr substr "$art" 1 40`"
 ttl="`expr substr "$ttl" 1 40`"
 al=${#art}
 tl=${#ttl}
 if [ $al -gt $tl ]
  then
   maxl=$al
   ttl="`expr substr "$spaces" 1 $(( ( $al - $tl ) / 2 ))`$ttl"
  else
   maxl=$tl
   art="`expr substr "$spaces" 1 $(( ( $tl - $al ) / 2 ))`$art"
  fi
  if [ "${art}" != "${oldart}" -o "${ttl}" != "${oldttl}" ]
   then
    lcdcmd 1 0 "`expr substr "$art" 1 20`" 0 "`expr substr "$art" 21 20`"
    lcdcmd 3 0 "`expr substr "$ttl" 1 20`" 0 "`expr substr "$ttl" 21 20`"
   fi
 i=$maxl
 while [ $i -gt 16 ]
  do
  lcdcmd 5
  i=$(( $i - 1 ))
  done
 sleep 1
 while [ $i -lt $maxl ]
  do
  lcdcmd 4
  i=$(( $i + 1 ))
  done
 oldart="$art"
 oldttl="$ttl"
 done

Remote filesystem mounting

Used to mount the remote filesystem and prepare for mpd loading. It also loads mpd.

File: /usr/sbin/gompd rwx
#!/bin/sh
#Usage: gompd (computer IP address)
# You must edit this file to work with your remote filesystem.
# In this configuration, gompd will connect to the share called
#  mp3 on the specified computer, with the username "Nate True".
#  It will ask for a password upon connect, if required.
#  CIFS is the file system used to access Windows shares.
mkdir /tmp/.mpd
mkdir /tmp/music
mount.cifs //$1/mp3 /tmp/music -o "user=Nate True"
#This line reduces latency for pause and setvol commands
echo mpd 5 16384 > /proc/asound/card0/pcm0p/oss
mpd

Automatic ShoutCAST radio tuning

This one was a fun one to make. Just type in the kind of music you want (ex. "trance", "symphonic classic", or "hindi") and it will search at ShoutCAST.com and play the first radio station it finds.

File: /usr/sbin/goradio rwx
#!/bin/sh
cd /tmp
rm -f mpdradio
q=`echo "$*" | sed 's/ /+/g'`
echo Performing search...
wget -qO mpdradio http://www.shoutcast.com/directory/?s=$q
until [ -f mpdradio ]; do sleep 1; done
url=`cat mpdradio | sed -n '/sbin[^"]*"/{p;q;}' | sed 's/^.*href="//g' | sed 's/.pls">.*$/.pls/g'`
if [ -z "$url" ]
 then
 echo No results found.
 exit
 fi
echo Downloading playlist...
rm -f mpdradio
wget -qO mpdradio http://www.shoutcast.com$url
until [ -f mpdradio ]; do sleep 1; done
radio=`cat mpdradio | sed -n '/http/{p;q;}' | sed 's/File[0-9]*=//g'`
echo Adding $radio to playlist.
mpc stop > /dev/null
mpc clear > /dev/null
mpc add $radio > /dev/null
mpc play > /dev/null
echo Done.

Exercises for the reader

How would one...

Conclusion

This was a really fun project. I especially like the one-word radio tuning, because it makes it so easy to explore new music categories. I discovered how motivating European Trance music can be, and how fun Hindi music is to listen to.

Be sure to check out some of my other projects below, and a big thanks to HostGator for helping me survive such huge surges in traffic.

Where to go from here

Copyright © 2006 by Nathan True. All rights reserved.