Building On-The-Spot: A Spotify play queue
About the Application
The idea behind On the Spot was to allow everyone in the office at work to control the playlist, so that there was some semblence of fairness about what we listen to. Probably the simplest way of showing you what it is is to see some pictures, right?
So, we basically have a two-page app - one page for finding music, another for playing it. This whole thing runs on a server in the office, and is DNS-d to http://spotify.office.3months.com, making it accessible to all staff.
Technology Choices
The technology choices for this app ended up being pretty clear cut, although as with all projects I do in Rails, I do sense that I could have found a lighter approach.
In the end, the core technologies are:
- Rails 3.2
- No database
- Redis
- Hallon
- Daemons Rails
- Bootstrap for UI (customized)
- Font Awesome for Icons
When I started the project, I considered a couple of projects that I thought might make the ‘real-time’ part of the application, mostly (Sinatra and Cramp). I figured though, that as I wanted to add extra features, the drawbacks of these frameworks were going to get in the way - I opted to use Rails, accept the performance hit, in favor of not having to risk the framework getting in the way too much.
Searching
Searching was the first feature I worked on - here’s a reminder of what a search looks like:
I actually tried two different ways of searching Spotify - the first was Meta Spotify, and the second was Hallon. I ended up sticking with Hallon, as I was using this library to also play the files, however I did that Meta Spotify’s results seemed more accurate.
The way I implemented the search was actually very simple - I have a SearchController
, with a new
action which looks a bit like this:
In human terms, I perform the search, restricting the number of results to 25 for performance, and then pull a subset of the information available to me out, and return the data as JSON.
The other side of this is the Javascript - once again, quite a simple and common implementation of a typeahead search. The code for this is a bit more convoluted, so I’m going to post a shortened and annotated version of the main bit of it:
So, the combination of these two code blocks is enough to give us a typeahead search of tracks on Spotify. The search itself is trivialized by the Hallon library, and so the only real concern for us here is performance - each search takes about 500ms, and each key stroke performs a search.
Queueing Tracks
Once we have our search results, clicking on the ‘+’ icon next to the track queues it. The queue is a simple Redis list
, which I push onto from the ‘left’ side, and pop items off from the ‘right’ side. This makes the controller action to queue a track as simple as this:
Queueing is one thing, but we still need a way to interact with this queue, and play tracks through Spotify. This is where the daemons-rails
gem comes in!
Playing Tracks
‘On the Spot’ has two components. The first, we’ve discussed - it’s the Rails application, that we use for searching and queueing tracks. The second is a daemon, which runs in a loop, grabbing the next track to play, and playing it using Hallon - here’s the main bit of this code:
In a similar way to searching, much of the work is done for us. Really, all this code is doing is pulling a Spotify URI (pretty much an ID) from our Redis list (called “tracks”), storing it as the value of a Redis key (called “currently_playing”), so that we can display which track is playing, and then actually plays the track (using Hallon). Once the track has finished playing, we un-set that currently playing value.
Future Features
Really, all I’ve done so far, then, is built a web-interface around the functionality afforded by the Hallon
gem (which is itself a wrapper around Spotify’s API library, libspotify
). Despite this though, it does work exactly do design. The next thing that needs doing is the ability to control the player - right now, there is no way to pause or stop the player, except by actually logging into the Redis console and clearing the list by hand. I’d also like to add some more realtime capability using Faye or Pusher, and provide browser notifications of playing tracks.
Conclusion
This has ended up a bit more long-winded than I meant it to be, but has hopefully touched on the process I’ve gone through to build this app - in total, I’ve spent around 12-15 hours getting this to its current state, including writing this blog post, and altogether, it’s working pretty well. In the future, I hope to write further about adding realtime notifications and features to this application, so stay tuned!
-
Hallon
Hallon is a Ruby interface to the Spotify C library supporting searching, playback, and basically anything Spotify itself can do.
-
Meta Spotify
A Rubygem for searching tracks using Spotify's web services.
-
Redis
Redis is a key-value store also supporting complex data types such as lists and sets. Super cool.
-
Daemons Rails
A handy gem for generating the boilerplate required to run daemon processes with Rails.