Merge branch 'development' into LTS_development
This commit is contained in:
commit
51a65209fa
20 changed files with 59389 additions and 249 deletions
File diff suppressed because one or more lines are too long
|
@ -1 +1 @@
|
|||
mistplayers.dashjs={name:"Dash.js player",mimes:["dash/video/mp4"],priority:MistUtil.object.keys(mistplayers).length+1,isMimeSupported:function(t){return MistUtil.array.indexOf(this.mimes,t)==-1?false:true},isBrowserSupported:function(t,e,i){if(location.protocol!=MistUtil.http.url.split(e.url).protocol){i.log("HTTP/HTTPS mismatch for this source");return false}if(location.protocol=="file:"){i.log("This source ("+t+") won't load if the page is run via file://");return false}return"MediaSource"in window},player:function(){this.onreadylist=[]},scriptsrc:function(t){return t+"/dashjs.js"}};var p=mistplayers.dashjs.player;p.prototype=new MistPlayer;p.prototype.build=function(t,e){var i=this;this.onDashLoad=function(){if(t.destroyed){return}t.log("Building DashJS player..");var a=document.createElement("video");if("Proxy"in window){var r={get:{},set:{}};t.player.api=new Proxy(a,{get:function(t,e,i){if(e in r.get){return r.get[e].apply(t,arguments)}var a=t[e];if(typeof a==="function"){return function(){return a.apply(t,arguments)}}return a},set:function(t,e,i){if(e in r.set){return r.set[e].call(t,i)}return t[e]=i}});if(t.info.type=="live"){r.get.duration=function(){var e=0;if(this.buffered.length){e=this.buffered.end(this.buffered.length-1)}var i=((new Date).getTime()-t.player.api.lastProgress.getTime())*.001;return e+i+-1*t.player.api.liveOffset+45};r.set.currentTime=function(e){var i=e-t.player.api.duration;t.log("Seeking to "+MistUtil.format.time(e)+" ("+Math.round(i*-10)/10+"s from live)");t.video.currentTime=e};MistUtil.event.addListener(a,"progress",function(){t.player.api.lastProgress=new Date});t.player.api.lastProgress=new Date;t.player.api.liveOffset=0}}else{i.api=a}if(t.options.autoplay){a.setAttribute("autoplay","")}if(t.options.loop&&t.info.type!="live"){a.setAttribute("loop","")}if(t.options.poster){a.setAttribute("poster",t.options.poster)}if(t.options.muted){a.muted=true}if(t.options.controls=="stock"){a.setAttribute("controls","")}var s=dashjs.MediaPlayer().create();s.initialize(a,t.source.url,t.options.autoplay);i.dash=s;var n=["METRIC_ADDED","METRIC_CHANGED","METRICS_CHANGED","FRAGMENT_LOADING_STARTED","FRAGMENT_LOADING_COMPLETED","LOG","PLAYBACK_TIME_UPDATED","PLAYBACK_PROGRESS"];for(var o in dashjs.MediaPlayer.events){if(n.indexOf(o)<0){i.dash.on(dashjs.MediaPlayer.events[o],function(e){t.log("Player event fired: "+e.type)})}}t.player.setSize=function(t){this.api.style.width=t.width+"px";this.api.style.height=t.height+"px"};t.player.api.setSource=function(e){t.player.dash.attachSource(e)};t.player.api.setTrack=function(e,a){var r=MistUtil.tracks.parse(t.info.meta.tracks);if(!(e in r)||!(a in r[e])&&a!="none"){t.log("Skipping trackselection of "+e+" track "+a+" because it does not exist");return}var s=[];for(var n in t.info.meta.tracks){var o=t.info.meta.tracks[n];if(o.type==e){s.push(o)}}MistUtil.array.multiSort(s,["bps"]);var l=false;for(var n in s){var d="idx"in s[n]?s[n].idx:s[n].trackid;if(d==a){l=n;break}}if(l===false){return false}i.dash.setAutoSwitchQualityFor(e,false);i.dash.setFastSwitchEnabled(true);i.dash.setQualityFor(e,l);return true};i.dash.on("qualityChangeRendered",function(e){var i=[];for(var a in t.info.meta.tracks){var r=t.info.meta.tracks[a];if(r.type==e.mediaType){i.push(r)}}MistUtil.array.multiSort(i,["bps"]);var s="idx"in i[e.newQuality]?i[e.newQuality].idx:i[e.newQuality].trackid;MistUtil.event.send("playerUpdate_trackChanged",{type:e.mediaType,trackid:s},t.video)});var l=false;i.dash.on("allTextTracksAdded",function(){l=true});t.player.api.setSubtitle=function(e){if(!l){var a=function(){t.player.api.setSubtitle(e);i.dash.off("allTextTracksAdded",a)};i.dash.on("allTextTracksAdded",a);return}if(!e){i.dash.enableText(false);return}var r=i.dash.getTracksFor("text");for(var s in r){var n="idx"in e?e.idx:e.trackid;if(r[s].id==n){i.dash.setTextTrack(s);if(!i.dash.isTextEnabled()){i.dash.enableText()}return true}}return false};MistUtil.event.addListener(a,"progress",function(e){if(t.container.getAttribute("data-loading")=="stalled"){t.container.removeAttribute("data-loading")}});i.api.unload=function(){i.dash.reset()};t.log("Built html");e(a)};if("dashjs"in window){this.onDashLoad()}else{var a=MistUtil.scripts.insert(t.urlappend(mistplayers.dashjs.scriptsrc(t.options.host)),{onerror:function(e){var i="Failed to load dashjs.js";if(e.message){i+=": "+e.message}t.showError(i)},onload:i.onDashLoad},t)}};
|
||||
mistplayers.dashjs={name:"Dash.js player",mimes:["dash/video/mp4"],priority:MistUtil.object.keys(mistplayers).length+1,isMimeSupported:function(e){return MistUtil.array.indexOf(this.mimes,e)==-1?false:true},isBrowserSupported:function(e,t,i){if(location.protocol!=MistUtil.http.url.split(t.url).protocol){i.log("HTTP/HTTPS mismatch for this source");return false}if(location.protocol=="file:"){i.log("This source ("+e+") won't load if the page is run via file://");return false}return"MediaSource"in window},player:function(){this.onreadylist=[]},scriptsrc:function(e){return e+"/dashjs.js"}};var p=mistplayers.dashjs.player;p.prototype=new MistPlayer;p.prototype.build=function(e,t){var i=this;this.onDashLoad=function(){if(e.destroyed){return}e.log("Building DashJS player..");var r=document.createElement("video");if("Proxy"in window){var a={get:{},set:{}};e.player.api=new Proxy(r,{get:function(e,t,i){if(t in a.get){return a.get[t].apply(e,arguments)}var r=e[t];if(typeof r==="function"){return function(){return r.apply(e,arguments)}}return r},set:function(e,t,i){if(t in a.set){return a.set[t].call(e,i)}return e[t]=i}});if(e.info.type=="live"){a.get.duration=function(){var t=0;if(this.buffered.length){t=this.buffered.end(this.buffered.length-1)}var i=((new Date).getTime()-e.player.api.lastProgress.getTime())*.001;return t+i+-1*e.player.api.liveOffset+45};a.set.currentTime=function(t){var i=t-e.player.api.duration;e.log("Seeking to "+MistUtil.format.time(t)+" ("+Math.round(i*-10)/10+"s from live)");e.video.currentTime=t};MistUtil.event.addListener(r,"progress",function(){e.player.api.lastProgress=new Date});e.player.api.lastProgress=new Date;e.player.api.liveOffset=0}}else{i.api=r}if(e.options.autoplay){r.setAttribute("autoplay","")}if(e.options.loop&&e.info.type!="live"){r.setAttribute("loop","")}if(e.options.poster){r.setAttribute("poster",e.options.poster)}if(e.options.muted){r.muted=true}if(e.options.controls=="stock"){r.setAttribute("controls","")}var s=dashjs.MediaPlayer().create();s.initialize(r,e.source.url,e.options.autoplay);i.dash=s;var o=["METRIC_ADDED","METRIC_CHANGED","METRICS_CHANGED","FRAGMENT_LOADING_STARTED","FRAGMENT_LOADING_COMPLETED","LOG","PLAYBACK_TIME_UPDATED","PLAYBACK_PROGRESS"];for(var n in dashjs.MediaPlayer.events){if(o.indexOf(n)<0){i.dash.on(dashjs.MediaPlayer.events[n],function(t){e.log("Player event fired: "+t.type)})}}e.player.setSize=function(e){this.api.style.width=e.width+"px";this.api.style.height=e.height+"px"};e.player.api.setSource=function(t){e.player.dash.attachSource(t)};var l=false;i.dash.on("allTextTracksAdded",function(){l=true});e.player.api.setSubtitle=function(t){if(!l){var r=function(){e.player.api.setSubtitle(t);i.dash.off("allTextTracksAdded",r)};i.dash.on("allTextTracksAdded",r);return}if(!t){i.dash.enableText(false);return}var a=i.dash.getTracksFor("text");for(var s in a){var o="idx"in t?t.idx:t.trackid;if(a[s].id==o){i.dash.setTextTrack(s);if(!i.dash.isTextEnabled()){i.dash.enableText()}return true}}return false};MistUtil.event.addListener(r,"progress",function(t){if(e.container.getAttribute("data-loading")=="stalled"){e.container.removeAttribute("data-loading")}});i.api.unload=function(){i.dash.reset()};e.log("Built html");t(r)};if("dashjs"in window){this.onDashLoad()}else{var r=MistUtil.scripts.insert(e.urlappend(mistplayers.dashjs.scriptsrc(e.options.host)),{onerror:function(t){var i="Failed to load dashjs.js";if(t.message){i+=": "+t.message}e.showError(i)},onload:i.onDashLoad},e)}};
|
|
@ -1 +1 @@
|
|||
mistplayers.videojs={name:"VideoJS player",mimes:["html5/application/vnd.apple.mpegurl"],priority:MistUtil.object.keys(mistplayers).length+1,isMimeSupported:function(e){return this.mimes.indexOf(e)==-1?false:true},isBrowserSupported:function(e,t,i){if(location.protocol!=MistUtil.http.url.split(t.url).protocol){i.log("HTTP/HTTPS mismatch for this source");return false}if(location.protocol=="file:"&&e=="html5/application/vnd.apple"){i.log("This source ("+e+") won't load if the page is run via file://");return false}return"MediaSource"in window},player:function(){},scriptsrc:function(e){return e+"/videojs.js"}};var p=mistplayers.videojs.player;p.prototype=new MistPlayer;p.prototype.build=function(e,t){var i=this;function r(){if(e.destroyed){return}e.log("Building VideoJS player..");var r=document.createElement("video");if(e.source.type!="html5/video/ogg"){r.crossOrigin="anonymous"}var o=e.source.type.split("/");o.shift();var n=document.createElement("source");n.setAttribute("src",e.source.url);i.source=n;r.appendChild(n);n.type=o.join("/");e.log("Adding "+n.type+" source @ "+e.source.url);if(n.type=="application/vnd.apple.mpegurl"){n.type="application/x-mpegURL"}MistUtil.class.add(r,"video-js");var s={};if(e.options.autoplay){s.autoplay=true}if(e.options.loop&&e.info.type!="live"){s.loop=true;r.loop=true}if(e.options.muted){s.muted=true;r.muted=true}if(e.options.poster){s.poster=e.options.poster}if(e.options.controls=="stock"){r.setAttribute("controls","");if(!document.getElementById("videojs-css")){var l=document.createElement("link");l.rel="stylesheet";l.href=e.options.host+"/skins/videojs.css";l.id="videojs-css";document.head.appendChild(l)}}i.onready(function(){i.videojs=videojs(r,s,function(){e.log("Videojs initialized")});i.api.unload=function(){videojs(r).dispose()}});e.log("Built html");if("Proxy"in window&&"Reflect"in window){var a={get:{},set:{}};e.player.api=new Proxy(r,{get:function(e,t,i){if(t in a.get){return a.get[t].apply(e,arguments)}var r=e[t];if(typeof r==="function"){return function(){return r.apply(e,arguments)}}return r},set:function(e,t,i){if(t in a.set){return a.set[t].call(e,i)}return e[t]=i}});if(e.info.type=="live"){function p(e){var t=0;if(e.buffered.length){t=e.buffered.end(e.buffered.length-1)}return t}var u=90;a.get.duration=function(){return(e.info.lastms+(new Date).getTime()-e.info.updated.getTime())*.001};e.player.api.lastProgress=new Date;e.player.api.liveOffset=0;MistUtil.event.addListener(r,"progress",function(){e.player.api.lastProgress=new Date});a.set.currentTime=function(t){var i=e.player.api.currentTime-t;var r=t-e.player.api.duration;e.log("Seeking to "+MistUtil.format.time(t)+" ("+Math.round(r*-10)/10+"s from live)");e.video.currentTime-=i};a.get.currentTime=function(){return this.currentTime+e.info.lastms*.001-e.player.api.liveOffset-u}}}else{i.api=r}e.player.setSize=function(t){if("videojs"in e.player){e.player.videojs.dimensions(t.width,t.height);r.parentNode.style.width=t.width+"px";r.parentNode.style.height=t.height+"px"}this.api.style.width=t.width+"px";this.api.style.height=t.height+"px"};e.player.api.setSource=function(t){if(!e.player.videojs){return}if(e.player.videojs.src()!=t){e.player.videojs.src({type:e.player.videojs.currentSource().type,src:t})}};e.player.api.setSubtitle=function(e){var t=r.getElementsByTagName("track");for(var i=t.length-1;i>=0;i--){r.removeChild(t[i])}if(e){var o=document.createElement("track");r.appendChild(o);o.kind="subtitles";o.label=e.label;o.srclang=e.lang;o.src=e.src;o.setAttribute("default","")}};t(r)}if("videojs"in window){r()}else{var o=MistUtil.scripts.insert(e.urlappend(mistplayers.videojs.scriptsrc(e.options.host)),{onerror:function(t){var i="Failed to load videojs.js";if(t.message){i+=": "+t.message}e.showError(i)},onload:r},e)}};
|
||||
mistplayers.videojs={name:"VideoJS player",mimes:["html5/application/vnd.apple.mpegurl","html5/application/vnd.apple.mpegurl;version=7"],priority:MistUtil.object.keys(mistplayers).length+1,isMimeSupported:function(e){return this.mimes.indexOf(e)==-1?false:true},isBrowserSupported:function(e,t,i){if(location.protocol!=MistUtil.http.url.split(t.url).protocol){i.log("HTTP/HTTPS mismatch for this source");return false}if(location.protocol=="file:"&&e=="html5/application/vnd.apple"){i.log("This source ("+e+") won't load if the page is run via file://");return false}return"MediaSource"in window},player:function(){},scriptsrc:function(e){return e+"/videojs.js"}};var p=mistplayers.videojs.player;p.prototype=new MistPlayer;p.prototype.build=function(e,t){var i=this;var r;function o(){if(e.destroyed){return}e.log("Building VideoJS player..");r=document.createElement("video");if(e.source.type!="html5/video/ogg"){r.crossOrigin="anonymous"}var o=e.source.type.split("/");if(o[0]=="html5"){o.shift()}var s=document.createElement("source");s.setAttribute("src",e.source.url);i.source=s;r.appendChild(s);s.type=o.join("/");e.log("Adding "+s.type+" source @ "+e.source.url);MistUtil.class.add(r,"video-js");var n={};if(e.options.autoplay){n.autoplay=true}if(e.options.loop&&e.info.type!="live"){r.setAttribute("loop","")}if(e.options.muted){r.setAttribute("muted","")}if(e.options.poster){n.poster=e.options.poster}if(e.options.controls=="stock"){r.setAttribute("controls","");if(!document.getElementById("videojs-css")){var a=document.createElement("link");a.rel="stylesheet";a.href=e.options.host+"/skins/videojs.css";a.id="videojs-css";document.head.appendChild(a)}}else{n.controls=false}i.onready(function(){e.log("Building videojs");i.videojs=videojs(r,n,function(){e.log("Videojs initialized")});i.api.unload=function(){if(i.videojs){videojs(r).dispose();i.videojs=false;e.log("Videojs instance disposed")}};MistUtil.event.addListener(e.options.target,"error",function(t){var r=false;switch(t.message){case"Stream is shutting down":{t.preventDefault();break}case"Stream is offline":{e.clearError();t.preventDefault();if(e.video){r=MistUtil.event.addListener(e.video,"ended",function(){e.showError("Stream is offline ",{polling:true});if(r){MistUtil.event.removeListener(r)}})}break}case"Stream is waiting for data":{if(r){MistUtil.event.removeListener(r)}i.api.pause();e.reload();break}}},e.video)});e.log("Built html");if("Proxy"in window&&"Reflect"in window){var l={get:{},set:{}};e.player.api=new Proxy(r,{get:function(e,t,i){if(t in l.get){return l.get[t].apply(e,arguments)}var r=e[t];if(typeof r==="function"){return function(){return r.apply(e,arguments)}}return r},set:function(e,t,i){if(t in l.set){return l.set[t].call(e,i)}return e[t]=i}});e.player.api.load=function(){};if(e.info.type=="live"){function p(e){var t=0;if(e.buffered.length){t=e.buffered.end(e.buffered.length-1)}return t}var d=0;l.get.duration=function(){if(e.info){var t=(e.info.lastms+(new Date).getTime()-e.info.updated.getTime())*.001;return t}return 0};e.player.api.lastProgress=new Date;e.player.api.liveOffset=0;MistUtil.event.addListener(r,"progress",function(){e.player.api.lastProgress=new Date});l.set.currentTime=function(t){var i=e.player.api.currentTime-t;var r=t-e.player.api.duration;e.log("Seeking to "+MistUtil.format.time(t)+" ("+Math.round(r*-10)/10+"s from live)");e.video.currentTime-=i};var u=0;l.get.currentTime=function(){if(e.info){u=e.info.lastms*.001}var t=this.currentTime+u-e.player.api.liveOffset-d;if(isNaN(t)){return 0}return t}}}else{i.api=r}e.player.setSize=function(t){if("videojs"in e.player){e.player.videojs.dimensions(t.width,t.height);r.parentNode.style.width=t.width+"px";r.parentNode.style.height=t.height+"px"}this.api.style.width=t.width+"px";this.api.style.height=t.height+"px"};e.player.api.setSource=function(t){if(!e.player.videojs){return}if(e.player.videojs.src()!=t){e.player.videojs.src({type:e.player.videojs.currentSource().type,src:t})}};e.player.api.setSubtitle=function(e){var t=r.getElementsByTagName("track");for(var i=t.length-1;i>=0;i--){r.removeChild(t[i])}if(e){var o=document.createElement("track");r.appendChild(o);o.kind="subtitles";o.label=e.label;o.srclang=e.lang;o.src=e.src;o.setAttribute("default","")}};t(r)}if("videojs"in window){o()}else{var s=e.urlappend(mistplayers.videojs.scriptsrc(e.options.host));var n;window.onerror=function(t,i,o,s,a){if(i==n.src){r.pause();e.showError("Error in videojs player");e.reload()}return false};n=MistUtil.scripts.insert(s,{onerror:function(t){var i="Failed to load videojs.js";if(t.message){i+=": "+t.message}e.showError(i)},onload:o},e)}};
|
File diff suppressed because one or more lines are too long
|
@ -14,45 +14,45 @@ echo "Minimizing player code..";
|
|||
|
||||
echo " Minimizing JS..";
|
||||
|
||||
if elementIn "embed/util.js" "${CHANGES[@]}" || elementIn "embed/skins.js" "${CHANGES[@]}" || elementIn "embed/controls.js" "${CHANGES[@]}" || elementIn "embed/player.js" "${CHANGES[@]}" ; then
|
||||
# if elementIn "embed/util.js" "${CHANGES[@]}" || elementIn "embed/skins.js" "${CHANGES[@]}" || elementIn "embed/controls.js" "${CHANGES[@]}" || elementIn "embed/player.js" "${CHANGES[@]}" ; then
|
||||
echo " Minimizing 'util.js skins.js controls.js player.js' into 'min/player.js'..";
|
||||
terser -mc -o min/player.js -- util.js skins.js controls.js player.js
|
||||
fi
|
||||
#fi
|
||||
echo " Done.";
|
||||
|
||||
echo " Minimizing wrappers.."
|
||||
|
||||
if elementIn "embed/wrappers/dashjs.js" "${CHANGES[@]}"; then
|
||||
#if elementIn "embed/wrappers/dashjs.js" "${CHANGES[@]}"; then
|
||||
echo " Minimizing dashjs";
|
||||
terser -mn -o min/wrappers/dashjs.js -- wrappers/dashjs.js
|
||||
fi
|
||||
if elementIn "embed/wrappers/flash_strobe.js" "${CHANGES[@]}"; then
|
||||
#fi
|
||||
#if elementIn "embed/wrappers/flash_strobe.js" "${CHANGES[@]}"; then
|
||||
echo " Minimizing flash_strobe";
|
||||
terser -mn -o min/wrappers/flash_strobe.js -- wrappers/flash_strobe.js
|
||||
fi
|
||||
if elementIn "embed/wrappers/html5.js" "${CHANGES[@]}"; then
|
||||
#fi
|
||||
#if elementIn "embed/wrappers/html5.js" "${CHANGES[@]}"; then
|
||||
echo " Minimizing html5";
|
||||
terser -mn -o min/wrappers/html5.js -- wrappers/html5.js
|
||||
fi
|
||||
if elementIn "embed/wrappers/videojs.js" "${CHANGES[@]}"; then
|
||||
#fi
|
||||
#if elementIn "embed/wrappers/videojs.js" "${CHANGES[@]}"; then
|
||||
echo " Minimizing videojs";
|
||||
terser -mn -o min/wrappers/videojs.js -- wrappers/videojs.js
|
||||
fi
|
||||
if elementIn "embed/wrappers/webrtc.js" "${CHANGES[@]}"; then
|
||||
#fi
|
||||
#if elementIn "embed/wrappers/webrtc.js" "${CHANGES[@]}"; then
|
||||
echo " Minimizing webrtc";
|
||||
terser -mn -o min/wrappers/webrtc.js -- wrappers/webrtc.js
|
||||
fi
|
||||
#fi
|
||||
echo " Done.";
|
||||
|
||||
echo " Minimizing CSS..";
|
||||
|
||||
if elementIn "embed/skins/default.css" "${CHANGES[@]}" || elementIn "embed/skins/general.css" "${CHANGES[@]}"; then
|
||||
#if elementIn "embed/skins/default.css" "${CHANGES[@]}" || elementIn "embed/skins/general.css" "${CHANGES[@]}"; #then
|
||||
echo " Minimizing default";
|
||||
cleancss --format keep-breaks -o min/skins/default.css skins/general.css skins/default.css
|
||||
fi
|
||||
if elementIn "embed/skins/default.css" "${CHANGES[@]}" || elementIn "embed/skins/general.css" "${CHANGES[@]}" || elementIn "embed/skins/dev.css" "${CHANGES[@]}"; then
|
||||
#fi
|
||||
#if elementIn "embed/skins/default.css" "${CHANGES[@]}" || elementIn "embed/skins/general.css" "${CHANGES[@]}" || elementIn "embed/skins/dev.css" "${CHANGES[@]}"; then
|
||||
echo " Minimizing dev";
|
||||
cleancss --format keep-breaks -o min/skins/dev.css skins/general.css skins/default.css skins/dev.css
|
||||
fi
|
||||
#fi
|
||||
echo " Done.";
|
||||
echo "Done.";
|
||||
|
|
|
@ -43,7 +43,7 @@ function MistVideo(streamName,options) {
|
|||
this.logs = [];
|
||||
this.log = function(message,type){
|
||||
if (!type) { type = "log"; }
|
||||
MistUtil.event.send(type,message,options.target);
|
||||
var event = MistUtil.event.send(type,message,options.target);
|
||||
var data = {
|
||||
type: type
|
||||
};
|
||||
|
@ -59,6 +59,7 @@ function MistVideo(streamName,options) {
|
|||
else { console.log(msg); }
|
||||
} catch(e){}
|
||||
}
|
||||
return event;
|
||||
};
|
||||
this.log("Initializing..");
|
||||
|
||||
|
@ -301,7 +302,7 @@ function MistVideo(streamName,options) {
|
|||
var fw = size.width || ('width' in options && options.width ? options.width : false ); //force this width
|
||||
var fh = size.height || ('height' in options && options.height ? options.height : false ); //force this height
|
||||
|
||||
if (!("source" in this.info)) {
|
||||
if ((!this.info) || !("source" in this.info)) {
|
||||
fw = 640;
|
||||
fh = 480;
|
||||
}
|
||||
|
@ -387,6 +388,7 @@ function MistVideo(streamName,options) {
|
|||
|
||||
|
||||
MistVideo.player.build(MistVideo,function(video){
|
||||
MistVideo.log("Building new player");
|
||||
|
||||
MistVideo.container.removeAttribute("data-loading");
|
||||
MistVideo.video = video;
|
||||
|
@ -727,7 +729,7 @@ function MistVideo(streamName,options) {
|
|||
};
|
||||
|
||||
//add track selection function
|
||||
if (!("setTrack" in MistVideo.player.api)) {
|
||||
if (!("setTracks" in MistVideo.player.api)) {
|
||||
MistVideo.player.api.setTracks = function(usetracks){
|
||||
|
||||
//check tracks exist
|
||||
|
@ -740,30 +742,7 @@ function MistVideo(streamName,options) {
|
|||
//if (!MistUtil.object.keys(usetracks).length) { return; } //don't do this; allow switching back to auto
|
||||
|
||||
//create source url
|
||||
var newurl;
|
||||
if (MistVideo.source.type == "html5/application/vnd.apple.mpegurl") { //for HLS, use a different format for track selection
|
||||
newurl = MistVideo.source.url.split("/");
|
||||
var m3u8 = newurl.pop(); //take this off now, it will be added back later
|
||||
var hlstracks = [];
|
||||
for (var i in usetracks) {
|
||||
//for audio or video tracks, just add the tracknumber between slashes
|
||||
switch (i) {
|
||||
case "audio":
|
||||
case "video":
|
||||
if (usetracks[i] == "none") { continue; }
|
||||
hlstracks.push(usetracks[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (hlstracks.length) { newurl.push(hlstracks.join("_")); }
|
||||
newurl.push(m3u8); //put back index.m3u8
|
||||
newurl = newurl.join("/");
|
||||
usetracks = {};
|
||||
}
|
||||
else {
|
||||
newurl = MistVideo.source.url;
|
||||
}
|
||||
|
||||
var newurl = MistVideo.source.url;
|
||||
var time = MistVideo.player.api.currentTime;
|
||||
|
||||
//actually switch to the new source url
|
||||
|
@ -782,6 +761,15 @@ function MistVideo(streamName,options) {
|
|||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
//add general setTracks function if setTrack exists
|
||||
if (!("setTracks" in MistVideo.player.api) && ("setTrack" in MistVideo.player.api)) {
|
||||
MistVideo.player.api.setTracks = function(usetracks){
|
||||
for (var i in usetracks) {
|
||||
MistVideo.player.api.setTrack(i,usetracks[i]);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if (options.setTracks) {
|
||||
|
@ -1100,6 +1088,12 @@ function MistVideo(streamName,options) {
|
|||
if ((this.UI) && (this.UI.elements)) {
|
||||
for (var i in this.UI.elements) {
|
||||
var e = this.UI.elements[i];
|
||||
if ("attachedListeners" in e) {
|
||||
//remove attached event listeners
|
||||
for (var i in e.attachedListeners) {
|
||||
MistUtil.event.removeListener(e.attachedListeners[i]);
|
||||
}
|
||||
}
|
||||
if (e.parentNode) {
|
||||
e.parentNode.removeChild(e);
|
||||
}
|
||||
|
|
|
@ -5,4 +5,4 @@ wget https://cdn.dashjs.org/latest/dash.all.min.js -O dash.all.min.js
|
|||
|
||||
echo "Videojs"
|
||||
echo "You'll want to check for the latest version at https://videojs.com/getting-started/#download-cdn"
|
||||
wget https://vjs.zencdn.net/7.3.0/video.min.js -O video.min.js
|
||||
wget https://vjs.zencdn.net/7.5.4/video.min.js -O video.min.js
|
||||
|
|
58931
embed/players/video.js
Normal file
58931
embed/players/video.js
Normal file
File diff suppressed because it is too large
Load diff
14
embed/players/video.min.js
vendored
14
embed/players/video.min.js
vendored
File diff suppressed because one or more lines are too long
|
@ -91,12 +91,13 @@ MistSkins["default"] = {
|
|||
children: [{
|
||||
type: "volume",
|
||||
mode: "horizontal",
|
||||
size: {height: 22}
|
||||
size: {height: 22},
|
||||
classes: ["mistvideo-pointer"]
|
||||
}]
|
||||
},
|
||||
{
|
||||
type: "speaker",
|
||||
classse: ["mistvideo-pointer"],
|
||||
classes: ["mistvideo-pointer"],
|
||||
style: {"margin-left": "-2px"}
|
||||
}
|
||||
]
|
||||
|
@ -129,7 +130,7 @@ MistSkins["default"] = {
|
|||
show: "right: 5px;",
|
||||
viewport: "right: 0; left: 0; bottom: 0; top: -1000px"
|
||||
},
|
||||
button: {type: "settings"},
|
||||
button: {type: "settings", classes: ["mistvideo-pointer"]},
|
||||
window: {type: "submenu"}
|
||||
}
|
||||
]}
|
||||
|
@ -1005,9 +1006,12 @@ MistSkins["default"] = {
|
|||
},button);
|
||||
|
||||
//apply initial video state
|
||||
if (('localStorage' in window) && (localStorage != null) && ('mistVolume' in localStorage)) {
|
||||
MistVideo.player.api.volume = localStorage['mistVolume'];
|
||||
}
|
||||
var initevent = MistUtil.event.addListener(video,"loadstart",function(){
|
||||
if (('localStorage' in window) && (localStorage != null) && ('mistVolume' in localStorage)) {
|
||||
MistVideo.player.api.volume = localStorage['mistVolume'];
|
||||
}
|
||||
MistUtil.event.removeListener(initevent);
|
||||
});
|
||||
|
||||
button.addPadding = function(actual){
|
||||
return actual * (1 - (this.margin.start + this.margin.end)) + this.margin.start;
|
||||
|
@ -1190,7 +1194,7 @@ MistSkins["default"] = {
|
|||
},
|
||||
settings: function(){
|
||||
var button = this.skin.icons.build("settings");
|
||||
|
||||
button.setAttribute("onclick","");
|
||||
return button;
|
||||
},
|
||||
loop: function(){
|
||||
|
@ -1287,6 +1291,9 @@ MistSkins["default"] = {
|
|||
|
||||
if (!MistVideo.options.setTracks) { MistVideo.options.setTracks = {}; }
|
||||
MistVideo.options.setTracks[type] = value;
|
||||
if ((value === true) && selections[type]) {
|
||||
MistUtil.event.send("change",null,selections[type]);
|
||||
}
|
||||
|
||||
if ("setTrack" in MistVideo.player.api) {
|
||||
return MistVideo.player.api.setTrack(type,value);
|
||||
|
@ -1374,6 +1381,15 @@ MistSkins["default"] = {
|
|||
cell.appendChild(checkbox);
|
||||
checkboxes[type] = checkbox;
|
||||
|
||||
if (MistVideo.options.setTracks && (MistVideo.options.setTracks[type])) {
|
||||
if (MistVideo.options.setTracks[type] == "none") {
|
||||
checkbox.checked = false;
|
||||
}
|
||||
else {
|
||||
checkbox.checked = true;
|
||||
}
|
||||
}
|
||||
|
||||
MistUtil.event.addListener(checkbox,"change",function(){
|
||||
//make sure at least one checkbox is checked
|
||||
var n = 0;
|
||||
|
@ -1407,6 +1423,15 @@ MistSkins["default"] = {
|
|||
}
|
||||
changeToTracks(this.trackType,(this.checked ? value : "none"));
|
||||
});
|
||||
|
||||
MistUtil.event.addListener(MistVideo.video,"playerUpdate_trackChanged",function(e){
|
||||
|
||||
if (e.message.type != type) { return; }
|
||||
|
||||
if (e.message.value == "none") { this.checked = false; }
|
||||
else { this.checked = true; }
|
||||
|
||||
},select);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1486,7 +1511,7 @@ MistSkins["default"] = {
|
|||
|
||||
MistUtil.event.addListener(MistVideo.video,"playerUpdate_trackChanged",function(e){
|
||||
|
||||
if (e.message.type != type) { return; }
|
||||
if ((e.message.type != type) || (e.message.trackid == "none")) { return; }
|
||||
select.value = e.message.trackid;
|
||||
MistVideo.log("Player selected "+type+" track with id "+e.message.trackid);
|
||||
|
||||
|
@ -1701,7 +1726,7 @@ MistSkins["default"] = {
|
|||
d.appendChild(document.createTextNode(details));
|
||||
}
|
||||
else if ("decodingIssues" in MistVideo.skin.blueprints) { //dev mode
|
||||
if (("player" in MistVideo) && ("api" in MistVideo.player)) {
|
||||
if (("player" in MistVideo) && ("api" in MistVideo.player) && (MistVideo.video)) {
|
||||
details = [];
|
||||
if (typeof MistVideo.player.api.currentTime != "undefined") {
|
||||
details.push(["Current video time:",MistUtil.format.time(MistVideo.player.api.currentTime)]);
|
||||
|
@ -1771,7 +1796,7 @@ MistSkins["default"] = {
|
|||
this.showError = function(message,options){
|
||||
if (!options) {
|
||||
options = {
|
||||
softReload: !!((MistVideo.video) && (MistVideo.video.load)),
|
||||
softReload: !!(MistVideo.player && MistVideo.player.api && MistVideo.player.api.load),
|
||||
reload: true,
|
||||
nextCombo: !!MistVideo.info,
|
||||
polling: false,
|
||||
|
@ -1809,7 +1834,7 @@ MistSkins["default"] = {
|
|||
since = (new Date()).getTime();
|
||||
|
||||
|
||||
this.log(message,"error");
|
||||
var event = this.log(message,"error");
|
||||
var message_container = container.message(message,false,options);
|
||||
message_global = message_container;
|
||||
|
||||
|
@ -1872,6 +1897,10 @@ MistSkins["default"] = {
|
|||
if ("container" in MistVideo) {
|
||||
MistVideo.container.removeAttribute("data-loading");
|
||||
}
|
||||
|
||||
if (event.defaultPrevented) {
|
||||
container.clear();
|
||||
}
|
||||
};
|
||||
container.clear = function(message){
|
||||
var countdowns = container.querySelectorAll("svg.icon.timeout");
|
||||
|
|
|
@ -84,7 +84,11 @@ var MistUtil = {
|
|||
break;
|
||||
}
|
||||
case "html5/application/vnd.apple.mpegurl": {
|
||||
return "HLS";
|
||||
return "HLS (TS)";
|
||||
break;
|
||||
}
|
||||
case "html5/application/vnd.apple.mpegurl;version=7": {
|
||||
return "HLS (CMAF)";
|
||||
break;
|
||||
}
|
||||
case "flash/10": {
|
||||
|
@ -103,8 +107,9 @@ var MistUtil = {
|
|||
return "TS";
|
||||
break;
|
||||
}
|
||||
case "html5/application/vnd.ms-sstr+xml":
|
||||
case "html5/application/vnd.ms-ss": {
|
||||
return "Smooth streaming";
|
||||
return "Smooth Streaming";
|
||||
break;
|
||||
}
|
||||
case "dash/video/mp4": {
|
||||
|
@ -582,6 +587,7 @@ var MistUtil = {
|
|||
});
|
||||
event.message = message;
|
||||
target.dispatchEvent(event);
|
||||
return event;
|
||||
}
|
||||
catch (e) {
|
||||
try {
|
||||
|
@ -589,6 +595,7 @@ var MistUtil = {
|
|||
event.initEvent(type,true,true);
|
||||
event.message = message;
|
||||
target.dispatchEvent(event);
|
||||
return event;
|
||||
}
|
||||
catch (e) { return false; }
|
||||
}
|
||||
|
@ -942,6 +949,8 @@ var MistUtil = {
|
|||
|
||||
line.addData = function(newData) {
|
||||
|
||||
if (isNaN(newData.y)) { return; }
|
||||
|
||||
if (options.differentiate) {
|
||||
var diff = newData.y - lasty;
|
||||
lasty = newData.y;
|
||||
|
|
|
@ -135,72 +135,6 @@ p.prototype.build = function (MistVideo,callback) {
|
|||
MistVideo.player.dash.attachSource(url);
|
||||
};
|
||||
|
||||
//trackswitching
|
||||
MistVideo.player.api.setTrack = function(type,id){
|
||||
var meta = MistUtil.tracks.parse(MistVideo.info.meta.tracks);
|
||||
if ((!(type in meta)) || ((!(id in meta[type]) && (id != "none")))) {
|
||||
MistVideo.log("Skipping trackselection of "+type+" track "+id+" because it does not exist");
|
||||
return;
|
||||
}
|
||||
|
||||
//figure out what the track number is
|
||||
//for dash: 0 lowest bitrate, going up
|
||||
//get the relevant tracks
|
||||
var mistTracks = [];
|
||||
for (var i in MistVideo.info.meta.tracks) {
|
||||
var t = MistVideo.info.meta.tracks[i];
|
||||
if (t.type == type) {
|
||||
mistTracks.push(t);
|
||||
}
|
||||
}
|
||||
//sort by bitrate
|
||||
MistUtil.array.multiSort(mistTracks,["bps"]);
|
||||
var n = false;
|
||||
for (var i in mistTracks) {
|
||||
var trackid = ("idx" in mistTracks[i] ? mistTracks[i].idx : mistTracks[i].trackid);
|
||||
if (trackid == id) {
|
||||
n = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (n === false) {
|
||||
return false; //track not found
|
||||
}
|
||||
|
||||
me.dash.setAutoSwitchQualityFor(type,false); //turn off ABR rules //TODO do we want this by default?
|
||||
me.dash.setFastSwitchEnabled(true); //show the new track asap
|
||||
me.dash.setQualityFor(type,n);
|
||||
//dash does change the track, but is appended to the buffer, so it seems to take a while..
|
||||
|
||||
return true; //track found and change requested
|
||||
}
|
||||
|
||||
//react to automatic trackswitching
|
||||
me.dash.on("qualityChangeRendered",function(e){
|
||||
//the newQuality-th track of type mediaType is being selected
|
||||
|
||||
//figure out the track id
|
||||
//for dash: 0 lowest bitrate, going up
|
||||
//get the relevant tracks
|
||||
var mistTracks = [];
|
||||
for (var i in MistVideo.info.meta.tracks) {
|
||||
var t = MistVideo.info.meta.tracks[i];
|
||||
if (t.type == e.mediaType) {
|
||||
mistTracks.push(t);
|
||||
}
|
||||
}
|
||||
//sort by bitrate
|
||||
MistUtil.array.multiSort(mistTracks,["bps"]);
|
||||
//get mist's id for the track
|
||||
var id = ("idx" in mistTracks[e.newQuality] ? mistTracks[e.newQuality].idx : mistTracks[e.newQuality].trackid);
|
||||
|
||||
//create an event to pass this to the skin
|
||||
MistUtil.event.send("playerUpdate_trackChanged",{
|
||||
type: e.mediaType,
|
||||
trackid: id
|
||||
},MistVideo.video);
|
||||
|
||||
});
|
||||
var subsloaded = false;
|
||||
me.dash.on("allTextTracksAdded",function(){
|
||||
subsloaded = true;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
mistplayers.videojs = {
|
||||
name: "VideoJS player",
|
||||
mimes: ["html5/application/vnd.apple.mpegurl"],
|
||||
mimes: ["html5/application/vnd.apple.mpegurl","html5/application/vnd.apple.mpegurl;version=7"],
|
||||
priority: MistUtil.object.keys(mistplayers).length + 1,
|
||||
isMimeSupported: function (mimetype) {
|
||||
return (this.mimes.indexOf(mimetype) == -1 ? false : true);
|
||||
|
@ -29,18 +29,21 @@ p.prototype = new MistPlayer();
|
|||
p.prototype.build = function (MistVideo,callback) {
|
||||
var me = this; //to allow nested functions to access the player class itself
|
||||
|
||||
var ele;
|
||||
function onVideoJSLoad () {
|
||||
if (MistVideo.destroyed) { return;}
|
||||
|
||||
MistVideo.log("Building VideoJS player..");
|
||||
|
||||
var ele = document.createElement("video");
|
||||
ele = document.createElement("video");
|
||||
if (MistVideo.source.type != "html5/video/ogg") {
|
||||
ele.crossOrigin = "anonymous"; //required for subtitles, but if ogg, the video won"t load
|
||||
}
|
||||
|
||||
var shortmime = MistVideo.source.type.split("/");
|
||||
shortmime.shift();
|
||||
if (shortmime[0] == "html5") {
|
||||
shortmime.shift();
|
||||
}
|
||||
|
||||
var source = document.createElement("source");
|
||||
source.setAttribute("src",MistVideo.source.url);
|
||||
|
@ -48,7 +51,8 @@ p.prototype.build = function (MistVideo,callback) {
|
|||
ele.appendChild(source);
|
||||
source.type = shortmime.join("/");
|
||||
MistVideo.log("Adding "+source.type+" source @ "+MistVideo.source.url);
|
||||
if (source.type == "application/vnd.apple.mpegurl") { source.type = "application/x-mpegURL"; }
|
||||
//if (source.type.indexOf("application/vnd.apple.mpegurl") >= 0) { source.type = "application/x-mpegURL"; }
|
||||
//source.type = "application/vnd.apple.mpegurl";
|
||||
|
||||
MistUtil.class.add(ele,"video-js");
|
||||
|
||||
|
@ -56,12 +60,12 @@ p.prototype.build = function (MistVideo,callback) {
|
|||
|
||||
if (MistVideo.options.autoplay) { vjsopts.autoplay = true; }
|
||||
if ((MistVideo.options.loop) && (MistVideo.info.type != "live")) {
|
||||
vjsopts.loop = true;
|
||||
ele.loop = true;
|
||||
//vjsopts.loop = true;
|
||||
ele.setAttribute("loop","");
|
||||
}
|
||||
if (MistVideo.options.muted) {
|
||||
vjsopts.muted = true;
|
||||
ele.muted = true;
|
||||
//vjsopts.muted = true;
|
||||
ele.setAttribute("muted","");
|
||||
}
|
||||
if (MistVideo.options.poster) { vjsopts.poster = MistVideo.options.poster; }
|
||||
if (MistVideo.options.controls == "stock") {
|
||||
|
@ -74,15 +78,55 @@ p.prototype.build = function (MistVideo,callback) {
|
|||
document.head.appendChild(style);
|
||||
}
|
||||
}
|
||||
else {
|
||||
vjsopts.controls = false;
|
||||
}
|
||||
|
||||
me.onready(function(){
|
||||
MistVideo.log("Building videojs");
|
||||
me.videojs = videojs(ele,vjsopts,function(){
|
||||
MistVideo.log("Videojs initialized");
|
||||
});
|
||||
|
||||
me.api.unload = function(){
|
||||
videojs(ele).dispose();
|
||||
if (me.videojs) {
|
||||
videojs(ele).dispose();
|
||||
me.videojs = false;
|
||||
MistVideo.log("Videojs instance disposed");
|
||||
}
|
||||
};
|
||||
|
||||
//special HLS live when-stream-ends code because holy crap latency
|
||||
MistUtil.event.addListener(MistVideo.options.target,"error",function(e){
|
||||
var eventdata = false;
|
||||
switch (e.message) {
|
||||
case "Stream is shutting down": {
|
||||
//MistVideo.clearError(); //we've probably got loads of buffer left to play
|
||||
e.preventDefault();
|
||||
break;
|
||||
}
|
||||
case "Stream is offline": {
|
||||
MistVideo.clearError(); //we've probably got loads of buffer left to play
|
||||
e.preventDefault();
|
||||
|
||||
if (MistVideo.video) {
|
||||
eventdata = MistUtil.event.addListener(MistVideo.video,"ended",function(){
|
||||
//show stream offline error
|
||||
MistVideo.showError("Stream is offline ",{polling:true});
|
||||
|
||||
if (eventdata) { MistUtil.event.removeListener(eventdata); }
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "Stream is waiting for data": {
|
||||
if (eventdata) { MistUtil.event.removeListener(eventdata); }
|
||||
me.api.pause();
|
||||
MistVideo.reload();
|
||||
break;
|
||||
}
|
||||
}
|
||||
},MistVideo.video);
|
||||
});
|
||||
|
||||
MistVideo.log("Built html");
|
||||
|
@ -113,6 +157,7 @@ p.prototype.build = function (MistVideo,callback) {
|
|||
return target[key] = value;
|
||||
}
|
||||
});
|
||||
MistVideo.player.api.load = function(){};
|
||||
|
||||
if (MistVideo.info.type == "live") {
|
||||
function getLastBuffer(video) {
|
||||
|
@ -122,10 +167,15 @@ p.prototype.build = function (MistVideo,callback) {
|
|||
}
|
||||
return buffer_end;
|
||||
}
|
||||
var HLSlatency = 90; //best guess..
|
||||
var HLSlatency = 0; //best guess..
|
||||
|
||||
overrides.get.duration = function(){
|
||||
return (MistVideo.info.lastms + (new Date()).getTime() - MistVideo.info.updated.getTime())*1e-3;
|
||||
if (MistVideo.info) {
|
||||
var duration = (MistVideo.info.lastms + (new Date()).getTime() - MistVideo.info.updated.getTime())*1e-3;
|
||||
//if (isNaN(duration)) { return 1e9; }
|
||||
return duration;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
MistVideo.player.api.lastProgress = new Date();
|
||||
MistVideo.player.api.liveOffset = 0;
|
||||
|
@ -141,8 +191,12 @@ p.prototype.build = function (MistVideo,callback) {
|
|||
MistVideo.log("Seeking to "+MistUtil.format.time(value)+" ("+Math.round(offset*-10)/10+"s from live)");
|
||||
MistVideo.video.currentTime -= diff;
|
||||
}
|
||||
var lastms = 0;
|
||||
overrides.get.currentTime = function(){
|
||||
return this.currentTime + MistVideo.info.lastms*1e-3 - MistVideo.player.api.liveOffset - HLSlatency;
|
||||
if (MistVideo.info) { lastms = MistVideo.info.lastms*1e-3; }
|
||||
var time = this.currentTime + lastms - MistVideo.player.api.liveOffset - HLSlatency;
|
||||
if (isNaN(time)) { return 0; }
|
||||
return time;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -198,7 +252,25 @@ p.prototype.build = function (MistVideo,callback) {
|
|||
else {
|
||||
//load the videojs player
|
||||
|
||||
var scripttag = MistUtil.scripts.insert(MistVideo.urlappend(mistplayers.videojs.scriptsrc(MistVideo.options.host)),{
|
||||
var scripturl = MistVideo.urlappend(mistplayers.videojs.scriptsrc(MistVideo.options.host));
|
||||
var scripttag;
|
||||
window.onerror = function (msg, url, lineNo, columnNo, error) {
|
||||
|
||||
if (url == scripttag.src) {
|
||||
//error in internal videojs code
|
||||
//console.error(me.videojs,MistVideo.video,ele,arguments);
|
||||
|
||||
ele.pause();
|
||||
|
||||
MistVideo.showError("Error in videojs player");
|
||||
|
||||
MistVideo.reload();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
scripttag = MistUtil.scripts.insert(scripturl,{
|
||||
onerror: function(e){
|
||||
var msg = "Failed to load videojs.js";
|
||||
if (e.message) { msg += ": "+e.message; }
|
||||
|
|
|
@ -73,8 +73,10 @@ p.prototype.build = function (MistVideo,callback) {
|
|||
seekoffset = 0;
|
||||
hasended = false;
|
||||
this.webrtc.play();
|
||||
MistUtil.event.send("webrtc_connected",null,video);
|
||||
},
|
||||
on_disconnected: function() {
|
||||
MistUtil.event.send("webrtc_disconnected",null,video);
|
||||
MistVideo.log("Websocket sent on_disconnect");
|
||||
/*
|
||||
If a VoD file ends, we receive an on_stop, but no on_disconnect
|
||||
|
@ -105,10 +107,50 @@ p.prototype.build = function (MistVideo,callback) {
|
|||
duration = d;
|
||||
MistUtil.event.send("durationchange",d,video);
|
||||
}
|
||||
|
||||
if (currenttracks != ev.tracks) {
|
||||
var tracks = MistUtil.tracks.parse(MistVideo.info.meta.tracks);
|
||||
for (var i in ev.tracks) {
|
||||
if (currenttracks.indexOf(ev.tracks[i]) < 0) {
|
||||
//find track type
|
||||
var type;
|
||||
for (var j in tracks) {
|
||||
if (ev.tracks[i] in tracks[j]) {
|
||||
type = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!type) {
|
||||
//track type not found, this should not happen
|
||||
continue;
|
||||
}
|
||||
|
||||
//create an event to pass this to the skin
|
||||
MistUtil.event.send("playerUpdate_trackChanged",{
|
||||
type: type,
|
||||
trackid: ev.tracks[i]
|
||||
},MistVideo.video);
|
||||
}
|
||||
}
|
||||
|
||||
currenttracks = ev.tracks;
|
||||
}
|
||||
},
|
||||
on_seek: function(){
|
||||
var thisPlayer = this;
|
||||
MistUtil.event.send("seeked",seekoffset,video);
|
||||
video.play();
|
||||
if ("seekPromise" in this.webrtc.signaling){
|
||||
video.play().then(function(){
|
||||
if ("seekPromise" in thisPlayer.webrtc.signaling) {
|
||||
thisPlayer.webrtc.signaling.seekPromise.resolve("Play promise resolved");
|
||||
}
|
||||
}).catch(function(){
|
||||
if ("seekPromise" in thisPlayer.webrtc.signaling) {
|
||||
thisPlayer.webrtc.signaling.seekPromise.reject("Play promise rejected");
|
||||
}
|
||||
});
|
||||
}
|
||||
else { video.play(); }
|
||||
},
|
||||
on_stop: function(){
|
||||
MistVideo.log("Websocket sent on_stop");
|
||||
|
@ -185,8 +227,25 @@ p.prototype.build = function (MistVideo,callback) {
|
|||
this.signaling.send({type: "stop"});
|
||||
};
|
||||
this.seek = function(seekTime){
|
||||
if (!this.isConnected) { return; }
|
||||
this.signaling.send({type: "seek", "seek_time": seekTime*1e3});
|
||||
var p = new Promise(function(resolve,reject){
|
||||
if (!thisWebRTCPlayer.isConnected || !thisWebRTCPlayer.signaling) { return reject("Failed seek: not connected"); }
|
||||
thisWebRTCPlayer.signaling.send({type: "seek", "seek_time": seekTime*1e3});
|
||||
if ("seekPromise" in thisWebRTCPlayer.signaling) {
|
||||
thisWebRTCPlayer.signaling.seekPromise.reject("Doing new seek");
|
||||
}
|
||||
|
||||
thisWebRTCPlayer.signaling.seekPromise = {
|
||||
resolve: function(msg){
|
||||
resolve("seeked");
|
||||
delete thisWebRTCPlayer.signaling.seekPromise;
|
||||
},
|
||||
reject: function(msg) {
|
||||
reject("Failed to seek: "+msg);
|
||||
delete thisWebRTCPlayer.signaling.seekPromise;
|
||||
}
|
||||
};
|
||||
});
|
||||
return p;
|
||||
};
|
||||
this.pause = function(){
|
||||
if (!this.isConnected) { throw "Not connected, cannot pause." }
|
||||
|
@ -265,6 +324,7 @@ p.prototype.build = function (MistVideo,callback) {
|
|||
|
||||
//override video duration
|
||||
var duration;
|
||||
var currenttracks = [];
|
||||
Object.defineProperty(this.api,"duration",{
|
||||
get: function(){ return duration; }
|
||||
});
|
||||
|
@ -322,17 +382,28 @@ p.prototype.build = function (MistVideo,callback) {
|
|||
//redirect play
|
||||
me.api.play = function(){
|
||||
if (me.api.currentTime) {
|
||||
if ((!me.webrtc.isConnected) || (me.webrtc.peerConn.iceConnectionState != "completed")) {
|
||||
me.webrtc.connect(function(){
|
||||
me.webrtc.seek(me.api.currentTime);
|
||||
});
|
||||
}
|
||||
else {
|
||||
me.webrtc.seek(me.api.currentTime);
|
||||
}
|
||||
var p = new Promise(function(resolve,reject){
|
||||
if ((!me.webrtc.isConnected) || (me.webrtc.peerConn.iceConnectionState != "completed")) {
|
||||
me.webrtc.connect(function(){
|
||||
me.webrtc.seek(me.api.currentTime).then(function(msg){
|
||||
resolve("played "+msg);
|
||||
}).catch(function(msg){
|
||||
reject(msg);
|
||||
});
|
||||
});
|
||||
}
|
||||
else {
|
||||
me.webrtc.seek(me.api.currentTime).then(function(msg){
|
||||
resolve("played "+msg);
|
||||
}).catch(function(msg){
|
||||
reject(msg);
|
||||
});
|
||||
}
|
||||
});
|
||||
return p;
|
||||
}
|
||||
else {
|
||||
video.play();
|
||||
return video.play();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -347,7 +418,16 @@ p.prototype.build = function (MistVideo,callback) {
|
|||
};
|
||||
|
||||
me.api.setTracks = function(obj){
|
||||
me.webrtc.setTrack(obj);
|
||||
if (me.webrtc.isConnected) {
|
||||
me.webrtc.setTrack(obj);
|
||||
}
|
||||
else {
|
||||
var f = function(){
|
||||
me.webrtc.setTrack(obj);
|
||||
MistUtil.event.removeListener({type: "webrtc_connected", callback: f, element: video});
|
||||
};
|
||||
MistUtil.event.addListener(video,"webrtc_connected",f);
|
||||
}
|
||||
};
|
||||
function correctSubtitleSync() {
|
||||
if (!me.api.textTracks[0]) { return; }
|
||||
|
|
|
@ -12,9 +12,9 @@ elementIn () {
|
|||
|
||||
echo "Minimizing LSP..";
|
||||
|
||||
if elementIn "lsp/plugins/md5.js" "${CHANGES[@]}" || elementIn "lsp/plugins/cattablesort.js" "${CHANGES[@]}" || elementIn "lsp/mist.js" "${CHANGES[@]}" ; then
|
||||
#if elementIn "lsp/plugins/md5.js" "${CHANGES[@]}" || elementIn "lsp/plugins/cattablesort.js" "${CHANGES[@]}" || elementIn "lsp/mist.js" "${CHANGES[@]}" ; then
|
||||
echo " Generating minified.js.."
|
||||
java -jar closure-compiler.jar --warning_level QUIET plugins/md5.js plugins/cattablesort.js mist.js > minified.js
|
||||
fi
|
||||
#fi
|
||||
|
||||
echo "Done.";
|
||||
|
|
File diff suppressed because one or more lines are too long
141
lsp/minified.js
141
lsp/minified.js
|
@ -18,72 +18,74 @@ QA:"Qatar",RE:"Réunion",RO:"Romania",RU:"Russian Federation",RW:"Rwanda",
|
|||
SB:"Solomon Islands",SO:"Somalia",ZA:"South Africa",GS:"South Georgia and the South Sandwich Islands",SS:"South Sudan",ES:"Spain",LK:"Sri Lanka",SD:"Sudan",SR:"Suriname",SJ:"Svalbard and Jan Mayen",SZ:"Swaziland",SE:"Sweden",CH:"Switzerland",SY:"Syrian Arab Republic",TW:"Taiwan, Province of China",TJ:"Tajikistan",TZ:"Tanzania, United Republic of",TH:"Thailand",TL:"Timor-Leste",TG:"Togo",TK:"Tokelau",TO:"Tonga",TT:"Trinidad and Tobago",TN:"Tunisia",TR:"Turkey",TM:"Turkmenistan",TC:"Turks and Caicos Islands",
|
||||
TV:"Tuvalu",UG:"Uganda",UA:"Ukraine",AE:"United Arab Emirates",GB:"United Kingdom",US:"United States",UM:"United States Minor Outlying Islands",UY:"Uruguay",UZ:"Uzbekistan",VU:"Vanuatu",VE:"Venezuela, Bolivarian Republic of",VN:"Viet Nam",VG:"Virgin Islands, British",VI:"Virgin Islands, U.S.",WF:"Wallis and Futuna",EH:"Western Sahara",YE:"Yemen",ZM:"Zambia",ZW:"Zimbabwe"},tooltip:{show:function(a,c){$tooltip=this.element;$.contains(document.body,$tooltip[0])||$("body").append($tooltip);$tooltip.html(c);
|
||||
clearTimeout(this.hiding);delete this.hiding;var d=$(document).height()-$tooltip.outerHeight(),b=$(document).width()-$tooltip.outerWidth();$tooltip.css("left",Math.min(a.pageX+10,b-10));$tooltip.css("top",Math.min(a.pageY+25,d-10));$tooltip.show().addClass("show")},hide:function(){$tooltip=this.element;$tooltip.removeClass("show");this.hiding=setTimeout(function(){$tooltip.hide()},500)},element:$("<div>").attr("id","tooltip")},humanMime:function(a){var c=!1;switch(a){case "html5/application/vnd.apple.mpegurl":c=
|
||||
"HLS";break;case "html5/video/webm":c="WebM";break;case "html5/video/mp4":c="MP4";break;case "dash/video/mp4":c="DASH";break;case "flash/11":c="HDS";break;case "flash/10":c="RTMP";break;case "flash/7":c="Progressive";break;case "html5/audio/mp3":c="MP3";break;case "html5/audio/wav":c="WAV";break;case "html5/video/mp2t":case "html5/video/mpeg":c="TS";break;case "html5/application/vnd.ms-ss":c="Smooth";break;case "html5/text/vtt":c="VTT Subtitles";break;case "html5/text/plain":c="SRT Subtitles";break;
|
||||
case "html5/text/javascript":c="JSON Subtitles";break;case "rtsp":c="RTSP";break;case "webrtc":c="WebRTC"}return c},popup:{element:null,show:function(a){this.element=$("<div>").attr("id","popup").append($("<button>").text("Close").addClass("close").click(function(){UI.popup.element.fadeOut("fast",function(){UI.popup.element.remove();UI.popup.element=null})})).append(a);$("body").append(this.element)}},menu:[{Overview:{},Protocols:{},Streams:{hiddenmenu:{Edit:{},Preview:{},Embed:{}}},Push:{LTSonly:!0},
|
||||
Triggers:{LTSonly:!1},Logs:{},Statistics:{},"Server Stats":{}},{Disconnect:{classes:["red"]}},{Guides:{link:"http://mistserver.org/documentation#Userdocs"},Tools:{submenu:{"Release notes":{link:"http://mistserver.org/documentation#Devdocs"},"Mist Shop":{link:"http://mistserver.org/products"},"Email for Help":{}}}}],buildMenu:function(){function a(a,b){var c=$("<a>").addClass("button");c.html($("<span>").addClass("plain").text(a)).append($("<span>").addClass("highlighted").text(a));for(var d in b.classes)c.addClass(b.classes[d]);
|
||||
"LTSonly"in b&&c.addClass("LTSonly");"link"in b?c.attr("href",b.link).attr("target","_blank"):"submenu"in b||c.click(function(b){$(this).closest(".menu").hasClass("hide")||(UI.navto(a),b.stopPropagation())});return c}var c=UI.elements.menu,d;for(d in UI.menu){0<d&&c.append($("<br>"));for(var b in UI.menu[d]){var i=UI.menu[d][b],m=a(b,i);c.append(m);if("submenu"in i){var h=$("<span>").addClass("submenu");m.addClass("arrowdown").append(h);for(var f in i.submenu)h.append(a(f,i.submenu[f]))}else if("hiddenmenu"in
|
||||
i)for(f in h=$("<span>").addClass("hiddenmenu"),m.append(h),i.hiddenmenu)h.append(a(f,i.hiddenmenu[f]))}}d=$("<div>").attr("id","ih_button").text("?").click(function(){$("body").toggleClass("helpme");UI.stored.saveOpt("helpme",$("body").hasClass("helpme"))}).attr("title","Click to toggle the display of integrated help");UI.stored.getOpts().helpme&&$("body").addClass("helpme");c.after(d).after($("<div>").addClass("separator"))},findInput:function(a){return this.findInOutput("inputs",a)},findOutput:function(a){return this.findInOutput("connectors",
|
||||
a)},findInOutput:function(a,c){if("capabilities"in mist.data){var d=!1,b=mist.data.capabilities[a];c in b&&(d=b[c]);c+".exe"in b&&(d=b[c+".exe"]);return d}throw"Request capabilities first";},buildUI:function(a){var c=$("<div>").addClass("input_container"),d;for(d in a){var b=a[d];if(b instanceof jQuery)c.append(b);else if("help"==b.type){var i=$("<span>").addClass("text_container").append($("<span>").addClass("description").append(b.help));c.append(i);if("classes"in b)for(var m in b.classes)i.addClass(b.classes[m])}else if("text"==
|
||||
b.type)c.append($("<span>").addClass("text_container").append($("<span>").addClass("text").append(b.text)));else if("custom"==b.type)c.append(b.custom);else if("buttons"==b.type)for(m in i=$("<span>").addClass("button_container").on("keydown",function(a){a.stopPropagation()}),"css"in b&&i.css(b.css),c.append(i),b.buttons){var h=b.buttons[m],f=$("<button>").text(h.label).data("opts",h);"css"in h&&f.css(h.css);if("classes"in h)for(var r in h.classes)f.addClass(h.classes[r]);i.append(f);switch(h.type){case "cancel":f.addClass("cancel").click(h["function"]);
|
||||
break;case "save":f.addClass("save").click(function(){var a=$(this).closest(".input_container"),b=!1;a.find('.hasValidate:visible, input[type="hidden"].hasValidate').each(function(){if(b=$(this).data("validate")(this,!0))return!1});b||(a.find('.isSetting:visible, input[type="hidden"].isSetting').each(function(){var a=$(this).getval(),b=$(this).data("pointer");if(""==a)if("default"in $(this).data("opts"))a=$(this).data("opts")["default"];else return b.main[b.index]=null,!0;b.main[b.index]=a}),(a=$(this).data("opts")["function"])&&
|
||||
a(this))});break;default:f.click(h["function"])}}else{var j=$("<label>").addClass("UIelement");c.append(j);"css"in b&&j.css(b.css);j.append($("<span>").addClass("label").html("label"in b?b.label+":":""));i=$("<span>").addClass("field_container");j.append(i);var l;switch(b.type){case "password":l=$("<input>").attr("type","password");break;case "int":l=$("<input>").attr("type","number");"min"in b&&l.attr("min",b.min);"max"in b&&l.attr("max",b.max);"validate"in b?b.validate.push("int"):b.validate=["int"];
|
||||
break;case "span":l=$("<span>");break;case "debug":b.select=[["","Default"],[0,"0 - All debugging messages disabled"],[1,"1 - Messages about failed operations"],[2,"2 - Previous level, and error messages"],[3,"3 - Previous level, and warning messages"],[4,"4 - Previous level, and status messages for development"],[5,"5 - Previous level, and more status messages for development"],[6,"6 - Previous level, and verbose debugging messages"],[7,"7 - Previous level, and very verbose debugging messages"],
|
||||
[8,"8 - Report everything in extreme detail"],[9,"9 - Report everything in insane detail"],[10,"10 - All messages enabled"]];case "select":l=$("<select>");for(m in b.select)f=$("<option>"),"string"==typeof b.select[m]?f.text(b.select[m]):f.val(b.select[m][0]).text(b.select[m][1]),l.append(f);break;case "textarea":l=$("<textarea>").on("keydown",function(a){a.stopPropagation()});break;case "checkbox":l=$("<input>").attr("type","checkbox");break;case "hidden":l=$("<input>").attr("type","hidden");j.hide();
|
||||
break;case "email":l=$("<input>").attr("type","email").attr("autocomplete","on").attr("required","");break;case "browse":l=$("<input>").attr("type","text");"filetypes"in b&&l.data("filetypes",b.filetypes);break;case "geolimited":case "hostlimited":l=$("<input>").attr("type","hidden");break;case "radioselect":l=$("<div>").addClass("radioselect");for(d in b.radioselect)if(h=$("<input>").attr("type","radio").val(b.radioselect[d][0]).attr("name",b.label),("LTSonly"in b&&!mist.data.LTS||b.readonly)&&h.prop("disabled",
|
||||
!0),f=$("<label>").append(h).append($("<span>").html(b.radioselect[d][1])),l.append(f),2<b.radioselect[d].length)for(m in h=$("<select>").change(function(){$(this).parent().find("input[type=radio]:enabled").prop("checked","true")}),f.append(h),("LTSonly"in b&&!mist.data.LTS||b.readonly)&&h.prop("disabled",!0),b.radioselect[d][2])f=$("<option>"),h.append(f),b.radioselect[d][2][m]instanceof Array?f.val(b.radioselect[d][2][m][0]).html(b.radioselect[d][2][m][1]):f.html(b.radioselect[d][2][m]);break;case "checklist":l=
|
||||
$("<div>").addClass("checkcontainer");$controls=$("<div>").addClass("controls");$checklist=$("<div>").addClass("checklist");l.append($checklist);for(d in b.checklist)"string"==typeof b.checklist[d]&&(b.checklist[d]=[b.checklist[d],b.checklist[d]]),$checklist.append($("<label>").text(b.checklist[d][1]).prepend($("<input>").attr("type","checkbox").attr("name",b.checklist[d][0])));break;case "DOMfield":l=b.DOMfield;break;case "unix":l=$("<input>").attr("type","datetime-local").attr("step",1);b.unit=
|
||||
$("<button>").text("Now").click(function(){$(this).closest(".field_container").find(".field").setval((new Date).getTime()/1E3)});break;case "selectinput":l=$("<div>").addClass("selectinput");h=$("<select>");l.append(h);h.data("input",!1);"LTSonly"in b&&!mist.data.LTS&&h.prop("disabled",!0);for(d in b.selectinput)f=$("<option>"),h.append(f),"string"==typeof b.selectinput[d]?f.text(b.selectinput[d]):(f.text(b.selectinput[d][1]),"string"==typeof b.selectinput[d][0]?f.val(b.selectinput[d][0]):(f.val("CUSTOM"),
|
||||
h.data("input")||h.data("input",UI.buildUI([b.selectinput[d][0]]).children())));h.data("input")&&l.append(h.data("input"));h.change(function(){"CUSTOM"==$(this).val()?$(this).data("input").css("display","flex"):$(this).data("input").hide()});h.trigger("change");break;case "inputlist":l=$("<div>").addClass("inputlist");l.data("newitem",function(){var a=$("<input>").attr("type","text").addClass("listitem");("LTSonly"in b&&!mist.data.LTS||b.readonly)&&a.prop("disabled",!0);var c=function(b){$(this).is(":last-child")?
|
||||
""!=$(this).val()?$(this).after(a.clone().keyup(c).val("")):8==b.which&&$(this).prev().focus():""==$(this).val()&&($(this).next().focus(),$(this).remove())};a.keyup(c);return a});l.append(l.data("newitem"));break;case "sublist":l=$("<div>").addClass("sublist");h=$("<div>").addClass("curvals");h.append($("<span>").text("None."));var u=$("<div>").addClass("itemsettings"),g=$("<button>").text("New "+b.itemLabel),e=b.sublist;l.data("build",function(a,c){for(var d in b.saveas)d in a||delete b.saveas[d];
|
||||
b.saveas=Object.assign(b.saveas,a);d="New";"undefined"!=typeof c&&(d="Edit");d=UI.buildUI([$("<h4>").text(d+" "+b.itemLabel)].concat(e).concat([{type:"buttons",buttons:[{label:"Cancel",type:"cancel","function":function(){u.html("");g.show();j.show()}},{label:"Save "+b.itemLabel,type:"save","function":function(){var a=l.getval(),d=Object.assign({},b.saveas),e;for(e in d)null===d[e]&&delete d[e];"undefined"==typeof c?a.push(d):a[c]=d;l.setval(a);u.html("");g.show();j.show()}}]}]));u.html(d);g.hide();
|
||||
j.hide()});g.click(function(){l.data("build")({})});e.unshift({type:"str",label:"Human readable name",placeholder:"none",help:"A convenient name to describe this "+b.itemLabel+". It won't be used by MistServer.",pointer:{main:b.saveas,index:"x-LSP-name"}});l.data("savelist",[]);l.append(h).append(g);c.append(u);break;default:l=$("<input>").attr("type","text")}l.addClass("field").data("opts",b);"pointer"in b&&l.attr("name",b.pointer.index);i.append(l);if("classes"in b)for(m in b.classes)l.addClass(b.classes[m]);
|
||||
"placeholder"in b&&l.attr("placeholder",b.placeholder);"default"in b&&l.attr("placeholder",b["default"]);"unit"in b&&i.append($("<span>").addClass("unit").html(b.unit));"readonly"in b&&(l.attr("readonly","readonly"),l.click(function(){$(this).select()}));"qrcode"in b&&i.append($("<span>").addClass("unit").html($("<button>").text("QR").on("keydown",function(a){a.stopPropagation()}).click(function(){var a=String($(this).closest(".field_container").find(".field").getval()),b=$("<div>").addClass("qrcode");
|
||||
UI.popup.show($("<span>").addClass("qr_container").append($("<p>").text(a)).append(b));b.qrcode({text:a,size:Math.min(b.width(),b.height())})})));"clipboard"in b&&document.queryCommandSupported("copy")&&i.append($("<span>").addClass("unit").html($("<button>").text("Copy").on("keydown",function(a){a.stopPropagation()}).click(function(){var a=String($(this).closest(".field_container").find(".field").getval()),b=document.createElement("textarea");b.value=a;document.body.appendChild(b);b.select();var c=
|
||||
false;try{c=document.execCommand("copy")}catch(d){}if(c){$(this).text("Copied to clipboard!");document.body.removeChild(b);var e=$(this);setTimeout(function(){e.text("Copy")},5E3)}else{document.body.removeChild(b);alert("Failed to copy:\n"+a)}})));"rows"in b&&l.attr("rows",b.rows);"LTSonly"in b&&!mist.data.LTS&&(i.addClass("LTSonly"),l.prop("disabled",!0));if("dependent"in b)for(d in b.dependent)j.attr("data-dependent-"+d,b.dependent[d]);switch(b.type){case "browse":h=$("<div>").addClass("grouper").append(j);
|
||||
c.append(h);h=$("<button>").text("Browse").on("keydown",function(a){a.stopPropagation()});i.append(h);h.click(function(){function a(b){h.text("Loading..");mist.send(function(a){f.text(a.browse.path[0]);mist.data.LTS&&d.setval(a.browse.path[0]+"/");h.html(i.clone(true).text("..").attr("title","Folder up"));if(a.browse.subdirectories){a.browse.subdirectories.sort();for(var b in a.browse.subdirectories){var g=a.browse.subdirectories[b];h.append(i.clone(true).attr("title",f.text()+l+g).text(g))}}if(a.browse.files){a.browse.files.sort();
|
||||
for(b in a.browse.files){var g=a.browse.files[b],k=f.text()+l+g,g=$("<a>").text(g).addClass("file").attr("title",k);h.append(g);if(j){var n=true,m;for(m in j)if(typeof j[m]!="undefined"&&mist.inputMatch(j[m],k)){n=false;break}n&&g.hide()}g.click(function(){var a=$(this).attr("title");d.setval(a).removeAttr("readonly").css("opacity",1);e.show();c.remove()})}}},{browse:b})}var b=$(this).closest(".grouper"),c=$("<div>").addClass("browse_container"),d=b.find(".field").attr("readonly","readonly").css("opacity",
|
||||
0.5),e=$(this),g=$("<button>").text("Stop browsing").click(function(){e.show();c.remove();d.removeAttr("readonly").css("opacity",1)}),f=$("<span>").addClass("field"),h=$("<div>").addClass("browse_contents"),i=$("<a>").addClass("folder"),j=d.data("filetypes");b.append(c);c.append($("<label>").addClass("UIelement").append($("<span>").addClass("label").text("Current folder:")).append($("<span>").addClass("field_container").append(f).append(g))).append(h);var l="/";mist.data.config.version.indexOf("indows")>
|
||||
-1&&(l="\\");i.click(function(){var b=f.text()+l+$(this).text();a(b)});b=d.getval();g=b.split("://");g.length>1&&(b=g[0]=="file"?g[1]:"");b=b.split(l);b.pop();b=b.join(l);e.hide();a(b)});break;case "geolimited":case "hostlimited":h={field:l};h.blackwhite=$("<select>").append($("<option>").val("-").text("Blacklist")).append($("<option>").val("+").text("Whitelist"));h.values=$("<span>").addClass("limit_value_list");switch(b.type){case "geolimited":h.prototype=$("<select>").append($("<option>").val("").text("[Select a country]"));
|
||||
for(d in UI.countrylist)h.prototype.append($("<option>").val(d).html(UI.countrylist[d]));break;case "hostlimited":h.prototype=$("<input>").attr("type","text").attr("placeholder","type a host")}h.prototype.on("change keyup",function(){$(this).closest(".field_container").data("subUI").blackwhite.trigger("change")});h.blackwhite.change(function(){var a=$(this).closest(".field_container").data("subUI"),b=[],c=false;a.values.children().each(function(){c=$(this).val();c!=""?b.push(c):$(this).remove()});
|
||||
a.values.append(a.prototype.clone(true));b.length>0?a.field.val($(this).val()+b.join(" ")):a.field.val("");a.field.trigger("change")});"LTSonly"in b&&!mist.data.LTS&&(h.blackwhite.prop("disabled",!0),h.prototype.prop("disabled",!0));h.values.append(h.prototype.clone(!0));i.data("subUI",h).addClass("limit_list").append(h.blackwhite).append(h.values)}"pointer"in b&&(l.data("pointer",b.pointer).addClass("isSetting"),b.pointer.main&&(h=b.pointer.main[b.pointer.index],"undefined"!=h&&l.setval(h)));(""==
|
||||
l.getval()||null==l.getval())&&"value"in b&&l.setval(b.value);if("datalist"in b)for(d in h="datalist_"+d+MD5(l[0].outerHTML),l.attr("list",h),h=$("<datalist>").attr("id",h),i.append(h),b.datalist)h.append($("<option>").val(b.datalist[d]));i=$("<span>").addClass("help_container");j.append(i);"help"in b&&(i.append($("<span>").addClass("ih_balloon").html(b.help)),l.on("focus mouseover",function(){$(this).closest("label").addClass("active")}).on("blur mouseout",function(){$(this).closest("label").removeClass("active")}));
|
||||
"HLS (TS)";break;case "html5/application/vnd.apple.mpegurl;version=7":c="HLS (CMAF)";break;case "html5/video/webm":c="WebM";break;case "html5/video/mp4":c="MP4";break;case "dash/video/mp4":c="DASH";break;case "flash/11":c="HDS";break;case "flash/10":c="RTMP";break;case "flash/7":c="Progressive";break;case "html5/audio/mp3":c="MP3";break;case "html5/audio/wav":c="WAV";break;case "html5/video/mp2t":case "html5/video/mpeg":c="TS";break;case "html5/application/vnd.ms-sstr+xml":case "html5/application/vnd.ms-ss":c=
|
||||
"Smooth Streaming";break;case "html5/text/vtt":c="VTT Subtitles";break;case "html5/text/plain":c="SRT Subtitles";break;case "html5/text/javascript":c="JSON Subtitles";break;case "rtsp":c="RTSP";break;case "webrtc":c="WebRTC"}return c},popup:{element:null,show:function(a){this.element=$("<div>").attr("id","popup").append($("<button>").text("Close").addClass("close").click(function(){UI.popup.element.fadeOut("fast",function(){UI.popup.element.remove();UI.popup.element=null})})).append(a);$("body").append(this.element)}},
|
||||
menu:[{Overview:{},Protocols:{},Streams:{hiddenmenu:{Edit:{},Preview:{},Embed:{}}},Push:{LTSonly:!0},Triggers:{LTSonly:!1},Logs:{},Statistics:{},"Server Stats":{}},{Disconnect:{classes:["red"]}},{Guides:{link:"http://mistserver.org/documentation#Userdocs"},Tools:{submenu:{"Release notes":{link:"http://mistserver.org/documentation#Devdocs"},"Mist Shop":{link:"http://mistserver.org/products"},"Email for Help":{}}}}],buildMenu:function(){function a(a,b){var c=$("<a>").addClass("button");c.html($("<span>").addClass("plain").text(a)).append($("<span>").addClass("highlighted").text(a));
|
||||
for(var d in b.classes)c.addClass(b.classes[d]);"LTSonly"in b&&c.addClass("LTSonly");"link"in b?c.attr("href",b.link).attr("target","_blank"):"submenu"in b||c.click(function(b){$(this).closest(".menu").hasClass("hide")||(UI.navto(a),b.stopPropagation())});return c}var c=UI.elements.menu,d;for(d in UI.menu){0<d&&c.append($("<br>"));for(var b in UI.menu[d]){var i=UI.menu[d][b],m=a(b,i);c.append(m);if("submenu"in i){var h=$("<span>").addClass("submenu");m.addClass("arrowdown").append(h);for(var f in i.submenu)h.append(a(f,
|
||||
i.submenu[f]))}else if("hiddenmenu"in i)for(f in h=$("<span>").addClass("hiddenmenu"),m.append(h),i.hiddenmenu)h.append(a(f,i.hiddenmenu[f]))}}d=$("<div>").attr("id","ih_button").text("?").click(function(){$("body").toggleClass("helpme");UI.stored.saveOpt("helpme",$("body").hasClass("helpme"))}).attr("title","Click to toggle the display of integrated help");UI.stored.getOpts().helpme&&$("body").addClass("helpme");c.after(d).after($("<div>").addClass("separator"))},findInput:function(a){return this.findInOutput("inputs",
|
||||
a)},findOutput:function(a){return this.findInOutput("connectors",a)},findInOutput:function(a,c){if("capabilities"in mist.data){var d=!1,b=mist.data.capabilities[a];c in b&&(d=b[c]);c+".exe"in b&&(d=b[c+".exe"]);return d}throw"Request capabilities first";},buildUI:function(a){var c=$("<div>").addClass("input_container"),d;for(d in a){var b=a[d];if(b instanceof jQuery)c.append(b);else if("help"==b.type){var i=$("<span>").addClass("text_container").append($("<span>").addClass("description").append(b.help));
|
||||
c.append(i);if("classes"in b)for(var m in b.classes)i.addClass(b.classes[m])}else if("text"==b.type)c.append($("<span>").addClass("text_container").append($("<span>").addClass("text").append(b.text)));else if("custom"==b.type)c.append(b.custom);else if("buttons"==b.type)for(m in i=$("<span>").addClass("button_container").on("keydown",function(a){a.stopPropagation()}),"css"in b&&i.css(b.css),c.append(i),b.buttons){var h=b.buttons[m],f=$("<button>").text(h.label).data("opts",h);"css"in h&&f.css(h.css);
|
||||
if("classes"in h)for(var r in h.classes)f.addClass(h.classes[r]);i.append(f);switch(h.type){case "cancel":f.addClass("cancel").click(h["function"]);break;case "save":f.addClass("save").click(function(){var a=$(this).data("opts").preSave;a&&a.call(this);var b=$(this).closest(".input_container"),c=!1;b.find('.hasValidate:visible, input[type="hidden"].hasValidate').each(function(){if(c=$(this).data("validate")(this,!0))return!1});(a=$(this).data("opts").failedValidate)&&a.call(this);c||(b.find('.isSetting:visible, input[type="hidden"].isSetting').each(function(){var a=
|
||||
$(this).getval(),b=$(this).data("pointer");if(""==a)if("default"in $(this).data("opts"))a=$(this).data("opts")["default"];else return b.main[b.index]=null,!0;b.main[b.index]=a}),(a=$(this).data("opts")["function"])&&a(this))});break;default:f.click(h["function"])}}else{var j=$("<label>").addClass("UIelement");c.append(j);"css"in b&&j.css(b.css);j.append($("<span>").addClass("label").html("label"in b?b.label+":":""));if("classes"in b)for(r in b.classes)j.addClass(b.classes[r]);i=$("<span>").addClass("field_container");
|
||||
j.append(i);var l;switch(b.type){case "password":l=$("<input>").attr("type","password");break;case "int":l=$("<input>").attr("type","number");"min"in b&&l.attr("min",b.min);"max"in b&&l.attr("max",b.max);"validate"in b?b.validate.push("int"):b.validate=["int"];break;case "span":l=$("<span>");break;case "debug":b.select=[["","Default"],[0,"0 - All debugging messages disabled"],[1,"1 - Messages about failed operations"],[2,"2 - Previous level, and error messages"],[3,"3 - Previous level, and warning messages"],
|
||||
[4,"4 - Previous level, and status messages for development"],[5,"5 - Previous level, and more status messages for development"],[6,"6 - Previous level, and verbose debugging messages"],[7,"7 - Previous level, and very verbose debugging messages"],[8,"8 - Report everything in extreme detail"],[9,"9 - Report everything in insane detail"],[10,"10 - All messages enabled"]];case "select":l=$("<select>");for(m in b.select)f=$("<option>"),"string"==typeof b.select[m]?f.text(b.select[m]):f.val(b.select[m][0]).text(b.select[m][1]),
|
||||
l.append(f);break;case "textarea":l=$("<textarea>").on("keydown",function(a){a.stopPropagation()});break;case "checkbox":l=$("<input>").attr("type","checkbox");break;case "hidden":l=$("<input>").attr("type","hidden");j.hide();break;case "email":l=$("<input>").attr("type","email").attr("autocomplete","on").attr("required","");break;case "browse":l=$("<input>").attr("type","text");"filetypes"in b&&l.data("filetypes",b.filetypes);break;case "geolimited":case "hostlimited":l=$("<input>").attr("type",
|
||||
"hidden");break;case "radioselect":l=$("<div>").addClass("radioselect");for(d in b.radioselect)if(h=$("<input>").attr("type","radio").val(b.radioselect[d][0]).attr("name",b.label),("LTSonly"in b&&!mist.data.LTS||b.readonly)&&h.prop("disabled",!0),f=$("<label>").append(h).append($("<span>").html(b.radioselect[d][1])),l.append(f),2<b.radioselect[d].length)for(m in h=$("<select>").change(function(){$(this).parent().find("input[type=radio]:enabled").prop("checked","true")}),f.append(h),("LTSonly"in b&&
|
||||
!mist.data.LTS||b.readonly)&&h.prop("disabled",!0),b.radioselect[d][2])f=$("<option>"),h.append(f),b.radioselect[d][2][m]instanceof Array?f.val(b.radioselect[d][2][m][0]).html(b.radioselect[d][2][m][1]):f.html(b.radioselect[d][2][m]);break;case "checklist":l=$("<div>").addClass("checkcontainer");$controls=$("<div>").addClass("controls");$checklist=$("<div>").addClass("checklist");l.append($checklist);for(d in b.checklist)"string"==typeof b.checklist[d]&&(b.checklist[d]=[b.checklist[d],b.checklist[d]]),
|
||||
$checklist.append($("<label>").text(b.checklist[d][1]).prepend($("<input>").attr("type","checkbox").attr("name",b.checklist[d][0])));break;case "DOMfield":l=b.DOMfield;break;case "unix":l=$("<input>").attr("type","datetime-local").attr("step",1);b.unit=$("<button>").text("Now").click(function(){$(this).closest(".field_container").find(".field").setval((new Date).getTime()/1E3)});break;case "selectinput":l=$("<div>").addClass("selectinput");h=$("<select>");l.append(h);h.data("input",!1);"LTSonly"in
|
||||
b&&!mist.data.LTS&&h.prop("disabled",!0);for(d in b.selectinput)f=$("<option>"),h.append(f),"string"==typeof b.selectinput[d]?f.text(b.selectinput[d]):(f.text(b.selectinput[d][1]),"string"==typeof b.selectinput[d][0]?f.val(b.selectinput[d][0]):(f.val("CUSTOM"),h.data("input")||h.data("input",UI.buildUI([b.selectinput[d][0]]).children())));h.data("input")&&l.append(h.data("input"));h.change(function(){"CUSTOM"==$(this).val()?$(this).data("input").css("display","flex"):$(this).data("input").hide()});
|
||||
h.trigger("change");break;case "inputlist":l=$("<div>").addClass("inputlist");l.data("newitem",function(){var a=$("<input>").attr("type","text").addClass("listitem");("LTSonly"in b&&!mist.data.LTS||b.readonly)&&a.prop("disabled",!0);var c=function(b){$(this).is(":last-child")?""!=$(this).val()?$(this).after(a.clone().keyup(c).val("")):8==b.which&&$(this).prev().focus():""==$(this).val()&&($(this).next().focus(),$(this).remove())};a.keyup(c);return a});l.append(l.data("newitem"));break;case "sublist":l=
|
||||
$("<div>").addClass("sublist");h=$("<div>").addClass("curvals");h.append($("<span>").text("None."));var u=$("<div>").addClass("itemsettings"),g=$("<button>").text("New "+b.itemLabel),e=b.sublist;l.data("build",function(a,c){for(var d in b.saveas)d in a||delete b.saveas[d];b.saveas=Object.assign(b.saveas,a);d="New";"undefined"!=typeof c&&(d="Edit");d=UI.buildUI([$("<h4>").text(d+" "+b.itemLabel)].concat(e).concat([{label:"Save first",type:"str",classes:["onlyshowhelp"],validate:[function(){return{msg:"Did you want to save this "+
|
||||
b.itemLabel+"?",classes:["red"]}}]},{type:"buttons",buttons:[{label:"Cancel",type:"cancel","function":function(){u.html("");g.show();j.show()}},{label:"Save "+b.itemLabel,type:"save",preSave:function(){$(this).closest(".input_container").find(".onlyshowhelp").closest("label").hide()},failedValidate:function(){$(this).closest(".input_container").find(".onlyshowhelp").closest("label").show()},"function":function(){var a=l.getval(),d=Object.assign({},b.saveas),e;for(e in d)null===d[e]&&delete d[e];"undefined"==
|
||||
typeof c?a.push(d):a[c]=d;l.setval(a);u.html("");g.show();j.show()}}]}]));u.html(d);g.hide();j.hide()});g.click(function(){l.data("build")({})});e.unshift({type:"str",label:"Human readable name",placeholder:"none",help:"A convenient name to describe this "+b.itemLabel+". It won't be used by MistServer.",pointer:{main:b.saveas,index:"x-LSP-name"}});l.data("savelist",[]);l.append(h).append(g);c.append(u);break;default:l=$("<input>").attr("type","text")}l.addClass("field").data("opts",b);"pointer"in
|
||||
b&&l.attr("name",b.pointer.index);i.append(l);if("classes"in b)for(m in b.classes)l.addClass(b.classes[m]);"placeholder"in b&&l.attr("placeholder",b.placeholder);"default"in b&&l.attr("placeholder",b["default"]);"unit"in b&&i.append($("<span>").addClass("unit").html(b.unit));"readonly"in b&&(l.attr("readonly","readonly"),l.click(function(){$(this).select()}));"qrcode"in b&&i.append($("<span>").addClass("unit").html($("<button>").text("QR").on("keydown",function(a){a.stopPropagation()}).click(function(){var a=
|
||||
String($(this).closest(".field_container").find(".field").getval()),b=$("<div>").addClass("qrcode");UI.popup.show($("<span>").addClass("qr_container").append($("<p>").text(a)).append(b));b.qrcode({text:a,size:Math.min(b.width(),b.height())})})));"clipboard"in b&&document.queryCommandSupported("copy")&&i.append($("<span>").addClass("unit").html($("<button>").text("Copy").on("keydown",function(a){a.stopPropagation()}).click(function(){var a=String($(this).closest(".field_container").find(".field").getval()),
|
||||
b=document.createElement("textarea");b.value=a;document.body.appendChild(b);b.select();var c=false;try{c=document.execCommand("copy")}catch(d){}if(c){$(this).text("Copied to clipboard!");document.body.removeChild(b);var e=$(this);setTimeout(function(){e.text("Copy")},5E3)}else{document.body.removeChild(b);alert("Failed to copy:\n"+a)}})));"rows"in b&&l.attr("rows",b.rows);"LTSonly"in b&&!mist.data.LTS&&(i.addClass("LTSonly"),l.prop("disabled",!0));if("dependent"in b)for(d in b.dependent)j.attr("data-dependent-"+
|
||||
d,b.dependent[d]);switch(b.type){case "browse":h=$("<div>").addClass("grouper").append(j);c.append(h);h=$("<button>").text("Browse").on("keydown",function(a){a.stopPropagation()});i.append(h);h.click(function(){function a(b){h.text("Loading..");mist.send(function(a){f.text(a.browse.path[0]);mist.data.LTS&&d.setval(a.browse.path[0]+"/");h.html(i.clone(true).text("..").attr("title","Folder up"));if(a.browse.subdirectories){a.browse.subdirectories.sort();for(var b in a.browse.subdirectories){var g=a.browse.subdirectories[b];
|
||||
h.append(i.clone(true).attr("title",f.text()+l+g).text(g))}}if(a.browse.files){a.browse.files.sort();for(b in a.browse.files){var g=a.browse.files[b],k=f.text()+l+g,g=$("<a>").text(g).addClass("file").attr("title",k);h.append(g);if(j){var n=true,m;for(m in j)if(typeof j[m]!="undefined"&&mist.inputMatch(j[m],k)){n=false;break}n&&g.hide()}g.click(function(){var a=$(this).attr("title");d.setval(a).removeAttr("readonly").css("opacity",1);e.show();c.remove()})}}},{browse:b})}var b=$(this).closest(".grouper"),
|
||||
c=$("<div>").addClass("browse_container"),d=b.find(".field").attr("readonly","readonly").css("opacity",0.5),e=$(this),g=$("<button>").text("Stop browsing").click(function(){e.show();c.remove();d.removeAttr("readonly").css("opacity",1)}),f=$("<span>").addClass("field"),h=$("<div>").addClass("browse_contents"),i=$("<a>").addClass("folder"),j=d.data("filetypes");b.append(c);c.append($("<label>").addClass("UIelement").append($("<span>").addClass("label").text("Current folder:")).append($("<span>").addClass("field_container").append(f).append(g))).append(h);
|
||||
var l="/";mist.data.config.version.indexOf("indows")>-1&&(l="\\");i.click(function(){var b=f.text()+l+$(this).text();a(b)});b=d.getval();g=b.split("://");g.length>1&&(b=g[0]=="file"?g[1]:"");b=b.split(l);b.pop();b=b.join(l);e.hide();a(b)});break;case "geolimited":case "hostlimited":h={field:l};h.blackwhite=$("<select>").append($("<option>").val("-").text("Blacklist")).append($("<option>").val("+").text("Whitelist"));h.values=$("<span>").addClass("limit_value_list");switch(b.type){case "geolimited":h.prototype=
|
||||
$("<select>").append($("<option>").val("").text("[Select a country]"));for(d in UI.countrylist)h.prototype.append($("<option>").val(d).html(UI.countrylist[d]));break;case "hostlimited":h.prototype=$("<input>").attr("type","text").attr("placeholder","type a host")}h.prototype.on("change keyup",function(){$(this).closest(".field_container").data("subUI").blackwhite.trigger("change")});h.blackwhite.change(function(){var a=$(this).closest(".field_container").data("subUI"),b=[],c=false;a.values.children().each(function(){c=
|
||||
$(this).val();c!=""?b.push(c):$(this).remove()});a.values.append(a.prototype.clone(true));b.length>0?a.field.val($(this).val()+b.join(" ")):a.field.val("");a.field.trigger("change")});"LTSonly"in b&&!mist.data.LTS&&(h.blackwhite.prop("disabled",!0),h.prototype.prop("disabled",!0));h.values.append(h.prototype.clone(!0));i.data("subUI",h).addClass("limit_list").append(h.blackwhite).append(h.values)}"pointer"in b&&(l.data("pointer",b.pointer).addClass("isSetting"),b.pointer.main&&(h=b.pointer.main[b.pointer.index],
|
||||
"undefined"!=h&&l.setval(h)));(""==l.getval()||null==l.getval())&&"value"in b&&l.setval(b.value);if("datalist"in b)for(d in h="datalist_"+d+MD5(l[0].outerHTML),l.attr("list",h),h=$("<datalist>").attr("id",h),i.append(h),b.datalist)h.append($("<option>").val(b.datalist[d]));i=$("<span>").addClass("help_container");j.append(i);"help"in b&&(i.append($("<span>").addClass("ih_balloon").html(b.help)),l.on("focus mouseover",function(){$(this).closest("label").addClass("active")}).on("blur mouseout",function(){$(this).closest("label").removeClass("active")}));
|
||||
if("validate"in b){h=[];for(m in b.validate){f=b.validate[m];if("function"!=typeof f)switch(f){case "required":f=function(a){return a==""||a==null?{msg:"This is a required field.",classes:["red"]}:false};break;case "int":f=function(a,b){var c=$(b).data("opts");if(!$(b)[0].validity.valid){var d=[];"min"in c&&d.push(" greater than or equal to "+c.min);"max"in c&&d.push(" smaller than or equal to "+c.max);return{msg:"Please enter an integer"+d.join(" and")+".",classes:["red"]}}if(parseInt(Number(a))!=
|
||||
a)return{msg:"Please enter an integer.",classes:["red"]}};break;case "streamname":f=function(a,b){if(a!=""){if(!isNaN(a.charAt(0)))return{msg:"The first character may not be a number.",classes:["red"]};if(a.toLowerCase()!=a)return{msg:"Uppercase letters are not allowed.",classes:["red"]};if(a.replace(/[^\da-z_]/g,"")!=a)return{msg:"Special characters (except for underscores) are not allowed.",classes:["red"]};if("streams"in mist.data&&a in mist.data.streams&&$(b).data("pointer").main.name!=a)return{msg:"This streamname already exists.<br>If you want to edit an existing stream, please click edit on the the streams tab.",
|
||||
classes:["red"]}}};break;case "streamname_with_wildcard":f=function(a){if(a!=""){streampart=a.split("+");var b=streampart.slice(1).join("+");streampart=streampart[0];if(!isNaN(streampart.charAt(0)))return{msg:"The first character may not be a number.",classes:["red"]};if(streampart.toLowerCase()!=streampart)return{msg:"Uppercase letters are not allowed in a stream name.",classes:["red"]};if(streampart.replace(/[^\da-z_]/g,"")!=streampart)return{msg:"Special characters (except for underscores) are not allowed in a stream name.",
|
||||
classes:["red"]};if(streampart!=a&&b.replace(/[\00|\0|\/]/g,"")!=b)return{msg:"Slashes or null bytes are not allowed in wildcards.",classes:["red"]}}};break;default:f=function(){}}h.push(f)}l.data("validate_functions",h).data("help_container",i).data("validate",function(a,b){if($(a).is(":visible")){var c=$(a).getval(),d=$(a).data("validate_functions"),g=$(a).data("help_container");g.find(".err_balloon").remove();for(var e in d){var f=d[e](c,a);if(f){$err=$("<span>").addClass("err_balloon").html(f.msg);
|
||||
for(var h in f.classes)$err.addClass(f.classes[h]);g.prepend($err);b&&$(a).focus();return typeof f=="object"&&"break"in f?f["break"]:true}}return false}}).addClass("hasValidate").on("change keyup",function(){$(this).data("validate")($(this))});""!=l.getval()&&l.trigger("change")}"function"in b&&(l.on("change keyup",b["function"]),l.trigger("change"))}}c.on("keydown",function(a){var b=!1;switch(a.which){case 13:b=$(this).find("button.save").first();break;case 27:b=$(this).find("button.cancel").first()}b&&
|
||||
b.length&&(b.trigger("click"),a.stopPropagation())});return c},buildVheaderTable:function(a){var c=$("<table>").css("margin","0.2em"),d=$("<tr>").addClass("header").append($("<td>").addClass("vheader").attr("rowspan",a.labels.length+1).append($("<span>").text(a.vheader))),b=[];d.append($("<td>"));for(var i in a.labels)b.push($("<tr>").append($("<td>").html(""==a.labels[i]?" ":a.labels[i]+":")));for(var m in a.content)for(i in d.append($("<td>").html(a.content[m].header)),a.content[m].body)b[i].append($("<td>").html(a.content[m].body[i]));
|
||||
c.append($("<tbody>").append(d).append(b));return c},plot:{addGraph:function(a,c){var d={id:a.id,xaxis:a.xaxis,datasets:[],elements:{cont:$("<div>").addClass("graph"),plot:$("<div>").addClass("plot"),legend:$("<div>").addClass("legend").attr("draggable","true")}};UI.draggable(d.elements.legend);d.elements.cont.append(d.elements.plot).append(d.elements.legend);c.append(d.elements.cont);return d},go:function(a){if(!(1>Object.keys(a).length)){var c={totals:[],clients:[]},d;for(d in a)for(var b in a[d].datasets){var i=
|
||||
a[d].datasets[b];switch(i.datatype){case "clients":case "upbps":case "downbps":switch(i.origin[0]){case "total":c.totals.push({fields:[i.datatype],end:-15});break;case "stream":c.totals.push({fields:[i.datatype],streams:[i.origin[1]],end:-15});break;case "protocol":c.totals.push({fields:[i.datatype],protocols:[i.origin[1]],end:-15})}break;case "cpuload":case "memload":c.capabilities={}}}0==c.totals.length&&delete c.totals;0==c.clients.length&&delete c.clients;mist.send(function(){for(var b in a){var c=
|
||||
a[b];if(1>c.datasets.length){c.elements.plot.html("");c.elements.legend.html("");break}switch(c.xaxis){case "time":var d=[];c.yaxes={};var i=[],j;for(j in c.datasets){var l=c.datasets[j];l.display&&(l.getdata(),l.yaxistype in c.yaxes||(d.push(UI.plot.yaxes[l.yaxistype]),c.yaxes[l.yaxistype]=d.length),l.yaxis=c.yaxes[l.yaxistype],i.push(l))}d[0]&&(d[0].color=0);c.plot=$.plot(c.elements.plot,i,{legend:{show:!1},xaxis:UI.plot.xaxes[c.xaxis],yaxes:d,grid:{hoverable:!0,borderWidth:{top:0,right:0,bottom:1,
|
||||
left:1},color:"black",backgroundColor:{colors:["rgba(0,0,0,0)","rgba(0,0,0,0.025)"]}},crosshair:{mode:"x"}});d=$("<table>").addClass("legend-list").addClass("nolay").html($("<tr>").html($("<td>").html($("<h3>").text(c.id))).append($("<td>").css("padding-right","2em").css("text-align","right").html($("<span>").addClass("value")).append($("<button>").data("opts",c).text("X").addClass("close").click(function(){var b=$(this).data("opts");if(confirm("Are you sure you want to remove "+b.id+"?")){b.elements.cont.remove();
|
||||
var c=$(".graph_ids option:contains("+b.id+")"),d=c.parent();c.remove();UI.plot.del(b.id);delete a[b.id];d.trigger("change");UI.plot.go(a)}}))));c.elements.legend.html(d);var u=function(a){var b=c.elements.legend.find(".value"),d=1;if(typeof a=="undefined")b.eq(0).html("Latest:");else{var g=c.plot.getXAxes()[0],a=Math.min(g.max,a),a=Math.max(g.min,a);b.eq(0).html(UI.format.time(a/1E3))}for(var f in c.datasets){var i=" ";if(c.datasets[f].display){var g=UI.plot.yaxes[c.datasets[f].yaxistype].tickFormatter,
|
||||
j=c.datasets[f].data;if(a)for(var l in j){if(j[l][0]==a){i=g(j[l][1]);break}if(j[l][0]>a){if(l!=0){i=j[l];j=j[l-1];i=g(i[1]+(a-i[0])*(j[1]-i[1])/(j[0]-i[0]))}break}}else i=g(c.datasets[f].data[c.datasets[f].data.length-1][1])}b.eq(d).html(i);d++}};c.plot.getOptions();for(j in c.datasets)i=$("<input>").attr("type","checkbox").data("index",j).data("graph",c).click(function(){var a=$(this).data("graph");$(this).is(":checked")?a.datasets[$(this).data("index")].display=true:a.datasets[$(this).data("index")].display=
|
||||
false;var b={};b[a.id]=a;UI.plot.go(b)}),c.datasets[j].display&&i.attr("checked","checked"),d.append($("<tr>").html($("<td>").html($("<label>").html(i).append($("<div>").addClass("series-color").css("background-color",c.datasets[j].color)).append(c.datasets[j].label))).append($("<td>").css("padding-right","2em").css("text-align","right").html($("<span>").addClass("value")).append($("<button>").text("X").addClass("close").data("index",j).data("graph",c).click(function(){var b=$(this).data("index"),
|
||||
c=$(this).data("graph");if(confirm("Are you sure you want to remove "+c.datasets[b].label+" from "+c.id+"?")){c.datasets.splice(b,1);if(c.datasets.length==0){c.elements.cont.remove();var b=$(".graph_ids option:contains("+c.id+")"),d=b.parent();b.remove();d.trigger("change");UI.plot.del(c.id);delete a[c.id];UI.plot.go(a)}else{UI.plot.save(c);b={};b[c.id]=c;UI.plot.go(b)}}}))));u();var g=!1;c.elements.plot.on("plothover",function(a,b,c){if(b.x!=g){u(b.x);g=b.x}if(c){a=$("<span>").append($("<h3>").text(c.series.label).prepend($("<div>").addClass("series-color").css("background-color",
|
||||
c.series.color))).append($("<table>").addClass("nolay").html($("<tr>").html($("<td>").text("Time:")).append($("<td>").html(UI.format.dateTime(c.datapoint[0]/1E3,"long")))).append($("<tr>").html($("<td>").text("Value:")).append($("<td>").html(c.series.yaxis.tickFormatter(c.datapoint[1],c.series.yaxis)))));UI.tooltip.show(b,a.children())}else UI.tooltip.hide()}).on("mouseout",function(){u()})}}},c)}},save:function(a){var c={id:a.id,xaxis:a.xaxis,datasets:[]},d;for(d in a.datasets)c.datasets.push({origin:a.datasets[d].origin,
|
||||
datatype:a.datasets[d].datatype});a=mist.stored.get().graphs||{};a[c.id]=c;mist.stored.set("graphs",a)},del:function(a){var c=mist.stored.get().graphs||{};delete c[a];mist.stored.set("graphs",c)},datatype:{getOptions:function(a){var c=$.extend(!0,{},UI.plot.datatype.templates.general),d=$.extend(!0,{},UI.plot.datatype.templates[a.datatype]),a=$.extend(!0,d,a),a=$.extend(!0,c,a);switch(a.origin[0]){case "total":switch(a.datatype){case "cpuload":case "memload":break;default:a.label+=" (total)"}break;
|
||||
case "stream":case "protocol":a.label+=" ("+a.origin[1]+")"}var c=[],b;for(b in a.basecolor)d=a.basecolor[b],d+=50*(0.5-Math.random()),d=Math.round(d),d=Math.min(255,Math.max(0,d)),c.push(d);a.color="rgb("+c.join(",")+")";return a},templates:{general:{display:!0,datatype:"general",label:"",yaxistype:"amount",data:[],lines:{show:!0},points:{show:!1},getdata:function(){var a=mist.data.totals["stream"==this.origin[0]?this.origin[1]:"all_streams"]["protocol"==this.origin[0]?this.origin[1]:"all_protocols"][this.datatype];
|
||||
return this.data=a}},cpuload:{label:"CPU use",yaxistype:"percentage",basecolor:[237,194,64],cores:1,getdata:function(){var a=!1,c;for(c in this.data)this.data[c][0]<1E3*(mist.data.config.time-600)&&(a=c);!1!==a&&this.data.splice(0,Number(a)+1);this.data.push([1E3*mist.data.config.time,mist.data.capabilities.cpu_use/10]);return this.data}},memload:{label:"Memory load",yaxistype:"percentage",basecolor:[175,216,248],getdata:function(){var a=!1,c;for(c in this.data)this.data[c][0]<1E3*(mist.data.config.time-
|
||||
600)&&(a=c);!1!==a&&this.data.splice(0,Number(a)+1);this.data.push([1E3*mist.data.config.time,mist.data.capabilities.load.memory]);return this.data}},clients:{label:"Connections",basecolor:[203,75,75]},upbps:{label:"Bandwidth up",yaxistype:"bytespersec",basecolor:[77,167,77]},downbps:{label:"Bandwidth down",yaxistype:"bytespersec",basecolor:[148,64,237]}}},yaxes:{percentage:{name:"percentage",color:"black",tickColor:0,tickDecimals:0,tickFormatter:function(a){return UI.format.addUnit(UI.format.number(a),
|
||||
"%")},tickLength:0,min:0,max:100},amount:{name:"amount",color:"black",tickColor:0,tickDecimals:0,tickFormatter:function(a){return UI.format.number(a)},tickLength:0,min:0},bytespersec:{name:"bytespersec",color:"black",tickColor:0,tickDecimals:1,tickFormatter:function(a){return UI.format.bytes(a,!0)},tickLength:0,ticks:function(a){var c=0.3*Math.sqrt($(".graph").first().height()),c=(a.max-a.min)/c,d=Math.floor(Math.log(Math.abs(c))/Math.log(1024)),b=c/Math.pow(1024,d),i=-Math.floor(Math.log(b)/Math.LN10),
|
||||
m=a.tickDecimals;null!=m&&i>m&&(i=m);var h=Math.pow(10,-i),b=b/h,f;if(1.5>b)f=1;else if(3>b){if(f=2,2.25<b&&(null==m||i+1<=m))f=2.5,++i}else f=7.5>b?5:10;f=f*h*Math.pow(1024,d);null!=a.minTickSize&&f<a.minTickSize&&(f=a.minTickSize);a.delta=c;a.tickDecimals=Math.max(0,null!=m?m:i);a.tickSize=f;c=[];d=a.tickSize*Math.floor(a.min/a.tickSize);i=0;m=Number.NaN;do h=m,m=d+i*a.tickSize,c.push(m),++i;while(m<a.max&&m!=h);return c},min:0}},xaxes:{time:{name:"time",mode:"time",timezone:"browser",ticks:5}}},
|
||||
draggable:function(a){a.attr("draggable",!0);a.on("dragstart",function(a){$(this).css("opacity",0.4).data("dragstart",{click:{x:a.originalEvent.pageX,y:a.originalEvent.pageY},ele:{x:this.offsetLeft,y:this.offsetTop}})}).on("dragend",function(a){var d=$(this).data("dragstart"),b=d.ele.x-d.click.x+a.originalEvent.pageX,a=d.ele.y-d.click.y+a.originalEvent.pageY;$(this).css({opacity:1,top:a,left:b,right:"auto",bottom:"auto"})});a.parent().on("dragleave",function(){})},format:{time:function(a,c){var d=
|
||||
new Date(1E3*a),b=[];b.push(("0"+d.getHours()).slice(-2));b.push(("0"+d.getMinutes()).slice(-2));"short"!=c&&b.push(("0"+d.getSeconds()).slice(-2));return b.join(":")},date:function(a,c){var d=new Date(1E3*a),b="Sun Mon Tue Wed Thu Fri Sat".split(" "),i=[];"long"==c&&i.push(b[d.getDay()]);i.push(("0"+d.getDate()).slice(-2));i.push("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" ")[d.getMonth()]);"short"!=c&&i.push(d.getFullYear());return i.join(" ")},dateTime:function(a,c){return UI.format.date(a,
|
||||
c)+", "+UI.format.time(a,c)},duration:function(a){var c=[0.001,1E3,60,60,24,7,52,1E9],d="ms sec min hr day week year".split(" "),b={},i;for(i in d){var a=a/c[i],m=Math.round(a%c[Number(i)+1]);b[d[i]]=m;a-=m}var h;for(i=d.length-1;0<=i;i--)if(0<b[d[i]]){h=d[i];break}c=$("<span>");switch(h){case "year":c.append(UI.format.addUnit(b.year,"years, ")).append(UI.format.addUnit(b.week,"wks"));break;case "week":c.append(UI.format.addUnit(b.week,"wks, ")).append(UI.format.addUnit(b.day,"days"));break;case "day":c.append(UI.format.addUnit(b.day,
|
||||
"days, ")).append(UI.format.addUnit(b.hr,"hrs"));break;default:c.append([("0"+b.hr).slice(-2),("0"+b.min).slice(-2),("0"+b.sec).slice(-2)+(b.ms?"."+b.ms:"")].join(":"))}return c[0].innerHTML},number:function(a){if(isNaN(Number(a))||0==a)return a;var c=Math.pow(10,3-Math.floor(Math.log(a)/Math.LN10)-1),a=Math.round(a*c)/c;if(1E4<a){number=a.toString().split(".");for(a=/(\d+)(\d{3})/;a.test(number[0]);)number[0]=number[0].replace(a,"$1 $2");a=number.join(".")}return a},status:function(a){var c=$("<span>");
|
||||
if("undefined"==typeof a.online)return c.text("Unknown, checking.."),"undefined"!=typeof a.error&&c.text(a.error),c;switch(a.online){case -1:c.text("Enabling");break;case 0:c.text("Unavailable").addClass("red");break;case 1:c.text("Active").addClass("green");break;case 2:c.text("Standby").addClass("orange");break;default:c.text(a.online)}"error"in a&&c.text(a.error);return c},capital:function(a){return a.charAt(0).toUpperCase()+a.substring(1)},addUnit:function(a,c){var d=$("<span>").html(a);d.append($("<span>").addClass("unit").html(c));
|
||||
return d[0].innerHTML},bytes:function(a,c){var d="bytes KiB MiB GiB TiB PiB".split(" ");if(0==a)unit=d[0];else{var b=Math.floor(Math.log(Math.abs(a))/Math.log(1024));0>b?unit=d[0]:(a/=Math.pow(1024,b),unit=d[b])}return UI.format.addUnit(UI.format.number(a),unit+(c?"/s":""))}},navto:function(a,c){var d=location.hash,b=d.split("@");b[0]=[mist.user.name,mist.user.host].join("&");b[1]=[a,c].join("&");"undefined"!=typeof screenlog&&screenlog.navto(b[1]);location.hash=b.join("@");location.hash==d&&$(window).trigger("hashchange")},
|
||||
showTab:function(a,c){var d=UI.elements.main;if(mist.user.loggedin){if(!("ui_settings"in mist.data)){d.html("Loading..");mist.send(function(){UI.showTab(a,c)},{ui_settings:!0});return}mist.data.config.serverid&&(document.title=mist.data.config.serverid+" - MistServer MI")}var b=UI.elements.menu.removeClass("hide").find('.plain:contains("'+a+'")').closest(".button");0<b.length&&(UI.elements.menu.find(".button.active").removeClass("active"),b.addClass("active"));MistVideoObject&&MistVideoObject.reference&&
|
||||
MistVideoObject.reference.unload();UI.interval.clear();d.html($("<h2>").text(a));switch(a){case "Login":if(mist.user.loggedin){UI.navto("Overview");return}document.title="MistServer MI";UI.elements.menu.addClass("hide");UI.elements.connection.status.text("Disconnected").removeClass("green").addClass("red");d.append(UI.buildUI([{type:"help",help:"Please provide your account details.<br>You were asked to set these when MistController was started for the first time. If you did not yet set any account details, log in with your desired credentials to create a new account."},
|
||||
classes:["red"]};if(streampart!=a&&b.replace(/[\00|\0|\/]/g,"")!=b)return{msg:"Slashes or null bytes are not allowed in wildcards.",classes:["red"]}}};break;case "streamname_with_wildcard_and_variables":f=function(a){if(a!=""){streampart=a.split("+");var b=streampart.slice(1).join("+");streampart=streampart[0];if(!isNaN(streampart.charAt(0)))return{msg:"The first character may not be a number.",classes:["red"]};if(streampart.toLowerCase()!=streampart)return{msg:"Uppercase letters are not allowed in a stream name.",
|
||||
classes:["red"]};if(streampart.replace(/[^\da-z_$]/g,"")!=streampart)return{msg:"Special characters (except for underscores) are not allowed in a stream name.",classes:["red"]};if(streampart!=a&&b.replace(/[\00|\0|\/]/g,"")!=b)return{msg:"Slashes or null bytes are not allowed in wildcards.",classes:["red"]}}};break;default:f=function(){}}h.push(f)}l.data("validate_functions",h).data("help_container",i).data("validate",function(a,b){if($(a).is(":visible")||$(a).is('input[type="hidden"]')){var c=$(a).getval(),
|
||||
d=$(a).data("validate_functions"),g=$(a).data("help_container");g.find(".err_balloon").remove();for(var e in d){var f=d[e](c,a);if(f){$err=$("<span>").addClass("err_balloon").html(f.msg);for(var h in f.classes)$err.addClass(f.classes[h]);g.prepend($err);b&&$(a).focus();return typeof f=="object"&&"break"in f?f["break"]:true}}return false}}).addClass("hasValidate").on("change keyup",function(){$(this).data("validate")($(this))});""!=l.getval()&&l.trigger("change")}"function"in b&&(l.on("change keyup",
|
||||
b["function"]),l.trigger("change"))}}c.on("keydown",function(a){var b=!1;switch(a.which){case 13:b=$(this).find("button.save").first();break;case 27:b=$(this).find("button.cancel").first()}b&&b.length&&(b.trigger("click"),a.stopPropagation())});return c},buildVheaderTable:function(a){var c=$("<table>").css("margin","0.2em"),d=$("<tr>").addClass("header").append($("<td>").addClass("vheader").attr("rowspan",a.labels.length+1).append($("<span>").text(a.vheader))),b=[];d.append($("<td>"));for(var i in a.labels)b.push($("<tr>").append($("<td>").html(""==
|
||||
a.labels[i]?" ":a.labels[i]+":")));for(var m in a.content)for(i in d.append($("<td>").html(a.content[m].header)),a.content[m].body)b[i].append($("<td>").html(a.content[m].body[i]));c.append($("<tbody>").append(d).append(b));return c},plot:{addGraph:function(a,c){var d={id:a.id,xaxis:a.xaxis,datasets:[],elements:{cont:$("<div>").addClass("graph"),plot:$("<div>").addClass("plot"),legend:$("<div>").addClass("legend").attr("draggable","true")}};UI.draggable(d.elements.legend);d.elements.cont.append(d.elements.plot).append(d.elements.legend);
|
||||
c.append(d.elements.cont);return d},go:function(a){if(!(1>Object.keys(a).length)){var c={totals:[],clients:[]},d;for(d in a)for(var b in a[d].datasets){var i=a[d].datasets[b];switch(i.datatype){case "clients":case "upbps":case "downbps":switch(i.origin[0]){case "total":c.totals.push({fields:[i.datatype],end:-15});break;case "stream":c.totals.push({fields:[i.datatype],streams:[i.origin[1]],end:-15});break;case "protocol":c.totals.push({fields:[i.datatype],protocols:[i.origin[1]],end:-15})}break;case "cpuload":case "memload":c.capabilities=
|
||||
{}}}0==c.totals.length&&delete c.totals;0==c.clients.length&&delete c.clients;mist.send(function(){for(var b in a){var c=a[b];if(1>c.datasets.length){c.elements.plot.html("");c.elements.legend.html("");break}switch(c.xaxis){case "time":var d=[];c.yaxes={};var i=[],j;for(j in c.datasets){var l=c.datasets[j];l.display&&(l.getdata(),l.yaxistype in c.yaxes||(d.push(UI.plot.yaxes[l.yaxistype]),c.yaxes[l.yaxistype]=d.length),l.yaxis=c.yaxes[l.yaxistype],i.push(l))}d[0]&&(d[0].color=0);c.plot=$.plot(c.elements.plot,
|
||||
i,{legend:{show:!1},xaxis:UI.plot.xaxes[c.xaxis],yaxes:d,grid:{hoverable:!0,borderWidth:{top:0,right:0,bottom:1,left:1},color:"black",backgroundColor:{colors:["rgba(0,0,0,0)","rgba(0,0,0,0.025)"]}},crosshair:{mode:"x"}});d=$("<table>").addClass("legend-list").addClass("nolay").html($("<tr>").html($("<td>").html($("<h3>").text(c.id))).append($("<td>").css("padding-right","2em").css("text-align","right").html($("<span>").addClass("value")).append($("<button>").data("opts",c).text("X").addClass("close").click(function(){var b=
|
||||
$(this).data("opts");if(confirm("Are you sure you want to remove "+b.id+"?")){b.elements.cont.remove();var c=$(".graph_ids option:contains("+b.id+")"),d=c.parent();c.remove();UI.plot.del(b.id);delete a[b.id];d.trigger("change");UI.plot.go(a)}}))));c.elements.legend.html(d);var u=function(a){var b=c.elements.legend.find(".value"),d=1;if(typeof a=="undefined")b.eq(0).html("Latest:");else{var g=c.plot.getXAxes()[0],a=Math.min(g.max,a),a=Math.max(g.min,a);b.eq(0).html(UI.format.time(a/1E3))}for(var f in c.datasets){var i=
|
||||
" ";if(c.datasets[f].display){var g=UI.plot.yaxes[c.datasets[f].yaxistype].tickFormatter,j=c.datasets[f].data;if(a)for(var l in j){if(j[l][0]==a){i=g(j[l][1]);break}if(j[l][0]>a){if(l!=0){i=j[l];j=j[l-1];i=g(i[1]+(a-i[0])*(j[1]-i[1])/(j[0]-i[0]))}break}}else i=g(c.datasets[f].data[c.datasets[f].data.length-1][1])}b.eq(d).html(i);d++}};c.plot.getOptions();for(j in c.datasets)i=$("<input>").attr("type","checkbox").data("index",j).data("graph",c).click(function(){var a=$(this).data("graph");$(this).is(":checked")?
|
||||
a.datasets[$(this).data("index")].display=true:a.datasets[$(this).data("index")].display=false;var b={};b[a.id]=a;UI.plot.go(b)}),c.datasets[j].display&&i.attr("checked","checked"),d.append($("<tr>").html($("<td>").html($("<label>").html(i).append($("<div>").addClass("series-color").css("background-color",c.datasets[j].color)).append(c.datasets[j].label))).append($("<td>").css("padding-right","2em").css("text-align","right").html($("<span>").addClass("value")).append($("<button>").text("X").addClass("close").data("index",
|
||||
j).data("graph",c).click(function(){var b=$(this).data("index"),c=$(this).data("graph");if(confirm("Are you sure you want to remove "+c.datasets[b].label+" from "+c.id+"?")){c.datasets.splice(b,1);if(c.datasets.length==0){c.elements.cont.remove();var b=$(".graph_ids option:contains("+c.id+")"),d=b.parent();b.remove();d.trigger("change");UI.plot.del(c.id);delete a[c.id];UI.plot.go(a)}else{UI.plot.save(c);b={};b[c.id]=c;UI.plot.go(b)}}}))));u();var g=!1;c.elements.plot.on("plothover",function(a,b,c){if(b.x!=
|
||||
g){u(b.x);g=b.x}if(c){a=$("<span>").append($("<h3>").text(c.series.label).prepend($("<div>").addClass("series-color").css("background-color",c.series.color))).append($("<table>").addClass("nolay").html($("<tr>").html($("<td>").text("Time:")).append($("<td>").html(UI.format.dateTime(c.datapoint[0]/1E3,"long")))).append($("<tr>").html($("<td>").text("Value:")).append($("<td>").html(c.series.yaxis.tickFormatter(c.datapoint[1],c.series.yaxis)))));UI.tooltip.show(b,a.children())}else UI.tooltip.hide()}).on("mouseout",
|
||||
function(){u()})}}},c)}},save:function(a){var c={id:a.id,xaxis:a.xaxis,datasets:[]},d;for(d in a.datasets)c.datasets.push({origin:a.datasets[d].origin,datatype:a.datasets[d].datatype});a=mist.stored.get().graphs||{};a[c.id]=c;mist.stored.set("graphs",a)},del:function(a){var c=mist.stored.get().graphs||{};delete c[a];mist.stored.set("graphs",c)},datatype:{getOptions:function(a){var c=$.extend(!0,{},UI.plot.datatype.templates.general),d=$.extend(!0,{},UI.plot.datatype.templates[a.datatype]),a=$.extend(!0,
|
||||
d,a),a=$.extend(!0,c,a);switch(a.origin[0]){case "total":switch(a.datatype){case "cpuload":case "memload":break;default:a.label+=" (total)"}break;case "stream":case "protocol":a.label+=" ("+a.origin[1]+")"}var c=[],b;for(b in a.basecolor)d=a.basecolor[b],d+=50*(0.5-Math.random()),d=Math.round(d),d=Math.min(255,Math.max(0,d)),c.push(d);a.color="rgb("+c.join(",")+")";return a},templates:{general:{display:!0,datatype:"general",label:"",yaxistype:"amount",data:[],lines:{show:!0},points:{show:!1},getdata:function(){var a=
|
||||
mist.data.totals["stream"==this.origin[0]?this.origin[1]:"all_streams"]["protocol"==this.origin[0]?this.origin[1]:"all_protocols"][this.datatype];return this.data=a}},cpuload:{label:"CPU use",yaxistype:"percentage",basecolor:[237,194,64],cores:1,getdata:function(){var a=!1,c;for(c in this.data)this.data[c][0]<1E3*(mist.data.config.time-600)&&(a=c);!1!==a&&this.data.splice(0,Number(a)+1);this.data.push([1E3*mist.data.config.time,mist.data.capabilities.cpu_use/10]);return this.data}},memload:{label:"Memory load",
|
||||
yaxistype:"percentage",basecolor:[175,216,248],getdata:function(){var a=!1,c;for(c in this.data)this.data[c][0]<1E3*(mist.data.config.time-600)&&(a=c);!1!==a&&this.data.splice(0,Number(a)+1);this.data.push([1E3*mist.data.config.time,mist.data.capabilities.load.memory]);return this.data}},clients:{label:"Connections",basecolor:[203,75,75]},upbps:{label:"Bandwidth up",yaxistype:"bytespersec",basecolor:[77,167,77]},downbps:{label:"Bandwidth down",yaxistype:"bytespersec",basecolor:[148,64,237]}}},yaxes:{percentage:{name:"percentage",
|
||||
color:"black",tickColor:0,tickDecimals:0,tickFormatter:function(a){return UI.format.addUnit(UI.format.number(a),"%")},tickLength:0,min:0,max:100},amount:{name:"amount",color:"black",tickColor:0,tickDecimals:0,tickFormatter:function(a){return UI.format.number(a)},tickLength:0,min:0},bytespersec:{name:"bytespersec",color:"black",tickColor:0,tickDecimals:1,tickFormatter:function(a){return UI.format.bytes(a,!0)},tickLength:0,ticks:function(a){var c=0.3*Math.sqrt($(".graph").first().height()),c=(a.max-
|
||||
a.min)/c,d=Math.floor(Math.log(Math.abs(c))/Math.log(1024)),b=c/Math.pow(1024,d),i=-Math.floor(Math.log(b)/Math.LN10),m=a.tickDecimals;null!=m&&i>m&&(i=m);var h=Math.pow(10,-i),b=b/h,f;if(1.5>b)f=1;else if(3>b){if(f=2,2.25<b&&(null==m||i+1<=m))f=2.5,++i}else f=7.5>b?5:10;f=f*h*Math.pow(1024,d);null!=a.minTickSize&&f<a.minTickSize&&(f=a.minTickSize);a.delta=c;a.tickDecimals=Math.max(0,null!=m?m:i);a.tickSize=f;c=[];d=a.tickSize*Math.floor(a.min/a.tickSize);i=0;m=Number.NaN;do h=m,m=d+i*a.tickSize,
|
||||
c.push(m),++i;while(m<a.max&&m!=h);return c},min:0}},xaxes:{time:{name:"time",mode:"time",timezone:"browser",ticks:5}}},draggable:function(a){a.attr("draggable",!0);a.on("dragstart",function(a){$(this).css("opacity",0.4).data("dragstart",{click:{x:a.originalEvent.pageX,y:a.originalEvent.pageY},ele:{x:this.offsetLeft,y:this.offsetTop}})}).on("dragend",function(a){var d=$(this).data("dragstart"),b=d.ele.x-d.click.x+a.originalEvent.pageX,a=d.ele.y-d.click.y+a.originalEvent.pageY;$(this).css({opacity:1,
|
||||
top:a,left:b,right:"auto",bottom:"auto"})});a.parent().on("dragleave",function(){})},format:{time:function(a,c){var d=new Date(1E3*a),b=[];b.push(("0"+d.getHours()).slice(-2));b.push(("0"+d.getMinutes()).slice(-2));"short"!=c&&b.push(("0"+d.getSeconds()).slice(-2));return b.join(":")},date:function(a,c){var d=new Date(1E3*a),b="Sun Mon Tue Wed Thu Fri Sat".split(" "),i=[];"long"==c&&i.push(b[d.getDay()]);i.push(("0"+d.getDate()).slice(-2));i.push("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" ")[d.getMonth()]);
|
||||
"short"!=c&&i.push(d.getFullYear());return i.join(" ")},dateTime:function(a,c){return UI.format.date(a,c)+", "+UI.format.time(a,c)},duration:function(a){var c=[0.001,1E3,60,60,24,7,52,1E9],d="ms sec min hr day week year".split(" "),b={},i;for(i in d){var a=a/c[i],m=Math.round(a%c[Number(i)+1]);b[d[i]]=m;a-=m}var h;for(i=d.length-1;0<=i;i--)if(0<b[d[i]]){h=d[i];break}c=$("<span>");switch(h){case "year":c.append(UI.format.addUnit(b.year,"years, ")).append(UI.format.addUnit(b.week,"wks"));break;case "week":c.append(UI.format.addUnit(b.week,
|
||||
"wks, ")).append(UI.format.addUnit(b.day,"days"));break;case "day":c.append(UI.format.addUnit(b.day,"days, ")).append(UI.format.addUnit(b.hr,"hrs"));break;default:c.append([("0"+b.hr).slice(-2),("0"+b.min).slice(-2),("0"+b.sec).slice(-2)+(b.ms?"."+b.ms:"")].join(":"))}return c[0].innerHTML},number:function(a){if(isNaN(Number(a))||0==a)return a;var c=Math.pow(10,3-Math.floor(Math.log(a)/Math.LN10)-1),a=Math.round(a*c)/c;if(1E4<a){number=a.toString().split(".");for(a=/(\d+)(\d{3})/;a.test(number[0]);)number[0]=
|
||||
number[0].replace(a,"$1 $2");a=number.join(".")}return a},status:function(a){var c=$("<span>");if("undefined"==typeof a.online)return c.text("Unknown, checking.."),"undefined"!=typeof a.error&&c.text(a.error),c;switch(a.online){case -1:c.text("Enabling");break;case 0:c.text("Unavailable").addClass("red");break;case 1:c.text("Active").addClass("green");break;case 2:c.text("Standby").addClass("orange");break;default:c.text(a.online)}"error"in a&&c.text(a.error);return c},capital:function(a){return a.charAt(0).toUpperCase()+
|
||||
a.substring(1)},addUnit:function(a,c){var d=$("<span>").html(a);d.append($("<span>").addClass("unit").html(c));return d[0].innerHTML},bytes:function(a,c){var d="bytes KiB MiB GiB TiB PiB".split(" ");if(0==a)unit=d[0];else{var b=Math.floor(Math.log(Math.abs(a))/Math.log(1024));0>b?unit=d[0]:(a/=Math.pow(1024,b),unit=d[b])}return UI.format.addUnit(UI.format.number(a),unit+(c?"/s":""))}},navto:function(a,c){var d=location.hash,b=d.split("@");b[0]=[mist.user.name,mist.user.host].join("&");b[1]=[a,c].join("&");
|
||||
"undefined"!=typeof screenlog&&screenlog.navto(b[1]);location.hash=b.join("@");location.hash==d&&$(window).trigger("hashchange")},showTab:function(a,c){var d=UI.elements.main;if(mist.user.loggedin){if(!("ui_settings"in mist.data)){d.html("Loading..");mist.send(function(){UI.showTab(a,c)},{ui_settings:!0});return}mist.data.config.serverid&&(document.title=mist.data.config.serverid+" - MistServer MI")}var b=UI.elements.menu.removeClass("hide").find('.plain:contains("'+a+'")').closest(".button");0<b.length&&
|
||||
(UI.elements.menu.find(".button.active").removeClass("active"),b.addClass("active"));MistVideoObject&&MistVideoObject.reference&&MistVideoObject.reference.unload();UI.interval.clear();d.html($("<h2>").text(a));switch(a){case "Login":if(mist.user.loggedin){UI.navto("Overview");return}document.title="MistServer MI";UI.elements.menu.addClass("hide");UI.elements.connection.status.text("Disconnected").removeClass("green").addClass("red");d.append(UI.buildUI([{type:"help",help:"Please provide your account details.<br>You were asked to set these when MistController was started for the first time. If you did not yet set any account details, log in with your desired credentials to create a new account."},
|
||||
{label:"Host",help:"Url location of the MistServer API. Generally located at http://MistServerIP:4242/api","default":"http://localhost:4242/api",pointer:{main:mist.user,index:"host"}},{label:"Username",help:"Please enter your username here.",validate:["required"],pointer:{main:mist.user,index:"name"}},{label:"Password",type:"password",help:"Please enter your password here.",validate:["required"],pointer:{main:mist.user,index:"rawpassword"}},{type:"buttons",buttons:[{label:"Login",type:"save","function":function(){mist.user.password=
|
||||
MD5(mist.user.rawpassword);delete mist.user.rawpassword;mist.send(function(){UI.navto("Overview")})}}]}]));break;case "Create a new account":UI.elements.menu.addClass("hide");d.append($("<p>").text("No account has been created yet in the MistServer at ").append($("<i>").text(mist.user.host)).append("."));d.append(UI.buildUI([{type:"buttons",buttons:[{label:"Select other host",type:"cancel",css:{"float":"left"},"function":function(){UI.navto("Login")}}]},{type:"custom",custom:$("<br>")},{label:"Desired username",
|
||||
type:"str",validate:["required"],help:"Enter your desired username. In the future, you will need this to access the Management Interface.",pointer:{main:mist.user,index:"name"}},{label:"Desired password",type:"password",validate:["required",function(a,b){$(".match_password").not($(b)).trigger("change");return false}],help:"Enter your desired password. In the future, you will need this to access the Management Interface.",pointer:{main:mist.user,index:"rawpassword"},classes:["match_password"]},{label:"Repeat password",
|
||||
type:"password",validate:["required",function(a,b){return a!=$(".match_password").not($(b)).val()?{msg:'The fields "Desired password" and "Repeat password" do not match.',classes:["red"]}:false}],help:"Repeat your desired password.",classes:["match_password"]},{type:"buttons",buttons:[{type:"save",label:"Create new account","function":function(){mist.send(function(){UI.navto("Account created")},{authorize:{new_username:mist.user.name,new_password:mist.user.rawpassword}});mist.user.password=MD5(mist.user.rawpassword);
|
||||
delete mist.user.rawpassword}}]}]));break;case "Account created":UI.elements.menu.addClass("hide");d.append($("<p>").text("Your account has been created succesfully.")).append(UI.buildUI([{type:"text",text:"Would you like to enable all (currently) available protocols with their default settings?"},{type:"buttons",buttons:[{label:"Enable protocols",type:"save","function":function(){if(mist.data.config.protocols)d.append("Unable to enable all protocols as protocol settings already exist.<br>");else{d.append("Retrieving available protocols..<br>");
|
||||
mist.send(function(a){var b=[],c;for(c in a.capabilities.connectors)if(a.capabilities.connectors[c].required)d.append('Could not enable protocol "'+c+'" because it has required settings.<br>');else{b.push({connector:c});d.append('Enabled protocol "'+c+'".<br>')}d.append("Saving protocol settings..<br>");mist.send(function(){d.append("Protocols enabled. Redirecting..");setTimeout(function(){UI.navto("Overview")},5E3)},{config:{protocols:b}})},{capabilities:true})}}},{label:"Skip",type:"cancel","function":function(){UI.navto("Overview")}}]}]));
|
||||
break;case "Overview":if("undefined"==typeof mist.data.bandwidth){mist.send(function(){UI.navto(a)},{bandwidth:!0});d.append("Loading..");return}var i=$("<span>").text("Loading.."),m=$("<span>"),h=$("<span>").addClass("logs"),f=$("<span>"),r=$("<span>"),j=$("<span>").text("Unknown"),l=$("<span>"),u=$("<span>"),g={serverid:mist.data.config.serverid,debug:mist.data.config.debug,accesslog:mist.data.config.accesslog,prometheus:mist.data.config.prometheus},e={};"bandwidth"in mist.data&&(e=mist.data.bandwidth,
|
||||
null==e&&(e={}),e.limit||(e.limit=""));var k=$("<select>").html($("<option>").val(1).text("bytes/s")).append($("<option>").val(1024).text("KiB/s")).append($("<option>").val(1048576).text("MiB/s")).append($("<option>").val(1073741824).text("GiB/s")),b=parseURL(mist.user.host),b=b.protocol+b.host+b.port;d.append(UI.buildUI([{type:"help",help:"You can find most basic information about your MistServer here.<br>You can also set the debug level and force a save to the config.json file that MistServer uses to save your settings. "},
|
||||
type:"str",validate:["required"],help:"Enter your desired username. In the future, you will need this to access the Management Interface.",pointer:{main:mist.user,index:"name"}},{label:"Desired password",type:"password",validate:["required",function(a,b){$(".match_password.field").not($(b)).trigger("change");return false}],help:"Enter your desired password. In the future, you will need this to access the Management Interface.",pointer:{main:mist.user,index:"rawpassword"},classes:["match_password"]},
|
||||
{label:"Repeat password",type:"password",validate:["required",function(a,b){return a!=$(".match_password.field").not($(b)).val()?{msg:'The fields "Desired password" and "Repeat password" do not match.',classes:["red"]}:false}],help:"Repeat your desired password.",classes:["match_password"]},{type:"buttons",buttons:[{type:"save",label:"Create new account","function":function(){mist.send(function(){UI.navto("Account created")},{authorize:{new_username:mist.user.name,new_password:mist.user.rawpassword}});
|
||||
mist.user.password=MD5(mist.user.rawpassword);delete mist.user.rawpassword}}]}]));break;case "Account created":UI.elements.menu.addClass("hide");d.append($("<p>").text("Your account has been created succesfully.")).append(UI.buildUI([{type:"text",text:"Would you like to enable all (currently) available protocols with their default settings?"},{type:"buttons",buttons:[{label:"Enable protocols",type:"save","function":function(){if(mist.data.config.protocols)d.append("Unable to enable all protocols as protocol settings already exist.<br>");
|
||||
else{d.append("Retrieving available protocols..<br>");mist.send(function(a){var b=[],c;for(c in a.capabilities.connectors)if(a.capabilities.connectors[c].required)d.append('Could not enable protocol "'+c+'" because it has required settings.<br>');else{b.push({connector:c});d.append('Enabled protocol "'+c+'".<br>')}d.append("Saving protocol settings..<br>");mist.send(function(){d.append("Protocols enabled. Redirecting..");setTimeout(function(){UI.navto("Overview")},5E3)},{config:{protocols:b}})},{capabilities:true})}}},
|
||||
{label:"Skip",type:"cancel","function":function(){UI.navto("Overview")}}]}]));break;case "Overview":if("undefined"==typeof mist.data.bandwidth){mist.send(function(){UI.navto(a)},{bandwidth:!0});d.append("Loading..");return}var i=$("<span>").text("Loading.."),m=$("<span>"),h=$("<span>").addClass("logs"),f=$("<span>"),r=$("<span>"),j=$("<span>").text("Unknown"),l=$("<span>"),u=$("<span>"),g={serverid:mist.data.config.serverid,debug:mist.data.config.debug,accesslog:mist.data.config.accesslog,prometheus:mist.data.config.prometheus},
|
||||
e={};"bandwidth"in mist.data&&(e=mist.data.bandwidth,null==e&&(e={}),e.limit||(e.limit=""));var k=$("<select>").html($("<option>").val(1).text("bytes/s")).append($("<option>").val(1024).text("KiB/s")).append($("<option>").val(1048576).text("MiB/s")).append($("<option>").val(1073741824).text("GiB/s")),b=parseURL(mist.user.host),b=b.protocol+b.host+b.port;d.append(UI.buildUI([{type:"help",help:"You can find most basic information about your MistServer here.<br>You can also set the debug level and force a save to the config.json file that MistServer uses to save your settings. "},
|
||||
{type:"span",label:"Version",pointer:{main:mist.data.config,index:"version"}},{type:"span",label:"Version check",value:i,LTSonly:!0},{type:"span",label:"Server time",value:r},{type:"span",label:"Licensed to",value:"license"in mist.data.config?mist.data.config.license.user:"",LTSonly:!0},{type:"span",label:"Active products",value:j,LTSonly:!0},{type:"span",label:"Configured streams",value:mist.data.streams?Object.keys(mist.data.streams).length:0},{type:"span",label:"Active streams",value:m},{type:"span",
|
||||
label:"Current connections",value:f},{type:"span",label:"Enabled protocols",value:l},{type:"span",label:"Disabled protocols",value:u},{type:"span",label:"Recent problems",value:h},$("<br>"),{type:"str",label:"Human readable name",pointer:{main:g,index:"serverid"},help:"You can name your MistServer here for personal use. You'll still need to set host name within your network yourself."},{type:"debug",label:"Debug level",pointer:{main:g,index:"debug"},help:"You can set the amount of debug information MistServer saves in the log. A full reboot of MistServer is required before some components of MistServer can post debug information."},
|
||||
{type:"selectinput",label:"Access log",selectinput:[["","Do not track"],["LOG","Log to MistServer log"],[{type:"str",label:"Path",LTSonly:!0},"Log to file"]],pointer:{main:g,index:"accesslog"},help:"Enable access logs.",LTSonly:!0},{type:"selectinput",label:"Prometheus stats output",selectinput:[["","Disabled"],[{type:"str",label:"Passphrase",LTSonly:!0},"Enabled"]],pointer:{main:g,index:"prometheus"},help:"Make stats available in Prometheus format. These can be accessed via "+b+"/PASSPHRASE or "+
|
||||
|
@ -114,8 +116,8 @@ d.append(h);h.stupidtable();var m=function(){var a=[],b;for(b in mist.data.activ
|
|||
"undefined"){var w=mist.data.totals[d].all_protocols.clients,e=0;if(w.length){for(a in w)e=e+w[a][1];e=Math.round(e/w.length)}}f.html(UI.format.number(e));if(e==0&&g.online==1)g.online=2;e=$("<td>").css("text-align","right").css("white-space","nowrap");(!("ischild"in g)||!g.ischild)&&e.html($("<button>").text("Settings").click(function(){UI.navto("Edit",$(this).closest("tr").data("index"))})).append($("<button>").text("Delete").click(function(){var a=$(this).closest("tr").data("index");if(confirm('Are you sure you want to delete the stream "'+
|
||||
a+'"?')){delete mist.data.streams[a];var b={};mist.data.LTS?b.deletestream=[a]:b.streams=mist.data.streams;mist.send(function(){UI.navto("Streams")},b)}}));w=$("<span>").text(g.name);g.ischild&&w.css("padding-left","1em");var h=UI.format.status(g),i=$("<button>").text("Preview").click(function(){UI.navto("Preview",$(this).closest("tr").data("index"))}),ja=$("<button>").text("Embed").click(function(){UI.navto("Embed",$(this).closest("tr").data("index"))});if("filesfound"in z[d]||g.online<0){h.html("");
|
||||
i="";f.html("");ja=""}o.append($("<tr>").data("index",d).html($("<td>").html(w).attr("title",g.name=="..."?"The results were truncated":g.name).addClass("overflow_ellipsis")).append($("<td>").text(g.source).attr("title",g.source).addClass("description").addClass("overflow_ellipsis").css("max-width","20em")).append($("<td>").data("sort-value",g.online).html(h)).append(f).append($("<td>").css("white-space","nowrap").html(i).append(ja)).append(e));a++}},{totals:a,active_streams:true})};if(mist.data.LTS){var p=
|
||||
0,q=0;for(e in mist.data.streams){h=mist.data.capabilities.inputs.Folder||mist.data.capabilities.inputs["Folder.exe"];if(!h)break;if(mist.inputMatch(h.source_match,mist.data.streams[e].source)){z[e].source=z[e].source+"*";z[e].filesfound=null;mist.send(function(a,b){var c=b.stream,d=0,g;a:for(g in a.browse.files){var f;for(f in mist.data.capabilities.inputs)if(!(f.indexOf("Buffer")>=0||f.indexOf("Buffer.exe")>=0||f.indexOf("Folder")>=0||f.indexOf("Folder.exe")>=0)&&mist.inputMatch(mist.data.capabilities.inputs[f].source_match,
|
||||
"/"+a.browse.files[g])){var e=c+"+"+a.browse.files[g];z[e]=U(e,mist.data.streams[c]);z[e].source=mist.data.streams[c].source+a.browse.files[g];d++;if(d>=500){z[c+"+zzzzzzzzz"]={ischild:true,name:"...",online:-1};break a}}}"files"in a.browse&&a.browse.files.length?z[c].filesfound=true:mist.data.streams[c].filesfound=false;q++;if(p==q){mist.send(function(){m()},{active_streams:true});UI.interval.set(function(){m()},5E3)}},{browse:mist.data.streams[e].source},{stream:e});p++}}if(p==0){mist.send(function(){m()},
|
||||
0,r=0;for(e in mist.data.streams){h=mist.data.capabilities.inputs.Folder||mist.data.capabilities.inputs["Folder.exe"];if(!h)break;if(mist.inputMatch(h.source_match,mist.data.streams[e].source)){z[e].source=z[e].source+"*";z[e].filesfound=null;mist.send(function(a,b){var c=b.stream,d=0,g;a:for(g in a.browse.files){var f;for(f in mist.data.capabilities.inputs)if(!(f.indexOf("Buffer")>=0||f.indexOf("Buffer.exe")>=0||f.indexOf("Folder")>=0||f.indexOf("Folder.exe")>=0)&&mist.inputMatch(mist.data.capabilities.inputs[f].source_match,
|
||||
"/"+a.browse.files[g])){var e=c+"+"+a.browse.files[g];z[e]=U(e,mist.data.streams[c]);z[e].source=mist.data.streams[c].source+a.browse.files[g];d++;if(d>=500){z[c+"+zzzzzzzzz"]={ischild:true,name:"...",online:-1};break a}}}"files"in a.browse&&a.browse.files.length?z[c].filesfound=true:mist.data.streams[c].filesfound=false;r++;if(p==r){mist.send(function(){m()},{active_streams:true});UI.interval.set(function(){m()},5E3)}},{browse:mist.data.streams[e].source},{stream:e});p++}}if(p==0){mist.send(function(){m()},
|
||||
{active_streams:true});UI.interval.set(function(){m()},5E3)}}else{mist.send(function(){m()},{active_streams:true});UI.interval.set(function(){m()},5E3)}}};if(mist.data.LTS){var W=0,ka=0,s={},la=[];for(g in mist.data.streams)if(mist.inputMatch((mist.data.capabilities.inputs.Folder||mist.data.capabilities.inputs["Folder.exe"]).source_match,mist.data.streams[g].source))la.push(g),mist.send(function(a,b){var d=b.stream,g=0,f;a:for(f in a.browse.files){var e;for(e in mist.data.capabilities.inputs)if(!(e.indexOf("Buffer")>=
|
||||
0||e.indexOf("Folder")>=0)&&mist.inputMatch(mist.data.capabilities.inputs[e].source_match,"/"+a.browse.files[f])){s[d+"+"+a.browse.files[f]]=true;g++;if(g>=500){s[d+"+zzzzzzzzz"]=true;break a}}}ka++;W==ka&&mist.send(function(){for(var a in mist.data.active_streams){var b=mist.data.active_streams[a].split("+");if(b.length>1&&b[0]in mist.data.streams){s[mist.data.active_streams[a]]=true;z[mist.data.active_streams[a]]=U(mist.data.active_streams[a],mist.data.streams[b[0]])}}s=Object.keys(s);s=s.concat(Object.keys(mist.data.streams));
|
||||
s.sort();V(c,s,la)},{active_streams:true})},{browse:mist.data.streams[g].source},{stream:g}),W++;0==W&&mist.send(function(){for(var a in mist.data.active_streams){var b=mist.data.active_streams[a].split("+");if(b.length>1&&b[0]in mist.data.streams){s[mist.data.active_streams[a]]=true;z[mist.data.active_streams[a]]=U(mist.data.active_streams[a],mist.data.streams[b[0]])}}s=Object.keys(s);mist.data.streams&&(s=s.concat(Object.keys(mist.data.streams)));s.sort();V(c,s)},{active_streams:!0})}else V(c,Object.keys(mist.data.streams));
|
||||
|
@ -158,10 +160,10 @@ $(this).getval()==1;switch($(this).getval()){case 0:q.controls=false;break;case
|
|||
$(this).getval();$(".embed_code").setval(x(q))},help:"If the video should restart when the end is reached."},{label:"Start muted",type:"checkbox",pointer:{main:q,index:"muted"},"function":function(){q.muted=$(this).getval();$(".embed_code").setval(x(q))},help:"If the video should restart when the end is reached."},{label:"Fill available space",type:"checkbox",pointer:{main:q,index:"fillSpace"},"function":function(){q.fillSpace=$(this).getval();$(".embed_code").setval(x(q))},help:"The video will fit the available space in its container, even if the video stream has a smaller resolution."},
|
||||
{label:"Poster",type:"str",pointer:{main:q,index:"poster"},"function":function(){q.poster=$(this).getval();$(".embed_code").setval(x(q))},help:"URL to an image that is displayed when the video is not playing."},{label:"Video URL addition",type:"str",pointer:{main:q,index:"urlappend"},help:"The embed script will append this string to the video url, useful for sending through params.",classes:["embed_code_forceprotocol"],"function":function(){q.urlappend=$(this).getval();$(".embed_code").setval(x(q))}},
|
||||
{label:"Preselect tracks",type:"DOMfield",DOMfield:L,help:"Pre-select these tracks."},{label:"Monitoring action",type:"select",select:[["","Ask the viewer what to do"],["nextCombo","Try the next source / player combination"]],pointer:{main:q,index:"monitor_action"},"function":function(){q.monitor_action=$(this).getval();$(".embed_code").setval(x(q))},help:"What the player should do when playback is poor."},$("<h3>").text("Protocol stream urls"),ba]));$.ajax({type:"GET",url:H+"json_"+C+".js",success:function(a){var b=
|
||||
[],c=O.find(".forceType"),d=O.find(".prioritize_type"),g;for(g in a.source){var e=a.source[g],f=UI.humanMime(e.type);b.push({label:f?f+" <span class=description>("+e.type+")</span>":UI.format.capital(e.type),type:"str",value:e.url,readonly:true,qrcode:true,clipboard:true});f=UI.humanMime(e.type);if(c.children('option[value="'+e.type+'"]').length==0){c.append($("<option>").text(f?f+" ("+e.type+")":UI.format.capital(e.type)).val(e.type));d.append($("<option>").text(f?f+" ("+e.type+")":UI.format.capital(e.type)).val(e.type))}}c.val(q.forceType);
|
||||
d.val(q.prioritize_type);ba.html(UI.buildUI(b));L.html("");b={};for(g in a.meta.tracks){c=a.meta.tracks[g];if(c.codec=="subtitle")c.type="subtitle";if(!(c.type!="audio"&&c.type!="video"&&c.type!="subtitle")){c.type in b||(b[c.type]=c.type=="subtitle"?[]:[["","Autoselect "+c.type]]);b[c.type].push([c.trackid,UI.format.capital(c.type)+" track "+(b[c.type].length+(c.type=="subtitle"?1:0))])}}if(Object.keys(b).length){L.closest("label").show();var a=["audio","video","subtitle"],h;for(h in a){g=a[h];if(b[g].length){c=
|
||||
$("<select>").attr("data-type",g).css("flex-grow","1").change(function(){$(this).val()==""?delete q.setTracks[$(this).attr("data-type")]:q.setTracks[$(this).attr("data-type")]=$(this).val();$(".embed_code").setval(x(q))});L.append(c);g=="subtitle"?b[g].unshift(["","No "+g]):b[g].push([-1,"No "+g]);for(var i in b[g])c.append($("<option>").val(b[g][i][0]).text(b[g][i][1]));if(g in q.setTracks){c.val(q.setTracks[g]);if(c.val()==null){c.val("");delete q.setTracks[g];$(".embed_code").setval(x(q))}}}}}else L.closest("label").hide();
|
||||
P=true},error:function(){ba.html("Error while retrieving stream info.");L.closest("label").hide();q.setTracks={}}});o=document.createElement("script");o.src=K+"player.js";document.head.appendChild(o);o.onload=function(){var a=O.find(".forcePlayer"),b;for(b in mistplayers)a.append($("<option>").text(mistplayers[b].name).val(b));document.head.removeChild(this)};o.onerror=function(){document.head.removeChild(this)};break;case "Push":var D=$("<div>").text("Loading..");d.append(D);mist.send(function(a){function b(a){setTimeout(function(){mist.send(function(c){var d=
|
||||
[],c=O.find(".field.forceType"),d=O.find(".field.prioritize_type"),g;for(g in a.source){var e=a.source[g],f=UI.humanMime(e.type);b.push({label:f?f+" <span class=description>("+e.type+")</span>":UI.format.capital(e.type),type:"str",value:e.url,readonly:true,qrcode:true,clipboard:true});f=UI.humanMime(e.type);if(c.children('option[value="'+e.type+'"]').length==0){c.append($("<option>").text(f?f+" ("+e.type+")":UI.format.capital(e.type)).val(e.type));d.append($("<option>").text(f?f+" ("+e.type+")":UI.format.capital(e.type)).val(e.type))}}c.val(q.forceType);
|
||||
d.val(q.prioritize_type);ba.html(UI.buildUI(b));L.html("");b={};for(g in a.meta.tracks){c=a.meta.tracks[g];if(c.codec=="subtitle")c.type="subtitle";if(!(c.type!="audio"&&c.type!="video"&&c.type!="subtitle")){c.type in b||(b[c.type]=c.type=="subtitle"?[]:[["","Autoselect "+c.type]]);b[c.type].push([c.trackid,UI.format.capital(c.type)+" track "+(b[c.type].length+(c.type=="subtitle"?1:0))])}}if(Object.keys(b).length){L.closest("label").show();var a=["audio","video","subtitle"],h;for(h in a){g=a[h];if(b[g]&&
|
||||
b[g].length){c=$("<select>").attr("data-type",g).css("flex-grow","1").change(function(){$(this).val()==""?delete q.setTracks[$(this).attr("data-type")]:q.setTracks[$(this).attr("data-type")]=$(this).val();$(".embed_code").setval(x(q))});L.append(c);g=="subtitle"?b[g].unshift(["","No "+g]):b[g].push([-1,"No "+g]);for(var i in b[g])c.append($("<option>").val(b[g][i][0]).text(b[g][i][1]));if(g in q.setTracks){c.val(q.setTracks[g]);if(c.val()==null){c.val("");delete q.setTracks[g];$(".embed_code").setval(x(q))}}}}}else L.closest("label").hide();
|
||||
P=true},error:function(){ba.html("Error while retrieving stream info.");L.closest("label").hide();q.setTracks={}}});o=document.createElement("script");o.src=K+"player.js";document.head.appendChild(o);o.onload=function(){var a=O.find(".field.forcePlayer"),b;for(b in mistplayers)a.append($("<option>").text(mistplayers[b].name).val(b));document.head.removeChild(this)};o.onerror=function(){document.head.removeChild(this)};break;case "Push":var D=$("<div>").text("Loading..");d.append(D);mist.send(function(a){function b(a){setTimeout(function(){mist.send(function(c){var d=
|
||||
false;if("push_list"in c&&c.push_list&&c.push_list.length){var d=true,e;for(e in c.push_list)if(a.indexOf(c.push_list[e][0])>-1){d=false;break}}else d=true;if(d)for(e in a)g.find("tr[data-pushid="+a[e]+"]").remove();else b()},{push_list:1})},1E3)}function c(e,f){var h=$("<span>");if(f=="Automatic"&&e.length>=4){h.append($("<span>").text(e[2]));e[3]&&h.append($("<span>").text(", schedule on "+(new Date(e[3]*1E3)).toLocaleString()));e.length>=5&&e[4]&&h.append($("<span>").text(", complete on "+(new Date(e[4]*
|
||||
1E3)).toLocaleString()))}else e.length>=4&&e[2]!=e[3]?h.append($("<span>").text(e[2])).append($("<span>").html("»").addClass("unit").css("margin","0 0.5em")).append($("<span>").text(e[3])):h.append($("<span>").text(e[2]));var i=$("<td>").append($("<button>").text(f=="Automatic"?"Remove":"Stop").click(function(){if(confirm("Are you sure you want to "+$(this).text().toLowerCase()+" this push?\n"+e[1]+" to "+e[2])){var a=$(this).closest("tr");a.html($("<td colspan=99>").html($("<span>").addClass("red").text(f==
|
||||
"Automatic"?"Removing..":"Stopping..")));if(f=="Automatic"){var c=e.slice(1);mist.send(function(){a.remove()},{push_auto_remove:[c]})}else mist.send(function(){b([e[0]])},{push_stop:[e[0]]})}}));if(f=="Automatic"){i.prepend($("<button>").text("Edit").click(function(){UI.navto("Start Push","auto_"+($(this).closest("tr").index()-1))}));i.append($("<button>").text("Stop pushes").click(function(){if(confirm('Are you sure you want to stop all pushes matching \n"'+e[1]+" to "+e[2]+'"?'+(d.wait!=0?"\n\nRetrying is enabled. You'll probably want to set that to 0.":
|
||||
|
@ -221,8 +223,9 @@ a[d].replace(/[^\w\s]/g,"\\$&"),b=b.replace(/\\\*/g,".*");if(RegExp("^(?:[a-zA-Z
|
|||
d.select[f][1];break}}if("help"in d)e.help=d.help;if("unit"in d)e.unit=d.unit;if("placeholder"in d)e.placeholder=d.placeholder;if("type"in d)switch(d.type){case "int":e.type="int";if("max"in d)e.max=d.max;if("min"in d)e.min=d.min;break;case "uint":e.type="int";e.min=0;if("max"in d)e.max=d.max;if("min"in d)e.min=Math.max(e.min,d.min);break;case "debug":e.type="debug";break;case "radioselect":e.type="radioselect";e.radioselect=d.radioselect;break;case "select":e.type="select";e.select=d.select.slice(0);
|
||||
e.validate.indexOf("required")>=0&&e.select.unshift(["","placeholder"in e?"Default ("+e.placeholder+")":""]);break;case "sublist":e.type="sublist";e.saveas={};e.itemLabel=d.itemLabel;e.sublist=mist.convertBuildOptions(d,e.saveas);break;default:e.type="str"}else e.type="checkbox";"influences"in d&&(e["function"]=function(){var a=$(this).closest(".UIelement"),c=a.find("style");if(c.length)c=c[0];else{c=$("<style>").addClass("dependencies")[0];a.append(c)}c.innerHTML=".UIelement[data-dependent-"+b+"]:not([data-dependent-"+
|
||||
b+'~="'+$(this).getval()+'"]) { display: none; }\n';$(c).data("content",c.innerHTML);$("style.dependencies.hidden").each(function(){$(this).html($(this).data("content")).removeClass("hidden")});$(".UIelement:not(:visible) style.dependencies:not(.hidden)").each(function(){$(this).addClass("hidden");$(this).html("")})});if("dependent"in d)e.dependent=d.dependent;if("value"in d)e.value=d.value;if("validate"in d)e.validate=e.validate.concat(d.validate);return e}var b=[],i=["required","optional"];"desc"in
|
||||
a&&b.push({type:"help",help:a.desc});if("sort"in a){var m=[],h;for(h in i)if(a[i[h]])for(var f in a[i[h]]){var r=a[i[h]][f];if(Array.isArray(r))for(var j in r){r[j].validate=i[h];r[j].id=f;m.push(r[j])}else{r.validate=i[h];r.id=f;m.push(r)}}m.sort(function(b,c){return(""+b[a.sort]).localeCompare(c[a.sort])});for(f in m){r=m[f];b.push(d(r.validate,r.id,r))}}else for(h in i)if(a[i[h]]){b.push($("<h4>").text(UI.format.capital(i[h])+" parameters"));for(f in a[i[h]]){r=a[i[h]][f];if(Array.isArray(r))for(j in r)b.push(d(h,
|
||||
f,r[j]));else b.push(d(h,f,r))}}return b},stored:{get:function(){return mist.data.ui_settings||{}},set:function(a,c){var d=this.get();d[a]=c;mist.send(function(){},{ui_settings:d})},del:function(a){delete mist.data.ui_settings[a];mist.send(function(){},{ui_settings:mist.data.ui_settings})}}};function log(){try{UI.debug&&[].push.call(arguments,Error().stack);[].unshift.call(arguments,"["+UI.format.time((new Date).getTime()/1E3)+"]");console.log.apply(console,arguments)}catch(a){}}
|
||||
a&&b.push({type:"help",help:a.desc});if("sort"in a){var m=[],h;for(h in i)if(a[i[h]])for(var f in a[i[h]]){var r=a[i[h]][f];if(Array.isArray(r))for(var j in r){if(!("validate"in r[j]))r[j].validate=[];r[j].validate=i[h];r[j].id=f;m.push(r[j])}else{if(!("validate"in r))r.validate=[];r.validate.push(i[h]);r.id=f;m.push(r)}}m.sort(function(b,c){return(""+b[a.sort]).localeCompare(c[a.sort])});for(f in m){r=m[f];b.push(d(r.validate,r.id,r))}}else for(h in i)if(a[i[h]]){b.push($("<h4>").text(UI.format.capital(i[h])+
|
||||
" parameters"));for(f in a[i[h]]){r=a[i[h]][f];if(Array.isArray(r))for(j in r)b.push(d(h,f,r[j]));else b.push(d(h,f,r))}}return b},stored:{get:function(){return mist.data.ui_settings||{}},set:function(a,c){var d=this.get();d[a]=c;mist.send(function(){},{ui_settings:d})},del:function(a){delete mist.data.ui_settings[a];mist.send(function(){},{ui_settings:mist.data.ui_settings})}}};
|
||||
function log(){try{UI.debug&&[].push.call(arguments,Error().stack);[].unshift.call(arguments,"["+UI.format.time((new Date).getTime()/1E3)+"]");console.log.apply(console,arguments)}catch(a){}}
|
||||
$.fn.getval=function(){var a=$(this).data("opts"),c=$(this).val();if(a&&"type"in a)switch(a.type){case "span":c=$(this).html();break;case "checkbox":c=$(this).prop("checked");break;case "radioselect":a=$(this).find("label > input[type=radio]:checked").parent();if(a.length){c=[];c.push(a.children("input[type=radio]").val());a=a.children("select");a.length&&c.push(a.val())}else c="";break;case "checklist":c=[];$(this).find(".checklist input[type=checkbox]:checked").each(function(){c.push($(this).attr("name"))});
|
||||
break;case "unix":c!=""&&(c=Math.round(new Date($(this).val())/1E3));break;case "selectinput":c=$(this).children("select").first().val();c=="CUSTOM"&&(c=$(this).children("label").first().find(".field_container").children().first().getval());break;case "inputlist":c=[];$(this).children().each(function(){$(this).val()!=""&&c.push($(this).val())});break;case "sublist":c=$(this).data("savelist")}return c};
|
||||
$.fn.setval=function(a){var c=$(this).data("opts");$(this).val(a);if(c&&"type"in c)switch(c.type){case "span":$(this).html(a);break;case "checkbox":$(this).prop("checked",a);break;case "geolimited":case "hostlimited":c=$(this).closest(".field_container").data("subUI");if(typeof a=="undefined"||a.length==0)a="-";c.blackwhite.val(a.charAt(0));var a=a.substr(1).split(" "),d;for(d in a)c.values.append(c.prototype.clone(true).val(a[d]));c.blackwhite.trigger("change");break;case "radioselect":if(typeof a==
|
||||
|
|
99
lsp/mist.js
99
lsp/mist.js
|
@ -178,7 +178,10 @@ var UI = {
|
|||
var human = false;
|
||||
switch (type) {
|
||||
case 'html5/application/vnd.apple.mpegurl':
|
||||
human = 'HLS';
|
||||
human = 'HLS (TS)';
|
||||
break;
|
||||
case "html5/application/vnd.apple.mpegurl;version=7":
|
||||
human = "HLS (CMAF)";
|
||||
break;
|
||||
case 'html5/video/webm':
|
||||
human = 'WebM';
|
||||
|
@ -208,8 +211,9 @@ var UI = {
|
|||
case 'html5/video/mpeg':
|
||||
human = 'TS';
|
||||
break;
|
||||
case "html5/application/vnd.ms-sstr+xml":
|
||||
case 'html5/application/vnd.ms-ss':
|
||||
human = 'Smooth';
|
||||
human = 'Smooth Streaming';
|
||||
break;
|
||||
case 'html5/text/vtt':
|
||||
human = 'VTT Subtitles';
|
||||
|
@ -439,11 +443,14 @@ var UI = {
|
|||
break;
|
||||
case 'save':
|
||||
$b.addClass('save').click(function(e){
|
||||
var fn = $(this).data('opts')['preSave'];
|
||||
if (fn) { fn.call(this); }
|
||||
|
||||
var $ic = $(this).closest('.input_container');
|
||||
|
||||
//skip any hidden fields
|
||||
|
||||
//validate$()
|
||||
//validate
|
||||
var error = false;
|
||||
$ic.find('.hasValidate:visible, input[type="hidden"].hasValidate').each(function(){
|
||||
var vf = $(this).data('validate');
|
||||
|
@ -452,6 +459,8 @@ var UI = {
|
|||
return false; //break loop
|
||||
}
|
||||
});
|
||||
var fn = $(this).data('opts')['failedValidate'];
|
||||
if (fn) { fn.call(this); }
|
||||
if (error) { return; } //validation failed
|
||||
|
||||
//for all inputs
|
||||
|
@ -497,6 +506,11 @@ var UI = {
|
|||
$e.append(
|
||||
$('<span>').addClass('label').html(('label' in e ? e.label+':' : ''))
|
||||
);
|
||||
if ('classes' in e) {
|
||||
for (var k in e.classes) {
|
||||
$e.addClass(e.classes[k]);
|
||||
}
|
||||
}
|
||||
|
||||
//field
|
||||
var $fc = $('<span>').addClass('field_container');
|
||||
|
@ -739,6 +753,16 @@ var UI = {
|
|||
sublist
|
||||
).concat([
|
||||
{
|
||||
label: "Save first",
|
||||
type: "str",
|
||||
classes: ["onlyshowhelp"],
|
||||
validate: [function(){
|
||||
return {
|
||||
msg: "Did you want to save this "+e.itemLabel+"?",
|
||||
classes: ["red"]
|
||||
};
|
||||
}]
|
||||
},{
|
||||
type: "buttons",
|
||||
buttons: [{
|
||||
label: "Cancel",
|
||||
|
@ -751,6 +775,12 @@ var UI = {
|
|||
},{
|
||||
label: "Save "+e.itemLabel,
|
||||
type: "save",
|
||||
preSave: function(){
|
||||
$(this).closest('.input_container').find(".onlyshowhelp").closest("label").hide();
|
||||
},
|
||||
failedValidate: function(){
|
||||
$(this).closest('.input_container').find(".onlyshowhelp").closest("label").show();
|
||||
},
|
||||
"function": function(){
|
||||
var savelist = $field.getval();
|
||||
var save = Object.assign({},e.saveas);
|
||||
|
@ -1240,6 +1270,47 @@ var UI = {
|
|||
};
|
||||
break;
|
||||
}
|
||||
case 'streamname_with_wildcard_and_variables': {
|
||||
f = function(val,me) {
|
||||
if (val == "") { return; }
|
||||
|
||||
streampart = val.split("+");
|
||||
var wildpart = streampart.slice(1).join("+");
|
||||
streampart = streampart[0];
|
||||
|
||||
//validate streampart
|
||||
if (!isNaN(streampart.charAt(0))) {
|
||||
return {
|
||||
msg: 'The first character may not be a number.',
|
||||
classes: ['red']
|
||||
};
|
||||
}
|
||||
if (streampart.toLowerCase() != streampart) {
|
||||
return {
|
||||
msg: 'Uppercase letters are not allowed in a stream name.',
|
||||
classes: ['red']
|
||||
};
|
||||
}
|
||||
if (streampart.replace(/[^\da-z_$]/g,'') != streampart) {
|
||||
return {
|
||||
msg: 'Special characters (except for underscores) are not allowed in a stream name.',
|
||||
classes: ['red']
|
||||
};
|
||||
}
|
||||
|
||||
if (streampart != val) {
|
||||
//validate wildcard part
|
||||
//anything is allowed except / and nullbytes
|
||||
if (wildpart.replace(/[\00|\0|\/]/g,'') != wildpart) {
|
||||
return {
|
||||
msg: 'Slashes or null bytes are not allowed in wildcards.',
|
||||
classes: ['red']
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
break;
|
||||
}
|
||||
case 'track_selector': {
|
||||
//something like "audio=1&video=eng"
|
||||
//keep at default for now..
|
||||
|
@ -1252,7 +1323,7 @@ var UI = {
|
|||
fs.push(f);
|
||||
}
|
||||
$field.data('validate_functions',fs).data('help_container',$ihc).data('validate',function(me,focusonerror){
|
||||
if (!$(me).is(":visible")) { return; }
|
||||
if ((!$(me).is(":visible")) && (!$(me).is("input[type=\"hidden\"]"))) { return; }
|
||||
|
||||
var val = $(me).getval();
|
||||
var fs = $(me).data('validate_functions');
|
||||
|
@ -2167,7 +2238,7 @@ var UI = {
|
|||
label: 'Desired password',
|
||||
type: 'password',
|
||||
validate: ['required',function(val,me){
|
||||
$('.match_password').not($(me)).trigger('change');
|
||||
$('.match_password.field').not($(me)).trigger('change');
|
||||
return false;
|
||||
}],
|
||||
help: 'Enter your desired password. In the future, you will need this to access the Management Interface.',
|
||||
|
@ -2180,7 +2251,7 @@ var UI = {
|
|||
label: 'Repeat password',
|
||||
type: 'password',
|
||||
validate: ['required',function(val,me){
|
||||
if (val != $('.match_password').not($(me)).val()) {
|
||||
if (val != $('.match_password.field').not($(me)).val()) {
|
||||
return {
|
||||
msg:'The fields "Desired password" and "Repeat password" do not match.',
|
||||
classes: ['red']
|
||||
|
@ -4635,8 +4706,8 @@ var UI = {
|
|||
success: function(d) {
|
||||
|
||||
var build = [];
|
||||
var $s_forceType = $embedlinks.find('.forceType');
|
||||
var $s_prioritizeType = $embedlinks.find('.prioritize_type');
|
||||
var $s_forceType = $embedlinks.find('.field.forceType');
|
||||
var $s_prioritizeType = $embedlinks.find('.field.prioritize_type');
|
||||
for (var i in d.source) {
|
||||
var source = d.source[i];
|
||||
var human = UI.humanMime(source.type);
|
||||
|
@ -4687,7 +4758,7 @@ var UI = {
|
|||
var trackarray = ["audio","video","subtitle"];
|
||||
for (var n in trackarray) {
|
||||
var i = trackarray[n];
|
||||
if (!tracks[i].length) { continue; }
|
||||
if (!tracks[i] || !tracks[i].length) { continue; }
|
||||
var $select = $('<select>').attr('data-type',i).css('flex-grow','1').change(function(){
|
||||
if ($(this).val() == '') {
|
||||
delete embedoptions.setTracks[$(this).attr('data-type')];
|
||||
|
@ -4736,7 +4807,7 @@ var UI = {
|
|||
script.src = embedbase+'player.js';
|
||||
document.head.appendChild(script);
|
||||
script.onload = function(){
|
||||
var $s_forcePlayer = $embedlinks.find('.forcePlayer');
|
||||
var $s_forcePlayer = $embedlinks.find('.field.forcePlayer');
|
||||
for (var i in mistplayers) {
|
||||
$s_forcePlayer.append(
|
||||
$('<option>').text(mistplayers[i].name).val(i)
|
||||
|
@ -6623,13 +6694,19 @@ var mist = {
|
|||
var ele = input[type[j]][i];
|
||||
if (Array.isArray(ele)) {
|
||||
for (var m in ele) {
|
||||
if (!("validate" in ele[m])) {
|
||||
ele[m].validate = [];
|
||||
}
|
||||
ele[m].validate = type[j];
|
||||
ele[m].id = i;
|
||||
list.push(ele[m]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ele.validate = type[j];
|
||||
if (!("validate" in ele)) {
|
||||
ele.validate = [];
|
||||
}
|
||||
ele.validate.push(type[j]);
|
||||
ele.id = i;
|
||||
list.push(ele);
|
||||
}
|
||||
|
|
|
@ -612,4 +612,19 @@ namespace Mist {
|
|||
void OutHLS::sendTS(const char * tsData, unsigned int len) {
|
||||
H.Chunkify(tsData, len, myConn);
|
||||
}
|
||||
|
||||
void OutHLS::onFail(const std::string & msg, bool critical){
|
||||
if (H.url.find(".m3u") == std::string::npos){
|
||||
HTTPOutput::onFail(msg, critical);
|
||||
return;
|
||||
}
|
||||
H.Clean(); //make sure no parts of old requests are left in any buffers
|
||||
H.SetHeader("Server", "MistServer/" PACKAGE_VERSION);
|
||||
H.setCORSHeaders();
|
||||
H.SetHeader("Content-Type", "application/vnd.apple.mpegurl");
|
||||
H.SetHeader("Cache-Control", "no-cache");
|
||||
H.SetBody("#EXTM3U\r\n#EXT-X-ERROR: "+msg+"\r\n#EXT-X-ENDLIST\r\n");
|
||||
H.SendResponse("200", "OK", myConn);
|
||||
Output::onFail(msg, critical);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ namespace Mist {
|
|||
void sendNext();
|
||||
void onHTTP();
|
||||
bool isReadyForPlay();
|
||||
virtual void onFail(const std::string & msg, bool critical = false);
|
||||
protected:
|
||||
std::string h264init(const std::string & initData);
|
||||
std::string h265init(const std::string & initData);
|
||||
|
|
Loading…
Add table
Reference in a new issue