An AJAX Erlang Jukebox

By: on November 6, 2006

Erlang Jukebox Screenshot

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 repository:
hg clone http://hg.opensource.lshift.net/erlang-jukebox/.)
Click on the image for a screenshot.

To run it, you will need Erlang, Yaws (the Erlang webserver), a modern browser, href="http://www.mpg123.de/">mpg123, ogg123 (from
vorbis-tools)
, and some MP3 or OGG files to listen to.

I’ve made a start on a bit of href="http://hg.opensource.lshift.net/erlang-jukebox/raw-file/default/doc/index.html">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 href="http://en.wikipedia.org/wiki/XMLHttpRequest">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 href="http://hg.opensource.lshift.net/erlang-jukebox/file/default/priv/execdaemon/">execdaemon
and its associated Erlang href="http://hg.opensource.lshift.net/erlang-jukebox/file/default/src/execdaemon.erl">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.

* href="http://hg.opensource.lshift.net/erlang-jukebox/file/default/priv/server_root/htdocs/jsonrpc.js">jsonrpc.js
is a tiny, simple layer atop href="http://hg.opensource.lshift.net/erlang-jukebox/file/default/priv/server_root/htdocs/json.js">json.js
and prototype that supports basic parsing of href="http://manual.dojotoolkit.org/WikiHome/DojoDotBook/Book9">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.]

FacebookTwitterGoogle+

17 Comments

  1. Andrew Barilla says:

    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?

  2. tonyg says:

    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.

  3. Tobbe says:

    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!!

  4. tonyg says:

    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.

  5. tonyg says:

    As a pleasant side-effect, removing the Javaisms from json.js seems to have let the code run on Safari and IE6…

  6. Tobbe says:

    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.

  7. Tobbe says:

    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.

  8. tonyg says:

    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?

  9. Tobbe says:

    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 ?

  10. Samir says:

    Have you looked at jinzora? How is your Jukebox different than Jinzora? It has same functionality as yours and then some. Thanks.

  11. tonyg says:

    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.

  12. tonyg says:

    @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.

  13. Henry says:

    Another cool AJAX jukebox is at http://www.streampad.com

    Seems a lot more advanced than this although certainly not as tiny!

  14. Tobbe says:

    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"
    
  15. Tobbe says:

    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)

  16. tonyg says:

    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.

  17. Paul Crowley says:

    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.

Post a comment

Your email address will not be published.

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>