Rio Receiver Protocol

Boot Process


The Rio receiver uses a two-step boot process, which quite ingeniously allows for easy updating of the operating system without having to
worry about messy flash memory. When the system first powers up, it sends out a DHCP request, to receive an IP address. In the JRec and Mock receivers,
the Linux system's DHCP server is simply given an entry for the Rio. The stock Rio server software (for windows) runs its own DHCP server. Apparently,
according to Chris Uriarte (who got this from Rio devleopers), the windows software only responds to Rio DHCP requests, based on the presence of a special
cookie in the Rio's request.



Once the Rio has its very own IP address, it broadcasts an SSDP request via UDP port 21075. Basically, it says "Hey, I'm here, who's my server?" The actual
request looks something like this: "^upnp:uuid:1D274DB0-F053-11d3-BF72-0050DA689B2F\n(mac address)\n". The server then responds to the client with
the IP address of the server, and the correct port to use (generally 12768, but not required to be so). It also apparently returns a pointer to an XML file (descriptor.xml),
but I haven't been able to actually see any XML files being delivered.



Now, the Receiver does an NFS mount from the server -- I can't recall if it's always in "/tftpboot/<ip address>", but that's where it is on my system. Again, the
Windows server software provides this NFS service automagically -- on my Linux server, I've simply set it up as I would any other NFS server. The Rio mounts that
NFS directory, and reboots, using that directory as root. On the Windows system, that folder is contained in the "mercury.arf" archive file, which is basically just a
tarball. On the Linux server, it's simply a folder. Be careful trying to rebuild that .arf file, however, as it includes special device files in /dev that are difficult to get
just right with, say, WinZip. The great part about this is that it's simple to upgrade your receiver, or to add new components, simply by changing the .arf file.


At this point, the Rio isfully booted and ready to work. Much of the rest of the Rio's communication with the server is via HTTP calls over TCP/IP, though there are some
functions (status queries and favorites handling) that happen over a separate UDP protocol.

Client / Server HTTP Protocol


The Rio Receiver communicates with the server primarily over HTTP, though some status and control data goes over a UDP connection.
There are 7 system calls (server applets, I'll call them):



list

Returns contents of a playlist.


query

Top-level query of database for artist, album, track, or genre information.


result

Returns a track list when given some kind of search criteria.


tags

Returns information about the given song.


content

Delivers actual MP3 or WMA data.


layout

Lists and selects screen layouts.


favourites

For favorites lists (00 - 99).


Artist, Album, Genre, and Track Selection


The Rio handles the "Select Music" menu items for Artist, Album, Genre, and Tracks in the same fashion. (The Playlists menu is handled differently, and is described
later). First, when the user selects (for example) "Artist," the player sends an HTTP request to the server that looks something like this:

http://server:12768/query?artist=

The "artist=" query can be "artist" (which selects based on the artist tag in the MP3 files), or "source" (which refers to the album listed in each tag), "title" (the,
you guessed it, "title" associated with songs), or "genre" (spelled-out genre titles). For each of these, the response is the same: an ASCII list of matching titles,
artist, genres, or albums. Example:

matches=
0=15,0,0:311
1=1,0,0:A-Ha
2=41,0,0:Aaron Copland
3=19,0,0:Abba
4=9,0,0:Action Figure Party
5=2,0,0:Adam Ant
6=15,0,0:Aerosmith
7=1,0,0:Afroman

The "matches=" line doesn't seem to do anything, but that's how the Windows server works, so we include it here. The first number (0-7 here) is simply an index to the entire list of matches. Only the first of the next group of numbers seems to be utilizied, it gives the number of tracks "under" that named item. For example, this result
is telling the receiver that there are 41 tracks listed with the Artist name "Aaron Copland," and ony 1 track listed for "Afroman." As you can imagine, this by-Artist listing
can get quite long, if you've got a lot of individual tracks taped off the radio.



The query can also include expressions to narrow down the search, or to reduce the number of results returned. By adding a simple word to the URL, the user can
do a quick "begins with" search:

http://server/query?artist=Al

matches=
0=1,0,0:Alan Parson's Project
1=16,0,0:Alan Parsons
2=1,0,0:Alan Parsons Project
3=10,0,0:Alan Parsons Project, The
4=13,0,0:Alanis Morissette
5=1,0,0:Albeniz
6=1,0,0:Alexander Borodin
7=2,0,0:Alexis Emanuel Chabrier

(You can see that I need to clean up my tags somewhat.) Also, simple regular expressions are supported. The Rio remote, for example, is arranged with letters
on the numeric keypad similar to a telephone keypad. So, if you want to look for, say, Genesis, rather than typing out the entire name you simply press 4-3-6, and a regular expression is built like this:

http://server/query?artist=[4ghi][3def][6mno]

matches=
0=47,0,0:Genesis
1=1,0,0:George Baker Selection, The
2=1,0,0:George Enesco
3=1,0,0:George Frideric Handel
4=12,0,0:George Winston
5=2,0,0:Georges Bizet
6=1,0,0:Georges Enescu

By adding _begin=# and/or _end=# to the URL, you can restrict the list to a smaller subsection:

http://server/query?title=&_begin=4500&_end=4504

matches=
4500=1,0,0:Ultra Violet (Light My Way)
4501=1,0,0:Ultrasonic Sound
4502=2,0,0:Un Amor
4503=1,0,0:UN Me
4504=1,0,0:Unchained Melody

Selecting a Playlist


Selecting a Playlist is a little different. First, when the user selects "Playlists" from the "Select Music" menu, the Rio requests the contents of file id 100. (note that all file ids are hexadecimal numbers). Generally, such a request would return the actual MP3 data for track number 100, however, 0x100 is a special case. When the server
receives this request, it returns a list of playlists.

http://server/content/100

e7a=PChristmas
111=PNew this week
110=PNew today
1647=PPartyMix

This is a list of playlist names, each with its own unique hex id code. The "P" after the "=" sign apparently flags the item as a playlist, other responses return a "T"
in that position, presumably to denote a track. However, the Rio doesn't appear to care what goes there, as long as there's a single character between the
= and the track (or playlist) name.

Playing Something


Artists, Albums, Genres, and Titles


When the user selects an Artist, Album, Genre, or Title, the Rio issues a new kind of request, using the "results" applet. The result is either ASCII or Binary, depending on flags present in the request. When _extended=1 is present in the URL, an ASCII response is issued. For _extended=0 or _extended=2, or when no extended variableis present, a binary-formatted response is issued.

http://server/results?title=Time&_extended=1

e15=TTime
f91=TTime

In this case, the result is very similar to the list returned as the top-level Playlist list, only now the "P" flags have been changed to "T" flags. This represents what
the receiver would get were the user to select a track called "Time" in the "Titles" menu. There are two songs by that name in my system (one by Pink Floyd,
the other by Alan Parsons). The receiver will then play each of these tracks, either in order (if shuffle is off), or randomly.



In the case where the receiver adds _extended=0, or when there's no _extended variable in the URL, the server responds with a binary list of tracks. The response
is a pair of DWORDS -- 4-byte words -- for each track in the list. The first DWORD contains the file ID, the second, its filesize. This simly repeats for each track in the response. When the receiver includes _extended=2, the list is comprised of DWORD triplets -- file ID, file size, and MPEG data offset within the file.
When the user selects "Play All Music" for any given Artist, Album, or Genre, the Rio simply repeats the original results query with _extended=2, and plays the songs that are listed there.



Now that the receiver has a nice, compact, binary list of all the tracks it's supposed to be playing, it plays each track in turn, issuing "content" commands for each.


Playlists


The receiver first, as described above, uses the "content/100" call to get a list of all available playlists. The user then selects a playlist, and the content call is repeated
with the ID of that playlist. Since the ID points to a playlist, and not to a music file, the server returns a list of the items in that playlist. At this point, the user selects one of the tracks from that playlist, or selects "Play All Music". For the "All Music" selection, the Rio sends a "list" request:

http://server/list/1647?shuffle=1&_extended=2

The server then returns a binary list (as described above), of all the songs in the given playlist. If shuffle=1 is included, the list is randomized at the server before
being returned to the player. If shuffle=0, or is not present, the songs are presented in the order they're listed in the playlist. Note that the items listed in the playlist
are sorted alphabetically by the player for display.



If the user selects an individual track from the list of the playlist's contents, however, the Receiver issues the same command! That is, rather than issuing
a "content" command (as you might expect), it requests a list of tracks matching the given ID. Since, in most cases, this will not be a playlist, but rather an actual musical track, the server would return the binary response for a single file (giving its ID, filesize, and MPEG offset, since all list queries are issued with _extended=2.) However, if the given ID points to another playlist, then the Rio displays the contents of that playlist, and can continue downwards, hierarchically, through many
levels of nested playlists. I have actually tested this with a modified perl server, but as I write this documentation I don't have details as to how it worked. I believe
that, in this case, the Rio pays attention to the "T" or "P" designation in the playlist, and issues a "content" call with _extended=1.

Actually Playing Something


When the receiver finally is ready to actually play a track, it first requests information about that track. It does this by issuing a "tags" command for the
given file. A tags command, with no arguments, simply returns a list of valid information that the server knows about (most) tracks:

http://server/tags/

fid
title
artist
source
year
comment
length
type
path
genre
bitrate
playlist
codec
offset
duration
tracknr

Most of these are pretty easy to figure out (file id, title, etc.) Some are a little more complicated. When the Rio requests tag information for a specific file (like "tags/3a1"), it returns a binary response with tag information packed in. The format of this is "KEY", "SIZE", and "DATA", where KEY and SIZE are single bytes, the key designating what kind of data is next in the stream, and the size telling how long, in bytes, that data is. Key values, for each tag, are:


0

File ID

1

Title

2

Artist

3

Album

4

Year

5

Comment (from ID3 comment tag)

6

Filesize

7

Sourcetype ("tune" for music track)

8

File Path

9

genre

10

Bitrate

11

Playlist name

12

CODEC (MP3 or WMA)

13

Data Offset

14

Duration (in milliseconds, I believe)

15

Track Number (on album)


I'm not sure if there's a particular required order for these tags to appear in the response, but in testing I had trouble when certain tags appeared
before some others. I'm not sure if this is a Rio problem, or if it was a bug in my test script. Also, not all of these are actually displayed on the Rio -- I've
yet to figure out how to show a song's Genre, for example, or any comments.



After receiving the tag information for a track, the receiver retrieves the music data for that song, using the "content" app, like this: "http://server/content/<id>". The HTTP request can include beginning and ending byte marks, so the entire song doesn't need to be downloaded at once (which also facilitates fast forwarding through the song).