This page explains the details of building Flash plugins for JW Player. See About JW Player Plugins for a general overview and info on embedding plugins.
Before starting development, you need the following free tools:
Each plugin should implement the JW Player IPlugin6 interface, which defines an initPlugin() function, a resize() function and id() and target() getters. Second, plugins need to extend the Sprite or Movieclip class.
Here is an example of a very basic JW Player plugin:
package { import flash.display.Sprite; import flash.text.TextField; import com.longtailvideo.jwplayer.player.*; import com.longtailvideo.jwplayer.plugins.*; public class HelloWorld extends Sprite implements IPlugin6 { /** Configuration options of the plugin. **/ private var config:Object; /** Reference to the JW Player API. **/ private var player:IPlayer; /** Text field to print into. **/ private var field:TextField; /** This function is automatically called upon load. **/ public function initPlugin(ply:IPlayer, cfg:Object):void { player = ply; config = cfg; field = new TextField(); if(config.text) { field.text = config.text; } else { field.text = "Hello World!"; } addChild(field); } /** This should be the lowercase name of the plugin SWF file. **/ public function get id():String { return "helloworld"; } /** This should be the player version the plugin is targeted for. **/ public function get target():String { return "6.0"; } /** This is called when the player resizes. **/ public function resize(width:Number, height:Number):void { field.x = width/2 - 50; field.y = height/2 - 50; } } }
The JW6 plugin SDK contains a build script (build.sh for Mac OS X and Linux, build.bat for Windows) that can be used to compile this code into a plugin using Flex SDK's mxmlc compiler.
Like their JavaScript counterparts, Flash plugins integrate with JW Player in a couple of ways. They can access the player API, accept configuration options and place visual assets on the stage.
The first parameter of the required initPlugin method (see example above) is a reference to the player API. This can be used to get player variables, call player functions and listen to player events. Here's a code snippet that does all three:
// Get a player variable var volume:Number = player.config.volume; // Call a player function player.volume(50); // Listen to a player event private function volumeListener(event:MediaEvent) { var newVolume:Number = event.volume; } player.addEventListener(MediaEvent.JWPLAYER_MEDIA_VOLUME, volumeListener);
The Flash plugin API reference contains the same classes and calls a the JavaScript API, but the signatures differ. See Flash Plugins API Reference for a mapping of all API calls from JavaScript to ActionScript.
Just like the player at large, plugins can have themselves tweaked using configuration options. These options are provided by publishers inside the configuration block for the plugin:
jwplayer("myElement").setup({ file: "/uploads/example.mp4", image: "/uploads/example.jpg", plugins: { "/scripts/helloworld.swf": { text: 'Hello all!' } }, primary: 'flash' });
The player passes these configuration options forward to the plugin as the second parameter of the initPlugin() function call (see example above). The parameter is an object containing all options.
Every plugin has the ability to render visual assets on top of the player display. For that purpose, JW Player automatically adds the plugin to the displayStack of the player. That's why every plugin must subclass Sprite or MovieClip. Plugins can nest whatever visual assets they want using addChild().
The -required- resize() method of a plugin is automatically called by the player whenever it gets resized. This includes the initial setup (shortly before onReady). Use this call to ensure your visuals are correctly scaled and stretched over the player display. Note the above helloworld example uses the resize() call to re-center itself over the player.
Note the player controls are also displayed on top of JW Player, possibly interfering with the plugin visuals. Plugins are z-indexed on top of the controls though, so they can obscure them if they want. If a plugin needs to be visible together with the controls, it should use the player.getSafeMargins() API call to find out which top and bottom margins are used by the player controls.
This section explains how to compile plugins using the Adobe Flex SDK. With a combination of this free-for-download tool and a text editor of choice, anyone can build plugins for the JW Player. The Flex SDK is available for Linux, Mac OS X and Windows.
This JW6 plugin SDK contains a few example plugins. Each plugin source includes both a build.bat and a build.sh file. The first will compile the plugin on Windows, the latter will compile the plugin on Linux and Mac OS X. The SDK also contains the jwplayer.swc library, which is required for compiling a JW6 plugin.
The build.bat file is used when you run Windows. Open the file in a text editor to check (and possibly change) the path to the Flex SDK on your computer. By default, it is \Program Files\flex_sdk_3. If the path is OK, you can double-click the build.bat file to compile the plugin. That's all!
Note that the compiler will automatically stop and display compilation errors, should there be any in your source code. Use these error messages to find and fix the bugs.
The build.sh file is used when you run Linux or Mac OS X. Open the file in a text editor to check (and possibly change) the path to the Flex SDK on your computer. By default, it is /Developer/SDKs/flex_sdk_3. If the path is OK, you can open a Terminal window and insert the full path to the build.sh script to run it. Since sometimes the permissions of this build.sh file are not sufficient to run it, here is an example of what to insert in the terminal window to also set the permissions right:
cd ~/Desktop/sdks/jw6-plugin-sdk/plugins/apitester chmod 777 build.sh ./build.sh
That's it! Your plugin will now be built.
As you may have seen when opening build.bat or build.sh in the text editor, the actual compilation command is just one line of code:
$FLEXPATH/bin/mxmlc ./APITester.as -sp ./ -o ./apitester.swf -external-library-path+=../../libs -use-network=false -static-link-runtime-shared-libraries=true
This command tells mxmlc (the compiler executive) which actionscript file to compile (APITester.as). This file is the main class of the plugin. When the plugin is loaded into a player, this main class will be instantiated once. Next to the class to build, the compiler is also given a few options:
The options listed above are sufficient to compile working plugins. The compiler supports a large number of options though, most of them are for more advanced compilation workflows or metadata insertion.
Tracking what's going on in your compiled plugin can be done in various ways. The professional Flash Builder from Adobe for example, has many options for step debugging and runtime data inspection. Another, quite simple option, is to use the ExternalInterface functionality of Flash to send traces to your browser console:
ExternalInterface.call("console.log","This text will appear in the browser console");
If you use a debug version of the Adobe Flash player, any run-time coding errors will display in a popup menu. This is very convenient for tracing down issues.