annotate build/mediaelement.js @ 25:4a4bd554b4c1 tip

Closing this sub branch.
author Daniele Barchiesi <daniele.barchiesi@eecs.qmul.ac.uk>
date Mon, 25 Mar 2013 14:02:54 +0000
parents 032bc65ebafc
children
rev   line source
gyorgy@0 1 /*!
gyorgy@0 2 * MediaElement.js
gyorgy@0 3 * HTML5 <video> and <audio> shim and player
gyorgy@0 4 * http://mediaelementjs.com/
gyorgy@0 5 *
gyorgy@0 6 * Creates a JavaScript object that mimics HTML5 MediaElement API
gyorgy@0 7 * for browsers that don't understand HTML5 or can't play the provided codec
gyorgy@0 8 * Can play MP4 (H.264), Ogg, WebM, FLV, WMV, WMA, ACC, and MP3
gyorgy@0 9 *
gyorgy@0 10 * Copyright 2010-2011, John Dyer (http://j.hn)
gyorgy@0 11 * Dual licensed under the MIT or GPL Version 2 licenses.
gyorgy@0 12 *
gyorgy@0 13 */
gyorgy@0 14 // Namespace
gyorgy@0 15 var mejs = mejs || {};
gyorgy@0 16
gyorgy@0 17 // version number
gyorgy@0 18 mejs.version = '2.1.9';
gyorgy@0 19
gyorgy@0 20 // player number (for missing, same id attr)
gyorgy@0 21 mejs.meIndex = 0;
gyorgy@0 22
gyorgy@0 23 // media types accepted by plugins
gyorgy@0 24 mejs.plugins = {
gyorgy@0 25 silverlight: [
gyorgy@0 26 {version: [3,0], types: ['video/mp4','video/m4v','video/mov','video/wmv','audio/wma','audio/m4a','audio/mp3','audio/wav','audio/mpeg']}
gyorgy@0 27 ],
gyorgy@0 28 flash: [
gyorgy@0 29 {version: [9,0,124], types: ['video/mp4','video/m4v','video/mov','video/flv','video/x-flv','audio/flv','audio/x-flv','audio/mp3','audio/m4a','audio/mpeg']}
gyorgy@0 30 //,{version: [11,0], types: ['video/webm']} // for future reference
gyorgy@0 31 ]
gyorgy@0 32 };
gyorgy@0 33
gyorgy@0 34 /*
gyorgy@0 35 Utility methods
gyorgy@0 36 */
gyorgy@0 37 mejs.Utility = {
gyorgy@0 38 encodeUrl: function(url) {
gyorgy@0 39 return encodeURIComponent(url); //.replace(/\?/gi,'%3F').replace(/=/gi,'%3D').replace(/&/gi,'%26');
gyorgy@0 40 },
gyorgy@0 41 escapeHTML: function(s) {
gyorgy@0 42 return s.toString().split('&').join('&amp;').split('<').join('&lt;').split('"').join('&quot;');
gyorgy@0 43 },
gyorgy@0 44 absolutizeUrl: function(url) {
gyorgy@0 45 var el = document.createElement('div');
gyorgy@0 46 el.innerHTML = '<a href="' + this.escapeHTML(url) + '">x</a>';
gyorgy@0 47 return el.firstChild.href;
gyorgy@0 48 },
gyorgy@0 49 getScriptPath: function(scriptNames) {
gyorgy@0 50 var
gyorgy@0 51 i = 0,
gyorgy@0 52 j,
gyorgy@0 53 path = '',
gyorgy@0 54 name = '',
gyorgy@0 55 script,
gyorgy@0 56 scripts = document.getElementsByTagName('script');
gyorgy@0 57
gyorgy@0 58 for (; i < scripts.length; i++) {
gyorgy@0 59 script = scripts[i].src;
gyorgy@0 60 for (j = 0; j < scriptNames.length; j++) {
gyorgy@0 61 name = scriptNames[j];
gyorgy@0 62 if (script.indexOf(name) > -1) {
gyorgy@0 63 path = script.substring(0, script.indexOf(name));
gyorgy@0 64 break;
gyorgy@0 65 }
gyorgy@0 66 }
gyorgy@0 67 if (path !== '') {
gyorgy@0 68 break;
gyorgy@0 69 }
gyorgy@0 70 }
gyorgy@0 71 return path;
gyorgy@0 72 },
gyorgy@0 73 secondsToTimeCode: function(seconds,forceHours) {
gyorgy@0 74 seconds = Math.round(seconds);
gyorgy@0 75 var hours,
gyorgy@0 76 minutes = Math.floor(seconds / 60);
gyorgy@0 77 if (minutes >= 60) {
gyorgy@0 78 hours = Math.floor(minutes / 60);
gyorgy@0 79 minutes = minutes % 60;
gyorgy@0 80 }
gyorgy@0 81 hours = hours === undefined ? "00" : (hours >= 10) ? hours : "0" + hours;
gyorgy@0 82 minutes = (minutes >= 10) ? minutes : "0" + minutes;
gyorgy@0 83 seconds = Math.floor(seconds % 60);
gyorgy@0 84 seconds = (seconds >= 10) ? seconds : "0" + seconds;
gyorgy@0 85 return ((hours > 0 || forceHours === true) ? hours + ":" :'') + minutes + ":" + seconds;
gyorgy@0 86 },
gyorgy@0 87 timeCodeToSeconds: function(timecode){
gyorgy@0 88 var tab = timecode.split(':');
gyorgy@0 89 return tab[0]*60*60 + tab[1]*60 + parseFloat(tab[2].replace(',','.'));
gyorgy@0 90 }
gyorgy@0 91 };
gyorgy@0 92
gyorgy@0 93
gyorgy@0 94 // Core detector, plugins are added below
gyorgy@0 95 mejs.PluginDetector = {
gyorgy@0 96
gyorgy@0 97 // main public function to test a plug version number PluginDetector.hasPluginVersion('flash',[9,0,125]);
gyorgy@0 98 hasPluginVersion: function(plugin, v) {
gyorgy@0 99 var pv = this.plugins[plugin];
gyorgy@0 100 v[1] = v[1] || 0;
gyorgy@0 101 v[2] = v[2] || 0;
gyorgy@0 102 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;
gyorgy@0 103 },
gyorgy@0 104
gyorgy@0 105 // cached values
gyorgy@0 106 nav: window.navigator,
gyorgy@0 107 ua: window.navigator.userAgent.toLowerCase(),
gyorgy@0 108
gyorgy@0 109 // stored version numbers
gyorgy@0 110 plugins: [],
gyorgy@0 111
gyorgy@0 112 // runs detectPlugin() and stores the version number
gyorgy@0 113 addPlugin: function(p, pluginName, mimeType, activeX, axDetect) {
gyorgy@0 114 this.plugins[p] = this.detectPlugin(pluginName, mimeType, activeX, axDetect);
gyorgy@0 115 },
gyorgy@0 116
gyorgy@0 117 // get the version number from the mimetype (all but IE) or ActiveX (IE)
gyorgy@0 118 detectPlugin: function(pluginName, mimeType, activeX, axDetect) {
gyorgy@0 119
gyorgy@0 120 var version = [0,0,0],
gyorgy@0 121 description,
gyorgy@0 122 i,
gyorgy@0 123 ax;
gyorgy@0 124
gyorgy@0 125 // Firefox, Webkit, Opera
gyorgy@0 126 if (typeof(this.nav.plugins) != 'undefined' && typeof this.nav.plugins[pluginName] == 'object') {
gyorgy@0 127 description = this.nav.plugins[pluginName].description;
gyorgy@0 128 if (description && !(typeof this.nav.mimeTypes != 'undefined' && this.nav.mimeTypes[mimeType] && !this.nav.mimeTypes[mimeType].enabledPlugin)) {
gyorgy@0 129 version = description.replace(pluginName, '').replace(/^\s+/,'').replace(/\sr/gi,'.').split('.');
gyorgy@0 130 for (i=0; i<version.length; i++) {
gyorgy@0 131 version[i] = parseInt(version[i].match(/\d+/), 10);
gyorgy@0 132 }
gyorgy@0 133 }
gyorgy@0 134 // Internet Explorer / ActiveX
gyorgy@0 135 } else if (typeof(window.ActiveXObject) != 'undefined') {
gyorgy@0 136 try {
gyorgy@0 137 ax = new ActiveXObject(activeX);
gyorgy@0 138 if (ax) {
gyorgy@0 139 version = axDetect(ax);
gyorgy@0 140 }
gyorgy@0 141 }
gyorgy@0 142 catch (e) { }
gyorgy@0 143 }
gyorgy@0 144 return version;
gyorgy@0 145 }
gyorgy@0 146 };
gyorgy@0 147
gyorgy@0 148 // Add Flash detection
gyorgy@0 149 mejs.PluginDetector.addPlugin('flash','Shockwave Flash','application/x-shockwave-flash','ShockwaveFlash.ShockwaveFlash', function(ax) {
gyorgy@0 150 // adapted from SWFObject
gyorgy@0 151 var version = [],
gyorgy@0 152 d = ax.GetVariable("$version");
gyorgy@0 153 if (d) {
gyorgy@0 154 d = d.split(" ")[1].split(",");
gyorgy@0 155 version = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];
gyorgy@0 156 }
gyorgy@0 157 return version;
gyorgy@0 158 });
gyorgy@0 159
gyorgy@0 160 // Add Silverlight detection
gyorgy@0 161 mejs.PluginDetector.addPlugin('silverlight','Silverlight Plug-In','application/x-silverlight-2','AgControl.AgControl', function (ax) {
gyorgy@0 162 // Silverlight cannot report its version number to IE
gyorgy@0 163 // but it does have a isVersionSupported function, so we have to loop through it to get a version number.
gyorgy@0 164 // adapted from http://www.silverlightversion.com/
gyorgy@0 165 var v = [0,0,0,0],
gyorgy@0 166 loopMatch = function(ax, v, i, n) {
gyorgy@0 167 while(ax.isVersionSupported(v[0]+ "."+ v[1] + "." + v[2] + "." + v[3])){
gyorgy@0 168 v[i]+=n;
gyorgy@0 169 }
gyorgy@0 170 v[i] -= n;
gyorgy@0 171 };
gyorgy@0 172 loopMatch(ax, v, 0, 1);
gyorgy@0 173 loopMatch(ax, v, 1, 1);
gyorgy@0 174 loopMatch(ax, v, 2, 10000); // the third place in the version number is usually 5 digits (4.0.xxxxx)
gyorgy@0 175 loopMatch(ax, v, 2, 1000);
gyorgy@0 176 loopMatch(ax, v, 2, 100);
gyorgy@0 177 loopMatch(ax, v, 2, 10);
gyorgy@0 178 loopMatch(ax, v, 2, 1);
gyorgy@0 179 loopMatch(ax, v, 3, 1);
gyorgy@0 180
gyorgy@0 181 return v;
gyorgy@0 182 });
gyorgy@0 183 // add adobe acrobat
gyorgy@0 184 /*
gyorgy@0 185 PluginDetector.addPlugin('acrobat','Adobe Acrobat','application/pdf','AcroPDF.PDF', function (ax) {
gyorgy@0 186 var version = [],
gyorgy@0 187 d = ax.GetVersions().split(',')[0].split('=')[1].split('.');
gyorgy@0 188
gyorgy@0 189 if (d) {
gyorgy@0 190 version = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];
gyorgy@0 191 }
gyorgy@0 192 return version;
gyorgy@0 193 });
gyorgy@0 194 */
gyorgy@0 195 // necessary detection (fixes for <IE9)
gyorgy@0 196 mejs.MediaFeatures = {
gyorgy@0 197 init: function() {
gyorgy@0 198 var
gyorgy@0 199 nav = mejs.PluginDetector.nav,
gyorgy@0 200 ua = mejs.PluginDetector.ua.toLowerCase(),
gyorgy@0 201 i,
gyorgy@0 202 v,
gyorgy@0 203 html5Elements = ['source','track','audio','video'];
gyorgy@0 204
gyorgy@0 205 // detect browsers (only the ones that have some kind of quirk we need to work around)
gyorgy@0 206 this.isiPad = (ua.match(/ipad/i) !== null);
gyorgy@0 207 this.isiPhone = (ua.match(/iphone/i) !== null);
gyorgy@0 208 this.isAndroid = (ua.match(/android/i) !== null);
gyorgy@0 209 this.isBustedAndroid = (ua.match(/android 2\.[12]/) !== null);
gyorgy@0 210 this.isIE = (nav.appName.toLowerCase().indexOf("microsoft") != -1);
gyorgy@0 211 this.isChrome = (ua.match(/chrome/gi) !== null);
gyorgy@0 212 this.isFirefox = (ua.match(/firefox/gi) !== null);
gyorgy@0 213
gyorgy@0 214 // create HTML5 media elements for IE before 9, get a <video> element for fullscreen detection
gyorgy@0 215 for (i=0; i<html5Elements.length; i++) {
gyorgy@0 216 v = document.createElement(html5Elements[i]);
gyorgy@0 217 }
gyorgy@0 218
gyorgy@0 219 // detect native JavaScript fullscreen (Safari only, Chrome fails)
gyorgy@0 220 this.hasNativeFullScreen = (typeof v.webkitRequestFullScreen !== 'undefined');
gyorgy@0 221 if (this.isChrome) {
gyorgy@0 222 this.hasNativeFullScreen = false;
gyorgy@0 223 }
gyorgy@0 224 // OS X 10.5 can't do this even if it says it can :(
gyorgy@0 225 if (this.hasNativeFullScreen && ua.match(/mac os x 10_5/i)) {
gyorgy@0 226 this.hasNativeFullScreen = false;
gyorgy@0 227 }
gyorgy@0 228 }
gyorgy@0 229 };
gyorgy@0 230 mejs.MediaFeatures.init();
gyorgy@0 231
gyorgy@0 232
gyorgy@0 233 /*
gyorgy@0 234 extension methods to <video> or <audio> object to bring it into parity with PluginMediaElement (see below)
gyorgy@0 235 */
gyorgy@0 236 mejs.HtmlMediaElement = {
gyorgy@0 237 pluginType: 'native',
gyorgy@0 238 isFullScreen: false,
gyorgy@0 239
gyorgy@0 240 setCurrentTime: function (time) {
gyorgy@0 241 this.currentTime = time;
gyorgy@0 242 },
gyorgy@0 243
gyorgy@0 244 setMuted: function (muted) {
gyorgy@0 245 this.muted = muted;
gyorgy@0 246 },
gyorgy@0 247
gyorgy@0 248 setVolume: function (volume) {
gyorgy@0 249 this.volume = volume;
gyorgy@0 250 },
gyorgy@0 251
gyorgy@0 252 // for parity with the plugin versions
gyorgy@0 253 stop: function () {
gyorgy@0 254 this.pause();
gyorgy@0 255 },
gyorgy@0 256
gyorgy@0 257 // This can be a url string
gyorgy@0 258 // or an array [{src:'file.mp4',type:'video/mp4'},{src:'file.webm',type:'video/webm'}]
gyorgy@0 259 setSrc: function (url) {
gyorgy@0 260 if (typeof url == 'string') {
gyorgy@0 261 this.src = url;
gyorgy@0 262 } else {
gyorgy@0 263 var i, media;
gyorgy@0 264
gyorgy@0 265 for (i=0; i<url.length; i++) {
gyorgy@0 266 media = url[i];
gyorgy@0 267 if (this.canPlayType(media.type)) {
gyorgy@0 268 this.src = media.src;
gyorgy@0 269 }
gyorgy@0 270 }
gyorgy@0 271 }
gyorgy@0 272 },
gyorgy@0 273
gyorgy@0 274 setVideoSize: function (width, height) {
gyorgy@0 275 this.width = width;
gyorgy@0 276 this.height = height;
gyorgy@0 277 }
gyorgy@0 278 };
gyorgy@0 279
gyorgy@0 280 /*
gyorgy@0 281 Mimics the <video/audio> element by calling Flash's External Interface or Silverlights [ScriptableMember]
gyorgy@0 282 */
gyorgy@0 283 mejs.PluginMediaElement = function (pluginid, pluginType, mediaUrl) {
gyorgy@0 284 this.id = pluginid;
gyorgy@0 285 this.pluginType = pluginType;
gyorgy@0 286 this.src = mediaUrl;
gyorgy@0 287 this.events = {};
gyorgy@0 288 };
gyorgy@0 289
gyorgy@0 290 // JavaScript values and ExternalInterface methods that match HTML5 video properties methods
gyorgy@0 291 // http://www.adobe.com/livedocs/flash/9.0/ActionScriptLangRefV3/fl/video/FLVPlayback.html
gyorgy@0 292 // http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html
gyorgy@0 293 mejs.PluginMediaElement.prototype = {
gyorgy@0 294
gyorgy@0 295 // special
gyorgy@0 296 pluginElement: null,
gyorgy@0 297 pluginType: '',
gyorgy@0 298 isFullScreen: false,
gyorgy@0 299
gyorgy@0 300 // not implemented :(
gyorgy@0 301 playbackRate: -1,
gyorgy@0 302 defaultPlaybackRate: -1,
gyorgy@0 303 seekable: [],
gyorgy@0 304 played: [],
gyorgy@0 305
gyorgy@0 306 // HTML5 read-only properties
gyorgy@0 307 paused: true,
gyorgy@0 308 ended: false,
gyorgy@0 309 seeking: false,
gyorgy@0 310 duration: 0,
gyorgy@0 311 error: null,
gyorgy@0 312
gyorgy@0 313 // HTML5 get/set properties, but only set (updated by event handlers)
gyorgy@0 314 muted: false,
gyorgy@0 315 volume: 1,
gyorgy@0 316 currentTime: 0,
gyorgy@0 317
gyorgy@0 318 // HTML5 methods
gyorgy@0 319 play: function () {
gyorgy@0 320 if (this.pluginApi != null) {
gyorgy@0 321 this.pluginApi.playMedia();
gyorgy@0 322 this.paused = false;
gyorgy@0 323 }
gyorgy@0 324 },
gyorgy@0 325 load: function () {
gyorgy@0 326 if (this.pluginApi != null) {
gyorgy@0 327 this.pluginApi.loadMedia();
gyorgy@0 328 this.paused = false;
gyorgy@0 329 }
gyorgy@0 330 },
gyorgy@0 331 pause: function () {
gyorgy@0 332 if (this.pluginApi != null) {
gyorgy@0 333 this.pluginApi.pauseMedia();
gyorgy@0 334 this.paused = true;
gyorgy@0 335 }
gyorgy@0 336 },
gyorgy@0 337 stop: function () {
gyorgy@0 338 if (this.pluginApi != null) {
gyorgy@0 339 this.pluginApi.stopMedia();
gyorgy@0 340 this.paused = true;
gyorgy@0 341 }
gyorgy@0 342 },
gyorgy@0 343 canPlayType: function(type) {
gyorgy@0 344 var i,
gyorgy@0 345 j,
gyorgy@0 346 pluginInfo,
gyorgy@0 347 pluginVersions = mejs.plugins[this.pluginType];
gyorgy@0 348
gyorgy@0 349 for (i=0; i<pluginVersions.length; i++) {
gyorgy@0 350 pluginInfo = pluginVersions[i];
gyorgy@0 351
gyorgy@0 352 // test if user has the correct plugin version
gyorgy@0 353 if (mejs.PluginDetector.hasPluginVersion(this.pluginType, pluginInfo.version)) {
gyorgy@0 354
gyorgy@0 355 // test for plugin playback types
gyorgy@0 356 for (j=0; j<pluginInfo.types.length; j++) {
gyorgy@0 357 // find plugin that can play the type
gyorgy@0 358 if (type == pluginInfo.types[j]) {
gyorgy@0 359 return true;
gyorgy@0 360 }
gyorgy@0 361 }
gyorgy@0 362 }
gyorgy@0 363 }
gyorgy@0 364
gyorgy@0 365 return false;
gyorgy@0 366 },
gyorgy@0 367
gyorgy@0 368 // custom methods since not all JavaScript implementations support get/set
gyorgy@0 369
gyorgy@0 370 // This can be a url string
gyorgy@0 371 // or an array [{src:'file.mp4',type:'video/mp4'},{src:'file.webm',type:'video/webm'}]
gyorgy@0 372 setSrc: function (url) {
gyorgy@0 373 if (typeof url == 'string') {
gyorgy@0 374 this.pluginApi.setSrc(mejs.Utility.absolutizeUrl(url));
gyorgy@0 375 this.src = mejs.Utility.absolutizeUrl(url);
gyorgy@0 376 } else {
gyorgy@0 377 var i, media;
gyorgy@0 378
gyorgy@0 379 for (i=0; i<url.length; i++) {
gyorgy@0 380 media = url[i];
gyorgy@0 381 if (this.canPlayType(media.type)) {
gyorgy@0 382 this.pluginApi.setSrc(mejs.Utility.absolutizeUrl(media.src));
gyorgy@0 383 this.src = mejs.Utility.absolutizeUrl(url);
gyorgy@0 384 }
gyorgy@0 385 }
gyorgy@0 386 }
gyorgy@0 387
gyorgy@0 388 },
gyorgy@0 389 setCurrentTime: function (time) {
gyorgy@0 390 if (this.pluginApi != null) {
gyorgy@0 391 this.pluginApi.setCurrentTime(time);
gyorgy@0 392 this.currentTime = time;
gyorgy@0 393 }
gyorgy@0 394 },
gyorgy@0 395 setVolume: function (volume) {
gyorgy@0 396 if (this.pluginApi != null) {
gyorgy@0 397 this.pluginApi.setVolume(volume);
gyorgy@0 398 this.volume = volume;
gyorgy@0 399 }
gyorgy@0 400 },
gyorgy@0 401 setMuted: function (muted) {
gyorgy@0 402 if (this.pluginApi != null) {
gyorgy@0 403 this.pluginApi.setMuted(muted);
gyorgy@0 404 this.muted = muted;
gyorgy@0 405 }
gyorgy@0 406 },
gyorgy@0 407
gyorgy@0 408 // additional non-HTML5 methods
gyorgy@0 409 setVideoSize: function (width, height) {
gyorgy@0 410 if ( this.pluginElement.style) {
gyorgy@0 411 this.pluginElement.style.width = width + 'px';
gyorgy@0 412 this.pluginElement.style.height = height + 'px';
gyorgy@0 413 }
gyorgy@0 414 if (this.pluginApi != null) {
gyorgy@0 415 this.pluginApi.setVideoSize(width, height);
gyorgy@0 416 }
gyorgy@0 417 },
gyorgy@0 418
gyorgy@0 419 setFullscreen: function (fullscreen) {
gyorgy@0 420 if (this.pluginApi != null) {
gyorgy@0 421 this.pluginApi.setFullscreen(fullscreen);
gyorgy@0 422 }
gyorgy@0 423 },
gyorgy@0 424
gyorgy@0 425 // start: fake events
gyorgy@0 426 addEventListener: function (eventName, callback, bubble) {
gyorgy@0 427 this.events[eventName] = this.events[eventName] || [];
gyorgy@0 428 this.events[eventName].push(callback);
gyorgy@0 429 },
gyorgy@0 430 removeEventListener: function (eventName, callback) {
gyorgy@0 431 if (!eventName) { this.events = {}; return true; }
gyorgy@0 432 var callbacks = this.events[eventName];
gyorgy@0 433 if (!callbacks) return true;
gyorgy@0 434 if (!callback) { this.events[eventName] = []; return true; }
gyorgy@0 435 for (i = 0; i < callbacks.length; i++) {
gyorgy@0 436 if (callbacks[i] === callback) {
gyorgy@0 437 this.events[eventName].splice(i, 1);
gyorgy@0 438 return true;
gyorgy@0 439 }
gyorgy@0 440 }
gyorgy@0 441 return false;
gyorgy@0 442 },
gyorgy@0 443 dispatchEvent: function (eventName) {
gyorgy@0 444 var i,
gyorgy@0 445 args,
gyorgy@0 446 callbacks = this.events[eventName];
gyorgy@0 447
gyorgy@0 448 if (callbacks) {
gyorgy@0 449 args = Array.prototype.slice.call(arguments, 1);
gyorgy@0 450 for (i = 0; i < callbacks.length; i++) {
gyorgy@0 451 callbacks[i].apply(null, args);
gyorgy@0 452 }
gyorgy@0 453 }
gyorgy@0 454 }
gyorgy@0 455 // end: fake events
gyorgy@0 456 };
gyorgy@0 457
gyorgy@0 458
gyorgy@0 459 // Handles calls from Flash/Silverlight and reports them as native <video/audio> events and properties
gyorgy@0 460 mejs.MediaPluginBridge = {
gyorgy@0 461
gyorgy@0 462 pluginMediaElements:{},
gyorgy@0 463 htmlMediaElements:{},
gyorgy@0 464
gyorgy@0 465 registerPluginElement: function (id, pluginMediaElement, htmlMediaElement) {
gyorgy@0 466 this.pluginMediaElements[id] = pluginMediaElement;
gyorgy@0 467 this.htmlMediaElements[id] = htmlMediaElement;
gyorgy@0 468 },
gyorgy@0 469
gyorgy@0 470 // when Flash/Silverlight is ready, it calls out to this method
gyorgy@0 471 initPlugin: function (id) {
gyorgy@0 472
gyorgy@0 473 var pluginMediaElement = this.pluginMediaElements[id],
gyorgy@0 474 htmlMediaElement = this.htmlMediaElements[id];
gyorgy@0 475
gyorgy@0 476 // find the javascript bridge
gyorgy@0 477 switch (pluginMediaElement.pluginType) {
gyorgy@0 478 case "flash":
gyorgy@0 479 pluginMediaElement.pluginElement = pluginMediaElement.pluginApi = document.getElementById(id);
gyorgy@0 480 break;
gyorgy@0 481 case "silverlight":
gyorgy@0 482 pluginMediaElement.pluginElement = document.getElementById(pluginMediaElement.id);
gyorgy@0 483 pluginMediaElement.pluginApi = pluginMediaElement.pluginElement.Content.MediaElementJS;
gyorgy@0 484 break;
gyorgy@0 485 }
gyorgy@0 486
gyorgy@0 487 if (pluginMediaElement.pluginApi != null && pluginMediaElement.success) {
gyorgy@0 488 pluginMediaElement.success(pluginMediaElement, htmlMediaElement);
gyorgy@0 489 }
gyorgy@0 490 },
gyorgy@0 491
gyorgy@0 492 // receives events from Flash/Silverlight and sends them out as HTML5 media events
gyorgy@0 493 // http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html
gyorgy@0 494 fireEvent: function (id, eventName, values) {
gyorgy@0 495
gyorgy@0 496 var
gyorgy@0 497 e,
gyorgy@0 498 i,
gyorgy@0 499 bufferedTime,
gyorgy@0 500 pluginMediaElement = this.pluginMediaElements[id];
gyorgy@0 501
gyorgy@0 502 pluginMediaElement.ended = false;
gyorgy@0 503 pluginMediaElement.paused = true;
gyorgy@0 504
gyorgy@0 505 // fake event object to mimic real HTML media event.
gyorgy@0 506 e = {
gyorgy@0 507 type: eventName,
gyorgy@0 508 target: pluginMediaElement
gyorgy@0 509 };
gyorgy@0 510
gyorgy@0 511 // attach all values to element and event object
gyorgy@0 512 for (i in values) {
gyorgy@0 513 pluginMediaElement[i] = values[i];
gyorgy@0 514 e[i] = values[i];
gyorgy@0 515 }
gyorgy@0 516
gyorgy@0 517 // fake the newer W3C buffered TimeRange (loaded and total have been removed)
gyorgy@0 518 bufferedTime = values.bufferedTime || 0;
gyorgy@0 519
gyorgy@0 520 e.target.buffered = e.buffered = {
gyorgy@0 521 start: function(index) {
gyorgy@0 522 return 0;
gyorgy@0 523 },
gyorgy@0 524 end: function (index) {
gyorgy@0 525 return bufferedTime;
gyorgy@0 526 },
gyorgy@0 527 length: 1
gyorgy@0 528 };
gyorgy@0 529
gyorgy@0 530 pluginMediaElement.dispatchEvent(e.type, e);
gyorgy@0 531 }
gyorgy@0 532 };
gyorgy@0 533
gyorgy@0 534 /*
gyorgy@0 535 Default options
gyorgy@0 536 */
gyorgy@0 537 mejs.MediaElementDefaults = {
gyorgy@0 538 // allows testing on HTML5, flash, silverlight
gyorgy@0 539 // auto: attempts to detect what the browser can do
gyorgy@0 540 // native: forces HTML5 playback
gyorgy@0 541 // shim: disallows HTML5, will attempt either Flash or Silverlight
gyorgy@0 542 // none: forces fallback view
gyorgy@0 543 mode: 'auto',
gyorgy@0 544 // remove or reorder to change plugin priority and availability
gyorgy@0 545 plugins: ['flash','silverlight'],
gyorgy@0 546 // shows debug errors on screen
gyorgy@0 547 enablePluginDebug: false,
gyorgy@0 548 // overrides the type specified, useful for dynamic instantiation
gyorgy@0 549 type: '',
gyorgy@0 550 // path to Flash and Silverlight plugins
gyorgy@0 551 pluginPath: mejs.Utility.getScriptPath(['mediaelement.js','mediaelement.min.js','mediaelement-and-player.js','mediaelement-and-player.min.js']),
gyorgy@0 552 // name of flash file
gyorgy@0 553 flashName: 'flashmediaelement.swf',
gyorgy@0 554 // turns on the smoothing filter in Flash
gyorgy@0 555 enablePluginSmoothing: false,
gyorgy@0 556 // name of silverlight file
gyorgy@0 557 silverlightName: 'silverlightmediaelement.xap',
gyorgy@0 558 // default if the <video width> is not specified
gyorgy@0 559 defaultVideoWidth: 480,
gyorgy@0 560 // default if the <video height> is not specified
gyorgy@0 561 defaultVideoHeight: 270,
gyorgy@0 562 // overrides <video width>
gyorgy@0 563 pluginWidth: -1,
gyorgy@0 564 // overrides <video height>
gyorgy@0 565 pluginHeight: -1,
gyorgy@0 566 // rate in milliseconds for Flash and Silverlight to fire the timeupdate event
gyorgy@0 567 // larger number is less accurate, but less strain on plugin->JavaScript bridge
gyorgy@0 568 timerRate: 250,
gyorgy@0 569 success: function () { },
gyorgy@0 570 error: function () { }
gyorgy@0 571 };
gyorgy@0 572
gyorgy@0 573 /*
gyorgy@0 574 Determines if a browser supports the <video> or <audio> element
gyorgy@0 575 and returns either the native element or a Flash/Silverlight version that
gyorgy@0 576 mimics HTML5 MediaElement
gyorgy@0 577 */
gyorgy@0 578 mejs.MediaElement = function (el, o) {
gyorgy@0 579 return mejs.HtmlMediaElementShim.create(el,o);
gyorgy@0 580 };
gyorgy@0 581
gyorgy@0 582 mejs.HtmlMediaElementShim = {
gyorgy@0 583
gyorgy@0 584 create: function(el, o) {
gyorgy@0 585 var
gyorgy@0 586 options = mejs.MediaElementDefaults,
gyorgy@0 587 htmlMediaElement = (typeof(el) == 'string') ? document.getElementById(el) : el,
gyorgy@0 588 isVideo = (htmlMediaElement.tagName.toLowerCase() == 'video'),
gyorgy@0 589 supportsMediaTag = (typeof(htmlMediaElement.canPlayType) != 'undefined'),
gyorgy@0 590 playback = {method:'', url:''},
gyorgy@0 591 poster = htmlMediaElement.getAttribute('poster'),
gyorgy@0 592 autoplay = htmlMediaElement.getAttribute('autoplay'),
gyorgy@0 593 preload = htmlMediaElement.getAttribute('preload'),
gyorgy@0 594 controls = htmlMediaElement.getAttribute('controls'),
gyorgy@0 595 prop;
gyorgy@0 596
gyorgy@0 597 // extend options
gyorgy@0 598 for (prop in o) {
gyorgy@0 599 options[prop] = o[prop];
gyorgy@0 600 }
gyorgy@0 601
gyorgy@0 602 // check for real poster
gyorgy@0 603 poster = (typeof poster == 'undefined' || poster === null) ? '' : poster;
gyorgy@0 604 preload = (typeof preload == 'undefined' || preload === null || preload === 'false') ? 'none' : preload;
gyorgy@0 605 autoplay = !(typeof autoplay == 'undefined' || autoplay === null || autoplay === 'false');
gyorgy@0 606 controls = !(typeof controls == 'undefined' || controls === null || controls === 'false');
gyorgy@0 607
gyorgy@0 608 // test for HTML5 and plugin capabilities
gyorgy@0 609 playback = this.determinePlayback(htmlMediaElement, options, isVideo, supportsMediaTag);
gyorgy@0 610
gyorgy@0 611 if (playback.method == 'native') {
gyorgy@0 612 // second fix for android
gyorgy@0 613 if (mejs.MediaFeatures.isBustedAndroid) {
gyorgy@0 614 htmlMediaElement.src = playback.url;
gyorgy@0 615 htmlMediaElement.addEventListener('click', function() {
gyorgy@0 616 htmlMediaElement.play();
gyorgy@0 617 }, true);
gyorgy@0 618 }
gyorgy@0 619
gyorgy@0 620 // add methods to native HTMLMediaElement
gyorgy@0 621 return this.updateNative( htmlMediaElement, options, autoplay, preload, playback);
gyorgy@0 622 } else if (playback.method !== '') {
gyorgy@0 623 // create plugin to mimic HTMLMediaElement
gyorgy@0 624 return this.createPlugin( htmlMediaElement, options, isVideo, playback.method, (playback.url !== null) ? mejs.Utility.absolutizeUrl(playback.url) : '', poster, autoplay, preload, controls);
gyorgy@0 625 } else {
gyorgy@0 626 // boo, no HTML5, no Flash, no Silverlight.
gyorgy@0 627 this.createErrorMessage( htmlMediaElement, options, (playback.url !== null) ? mejs.Utility.absolutizeUrl(playback.url) : '', poster );
gyorgy@0 628 }
gyorgy@0 629 },
gyorgy@0 630
gyorgy@0 631 determinePlayback: function(htmlMediaElement, options, isVideo, supportsMediaTag) {
gyorgy@0 632 var
gyorgy@0 633 mediaFiles = [],
gyorgy@0 634 i,
gyorgy@0 635 j,
gyorgy@0 636 k,
gyorgy@0 637 l,
gyorgy@0 638 n,
gyorgy@0 639 type,
gyorgy@0 640 result = { method: '', url: ''},
gyorgy@0 641 src = htmlMediaElement.getAttribute('src'),
gyorgy@0 642 pluginName,
gyorgy@0 643 pluginVersions,
gyorgy@0 644 pluginInfo;
gyorgy@0 645
gyorgy@0 646 // clean up src attr
gyorgy@0 647 if (src == 'undefined' || src == '' || src === null)
gyorgy@0 648 src = null;
gyorgy@0 649
gyorgy@0 650 // STEP 1: Get URL and type from <video src> or <source src>
gyorgy@0 651
gyorgy@0 652 // supplied type overrides all HTML
gyorgy@0 653 if (typeof (options.type) != 'undefined' && options.type !== '') {
gyorgy@0 654 mediaFiles.push({type:options.type, url:src});
gyorgy@0 655
gyorgy@0 656 // test for src attribute first
gyorgy@0 657 } else if (src !== null) {
gyorgy@0 658 type = this.checkType(src, htmlMediaElement.getAttribute('type'), isVideo);
gyorgy@0 659 mediaFiles.push({type:type, url:src});
gyorgy@0 660
gyorgy@0 661 // then test for <source> elements
gyorgy@0 662 } else {
gyorgy@0 663 // test <source> types to see if they are usable
gyorgy@0 664 for (i = 0; i < htmlMediaElement.childNodes.length; i++) {
gyorgy@0 665 n = htmlMediaElement.childNodes[i];
gyorgy@0 666 if (n.nodeType == 1 && n.tagName.toLowerCase() == 'source') {
gyorgy@0 667 src = n.getAttribute('src');
gyorgy@0 668 type = this.checkType(src, n.getAttribute('type'), isVideo);
gyorgy@0 669 mediaFiles.push({type:type, url:src});
gyorgy@0 670 }
gyorgy@0 671 }
gyorgy@0 672 }
gyorgy@0 673
gyorgy@0 674 // STEP 2: Test for playback method
gyorgy@0 675
gyorgy@0 676 // special case for Android which sadly doesn't implement the canPlayType function (always returns '')
gyorgy@0 677 if (mejs.MediaFeatures.isBustedAndroid) {
gyorgy@0 678 htmlMediaElement.canPlayType = function(type) {
gyorgy@0 679 return (type.match(/video\/(mp4|m4v)/gi) !== null) ? 'maybe' : '';
gyorgy@0 680 };
gyorgy@0 681 }
gyorgy@0 682
gyorgy@0 683
gyorgy@0 684 // test for native playback first
gyorgy@0 685 if (supportsMediaTag && (options.mode === 'auto' || options.mode === 'native')) {
gyorgy@0 686 for (i=0; i<mediaFiles.length; i++) {
gyorgy@0 687 // normal check
gyorgy@0 688 if (htmlMediaElement.canPlayType(mediaFiles[i].type).replace(/no/, '') !== ''
gyorgy@0 689 // special case for Mac/Safari 5.0.3 which answers '' to canPlayType('audio/mp3') but 'maybe' to canPlayType('audio/mpeg')
gyorgy@0 690 || htmlMediaElement.canPlayType(mediaFiles[i].type.replace(/mp3/,'mpeg')).replace(/no/, '') !== '') {
gyorgy@0 691 result.method = 'native';
gyorgy@0 692 result.url = mediaFiles[i].url;
gyorgy@0 693 return result;
gyorgy@0 694 }
gyorgy@0 695 }
gyorgy@0 696 }
gyorgy@0 697
gyorgy@0 698 // if native playback didn't work, then test plugins
gyorgy@0 699 if (options.mode === 'auto' || options.mode === 'shim') {
gyorgy@0 700 for (i=0; i<mediaFiles.length; i++) {
gyorgy@0 701 type = mediaFiles[i].type;
gyorgy@0 702
gyorgy@0 703 // test all plugins in order of preference [silverlight, flash]
gyorgy@0 704 for (j=0; j<options.plugins.length; j++) {
gyorgy@0 705
gyorgy@0 706 pluginName = options.plugins[j];
gyorgy@0 707
gyorgy@0 708 // test version of plugin (for future features)
gyorgy@0 709 pluginVersions = mejs.plugins[pluginName];
gyorgy@0 710 for (k=0; k<pluginVersions.length; k++) {
gyorgy@0 711 pluginInfo = pluginVersions[k];
gyorgy@0 712
gyorgy@0 713 // test if user has the correct plugin version
gyorgy@0 714 if (mejs.PluginDetector.hasPluginVersion(pluginName, pluginInfo.version)) {
gyorgy@0 715
gyorgy@0 716 // test for plugin playback types
gyorgy@0 717 for (l=0; l<pluginInfo.types.length; l++) {
gyorgy@0 718 // find plugin that can play the type
gyorgy@0 719 if (type == pluginInfo.types[l]) {
gyorgy@0 720 result.method = pluginName;
gyorgy@0 721 result.url = mediaFiles[i].url;
gyorgy@0 722 return result;
gyorgy@0 723 }
gyorgy@0 724 }
gyorgy@0 725 }
gyorgy@0 726 }
gyorgy@0 727 }
gyorgy@0 728 }
gyorgy@0 729 }
gyorgy@0 730
gyorgy@0 731 // what if there's nothing to play? just grab the first available
gyorgy@0 732 if (result.method === '') {
gyorgy@0 733 result.url = mediaFiles[0].url;
gyorgy@0 734 }
gyorgy@0 735
gyorgy@0 736 return result;
gyorgy@0 737 },
gyorgy@0 738
gyorgy@0 739 checkType: function(url, type, isVideo) {
gyorgy@0 740 var ext;
gyorgy@0 741
gyorgy@0 742 // if no type is supplied, fake it with the extension
gyorgy@0 743 if (url && !type) {
gyorgy@0 744 ext = url.substring(url.lastIndexOf('.') + 1);
gyorgy@0 745 return ((isVideo) ? 'video' : 'audio') + '/' + ext;
gyorgy@0 746 } else {
gyorgy@0 747 // only return the mime part of the type in case the attribute contains the codec
gyorgy@0 748 // see http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html#the-source-element
gyorgy@0 749 // `video/mp4; codecs="avc1.42E01E, mp4a.40.2"` becomes `video/mp4`
gyorgy@0 750
gyorgy@0 751 if (type && ~type.indexOf(';')) {
gyorgy@0 752 return type.substr(0, type.indexOf(';'));
gyorgy@0 753 } else {
gyorgy@0 754 return type;
gyorgy@0 755 }
gyorgy@0 756 }
gyorgy@0 757 },
gyorgy@0 758
gyorgy@0 759 createErrorMessage: function(htmlMediaElement, options, downloadUrl, poster) {
gyorgy@0 760 var errorContainer = document.createElement('div');
gyorgy@0 761 errorContainer.className = 'me-cannotplay';
gyorgy@0 762
gyorgy@0 763 try {
gyorgy@0 764 errorContainer.style.width = htmlMediaElement.width + 'px';
gyorgy@0 765 errorContainer.style.height = htmlMediaElement.height + 'px';
gyorgy@0 766 } catch (e) {}
gyorgy@0 767
gyorgy@0 768 errorContainer.innerHTML = (poster !== '') ?
gyorgy@0 769 '<a href="' + downloadUrl + '"><img src="' + poster + '" /></a>' :
gyorgy@0 770 '<a href="' + downloadUrl + '"><span>Download File</span></a>';
gyorgy@0 771
gyorgy@0 772 htmlMediaElement.parentNode.insertBefore(errorContainer, htmlMediaElement);
gyorgy@0 773 htmlMediaElement.style.display = 'none';
gyorgy@0 774
gyorgy@0 775 options.error(htmlMediaElement);
gyorgy@0 776 },
gyorgy@0 777
gyorgy@0 778 createPlugin:function(htmlMediaElement, options, isVideo, pluginType, mediaUrl, poster, autoplay, preload, controls) {
gyorgy@0 779 var width = 1,
gyorgy@0 780 height = 1,
gyorgy@0 781 pluginid = 'me_' + pluginType + '_' + (mejs.meIndex++),
gyorgy@0 782 pluginMediaElement = new mejs.PluginMediaElement(pluginid, pluginType, mediaUrl),
gyorgy@0 783 container = document.createElement('div'),
gyorgy@0 784 specialIEContainer,
gyorgy@0 785 node,
gyorgy@0 786 initVars;
gyorgy@0 787
gyorgy@0 788 // check for placement inside a <p> tag (sometimes WYSIWYG editors do this)
gyorgy@0 789 node = htmlMediaElement.parentNode;
gyorgy@0 790 while (node !== null && node.tagName.toLowerCase() != 'body') {
gyorgy@0 791 if (node.parentNode.tagName.toLowerCase() == 'p') {
gyorgy@0 792 node.parentNode.parentNode.insertBefore(node, node.parentNode);
gyorgy@0 793 break;
gyorgy@0 794 }
gyorgy@0 795 node = node.parentNode;
gyorgy@0 796 }
gyorgy@0 797
gyorgy@0 798 if (isVideo) {
gyorgy@0 799 width = (options.videoWidth > 0) ? options.videoWidth : (htmlMediaElement.getAttribute('width') !== null) ? htmlMediaElement.getAttribute('width') : options.defaultVideoWidth;
gyorgy@0 800 height = (options.videoHeight > 0) ? options.videoHeight : (htmlMediaElement.getAttribute('height') !== null) ? htmlMediaElement.getAttribute('height') : options.defaultVideoHeight;
gyorgy@0 801 } else {
gyorgy@0 802 if (options.enablePluginDebug) {
gyorgy@0 803 width = 320;
gyorgy@0 804 height = 240;
gyorgy@0 805 }
gyorgy@0 806 }
gyorgy@0 807
gyorgy@0 808 // register plugin
gyorgy@0 809 pluginMediaElement.success = options.success;
gyorgy@0 810 mejs.MediaPluginBridge.registerPluginElement(pluginid, pluginMediaElement, htmlMediaElement);
gyorgy@0 811
gyorgy@0 812 // add container (must be added to DOM before inserting HTML for IE)
gyorgy@0 813 container.className = 'me-plugin';
gyorgy@0 814 htmlMediaElement.parentNode.insertBefore(container, htmlMediaElement);
gyorgy@0 815
gyorgy@0 816 // flash/silverlight vars
gyorgy@0 817 initVars = [
gyorgy@0 818 'id=' + pluginid,
gyorgy@0 819 'isvideo=' + ((isVideo) ? "true" : "false"),
gyorgy@0 820 'autoplay=' + ((autoplay) ? "true" : "false"),
gyorgy@0 821 'preload=' + preload,
gyorgy@0 822 'width=' + width,
gyorgy@0 823 'startvolume=' + options.startVolume,
gyorgy@0 824 'timerrate=' + options.timerRate,
gyorgy@0 825 'height=' + height];
gyorgy@0 826
gyorgy@0 827 if (mediaUrl !== null) {
gyorgy@0 828 if (pluginType == 'flash') {
gyorgy@0 829 initVars.push('file=' + mejs.Utility.encodeUrl(mediaUrl));
gyorgy@0 830 } else {
gyorgy@0 831 initVars.push('file=' + mediaUrl);
gyorgy@0 832 }
gyorgy@0 833 }
gyorgy@0 834 if (options.enablePluginDebug) {
gyorgy@0 835 initVars.push('debug=true');
gyorgy@0 836 }
gyorgy@0 837 if (options.enablePluginSmoothing) {
gyorgy@0 838 initVars.push('smoothing=true');
gyorgy@0 839 }
gyorgy@0 840 if (controls) {
gyorgy@0 841 initVars.push('controls=true'); // shows controls in the plugin if desired
gyorgy@0 842 }
gyorgy@0 843
gyorgy@0 844 switch (pluginType) {
gyorgy@0 845 case 'silverlight':
gyorgy@0 846 container.innerHTML =
gyorgy@0 847 '<object data="data:application/x-silverlight-2," type="application/x-silverlight-2" id="' + pluginid + '" name="' + pluginid + '" width="' + width + '" height="' + height + '">' +
gyorgy@0 848 '<param name="initParams" value="' + initVars.join(',') + '" />' +
gyorgy@0 849 '<param name="windowless" value="true" />' +
gyorgy@0 850 '<param name="background" value="black" />' +
gyorgy@0 851 '<param name="minRuntimeVersion" value="3.0.0.0" />' +
gyorgy@0 852 '<param name="autoUpgrade" value="true" />' +
gyorgy@0 853 '<param name="source" value="' + options.pluginPath + options.silverlightName + '" />' +
gyorgy@0 854 '</object>';
gyorgy@0 855 break;
gyorgy@0 856
gyorgy@0 857 case 'flash':
gyorgy@0 858
gyorgy@0 859 if (mejs.MediaFeatures.isIE) {
gyorgy@0 860 specialIEContainer = document.createElement('div');
gyorgy@0 861 container.appendChild(specialIEContainer);
gyorgy@0 862 specialIEContainer.outerHTML =
gyorgy@0 863 '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab" ' +
gyorgy@0 864 'id="' + pluginid + '" width="' + width + '" height="' + height + '">' +
gyorgy@0 865 '<param name="movie" value="' + options.pluginPath + options.flashName + '?x=' + (new Date()) + '" />' +
gyorgy@0 866 '<param name="flashvars" value="' + initVars.join('&amp;') + '" />' +
gyorgy@0 867 '<param name="quality" value="high" />' +
gyorgy@0 868 '<param name="bgcolor" value="#000000" />' +
gyorgy@0 869 '<param name="wmode" value="transparent" />' +
gyorgy@0 870 '<param name="allowScriptAccess" value="always" />' +
gyorgy@0 871 '<param name="allowFullScreen" value="true" />' +
gyorgy@0 872 '</object>';
gyorgy@0 873
gyorgy@0 874 } else {
gyorgy@0 875
gyorgy@0 876 container.innerHTML =
gyorgy@0 877 '<embed id="' + pluginid + '" name="' + pluginid + '" ' +
gyorgy@0 878 'play="true" ' +
gyorgy@0 879 'loop="false" ' +
gyorgy@0 880 'quality="high" ' +
gyorgy@0 881 'bgcolor="#000000" ' +
gyorgy@0 882 'wmode="transparent" ' +
gyorgy@0 883 'allowScriptAccess="always" ' +
gyorgy@0 884 'allowFullScreen="true" ' +
gyorgy@0 885 'type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" ' +
gyorgy@0 886 'src="' + options.pluginPath + options.flashName + '" ' +
gyorgy@0 887 'flashvars="' + initVars.join('&') + '" ' +
gyorgy@0 888 'width="' + width + '" ' +
gyorgy@0 889 'height="' + height + '"></embed>';
gyorgy@0 890 }
gyorgy@0 891 break;
gyorgy@0 892 }
gyorgy@0 893 // hide original element
gyorgy@0 894 htmlMediaElement.style.display = 'none';
gyorgy@0 895
gyorgy@0 896 // FYI: options.success will be fired by the MediaPluginBridge
gyorgy@0 897
gyorgy@0 898 return pluginMediaElement;
gyorgy@0 899 },
gyorgy@0 900
gyorgy@0 901 updateNative: function(htmlMediaElement, options, autoplay, preload, playback) {
gyorgy@0 902 // add methods to video object to bring it into parity with Flash Object
gyorgy@0 903 for (var m in mejs.HtmlMediaElement) {
gyorgy@0 904 htmlMediaElement[m] = mejs.HtmlMediaElement[m];
gyorgy@0 905 }
gyorgy@0 906
gyorgy@0 907 /*
gyorgy@0 908 Chrome now supports preload="none"
gyorgy@0 909 if (mejs.MediaFeatures.isChrome) {
gyorgy@0 910
gyorgy@0 911 // special case to enforce preload attribute (Chrome doesn't respect this)
gyorgy@0 912 if (preload === 'none' && !autoplay) {
gyorgy@0 913
gyorgy@0 914 // forces the browser to stop loading (note: fails in IE9)
gyorgy@0 915 htmlMediaElement.src = '';
gyorgy@0 916 htmlMediaElement.load();
gyorgy@0 917 htmlMediaElement.canceledPreload = true;
gyorgy@0 918
gyorgy@0 919 htmlMediaElement.addEventListener('play',function() {
gyorgy@0 920 if (htmlMediaElement.canceledPreload) {
gyorgy@0 921 htmlMediaElement.src = playback.url;
gyorgy@0 922 htmlMediaElement.load();
gyorgy@0 923 htmlMediaElement.play();
gyorgy@0 924 htmlMediaElement.canceledPreload = false;
gyorgy@0 925 }
gyorgy@0 926 }, false);
gyorgy@0 927 // for some reason Chrome forgets how to autoplay sometimes.
gyorgy@0 928 } else if (autoplay) {
gyorgy@0 929 htmlMediaElement.load();
gyorgy@0 930 htmlMediaElement.play();
gyorgy@0 931 }
gyorgy@0 932 }
gyorgy@0 933 */
gyorgy@0 934
gyorgy@0 935 // fire success code
gyorgy@0 936 options.success(htmlMediaElement, htmlMediaElement);
gyorgy@0 937
gyorgy@0 938 return htmlMediaElement;
gyorgy@0 939 }
gyorgy@0 940 };
gyorgy@0 941
gyorgy@0 942 window.mejs = mejs;
gyorgy@0 943 window.MediaElement = mejs.MediaElement;