Archive for July, 2007|Monthly archive page
I can’t afford to buy a house here, that’s a fact. However internet space is much cheaper so I’ve decided to get my own domain, my own blog and possibly my own code. I’ve been hosting elsewhere for a while, always moving here and there instead of building my own place but that’s not a good long term strategy. It’s time to settle down.
Thanks and see you there!
In the current Apple frenzy, what’s better than a post about an old Apple product: the Airport Express. Small and versatile, this device can be used for several different applications but it’s most popular to send music over wi-fi (to your good ole’ amplifier located on the other side of your apartment for example). It’s also a pretty cheap thing.
I mentioned in my last post that I was using my little last.fm reader script to feed an Airport Express and somebody asked me how. First, I have to say that there isn’t much to do, thanks to the nice raop client created by Aaron Patterson. So like many other Ruby hacks, it starts with a:
gem install raop-client
Playing an MP3 file to your Airport is now just a small script and a command away:
require 'raop' raop = Net::RAOP::Client.new("192.168.1.63") raop.connect # Closer to 0 is louder raop.volume=5 raop.play $stdin
What looks like an IP address above (192.168.1.63) really is an IP address. It’s the one of your Airport Express on your local network, I’m sure you now how to find it (hint: your router probably knows). Save this script in a file (aex.rb for example). It takes a stream of raw wav as input, so we’ll need to summon the power of LAME (Lame Ain’t an MP3 Encoder) to produce the stream:
lame --decode "Joe Dassin - Les Champs-Élysées.mp3" - | ruby aex.rb
Mind the dash after the file name, it’s important. If you’re not a Linux happy user ™, you’ll need to get LAME. If you’re a Windows user, good luck with the pipe. Divide & Conquer with Cygwin would probably work though.
Note that making open source software that uses MP3 files isn’t an easy task. The Fraunhofer Society owns a patent on the MP3 format and has enforced it in several occasions (generating a good deal of revenue). Everything that encodes, decodes or reads MP3s have to pay and yes, that includes your iPod. I don’t think it ever went directly against open source developers but then it never said it wouldn’t either. A very reasonable move would be to authorize GPL licensed software to use their patent. I’m sure they use open source software as well, so they should really stop leaching.
Anyway you’re now happily playing songs to your Airport Express but you’re still missing the last.fm part. As I said, raop client accepts any wav stream so it’s just a matter of piping the last.fm stream (obtained in my last installment) through LAME and redirecting that to raop client.
To glue this with the last.fm script I’ve shown you last time, just do:
lastfm = LastFM.login("mriou", "****") lastfm.tune("lastfm://user/mriou/playlist") aex = AirportListener.new("192.168.1.65") lastfm.play(aex)
If you want to see the whole script plus a few additional niceties, it’s available on Rubyforge. You can checkout the whole thing and then run bin/lastfm.rb.
svn co svn://rubyforge.org/var/svn/dubya/trunk dubya
Irecently have been unlucky enough to experience a hard drive crash. The unrecoverable type of crash. Being on the light side for backups, I’ve lost all my (legally obtained of course) collection of mp3. Tons and gigs of them. I’m not crying because I’m a man but I can tell you that my heart bleeds. So as a result, I pretty much rely on internet radios now, among which last.fm. The trick though, is that I run Linux so their default player (iTunes nastiness) doesn’t work for me. And I hate iTunes anyway. Amarok is much better but I own an Airport Express and I can’t easily stream to my Airport using Amarok. Long story to say that I needed some more creativity.
Turns out that the last.fm protocol is pretty simple. A very nice person has retro-engineered it in a pretty thorough manner. So I won’t repeat everything that has already been explained in detail, just sum up and add a couple more missing things:
- The last.fm stream is a plain old MP3 stream (more poms for the Maven fans out there). It doesn’t have any Shoutcast style meta data.
- On the other hand, they insert a “SYNC” string in there signal anytime the song changes in there stream, to let you know what’s happening.
- To get what’s currently playing they have a web service (the kind of RESTful type) that can be invoked anytime and returns all kind of information about the song. That with the previous point allow you to know what’s happening. There are also a few more services to skip, love, ban and let them know how you really feel right now.
- To start the interaction, you only need to login by invoking a URL, sending you username and password. I can hear your knees jerking my security-aware friends, but don’t worry, the password is MD5 encoded. They reply to you with a session id that you pass in any subsequent calls.
I told you it was simple. So I went ahead and implemented the whole thing in Ruby, which turned out to be equally simple, once all the aforementioned details were clear. And here is the thing:
Now what do you do with that little “out” variable? Pretty much everything you want. You really can’t pass a file, to stream everything to your disk and therefore get MP3s for everything you’re listening. That would be illegal. Plus the RIAA people don’t like it and we should really listen to them, they act for the good of music.