An AJAX Erlang Jukebox
This page is a mirrored copy of an article originally posted on the (now sadly defunct) LShift blog; see the archive index here.
Mon, 6 November 2006
Sometime around the beginning of July I rewrote our internal jukebox
in Erlang. It’s taken me four months to get a round tuit, but new
stock has just arrived: here’s the code for our AJAX jukebox
web-application, as a tarball. (There’s
also a mercurial git repository:
hg clone http://hg.opensource.lshift.net/erlang-jukebox/
git clone https://github.com/tonyg/erlang-jukebox
.)
Click on the image for a screenshot.
To run it, you will need Erlang, Yaws (the Erlang webserver), a modern browser, mpg123, ogg123 (from vorbis-tools), and some MP3 or OGG files to listen to.
I’ve made a start on a bit of documentation and design rationale. Here are a few highlights for the curious:
You point the jukebox at one or more root URLs, which it then spiders, collecting URLs for MP3 and OGG files, which it puts into a simple flat-file database. Just expose, say, your iTunes folder via Apache, point the Jukebox at it, and you’re away.
It relies on mpg123 and ogg123’s support for playing HTTP-streamed MP3 and OGG files, respectively, rather than retrieving or playing the media itself.
The user interface is completely written in HTML+Javascript, using prototype for its event binding and XMLHttpRequest support.
The server side of the application communicates with the user interface solely via JSON-RPC.
Erlang made a great platform for the server side of the application. Its support for clean, simple concurrency let me design the program in a very natural way.
As part of the development of the program, I built a few stand-alone modules that others might be interested in reusing:
the execdaemon and its associated Erlang controller module is a filthy hack I threw together to get better than the built-in support for POSIX process control and signalling from Erlang.
jsonrpc.js is a tiny, simple layer atop json.js and prototype that supports basic parsing of Simple Method Description (SMD) files, generating Javascript client proxy objects for each JSON-RPC service described by an SMD.
[Update: fixed an issue with json.js, tweaked the use of screen real-estate, and now seems to work with Safari, IE6, and Opera. I've changed the tarball link above to point to the new version.]
[Update: fixed a couple of links that had broken over time as the darcs repository evolved.]
[Update: moved from darcs to mercurial, and altered the links to reflect the change.]
Comments
On 7 November, 2006 at 4:27 pm,
wrote:On 7 November, 2006 at 5:22 pm,
wrote:Sorry, Andrew, I didn’t; I’ve been ignoring the whole issue of file tagging as “too difficult”. We’ve been finding that a stupid simple substring search on the whole file URL is good enough for us - “worse is better” strikes again?
We’re mitigating the unstructured search approach a bit by exploiting the structure found in the URL itself, clustering result URLs together by their directory part and sorting results lexicographically. We end up with a search result list that is often both clustered by album and in track order (if tracks have “01…” etc. prepended to their filenames) within each album.
On 7 November, 2006 at 11:16 pm,
wrote:Nice! In fact very nice!
However, on my old laptop I didn’t have Java installed, which seem to be needed by the json.js code, so I couldn’t try it out. Apart from that, it is the first real Erlang/Ajax app. I’ve seen so far. Good work!!
On 8 November, 2006 at 11:46 am,
wrote:Doh! That was a remnant from an earlier hacking session - I’d taken json.js from this earlier project. I’m surprised it works at all! I’ll fix that now and update the tarball.
On 8 November, 2006 at 12:15 pm,
wrote:As a pleasant side-effect, removing the Javaisms from json.js seems to have let the code run on Safari and IE6…
On 9 November, 2006 at 8:42 pm,
wrote:Ok, I got past that problem. But I guess I have a to old Firefox version (1.5.0.7). Since it complains about line 168:
color: red ! important;
Perhaps I sould try and install Firefox 2.0 (if I can figure out how that is done in Ubuntu…).
Another, thing: perhaps you should make use of some of the new nice Autoconf macros for Erlang to locate Yaws (they were presented at the EUC today btw :-) As it is now, I have to change the ref. to /opt every time.
On 9 November, 2006 at 9:34 pm,
wrote:Update: I had to fix a small bug in Yaws. When having several servers listening to the same port, then the ’start_mod’ module was not called properly. It is now fixed in Yaws CVS.
On 10 November, 2006 at 12:51 pm,
wrote:Hey, great that you have it running!
The CSS problem is odd - how does it manifest itself? I’m using 1.5.0.7 here and it seems to work okay. Perhaps you have a developer plugin I’ve not tried?
On 10 November, 2006 at 5:04 pm,
wrote:Well, actually; I can’t get it to work :-)
Follow my link and see if it works for you.
It could be my server, I’ll have to check more closely.
Btw: how do I start playing a tune, just by enque it, or ?
On 10 November, 2006 at 7:16 pm,
wrote:Have you looked at jinzora? How is your Jukebox different than Jinzora? It has same functionality as yours and then some. Thanks.
On 10 November, 2006 at 8:27 pm,
wrote:There’s really no comparison. This is a new, small, simple program, weighing in at 1,400 lines of Erlang and Javascript; Jinzora is a mature, large, complex program, with over 100,000 (!) lines of PHP code. Both are open-source, and both have something to do with playing MP3s in some kind of jukebox-like configuration, but that’s about where the similarities end, it seems to me.
On 10 November, 2006 at 8:31 pm,
wrote:@Tobbe: yes, just enqueueing it ought to do the trick. It’s very strange, the installation you have: it seems that some of the features are working, while others aren’t. For instance, typing in a chat message causes the history list to update, but the timer-based history (and playlist) refresh seems to be broken. Weird.
On 11 November, 2006 at 9:08 am,
wrote:Another cool AJAX jukebox is at http://www.streampad.com
Seems a lot more advanced than this although certainly not as tiny!
On 11 November, 2006 at 9:57 am,
wrote:Update: Found that I need to start Yaws in the same directory as the code. So now I don’t get any errors in the log at least. Still doesn’t work though.
It could be a good idea to structure the code under src,ebin,priv directories. The execdaemon binary then goes into the priv directory. You can then locate it with code:priv_dir/1.
Example:
# erl -pa `pwd`/erlang_jukebox 1> l(spider). {module,spider} 2> code:priv_dir(erlang_jukebox). "/home/www/site/erlang_jukebox/priv"
On 11 November, 2006 at 10:02 am,
wrote:Also: Where do I find this ‘hmix’ program that volume.erl wants to use ? (I’m running Gentoo btw and it doesn’t seem to exist among Gentoo’s packages)
On 11 November, 2006 at 2:57 pm,
wrote:Tobbe, thanks for the tip. I’m still getting to grips with the Erlang way of working - anyway, I’ve just found the guide to application directory structure, and I’ll take your advice regarding priv
. I’ll post again when I’ve committed the changes to darcs.
Oh - there’s a copy of the hmix source code in the util/
subdirectory.
On 14 November, 2006 at 10:42 am,
wrote:A friend pointed out Music Playing Daemon to me; it’s the first thing I’ve found that makes it clear that it has similar goals to our jukebox software, ie a single playlist that’s under the control of multiple users.
I looked into Erlang for rewriting my jukebox program which is currently in Java. However, I couldn’t find any modules to read tag information which is what my jukebox uses instead of file names.
In your travels, did you run across any such modules?