A friend of mine introduced me to heavy metal in junior high with an audio cassette recorded off of Megadeth’s Youthanasia CD. Up to that point my personal music listening habits had consisted of 100% “Weird Al” Yankovic; I hated pretty much everything that my parents listened to or that was played on the radio, and was ready to try anything new.

This was the early 90s, I was a teenager, and heavy metal still had the stigma of being the preferred music of malcontents, stoners, and drop-outs. I’m embarrassed to admit I was a little scared when I first slid the tape into my stereo. I had no idea what to expect. Would it subliminally brainwash me into worshipping Satan? Would it expose my mind to nightmarish visions that would ultimately lead to criminal activity and drug addiction?

Needless to say, my innocent child-like mind survived the experience. I thought it was the greatest music I had ever heard in my life. I hit the mall at lunch the next day and spent some of my saved-up allowance to buy my own copy of Youthanasia on CD.

My heavy metal collection remained stagnant until a few years later when MP3s started becoming more mainstream and I discovered Hotline. Now that I think about it, I suppose my love for heavy metal did eventually lead to a life of cybercrime. After a few years of illicitly growing my library, several well-publicized cases of little girls and old ladies being fined hundreds of thousands of dollars for downloading MP3s finally convinced me that it was time to “go straight.” I wrote down my favoride artists and albums that I had discovered through my illegal activities, trashed my entire MP3 collection, and found myself once again staring at my Youthanasia CD—the only heavy metal album still in my possession. I hit Half.com (a marketplace for buying used CDs and books that was later purchased by eBay) and started the slow process of rebuilding my library.

Back then, there weren’t any services like Rdio, Spotify, or Pandora that could satisfy someone with non-mainstream tastes in music. There were no online stores through which you could legally purchase digital music. If you wanted to listen to anything other than The Spice Girls or Britney Spears and you didn’t want Lars Ulrich breaking down your door and confiscating your hard drive in the middle of the night, you bought CDs.

Consequently, this influenced the way I listened to my non-mainstream music—to entire albums at a time. I’d pop a CD into my stereo or Discman, slap my headphones onto my head, and get lost in the 40 to 70 minute sonic masterpiece in the way that the original artist had intended. Sure, I probably could have picked a few favorite tracks and cut a mix tape (CD burners were still prohibitively expensive), but for the most part I experienced heavy metal as full-length albums.

To this day, I still purchase physical CDs of music and rip them myself whenever I can. I do occasionally buy DRM-free digital music (perhaps a bit more often now that I’ve discovered the vast selection of heavy metal on Band Camp), but even when I do I’ll still buy whole albums with the intent to listen to them that way. I meticulously maintain the embedded tags on all of my music to the point of anal retentivity, and have very specific directory and naming conventions for its storage. I recently moved my whole collection to “the cloud” by copying it into my Dropbox folder, figuring this should give me options to listen to my music on mobile devices or the web even when I’m not physically carrying it with me.

That’s when I discovered the sad state of Dropbox music players. I gave up entirely on mobile, opting instead to buy a phone with enough storage to just take my collection with me. There are a few self-hostable web-based players that integrate with Dropbox, the most popular of which seems to be Cloudtunes. Sadly, it requires a Facebook account to log in (it also supports Last.fm, but you can no longer get API keys from them). No thanks. There’s cozy-music which is built on top of something ominously called the “Cozy Platform.” I don’t really want to wrap my mind around a whole platform… just a simple music player. I think I came across a few others as well, which were either too simple, too bloated, or didn’t fit my folder-album based music listening use case in a convenient way.

So I did what any self-respecting software engineer would do. I built my own!

My goal (which I feel I have achieved) was to build a super-simple, super lightweight music player that could simply list album folders from Dropbox, then play the entire album when you clicked one. I’ll cover some of the technical details in the rest of this blog post. The full source code is up on Github, or you can check out the live implementation at music.sitosis.com.

Challenge 1: Dropbox Integration

This ended up being surprisingly simple once I found dropbox-js. It’s a Javascript library that abstracts away the whole Dropbox API, and even works entirely client-side. Authenticating is as simple as this:

client = new Dropbox.Client key: 'my-api-key'
client.authenticate (error) ->
  if client.isAuthenticated()
    # go crazy!

Reading directories is even simpler:

client.readDir path, (error, entries) ->
  # entries contains all of the files found at the given path

Challenge 2: Playing Music

At first I thought I was going to have to get fancy—when you retrieve a binary file (such as an MP3) using dropbox.js, you get it in the form of a byte array. I worried that I would have to get fancy with streaming byte arrays to the HTML5 Web Audio API, or somehow convert the byte array into a data url to feed into an audio tag, but it turned out there was a much simpler way to achieve what I wanted.

The Dropbox API can generate temporary public links to files in your Dropbox folder which can be accessed without authentication, so my player simply generates links for all of the songs within an album folder and feeds them to bbplayer, an HTML5 audio player that provides braindead-simple playlist support on top of standard audio tags. In pseudocode, it looks something like this:

when user clicks an album {
  dropbox.readDir(albumDir, callback(songs){
    stop and delete any existing players
    audioEl = generate new bbplayer with audio element
    for(song in songs){
      audioEl.sources.push(dropbox.makeUrl(song))
    }
    inject audioEl onto page
    play it
  })
}

That’s pretty much the core functionality right there. There’s some extra garnish to make sure old players are retired when a new album is clicked, checking for cover art in the album directory to use as a background image, and error handling, but it’s all there to support this.

Challenge 3: Styling and Layout

I hate doing layout and styling stuff with a passion. I decided to use Bootstrap to minimize the suffering, but even that is a stretch. Who wants to learn about grid layout systems and all those crazy aria attributes? Yeesh. Fortunately I found Bootbox which takes a lot of the pain out of showing alerts and dialogs to the user.

A big part of collecting albums is enjoying the cover art—as a kid I’d flip through the booklets as I listened. I include a Folder.jpg file along with each album directory in my collection (it saves space, as opposed to embedding the same image into the metadata of every song). Usually I cheap out and just grab a pre-scanned version from the web, but there are a handful of albums in my collection that are obscure enough that I had to scan my own cover art in order to meet my minimum size and quality requirements. The player I built will grab the first jpg or png file it finds in the directory you’re playing and blow it up into the background image.

That’s about it. I wrote it over the course of two or three evenings and have reached that magical combination of being sufficiently pleased with the final product for my own use and sick enough of working on it that I’m calling it done for now. If you find any problems or can think of improvements you’d like to see, feel free to open issues on the Github page, or even make contributions yourself (either pull requests directly to my repo, or by starting your own fork).

As an aside, I never lost my love for “Weird Al” Yankovic. I just listen to this other stuff I own from time to time now as well.