Libraries, Playlists, & Tracks

Introduction

Whether you are working with Songbird as an extension, or by way of the Webpage API - if you want to do any sort of integration into Songbird's media player capabilities you will need to understand a few key concepts about Songbird's architecture and how to access its libraries, playlists, and tracks.

Whether you're a first-timer, or an experienced Songbird developer, using our source browser to look through the interface definitions (the .IDL files) will be an invaluable tool.

We also have automatically-generated API documentation available for all the interfaces.

Classes & Relationships

Objects representing media in Songbird are quite hierarchical.  Whether it's a library, playlist, or track - if it's conceptually part of the media library - then it must implement both the sbILibraryResource interface as well as sbIMediaItem.  If it's a playlist, then it must, in addition to the above two, implement the sbIMediaList interface.  And finally, if it's a library, then it must implement all of the above, as well as sbILibrary.

sbILibraryResource


Every library, playlist, and track (hereafter referred to as 'resources') all have the following members:
  • .guid
    • unique (string) GUIDs (globally unique IDs) that map 1:1 to the resource.
  • .created / .updated
    • Epoch timestamps indicating when the resource was created, or last updated
  • .userEditable
    • Boolean indicating whether the resource should be editable by the end user or not
Properties

Resources also have a set of properties.  These properties map to metadata describing the resource.  For tracks, they may map to the artist or album names, for libraries and playlists they may define whether the resource is hidden from the user, what type of playlist it is, etc.  Properties are accessible through a number of means:
  • .getProperty(propertyName)
    • Returns the value for the given property name
  • .setProperty(propertyName, propertyValue)
    • Sets the given property name to the given value

There are other methods available for setting multiple properties at a time, or enumerating through all the available property names.  We suggest taking a look at the sbILibraryResource API reference for more information.

Property names are in the form of a namespace URL, e.g.:
http://songbirdnest.com/data/1.0#artistName

Extensions, and web pages (via the Webpage API) can create arbitrary properties to help manage their own metadata they may wish to assign to resources, so having properties in the form of a namespace URL gives more guarantees in what could otherwise be a messy and competitive global namespace.

The standard set of properties Songbird ships with is in sbStandardProperties.h which is available for any C/C++ extension to include.  Javascript code can import (via Components.utils.import) the sbProperties.jsm which gets generated from the above .h file, and makes all of Songbird's default properties available via the form: SBProperties.<propertyName>, e.g.:

Components.utils.import("resource://app/jsmodules/sbProperties.jsm")
alert(myItem.getProperty(SBProperties.artistName));

sbIMediaItem


All sbIMediaItems provide the following members (note that there are other members available, and we recommend viewing the sbIMediaItem API reference for more exhaustive detail)

  • .library
    • The sbILibrary to which this item belongs to.  This is useful for backtracking from a given item to its owning library (for example, if you grab the currently playing item from the sbIMediacoreSequencer)
  • .isMutable
    • Whether or not this media item can be changed
  • .contentSrc
    • An nsIURI with the URL to the media.
  • .contentLength
    • The size in bytes of the content (may be 0 for streams)

sbIMediaList


Playlists are represented by the sbIMediaList interface.  There are quite a few members and methods available off this interface, so you should make sure to consult the API reference for the full list.  Because an sbIMediaList is also an sbIMediaItem, you can distinguish whether an sbIMediaItem is a list or not by examining the isList property, e.g.:
if (myItem.getProperty(SBProperties.isList) == "1") {
   alert(myItem.guid + " is an sbIMediaList");
} else {
   alert(myItem.guid + " is just a regular sbIMediaItem");
}
  • .name
    • The name of the playlist itself
  • .type
    • A string, either "simple" or "smart" depending on whether or not this is a plain playlist, or a smart playlist.
  • .length
    • The number of tracks within the playlist
  • .isEmpty
    • Boolean indicating whether or not the playlist is empty
  • .userEditableContent
    • Whether or not the contents of this list are user-editable.  See the comment in the IDL file for more descriptive text on why this is important.

Of course, the most interesting part of a playlist is getting access to its contents: the media items contained within it. 
  • .getItemByGuid(guid)
    • Given a GUID (string), returns the matching sbIMediaItem if it's within this list
  • .getItemByIndex(index)
    • Given an index into the playlist, returns the matching sbIMediaItem 
  • .enumerateAllItems()
  • .enumerateItemsByProperty()
    • Allows you to enumerate through all the items in the list that have a given property value
    • See Library Enumeration Recipe for an example
  • .enumerateItemsByProperties()
    • Allows you to enumerate through all the items in the list that match a given set of property values
    • See Library Enumeration Recipe for an example
  • .getItemsByProperty()
    • Like enumerateItemsByProperty(), except it returns an nsIArray of items instead of an enumeration
  • .getItemsByProperties()
    • Like enumerateItemsByProperties(), except it returns an nsIArray of items instead of an enumeration
  • .indexOf(mediaItem)
    • Given an sbIMediaItem, returns the index of the item within the playlist
  • .lastIndexOf(mediaItem)
    • Same as .indexOf(), except it returns the last index of the item (if it's contained multiple times)
  • .contains(mediaItem)
    • Returns true or false indicating whether or not the mediaItem is in the list
  • .getDistinctValuesForProperty()
    • Collects all the distinct values for a given property (commonly used to find out all the unique Artist Names, or Genres in a playlist) and returns an nsIStringEnumerator
    • See Library Enumeration Recipe for an example

If you'd like to manipulate the contents of the media list, there are of course routines for that too:
  • add(mediaItem)
    • Adds the given mediaItem to this list
  • addAll(mediaList)
    • Adds all the mediaItems in the given list to this list
  • addSome(enumerator of mediaItems)
    • Adds all the items provided by the given enumerator to this list
  • remove(mediaItem)
    • Removes the given mediaItem from this list
  • removeByIndex(index)
    • Removes the mediaItem at the given index from this list
  • removeSome(enumerator of mediaItems)
    • Removes all the items provided by the given enumerator from this list
  • clear()
    • Removes every item from the list

sbIMediaLists also allow you to add listeners.  These listeners are triggered depending on the flags they are added with.  For instance, you can add listeners to fire when the list itself is modified (e.g. metadata about the list), or when the list contents are modified (items are added, removed, changed, etc.).
  • addListener(sbIMediaListListener)
  • removeListener(sbIMediaListListener)

For an example on how to use the sbIMediaListListener interfaces, please see the Media List Listeners recipe.

sbIMediaLists can also be filtered and searched upon by creating sbIMediaListView objects from them.  An sbIMediaListView of a list is a way to filter based on properties, or search by full-text-search filtering.  To create an sbIMediaListView, you can simply do myList.createView().  Please read our further overview on sbIMediaListViews and how you can filter/search lists/libraries and present them to the end-user.

sbILibrary


An sbILibrary is derived from an sbIMediaList and is really just a special case of lists.  One major difference is that while a list can contain the same sbIMediaItem multiple times (since it is just an ordered playlist), a library can only contain unique items, and is inherently unordered.

The user will always have one main library and at least one library per device (MTP/iPod/etc.).

As usual, consult the sbILibrary API reference for a full list of the interfaces with more complete comments.  Some of the important methods to know that sbILibrary items implement are:
  • .createMediaItem(URI)
    • Given an nsIURI to some media, create a new media item to represent it
  • .createMediaList(type)
    • Creates a new media list of the given type (either "simple" or "smart")
  • .copyMediaList(type, sourceMediaList)
    • Copies the given media list to a new media list
  • .getMediaItem(GUID)
    • Given a GUID, returns the matching mediaItem owned by this library
  • .batchCreateMediaItems()
  • .batchCreateMediaItemsAsync()
    • More efficiently creates media items in batch mode (the first is a synchronous version, the latter is the asynchronous version)

Songbird provides an sbLibraryUtils JSM which you can import with:

Components.utils.import("resource://app/jsmodules/sbLibraryUtils.jsm");

You can then access things like the mainLibrary via:

alert(LibraryUtils.mainLibrary.length);

For more information, please see our JSM documentation for sbLibraryUtils.jsm.

Tag page
You must login to post a comment.