When a media page is loaded, it is passed the current MediaListView. This object is controlled by the page. Media pages are registered in an install.rdf file to work with media lists that have certain properties. For example, a media page can be set to support all media lists (the default), to target only media lists with a certain customtype (for example, "download"), or even to target a media list with a given GUID.
Certain other operations will call methods on the sbIMediaPage interface, such as dropping a selection onto a media page, attempting to highlight the current track, or initiating playback. Most media pages will include a <sb-playlist/> object which should be passed any calls you do not handle specially. The default media page created by the extension wizard will do this by default.
As usual, the Songbird Developer Tools Add-on greatly simplifies the process for developers. Using the Extension Wizard (accessed via the Tools menu under Create New Extension), you can create the skeleton/framework for your media page quickly and easily. The Extension Wizard takes care of setting up your install.rdf media page registration, and creating the basic "Hello World" media page.
When creating a new media page, you must add a <mediaPage> block to the install.rdf for that extension. It must include a <contentTitle/> and a <contentUrl/> which define the title shown in the menu and the document to load. It may optionally also include any number of <match/> elements.
Because some media pages may be specific to certain kinds of playlists, you may provide any number of <match/> elements to target particular kinds of lists. You can target "type", "customtype" or any SBProperty of the MediaList within the view.
<match>type:simple</match> | Match any "simple" media list. |
<match>customtype:downloads</match> | Match only the downloads list. |
<match>type:simple myExtensionProperty:someValue | Match simple media lists which have a custom property added by your extension. |
Because media pages can come from many sources, we have provided a mechanism to allow extension developers to specify that a particular MediaList would like to "opt out" of the generic media lists and only support custom media lists specially targetting them.
We have specified that any <mediaPage> rule which has no match rules, or any match rule which only targets the "type" property of a media list can be excluded by setting the "onlyCustomMediaPages" property of the list to true.
The example uses a mediaList with these properties:
mediaList.type == "simple" && mediaList.customtype == "downloads"
| <match/> rule | SBProperties.onlyCustomMediaPages | result | reason |
| (none provided) | false | matches | matches all |
| (none provided) | true | does not match (opt-outable rule) | opted out |
| type:simple | false | matches | same type |
| type:simple | true | does not match (opt-outable rule) | opted out |
| customtype:download | false | matches | same customtype |
| customtype:download | true | matches (not opt-outable) | same customtype |
| type:simple customtype:other | true/false | no match | does not match customtype |
If there are multiple <match/> rules, any rule which completely matches the list will cause the page to appear in the menu for that item.
Media pages can be implemented in either XUL or HTML. The easier method, and the one covered here, is implementing them via XUL. At its core, a media page is as simple as the following (as excerpted from the standard media-page.xul generated by the Extension Wizard)
<page
id="mymediapage-media-page"
title="My Media Page"
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns:rdf="http://www.w3.org/TR/WD-rdf-syntax#"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="window.mediaPage.onLoad();"
onunload="window.mediaPage.onUnload();"
windowtype="Songbird:MediaPage"
>
<sb-playlist id="playlist"
flex="1"
enableColumnDrag="true"
persist="column-list column-widths"
editable="true"
hidefilters="true"
/>
<!-- Page Controller.
Registers a window.mediaPage object implementing the
sbIMediaPage interface.
-->
<script type="application/x-javascript" src="media-page.js" />
</page>
The above media page is a simple recreation of the standard playlist view. You can see it defines a <page/> element of windowtype Songbird:MediaPage, and adds onload & onunload handlers to call the media page registration.
The media page should also define a window.mediaPage object which implements the sbIMediaPage interface. The above XUL implements this in the media-page.js file. The three methods the media page should implement are highlightItem(), canDrop(), and onDrop() which implement the behaviour the media page should take when items are highlighted or dropped.
highlightItem() is called when the item should be highlighted, e.g. when the user clicks on the playing track in the faceplate to jump the playlist to the currently playing track.
canDrop() is called when something is dragged on top of the tabbrowser tab (note this is the tab selector underneath the web navigation bar)
onDrop() is called when something is actually dropped onto the tabbrowser tab.
The following code is the media-page.js file referenced above:
// Shorthand
if (typeof(Cc) == "undefined")
var Cc = Components.classes;
if (typeof(Ci) == "undefined")
var Ci = Components.interfaces;
if (typeof(Cu) == "undefined")
var Cu = Components.utils;
if (typeof(Cr) == "undefined")
var Cr = Components.results;
/**
* Media Page Controller
*
* In order to display the contents of a library or list, pages
* must provide a "window.mediaPage" object implementing
* the Songbird sbIMediaPage interface. This interface allows
* the rest of Songbird to talk to the page without knowledge
* of what the page looks like.
*
* In this particular page most functionality is simply
* delegated to the sb-playlist widget.
*/
window.mediaPage = {
// The sbIMediaListView that this page is to display
_mediaListView: null,
// The sb-playlist XBL binding
_playlist: null,
/**
* Gets the sbIMediaListView that this page is displaying
*/
get mediaListView() {
return this._mediaListView;
},
/**
* Set the sbIMediaListView that this page is to display.
* Called in the capturing phase of window load by the Songbird browser.
* Note that to simplify page creation mediaListView may only be set once.
*/
set mediaListView(value) {
if (!this._mediaListView) {
this._mediaListView = value;
} else {
throw new Error("mediaListView may only be set once. Please reload the page");
}
},
/**
* Called when the page finishes loading.
* By this time window.mediaPage.mediaListView should have
* been externally set.
*/
onLoad: function(e) {
// Make sure we have the javascript modules we're going to use
if (!window.SBProperties)
Cu.import("resource://app/jsmodules/sbProperties.jsm");
if (!window.LibraryUtils)
Cu.import("resource://app/jsmodules/sbLibraryUtils.jsm");
if (!window.kPlaylistCommands)
Cu.import("resource://app/jsmodules/kPlaylistCommands.jsm");
if (!this._mediaListView) {
Components.utils.reportError("Media Page did not receive " +
"a mediaListView before the onload event!");
return;
}
this._playlist = document.getElementById("playlist");
//
// TODO: Do something interesting here!
//
// Get playlist commands (context menu, keyboard shortcuts, toolbar)
// Note: playlist commands currently depend on the playlist widget.
var mgr =
Components.classes["@songbirdnest.com/Songbird/PlaylistCommandsManager;1"]
.createInstance(Components.interfaces.sbIPlaylistCommandsManager);
var cmds = mgr.request(kPlaylistCommands.MEDIAITEM_DEFAULT);
// Set up the playlist widget
this._playlist.bind(this._mediaListView, cmds);
},
/**
* Called as the window is about to unload
*/
onUnload: function(e) {
if (this._playlist) {
this._playlist.destroy();
this._playlist = null;
}
},
/**
* Show/highlight the MediaItem at the given MediaListView index.
* Called by the Find Current Track button.
*/
highlightItem: function(aIndex) {
this._playlist.highlightItem(aIndex);
},
/**
* Called when something is dragged over the tabbrowser tab for this window
*/
canDrop: function(aEvent, aSession) {
return this._playlist.canDrop(aEvent, aSession);
},
/**
* Called when something is dropped on the tabbrowser tab for this window
*/
onDrop: function(aEvent, aSession) {
return this._playlist.
_dropOnTree(this._playlist.mediaListView.length,
Ci.sbIMediaListViewTreeViewObserver.DROP_AFTER);
}
} // End window.mediaPage
| Images 0 | ||
|---|---|---|
| No images to display in the gallery. |