2.0.5 Release Notes

  • Added error object to player
  • Adjusted popup timer and progress bar
  • Fixed media URL escaping
  • Stopped sending poster to plugin
  • Silverlight culture update
  • Added back reference check (also makes jQuery usage easier)
  • Added stop() function to mediaelement
  • timerupdate still fires when paused (plugins)
  • Added Security.allowDomain(“*”) to Flash so it can be used on different domains
  • Fixed progress bar for Firefox 3 with Ogg files
  • Prevented Flash from re-creating the player when show/hide restarts it
  • Fixed initial volume level in non-HTML5 players
  • Made PNG8 versions of controls images (for IE6)

Re-writing Flash and Silverlight Detection

The initial release of MediaElement.js included Flash detection derived from SWFObject and Silverlight detection from Microsoft’s own Silverlight.js files.

The problem was that this code didn’t adhere to a common coding standard, and I received a few negative comments on the code.

So as part of the process of re-writing MediaElement.js to be JSLint compliant and work well with YICompressor, I’ve built a new plugin detection system that very small and can be extended to work with other browser plugins like Adobe Reader if someone wanted to.

As usual IE does things one way (ActiveX) and other browsers do it another way (navigator.plugins), so the detection scheme has to check for both. Another difficulty is that Silverlight does not return a version number in IE, and instead only returns true or false to an isVersionSupported function. So to get the version for IE, you have to loop through all possibilities which is pretty nasty.

Here is the completed code for the PluginDetector object, which includes the core detection logic as well as Flash and Silverlight detection routines:

mejs.PluginDetector = {

	// main public function to test a plug version number PluginDetector.hasPluginVersion('flash',[9,0,125]);
	hasPluginVersion: function(plugin, v) {
		var pv = this.plugins[plugin];
		v[1] = v[1] || 0;
		v[2] = v[2] || 0;
		return (pv[0] > v[0] || (pv[0] == v[0] && pv[1] > v[1]) || (pv[0] == v[0] && pv[1] == v[1] && pv[2] >= v[2])) ? true : false;
	},

	// cached values
	nav: window.navigator,
	ua: window.navigator.userAgent.toLowerCase(),		

	// stored version numbers
	plugins: [],

	// runs detectPlugin() and stores the version number
	addPlugin: function(p, pluginName, mimeType, activeX, axDetect) {
		this.plugins[p] = this.detectPlugin(pluginName, mimeType, activeX, axDetect);
	},

	// get the version number from the mimetype (all but IE) or ActiveX (IE)
	detectPlugin: function(pluginName, mimeType, activeX, axDetect) {

		var version = [0,0,0],
			d,
			i,
			ax;

		// Firefox, Webkit, Opera
		if (typeof(this.nav.plugins) != 'undefined' && typeof this.nav.plugins[pluginName] == 'object') {
			d = this.nav.plugins[pluginName].description;
			if (d && !(typeof this.nav.mimeTypes != 'undefined' && this.nav.mimeTypes[mimeType] && !this.nav.mimeTypes[mimeType].enabledPlugin)) {
				version = d.replace(pluginName, '').replace(/^\s+/,'').replace(/\sr/gi,'.').split('.');
				for (i=0; i<version.length; i++) {
					version[i] = parseInt(version[i], 10);
				}
			}
		// Internet Explorer / ActiveX
		} else if (typeof(window.ActiveXObject) != 'undefined') {
			try {
				ax = new ActiveXObject(activeX);
				if (ax) {
					version = axDetect(ax);
				}
			}
			catch (e) { }
		}
		return version;
	}
};

// Add Flash detection
mejs.PluginDetector.addPlugin('flash','Shockwave Flash','application/x-shockwave-flash','ShockwaveFlash.ShockwaveFlash', function(ax) {
	// adapted from SWFObject
	var version = [],
		d = ax.GetVariable("$version");
	if (d) {
		d = d.split(" ")[1].split(",");
		version = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];
	}
	return version;
});

// Add Silverlight detection
mejs.PluginDetector.addPlugin('silverlight','Silverlight Plug-In','application/x-silverlight-2','AgControl.AgControl', function (ax) {
	// Silverlight cannot report its version number to IE
	// but it does have a isVersionSupported function, so we have to loop through it to get a version number.
	// adapted from http://www.silverlightversion.com/
	var v = [0,0,0,0],
		loopMatch = function(ax, v, i, n) {
			while(ax.isVersionSupported(v[0]+ "."+ v[1] + "." + v[2] + "." + v[3])){
				v[i]+=n;
			}
			v[i] -= n;
		};
	loopMatch(ax, v, 0, 1);
	loopMatch(ax, v, 1, 1);
	loopMatch(ax, v, 2, 10000); // the third place in the version number is usually 5 digits (4.0.xxxxx)
	loopMatch(ax, v, 2, 1000);
	loopMatch(ax, v, 2, 100);
	loopMatch(ax, v, 2, 10);
	loopMatch(ax, v, 2, 1);
	loopMatch(ax, v, 3, 1);		

	return v;
});

Then it can be used with the following code:

// get the version
var version = PluginDetector.plugins['flash'];

// check for specific verison
var hasVersion = PluginDetector.hasPluginVersion('flash', [9,0,125]);

Plugins for WordPress and Drupal

Matt Farina has generously created a Drupal plugin for MediaElement.js.

I’ve also put together a WordPress plugin that allows you to use the simple short code [ video src="myvideo.mp4"]

Updates for IE9 Beta 1 and Safari

I’ve made a few small tweaks for IE9 beta 1 problems and I’ve also added support for Safari’s fullscreen option. Here is the state of fullscreen support:

  • Safari 5 – native fullscreen, accessible through JavaScript
  • Chrome – no fullscreen (although it says it supports it)
  • Firefox – native fullscreen, only available through context menu
  • IE9 – no fullscreen
  • Opera – no fullscreen

Here’s hoping more browsers offer a true full screen for video.

HTML5 and the Today of the Web

MediaElement.js was originally built to show at ECHO conference. Here are the slides that Nathan Smith and I gave demoing HTML5 and CSS3 features that are broadly usable today.

MediaElement.js Released

As a demo for ECHO conference, I’m releasing the very first version of MediaElement.js which aims to do something new in the HTML5 world. All HTML5 video players out there today have the following behavior.

  1. HTML5 video player for HTML5 enabled browsers
  2. Completely separate Flash player for other browsers

Instead, MediaElement.js is a set of Flash and Silverlight plugins that implement the HTML5 MediaElement API spec. So instead of using Flash as a fallback, MediaElement.js uses Flash as a fallforward that mimics HTML5 for older browsers. Here’s how MediaElement.js works:

  1. Upgrade all browsers to HTML5 spec
  2. Build a player on top of the common framework

Here’s what’s happening

The added bonus to this approach is that it levels the codec playing field. In addition to adding HTML5 to IE and other older browsers, this approach also adds H.264 to Firefox and Opera, and when Flash gains WebM capability, it will be able to add WebM to Safari.

Hope you enjoy it!

Return top