Congratulations! You've stuck with us all this way through to releasing Songbird 1.0. We know it's been a sometimes-painful and bumpy road on this way to our big release... but we wouldn't be where we are today without your hard work.
That being said... we've got this one last speedbump, so we hope you'll bear with us through updating your extensions for Songbird 1.0.
(Gotta start with the easy stuff ;-)) First off, go ahead and bump your maxVersion in your extension's install.rdf to 1.0.*:
<em:targetApplication> <Description> <em:id>songbird@songbirdnest.com</em:id> <em:minVersion>0.7.0</em:minVersion> <em:maxVersion>1.0.*</em:maxVersion> </Description> </em:targetApplication>
Depending on the scope of your extension, you may want to set the minVersion to be 1.0.0 as well. For instance, the new Media Core API has some considerable changes (detailed below). If you want to drop support for the old gPPS (PlaylistPlaybackService) API, then you'll want to bump up the minVersion to be 1.0.0. (Rest assured, older Songbird versions will still be able to download the last working compatible version for their Songbird client through the add-ons site)
The biggest, and widest impacting, change in Songbird 1.0 is undoubtedly the new Media Core API. We've moved from using VLC to GStreamer, and in the process completely rewrote the way extensions can observe, and be informed of Media Core events such as track changes, playback status, etc.
The IDL files describing and documenting the new Media Core API can be found in the mediacore component in OpenGrok. Previously we had a hodgepodge of interfaces hanging off of the PlaylistPlaybackService, now we have a considerably more structured interface. The root of everything interesting starts with the sbIMediacoreManager. From this object, we can get references to all the various sequencers, balance controls, playback controls, etc. that we'd need to invoke playback control, observe currently playing views and items, and attach listeners. We recommend taking a look through the IDL file for sbIMediacoreManager to familiarise yourself with the organisation and hierarchy. We've highlighted some of the most often used members and functions here below:
.png)
Listening for media core events is now greatly simplified. You simply create an object that implements the sbIMediacoreEventListener interface, which is composed simply of one function:
void onMediacoreEvent(in sbIMediacoreEvent aEvent)
Once your listener is attached, its onMediacoreEvent member method will be called for every media core event generated by the Media Core Manager, or one of its members (e.g. sequencer, the media cores themselves, etc.). onMediacoreEvent is passed an sbIMediacoreEvent. This event's interface has 5 key members:
For an example of how to add a listener that observes track changes, please see our Media Playback Recipe.
Previously, any add-on or any site utilising the Webpage API that created properties would have these properties default to being user visible. This introduced a whole mess of properties that eventually cluttered up the "column picker" considerably. We put a lot of work into reworking the column selection widget for playlists and libraries, and in an attempt to make these lists of properties cleaner, we've defaulted to having new properties NOT be user visible anymore. This was done in bug 12246, if you care for the details.
You can, of course, still expose your custom properties to being user visible simply by setting the sbIPropertyInfo object's userViewable variable to be true.
For add-ons wishing to overlay into the metadata editor (a.k.a. Track Editor), we've cleaned up some of the XUL and added IDs to faciliate overlaying and extending the track editor. This work was done in bug 12715 and bug 12713, and you can see the exact changes committed to the trackEditor overlay for more details.
You should now be able to extend trackEditor.xul by overlaying and adding tab panels for your own custom properties. Please see rcw003's new LyricMaster add-on for an example of how he utilises this to integrate lyrics into the Track Editor.
A number of display pane enhancements went into this release in an effort to improve the user experience and add some more features for add-on developers.
Inspired by atrieu's Display Pane Buttons add-on, we've built in similar functionality for showing/hiding display panes. While this is no different from toggling display panes being visible/hidden from the menubar, this does mean that users are more likely to unload/load your add-ons. If you have an add-on that responds to media playback state, you might already be listening for media core events such as track changes, etc. To ensure your add-on properly initialises when being hidden/re-shown, you may want to check the currently playing state from your initialisation/onLoad routine and act accordingly. For most add-ons this is as simple as doing the following:
if (typeof(gMM) == "undefined")
var gMM = Cc["@songbirdnest.com/Songbird/Mediacore/Manager;1"]
.getService(Ci.sbIMediacoreManager);
// Check to see if we're already playing something
if ((gMM.status.state == Ci.sbIMediacoreStatus.STATUS_PLAYING) ||
(gMM.status.state == Ci.sbIMediacoreStatus.STATUS_PAUSED) ||
(gMM.status.state == Ci.sbIMediacoreStatus.STATUS_BUFFERING))
{
var currentItem = gMM.sequencer.currentItem;
// Do something with the media item
}
For add-ons which can be installed into different display panes, it can be helpful to determine which display pane you are currently being shown in. To do this, we use the display pane manager (sbIDisplayPaneManager):
var displayPaneMgr = Cc["@songbirdnest.com/Songbird/DisplayPane/Manager;1"] .getService(Ci.sbIDisplayPaneManager); var dpInstantiator = displayPaneMgr.getInstantiatorForWindow(window); var myDisplayPane = dpInstantiator.displayPane; // Do something neat
Once you have the display pane, you can check its ID to see if it's one of the following:
This is a feature for add-ons, like mashTape, that wish to utilise as much space as possible. For add-ons that may switch between different states (like mashTape with its News, Artist Info, Photo, and Video tabs), you can now embed XUL tab elements directly into the display pane header.
The first step is grab the display pane as covered previously. You can then invoke the displayPane.enableTabs() method and pass it a pointer to your XUL tabpanels that you've defined. Assuming you've got some XUL like:
<tabbox flex="1" orient="horizontal" id="my-tabbox">
<tabpanels flex="1" id="my-tabpanels">
<hbox><label value="Hello" /></hbox>
<hbox><label value="World" /></hbox>
</tabpanels>
</tabbox>
To enable tabs to hook up to these tabpanels, you can then run some Javascript like so:
var tabpanels = document.getElementById("my-tabpanels");
myDisplayPane.enableTabs(tabpanels);
To add tabs to the tabbar, you simply then run:
myDisplayPane.addTab("Tab1");
myDisplayPane.addTab("Tab2");
... and you will have hooked up the two tabs to the two tabpanels defined in your XUL.
If you utilise HTML iframes in your add-on, you'll want to make sure your include the current Feathers' html.css file so you can pick up the CSS styles from the Feather so your add-on won't look out of place. You can do this by simply including in your HTML iframe source.
<link type="test/css" rel="stylesheet" href="chrome://songbird/skin/html.css">
| File | Size | Date | Attached by | |||
|---|---|---|---|---|---|---|
| dp_button.png No description | 15.03 kB | 13:34, 20 Oct 2008 | stevel | Actions | ||
| new media core diagram (1).png Media Core Manager Diagram/API | 109.91 kB | 11:31, 14 Oct 2008 | stevel | Actions | ||
| ribbon-cutting-bird.png Ribbon Cutting Bird | 38.61 kB | 09:25, 14 Oct 2008 | stevel | Actions | ||
| Images 3 | ||
|---|---|---|
Media Core Manager Diagram/APInew media core diagram (1).png | Ribbon Cutting Birdribbon-cutting-bird.png | |