Sunday, 17 November 2013

First release of light-play available on GitHub


Finally, the first release of 'light-play' is available on GitHub. Check out https://github.com/ErikOnBike/light-play if you are interested.

It has been a while...

My optimism had the best of me during my previous post. Unfortunately, things did not go exactly as planned. First I mistakenly thought the newer Apple TV devices would still be able to handle the old AirTunes TCP protocol. Wrong! Stupidest thing, I could have seen this much earlier, but was just ignorant of the fact. So I came from TCP, went to implementing the newer UDP approach, and ended up...nowhere... Turned out that the default m4a ALAC file encoding uses 4096 frames per packet. This results in packets larger than UDP (by default) supports. I have look around, tried different things, but in the end failed to split these large audio packets in chunks which my Airport Express would swallow (and still produce useful sounds).

I'm still unsure if there is a way to split large ALAC packets in a way Airport Express can handle them. Normally, iTunes and other players will transcode the file into a format using 352 frames per packet. These audio packets fit inside a UDP packet. But my whole point was to develop a player which would not do any encoding/transcoding (including NO encryption). It should be a very light player (enough players out there doing it the full monthy). Frustrating...

Picking up the pieces

So after a period of doing nothing with light-play, I ended up changing it back to a TCP player for the good 'ol Airport Express. And there you have it. On GitHub (https://github.com/ErikOnBike/light-play) you can find it.

In the long run I still might support Apple TV devices, but only with AAC files probably. As far as I know, these normally have smaller packet sizes preventing the problems I had with large ALAC packets. But I'm definitely going to look into this very carefully before adding this support. Been there, done that, not intending to do the stupid things again.

In the mean time, I will try to turn the current command line application into a server based application with a web based user interface. Stay tuned...but do not hold your breath.

Past experience is no guarantee for the future

'Past experience is no guarantee for the future', a (very) free translation of a Dutch phrase added to all TV and radio commercials regarding the savings of money based on speculation. [The fact that a savings account did result in 10% interest last year does not guarantee it will be that high (or even profitable) this year.] My past experience with programming in C dated back many many years ago. I have been doing programming and scripting ever since, so I felt it would not be a problem. It turned out to take me quite a lot more time to develop a nice solution (or in my feeling enough close to it) in a language which is so bare metal. My preferred development environment is Pharo, based on Smalltalk. Quite a different beast.

The code itself now is fairly clean. Almost no need for external libraries. A makefile which could not be simpler (although this means it will not work directly on some tool chained environments as is OpenWrt). I really 'dug' the bike shed article (how appropriate for 'ErikOnBike'): http://queue.acm.org/detail.cfm?id=2349257 Happy reading...

Tuesday, 12 February 2013

Apple's audio devices don't need a Challenge

Apple's Airport Express and Apple TV devices are capable of receiving audio data and transmitting it to connected speakers or audio devices. In contrast to what I see in use, it does not need any encryption of the data. The audio capability of Apple's devices is typically used with iTunes to play your music files on these connected speakers and is called AirTunes. Jon Lech Johansen (see http://nanocr.eu) extracted the RSA public key from iTunes and with that was able to mimic iTunes in sending encrypted audio data to Airport Express and Apple TV devices. His open source implementation JustePort (see http://nanocr.eu/software/justeport/) shows this.
When trying to implement an iTunes server on my wireless router I came across forked-daapd by Julien Blache (see http://www.jblache.org and https://github.com/jasonmc/forked-daapd). The code uses the same key for encrypting the audio data. For my purpose forked-daapd is too heavy. My router's CPU is running at almost 100% to play a single AAC audio file. The weird thing was, MP3 files played with far lower CPU usage. Enough reason to dig a little bit into the code. My conclusion is that forked-daapd is a nice application...if your system has enough resources. Mine does not, so I started looking how to build a light weight implementation myself. I looked at the capabilities of my pretty ancient Airport Express and found it advertised two important features:

  1. Able to play ALAC encoded audio
  2. Able to support both encrypted and non-encrypted audio
Somehow I have not seen any AirTunes capable music player make use of this unencrypted support. Being able to use non-encrypted data would of course mean that my player would consume less CPU cycles. The funny thing is, setting the encryption on the audio does seem to have one single trigger that might not seem so obvious: sending a Challenge request to the AirTunes capable device at startup. Removing this was for me the logical thing to do to try and get rid of the encrypted communication. And of course, stop sending the RSA key and initialisation vector. It seemed to simple... To see if my theory was right I adopted Jon's JustePort application and tried to play music unencrypted by just not starting the conversation with a Challenge. And lo and behold my speakers came to live and played my ALAC audio file without any problem!


What's next?

I'm currently writing my own little music player. Adapting JustePort further would not work for me, since I still want to run it on a tiny system. So I'm implementing a player myself. It is going to be a mpeg4 player specifically to be able to use the AirTunes audio encoding ALAC and AAC. The AirTunes devices are capable of playing audio data with these encodings directly, so no extra decoding and encoding is required in my software. The player is in fact not much more than a data streamer with a little knowledge of the file format in use.
Since I only have an Airport Express, my theory still needs to be checked against an Apple TV device. I'm borrowing an Apple TV to test it out. If it fails, I'll still be able to play my ALAC files on my Airport Express. It takes at least double the storage space, so being able to play AAC's in the future would be nice. I'll have to get my hands on a nice second-hand Apple TV though, since that is the device capable of playing AAC's.
Next to the music player I'm developing a small web-application which allows me to control the music player somewhat like an iTunes player. Searching, showing and selecting albums, artists, genres and songs, create playlists from them and of course at some point...start playing these songs. A web-application might sound pretty hefty, but the heavy lifting is actually going to take place within the browser itself. Therefore I'm going to use jQuery Mobile and JSON to have most work done in the browser of my laptop, tablet or phone. My router will only serve data from an audio file (with a well known structure) to the AirTunes device.

Will we see more?

Yes, you will. Expect the source code of the music player and the web-application to become available in the coming days and/or weeks. After a little bit of testing. The software will be pretty autonomic in that it does not require any audio nor encryption libraries. I'll probably add in a package for OpenWrt (see https://openwrt.org) since that's what my router is running. The software should probably be pretty useful on the Raspberry Pi (see http://www.raspberrypi.org) as well...if you have an Airport Express or Apple TV and m4a (mpeg4 audio) files laying around.
For the record, the software will use MD5 hashing for situations in which the AirTunes device uses a password to protect playing music. The MD5 is only used to hash a certain piece of information as a sign of having the right access token. The audio data is still not encrypted.

Some background

To see the capabilities of you AirTunes devices you can browse for RAOP devices. RAOP stands for Remote Audio Output Protocol. You can run the following command in a Terminal on your Mac to browse for RAOP capable devices on the network:
dns-sd -B _raop._tcp

On my system/network it gives the following result:
Browsing for _raop._tcp
DATE: ---Tue 12 Feb 2013---
20:18:18.389 ...STARTING...
Timestamp    A/R Flags if Domain Service Type Instance Name
20:18:18.391 Add     2  4 local. _raop._tcp.  001122446688@MyAirPort


The above result shows my Airport Express device. I can now lookup its features by issuing:
dns-sd -L 001122446688@MyAirPort _raop._tcp

This gives the following result:
Lookup 001122446688@MyAirPort._raop._tcp.local
DATE: ---Tue 12 Feb 2013---
20:18:35.509  ...STARTING...
20:18:35.603  001122446688@MyAirPort._raop._tcp.local. can be reached at MyAirPort.local.:5000 (interface 4)
txtvers=1 vn=3 pw=false sr=44100 ss=16 ch=2 cn=0,1 et=0,1 ek=1 sv=false sm=false tp=TCP,UDP

As can be seen on http://nto.github.com/AirPlay.html the cn field specifies the supported encoding types (PCM and ALAC in this case). The et field specifies the encryption types supported (no and RSA). Apple TV devices luckily still have et=0,1 in their feature list.


Who are you anyway?

My name is Erik Stel, I'm an IT consultant and have a background in software development. The blog's name Erik on Bike comes from the fact that I like cycling (aka biking) and motorbiking a lot.