[[PlayerToc(flash)]]
= JW Player: Building Plugins =
Version 4 of the JW Player introduced an API architecture which allows developers to build plugins to the player. Example applications are ad serving, search engine integration and data analytics. [http://www.longtailvideo.com/addons/plugins LongTailVideo.com] serves as a distribution platform for the plugins. This tutorial is aimed at Flash developers who have a solid understanding of Actionscript 3 and want to start developing plugins.
== What is a plugin? ==
A JW Player plugin is a separate SWF file, written in Actionscript 3, which is loaded by the player at runtime. Plugins integrate seamlessly with the player, both in terms of coding (through the [wiki:FlashApi API]) and graphics (stacked on top of the player). Plugins are loaded into player by setting the [wiki:FlashVars#External plugins flashvar]. For example, if you wanted to load two plugins named '''advertising.swf''' and '''delicious.swf''', the corresponding flashvar would be ''plugins=advertising,delicious''. An SWFObject embed code would then look something like this:
{{{
}}}
By default, plugins are hosted at '''plugins.longtailvideo.com''' (using Amazon S3). This single-repository architecture enables every player on the internet (>1.000.000) to directly load your plugin by setting the [wiki:FlashVars#External plugins flashvar]. For testing or internal purposes, plugins can be set to load from other locations (by setting the variable ''basedir'' in [browser:trunk/as3/com/jeroenwijering/player/Player.as Player.as]).
== Getting started ==
You can develop plugins using the free [http://www.adobe.com/products/flex Flex SDK] or [http://www.adobe.com/products/flash Flash]. We have a handy [changeset:HEAD/trunk/sdk?old_path=/&format=zip plugin development SDK] you can use to quickly start building plugins. It contains a copy of the [/testing testing page], some plugin templates and the ''com.jeroenwijering.events'' actionscript package (the player API). Since the [http://www.adobe.com/products/flex Flex SDK] is free and cross-platform, all you need to start building plugins is a text editor!
'''Note:''' If you're looking to develop a plugin in order to serve ads in the JW Player, please [http://www.longtailvideo.com/about/contact-us contact us] beforehand. We have a special SDK for advertisers and advertising networks.
Each plugin should implement [browser:trunk/as3/com/jeroenwijering/events/PluginInterface.as com.jeroenwijering.events.PluginInterface]:
{{{
package com.jeroenwijering.events {
import flash.events.Event;
public interface PluginInterface {
function initializePlugin(vie:AbstractView):void;
}
}
}}}
The initializePlugin() function allows the player to give the plugin a reference. The player automatically calls this function after it has loaded the plugin. The ''view'' parameter is a reference to the players' [browser:trunk/as3/com/jeroenwijering/player/View.as View] object. The view allows you to read the config and playlist varilables, send events to the player and listen to events broadcast by the player. A complete overview can be found on the [wiki:FlashApi API overview page].
Although any SWF implementing the ''initializePlugin()'' function can be loaded, the recommended way of developing an plugin is by creating a class which extends the '''Sprite''' or '''Movieclip''' class. The most basic plugin to write would look something like this:
{{{
package {
import flash.display.Sprite;
import com.jeroenwijering.events.*;
public class Helloworld extends Sprite implements PluginInterface {
/** Configuration list of the plugin. **/
public var config:Object;
/** Reference to the JW Player View object. **/
private var view:AbstractView;
/** This function is automatically called by the player after the plugin has loaded. **/
public function initializePlugin(vw:AbstractView):void {
view = vw;
view.sendEvent(ViewEvent.TRACE,"Hello World!");
};
}
}
}}}
To compile this plugin in Flash CS3, copy-paste the code in a new textfile called Helloworld.as. Next, create a new FLA file (with Actionscript 3.0 / Flash Player 9 support) and set its ''Document class'' property to point to your new .as class.
== Interacting with the player ==
The [browser:trunk/as3/com/jeroenwijering/player/View.as View class] is the bridge by which the player and your plugin communicate. The following handful of properties and functions give you full access to the player:
1. Access the object with all configuration parameters of the player through '''view.config'''.
2. Access the playlist array of the player through '''view.playlist'''.
3. Send directives to the player with '''view.sendEvent(event,value)'''.
4. Subscribe to events from the [browser:trunk/as3/com/jeroenwijering/player/Controller.as Controller] with '''view.addControllerListener(event,function)''' ([wiki:FlashEvents overview]).
5. Subscribe to events from the [browser:trunk/as3/com/jeroenwijering/player/Model.as Model] with '''view.addModelListener(event,function)''' ([wiki:FlashEvents overview]).
6. Subscribe to events from the [browser:trunk/as3/com/jeroenwijering/player/View.as View] with '''view.addViewListener(event,function)''' ([wiki:FlashEvents overview]).
The 4.3 player introduced some new handlers through which plugins can have richer interaction with the stage and with each other:
7. Request a reference to another plugin with '''view.getPlugin(name)'''. This is useful for plugins that have public methods, such as the [browser:trunk/as3/com/jeroenwijering/plugins/Controlbar.as Controlbar] with ''hide()'' and ''addButton()''.
8. Request the configuration of a plugin through '''view.getPluginConfig(plugin)'''. Usually you'd use this as ''view.getPluginConfig(this)'' to request the positioning and additional variables for the plugin.
Again note that a complete overview of all available calls can be found on the [wiki:FlashApi API reference page]. [browser:trunk/as3/player.pdf This handy diagram] lists all variables in the ''config'' object and all events events of the ''view'', ''model'' and ''controller''.
Here's a plugin code snippet that listens to changes in the playback position:
{{{
public function initializePlugin(vw:AbstractView):void {
view = vw;
view.addModelListener(ModelEvent.TIME, timeHandler);
};
private function timeHandler(evt:ModelEvent):void {
trace("the new position is: "+evt.data.position);
};
}}}
Here's another snippet that loads a specific video once the user clicks a button:
{{{
private var button:Sprite;
private var video:String = "http://www.mysite.com/video/myVideo.flv";
private var view:AbstractView;
public function initializePlugin(vw:AbstractView) {
view = wv;
button.addEventListener(MouseEvent.CLICK,loadVideo);
};
private function loadVideo():void {
view.sendEvent(ViewEvent.LOAD,video);
};
}}}
This last snippet requests the plugins' configuration settings so it can be rescaled after a resize:
{{{
public var config:Object;
private var rectangle:MovieClip;
private var view:AbstractView;
public function initializePlugin(vw:AbstractView) {
view = vw;
view.addControllerListener(ControllerEvent.RESIZE,resizeHandler);
};
private function resizeHandler(evt:ControllerEvent) {
// A plugin config contains the x,y,width,height position of the plugin and is automatically updated.
rectangle.x = config['x'];
rectangle.y = config['y'];
rectangle.width = config['width'];
rectangle.height = config['height'];
};
}}}
Note that the [browser:trunk/as3/com/jeroenwijering/plugins plugins package] contains a string of example plugins you can borrow code snippets from.
There's also a separate tutorial that [wiki:YousearchTutorial describes step by step how to build the Yousearch plugin]. The Yousearch plugin shows a small Youtube search box on stage, used to load Youtube videos.
== Loading data ==
Basic configuration parameters for a specific plugin can be loaded through the same flashvars mechanism the player uses itself. Variables for a specific plugin must be prepended with the name of the plugin and a dot. So if your plugin is called ''delicious'', your variable names must start with the ''delicious.'' string. Example:
{{{
}}}
All the flashvars set in HTML will end up sitting in the view.config object, so you can request any flashvars from there. For example, this is how the ''delicious'' plugin could request its flashvars:
{{{
public function initializePlugin(vw:AbstractView) {
var user = view.config['delicious.user'];
var tags = view.config['delicious.tags'];
};
}}}
The 4.4 player will automatically push all flashvars to your plugin, so you won't have to get them from the global '''config''' file. Your ''config'' needs to be public then! You can also set defaults, which will automatically be overwritten. Example:
{{{
public var config:Object = {
user:'default',
tags:undefined
};
public function initializePlugin(vw:AbstractView) {
// when called, the player has already updated the flashvars.
var user = config['user'];
var tags = config['tags'];
};
}}}
Besides providing an automated mechanism for pushing plugin flashvars, the 4.4+ setup has two other advantages:
1. The '''config''' object will also contain the ''x'',''y'',''width'' and ''height'' properties of the plugin, so it is very easy to resize the plugin after requesting this object. [wiki:FlashOverview#Resizing Here's more info on resizing].
2. The '''config''' object continues working even if the plugin name is changed. If, for example, our plugin was renamed from '''delicious''' to '''mydelicious''', the first plugin retrieval method doesn't work anymore, but the second will.
If you want to pull more complex data into the plugin, it is best to let the plugin itself load the data through an external XML file. Keep in mind the [wiki:FlashSecurity Crossdomain security restrictions] of Flash then: the domain serving the XML needs a '''crossdomain.xml''' file that must allow access from the domain from which the '''player.swf''' (NOT the plugin!) is served.
== Building ==
We have a separate, short explanation on how to [wiki:PluginsBuilding compile your plugin] using the free, crossplatform Flex SDK.
This page is made separate because it also explains how to compile any of the open-source plugins [wiki:WikiStart#Plugins we offer at this site].
== Testing ==
For testing your plugin against various versions and setups of the player, you can use the [/testing testing page], which is part of the [changeset:HEAD/trunk/sdk?old_path=/&format=zip plugin development SDK]. Tests can be made against all versions of the player and with any combination of player/skin/plugins you'd like. Inserting your plugin in the testing page is simply a matter of changing the ''settings.js'' file that is included with the SDK. This is a dictionary that lists the location of all available plugins, skins, players and settings. It needs to know the location of your plugin SWF and the location of a plugin XML file, which describes your plugin. An example of such XML file is listed here, and more examples can be found in the [changeset:HEAD/trunk/sdk?old_path=/&format=zip plugin development SDK].
{{{
Plugin title
plugin.swf
1
Compatible with 4.X
Me
A short description of the plugin, in a few lines.
http://www.mywebsite.com/plugins/myplugin/
file
myfile.xml
A flashvar for this plugin
image
Another flashvar, with no default value.
}}}
== Debugging ==
Version 4.5 of the player also introduced plugin debugging capabilities in the form of the [browser:trunk/as3/com/jeroenwijering/utils/Logger.as com.jeroenwijering.utils.Logger] class. Include this class in your player and send a call to ''Logger.log()'' every time you want to log an event or error. The call takes a ''message'' and a ''type'' (which can be used to identify your plugin):
{{{
Logger.log('XML file loaded and parsed','MyPlugin');
}}}
If you use [http://kb2.adobe.com/cps/142/tn_14266.html a debug version] of the Adobe Flash player, you will have an additional rightclick menu item, saying "Logging to ...". The following options are available:
* '''none''': No logging is performed. This is the default.
* '''arthropod''': logs are sent to the [http://arthropod.stopp.se/ Arthropod AIR application]. It's a small, free and very useful tool.
* '''console''': logs are sent to the Firefox / Firebug console.
* '''trace''': logs are sent to actionscript's built-in tracing command. You can [http://www.actionscript.org/resources/articles/207/1/Trace-and-debug-ActionScript-from-your-browser/Page1.html write these to a logfile] in turn.
If you want to debug with a non-debug player, set the flashvar ''debug=xxx'' in your source code, ''xxx'' being one of the above options. It is recommended you install a debug player though, since that enables you to also debug players whose flashvars you cannot alter.
== Submit your plugin ==
When you're done testing your plugin and would like to get people start using it, submit your plugin to the [http://www.longtailvideo.com/addons/submitregister.html LongTailVideo Addons section]. Once loaded onto Longtails' repository, your plugin can be loaded into any JW Player out there through the plugins flashvar. You will instantly reach an audience of millions!
Good luck coding! And if you have any questions about building plugins, please visit the [http://www.longtailvideo.com/support/forum/Plugins/ plugins forum].