The JW Player 5 Beta is considered to be pre-release software.  The documentation below can (and will) change to reflect ongoing development.

JW Player: Architectural Roadmap

General Player Architecture

Built-in functionality for all plugins (mandatory base class)

  • Plugins must implement an IPlugin interface, which will be type-checked by the player before loading
    • Initialization (initPlugin)
    • Receives its configuration from the player on initialization
    • Receives a resize(width, height) call from the player when appropriate
    • Player sets plugin's (x,y) coordinates based on user configuration.

User Interface Components

Built-in UI elements, such as the Display area, the Controlbar, the Playlist, etc., play a core role inside the player. They can always be expected to be present in memory, even if they are disabled by configuration.

  • CoreComponent is the base class for all UI player UI components.
  • Each CoreComponent will implement its own interface (IControlbar, IPlaylist, etc.) which Plugins can also implement. This would allow plugins to replace built-in components through an API call (e.g. Player.overrideComponent(this)).

Typed Config Block

There will be a central, strongly typed Config class, named PlayerConfig. It will provide the following functionality:

  • Stores a very limited set of properties with strong types and default values.
  • Each property will have a getter and some will have setters, making certain values read-only. Additionally, the setters will be able to provide input checking when properties are set.
  • Allow for setting properties dynamically, enabling player-wide custom configuration items
  • Store Plugins' configuration data, indexed by the plugin name via the pluginConfig(pluginName) method
    • PluginConfig will also have typed and dynamic properties
  • Translate playlist elements

Skinning

  • Contains information about the availability of skin elements
  • Ability to load Zip files (tentative)
  • Ability to load Version 4 SWF skins
  • Ability to load XML manifest files (tentative)

Preventing deadlock / race conditions in synchronous / asynchronous situations

  • Do dispatches last
  • Don't dispatch in an event handler
  • Use synchronous callbacks whenever possible
  • API should expose a limited set of methods
  • Some configuration should be locked - r or rw.
  • Run unit testing

Predictable event flow

Plugins rely on the Player's events to time their actions appropriately. Therefore, we should attempt to keep the flow of events as predictable as possible. For example, the following event path should be avoided:

PLAY: true
TIME: 0.0
TIME: 0.2
TIME: 0.4
TIME: 0.6
PLAY: false (or PAUSED)
TIME: 0.8

In this case, the pause event should be marshaled until the player is certain all TIME events have completed before firing the PAUSED event. (Alternately, although not as elegant, the final TIME event could be ignored).

Relatedly, the Player's STATE events should always follow a predictable path. The following is an example state path

IDLE
BUFFERING
PLAYING
PAUSED (if necessary)
BUFFERING (if necessary)
COMPLETED

Cleaned-up Plugin API

Plugins should have an interface to the player that is simple, well-documented, and provides compile-time error checking. For developers using Adobe's Flash development tools, the interface should also expose metadata which allows for code-hinting and code completion.

To that end, the API should follow the following guidelines:

  • Plugins should receive a reference to Player, not to View.
  • Plugins should call synchronous methods whenever possible
  • The Player should dispatch all publicly-visible events, and swallow the rest. (Plugins would call addEventListener to the Player itself)
  • The Player exposes its Config object to the plugins, which has strongly-typed, permissioned properties (read/write or read-only).
    • A plugin may change a writable config property, which should synchronously alter the player, or throw an error.

Automated Building

  • Project can be built end-to-end using free / open-source tools (Flex SDK, Ant, ASDoc, FlexUnit).
  • Unlike the Version 4 Player, which required a licensed copy of Adobe Flash CS3 or above to compile, Version 5 can be compiled from the command line.
  • For information information on building the player, check out the README.

Automated Testing

The Player project will include automated unit and integration tests, which will highlight any bugs introduced by check-ins to the source repository.

  • On each commit to the trunk:
    • An automated build is run, ensuring the checked-in code compiles
    • FlexUnit testing, identifying any changes to player components' functionality
  • Nightly testing:
    • API testing (JS and AS)

What should be tested

  • Every public method, especially those with return type.
  • The player as a whole (integration test)
  • Certain plugins

Testing platform(s)

  • FlexUnit 4 (for unit testing of public methods)
  • A webpage with JavaScript for JS API
  • A webpage that loads a plugin for plugin API
  • FlexMonkey for integration testing (proposed)

Plugins

  • Synchronous / Asynchronous requests
  • Player addEventListener / removeEventListener
  • Kill view.sendEvent()
  • Event strings should be fully qualified
    • E.g. com.jeroenwijering.events.ModelEvent.TIME
  • Strongly typed Event classes, w/ typed properties
  • Base plugin signature shouldn’t change over life of version

Compatibility

  • addControllerListener/addModelListener/addViewListener » addEventListener()
  • sendEvent() stub redirecting to synchronous methods

Plugin Compatibility Mode

Version 5 of the player should make a best-effort attempt to make itself compatible with the 4.x player plugins. It needs to expose (and translate) the following APIs:

  • com.jeroenwijering.events.AbstractView
    • getPluginConfig
    • getPlugin
  • All new player event types must be translated into their 4.x equivalents and broadcast
    • addModelListener, addControllerListener, addViewListener
  • sendEvent() translates 4.x event types and either broadcasts a 5.x event, or calls a synchronous method
  • Use a new namespace so 4.x plugins may be identified by type checking
  • New plugins in diff repo - check there first

One possibility for handling 4.x plugins would be to create a built-in Proxy plugin, which would provide each plugin with a simulated 4.x environment, but would appear to the 5.x player as a standard plugin.

Javascript Compatibility Mode

The JavaScript functions and events available in 4.x must be available in 5.x and return the same values.

Skin Compatibility Mode

Skinning should be accomplished through an interface that would be implemented by a PNG skin loader, and a 4.x-compatible SWF skin loader. The interface should look something like this:

public interface ISkin {
  function load(url:String):void;                       // Dispatches an event on success or failure
  function hasSkinElement(name:String):Boolean;
  function getSkinElement(name:String):DisplayObject;
  function getSkinProperties():SkinProperties;          // Contains skin-specific player config properties, such as default colors.  These should override player defaults.
}

Which skin loader to use can be determined by simple file extension (.zip -> PNG skin; .swf -> SWF skin).

Functionality

  • public typed Config object w/ read-only or read-write properties

Loader

UI

The player should have a loader UI which replaces the standard player UI while the player loads its required components. It is removed as soon as all blocking setup operations have completed.

Sequence

  • Hit player constructor (wait until added to stage / width and height are > 0)
  • Load config
  • Load skin elements
  • Load plugins
  • Load loadable Model(s)
  • If plugins request takeover, wait until they relinquished control.
  • Redraw
  • Wait for externalInterface to be ready
  • Fire playerReady
  • Load file (if set)
  • Autostart

Each item in the boot sequence should be run from the following function: boot(workerFunction, checkCompleteFunction, nextBootFunction, minTimeToComplete, frequencyToCheckComplete);

Once these steps are complete, the loader UI can disappear.

PNG Skinning

Jeroen

Player Blocking / Locking

  • Locking is in the view.
    • Refers to the ability to disable player controls, effectively preventing user input.
    • This could be something as simple as putting up a curtain, but it probably means something more like enabling the lock mode of the controlbar, and then enabling certain buttons while locked.
  • Blocking is in the controller
    • Means of stopping input from all sources.
    • A plugin (or the player) would grab a lock for some configuration / state element, and then only that object would have control over that configuration / state until it released the lock.
    • The player would have the ability to clear locks.
  • TODO: Use cases

Embedding

Player-generated embed code

The player should allow plugins to request a simple embed code that represents the current state of the player. The following elements should be included:

  • Player swf location
  • Non-default player config parameters
  • Skin location
  • Plugin location(s)
  • Plugin configuration parameters

The embed code should be as platform-independent as possible, so a <object><embed></embed></object> method is prefereable. Plugins which need more sophisticated embed code may implement this on their own.

Javascript Embedding

  • SWFObject is fine for now
  • We could do things that were more intuitive if we wrote our own loader, vis-a-vis flowplayer.
  • We could even switch players (flash -> WMV) based on file extension.
  • Might be a good idea, as we could upgrade people's installation this way as well.

Model States

Error State

  • Create a separate state, error, which is like IDLE, but may trigger different behavior.

Additional Features

Base64-encoded config block

As an alternative to the flashvars and xml config options, the player could accept a zipped, base64-encoded version of the config object. This would allow plugins to bypass URL encoding schemes, and provide an easy mechanism to pass entire player configurations back and forth. It would also grant publishers a certain level of obfuscation for their configuration parameters.