LSP:
- Forward min/maxlength for strings in convertBuildOptions - Input validation: added default html5 validation when available + bugfix for onchange validation TSSRT: added minlength and maxlength to passphrase setting
This commit is contained in:
parent
13845ca4fc
commit
8737392b51
3 changed files with 76 additions and 54 deletions
104
lsp/minified.js
104
lsp/minified.js
|
@ -1,5 +1,5 @@
|
|||
var MD5=function(a){function b(a,b){var c,h,d,e,g;d=a&2147483648;e=b&2147483648;c=a&1073741824;h=b&1073741824;g=(a&1073741823)+(b&1073741823);return c&h?g^2147483648^d^e:c|h?g&1073741824?g^3221225472^d^e:g^1073741824^d^e:g^d^e}function d(a,c,h,d,e,g,f){a=b(a,b(b(c&h|~c&d,e),f));return b(a<<g|a>>>32-g,c)}function c(a,c,h,d,e,g,f){a=b(a,b(b(c&d|h&~d,e),f));return b(a<<g|a>>>32-g,c)}function e(a,c,h,d,e,g,f){a=b(a,b(b(c^h^d,e),f));return b(a<<g|a>>>32-g,c)}function l(a,c,h,d,g,e,f){a=b(a,b(b(h^(c|~d),
|
||||
g),f));return b(a<<e|a>>>32-e,c)}function i(a){var b="",c="",h;for(h=0;3>=h;h++)c=a>>>8*h&255,c="0"+c.toString(16),b+=c.substr(c.length-2,2);return b}var f=[],m,n,j,q,g,h,k,o,f=a.replace(/\r\n/g,"\n"),a="";for(m=0;m<f.length;m++)n=f.charCodeAt(m),128>n?a+=String.fromCharCode(n):(127<n&&2048>n?a+=String.fromCharCode(n>>6|192):(a+=String.fromCharCode(n>>12|224),a+=String.fromCharCode(n>>6&63|128)),a+=String.fromCharCode(n&63|128));f=a;a=f.length;m=a+8;n=16*((m-m%64)/64+1);j=Array(n-1);for(g=q=0;g<a;)m=
|
||||
var MD5=function(a){function b(a,b){var c,h,d,e,g;d=a&2147483648;e=b&2147483648;c=a&1073741824;h=b&1073741824;g=(a&1073741823)+(b&1073741823);return c&h?g^2147483648^d^e:c|h?g&1073741824?g^3221225472^d^e:g^1073741824^d^e:g^d^e}function d(a,c,h,d,e,g,f){a=b(a,b(b(c&h|~c&d,e),f));return b(a<<g|a>>>32-g,c)}function c(a,c,h,d,e,g,f){a=b(a,b(b(c&d|h&~d,e),f));return b(a<<g|a>>>32-g,c)}function e(a,c,h,d,e,g,f){a=b(a,b(b(c^h^d,e),f));return b(a<<g|a>>>32-g,c)}function l(a,c,h,d,e,g,f){a=b(a,b(b(h^(c|~d),
|
||||
e),f));return b(a<<g|a>>>32-g,c)}function i(a){var b="",c="",h;for(h=0;3>=h;h++)c=a>>>8*h&255,c="0"+c.toString(16),b+=c.substr(c.length-2,2);return b}var f=[],m,n,j,q,g,h,k,o,f=a.replace(/\r\n/g,"\n"),a="";for(m=0;m<f.length;m++)n=f.charCodeAt(m),128>n?a+=String.fromCharCode(n):(127<n&&2048>n?a+=String.fromCharCode(n>>6|192):(a+=String.fromCharCode(n>>12|224),a+=String.fromCharCode(n>>6&63|128)),a+=String.fromCharCode(n&63|128));f=a;a=f.length;m=a+8;n=16*((m-m%64)/64+1);j=Array(n-1);for(g=q=0;g<a;)m=
|
||||
(g-g%4)/4,q=8*(g%4),j[m]|=f.charCodeAt(g)<<q,g++;m=(g-g%4)/4;j[m]|=128<<8*(g%4);j[n-2]=a<<3;j[n-1]=a>>>29;f=j;g=1732584193;h=4023233417;k=2562383102;o=271733878;for(a=0;a<f.length;a+=16)m=g,n=h,j=k,q=o,g=d(g,h,k,o,f[a+0],7,3614090360),o=d(o,g,h,k,f[a+1],12,3905402710),k=d(k,o,g,h,f[a+2],17,606105819),h=d(h,k,o,g,f[a+3],22,3250441966),g=d(g,h,k,o,f[a+4],7,4118548399),o=d(o,g,h,k,f[a+5],12,1200080426),k=d(k,o,g,h,f[a+6],17,2821735955),h=d(h,k,o,g,f[a+7],22,4249261313),g=d(g,h,k,o,f[a+8],7,1770035416),
|
||||
o=d(o,g,h,k,f[a+9],12,2336552879),k=d(k,o,g,h,f[a+10],17,4294925233),h=d(h,k,o,g,f[a+11],22,2304563134),g=d(g,h,k,o,f[a+12],7,1804603682),o=d(o,g,h,k,f[a+13],12,4254626195),k=d(k,o,g,h,f[a+14],17,2792965006),h=d(h,k,o,g,f[a+15],22,1236535329),g=c(g,h,k,o,f[a+1],5,4129170786),o=c(o,g,h,k,f[a+6],9,3225465664),k=c(k,o,g,h,f[a+11],14,643717713),h=c(h,k,o,g,f[a+0],20,3921069994),g=c(g,h,k,o,f[a+5],5,3593408605),o=c(o,g,h,k,f[a+10],9,38016083),k=c(k,o,g,h,f[a+15],14,3634488961),h=c(h,k,o,g,f[a+4],20,3889429448),
|
||||
g=c(g,h,k,o,f[a+9],5,568446438),o=c(o,g,h,k,f[a+14],9,3275163606),k=c(k,o,g,h,f[a+3],14,4107603335),h=c(h,k,o,g,f[a+8],20,1163531501),g=c(g,h,k,o,f[a+13],5,2850285829),o=c(o,g,h,k,f[a+2],9,4243563512),k=c(k,o,g,h,f[a+7],14,1735328473),h=c(h,k,o,g,f[a+12],20,2368359562),g=e(g,h,k,o,f[a+5],4,4294588738),o=e(o,g,h,k,f[a+8],11,2272392833),k=e(k,o,g,h,f[a+11],16,1839030562),h=e(h,k,o,g,f[a+14],23,4259657740),g=e(g,h,k,o,f[a+1],4,2763975236),o=e(o,g,h,k,f[a+4],11,1272893353),k=e(k,o,g,h,f[a+7],16,4139469664),
|
||||
|
@ -60,53 +60,53 @@ c.min);"max"in c&&h.push(" smaller than or equal to "+c.max);return{msg:"Please
|
|||
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":j=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;case "streamname_with_wildcard_and_variables":j=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;case "track_selector_parameter":j=function(){};break;case "track_selector":j=function(){};break;default:j=function(){}}i.push(j)}e.data("validate_functions",i).data("help_container",f).data("validate",function(a,b){if($(a).is(":visible")||$(a).is('input[type="hidden"]')){var c=$(a).getval(),h=$(a).data("validate_functions"),d=$(a).data("help_container");d.find(".err_balloon").remove();for(var e in h){var g=h[e](c,a);if(g){$err=$("<span>").addClass("err_balloon").html(g.msg);
|
||||
for(var f in g.classes)$err.addClass(g.classes[f]);d.prepend($err);b&&$(a).focus();return typeof g=="object"&&"break"in g?g["break"]:true}}return false}}).addClass("hasValidate").on("change keyup",function(){$(this).data("validate")($(this))});""!=e.getval()&&e.trigger("change")}"function"in c&&(e.on("change keyup",c["function"]),e.trigger("change"))}}b.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 b},buildVheaderTable:function(a){var b=$("<table>"),d=$("<tr>").addClass("header").append($("<td>").addClass("vheader").attr("rowspan",a.labels.length+1).append($("<span>").text(a.vheader))),c=[];d.append($("<td>"));for(var e in a.labels)c.push($("<tr>").append($("<td>").html(""==a.labels[e]?" ":a.labels[e]+":")));for(var l in a.content)for(e in d.append($("<td>").html(a.content[l].header)),a.content[l].body)c[e].append($("<td>").html(a.content[l].body[e]));
|
||||
b.append($("<tbody>").append(d).append(c));return b},plot:{addGraph:function(a,b){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);b.append(d.elements.cont);return d},go:function(a){if(!(1>Object.keys(a).length)){var b={totals:[],clients:[]},d;for(d in a)for(var c in a[d].datasets){var e=
|
||||
a[d].datasets[c];switch(e.datatype){case "clients":case "upbps":case "downbps":case "perc_lost":case "perc_retrans":switch(e.origin[0]){case "total":b.totals.push({fields:[e.datatype],end:-15});break;case "stream":b.totals.push({fields:[e.datatype],streams:[e.origin[1]],end:-15});break;case "protocol":b.totals.push({fields:[e.datatype],protocols:[e.origin[1]],end:-15})}break;case "cpuload":case "memload":b.capabilities={}}}0==b.totals.length&&delete b.totals;0==b.clients.length&&delete b.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 e=[],n;for(n in c.datasets){var j=c.datasets[n];j.display&&(j.getdata(),j.yaxistype in c.yaxes||(d.push(UI.plot.yaxes[j.yaxistype]),c.yaxes[j.yaxistype]=d.length),j.yaxis=c.yaxes[j.yaxistype],e.push(j))}d[0]&&(d[0].color=0);c.plot=$.plot(c.elements.plot,e,{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 q=function(a){var b=c.elements.legend.find(".value"),d=1;if(typeof a=="undefined")b.eq(0).html("Latest:");else{var e=c.plot.getXAxes()[0],a=Math.min(e.max,a),a=Math.max(e.min,a);b.eq(0).html(UI.format.time(a/1E3))}for(var g in c.datasets){var f=" ";if(c.datasets[g].display){var e=UI.plot.yaxes[c.datasets[g].yaxistype].tickFormatter,
|
||||
m=c.datasets[g].data;if(a)for(var q in m){if(m[q][0]==a){f=e(m[q][1]);break}if(m[q][0]>a){if(q!=0){f=m[q];m=m[q-1];f=e(f[1]+(a-f[0])*(m[1]-f[1])/(m[0]-f[0]))}break}}else f=e(c.datasets[g].data[c.datasets[g].data.length-1][1])}b.eq(d).html(f);d++}};c.plot.getOptions();for(n in c.datasets)e=$("<input>").attr("type","checkbox").data("index",n).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[n].display&&e.attr("checked","checked"),d.append($("<tr>").html($("<td>").html($("<label>").html(e).append($("<div>").addClass("series-color").css("background-color",c.datasets[n].color)).append(c.datasets[n].label))).append($("<td>").css("padding-right","2em").css("text-align","right").html($("<span>").addClass("value")).append($("<button>").text("X").addClass("close").data("index",n).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)}}}))));q();var g=!1;c.elements.plot.on("plothover",function(a,b,c){if(b.x!=g){q(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(){q()})}}},b)}},save:function(a){var b={id:a.id,xaxis:a.xaxis,datasets:[]},d;for(d in a.datasets)b.datasets.push({origin:a.datasets[d].origin,
|
||||
datatype:a.datasets[d].datatype});a=mist.stored.get().graphs||{};a[b.id]=b;mist.stored.set("graphs",a)},del:function(a){var b=mist.stored.get().graphs||{};delete b[a];mist.stored.set("graphs",b)},datatype:{getOptions:function(a){var b=$.extend(!0,{},UI.plot.datatype.templates.general),d=$.extend(!0,{},UI.plot.datatype.templates[a.datatype]),a=$.extend(!0,d,a),a=$.extend(!0,b,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 b=[],c;for(c in a.basecolor)d=a.basecolor[c],d+=50*(0.5-Math.random()),d=Math.round(d),d=Math.min(255,Math.max(0,d)),b.push(d);a.color="rgb("+b.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,b;for(b in this.data)this.data[b][0]<1E3*(mist.data.config.time-600)&&(a=b);!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,b;for(b in this.data)this.data[b][0]<1E3*(mist.data.config.time-
|
||||
600)&&(a=b);!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]},perc_lost:{label:"Lost packages",yaxistype:"percentage",basecolor:[255,33,234]},perc_retrans:{label:"Re-transmitted packages",yaxistype:"percentage",
|
||||
basecolor:[0,0,255]}}},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 b=
|
||||
0.3*Math.sqrt($(".graph").first().height()),b=(a.max-a.min)/b,d=Math.floor(Math.log(Math.abs(b))/Math.log(1024)),c=b/Math.pow(1024,d),e=-Math.floor(Math.log(c)/Math.LN10),l=a.tickDecimals;null!=l&&e>l&&(e=l);var i=Math.pow(10,-e),c=c/i,f;if(1.5>c)f=1;else if(3>c){if(f=2,2.25<c&&(null==l||e+1<=l))f=2.5,++e}else f=7.5>c?5:10;f=f*i*Math.pow(1024,d);null!=a.minTickSize&&f<a.minTickSize&&(f=a.minTickSize);a.delta=b;a.tickDecimals=Math.max(0,null!=l?l:e);a.tickSize=f;b=[];d=a.tickSize*Math.floor(a.min/
|
||||
a.tickSize);e=0;l=Number.NaN;do i=l,l=d+e*a.tickSize,b.push(l),++e;while(l<a.max&&l!=i);return b},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"),c=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:c,right:"auto",bottom:"auto"})});a.parent().on("dragleave",function(){})},format:{time:function(a,b){var d=new Date(1E3*a),c=[];c.push(("0"+d.getHours()).slice(-2));c.push(("0"+d.getMinutes()).slice(-2));"short"!=b&&c.push(("0"+d.getSeconds()).slice(-2));return c.join(":")},date:function(a,b){var d=new Date(1E3*a),c="Sun Mon Tue Wed Thu Fri Sat".split(" "),e=[];"long"==b&&e.push(c[d.getDay()]);e.push(("0"+d.getDate()).slice(-2));e.push("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" ")[d.getMonth()]);
|
||||
"short"!=b&&e.push(d.getFullYear());return e.join(" ")},dateTime:function(a,b){return UI.format.date(a,b)+", "+UI.format.time(a,b)},duration:function(a,b){var d=[0.001,1E3,60,60,24,1E99],c=["ms","sec","min","hr","day"],e={},l=!!(0>a),i=Math.abs(a),f;for(f in c){var i=Math.round(i/d[f]),m=i%d[Number(f)+1];e[c[f]]=m;i-=m}var n;for(f=c.length-1;0<=f;f--)if(0<e[c[f]]){n=c[f];break}d=$("<span>");switch(n){case "day":if(b){d.append(UI.format.addUnit(e.day,"days, ")).append(UI.format.addUnit(e.hr,"hrs"));
|
||||
break}else d.append(UI.format.addUnit(e.day,"days, "));default:if(b)switch(n){case "hr":d.append(UI.format.addUnit(e.hr,"hrs, ")).append(UI.format.addUnit(e.min,"mins"));break;case "min":d.append(UI.format.addUnit(e.min,"mins, ")).append(UI.format.addUnit(e.sec,"s"));break;case "sec":e=Math.round(1E3*e.sec+e.ms)/1E3;d.append(UI.format.addUnit(e,"s"));break;case "ms":d.append(UI.format.addUnit(e.ms,"ms"))}else d.append([("0"+e.hr).slice(-2),("0"+e.min).slice(-2),("0"+e.sec).slice(-2)+(e.ms?"."+("00"+
|
||||
e.ms).slice(-3):"")].join(":"))}return(l?"- ":"")+d[0].innerHTML},number:function(a){if(isNaN(Number(a))||0==a)return a;var b=Math.pow(10,3-Math.floor(Math.log(a)/Math.LN10)-1),a=Math.round(a*b)/b;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 b=$("<span>");if("undefined"==typeof a.online)return b.text("Unknown, checking.."),"undefined"!=typeof a.error&&b.text(a.error),b;switch(a.online){case -1:b.text("Enabling");
|
||||
break;case 0:b.text("Unavailable").addClass("red");break;case 1:b.text("Active").addClass("green");break;case 2:b.text("Standby").addClass("orange");break;default:b.text(a.online)}"error"in a&&b.text(a.error);return b},capital:function(a){return a.charAt(0).toUpperCase()+a.substring(1)},addUnit:function(a,b){var d=$("<span>").html(a);d.append($("<span>").addClass("unit").html(b));return d[0].innerHTML},bytes:function(a,b){var d="bytes KiB MiB GiB TiB PiB".split(" ");if(0==a)unit=d[0];else{var c=Math.floor(Math.log(Math.abs(a))/
|
||||
Math.log(1024));0>c?unit=d[0]:(a/=Math.pow(1024,c),unit=d[c])}return UI.format.addUnit(UI.format.number(a),unit+(b?"/s":""))},bits:function(a,b){var d="b Kib Mib Gib Tib Pib".split(" ");if(0==a)unit=d[0];else{var c=Math.floor(Math.log(Math.abs(a))/Math.log(1024));0>c?unit=d[0]:(a/=Math.pow(1024,c),unit=d[c])}return UI.format.addUnit(UI.format.number(a),unit+(b?"ps":""))}},navto:function(a,b){var d=location.hash,c=d.split("@");c[0]=[mist.user.name,mist.user.host].join("&");c[1]=[a,b].join("&");"undefined"!=
|
||||
typeof screenlog&&screenlog.navto(c[1]);location.hash=c.join("@");location.hash==d&&$(window).trigger("hashchange")},showTab:function(a,b,d){var c=UI.elements.main;"undefined"==typeof d&&(d=[]);if(mist.user.loggedin){if(!("ui_settings"in mist.data)){c.html("Loading..");mist.send(function(){UI.showTab(a,b)},{ui_settings:!0});return}mist.data.config.serverid&&(document.title=mist.data.config.serverid+" - MistServer MI")}var e=UI.elements.menu.removeClass("hide").find('.plain:contains("'+a+'")').filter(function(){return $(this).text()===
|
||||
a}).closest(".button");0<e.length&&(UI.elements.menu.find(".button.active").removeClass("active"),e.addClass("active"),$submenu=e.closest("[data-param]"),$submenu.length&&$submenu.attr("data-param",b));window.mv&&mv.reference&&mv.reference.unload();UI.interval.clear();UI.websockets.clear();c.attr("data-tab",a).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");
|
||||
c.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");c.append($("<p>").text("No account has been created yet in the MistServer at ").append($("<i>").text(mist.user.host)).append("."));
|
||||
c.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.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");c.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)c.append("Unable to enable all protocols as protocol settings already exist.<br>");else{c.append("Retrieving available protocols..<br>");mist.send(function(a){var b=[],d;for(d in a.capabilities.connectors)if(a.capabilities.connectors[d].required)c.append('Could not enable protocol "'+d+'" because it has required settings.<br>');else{b.push({connector:d});c.append('Enabled protocol "'+
|
||||
d+'".<br>')}c.append("Saving protocol settings..<br>");mist.send(function(){c.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});c.append("Loading..");return}var l=$("<span>").text("Loading.."),i=$("<span>"),f=$("<span>").addClass("logs"),
|
||||
m=$("<span>"),n=$("<span>"),j=$("<span>").text("Unknown"),q=$("<span>"),g=$("<span>"),h=parseURL(mist.user.host),h=h.protocol+h.host+h.port,k={};c.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:l},{type:"span",
|
||||
label:"Server time",value:n},{type:"span",label:"Licensed to",value:"license"in mist.data.config?mist.data.config.license.user:""},{type:"span",label:"Active licenses",value:j},{type:"span",label:"Configured streams",value:mist.data.streams?Object.keys(mist.data.streams).length:0},{type:"span",label:"Active streams",value:i},{type:"span",label:"Current connections",value:m},{type:"span",label:"Enabled protocols",value:q},{type:"span",label:"Disabled protocols",value:g},{type:"span",label:"Recent problems",
|
||||
value:f},$("<br>"),$("<h3>").text("Write config now"),{type:"help",help:"Tick the box in order to force an immediate save to the config.json MistServer uses to save your settings. Saving will otherwise happen upon closing MistServer. Don't forget to press save after ticking the box."},{type:"checkbox",label:"Force configurations save",pointer:{main:k,index:"save"}},{type:"buttons",buttons:[{type:"save",label:"Save","function":function(){var a={};if(k.save)a.save=k.save;delete k.save;mist.send(function(){UI.navto("Overview")},
|
||||
a)}}]}]));if(mist.data.LTS){var o=function(a){function b(a){if(a.update){var d="";"progress"in a.update&&(d=" ("+a.update.progress+"%)");l.text("Updating.."+d);c(a.log);setTimeout(function(){mist.send(function(a){b(a)},{update:true})},1E3)}else UI.showTab("Overview")}function c(a){a=a.filter(function(a){return a[1]=="UPDR"});if(a.length){var b=$("<div>");l.append(b);for(var d in a)b.append($("<div>").text(a[d][2]))}}if(!a.update||!("uptodate"in a.update)){l.text("Unknown, checking..");setTimeout(function(){mist.send(function(a){"update"in
|
||||
a&&o(a)},{checkupdate:true})},5E3)}else if(a.update.error)l.addClass("red").text(a.update.error);else if(a.update.uptodate)l.text("Your version is up to date.").addClass("green");else{if(a.update.progress){l.addClass("orange").removeClass("red").text("Updating..");b(a)}else{l.text("");l.append($("<span>").addClass("red").text("On "+(new Date(a.update.date)).toLocaleDateString()+" version "+a.update.version+" became available."));(!a.update.url||a.update.url.slice(-4)!=".zip")&&l.append($("<button>").text("Rolling update").css({"font-size":"1em",
|
||||
"margin-left":"1em"}).click(function(){if(confirm("Are you sure you want to execute a rolling update?")){l.addClass("orange").removeClass("red").text("Rolling update command sent..");mist.send(function(a){b(a)},{autoupdate:true})}}));var d=$("<a>").attr("href",a.update.url).attr("target","_blank").text("Manual download");d[0].protocol="https:";l.append($("<div>").append(d))}c(a.log)}};o(mist.data);if("license"in mist.data.config){if("active_products"in mist.data.config.license&&Object.keys(mist.data.config.license.active_products).length){var s=
|
||||
$("<table>").css("text-indent","0");j.html(s);s.append($("<tr>").append($("<th>").append("Product")).append($("<th>").append("Updates until")).append($("<th>").append("Use until")).append($("<th>").append("Max. simul. instances")));for(var p in mist.data.config.license.active_products)h=mist.data.config.license.active_products[p],s.append($("<tr>").append($("<td>").append(h.name)).append($("<td>").append(h.updates_final?h.updates_final:"∞")).append($("<td>").append(h.use_final?h.use_final:"∞")).append($("<td>").append(h.amount?
|
||||
h.amount:"∞")))}else j.text("None. ");j.append($("<a>").text("More details").attr("href","https://shop.mistserver.org/myinvoices").attr("target","_blank"))}}else l.text("");p=function(){var a={totals:{fields:["clients"],start:-10},active_streams:true};if(!("capabilities"in mist.data))a.capabilities=true;mist.send(function(){ca()},a)};var ca=function(){i.text("active_streams"in mist.data?mist.data.active_streams?mist.data.active_streams.length:0:"?");if("totals"in mist.data&&"all_streams"in mist.data.totals)var a=
|
||||
mist.data.totals.all_streams.all_protocols.clients,a=a.length?UI.format.number(a[a.length-1][1]):0;else a="Loading..";m.text(a);n.text(UI.format.dateTime(mist.data.config.time,"long"));f.html("");a=0;"license"in mist.data.config&&"user_msg"in mist.data.config.license&&mist.data.log.unshift([mist.data.config.license.time,"ERROR",mist.data.config.license.user_msg]);for(var b in mist.data.log){var c=mist.data.log[b];if(["FAIL","ERROR"].indexOf(c[1])>-1){a++;var d=$("<span>").addClass("content").addClass("red"),
|
||||
h=c[2].split("|");for(b in h)d.append($("<span>").text(h[b]));f.append($("<div>").append($("<span>").append(UI.format.time(c[0]))).append(d));if(a==5)break}}a==0&&f.html("None.");a=[];c=[];for(b in mist.data.config.protocols){d=mist.data.config.protocols[b];a.indexOf(d.connector)>-1||a.push(d.connector)}q.text(a.length?a.join(", "):"None.");if("capabilities"in mist.data){for(b in mist.data.capabilities.connectors)a.indexOf(b)==-1&&c.push(b);g.text(c.length?c.join(", "):"None.")}else g.text("Loading..")};
|
||||
p();ca();UI.interval.set(p,3E4);break;case "General":var A={serverid:mist.data.config.serverid,debug:mist.data.config.debug,accesslog:mist.data.config.accesslog,prometheus:mist.data.config.prometheus,defaultStream:mist.data.config.defaultStream,trustedproxy:mist.data.config.trustedproxy},H={sessionViewerMode:mist.data.config.sessionViewerMode,sessionInputMode:mist.data.config.sessionInputMode,sessionOutputMode:mist.data.config.sessionOutputMode,sessionUnspecifiedMode:mist.data.config.sessionUnspecifiedMode,
|
||||
tknMode:mist.data.config.tknMode,sessionStreamInfoMode:mist.data.config.sessionStreamInfoMode},P={location:"location"in mist.data.config?mist.data.config.location:{}},D={limit:""};"bandwidth"in mist.data&&(D=mist.data.bandwidth,null==D&&(D={}),D.limit||(D.limit=""));var da=$("<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"));c.html(UI.buildUI([$("<h2>").text("General settings"),
|
||||
{type:"help",help:"These are settings that apply to your MistServer instance in general."},{type:"str",label:"Human readable name",pointer:{main:A,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:A,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."},
|
||||
classes:["red"]}}};break;case "track_selector_parameter":j=function(){};break;case "track_selector":j=function(){};break;default:j=function(){}}i.push(j)}"checkValidity"in e[0]&&i.push(function(a,b){if("checkValidity"in b&&b.checkValidity()==false)return{msg:"validationMessage"in b?b.validationMessage:"This value ("+a+") is invalid.",classes:["red"]}});e.data("validate_functions",i).data("help_container",f).data("validate",function(a,b){if($(a).is(":visible")||$(a).is('input[type="hidden"]')){var c=
|
||||
$(a).getval(),h=$(a).data("validate_functions"),d=$(a).data("help_container");d.find(".err_balloon").remove();for(var e in h){var g=h[e](c,a);if(g){$err=$("<span>").addClass("err_balloon").html(g.msg);for(var f in g.classes)$err.addClass(g.classes[f]);d.prepend($err);b&&$(a).focus();return typeof g=="object"&&"break"in g?g["break"]:true}}return false}}).addClass("hasValidate").on("change keyup",function(){$(this).data("validate")(this)});""!=e.getval()&&e.trigger("change")}"function"in c&&(e.on("change keyup",
|
||||
c["function"]),e.trigger("change"))}}b.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 b},buildVheaderTable:function(a){var b=$("<table>"),d=$("<tr>").addClass("header").append($("<td>").addClass("vheader").attr("rowspan",a.labels.length+1).append($("<span>").text(a.vheader))),c=[];d.append($("<td>"));for(var e in a.labels)c.push($("<tr>").append($("<td>").html(""==
|
||||
a.labels[e]?" ":a.labels[e]+":")));for(var l in a.content)for(e in d.append($("<td>").html(a.content[l].header)),a.content[l].body)c[e].append($("<td>").html(a.content[l].body[e]));b.append($("<tbody>").append(d).append(c));return b},plot:{addGraph:function(a,b){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);
|
||||
b.append(d.elements.cont);return d},go:function(a){if(!(1>Object.keys(a).length)){var b={totals:[],clients:[]},d;for(d in a)for(var c in a[d].datasets){var e=a[d].datasets[c];switch(e.datatype){case "clients":case "upbps":case "downbps":case "perc_lost":case "perc_retrans":switch(e.origin[0]){case "total":b.totals.push({fields:[e.datatype],end:-15});break;case "stream":b.totals.push({fields:[e.datatype],streams:[e.origin[1]],end:-15});break;case "protocol":b.totals.push({fields:[e.datatype],protocols:[e.origin[1]],
|
||||
end:-15})}break;case "cpuload":case "memload":b.capabilities={}}}0==b.totals.length&&delete b.totals;0==b.clients.length&&delete b.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 e=[],n;for(n in c.datasets){var j=c.datasets[n];j.display&&(j.getdata(),j.yaxistype in c.yaxes||(d.push(UI.plot.yaxes[j.yaxistype]),c.yaxes[j.yaxistype]=d.length),j.yaxis=c.yaxes[j.yaxistype],
|
||||
e.push(j))}d[0]&&(d[0].color=0);c.plot=$.plot(c.elements.plot,e,{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 q=function(a){var b=c.elements.legend.find(".value"),d=1;if(typeof a=="undefined")b.eq(0).html("Latest:");else{var e=c.plot.getXAxes()[0],a=Math.min(e.max,a),a=Math.max(e.min,
|
||||
a);b.eq(0).html(UI.format.time(a/1E3))}for(var g in c.datasets){var f=" ";if(c.datasets[g].display){var e=UI.plot.yaxes[c.datasets[g].yaxistype].tickFormatter,m=c.datasets[g].data;if(a)for(var q in m){if(m[q][0]==a){f=e(m[q][1]);break}if(m[q][0]>a){if(q!=0){f=m[q];m=m[q-1];f=e(f[1]+(a-f[0])*(m[1]-f[1])/(m[0]-f[0]))}break}}else f=e(c.datasets[g].data[c.datasets[g].data.length-1][1])}b.eq(d).html(f);d++}};c.plot.getOptions();for(n in c.datasets)e=$("<input>").attr("type","checkbox").data("index",
|
||||
n).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[n].display&&e.attr("checked","checked"),d.append($("<tr>").html($("<td>").html($("<label>").html(e).append($("<div>").addClass("series-color").css("background-color",c.datasets[n].color)).append(c.datasets[n].label))).append($("<td>").css("padding-right","2em").css("text-align",
|
||||
"right").html($("<span>").addClass("value")).append($("<button>").text("X").addClass("close").data("index",n).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)}}}))));q();var g=!1;c.elements.plot.on("plothover",function(a,b,c){if(b.x!=g){q(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(){q()})}}},b)}},save:function(a){var b={id:a.id,xaxis:a.xaxis,datasets:[]},d;for(d in a.datasets)b.datasets.push({origin:a.datasets[d].origin,datatype:a.datasets[d].datatype});a=mist.stored.get().graphs||{};a[b.id]=b;mist.stored.set("graphs",a)},del:function(a){var b=mist.stored.get().graphs||{};delete b[a];mist.stored.set("graphs",b)},datatype:{getOptions:function(a){var b=$.extend(!0,{},UI.plot.datatype.templates.general),
|
||||
d=$.extend(!0,{},UI.plot.datatype.templates[a.datatype]),a=$.extend(!0,d,a),a=$.extend(!0,b,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 b=[],c;for(c in a.basecolor)d=a.basecolor[c],d+=50*(0.5-Math.random()),d=Math.round(d),d=Math.min(255,Math.max(0,d)),b.push(d);a.color="rgb("+b.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,b;for(b in this.data)this.data[b][0]<1E3*(mist.data.config.time-600)&&(a=b);!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,b;for(b in this.data)this.data[b][0]<1E3*(mist.data.config.time-600)&&(a=b);!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]},perc_lost:{label:"Lost packages",yaxistype:"percentage",basecolor:[255,33,234]},perc_retrans:{label:"Re-transmitted packages",yaxistype:"percentage",basecolor:[0,0,255]}}},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 b=0.3*Math.sqrt($(".graph").first().height()),b=(a.max-a.min)/b,d=Math.floor(Math.log(Math.abs(b))/Math.log(1024)),c=b/Math.pow(1024,d),e=-Math.floor(Math.log(c)/Math.LN10),l=a.tickDecimals;null!=l&&e>l&&(e=l);var i=Math.pow(10,-e),c=c/i,f;if(1.5>c)f=1;else if(3>c){if(f=2,2.25<c&&(null==l||e+1<=l))f=2.5,++e}else f=7.5>
|
||||
c?5:10;f=f*i*Math.pow(1024,d);null!=a.minTickSize&&f<a.minTickSize&&(f=a.minTickSize);a.delta=b;a.tickDecimals=Math.max(0,null!=l?l:e);a.tickSize=f;b=[];d=a.tickSize*Math.floor(a.min/a.tickSize);e=0;l=Number.NaN;do i=l,l=d+e*a.tickSize,b.push(l),++e;while(l<a.max&&l!=i);return b},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"),c=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:c,right:"auto",bottom:"auto"})});a.parent().on("dragleave",function(){})},format:{time:function(a,b){var d=new Date(1E3*a),c=[];c.push(("0"+d.getHours()).slice(-2));c.push(("0"+d.getMinutes()).slice(-2));"short"!=b&&c.push(("0"+d.getSeconds()).slice(-2));return c.join(":")},
|
||||
date:function(a,b){var d=new Date(1E3*a),c="Sun Mon Tue Wed Thu Fri Sat".split(" "),e=[];"long"==b&&e.push(c[d.getDay()]);e.push(("0"+d.getDate()).slice(-2));e.push("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" ")[d.getMonth()]);"short"!=b&&e.push(d.getFullYear());return e.join(" ")},dateTime:function(a,b){return UI.format.date(a,b)+", "+UI.format.time(a,b)},duration:function(a,b){var d=[0.001,1E3,60,60,24,1E99],c=["ms","sec","min","hr","day"],e={},l=!!(0>a),i=Math.abs(a),f;for(f in c){var i=
|
||||
Math.round(i/d[f]),m=i%d[Number(f)+1];e[c[f]]=m;i-=m}var n;for(f=c.length-1;0<=f;f--)if(0<e[c[f]]){n=c[f];break}d=$("<span>");switch(n){case "day":if(b){d.append(UI.format.addUnit(e.day,"days, ")).append(UI.format.addUnit(e.hr,"hrs"));break}else d.append(UI.format.addUnit(e.day,"days, "));default:if(b)switch(n){case "hr":d.append(UI.format.addUnit(e.hr,"hrs, ")).append(UI.format.addUnit(e.min,"mins"));break;case "min":d.append(UI.format.addUnit(e.min,"mins, ")).append(UI.format.addUnit(e.sec,"s"));
|
||||
break;case "sec":e=Math.round(1E3*e.sec+e.ms)/1E3;d.append(UI.format.addUnit(e,"s"));break;case "ms":d.append(UI.format.addUnit(e.ms,"ms"))}else d.append([("0"+e.hr).slice(-2),("0"+e.min).slice(-2),("0"+e.sec).slice(-2)+(e.ms?"."+("00"+e.ms).slice(-3):"")].join(":"))}return(l?"- ":"")+d[0].innerHTML},number:function(a){if(isNaN(Number(a))||0==a)return a;var b=Math.pow(10,3-Math.floor(Math.log(a)/Math.LN10)-1),a=Math.round(a*b)/b;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 b=$("<span>");if("undefined"==typeof a.online)return b.text("Unknown, checking.."),"undefined"!=typeof a.error&&b.text(a.error),b;switch(a.online){case -1:b.text("Enabling");break;case 0:b.text("Unavailable").addClass("red");break;case 1:b.text("Active").addClass("green");break;case 2:b.text("Standby").addClass("orange");break;default:b.text(a.online)}"error"in a&&b.text(a.error);return b},capital:function(a){return a.charAt(0).toUpperCase()+
|
||||
a.substring(1)},addUnit:function(a,b){var d=$("<span>").html(a);d.append($("<span>").addClass("unit").html(b));return d[0].innerHTML},bytes:function(a,b){var d="bytes KiB MiB GiB TiB PiB".split(" ");if(0==a)unit=d[0];else{var c=Math.floor(Math.log(Math.abs(a))/Math.log(1024));0>c?unit=d[0]:(a/=Math.pow(1024,c),unit=d[c])}return UI.format.addUnit(UI.format.number(a),unit+(b?"/s":""))},bits:function(a,b){var d="b Kib Mib Gib Tib Pib".split(" ");if(0==a)unit=d[0];else{var c=Math.floor(Math.log(Math.abs(a))/
|
||||
Math.log(1024));0>c?unit=d[0]:(a/=Math.pow(1024,c),unit=d[c])}return UI.format.addUnit(UI.format.number(a),unit+(b?"ps":""))}},navto:function(a,b){var d=location.hash,c=d.split("@");c[0]=[mist.user.name,mist.user.host].join("&");c[1]=[a,b].join("&");"undefined"!=typeof screenlog&&screenlog.navto(c[1]);location.hash=c.join("@");location.hash==d&&$(window).trigger("hashchange")},showTab:function(a,b,d){var c=UI.elements.main;"undefined"==typeof d&&(d=[]);if(mist.user.loggedin){if(!("ui_settings"in mist.data)){c.html("Loading..");
|
||||
mist.send(function(){UI.showTab(a,b)},{ui_settings:!0});return}mist.data.config.serverid&&(document.title=mist.data.config.serverid+" - MistServer MI")}var e=UI.elements.menu.removeClass("hide").find('.plain:contains("'+a+'")').filter(function(){return $(this).text()===a}).closest(".button");0<e.length&&(UI.elements.menu.find(".button.active").removeClass("active"),e.addClass("active"),$submenu=e.closest("[data-param]"),$submenu.length&&$submenu.attr("data-param",b));window.mv&&mv.reference&&mv.reference.unload();
|
||||
UI.interval.clear();UI.websockets.clear();c.attr("data-tab",a).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");c.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");c.append($("<p>").text("No account has been created yet in the MistServer at ").append($("<i>").text(mist.user.host)).append("."));c.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.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");c.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)c.append("Unable to enable all protocols as protocol settings already exist.<br>");
|
||||
else{c.append("Retrieving available protocols..<br>");mist.send(function(a){var b=[],d;for(d in a.capabilities.connectors)if(a.capabilities.connectors[d].required)c.append('Could not enable protocol "'+d+'" because it has required settings.<br>');else{b.push({connector:d});c.append('Enabled protocol "'+d+'".<br>')}c.append("Saving protocol settings..<br>");mist.send(function(){c.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});c.append("Loading..");return}var l=$("<span>").text("Loading.."),i=$("<span>"),f=$("<span>").addClass("logs"),m=$("<span>"),n=$("<span>"),j=$("<span>").text("Unknown"),q=$("<span>"),g=$("<span>"),h=parseURL(mist.user.host),h=h.protocol+h.host+h.port,k={};c.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:l},{type:"span",label:"Server time",value:n},{type:"span",label:"Licensed to",value:"license"in mist.data.config?mist.data.config.license.user:""},{type:"span",label:"Active licenses",value:j},{type:"span",label:"Configured streams",value:mist.data.streams?Object.keys(mist.data.streams).length:0},{type:"span",label:"Active streams",value:i},{type:"span",label:"Current connections",
|
||||
value:m},{type:"span",label:"Enabled protocols",value:q},{type:"span",label:"Disabled protocols",value:g},{type:"span",label:"Recent problems",value:f},$("<br>"),$("<h3>").text("Write config now"),{type:"help",help:"Tick the box in order to force an immediate save to the config.json MistServer uses to save your settings. Saving will otherwise happen upon closing MistServer. Don't forget to press save after ticking the box."},{type:"checkbox",label:"Force configurations save",pointer:{main:k,index:"save"}},
|
||||
{type:"buttons",buttons:[{type:"save",label:"Save","function":function(){var a={};if(k.save)a.save=k.save;delete k.save;mist.send(function(){UI.navto("Overview")},a)}}]}]));if(mist.data.LTS){var o=function(a){function b(a){if(a.update){var d="";"progress"in a.update&&(d=" ("+a.update.progress+"%)");l.text("Updating.."+d);c(a.log);setTimeout(function(){mist.send(function(a){b(a)},{update:true})},1E3)}else UI.showTab("Overview")}function c(a){a=a.filter(function(a){return a[1]=="UPDR"});if(a.length){var b=
|
||||
$("<div>");l.append(b);for(var d in a)b.append($("<div>").text(a[d][2]))}}if(!a.update||!("uptodate"in a.update)){l.text("Unknown, checking..");setTimeout(function(){mist.send(function(a){"update"in a&&o(a)},{checkupdate:true})},5E3)}else if(a.update.error)l.addClass("red").text(a.update.error);else if(a.update.uptodate)l.text("Your version is up to date.").addClass("green");else{if(a.update.progress){l.addClass("orange").removeClass("red").text("Updating..");b(a)}else{l.text("");l.append($("<span>").addClass("red").text("On "+
|
||||
(new Date(a.update.date)).toLocaleDateString()+" version "+a.update.version+" became available."));(!a.update.url||a.update.url.slice(-4)!=".zip")&&l.append($("<button>").text("Rolling update").css({"font-size":"1em","margin-left":"1em"}).click(function(){if(confirm("Are you sure you want to execute a rolling update?")){l.addClass("orange").removeClass("red").text("Rolling update command sent..");mist.send(function(a){b(a)},{autoupdate:true})}}));var d=$("<a>").attr("href",a.update.url).attr("target",
|
||||
"_blank").text("Manual download");d[0].protocol="https:";l.append($("<div>").append(d))}c(a.log)}};o(mist.data);if("license"in mist.data.config){if("active_products"in mist.data.config.license&&Object.keys(mist.data.config.license.active_products).length){var s=$("<table>").css("text-indent","0");j.html(s);s.append($("<tr>").append($("<th>").append("Product")).append($("<th>").append("Updates until")).append($("<th>").append("Use until")).append($("<th>").append("Max. simul. instances")));for(var p in mist.data.config.license.active_products)h=
|
||||
mist.data.config.license.active_products[p],s.append($("<tr>").append($("<td>").append(h.name)).append($("<td>").append(h.updates_final?h.updates_final:"∞")).append($("<td>").append(h.use_final?h.use_final:"∞")).append($("<td>").append(h.amount?h.amount:"∞")))}else j.text("None. ");j.append($("<a>").text("More details").attr("href","https://shop.mistserver.org/myinvoices").attr("target","_blank"))}}else l.text("");p=function(){var a={totals:{fields:["clients"],start:-10},active_streams:true};
|
||||
if(!("capabilities"in mist.data))a.capabilities=true;mist.send(function(){ca()},a)};var ca=function(){i.text("active_streams"in mist.data?mist.data.active_streams?mist.data.active_streams.length:0:"?");if("totals"in mist.data&&"all_streams"in mist.data.totals)var a=mist.data.totals.all_streams.all_protocols.clients,a=a.length?UI.format.number(a[a.length-1][1]):0;else a="Loading..";m.text(a);n.text(UI.format.dateTime(mist.data.config.time,"long"));f.html("");a=0;"license"in mist.data.config&&"user_msg"in
|
||||
mist.data.config.license&&mist.data.log.unshift([mist.data.config.license.time,"ERROR",mist.data.config.license.user_msg]);for(var b in mist.data.log){var c=mist.data.log[b];if(["FAIL","ERROR"].indexOf(c[1])>-1){a++;var d=$("<span>").addClass("content").addClass("red"),h=c[2].split("|");for(b in h)d.append($("<span>").text(h[b]));f.append($("<div>").append($("<span>").append(UI.format.time(c[0]))).append(d));if(a==5)break}}a==0&&f.html("None.");a=[];c=[];for(b in mist.data.config.protocols){d=mist.data.config.protocols[b];
|
||||
a.indexOf(d.connector)>-1||a.push(d.connector)}q.text(a.length?a.join(", "):"None.");if("capabilities"in mist.data){for(b in mist.data.capabilities.connectors)a.indexOf(b)==-1&&c.push(b);g.text(c.length?c.join(", "):"None.")}else g.text("Loading..")};p();ca();UI.interval.set(p,3E4);break;case "General":var A={serverid:mist.data.config.serverid,debug:mist.data.config.debug,accesslog:mist.data.config.accesslog,prometheus:mist.data.config.prometheus,defaultStream:mist.data.config.defaultStream,trustedproxy:mist.data.config.trustedproxy},
|
||||
H={sessionViewerMode:mist.data.config.sessionViewerMode,sessionInputMode:mist.data.config.sessionInputMode,sessionOutputMode:mist.data.config.sessionOutputMode,sessionUnspecifiedMode:mist.data.config.sessionUnspecifiedMode,tknMode:mist.data.config.tknMode,sessionStreamInfoMode:mist.data.config.sessionStreamInfoMode},P={location:"location"in mist.data.config?mist.data.config.location:{}},D={limit:""};"bandwidth"in mist.data&&(D=mist.data.bandwidth,null==D&&(D={}),D.limit||(D.limit=""));var da=$("<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"));
|
||||
c.html(UI.buildUI([$("<h2>").text("General settings"),{type:"help",help:"These are settings that apply to your MistServer instance in general."},{type:"str",label:"Human readable name",pointer:{main:A,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:A,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:A,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:A,index:"prometheus"},help:"Make stats available in Prometheus format. These can be accessed via "+h+"/PASSPHRASE or "+
|
||||
h+"/PASSPHRASE.json.",LTSonly:!0},{type:"inputlist",label:"Trusted proxies",help:"List of proxy server addresses that are allowed to override the viewer IP address to arbitrary values.<br>You may use a hostname or IP address.",pointer:{main:A,index:"trustedproxy"}},{type:"str",validate:["streamname_with_wildcard_and_variables"],label:"Fallback stream",pointer:{main:A,index:"defaultStream"},help:"When this is set, if someone attempts to view a stream that does not exist, or is offline, they will be redirected to this stream instead. $stream may be used to refer to the original stream name.",
|
||||
LTSonly:!0},{type:"buttons",buttons:[{type:"save",label:"Save","function":function(a){$(a).text("Saving..");mist.send(function(){UI.navto("General")},{config:A})}}]}]));c.append(UI.buildUI([$("<h3>").text("Sessions"),{type:"bitmask",label:"Bundle viewer sessions by",bitmask:[[8,"Stream name"],[4,"IP address"],[2,"Token"],[1,"Protocol"]],pointer:{main:H,index:"sessionViewerMode"},help:"Change the way viewer connections are bundled into sessions.<br>Default: stream name, viewer IP and token"},{type:"bitmask",
|
||||
|
@ -344,9 +344,9 @@ d){f.placeholder=d["default"];if(d.type=="select")for(var i in d.select)if(d.sel
|
|||
"radioselect";f.radioselect=d.radioselect;break;case "select":f.type="select";f.select=d.select.slice(0);f.validate.indexOf("required")>=0&&f.select.unshift(["","placeholder"in f?"Default ("+f.placeholder+")":""]);break;case "sublist":f.type="sublist";f.saveas={};f.itemLabel=d.itemLabel;f.sublist=mist.convertBuildOptions(d,f.saveas);break;case "group":var j=$("<div>").addClass("itemgroup"),a=mist.convertBuildOptions({optional:d.options},b),a=a.slice(1),l=$("<ul>").addClass("summary");a.unshift(l);
|
||||
"help"in d&&a.unshift($("<span>").addClass("description").text(d.help));"name"in d&&a.unshift($("<b>").text(d.name).click(function(){j.toggleClass("expanded")}).attr("title","Click to show / hide these options"));(d.expand||d.expand!==false&&Object.keys(d.options).length<2)&&j.addClass("expanded");return j.change(function(){l.html("");$(this).find('.isSetting, input[type="hidden"].isSetting').each(function(){var a=$(this).getval();if(a!=""){var b=$(this).data("opts");if(a!=b["default"]){var c=b.label+
|
||||
": ";switch(b.type){case "select":a=b.select.filter(function(b){return b[0]==a?true:false})[0][1];break;case "unix":a=UI.format.dateTime(a);break;case "checkbox":a="";c=c.slice(0,-2)}l.append($("<li>").addClass("setting").append($("<span>").addClass("label").text(c)).append($("<span>").text(a)).append($("<span>").addClass("unit").text(typeof b.unit=="string"?b.unit:"")))}}})}).append(UI.buildUI(a)).trigger("change");case "bool":f.type="checkbox";break;case "unixtime":f.type="unix";break;case "json":case "debug":case "inputlist":f.type=
|
||||
d.type;break;default:f.type="str"}else f.type="checkbox";if("format"in d)switch(d.format){case "set_or_unset":f.postSave=function(){var a=$(this).data("pointer");a.main[a.index]||delete a.main[a.index]}}"influences"in d?f["function"]=function(){var a=$(this).closest(".UIelement"),b=a.find("style");if(b.length)b=b[0];else{b=$("<style>").addClass("dependencies")[0];a.append(b)}b.innerHTML=".UIelement[data-dependent-"+c+"]:not([data-dependent-"+c+'~="'+$(this).getval()+'"]) { display: none; }\n';$(b).data("content",
|
||||
b.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("")})}:"disable"in d&&(f["function"]=function(){for(var a=$(this).closest(".input_container"),b=$(this).getval(),c=0;c<d.disable.length;c++){var e=a.find('.field[name="'+d.disable[c]+'"]').closest(".UIelement");if(e.length)b==""?e[0].style.display="":e.hide()}});
|
||||
if("dependent"in d)f.dependent=d.dependent;if("value"in d)f.value=d.value;if("validate"in d){f.validate=f.validate.concat(d.validate);if(d.validate.indexOf("track_selector_parameter")>-1)f.help="<div>"+d.help+"</div><p>Track selector parameters consist of a string value which may be any of the following:</p> <ul><li><code>selector,selector</code>: Selects the union of the given selectors. Any number of comma-separated selector combinations may be used, they are evaluated one by one from left to right.</li> <li><code>selector,!selector</code>: Selects the difference of the given selectors. Specifically, all tracks part of the first selector that are not part of the second selector. Any number of comma-separated selector combinations may be used, they are evaluated one by one from left to right.</li> <li><code>selector,|selector</code>: Selects the intersection of the given selectors. Any number of comma-separated selector combinations may be used, they are evaluated one by one from left to right.</li> <li><code>none</code> or <code>-1</code>: Selects no tracks of this type.</li> <li><code>all</code> or <code>*</code>: Selects all tracks of this type.</li> <li>Any positive integer: Select this specific track ID. Does not apply if the given track ID does not exist or is of the wrong type. <strong>Does</strong> apply if the given track ID is incompatible with the currently active protocol or container format.</li> <li>ISO 639-1/639-3 language code: Select all tracks marked as the given language. Case insensitive.</li> <li>Codec string (e.g. <code>h264</code>): Select all tracks of the given codec. Case insensitive.</li> <li><code>highbps</code>, <code>maxbps</code> or <code>bestbps</code>: Select the track of this type with the highest bit rate.</li> <li><code>lowbps</code>, <code>minbps</code> or <code>worstbps</code>: Select the track of this type with the lowest bit rate.</li> <li><code>Xbps</code> or <code>Xkbps</code> or <code>Xmbps</code>: Select the single of this type which has a bit rate closest to the given number X. This number is in bits, not bytes.</li> <li><code>>Xbps</code> or <code>>Xkbps</code> or <code>>Xmbps</code>: Select all tracks of this type which have a bit rate greater than the given number X. This number is in bits, not bytes.</li> <li><code><Xbps</code> or <code><Xkbps</code> or <code><Xmbps</code>: Select all tracks of this type which have a bit rate less than the given number X. This number is in bits, not bytes.</li> <li><code>max<Xbps</code> or <code>max<Xkbps</code> or <code>max<Xmbps</code>: Select the one track of this type which has the highest bit rate less than the given number X. This number is in bits, not bytes.</li> <li><code>highres</code>, <code>maxres</code> or <code>bestres</code>: Select the track of this type with the highest pixel surface area. Only applied when the track type is video.</li> <li><code>lowres</code>, <code>minres</code> or <code>worstres</code>: Select the track of this type with the lowest pixel surface area. Only applied when the track type is video.</li> <li><code>XxY</code>: Select all tracks of this type with the given pixel surface area in X by Y pixels. Only applied when the track type is video.</li> <li><code>~XxY</code>: Select the single track of this type closest to the given pixel surface area in X by Y pixels. Only applied when the track type is video.</li> <li><code>>XxY</code>: Select all tracks of this type with a pixel surface area greater than X by Y pixels. Only applied when the track type is video.</li> <li><code><XxY</code>: Select all tracks of this type with a pixel surface area less than X by Y pixels. Only applied when the track type is video.</li> <li><code>720p</code>, <code>1080p</code>, <code>1440p</code>, <code>2k</code>, <code>4k</code>, <code>5k</code>, or <code>8k</code>: Select all tracks of this type with the given pixel surface area. Only applied when the track type is video.</li> <li><code>surround</code>, <code>mono</code>, <code>stereo</code>, <code>Xch</code>: Select all tracks of this type with the given channel count. The 'Xch' variant can use any positive integer for 'X'. Only applied when the track type is audio.</li></ul>";
|
||||
d.type;break;default:f.type="str";if("minlength"in d)f.minlength=d.minlength;if("maxlength"in d)f.maxlength=d.maxlength}else f.type="checkbox";if("format"in d)switch(d.format){case "set_or_unset":f.postSave=function(){var a=$(this).data("pointer");a.main[a.index]||delete a.main[a.index]}}"influences"in d?f["function"]=function(){var a=$(this).closest(".UIelement"),b=a.find("style");if(b.length)b=b[0];else{b=$("<style>").addClass("dependencies")[0];a.append(b)}b.innerHTML=".UIelement[data-dependent-"+
|
||||
c+"]:not([data-dependent-"+c+'~="'+$(this).getval()+'"]) { display: none; }\n';$(b).data("content",b.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("")})}:"disable"in d&&(f["function"]=function(){for(var a=$(this).closest(".input_container"),b=$(this).getval(),c=0;c<d.disable.length;c++){var e=a.find('.field[name="'+
|
||||
d.disable[c]+'"]').closest(".UIelement");if(e.length)b==""?e[0].style.display="":e.hide()}});if("dependent"in d)f.dependent=d.dependent;if("value"in d)f.value=d.value;if("validate"in d){f.validate=f.validate.concat(d.validate);if(d.validate.indexOf("track_selector_parameter")>-1)f.help="<div>"+d.help+"</div><p>Track selector parameters consist of a string value which may be any of the following:</p> <ul><li><code>selector,selector</code>: Selects the union of the given selectors. Any number of comma-separated selector combinations may be used, they are evaluated one by one from left to right.</li> <li><code>selector,!selector</code>: Selects the difference of the given selectors. Specifically, all tracks part of the first selector that are not part of the second selector. Any number of comma-separated selector combinations may be used, they are evaluated one by one from left to right.</li> <li><code>selector,|selector</code>: Selects the intersection of the given selectors. Any number of comma-separated selector combinations may be used, they are evaluated one by one from left to right.</li> <li><code>none</code> or <code>-1</code>: Selects no tracks of this type.</li> <li><code>all</code> or <code>*</code>: Selects all tracks of this type.</li> <li>Any positive integer: Select this specific track ID. Does not apply if the given track ID does not exist or is of the wrong type. <strong>Does</strong> apply if the given track ID is incompatible with the currently active protocol or container format.</li> <li>ISO 639-1/639-3 language code: Select all tracks marked as the given language. Case insensitive.</li> <li>Codec string (e.g. <code>h264</code>): Select all tracks of the given codec. Case insensitive.</li> <li><code>highbps</code>, <code>maxbps</code> or <code>bestbps</code>: Select the track of this type with the highest bit rate.</li> <li><code>lowbps</code>, <code>minbps</code> or <code>worstbps</code>: Select the track of this type with the lowest bit rate.</li> <li><code>Xbps</code> or <code>Xkbps</code> or <code>Xmbps</code>: Select the single of this type which has a bit rate closest to the given number X. This number is in bits, not bytes.</li> <li><code>>Xbps</code> or <code>>Xkbps</code> or <code>>Xmbps</code>: Select all tracks of this type which have a bit rate greater than the given number X. This number is in bits, not bytes.</li> <li><code><Xbps</code> or <code><Xkbps</code> or <code><Xmbps</code>: Select all tracks of this type which have a bit rate less than the given number X. This number is in bits, not bytes.</li> <li><code>max<Xbps</code> or <code>max<Xkbps</code> or <code>max<Xmbps</code>: Select the one track of this type which has the highest bit rate less than the given number X. This number is in bits, not bytes.</li> <li><code>highres</code>, <code>maxres</code> or <code>bestres</code>: Select the track of this type with the highest pixel surface area. Only applied when the track type is video.</li> <li><code>lowres</code>, <code>minres</code> or <code>worstres</code>: Select the track of this type with the lowest pixel surface area. Only applied when the track type is video.</li> <li><code>XxY</code>: Select all tracks of this type with the given pixel surface area in X by Y pixels. Only applied when the track type is video.</li> <li><code>~XxY</code>: Select the single track of this type closest to the given pixel surface area in X by Y pixels. Only applied when the track type is video.</li> <li><code>>XxY</code>: Select all tracks of this type with a pixel surface area greater than X by Y pixels. Only applied when the track type is video.</li> <li><code><XxY</code>: Select all tracks of this type with a pixel surface area less than X by Y pixels. Only applied when the track type is video.</li> <li><code>720p</code>, <code>1080p</code>, <code>1440p</code>, <code>2k</code>, <code>4k</code>, <code>5k</code>, or <code>8k</code>: Select all tracks of this type with the given pixel surface area. Only applied when the track type is video.</li> <li><code>surround</code>, <code>mono</code>, <code>stereo</code>, <code>Xch</code>: Select all tracks of this type with the given channel count. The 'Xch' variant can use any positive integer for 'X'. Only applied when the track type is audio.</li></ul>";
|
||||
if(d.validate.indexOf("track_selector")>-1)f.help="<div>"+d.help+"</div><p>A track selector is at least one track type (audio, video or subtitle) combined with a track selector parameter. For example: <code>audio=none&video=maxres</code>.<p>Track selector parameters consist of a string value which may be any of the following:</p> <ul><li><code>selector,selector</code>: Selects the union of the given selectors. Any number of comma-separated selector combinations may be used, they are evaluated one by one from left to right.</li> <li><code>selector,!selector</code>: Selects the difference of the given selectors. Specifically, all tracks part of the first selector that are not part of the second selector. Any number of comma-separated selector combinations may be used, they are evaluated one by one from left to right.</li> <li><code>selector,|selector</code>: Selects the intersection of the given selectors. Any number of comma-separated selector combinations may be used, they are evaluated one by one from left to right.</li> <li><code>none</code> or <code>-1</code>: Selects no tracks of this type.</li> <li><code>all</code> or <code>*</code>: Selects all tracks of this type.</li> <li>Any positive integer: Select this specific track ID. Does not apply if the given track ID does not exist or is of the wrong type. <strong>Does</strong> apply if the given track ID is incompatible with the currently active protocol or container format.</li> <li>ISO 639-1/639-3 language code: Select all tracks marked as the given language. Case insensitive.</li> <li>Codec string (e.g. <code>h264</code>): Select all tracks of the given codec. Case insensitive.</li> <li><code>highbps</code>, <code>maxbps</code> or <code>bestbps</code>: Select the track of this type with the highest bit rate.</li> <li><code>lowbps</code>, <code>minbps</code> or <code>worstbps</code>: Select the track of this type with the lowest bit rate.</li> <li><code>Xbps</code> or <code>Xkbps</code> or <code>Xmbps</code>: Select the single of this type which has a bit rate closest to the given number X. This number is in bits, not bytes.</li> <li><code>>Xbps</code> or <code>>Xkbps</code> or <code>>Xmbps</code>: Select all tracks of this type which have a bit rate greater than the given number X. This number is in bits, not bytes.</li> <li><code><Xbps</code> or <code><Xkbps</code> or <code><Xmbps</code>: Select all tracks of this type which have a bit rate less than the given number X. This number is in bits, not bytes.</li> <li><code>max<Xbps</code> or <code>max<Xkbps</code> or <code>max<Xmbps</code>: Select the one track of this type which has the highest bit rate less than the given number X. This number is in bits, not bytes.</li> <li><code>highres</code>, <code>maxres</code> or <code>bestres</code>: Select the track of this type with the highest pixel surface area. Only applied when the track type is video.</li> <li><code>lowres</code>, <code>minres</code> or <code>worstres</code>: Select the track of this type with the lowest pixel surface area. Only applied when the track type is video.</li> <li><code>XxY</code>: Select all tracks of this type with the given pixel surface area in X by Y pixels. Only applied when the track type is video.</li> <li><code>~XxY</code>: Select the single track of this type closest to the given pixel surface area in X by Y pixels. Only applied when the track type is video.</li> <li><code>>XxY</code>: Select all tracks of this type with a pixel surface area greater than X by Y pixels. Only applied when the track type is video.</li> <li><code><XxY</code>: Select all tracks of this type with a pixel surface area less than X by Y pixels. Only applied when the track type is video.</li> <li><code>720p</code>, <code>1080p</code>, <code>1440p</code>, <code>2k</code>, <code>4k</code>, <code>5k</code>, or <code>8k</code>: Select all tracks of this type with the given pixel surface area. Only applied when the track type is video.</li> <li><code>surround</code>, <code>mono</code>, <code>stereo</code>, <code>Xch</code>: Select all tracks of this type with the given channel count. The 'Xch' variant can use any positive integer for 'X'. Only applied when the track type is audio.</li></ul>"}return f}
|
||||
var c=[],e=["required","optional"];"desc"in a&&c.push({type:"help",help:a.desc});for(var l in e)if(a[e[l]]){c.push($("<h4>").text(UI.format.capital(e[l])+" parameters"));var i=Object.keys(a[e[l]]);"sort"in a&&i.sort(function(b,c){return(""+a[e[l]][b][a.sort]).localeCompare(a[e[l]][c][a.sort])});for(var f in i){var m=i[f],n=a[e[l]][m];if(Array.isArray(n))for(var j in n)c.push(d(l,m,n[j]));else c.push(d(l,m,n))}}return c},stored:{get:function(){return mist.data.ui_settings||{}},set:function(a,b){var d=
|
||||
this.get();d[a]=b;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){}}
|
||||
|
|
21
lsp/mist.js
21
lsp/mist.js
|
@ -1572,9 +1572,23 @@ var UI = {
|
|||
}
|
||||
fs.push(f);
|
||||
}
|
||||
|
||||
//add standard html5 validation
|
||||
if ("checkValidity" in $field[0]) {
|
||||
fs.push(function(val,me){
|
||||
if ("checkValidity" in me) {
|
||||
if (me.checkValidity() == false) {
|
||||
return {
|
||||
msg: "validationMessage" in me ? me.validationMessage : "This value ("+val+") is invalid." ,
|
||||
classes: ["red"]
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$field.data('validate_functions',fs).data('help_container',$ihc).data('validate',function(me,focusonerror){
|
||||
if ((!$(me).is(":visible")) && (!$(me).is("input[type=\"hidden\"]"))) { return; }
|
||||
|
||||
var val = $(me).getval();
|
||||
var fs = $(me).data('validate_functions');
|
||||
var $ihc = $(me).data('help_container');
|
||||
|
@ -1594,7 +1608,7 @@ var UI = {
|
|||
return false;
|
||||
}).addClass('hasValidate').on('change keyup',function(){
|
||||
var f = $(this).data('validate');
|
||||
f($(this));
|
||||
f(this);
|
||||
});
|
||||
if ($field.getval() != '') {
|
||||
$field.trigger('change');
|
||||
|
@ -10344,6 +10358,9 @@ var mist = {
|
|||
}
|
||||
default:
|
||||
obj.type = 'str';
|
||||
if ("minlength" in ele) { obj.minlength = ele.minlength; }
|
||||
if ("maxlength" in ele) { obj.maxlength = ele.maxlength; }
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -279,6 +279,9 @@ namespace Mist{
|
|||
addStrOpt(pp["srtopts_main"]["options"], "streamid", "Stream ID", "Stream ID to transmit to the other side. MistServer uses this field for the stream name, but the field is entirely free-form and may contain anything.");
|
||||
addStrOpt(pp["srtopts_main"]["options"], "passphrase", "Encryption passphrase", "Enables encryption with the given passphrase.");
|
||||
|
||||
pp["srtopts_main"]["options"]["passphrase"]["minlength"] = 10;
|
||||
pp["srtopts_main"]["options"]["passphrase"]["maxlength"] = 79;
|
||||
|
||||
|
||||
pp["srtopts"]["name"] = "More SRT options";
|
||||
pp["srtopts"]["help"] = "Control the SRT connection";
|
||||
|
@ -400,6 +403,8 @@ namespace Mist{
|
|||
capa["optional"]["passphrase"]["option"] = "--passphrase";
|
||||
capa["optional"]["passphrase"]["short"] = "P";
|
||||
capa["optional"]["passphrase"]["default"] = "";
|
||||
capa["optional"]["passphrase"]["minlength"] = 10;
|
||||
capa["optional"]["passphrase"]["maxlength"] = 79;
|
||||
|
||||
opt.null();
|
||||
opt["long"] = "passphrase";
|
||||
|
|
Loading…
Add table
Reference in a new issue