Songbird Media Player Integration for Web Pages, a Compendium

14 June, 2008

What is Songbird?

Songbird is an iTunes-style music player that contains an integrated web browser. Songbird detects rich media on pages you visit and integrates them into itself in a number of ways: making them navigable through a "web playlist" reflecting the current page, remembering them in a "web media history" that you can browse and search, and, finally, providing a bridge between the music player and the web browser itself that allows web pages to interact with the playing song and the user's music library.

Why does Songbird matter?

Songbird is to iTunes what Firefox is to Internet Explorer: it provides an open source alternative to an application built as part of a vendor's extremely successful lock-in strategy. And, following in Firefox's footsteps, Songbird aims to introduce a raft of technical innovations into a stagnant space.


The bird. Shown here in a rare non-farting moment.

While iTunes (and especially the iTunes store) revolutionized the music industry on first release, its rate of innovation is restricted by Apple's ability to imagine and implement new features and, even more tightly, by the constricting legal ties the company has woven with the media conglomerates that provide its content. Songbird, on the other hand, is trying to offer an open platform for anyone to build their own innovative applications or competing business models. If they succeed, these lowered boundaries to participation will mean that Songbird's feature count and available content options will zoom past iTunes', inevitably bringing along an ever-growing number of users and, eventually, breaking Apple's monopoly and forcing them to scramble to compete — just as Firefox has done with Internet Explorer.

What can I do with it?

So, in what ways is Songbird open? What can you do with it as a developer? Well, just like Firefox, Songbird is open in a number of ways. First, the code for the player itself is available for download and licensed under the GPL. This means you can modify it, use it in your own applications, print it on your school binder, whatever you want. Secondly, Songbird has a plug-in architecture against which you can develop. The Songbird team calls applications written on this architecture Add-ons and they have access to everything from the player's appearance (for building skins) to the actual data and UI of the application. Finally, and most importantly for us here, Songbird provides web pages with a javascript API that allows them access to the app's sophisticated playback interface and, with their permission, the user's media library and custom playlists. Since this last is by far the easiest to get started with, I'll spend the rest of this post focusing specifically on it.

Setting up a Songbird Javascript Development Environment

One of the hardest parts of starting development in any new environment is getting all the pieces in place to successfully write and run your first line of code. This is especially true in complex runtime environments like javascript hosted in a web page running against APIs in a rapidly developing client. Here are the steps I followed to get there:

  • Download a nightly build. At the time of this writing, 0.6 was the latest hotness, but things are moving rapidly.
  • Get Firebug lite. Like most Javascript developers, I've become increasingly dependent on Firebug since its introduction. Being able to test out code in its interactive shell and navigate the resulting objects is priceless. Heck, even just being able to log information to the console rather than having to dismiss an endless parade of alert statements is worth the price of admission alone. Unfortunately, because of Songbird's rapid pace of development, there isn't currently a version of Firebug that is compatible with 0.6 (if you come from the future, visit Firebug's page on the Songbird add-on site to see if things have changed). Thankfully, there's another version of Firebug that can reside in the DOM of any given page. It doesn't have all the niceties we'd want (like object navigation) and it's access to the Songbird-specific javascript APIs we'll be spending our time with can be a bit...err...intermittent, but at least it provides a console for logging and some ability to inspect our objects. Once you've downloaded firebug, stick the directory somewhere in your project and create an HTML file with the following in the head tag:

    <script language="javascript" type="text/javascript"
    src="/path/to/firebug/firebug.js"></script>

    You should also set the debug attribute in your opening html tag to "true". Now, when you open your page in Songbird, it'll have a mini version of Firebug running at the bottom of its window. You can log to it and interact with objects (though limits and quirks will abound).

Songbird's Model of the World


Songbird's viewer window explained (full-size version).

The purpose of the Songbird webpage API is to provide the javascript running on a particular page with access to the media-player side of the application. Through it your page can track changes in the currently playing song, manage the "web playlist" (a small iTunes-style song browser that shows up underneath the current web page), and access song listings and metadata for the user's local music library, including reading and creating local playlists — you can even download songs directly to the user's computer. Pretty much the only thing you can't do is delete files.

Songbird presents three main abstractions for working with this functionality: Libraries, Media Lists, and Media Items. Let's start at the bottom with Media Items and work our way up.

Media Items == Songs

A Media Item is a single song or video in your Songbird library (at this point, I'm just speculating about the video part, though the generic name is certainly tantalizing and I know that Songbird does have some form of video support; however, I've only worked with songs, and from here on I'll assume that a Media Item is really a song). Media Items provide access to a raft of metadata such as "trackName", "artistName", "duration", etc. See the full list of Media Item properties for everything that Songbird makes available. You can read these attributes and set them. Interestingly, metadata properties are namespaced so you can create your own solely for use by your application, or even attempt to get a community of developers to standardize around new attributes for a particular domain.

One important thing about Media Items is that they don't necessarily have to correspond to a song with a locally available media file. Just as your iTunes library can contain songs whose actual mp3 files are elsewhere (like on an external backup drive), Media Items can be associated with files that are not currently available or with no file at all. Unlike iTunes, Media Items in Songbird can also be associated URLs that point at online mp3s.

Media Lists == Playlists

The next step up the ladder is Media Lists. These, as you might expect, are collections of Media Items, i.e. playlists. They have a name which is a handle for finding them (and also what shows up in the app's sidebar if you add them to the Main Library). You can find out which Media Items belong to a Media List and you can add and remove them. Media Lists are ordered stacks, so there's some functionality for managing the position, uniqueness, and suchlike of individual Media Items and for iterating through the full set.

Libraries

At the top of this whole shebang are Libraries. Libraries represent the permissions and interaction scope associated with a Media List or group of Media Lists, i.e. in which part of the application they'll be visible and which chunks of code will have access to them. There are three types of Libraries in Songbird — the Main Library, the Web Library, and the Site Library — and one other entity (the "Web Playlist" mentioned above) that sits in the same spot as a Library and behaves almost exactly like a Library, but isn't technically a Library. Things will get clearer quickly if we talk about the purpose of each type of Library, so let's dive right into that.

Libraries: the Main Library

First up, we've got the Main Library. The Main Library contains all the Media Items on the user's computer. Remember, since Songbird can provision audio for Media Items from public URLs and can include local Media Items for which the file is not currently available (the Missing Backup Drive scenario), this is not limited to files actually "physically" present. Reasons to talk to the Main Library include: wanting to create a new playlist on the user's computer that will be available after they browse away from your site, wanting to see what songs the user already has in order to make content recommendations, getting a list of all the local playlists a user has created and what songs are in them, etc. By default websites are blocked from accessing the Main Library at all unless the user has changed their "Web Integration" preferences to allow general access or to allow it for your website in particular. If you attempt to access the Main Library of a user who has limited access to their Main Library, Songbird will prompt them to permit or deny the action; the javascript API includes callbacks to make your code aware of the user's response to this prompt.

Libraries: the Web Library

Next up, we've got the Web Library. The Web Library contains all the Media Items Songbird has extracted from the webpages the user has visited. When you navigate to a URL that contains links to music files, Songbird discovers these links and gives you an iTunes style playlist representation of them at the bottom of your window (the Web Playlist). The Web Library is everything that's ever shown up in this playlist. It's every song from every webpage the user has ever visited within Songbird. This list of songs is made available to the user as the "Web Media History" and is an incredibly useful feature — if you spend any significant amount of time reading mp3 blogs or browsing band sites your Web Library will rapidly become populated with most of the music you've ever heard about, even in passing. This makes it an extremely rich collection to search against and idly browse. I can only imagine all the cool apps you could build if you had access to the entire mp3 blog browsing history of your users...obviously recommendations (for both music and blogs) come to mind, but you could probably also build some kind of very kick ass client-resident distributed spidering operation, or something else extremely neat that I can't think of off the top of my head. As you'd expect, the Web Library is under exactly the same access restrictions as the Main Library.

Libraries: the Web Playlist

Now we start to move into the Libraries that belong more to our individual websites than to the users themselves and over which we therefore have more control. The first and most visible of these is the Web Playlist. In the normal course of events (i.e. while browsing sites that aren't cool enough to use the Songbird API), the Web Player simply reflects any mp3s or other media files Songbird happened to find on the page. However, with the API we can control just about every aspect of the Web Playlist from the tracks that populate it to what pieces of data show up in each of its columns. I mentioned above that the Web Playist is not, strictly speaking, a Library. This means that it doesn't offer quite the same API as other Libraries — it only contains a single Media List; it doesn't have its own access controls separated from those of the Media List assigned to it; etc. — however, I include it in this list because, in the javascript, it lives at the root of the 'songbird' namespace as a sibling to the other Libraries and it offers an API that is largely (though not entirely) parallel to the others.

Libraries: Site Libraries

Lastly, we come to Site Libraries. Unlike the other Libraries we've covered so far, Site Libraries don't directly control the display of tracks to the user. Instead, they are simply an application-specific namespace for storing Media Lists. In other words, they let your javascript build Media Lists that are available only to users visiting particular pages on your domain (controlled via a scoping mechanism much like the traditional robots.txt syntax). Once you've got a Media List safely inside your own private Site Library, you can then display it in a Web Playlist, save it to the user's Main Library, or simply keep it invisible and use it to swap out the currently playing song. In fact, if you don't actually use a Site Library to manipulate any part of Songbird's UI (for example if they're just a convenient way to store your app's internal data), you don't even need the user's permission to create them. Site Libraries are a little harder to grok than the other varieties since they lack visible representation, but you'll quickly get used to working with them as they're the main place you'll be storing all the Media Lists you build. If you're still confused as you come away from this paragraph, you can just think of Site Libraries as a private place to store the Media Lists you compose without having to display them to the user in any way.

Some code samples

Let's make this whirlwind conceptual tour more concrete by looking at some examples. I'll show you the code to accomplish some basic tasks and then explain it in terms of the concepts I've outlined above.

Putting songs in the Web Playlist


songbird.setSiteScope("", "/");
var library = songbird.siteLibrary;
var myMediaItem = songbird.siteLibrary.createMediaItem("http://www.example.com/track.mp3");
myMediaList.add(myMediaItem);
songbird.webPlaylist.mediaList = myMediaList;

I cribbed this example from the Songbird wiki. It simply creates a media item from an mp3 URL, assigns the item to a media list that is scoped to the domain of the current page, and tells songbird to display the media list in the web playlist. The song won't actually appear anywhere visible to the user until the last line of code in this sample. Once the web playlist receives the media item, it'll scan the URL for metadata and fill in the track display based on what it finds.

Set a property on a media item


var myMediaItem = songbird.siteLibrary.createMediaItem("http://www.example.com/track.mp3");
myMediaItem.setProperty( "http://songbirdnest.com/data/1.0#artistName", "The Rolling Stones" );

If you set a property before adding the media item to a list and displaying it, Songbird will trust your metadata assignment and not override it based on the results it finds on the attached mp3. There are parallel methods for getting the values of any already set properties. You can set properties on media lists in the same way.

Download a media items' file to the user's computer


var library = songbird.siteLibrary("", "");
var mediaItem = library.createMediaItem("http://path/to/item.mp3");
songbird.downloadItem(mediaItem);

In addition to providing access to the various libraries, the songbird object allows you to do a whole raft of useful things such as download an mp3 from the web into a local media item (as shown here), getting access to information about the currently playing track, controlling which track is playing, etc.

Get all the local playlists


var mediaLists = songbird.mainLibrary.getPlaylists();
var results = [];
while(mediaLists.hasMoreElements()) {
var mediaList = mediaLists.getNext();
results.push(mediaList);
}
return results;
};

This code asks the main library for a list of its playlists. When that first line of code runs, requesting access to the main library for the first time, Songbird will prompt the user for permission. In order to iterate through the results of getPlaylists, we have to call the special enumeration helper, hasMorePlaylists. This is a common pattern with collections of Songbird objects, there's often custom enumeration code that be somewhat counter-intuitive compared to standard array iteration.

Additional Resources

These examples only scratch the surface of what you can do with songbird. For more examples and more documentation, visit the Songbird webpage-api docs and the Songbird wiki entry on Webpage API integration.

The Songbird team hangs out at #songbird on irc.mozilla.org. They are quite friendly and open to helping out if you're confused or run into issues. I'd also like to thank them specifically for answering my large raft of questions as I was learning this API. This guide wouldn't have been possible without them.

Tagged: , , , , , ,