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