mistplayers.html5 = { name: 'HTML5 video player', version: '1.0', mimes: ['html5/application/vnd.apple.mpegurl','html5/video/mp4','html5/video/ogg','html5/video/webm','html5/audio/mp3','html5/audio/webm','html5/audio/ogg','html5/audio/wav'], priority: Object.keys(mistplayers).length + 1, isMimeSupported: function (mimetype) { return (this.mimes.indexOf(mimetype) == -1 ? false : true); }, isBrowserSupported: function (mimetype,source,options,streaminfo) { if ((['iPad','iPhone','iPod','MacIntel'].indexOf(navigator.platform) != -1) && (mimetype == 'html5/video/mp4')) { return false; } var support = false; var shortmime = mimetype.split('/'); shortmime.shift(); if ((shortmime[0] == 'audio') && (streaminfo.height) && (!options.forceType) && (!options.forceSource)) { //claim you don't support audio-only playback if there is video data, unless this mime is being forced return false; } try { var v = document.createElement((shortmime[0] == 'audio' ? 'audio' : 'video')); shortmime = shortmime.join('/') if ((v) && (v.canPlayType(shortmime) != "")) { support = v.canPlayType(shortmime); } } catch(e){} return support; }, player: function(){}, mistControls: true }; var p = mistplayers.html5.player; p.prototype = new MistPlayer(); p.prototype.build = function (options) { var cont = document.createElement('div'); cont.className = 'mistplayer'; var me = this; //to allow nested functions to access the player class itself var shortmime = options.source.type.split('/'); shortmime.shift(); var ele = this.getElement((shortmime[0] == 'audio' ? 'audio' : 'video')); ele.className = ''; cont.appendChild(ele); ele.crossOrigin = 'anonymous'; //required for subtitles if (shortmime[0] == 'audio') { this.setTracks = function() { return false; } this.fullscreen = false; cont.className += ' audio'; } this.addlog('Building HTML5 player..'); var source = document.createElement('source'); source.setAttribute('src',options.src); this.source = source; ele.appendChild(source); source.type = shortmime.join('/'); this.addlog('Adding '+source.type+' source @ '+options.src); if ((this.tracks.subtitle.length) && (this.subtitle)) { for (var i in this.tracks.subtitle) { var t = document.createElement('track'); ele.appendChild(t); t.kind = 'subtitles'; t.label = this.tracks.subtitle[i].desc; t.srclang = this.tracks.subtitle[i].lang; t.src = this.subtitle+'?track='+this.tracks.subtitle[i].trackid; } } ele.width = options.width; ele.height = options.height; ele.style.width = options.width+'px'; ele.style.height = options.height+'px'; if (options.autoplay) { ele.setAttribute('autoplay',''); } if (options.loop) { ele.setAttribute('loop',''); } if (options.poster) { ele.setAttribute('poster',options.poster); } if (options.controls) { if ((options.controls == 'stock') || (!this.buildMistControls())) { //MistControls have failed to build in the if condition ele.setAttribute('controls',''); } } cont.onclick = function(){ if (ele.paused) { ele.play(); } else { ele.pause(); } }; this.addlog('Built html'); //forward events ele.addEventListener('error',function(e){ if (options.live) { if ((ele.error) && (ele.error.code == 3)) { e.stopPropagation(); //dont let this error continue to prevent the core from trying to handle the error me.load(); me.cancelAskNextCombo(); e.message = 'Handled decoding error'; me.addlog('Decoding error: reloading..'); me.report({ type: 'playback', warn: 'A decoding error was encountered, but handled' }); return; } } var msg; if ('message' in e) { msg = e.message; } else if ((e.target.tagName == 'SOURCE') && (e.target.getAttribute('src') == '')) { e.stopPropagation(); //this error is triggered because the unload function was fired return; } else { msg = 'readyState: '; switch (me.element.readyState) { case 0: msg += 'HAVE_NOTHING'; break; case 1: msg += 'HAVE_METADATA'; break; case 2: msg += 'HAVE_CURRENT_DATA'; break; case 3: msg += 'HAVE_FUTURE_DATA'; break; case 4: msg += 'HAVE_ENOUGH_DATA'; break; } msg += ' networkState: '; switch (me.element.networkState) { case 0: msg += 'NETWORK_EMPTY'; break; case 1: msg += 'NETWORK_IDLE'; break; case 2: msg += 'NETWORK_LOADING'; break; case 3: msg += 'NETWORK_NO_SOURCE'; break; } } //prevent onerror loops if (e.target == me.element) { e.message = msg; } else { me.adderror(msg); } }); var events = ['abort','canplay','canplaythrough','durationchange','emptied','ended','interruptbegin','interruptend','loadeddata','loadedmetadata','loadstart','pause','play','playing','ratechange','seeked','seeking','stalled','volumechange','waiting','progress']; for (var i in events) { ele.addEventListener(events[i],function(e){ me.addlog('Player event fired: '+e.type); }); } return cont; } p.prototype.play = function(){ return this.element.play(); }; p.prototype.pause = function(){ return this.element.pause(); }; p.prototype.volume = function(level){ if (typeof level == 'undefined' ) { return this.element.volume; } return this.element.volume = level; }; p.prototype.loop = function(bool){ if (typeof bool == 'undefined') { return this.element.loop; } return this.element.loop = bool; }; p.prototype.load = function(){ var load; if (this.element.paused) { load = this.element.load(); } else { //sometimes there is a play / pause interrupt: try again //TODO figure out if this happens on paused or on playing this.load(); return; } //this helps to prevent the player from just showing a black screen after a reload if (this.element.paused) { var me = this; var unpause = function(){ if (me.element.paused) { me.element.play(); } me.element.removeEventListener('progress',unpause); } this.element.addEventListener('progress',unpause); } return load; }; if (document.fullscreenEnabled || document.webkitFullscreenEnabled || document.mozFullScreenEnabled || document.msFullscreenEnabled) { p.prototype.fullscreen = function(){ if(this.element.requestFullscreen) { return this.element.requestFullscreen(); } else if(this.element.mozRequestFullScreen) { return this.element.mozRequestFullScreen(); } else if(this.element.webkitRequestFullscreen) { return this.element.webkitRequestFullscreen(); } else if(this.element.msRequestFullscreen) { return this.element.msRequestFullscreen(); } }; } p.prototype.updateSrc = function(src){ this.source.setAttribute('src',src); return true; }; p.prototype.resize = function(size){ this.element.width = size.width; this.element.height = size.height; };