Embed: player switching
This commit is contained in:
parent
d5c526173b
commit
b3c6aedf5b
5 changed files with 158 additions and 57 deletions
137
embed/core.js
137
embed/core.js
|
@ -544,7 +544,54 @@ MistPlayer.prototype.buildMistControls = function(){
|
|||
|
||||
return true;
|
||||
}
|
||||
MistPlayer.prototype.askNextCombo = function(){
|
||||
var me = this;
|
||||
me.errorstate = true;
|
||||
|
||||
var err = document.createElement('div');
|
||||
var msgnode = document.createTextNode('Player or stream error detected');
|
||||
err.appendChild(msgnode);
|
||||
err.className = 'error';
|
||||
var button = document.createElement('button');
|
||||
var t = document.createTextNode('Try next source/player');
|
||||
button.appendChild(t);
|
||||
err.appendChild(button);
|
||||
button.onclick = function(){
|
||||
me.nextCombo();
|
||||
}
|
||||
var button = document.createElement('button');
|
||||
var t = document.createTextNode('Reload this player');
|
||||
button.appendChild(t);
|
||||
err.appendChild(button);
|
||||
button.onclick = function(){
|
||||
me.reload();
|
||||
}
|
||||
err.style.position = 'absolute';
|
||||
err.style.top = 0;
|
||||
err.style.width = '100%';
|
||||
err.style['margin-left'] = 0;
|
||||
|
||||
this.target.appendChild(err);
|
||||
this.element.style.opacity = '0.2';
|
||||
};
|
||||
MistPlayer.prototype.cancelAskNextCombo = function(){
|
||||
if (this.errorstate) {
|
||||
this.element.style.opacity = 1;
|
||||
var err = this.target.querySelector('.error');
|
||||
if (err) {
|
||||
this.target.removeChild(err);
|
||||
}
|
||||
this.errorstate = false;
|
||||
}
|
||||
};
|
||||
MistPlayer.prototype.reload = function(){
|
||||
mistPlay(this.mistplaySettings.streamname,this.mistplaySettings.options);
|
||||
};
|
||||
MistPlayer.prototype.nextCombo = function(){
|
||||
var opts = this.mistplaySettings.options;
|
||||
opts.startCombo = this.mistplaySettings.startCombo;
|
||||
mistPlay(this.mistplaySettings.streamname,opts);
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////
|
||||
// SELECT AND ADD A VIDEO PLAYER TO THE TARGET //
|
||||
|
@ -557,7 +604,8 @@ function mistPlay(streamName,options) {
|
|||
protoplay.sendEvent('log',msg,options.target);
|
||||
}
|
||||
function mistError(msg) {
|
||||
var info = mistvideo[streamName];
|
||||
var info = {};
|
||||
if ((typeof mistvideo != 'undefined') && ('streamName' in mistvideo)) { info = mistvideo[streamName]; }
|
||||
var displaymsg = msg;
|
||||
if ('on_error' in info) { displaymsg = info.on_error; }
|
||||
|
||||
|
@ -570,6 +618,7 @@ function mistPlay(streamName,options) {
|
|||
err.appendChild(button);
|
||||
button.onclick = function(){
|
||||
options.target.removeChild(err);
|
||||
delete options.startCombo;
|
||||
mistPlay(streamName,options);
|
||||
}
|
||||
|
||||
|
@ -625,10 +674,12 @@ function mistPlay(streamName,options) {
|
|||
embedLog('Retrieving stream info from '+info.src);
|
||||
document.head.appendChild(info);
|
||||
info.onerror = function(){
|
||||
options.target.innerHTML = '';
|
||||
options.target.removeAttribute('data-loading');
|
||||
mistError('Error while loading stream info.');
|
||||
}
|
||||
info.onload = function(){
|
||||
options.target.innerHTML = '';
|
||||
options.target.removeAttribute('data-loading');
|
||||
embedLog('Stream info was loaded succesfully');
|
||||
|
||||
|
@ -640,6 +691,11 @@ function mistPlay(streamName,options) {
|
|||
//embedLog('Stream info contents: '+JSON.stringify(streaminfo));
|
||||
streaminfo.initTime = new Date();
|
||||
|
||||
if (!('source' in streaminfo)) {
|
||||
mistError('Error while loading stream info.');
|
||||
return;
|
||||
}
|
||||
|
||||
//sort the sources by priority and mime, but prefer HTTPS
|
||||
streaminfo.source.sort(function(a,b){
|
||||
return (b.priority - a.priority) || a.type.localeCompare(b.type) || b.url.localeCompare(a.url);
|
||||
|
@ -673,6 +729,15 @@ function mistPlay(streamName,options) {
|
|||
embedLog('The forced player ('+options.forcePlayer+') isn\'t known, ignoring. Possible values are: '+Object.keys(mistplayers).join(', '));
|
||||
}
|
||||
}
|
||||
var startCombo = false;
|
||||
if ('startCombo' in options) {
|
||||
startCombo = options.startCombo;
|
||||
startCombo.started = {
|
||||
player: false,
|
||||
source: false
|
||||
};
|
||||
embedLog('Selecting a new player/source combo, starting after '+mistplayers[startCombo.player].name+' with '+streaminfo.source[startCombo.source].type+' @ '+streaminfo.source[startCombo.source].url);
|
||||
}
|
||||
|
||||
embedLog('Checking available players..');
|
||||
|
||||
|
@ -680,6 +745,12 @@ function mistPlay(streamName,options) {
|
|||
var mistPlayer = false;
|
||||
|
||||
function checkPlayer(p_shortname) {
|
||||
if ((startCombo) && (!startCombo.started.player)) {
|
||||
if (p_shortname != startCombo.player) { return false; }
|
||||
else {
|
||||
startCombo.started.player = true;
|
||||
}
|
||||
}
|
||||
|
||||
embedLog('Checking '+mistplayers[p_shortname].name+' (priority: '+mistplayers[p_shortname].priority+') ..');
|
||||
streaminfo.working[p_shortname] = [];
|
||||
|
@ -706,22 +777,39 @@ function mistPlay(streamName,options) {
|
|||
else {
|
||||
loop = streaminfo.source;
|
||||
}
|
||||
var broadcast = false;
|
||||
for (var s in loop) {
|
||||
if (loop[s].type == mime) {
|
||||
if (mistplayers[p_shortname].isBrowserSupported(mime,loop[s],options)) {
|
||||
broadcast = true;
|
||||
|
||||
if ((startCombo) && (!startCombo.started.source)) {
|
||||
if (s == startCombo.source) {
|
||||
startCombo.started.source = true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mistplayers[p_shortname].isBrowserSupported(mime,loop[s],options,streaminfo)) {
|
||||
embedLog('Found a working combo: '+mistplayers[p_shortname].name+' with '+mime+' @ '+loop[s].url);
|
||||
streaminfo.working[p_shortname].push(mime);
|
||||
if (!source) {
|
||||
mistPlayer = p_shortname;
|
||||
source = loop[s];
|
||||
source.index = s;
|
||||
}
|
||||
if (!forceSupportCheck) {
|
||||
return source;
|
||||
}
|
||||
}
|
||||
else {
|
||||
embedLog('This browser does not support '+mime);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if (!broadcast) {
|
||||
embedLog('Mist doesn\'t broadcast '+mime);
|
||||
}
|
||||
embedLog('Mist doesn\'t broadcast '+mime+' or there is no browser support.');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -742,7 +830,6 @@ function mistPlay(streamName,options) {
|
|||
}
|
||||
}
|
||||
|
||||
options.target.innerHTML = '';
|
||||
if (mistPlayer) {
|
||||
//create the options to send to the player
|
||||
var playerOpts = {
|
||||
|
@ -870,8 +957,25 @@ function mistPlay(streamName,options) {
|
|||
}
|
||||
|
||||
//build the player
|
||||
player.mistplaySettings = {
|
||||
streamname: streamName,
|
||||
options: local,
|
||||
startCombo: {
|
||||
player: mistPlayer,
|
||||
source: source.index
|
||||
}
|
||||
};
|
||||
player.options = playerOpts;
|
||||
var element = player.build(playerOpts);
|
||||
try {
|
||||
var element = player.build(playerOpts);
|
||||
}
|
||||
catch (e) {
|
||||
//show the next player/reload buttons if there is an error in the player build code
|
||||
options.target.appendChild(player.element);
|
||||
player.askNextCombo();
|
||||
throw e;
|
||||
return;
|
||||
}
|
||||
options.target.appendChild(element);
|
||||
element.setAttribute('data-player',mistPlayer);
|
||||
element.setAttribute('data-mime',source.type);
|
||||
|
@ -884,7 +988,28 @@ function mistPlay(streamName,options) {
|
|||
}
|
||||
|
||||
//monitor for errors
|
||||
//TODO
|
||||
player.checkPlayingTimeout = false;
|
||||
element.addEventListener('error',function(e){
|
||||
player.askNextCombo();
|
||||
},true);
|
||||
var stalled = function(e){
|
||||
if (player.checkPlayingTimeout) { return; }
|
||||
player.checkPlayingTimeout = setTimeout(function(){
|
||||
if (player.element.readyState >= 2) { return; }
|
||||
player.askNextCombo();
|
||||
},5e3);
|
||||
};
|
||||
element.addEventListener('stalled',stalled,true);
|
||||
element.addEventListener('waiting',stalled,true);
|
||||
var progress = function(e){
|
||||
if (player.checkPlayingTimeout) {
|
||||
clearTimeout(player.checkPlayingTimeout);
|
||||
player.checkPlayingTimeout = false;
|
||||
player.cancelAskNextCombo();
|
||||
}
|
||||
};
|
||||
element.addEventListener('progress',progress,true);
|
||||
element.addEventListener('playing',progress,true);
|
||||
|
||||
if (player.resize) {
|
||||
//monitor for resizes and fire if needed
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
color: white;
|
||||
font-family: sans-serif;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
text-shadow: 0 0 1px black, 0 0 1px black;
|
||||
}
|
||||
.mistvideo[data-loading] {
|
||||
background-image: none;
|
||||
|
@ -35,11 +37,16 @@
|
|||
}
|
||||
.mistvideo .error {
|
||||
margin: 225px 20px 20px;
|
||||
min-width: 300px;
|
||||
z-index: 69;
|
||||
}
|
||||
.mistvideo .error button {
|
||||
margin: 5px auto;
|
||||
display: block;
|
||||
}
|
||||
.mistvideo .vjs-error-display:before {
|
||||
content: '' !important;
|
||||
}
|
||||
.mistplayer {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
|
|
@ -15,9 +15,9 @@
|
|||
<script>
|
||||
// global options can be set here
|
||||
var mistoptions = {
|
||||
//host: 'http://cat.mistserver.org:8080'
|
||||
host: 'http://cat.mistserver.org:8080'
|
||||
//host: 'https://cat.mistserver.org:4433'
|
||||
host: 'http://localhost:8080'
|
||||
//host: 'http://localhost:8080'
|
||||
};
|
||||
</script>
|
||||
|
||||
|
@ -76,9 +76,10 @@
|
|||
|
||||
//tryplayers = Object.keys(mistplayers);
|
||||
tryplayers = [];
|
||||
tryplayers.push('derp');
|
||||
//tryplayers.push('html5');
|
||||
//tryplayers.push('dashjs');
|
||||
tryplayers.push('videojs');
|
||||
//tryplayers.push('videojs');
|
||||
//tryplayers.push('flash_strobe');
|
||||
//tryplayers.push('silverlight');
|
||||
streams = [];
|
||||
|
@ -86,8 +87,9 @@
|
|||
//streams.push('subtel');
|
||||
//streams.push('ogg');
|
||||
//streams.push('vids+mist.mp4');
|
||||
streams.push('vids+hahalol.mp3');
|
||||
//streams.push('lama');
|
||||
streams.push('bunny');
|
||||
//streams.push('bunny');
|
||||
|
||||
for (var j in streams) {
|
||||
for (var i in tryplayers) {
|
||||
|
@ -100,7 +102,7 @@
|
|||
maxwidth: 800,
|
||||
forcePlayer: tryplayers[i],
|
||||
//forceType: 'html5/video/mp4',
|
||||
forceType: 'html5/application/vnd.apple.mpegurl',
|
||||
//forceType: 'html5/application/vnd.apple.mpegurl',
|
||||
//forceType: 'dash/video/mp4',
|
||||
//forceSource: 5,
|
||||
loop: true,
|
||||
|
|
|
@ -5,11 +5,18 @@ mistplayers.html5 = {
|
|||
isMimeSupported: function (mimetype) {
|
||||
return (this.mimes.indexOf(mimetype) == -1 ? false : true);
|
||||
},
|
||||
isBrowserSupported: function (mimetype) {
|
||||
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)) {
|
||||
//claim you don't support audio only playback if there is video data
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
var v = document.createElement((shortmime[0] == 'audio' ? 'audio' : 'video'));
|
||||
shortmime = shortmime.join('/')
|
||||
|
@ -35,9 +42,9 @@ p.prototype.build = function (options) {
|
|||
var ele = this.element((shortmime[0] == 'audio' ? 'audio' : 'video'));
|
||||
ele.className = '';
|
||||
cont.appendChild(ele);
|
||||
//ele.crossOrigin = 'anonymous';
|
||||
ele.crossOrigin = 'anonymous'; //required for subtitles
|
||||
if (shortmime[0] == 'audio') {
|
||||
this.setTracks = false;
|
||||
this.setTracks = function() { return false; }
|
||||
this.fullscreen = false;
|
||||
cont.className += ' audio';
|
||||
}
|
||||
|
@ -92,51 +99,10 @@ p.prototype.build = function (options) {
|
|||
ele.addEventListener('error',function(e){
|
||||
if ((ele.error) && (ele.error.code == 3)) {
|
||||
ele.load();
|
||||
me.cancelAskNextCombo();
|
||||
me.addlog('Decoding error: reloading..');
|
||||
}
|
||||
},true);
|
||||
|
||||
var errorstate = false;
|
||||
function dced(e) {
|
||||
if (errorstate) { return; }
|
||||
|
||||
errorstate = true;
|
||||
me.adderror('Connection lost..');
|
||||
|
||||
var err = document.createElement('div');
|
||||
var msgnode = document.createTextNode('Connection lost..');
|
||||
err.appendChild(msgnode);
|
||||
err.className = 'error';
|
||||
var button = document.createElement('button');
|
||||
var t = document.createTextNode('Reload');
|
||||
button.appendChild(t);
|
||||
err.appendChild(button);
|
||||
button.onclick = function(){
|
||||
errorstate = false;
|
||||
ele.parentNode.removeChild(err);
|
||||
ele.load();
|
||||
ele.style.opacity = '';
|
||||
}
|
||||
err.style.position = 'absolute';
|
||||
err.style.top = 0;
|
||||
err.style.width = '100%';
|
||||
err.style['margin-left'] = 0;
|
||||
|
||||
ele.parentNode.appendChild(err);
|
||||
ele.style.opacity = '0.2';
|
||||
|
||||
function nolongerdced(){
|
||||
ele.removeEventListener('progress',nolongerdced);
|
||||
errorstate = false;
|
||||
ele.parentNode.removeChild(err);
|
||||
ele.style.opacity = '';
|
||||
}
|
||||
ele.addEventListener('progress',nolongerdced);
|
||||
}
|
||||
|
||||
ele.addEventListener('stalled',dced,true);
|
||||
ele.addEventListener('ended',dced,true);
|
||||
ele.addEventListener('pause',dced,true);
|
||||
}
|
||||
|
||||
this.addlog('Built html');
|
||||
|
|
|
@ -25,6 +25,7 @@ p.prototype.build = function (options) {
|
|||
var ele = this.element('video');
|
||||
cont.appendChild(ele);
|
||||
ele.className = '';
|
||||
ele.crossOrigin = 'anonymous'; //required for subtitles
|
||||
|
||||
var shortmime = options.source.type.split('/');
|
||||
shortmime.shift();
|
||||
|
|
Loading…
Add table
Reference in a new issue