- stop active pushes button update,
- also work with .exe on cygwin,
- new graph fix
- required settings at edit protocols are required fix
This commit is contained in:
Cat 2016-11-16 11:27:05 +01:00 committed by Thulinma
parent 59d5ee2cba
commit 8ba26b11e9
7 changed files with 64 additions and 678 deletions

View file

@ -90,7 +90,7 @@ var fa=function(){function a(b){var c=mist.data.capabilities.connectors[b.connec
3E4);break;case "Edit Protocol":if("undefined"==typeof mist.data.capabilities){mist.send(function(){UI.navto(a,b)},{capabilities:!0});c.append("Loading..");return}var G=!1;""!=b&&0<=b&&(G=!0);var K={};for(g in mist.data.config.protocols)K[mist.data.config.protocols[g].connector]=1;var ga=function(a){var c=mist.data.capabilities.connectors[a],d=mist.convertBuildOptions(c,n);d.push({type:"hidden",pointer:{main:n,index:"connector"},value:a});d.push({type:"buttons",buttons:[{type:"save",label:"Save",
"function":function(){if(G)mist.data.config.protocols[b]=n;else{if(!mist.data.config.protocols)mist.data.config.protocols=[];mist.data.config.protocols.push(n)}mist.send(function(){UI.navto("Protocols")},{config:mist.data.config})}},{type:"cancel",label:"Cancel","function":function(){UI.navto("Protocols")}}]});if("deps"in c&&c.deps!=""){$t=$("<span>").text("Dependencies:");$ul=$("<ul>");$t.append($ul);if(typeof c.deps=="string")c.deps=c.deps.split(", ");for(var g in c.deps){a=$("<li>").text(c.deps[g]+
" ");$ul.append(a);typeof K[c.deps[g]]!="undefined"||typeof K[c.deps[g]+".exe"]!="undefined"?a.append($("<span>").addClass("green").text("(Configured)")):a.append($("<span>").addClass("red").text("(Not yet configured)"))}d.unshift({type:"text",text:$t[0].innerHTML})}return UI.buildUI(d)},K={};for(g in mist.data.config.protocols)K[mist.data.config.protocols[g].connector]=1;if(G)n=d=mist.data.config.protocols[b],c.find("h2").append(' "'+d.connector+'"'),c.append(ga(d.connector));else{c.html($("<h2>").text("New Protocol"));
var n={},t=[];for(g in mist.data.capabilities.connectors)t.push([g,g]);var H=$("<span>");c.append(UI.buildUI([{label:"Protocol",type:"select",select:t,"function":function(){H.html(ga($(this).getval()))}}])).append(H)}break;case "Streams":if(!("capabilities"in mist.data)){c.html("Loading..");mist.send(function(){UI.navto(a)},{capabilities:!0});return}var g=$("<button>"),D=$("<span>").text("Loading..");c.append(UI.buildUI([{type:"help",help:"Here you can create, edit or delete new and existing streams. Go to stream preview or embed a video player on your website."},
var n={},t=[["",""]];for(g in mist.data.capabilities.connectors)t.push([g,g]);var H=$("<span>");c.append(UI.buildUI([{label:"Protocol",type:"select",select:t,"function":function(){$(this).getval()!=""&&H.html(ga($(this).getval()))}}])).append(H)}break;case "Streams":if(!("capabilities"in mist.data)){c.html("Loading..");mist.send(function(){UI.navto(a)},{capabilities:!0});return}var g=$("<button>"),D=$("<span>").text("Loading..");c.append(UI.buildUI([{type:"help",help:"Here you can create, edit or delete new and existing streams. Go to stream preview or embed a video player on your website."},
$("<div>").css({width:"45.25em",display:"flex","justify-content":"flex-end"}).append(g).append($("<button>").text("Create a new stream").click(function(){UI.navto("Edit")}))])).append(D);if(""==b){var r=mist.stored.get();"viewmode"in r&&(b=r.viewmode)}g.text("Switch to "+("thumbnails"==b?"list":"thumbnail")+" view").click(function(){mist.stored.set("viewmode",b=="thumbnails"?"list":"thumbnails");UI.navto("Streams",b=="thumbnails"?"list":"thumbnails")});var z=$.extend(!0,{},mist.data.streams),T=function(a,
b){var c=$.extend({},b);delete c.meta;delete c.error;c.online=2;c.name=a;c.ischild=true;return c},U=function(b,d,g){D.remove();switch(b){case "thumbnails":var e=$("<div>").addClass("preview_icons"),f;f=g||[];d.sort();d.unshift("");D.remove();c.append($("<h2>").text(a)).append(UI.buildUI([{label:"Filter the streams",type:"datalist",datalist:d,pointer:{main:{},index:"stream"},help:"If you type something here, the box below will only show streams with names that contain your text.","function":function(){var a=
$(this).val();e.children().each(function(){$(this).hide();$(this).attr("data-stream").indexOf(a)>-1&&$(this).show()})}}]));d.shift();c.append($("<span>").addClass("description").text("Choose a stream below.")).append(e);for(var h in d){var b=d[h],i="",j=$("<button>").text("Delete").click(function(){var a=$(this).closest("div").attr("data-stream");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;
@ -117,8 +117,8 @@ type:"span",clipboard:true,readonly:true,classes:["RTMP"]});a.push({label:"RTSP"
index:"keyid"}},{label:"Key seed",type:"str",LTSonly:!0,pointer:{main:n,index:"keyseed"}},{type:"buttons",buttons:[{type:"cancel",label:"Cancel","function":function(){UI.navto("Streams")}},{type:"save",label:"Save","function":function(){ja("Streams")}},{type:"save",label:"Save and Preview","function":function(){ja("Preview")},classes:["saveandpreview"]}]}]));c.find("[name=name]").keyup(function(){W()});W();break;case "Preview":""==b&&UI.navto("Streams");r=":8080";for(g in mist.data.config.protocols)if(d=
mist.data.config.protocols[g],"HTTP"==d.connector||"HTTP.exe"==d.connector)r=d.port?":"+d.port:":8080";var s=parseURL(mist.user.host),P=s.protocol+s.host+r+"/",H=$("<div>").css({display:"flex","flex-flow":"row wrap"}),s="";-1==b.indexOf("+")&&(s=$("<button>").text("Settings").addClass("settings").click(function(){UI.navto("Edit",b)}));c.html($("<div>").addClass("bigbuttons").append(s).append($("<button>").text("Embed").addClass("embed").click(function(){UI.navto("Embed",b)})).append($("<button>").addClass("cancel").addClass("return").text("Return").click(function(){UI.navto("Streams")}))).append($("<h2>").text('Preview of "'+
b+'"')).append(H);var E=encodeURIComponent(b),g=$("<div>");H.append(g);var X=$("<div>"),Q=$("<select>").append($("<option>").text("Automatic").val("")).change(function(){Y()}),M=$("<select>").append($("<option>").text("Automatic").val("")).change(function(){Y()}),s=UI.buildUI([{label:"Use player",type:"DOMfield",DOMfield:Q,help:"Choose a player to preview"},{label:"Use source",type:"DOMfield",DOMfield:M,help:"Choose an output type to preview"}]),I=$("<div>").addClass("mistvideo").text("Loading player..");
g.append(I).append(X).append(s);var Y=function(){I.html("");B.html("");var a={target:I[0],maxheight:window.innerHeight-$("header").height(),maxwidth:window.innerWidth-UI.elements.menu.width()-100,loop:true};if(Q.val()!="")a.forcePlayer=Q.val();if(M.val()!="")a.forceType=M.val();mistPlay(b,a)},B=$("<div>").addClass("player_log");g.append($("<div>").append($("<h3>").text("Player log:")).append(B));I.on("log error",function(a){var b=false;B.height()+B.scrollTop()==B[0].scrollHeight&&(b=true);B.append($("<div>").append($("<span>").text("["+
UI.format.time((new Date).getTime()/1E3)+"]").css("margin-right","0.5em")).append($("<span>").text(a.originalEvent.message)).addClass(a.type=="error"?"red":""));b&&B.scrollTop(B[0].scrollHeight)});var la=function(){X.text("");var a=document.createElement("script");c.append(a);a.src=P+"player.js";a.onerror=function(){I.html("Failed to load player.js").append($("<button>").text("Reload").css("display","block").click(function(){la()}))};a.onload=function(){for(var d in mistplayers)Q.append($("<option>").text(mistplayers[d].name).val(d));
g.append(I).append(X).append(s);var Y=function(){I.html("");C.html("");var a={target:I[0],maxheight:window.innerHeight-$("header").height(),maxwidth:window.innerWidth-UI.elements.menu.width()-100,loop:true};if(Q.val()!="")a.forcePlayer=Q.val();if(M.val()!="")a.forceType=M.val();mistPlay(b,a)},C=$("<div>").addClass("player_log");g.append($("<div>").append($("<h3>").text("Player log:")).append(C));I.on("log error",function(a){var b=false;C.height()+C.scrollTop()==C[0].scrollHeight&&(b=true);C.append($("<div>").append($("<span>").text("["+
UI.format.time((new Date).getTime()/1E3)+"]").css("margin-right","0.5em")).append($("<span>").text(a.originalEvent.message)).addClass(a.type=="error"?"red":""));b&&C.scrollTop(C[0].scrollHeight)});var la=function(){X.text("");var a=document.createElement("script");c.append(a);a.src=P+"player.js";a.onerror=function(){I.html("Failed to load player.js").append($("<button>").text("Reload").css("display","block").click(function(){la()}))};a.onload=function(){for(var d in mistplayers)Q.append($("<option>").text(mistplayers[d].name).val(d));
Y();I.on("initialized",function(){if(M.children().length<=1)for(var a in mistvideo[b].source){var c=mistvideo[b].source[a],d=UI.humanMime(c.type);M.append($("<option>").val(c.type).text(d?d+" @ "+c.url.substring(c.url.length-c.relurl.length,0):UI.format.capital(c.type)+" @ "+c.url.substring(c.url.length-c.relurl.length,0)))}a=mistvideo[b].embedded[mistvideo[b].embedded.length-1];d=UI.humanMime(a.player.options.source.type);X.html("You're watching "+(d?d+" <span class=description>("+a.player.options.source.type+
")</span>":UI.format.capital(a.player.options.source.type))+" through "+mistplayers[a.selectedPlayer].name+".")});c[0].removeChild(a)}};la();var g=$("<div>").append($("<h3>").text("Meta information")),R=$("<span>").text("Loading..");g.append(R);H.append(g);$.ajax({type:"GET",url:P+"json_"+E+".js",success:function(a){var b=a.meta;if(b){a=[];a.push({label:"Type",type:"span",value:b.live?"Live":"Pre-recorded (VoD)"});"format"in b&&a.push({label:"Format",type:"span",value:b.format});b.live&&a.push({label:"Buffer window",
type:"span",value:UI.format.addUnit(b.buffer_window,"ms")});var c={audio:{vheader:"Audio",labels:["Codec","Duration","Peak bitrate","Channels","Samplerate","Language"],content:[]},video:{vheader:"Video",labels:["Codec","Duration","Peak bitrate","Size","Framerate","Language"],content:[]},subtitle:{vheader:"Subtitles",labels:["Codec","Duration","Peak bitrate","Language"],content:[]}},d=Object.keys(b.tracks);d.sort(function(a,b){a=a.split("_").pop();b=b.split("_").pop();return a-b});for(var g in d){var e=
@ -142,17 +142,17 @@ pointer:{main:o,index:"urlappend"},help:"The embed script will append this strin
a.source[d],e=UI.humanMime(g.type);b.push({label:e?e+" <span class=description>("+g.type+")</span>":UI.format.capital(g.type),type:"str",value:g.url,readonly:true,qrcode:true,clipboard:true});e=UI.humanMime(g.type);c.append($("<option>").text(e?e+" ("+g.type+")":UI.format.capital(g.type)).val(g.type))}aa.html(UI.buildUI(b));J.html("");b={};for(d in a.meta.tracks){c=a.meta.tracks[d];c.type!="audio"&&c.type!="video"||(c.type in b?b[c.type].push([c.trackid,UI.format.capital(c.type)+" track "+(b[c.type].length+
1)]):b[c.type]=[["",UI.format.capital(c.type)+" track 1"]])}if(Object.keys(b).length){J.closest("label").show();for(d in b){a=$("<select>").attr("data-type",d).css("flex-grow","1").change(function(){$(this).val()==""?delete o.setTracks[$(this).attr("data-type")]:o.setTracks[$(this).attr("data-type")]=$(this).val();$(".embed_code").setval(w(o))});J.append(a);b[d].push([-1,"No "+d]);for(var f in b[d])a.append($("<option>").val(b[d][f][0]).text(b[d][f][1]));if(d in o.setTracks){a.val(o.setTracks[d]);
if(a.val()==null){a.val("");delete o.setTracks[d];$(".embed_code").setval(w(o))}}}}else J.closest("label").hide()},error:function(){aa.html("Error while retrieving stream info.");J.closest("label").hide();o.setTracks={}}});g=document.createElement("script");g.src=P+"player.js";document.head.appendChild(g);g.onload=function(){var a=S.find(".forcePlayer"),b;for(b in mistplayers)a.append($("<option>").text(mistplayers[b].name).val(b));document.head.removeChild(this)};g.onerror=function(){document.head.removeChild(this)};
break;case "Push":var A=$("<div>").text("Loading..");c.append(A);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(d,e){var f=$("<span>");d.length>=4&&d[2]!=d[3]?f.append($("<span>").text(d[2])).append($("<span>").html("&#187").addClass("unit").css("margin",
"0 0.5em")).append($("<span>").text(d[3])):f.append($("<span>").text(d[2]));var h=$("<td>").append($("<button>").text(e=="Automatic"?"Remove":"Stop").click(function(){if(confirm("Are you sure you want to "+$(this).text().toLowerCase()+" this push?\n"+d[1]+" to "+d[2])){var a=$(this).closest("tr");a.html($("<td colspan=99>").html($("<span>").addClass("red").text(e=="Automatic"?"Removing..":"Stopping..")));e=="Automatic"?mist.send(function(){a.remove()},{push_auto_remove:{stream:d[1],target:d[2]}}):
mist.send(function(){b([d[0]])},{push_stop:[d[0]]})}}));e=="Automatic"&&h.append($("<button>").text("Remove and stop pushes").click(function(){if(confirm("Are you sure you want to remove this automatic push, and also stop all pushes matching it?\n"+d[1]+" to "+d[2])){var c=$(this).closest("tr");c.html($("<td colspan=99>").html($("<span>").addClass("red").text("Removing and stopping..")));var e=[],f;for(f in a.push_list)if(d[1]==a.push_list[f][1]&&d[2]==a.push_list[f][2]){e.push(a.push_list[f][0]);
g.find("tr[data-pushid="+a.push_list[f][0]+"]").html($("<td colspan=99>").html($("<span>").addClass("red").text("Stopping..")))}mist.send(function(){c.remove();b(e)},{push_auto_remove:{stream:d[1],target:d[2]},push_stop:e})}}));return $("<tr>").attr("data-pushid",d[0]).append($("<td>").text(d[1])).append($("<td>").append(f.children())).append(h)}A.html("");var d=a.push_settings;d||(d={});A.append(UI.buildUI([{type:"help",help:"You can push streams to files or other servers, allowing them to broadcast your stream as well."},
$("<h3>").text("Settings"),{label:"Delay before retry",unit:"s",type:"int",min:0,help:"How long the delay should be before MistServer retries an automatic push.<br>If set to 0, it does not retry.","default":0,pointer:{main:d,index:"wait"},LTSonly:1},{label:"Maximum retries",unit:"/s",type:"int",min:0,help:"The maximum amount of retries per second (for all automatic pushes).<br>If set to 0, there is no limit.","default":0,pointer:{main:d,index:"maxspeed"},LTSonly:1},{type:"buttons",buttons:[{type:"save",
label:"Save","function":function(){mist.send(function(){UI.navto("Push")},{push_settings:d})}}]}]));var g=$("<table>").append($("<tr>").append($("<th>").text("Stream")).append($("<th>").text("Target")).append($("<th>"))),e=g.clone();if("push_list"in a)for(var f in a.push_list)g.append(c(a.push_list[f],"Manual"));if("push_auto_list"in a)for(f in a.push_auto_list)e.append(c([-1,a.push_auto_list[f][0],a.push_auto_list[f][1]],"Automatic"));A.append($("<h3>").text("Automatic pushes")).append($("<button>").text("Add an automatic push").click(function(){UI.navto("Start Push",
"auto")}));e.find("tr").length==1?A.append($("<div>").text("No automatic pushes have been configured.").addClass("text").css("margin-top","0.5em")):A.append(e);A.append($("<h3>").text("Pushes")).append($("<button>").text("Start a push").click(function(){UI.navto("Start Push")}));if(g.find("tr").length==1)A.append($("<div>").text("No pushes are active.").addClass("text").css("margin-top","0.5em"));else{var e=[],h=[],i=$("<select>").css("margin-left","0.5em").append($("<option>").text("Any stream").val("")),
j=$("<select>").css("margin-left","0.5em").append($("<option>").text("Any target").val(""));for(f in a.push_list){e.indexOf(a.push_list[f][1])==-1&&e.push(a.push_list[f][1]);h.indexOf(a.push_list[f][2])==-1&&h.push(a.push_list[f][2])}e.sort();h.sort();for(f in e)i.append($("<option>").text(e[f]));for(f in h)j.append($("<option>").text(h[f]));A.append($("<button>").text("Stop all pushes").click(function(){var c=[],d;for(d in a.push_list)c.push(a.push_list[d][0]);if(c.length!=0&&confirm("Are you sure you want to stop all pushes?")){mist.send(function(){b(c)},
{push_stop:c});g.find("tr:not(:first-child)").html($("<td colspan=99>").append($("<span>").addClass("red").text("Stopping..")));$(this).remove()}})).append($("<label>").css("margin-left","1em").append($("<span>").text("Stop all pushes that match: ").css("font-size","0.9em")).append(i).append($("<span>").css("margin-left","0.5em").text("and").css("font-size","0.9em")).append(j).append($("<button>").css("margin-left","0.5em").text("Apply").click(function(){var c=i.val(),d=j.val();if(c==""&&d=="")return alert("Looks like you want to stop all pushes. Maybe you should use that button?");
var e={},f;for(f in a.push_list)if((c==""||a.push_list[f][1]==c)&&(d==""||a.push_list[f][2]==d))e[a.push_list[f][0]]=a.push_list[f];if(Object.keys(e).length==0)return alert("No matching pushes.");c="Are you sure you want to stop these pushes?\n\n";for(f in e)c=c+(e[f][1]+" to "+e[f][2]+"\n");if(confirm(c)){e=Object.keys(e);mist.send(function(){b(e)},{push_stop:e});for(f in e)g.find("tr[data-pushid="+e[f]+"]").html($("<td colspan=99>").html($("<span>").addClass("red").text("Stopping..")))}}))).append(g)}},
{push_settings:1,push_list:1,push_auto_list:1});break;case "Start Push":if(!("capabilities"in mist.data)){c.append("Loading Mist capabilities..");mist.send(function(){UI.navto("Start Push",b)},{capabilities:1});return}var u,ba=function(){var a=[],d;for(d in mist.data.capabilities.connectors){var e=mist.data.capabilities.connectors[d];"push_urls"in e&&(a=a.concat(e.push_urls))}b=="auto"&&c.find("h2").text("Add automatic push");var g={};c.append(UI.buildUI([{label:"Stream name",type:"str",help:"This may either be a full stream name, a partial wildcard stream name, or a full wildcard stream name.<br>For example, given the stream <i>a</i> you can use:<ul><li><i>a</i>: the stream configured as <i>a</i></li><li><i>a+</i>: all streams configured as <i>a</i> with a wildcard behind it, but not <i>a</i> itself</li><li><i>a+b</i>: only the version of stream <i>a</i> that has wildcard <i>b</i></li></ul>",
break;case "Push":var A=$("<div>").text("Loading..");c.append(A);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>");e.length>=4&&e[2]!=e[3]?h.append($("<span>").text(e[2])).append($("<span>").html("&#187").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..")));f=="Automatic"?mist.send(function(){a.remove()},{push_auto_remove:{stream:e[1],target:e[2]}}):
mist.send(function(){b([e[0]])},{push_stop:[e[0]]})}}));f=="Automatic"&&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.":""))){var c=$(this);c.text("Stopping pushes..");var f=[],h;for(h in a.push_list)if(e[1]==a.push_list[h][1]&&e[2]==a.push_list[h][2]){f.push(a.push_list[h][0]);g.find("tr[data-pushid="+a.push_list[h][0]+"]").html($("<td colspan=99>").html($("<span>").addClass("red").text("Stopping..")))}mist.send(function(){c.text("Stop pushes");
b(f)},{push_stop:f,push_settings:{wait:0}})}}));return $("<tr>").attr("data-pushid",e[0]).append($("<td>").text(e[1])).append($("<td>").append(h.children())).append(i)}A.html("");var d=a.push_settings;d||(d={});A.append(UI.buildUI([{type:"help",help:"You can push streams to files or other servers, allowing them to broadcast your stream as well."},$("<h3>").text("Settings"),{label:"Delay before retry",unit:"s",type:"int",min:0,help:"How long the delay should be before MistServer retries an automatic push.<br>If set to 0, it does not retry.",
"default":0,pointer:{main:d,index:"wait"},LTSonly:1},{label:"Maximum retries",unit:"/s",type:"int",min:0,help:"The maximum amount of retries per second (for all automatic pushes).<br>If set to 0, there is no limit.","default":0,pointer:{main:d,index:"maxspeed"},LTSonly:1},{type:"buttons",buttons:[{type:"save",label:"Save","function":function(){mist.send(function(){UI.navto("Push")},{push_settings:d})}}]}]));var g=$("<table>").append($("<tr>").append($("<th>").text("Stream")).append($("<th>").text("Target")).append($("<th>"))),
e=g.clone();if("push_list"in a)for(var f in a.push_list)g.append(c(a.push_list[f],"Manual"));if("push_auto_list"in a)for(f in a.push_auto_list)e.append(c([-1,a.push_auto_list[f][0],a.push_auto_list[f][1]],"Automatic"));A.append($("<h3>").text("Automatic pushes")).append($("<button>").text("Add an automatic push").click(function(){UI.navto("Start Push","auto")}));e.find("tr").length==1?A.append($("<div>").text("No automatic pushes have been configured.").addClass("text").css("margin-top","0.5em")):
A.append(e);A.append($("<h3>").text("Pushes")).append($("<button>").text("Start a push").click(function(){UI.navto("Start Push")}));if(g.find("tr").length==1)A.append($("<div>").text("No pushes are active.").addClass("text").css("margin-top","0.5em"));else{var e=[],h=[],i=$("<select>").css("margin-left","0.5em").append($("<option>").text("Any stream").val("")),j=$("<select>").css("margin-left","0.5em").append($("<option>").text("Any target").val(""));for(f in a.push_list){e.indexOf(a.push_list[f][1])==
-1&&e.push(a.push_list[f][1]);h.indexOf(a.push_list[f][2])==-1&&h.push(a.push_list[f][2])}e.sort();h.sort();for(f in e)i.append($("<option>").text(e[f]));for(f in h)j.append($("<option>").text(h[f]));A.append($("<button>").text("Stop all pushes").click(function(){var c=[],d;for(d in a.push_list)c.push(a.push_list[d][0]);if(c.length!=0&&confirm("Are you sure you want to stop all pushes?")){mist.send(function(){b(c)},{push_stop:c});g.find("tr:not(:first-child)").html($("<td colspan=99>").append($("<span>").addClass("red").text("Stopping..")));
$(this).remove()}})).append($("<label>").css("margin-left","1em").append($("<span>").text("Stop all pushes that match: ").css("font-size","0.9em")).append(i).append($("<span>").css("margin-left","0.5em").text("and").css("font-size","0.9em")).append(j).append($("<button>").css("margin-left","0.5em").text("Apply").click(function(){var c=i.val(),d=j.val();if(c==""&&d=="")return alert("Looks like you want to stop all pushes. Maybe you should use that button?");var e={},f;for(f in a.push_list)if((c==""||
a.push_list[f][1]==c)&&(d==""||a.push_list[f][2]==d))e[a.push_list[f][0]]=a.push_list[f];if(Object.keys(e).length==0)return alert("No matching pushes.");c="Are you sure you want to stop these pushes?\n\n";for(f in e)c=c+(e[f][1]+" to "+e[f][2]+"\n");if(confirm(c)){e=Object.keys(e);mist.send(function(){b(e)},{push_stop:e});for(f in e)g.find("tr[data-pushid="+e[f]+"]").html($("<td colspan=99>").html($("<span>").addClass("red").text("Stopping..")))}}))).append(g)}},{push_settings:1,push_list:1,push_auto_list:1});
break;case "Start Push":if(!("capabilities"in mist.data)){c.append("Loading Mist capabilities..");mist.send(function(){UI.navto("Start Push",b)},{capabilities:1});return}var u,ba=function(){var a=[],d;for(d in mist.data.capabilities.connectors){var e=mist.data.capabilities.connectors[d];"push_urls"in e&&(a=a.concat(e.push_urls))}b=="auto"&&c.find("h2").text("Add automatic push");var g={};c.append(UI.buildUI([{label:"Stream name",type:"str",help:"This may either be a full stream name, a partial wildcard stream name, or a full wildcard stream name.<br>For example, given the stream <i>a</i> you can use:<ul><li><i>a</i>: the stream configured as <i>a</i></li><li><i>a+</i>: all streams configured as <i>a</i> with a wildcard behind it, but not <i>a</i> itself</li><li><i>a+b</i>: only the version of stream <i>a</i> that has wildcard <i>b</i></li></ul>",
pointer:{main:g,index:"stream"},validate:["required",function(a){a=a.split("+");a=a[0];return a in mist.data.streams?false:{msg:"'"+a+"' is not a stream name.",classes:["red"]}}],datalist:u,LTSonly:1},{label:"Target",type:"str",help:"Where the stream will be pushed to.<br>Valid formats:<ul><li>"+a.join("</li><li>")+"</li></ul> Valid text replacements:<ul><li>$stream - inserts the stream name used to push to MistServer</li><li>$day - inserts the current day number</li><li>$month - inserts the current month number</li><li>$year - inserts the current year number</li><li>$hour - inserts the hour timestamp when stream was received</li><li>$minute - inserts the minute timestamp the stream was received</li><li>$seconds - inserts the seconds timestamp when the stream was received</li><li>$datetime - inserts $year.$month.$day.$hour.$minute.$seconds timestamp when the stream was received</li>",
pointer:{main:g,index:"target"},validate:["required",function(b){for(var c in a)if(mist.inputMatch(a[c],b))return false;return{msg:"Does not match a valid target.<br>Valid formats:<ul><li>"+a.join("</li><li>")+"</li></ul>",classes:["red"]}}],LTSonly:1},{type:"buttons",buttons:[{type:"cancel",label:"Cancel","function":function(){UI.navto("Push")}},{type:"save",label:"Save","function":function(){var a={};a[b=="auto"?"push_auto_add":"push_start"]=g;mist.send(function(){UI.navto("Push")},a)}}]}]))};mist.data.LTS?
mist.send(function(a){(u=a.active_streams)||(u=[]);var a=[],b;for(b in u)u[b].indexOf("+")!=-1&&a.push(u[b].replace(/\+.*/,"")+"+");u=u.concat(a);var c=0,d=0;for(b in mist.data.streams){u.push(b);if(mist.inputMatch(mist.data.capabilities.inputs.Folder.source_match,mist.data.streams[b].source)){u.push(b+"+");mist.send(function(a,b){var e=b.stream,g;for(g in a.browse.files)for(var f in mist.data.capabilities.inputs)f.indexOf("Buffer")>=0||f.indexOf("Folder")>=0||mist.inputMatch(mist.data.capabilities.inputs[f].source_match,
@ -170,17 +170,17 @@ LTSonly:!0},{type:"buttons",buttons:[{type:"cancel",label:"Cancel","function":fu
{config:mist.data.config})}}]}]));$("[name=triggeron]").trigger("change");break;case "Logs":var na=$("<button>").text("Refresh now").click(function(){$(this).text("Loading..");mist.send(function(){ca();na.text("Refresh now")})}).css("padding","0.2em 0.5em").css("flex-grow",0);c.append(UI.buildUI([{type:"help",help:"Here you have an overview of all edited settings within MistServer and possible warnings or errors MistServer has encountered. MistServer stores up to 100 logs at a time."},{label:"Refresh every",
type:"select",select:[[10,"10 seconds"],[30,"30 seconds"],[60,"minute"],[300,"5 minutes"]],value:30,"function":function(){UI.interval.clear();UI.interval.set(function(){mist.send(function(){ca()})},$(this).val()*1E3)},help:"How often the table below should be updated."},{label:"..or",type:"DOMfield",DOMfield:na,help:"Instantly refresh the table below."}]));c.append($("<button>").text("Purge logs").click(function(){mist.send(function(){mist.data.log=[];UI.navto("Logs")},{clearstatlogs:true})}));k=
$("<tbody>").css("font-size","0.9em");c.append($("<table>").addClass("logs").append(k));var pa=function(a){var b=$("<span>").text(a);switch(a){case "WARN":b.addClass("orange");break;case "ERROR":case "FAIL":b.addClass("red")}return b},ca=function(){var a=mist.data.log;if(a){a.length>=2&&a[0][0]<a[a.length-1][0]&&a.reverse();k.html("");for(var b in a){var c=$("<span>").addClass("content"),d=a[b][2].split("|"),e;for(e in d)c.append($("<span>").text(d[e]));k.append($("<tr>").html($("<td>").text(UI.format.dateTime(a[b][0],
"long")).css("white-space","nowrap")).append($("<td>").html(pa(a[b][1])).css("text-align","center")).append($("<td>").html(c).css("text-align","left")))}}};ca();break;case "Statistics":var C=$("<span>").text("Loading..");c.append(C);var n={},x=mist.stored.get().graphs?$.extend(!0,{},mist.stored.get().graphs):{},N={};for(g in mist.data.streams)N[g]=!0;for(g in mist.data.active_streams)N[mist.data.active_streams[g]]=!0;var N=Object.keys(N).sort(),da=[];for(g in mist.data.config.protocols)da.push(mist.data.config.protocols[g].connector);
da.sort();mist.send(function(){UI.plot.datatype.templates.cpuload.cores=0;for(var a in mist.data.capabilities.cpu)UI.plot.datatype.templates.cpuload.cores=UI.plot.datatype.templates.cpuload.cores+mist.data.capabilities.cpu[a].cores;C.html(UI.buildUI([{type:"help",help:"Here you will find the MistServer stream statistics, you can select various categories yourself. All statistics are live: up to five minutes are saved."},$("<h3>").text("Select the data to display"),{label:"Add to",type:"select",select:[["new",
"New graph"]],pointer:{main:n,index:"graph"},classes:["graph_ids"],"function":function(){if($(this).val()){var a=C.find(".graph_xaxis"),b=C.find(".graph_id");if($(this).val()=="new"){a.children("option").prop("disabled",false);b.setval("Graph "+(Object.keys(x).length+1)).closest("label").show()}else{var c=x[$(this).val()].xaxis;a.children("option").prop("disabled",true).filter('[value="'+c+'"]').prop("disabled",false);b.closest("label").hide()}a.children('option[value="'+a.val()+'"]:disabled').length&&
a.val(a.children("option:enabled").first().val());a.trigger("change")}}},{label:"Graph id",type:"str",pointer:{main:n,index:"id"},classes:["graph_id"],validate:[function(a){return a in x?{msg:"This graph id has already been used. Please enter something else.",classes:["red"]}:false}]},{label:"Axis type",type:"select",select:[["time","Time line"]],pointer:{main:n,index:"xaxis"},value:"time",classes:["graph_xaxis"],"function":function(){$s=C.find(".graph_datatype");switch($(this).getval()){case "coords":$s.children("option").prop("disabled",
"long")).css("white-space","nowrap")).append($("<td>").html(pa(a[b][1])).css("text-align","center")).append($("<td>").html(c).css("text-align","left")))}}};ca();break;case "Statistics":var B=$("<span>").text("Loading..");c.append(B);var n={graph:"new"},x=mist.stored.get().graphs?$.extend(!0,{},mist.stored.get().graphs):{},N={};for(g in mist.data.streams)N[g]=!0;for(g in mist.data.active_streams)N[mist.data.active_streams[g]]=!0;var N=Object.keys(N).sort(),da=[];for(g in mist.data.config.protocols)da.push(mist.data.config.protocols[g].connector);
da.sort();mist.send(function(){UI.plot.datatype.templates.cpuload.cores=0;for(var a in mist.data.capabilities.cpu)UI.plot.datatype.templates.cpuload.cores=UI.plot.datatype.templates.cpuload.cores+mist.data.capabilities.cpu[a].cores;B.html(UI.buildUI([{type:"help",help:"Here you will find the MistServer stream statistics, you can select various categories yourself. All statistics are live: up to five minutes are saved."},$("<h3>").text("Select the data to display"),{label:"Add to",type:"select",select:[["new",
"New graph"]],pointer:{main:n,index:"graph"},classes:["graph_ids"],"function":function(){if($(this).val()){var a=B.find(".graph_xaxis"),b=B.find(".graph_id");if($(this).val()=="new"){a.children("option").prop("disabled",false);b.setval("Graph "+(Object.keys(x).length+1)).closest("label").show()}else{var c=x[$(this).val()].xaxis;a.children("option").prop("disabled",true).filter('[value="'+c+'"]').prop("disabled",false);b.closest("label").hide()}a.children('option[value="'+a.val()+'"]:disabled').length&&
a.val(a.children("option:enabled").first().val());a.trigger("change")}}},{label:"Graph id",type:"str",pointer:{main:n,index:"id"},classes:["graph_id"],validate:[function(a){return a in x?{msg:"This graph id has already been used. Please enter something else.",classes:["red"]}:false}]},{label:"Axis type",type:"select",select:[["time","Time line"]],pointer:{main:n,index:"xaxis"},value:"time",classes:["graph_xaxis"],"function":function(){$s=B.find(".graph_datatype");switch($(this).getval()){case "coords":$s.children("option").prop("disabled",
true).filter('[value="coords"]').prop("disabled",false);break;case "time":$s.children("option").prop("disabled",false).filter('[value="coords"]').prop("disabled",true)}if(!$s.val()||$s.children('option[value="'+$s.val()+'"]:disabled').length){$s.val($s.children("option:enabled").first().val());$s.trigger("change")}}},{label:"Data type",type:"select",select:[["clients","Connections"],["upbps","Bandwidth (up)"],["downbps","Bandwidth (down)"],["cpuload","CPU use"],["memload","Memory load"],["coords",
"Client location"]],pointer:{main:n,index:"datatype"},classes:["graph_datatype"],"function":function(){$s=C.find(".graph_origin");switch($(this).getval()){case "cpuload":case "memload":$s.find("input[type=radio]").not('[value="total"]').prop("disabled",true);$s.find('input[type=radio][value="total"]').prop("checked",true);break;default:$s.find("input[type=radio]").prop("disabled",false)}}},{label:"Data origin",type:"radioselect",radioselect:[["total","All"],["stream","The stream:",N],["protocol",
"The protocol:",da]],pointer:{main:n,index:"origin"},value:["total"],classes:["graph_origin"]},{type:"buttons",buttons:[{label:"Add data set",type:"save","function":function(){var a;if(n.graph=="new"){a=UI.plot.addGraph(n,b);x[a.id]=a;C.find("select.graph_ids").append($("<option>").text(a.id)).val(a.id).trigger("change")}else a=x[n.graph];var c=UI.plot.datatype.getOptions({datatype:n.datatype,origin:n.origin});a.datasets.push(c);UI.plot.save(a);UI.plot.go(x)}}]}]));var b=$("<div>").addClass("graph_container");
c.append(b);var d=C.find("select.graph_ids");for(a in x){var e=UI.plot.addGraph(x[a],b);d.append($("<option>").text(e.id)).val(e.id);var g=[],f;for(f in x[a].datasets){var h=UI.plot.datatype.getOptions({datatype:x[a].datasets[f].datatype,origin:x[a].datasets[f].origin});g.push(h)}e.datasets=g;x[e.id]=e}d.trigger("change");UI.plot.go(x);UI.interval.set(function(){UI.plot.go(x)},1E4)},{active_streams:!0,capabilities:!0});break;case "Server Stats":if("undefined"==typeof mist.data.capabilities){mist.send(function(){UI.navto(a)},
{capabilities:!0});c.append("Loading..");return}var ea=$("<table>"),D=$("<table>"),s={vheader:"CPUs",labels:["Model","Processor speed","Amount of cores","Amount of threads"],content:[]};for(g in mist.data.capabilities.cpu)r=mist.data.capabilities.cpu[g],s.content.push({header:"CPU #"+(Number(g)+1),body:[r.model,UI.format.addUnit(UI.format.number(r.mhz),"MHz"),r.cores,r.threads]});var g=UI.buildVheaderTable(s),oa=function(){var a=mist.data.capabilities.mem,b=mist.data.capabilities.load,a={vheader:"Memory",
labels:["Used","Cached","Available","Total"],content:[{header:"Physical memory",body:[UI.format.bytes(a.used*1048576)+" ("+UI.format.addUnit(b.memory,"%")+")",UI.format.bytes(a.cached*1048576),UI.format.bytes(a.free*1048576),UI.format.bytes(a.total*1048576)]},{header:"Swap memory",body:[UI.format.bytes((a.swaptotal-a.swapfree)*1048576),UI.format.addUnit("","N/A"),UI.format.bytes(a.swapfree*1048576),UI.format.bytes(a.swaptotal*1048576)]}]},a=UI.buildVheaderTable(a);ea.replaceWith(a);ea=a;b={vheader:"Load average",
labels:["CPU use","1 minute","5 minutes","15 minutes"],content:[{header:"&nbsp;",body:[UI.format.addUnit(UI.format.number(mist.data.capabilities.cpu_use/10),"%"),UI.format.number(b.one/100),UI.format.number(b.five/100),UI.format.number(b.fifteen/100)]}]};b=UI.buildVheaderTable(b);D.replaceWith(b);D=b};oa();c.append(UI.buildUI([{type:"help",help:"You can find general server statistics here. Note that memory and CPU usage is for your entire machine, not just MistServer."}])).append($("<table>").css("width",
"Client location"]],pointer:{main:n,index:"datatype"},classes:["graph_datatype"],"function":function(){$s=B.find(".graph_origin");switch($(this).getval()){case "cpuload":case "memload":$s.find("input[type=radio]").not('[value="total"]').prop("disabled",true);$s.find('input[type=radio][value="total"]').prop("checked",true);break;default:$s.find("input[type=radio]").prop("disabled",false)}}},{label:"Data origin",type:"radioselect",radioselect:[["total","All"],["stream","The stream:",N],["protocol",
"The protocol:",da]],pointer:{main:n,index:"origin"},value:["total"],classes:["graph_origin"]},{type:"buttons",buttons:[{label:"Add data set",type:"save","function":function(){var a;if(n.graph=="new"){a=UI.plot.addGraph(n,b);x[a.id]=a;B.find("input.graph_id").val("");B.find("select.graph_ids").append($("<option>").text(a.id)).val(a.id).trigger("change")}else a=x[n.graph];var c=UI.plot.datatype.getOptions({datatype:n.datatype,origin:n.origin});a.datasets.push(c);UI.plot.save(a);UI.plot.go(x)}}]}]));
var b=$("<div>").addClass("graph_container");c.append(b);var d=B.find("select.graph_ids");for(a in x){var e=UI.plot.addGraph(x[a],b);d.append($("<option>").text(e.id)).val(e.id);var g=[],f;for(f in x[a].datasets){var h=UI.plot.datatype.getOptions({datatype:x[a].datasets[f].datatype,origin:x[a].datasets[f].origin});g.push(h)}e.datasets=g;x[e.id]=e}d.trigger("change");UI.plot.go(x);UI.interval.set(function(){UI.plot.go(x)},1E4)},{active_streams:!0,capabilities:!0});break;case "Server Stats":if("undefined"==
typeof mist.data.capabilities){mist.send(function(){UI.navto(a)},{capabilities:!0});c.append("Loading..");return}var ea=$("<table>"),D=$("<table>"),s={vheader:"CPUs",labels:["Model","Processor speed","Amount of cores","Amount of threads"],content:[]};for(g in mist.data.capabilities.cpu)r=mist.data.capabilities.cpu[g],s.content.push({header:"CPU #"+(Number(g)+1),body:[r.model,UI.format.addUnit(UI.format.number(r.mhz),"MHz"),r.cores,r.threads]});var g=UI.buildVheaderTable(s),oa=function(){var a=mist.data.capabilities.mem,
b=mist.data.capabilities.load,a={vheader:"Memory",labels:["Used","Cached","Available","Total"],content:[{header:"Physical memory",body:[UI.format.bytes(a.used*1048576)+" ("+UI.format.addUnit(b.memory,"%")+")",UI.format.bytes(a.cached*1048576),UI.format.bytes(a.free*1048576),UI.format.bytes(a.total*1048576)]},{header:"Swap memory",body:[UI.format.bytes((a.swaptotal-a.swapfree)*1048576),UI.format.addUnit("","N/A"),UI.format.bytes(a.swapfree*1048576),UI.format.bytes(a.swaptotal*1048576)]}]},a=UI.buildVheaderTable(a);
ea.replaceWith(a);ea=a;b={vheader:"Load average",labels:["CPU use","1 minute","5 minutes","15 minutes"],content:[{header:"&nbsp;",body:[UI.format.addUnit(UI.format.number(mist.data.capabilities.cpu_use/10),"%"),UI.format.number(b.one/100),UI.format.number(b.five/100),UI.format.number(b.fifteen/100)]}]};b=UI.buildVheaderTable(b);D.replaceWith(b);D=b};oa();c.append(UI.buildUI([{type:"help",help:"You can find general server statistics here. Note that memory and CPU usage is for your entire machine, not just MistServer."}])).append($("<table>").css("width",
"auto").addClass("nolay").append($("<tr>").append($("<td>").append(ea)).append($("<td>").append(D))).append($("<tr>").append($("<td>").append(g).attr("colspan",2))));UI.interval.set(function(){mist.send(function(){oa()},{capabilities:true})},3E4);break;case "Email for Help":g=$.extend({},mist.data);delete g.statistics;delete g.totals;delete g.clients;delete g.capabilities;g=JSON.stringify(g);g="Version: "+mist.data.config.version+"\n\nConfig:\n"+g;n={};c.append(UI.buildUI([{type:"help",help:"You can use this form to email MistServer support if you're having difficulties.<br>A copy of your server config file will automatically be included."},
{type:"str",label:"Your name",validate:["required"],pointer:{main:n,index:"name"},value:mist.user.name},{type:"email",label:"Your email address",validate:["required"],pointer:{main:n,index:"email"}},{type:"hidden",value:"Integrated Help",pointer:{main:n,index:"subject"}},{type:"hidden",value:"-",pointer:{main:n,index:"company"}},{type:"textarea",rows:20,label:"Your message",validate:["required"],pointer:{main:n,index:"message"}},{type:"textarea",rows:20,label:"Your config file",readonly:!0,value:g,
pointer:{main:n,index:"configfile"}},{type:"buttons",buttons:[{type:"save",label:"Send","function":function(a){$(a).text("Sending..");$.ajax({type:"POST",url:"http://mistserver.org/contact?skin=plain",data:n,success:function(a){a=$("<span>").html(a);a.find("script").remove();c.html(a[0].innerHTML)}})}}]}]));break;case "Disconnect":mist.user.password="";delete mist.user.authstring;delete mist.user.loggedin;sessionStorage.removeItem("mistLogin");UI.navto("Login");break;default:c.append($("<p>").text("This tab does not exist."))}c.find(".field").filter(function(){return $(this).getval()==