UPDATE 1/1/2: I've received a lot of mail about this after getting mentioned on slashdot a couple of times. I haven't updated the scripts since the original writing, here are a couple of things to look out for. Dell doesn't seem to be selling their version of the receiver anymore, but you do see them on eBay now and then. SonicBlue has reduced the price of their box making it a very affordable toy.
A few common installation problems: You need to have the Perl module MP3::Info. Most people don't have this by default, you can get it at CPAN. The scripts aren't terribly robost about the way they handle bogus or missing tag information in MP3 files. Start out with a few MP3 files that you know have good tag info before building a song database with a large number of files. Some people have had problems with DHCP servers that might cause trouble booting the box. There are some subtle variations in DHCP servers and how the hostname is passed to the client box. This might cause the Rio Receiver to try and mount its root partition using its IP address instead of it's hostname in the path name. If you have troubles I advise snooping the network to see what path the Rio Receiver is trying to use as the root filesystem.
I've received email from people that are successfully running the scripts on Solaris, BSD, even Windows machines, so it seems to work in non-Linux environments.
This is a set of Perl CGI scripts for using the Rio Receiver with a Linux server. Download the latest from ftp://ftp.mock.com/pub/rioserve_0_10.tgz.
The Rio Receiver is a piece of home stereo equipment for playing MP3 or WMA files over either ethernet or an HPNA phone line network. The Rio Receiver is also sold as the Dell Digital Audio Receiver. The two products have different front bezels and splash screens, but they are the same product otherwise. Currently the Dell product is sold for $299 including speakers and the Rio product is sold for $349 without speakers. I'll refer to both devices as the Rio Receiver.
The device was developed by Empeg in England and they licensed the design to Rio/S3/Diamond/SonicBlue who later acquired Empeg. Empeg is the company that developed a well known Linux based automotive MP3 player.
The device is designed to work with a Windows host that serves audio files to the device. It's a nice idea, I bought one hoping to use a Linux machine as the server. I read that the Empeg automotive product was Linux based and fairly open, so I purchased a receiver optimistic that the home stereo product is a similar design and that I could coerce it to work with a Linux server.
With the enclosed Perl scripts it's easy to setup a Linux machine running Apache to serve MP3's to any number of these receivers. With a Linux server the device operates nearly identical to a box using a Windows machine as a server although there are still a few features missing from the Linux server. This code currently does not support saved playlists or saving favorites. I have not attempted to support the HPNA networking interface, I also have not attempted to support WMA files. All of my content is in MP3 format, but I suspect that adding WMA support to the server is trivial.
The linux server has a few features not provided in the windows implementation. It's open source and easy to change to suit your needs. The database of songs (stored in DBM files) can be modified while music is playing, the Windows implmentation requires that music play stop during a database update. When an album is selected this implementation plays songs in the original order of the album.
This document is still a bit rough. It is not a clean howto, it's more of a description about how the receiver works, but it should be easy to setup a server. I'm assuming that the reader is pretty technical and comfortable configuring Apache, setting up a DHCP server, and configuring NFS on a linux box.
I have not modified the device software so there's no worry about trashing the firmware stored in flash in the receiver. It's not necessary to open the case of the receiver so there's no worry about voiding the warranty.
The receiver also contains a 16-bit DAC, headphone amplifier, 10W power amp for speakers, an LCD, an IR receiver for a consumer remote control, and buttons for a user interface.
The box contains no storage for music, all of the content must come over the network. With 4MB of DRAM it has enough memory for many seconds of music buffering.
The box is currently priced at $299 (Dell) and $349 (SonicBlue). This price is similar to the introductory price for other MP3 devices, but I think the product is terribly over-priced as measured by parts cost. Portable MP3 players typically have 64MB of flash memory that is the main cost of the unit. At today's prices 64MB of flash is about $50 of parts cost. The Rio Receiver only contains 0.5 MB of flash for booting, this is inexpensive and the other components on the board are inexpensive as well. I estimate the parts cost of the receiver to be about $80. Using rule of thumb margins this device could sell online for well under $200. I hope the vendors will price the device more agressively after collecting money from the early adopters like me.
The first thing the box does on power-up is to send out a DHCP request to get an IP address. Rio's windows software has a limited DHCP server that evidently only repsonds to requests from audio receivers. It's easy enough to add a DHCP entry on the Linux box to provide an IP address to the reciever. I don't think there is a method to assign a static IP.
The second thing the box does is broadcast an SSDP request on a specific UDP port (21075) looking for a server. The server responds to the box on the same UDP port with a packet that contains a URL and port number.
The port number contained in the SSDP response is used by the server for all future communication between receiver and server. This is a little problematic in that this port is used for portmapper requests (instead of port 111) for NFS mounts.
My linux solution for the SSDP requests is a very simple UDP server written in Perl that listens on UDP port 21075 for requests from a receiver box and replies with an IP address for the server, but omits the port number. When the port number is ommitted in the SSDP reply the receiver uses standard ports for various requests making linux configuration easier.
I start the SSDP server ssdp.pl from
/etc/rc.d/rc.local. It sits
quietly and responds to a couple of SSDP requests when the receiver
is booted.
"/tftpboot" and looks for the path
/tftpboot/hostname/
on the server. If you have ssdp.pl running you should be able
to boot the box and see syslog messages for the NFS mount. Add
an entry in /etc/exports to provide an insecure read-only mount for
/tftpboot. Please review your network security and make sure
you're not doing anything to expose your machine to Internet attack. This
warning applies to all these configuration issues, none of this
should be considered secure.
After the NFS mount, the box proceeds to access
/zImage on the mounted
partition. On reset the box first boots Linux from the onboard flash, NFS
mounts the root partition, reads
/zImage from the mounted partition,
and boots linux a second time from the zImage file. The double boot stategy
is very clever, the kernel stored in flash does not need to change when
software is upgraded, kernel enhancements can be added to
/zImage on the NFS
partition and take effect on the second boot.
The /tftpboot/ path prefix for the root partition is a bit of a
misnomer. TFTP is a different UDP protocol for booting, we are NFS
mounting a directory called /tftpboot, there is no TFTP server required. This is a quirk of the default paths for NFS root partitions
in the Linux kernel.
mercury.arf. This is a standard GNU tar
archive file. Untar the file into /tftpboot/hostname and you'll find
a minimal but familiar looking linux root filesystem.
I have not included mercury.arf in this distribution because I don't believe that I can. In addition to the Linux kernel this tar file contains the closed source player application for the receiver that I do not have permission to distribute.
Once the root filesystem is in place you should be able to reboot the
reciever and follow the action in the server's syslog. First DHCP, a SSDP
request gets logged, NFS mount of "/", and if all goes well the box
will read zImage and boot a second time. On the second boot networking
information is passed in the command line to the kernel so it will
not make a second DHCP or SSDP request but it will mount the NFS
root filesystem a second time. If you snoop the NFS traffic (did I
mention how great ethereal is) you'll see the client box read quite a
few files including running the application in
/empeg/bin/player.
When the player starts in the client it will make a different SSDP
request you'll see in the syslog. Previous SSDP requrests are labeled
"linux" requests, this one will be labeled a "player" request. When
you get this far this is quite a milestone. You'll be playing music
soon after a little Apache configuration. The second SSDP reply
provides the server IP address, but also provides a port number this
time. This port is used for HTTP requests to access music content.
By default ssdp.pl tells the reciever to use port 81 for HTTP
requests but you can easily change this is if you would like to use
a different port. I use a non-standard port number and associated
Apache virual host configuration to keep my music playing separate from
my normal web server activities.
An interesting aspect of the receiver's user interface is that most of the onscreen navigation is a front end to web server requests that provide song information. This is an interesting way to build a user interface for a piece of consumer electronics, but sadly the Rio Receiver only takes this concept to the point where the web server provides data. Navigation and UI appearance are hard coded into the client app.
I use the virtual host facilities of Apache to setup a server specifically for the receiver on a non-standard port. Here is a snippet from my Apache httpd.conf file for the music server:
# for music server
Listen 192.168.10.1:81
<VirtualHost 192.168.10.1:81>
ServerAdmin jeff@mock.com
DocumentRoot /home/html/mserve
ServerName 192.168.10.1
AliasMatch ^/list/ /home/html/mserve/list.cgi
AliasMatch ^/tags/ /home/html/mserve/tags.cgi
AliasMatch ^/query /home/html/mserve/query.cgi
AliasMatch ^/results /home/html/mserve/results.cgi
ErrorLog logs/mserve-error_log
CustomLog logs/mserve-access_log common
<Directory "/home/html/mserve">
Options ExecCGI FollowSymLinks
</Directory>
</VirtualHost>
You can change this to suit your needs. The only funny business is
the AliasMatch directive. Some of the HTTP requests come in a
form that is a little awkward for running a CGI script so I use
the alias feature of Apache to coerce the URL into a suitable
form. For example, the box will make a request like
GET /tags/4000
to read the mp3 tag information from track 4000. The alias
causes the request to run the CGI script
/home/html/mserver/tags.cgi
which is passed the orignal URL to sort out and return
the correct data. It's not as complicated as I just made it
sound.
Untar this distrubution into the newly configured virtual web server,
/home/html/mserver
in my case. You should probably change the ownership
of all of the files in the directory to apache to avoid any weird permission
issues later:
% chown -R apache:apache /home/html/mserve
Restart apache and use a browser to go to
http://192.168.10.1:81/ (in my case).
You should see a simple page with pointers to this document and
some other miscellaneous items.
/home/html/music.
If you wish to store them elsewhere
then change the .CGI files to reflect the new path.
One of the things that happens when the music database is built is that
the content sub-directory is filled with a bunch of symbolic links to the actual
MP3 files. I was having trouble getting Apache to follow symbolic links
outside of
/home/html
and I wound up putting my music files within the
Apache directory tree in
/home/html/music,
but that might just be my
own ignorance about configuring Apache.
Once you have the paths configured in the scripts and your music files ready. From a web browser click on the "rebuild entire database" link located in the index.html page at the root of the music server. This should spew ugly text output about each MP3 file along with a 4 digit hex identifier used by the receiver. You might look in the content subdirectory and find a large number of symbolic links with names like "4000" that point to actual MP3 files. You should also look in the dbm directory and see a number of DBM files.
Finally, we can use a browser to make a request the same way the receiver does to verify operation. Try the following cryptic URL from a web browser:
http://192.168.10.1:81/query?artist=
If the databse has been built should see output something like this although your musical tastes may vary:
matches=
0=25,0,0:10,000 Maniacs
1=2,0,0:AC/DC
2=65,0,0:Al Green
3=2,0,0:Alpha Blondie
4=12,0,0:American Beauty
5=1,0,0:Archie Bell & The Drells
6=1,0,0:Arlo Guthrie
...
If there are problems the scripts are setup to dump errors to
the file error-log in the same directory. If this is working you
are pretty much ready to go. Reboot the receiver and you should be
rewarded with the MP3 tag information of one of your songs in the
display. If we're very lucky you can hit the play button and listen
to music.
Once you get this far you should play with the user interface of the box. The only missing features are the "list" button on the remote control and selecting songs by playlist. You can select songs by artist, album, etc. You can use the slightly awkward user interface feature to spell out a portion of a title using the telephone pad on the remote control.
There is another link on the page to incrementally add songs to the database. If the database is completely rebuilt the receiver needs to be rebooted but songs can be added incrementally. The script scans the music directory and only adds songs that aren't already in the database.
I no longer have a CD player in my livingroom. I still buy quite a few CDs, but they arrive from Amazon, get ripped on the CD drive of my PC, and then stored away in a closet and never make it to the livingroom.
The receiver has a generally annoying user interface, the screen is too small, and the UI presents information too small for navigation from across the room. The box has a couple of annoying qualities, the volume control only operates on the headphone and speaker outputs. Based on a suggestion from Hugo Fennes here is a kernel patch for the device to cause the volume control to operate on the line level outputs of the box as well. If you don't fell like getting setup for building an Arm Linux kernel there is a pre-built kernel linked on the page.
It's unfortunate that you can't control the receiver from the network interface. There is a UDP protocol in the receiver for getting status information and doing a few operations like rebooting or reloading database information, but it's not possible to control play from the network interface (as far as I can tell). I keep wanting to use the receiver as an alarm clock controlled by my linux box.
I don't think the HPNA interface was a great idea. I'm probably not a typical consumer, but if a consumer is interested in digital music in their livingroom, they probably use a program like Napster. If they run Napster they probably have a DSL line or a cable modem. If they have a high bandwidth connection then ethernet is already a part of their lives.
Having said that, the device is really nice and I enjoy having it my livingroom quite a lot. I trust the Empeg people are working on a new software release and will work out many of the kinks in the first release.
If you open the case there is a 4-pin header labelled JP5. This header provides 3.3v power, ground, Tx, and Rx pins for the serial port built into the Cirrus Arm processor. The pinout of the header is shown below. The Tx and Rx pins are 3.3v logic levels, so you have to build a small piece of hardware to convert the 3.3v logic levels to RS-232 levels. I built a small board with a Linear Tech LTC1348 from Digikey to get serial port out. The console header is show in the image above, the pinout as follows:
If you build a level converter and hook it to the header you'll see familiar Linux boot messages at 115k baud, you'll also see the two stage boot process when it loads the second kernel over NFS.
When the receiver boots it looks for /bin/bash and allows you
to drop into a shell from the console by typing
"q<cr>"
on the console.
The mercury.arf file distributed with the recevier does not contain
bash, but it's easy enough to build an ARM cross-compiler and then build
bash, but there's not much you can do with a shell right now.