Wedding Jukebox
June 29th, 2008Weddings are rather expensive. Well, for us anyway. I’m sure we could’ve cut the guest list down to a handful and just gone to get a marriage certificate and be done with it, but we’ve opted for something a little bigger. But since we can’t really afford a huge, lavish wedding, we’re trying to cut corners where we can. One of the corners we’re cutting is the DJ. I know that a DJ can be an important component of a wedding and that they do a lot to make sure the party keeps going, but there are good DJs and bad DJs and both are expensive. Rather than spending the money that we don’t have on something like a DJ we don’t know, we opted for the ultra-chic “iPod DJ” for our wedding.
Now, we never really intended to have an actual iPod play the music for our wedding, but we do want to spend as little money as possible to get the grooves going. My original plan was to hook up an external hard drive containing music to my old Powerbook and have everything run off of iTunes. We’ll make a few different playlists, one for cocktail hour with some lower-key stuff, one for the actual ceremony and all of that and one huge playlist for the reception that could go on random. Then I got to thinking, wouldn’t it be nice if people could go up to the laptop and “request” or queue music that they wanted to hear? Then we would be one step closer to having a DJ without actually having a DJ…
I started looking into “Jukebox” software or front ends for various music players. I have OSX on my laptop, and have an old PC, so I’m not limited by operating system. I searched for any software anywhere that would do the trick. It wasn’t as easy as I thought it’d be. The only software I came across that did what I wanted it to was a homegrown package for Windows, but I wasn’t so impressed with the styling of it. That’s when my coworker Jesse turned me on to DCOP. DCOP stands for Desktop COmmunications Protocol. DCOP is basically a way for KDE (a linux desktop manager) apps to talk to one another. You can issue commands on a command line which control components of an application. In a way, it’s similar to Applescript I suppose, not the scripting itself but the library attached to an application. Scripts or apps can be built to make calls to DCOP to control the actions of a program. Anywho… on to the good stuff.
In comes Amarok. Amarok is a KDE music program similar to Winamp or iTunes, only better. Or so I’m told. I haven’t really played around with it enough to say whether it’s better or not just yet. The setup for it is a bit quirky and I haven’t quite grown used to it yet so I’ll reserve my judgment until I’m more familiar with it. The good part about it, though, is that it has a long list of controls for DCOP. Just about anything you can control from the graphical interface, you can control from the command line. It also allows you to queue songs in the playlist, so it will play the queued songs before going back to regular playlist play. So now we have the perfect backend for a jukebox. All we need is a front end.
Let me lay out my ideal, end goal prior to detailing various issues with it. First off, I’m a web developer, so I’ve opted to try to get this to run as a local web app. I’m sure this whole thing could be written in C++ or Python or Ruby or LISP or assembly or whatever your favorite language is. I have to work with what I know best, which at the moment happens to be PHP. Amarok has the option to store the music database in MySQL, which I’m also comfortable with, so that works best for me. My final goal is to have a web browser in Kiosk Mode running a front end web page for interacting with the music playing in Amarok. You’ll be able to browse artists, albums and songs, view album art and maybe some other information and select tracks to queue. I want people to be able to see what’s on there and queue tracks, but not be able to stop the music from playing, change the volume, edit the queue, or anything like that.
The problem with this is that PHP is made to run web pages and web pages are designed not to interact with your system. There are enough security problems as it is with the web, nevermind web pages having access to your files or running applications. So, in order to have PHP call DCOP, we have to do some trickery. My coworker Jesse threw together a small C++ app called DCOP Daemon that runs every second listening for comands written to a text file and runs those commands against DCOP. By the end of this project I’ll probably have to add more to that program, so I may eventually have to learn a little more C++ or some Python if I decide to rewrite it in that. I rewrote it as a PHP CLI app, but couldn’t get it to work reliably. It might still work with a little more work put into it, but what I have now is at least good enough to start development and testing.
Another hurdle I came across is album art. Amarok stores album art in a hidden folder nested deeply inside the home folder. I know there are security issues with this app, but I’m trying to make it as secure as possible in hopes of releasing this code once it is complete. So I’m riding the line between a secure app and an easy to use app at the moment. I could have apache run as a different user (it’s www-data right now on Ubuntu) so that it could access all of my user files, but I’d rather keep the machine more secure and have it run as a normal server (I’m writing from that box right now, so until this is set up I’ll obviously have it on a network…). My solution was simply to have a script copy the image files to a web-readable location so they can be accessed by my front end. Once I have gigs of music in there, it’s probably not the most efficient method, but it works. I figure once I have all the music I want on there, I’ll only really need to copy it once. Just to be safe, I’ll probably have it copy on starting up the app/daemon just to make sure they’re in sync.
Another issue I’m currently worried about is the latency of the daemon and scripts. The daemon is checking one input file and has one output file for messages. It runs the commands it finds every second and writes output to the output file. I had some trouble with the front end querying for play status. The command “dcop amarok player isPlaying” returns true or false to say whether Amarok is currentlly playing, but if I issued a play command through my front end and then immediately query for play status, it would come up false. It takes up to one second for the command to be read and then probably another second or so for it to return the status to the output file. Meanwhile, the PHP app quickly checked the output file and saw it as false, as it hadn’t been updated yet. For testing, I put in a sleep command, but the full implementation could see multiple commands being sent in quick succession. My current thinking on this is to have the front end use AJAX calls so that I don’t need to reload the entire page each time an action is taken (which should cut down on the number of simultaneous calls), to use multiple output files, possibly one per command that requires output so that they don’t overwrite one another, and I might also opt for recording timestamps so that I know if a file has been updated or not. I’m not sure at this point what methods will work best or be needed.
Now that I’ve got album art working and basic play functionality working, I’m going to start working on the design for the front end. I need to play around with Amarok’s queueing system to learn how it works a bit better. I’m hoping that if I set repeat to “off” that it will not allow users to queue tracks multiple times. If it does allow repeats, I may need to record what has already played and control that on the front end. I’m thinking maybe I could gray out songs and/or albums that have already been played so that they could not be selected again (ie, “Sorry, this song was already played/queued”).
Our wedding is in October, so while I have grand designs for this project, it also has a very strict deadline. I’m hoping I can throw together a functioning app before the end of the summer and have some time to add features, test, and generally play around with it. Once I’ve gotten a little more work done on it, I’m hoping to open source the whole project so that I can a) contribute to the community and b) maybe get a little help/feedback on the project. I think it could fill a niche as I haven’t seen any other projects that are doing what I’m trying to do. Who knows, maybe someone will be nice enough to donate a touchscreen to the cause.
My current setup:
AMD 1.7GHz, 512MB RAM, 40GB HD
Ubuntu 8.04 “Hardy Heron”
Amarok 1.4.9
PHP 5.2.4, MySQL 5.0.5