- 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

@ -28,6 +28,8 @@
<script src=wrappers/silverlight.js></script>
<script src=wrappers/polytrope.js></script>
<script src=http://ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js>
<script src=players/dash.js></script>
<link rel=stylesheet href=mist.css id=mist_player_css>
@ -65,27 +67,29 @@
//tryplayers = Object.keys(mistplayers);
tryplayers = [];
tryplayers.push('html5');
//tryplayers.push('html5');
//tryplayers.push('dashjs');
//tryplayers.push('flash_strobe');
tryplayers.push('flash_strobe');
//tryplayers.push('silverlight');
streams = ['live'];
for (var i in tryplayers) {
var c = document.createElement('div');
c.className = 'mistvideo';
c.title = tryplayers[i];
document.body.appendChild(c);
mistPlay('live',{
//mistPlay('vids+mist.mp4',{
//mistPlay('lama',{
//mistPlay('bunny',{
target: c,
forcePlayer: tryplayers[i],
loop: true
});
for (var j in streams) {
for (var i in tryplayers) {
var c = document.createElement('div');
c.className = 'mistvideo';
c.title = tryplayers[i];
document.body.appendChild(c);
mistPlay(streams[j],{
//mistPlay('vids+mist.mp4',{
//mistPlay('lama',{
//mistPlay('bunny',{
target: c,
forcePlayer: tryplayers[i],
loop: true
});
}
}
};
/*

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()==

View file

@ -2472,7 +2472,7 @@ var UI = {
$('<h2>').text('New Protocol')
);
var saveas = {};
var select = [];
var select = [['','']];
for (var i in mist.data.capabilities.connectors) {
select.push([i,i]);
}
@ -2482,6 +2482,7 @@ var UI = {
type: 'select',
select: select,
'function': function(){
if ($(this).getval() == '') { return; }
$cont.html(buildProtocolSettings($(this).getval()));
}
}])).append(
@ -2821,7 +2822,7 @@ var UI = {
var s = opts.stream;
for (var i in d.browse.files) {
for (var j in mist.data.capabilities.inputs) {
if ((j.indexOf('Buffer') >= 0) || (j.indexOf('Folder') >= 0)) { continue; }
if ((j.indexOf('Buffer') >= 0) || (j.indexOf('Buffer.exe') >= 0) || (j.indexOf('Folder') >= 0) || (j.indexOf('Folder.exe') >= 0)) { continue; }
if (mist.inputMatch(mist.data.capabilities.inputs[j].source_match,'/'+d.browse.files[i])) {
var streamname = s+'+'+d.browse.files[i];
allstreams[streamname] = createWcStreamObject(streamname,mist.data.streams[s]);
@ -3119,10 +3120,11 @@ var UI = {
if (input.name == 'Folder') {
$main.append($style);
}
else if (['Buffer','TS'].indexOf(input.name) > -1) {
else if (['Buffer','Buffer.exe','TS','TS.exe'].indexOf(input.name) > -1) {
var fields = [$('<span>').text('Configure your source to push to:')];
switch (input.name) {
case 'Buffer':
case 'Buffer.exe':
fields.push({
label: 'RTMP',
type: 'span',
@ -3139,6 +3141,7 @@ var UI = {
});
break;
case 'TS':
case 'TS.exe':
fields.push({
label: 'TS',
type: 'span',
@ -3293,7 +3296,7 @@ var UI = {
var $video = $('<div>').addClass('mistvideo').text('Loading player..');
$preview_cont.append($video).append($title).append($switches);
function initPlayer() {
$video.html('');
//$video.html('');
$log.html('');
var options = {
target: $video[0],
@ -4135,14 +4138,10 @@ var UI = {
);
if (type == 'Automatic') {
$buttons.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"+push[1]+' to '+push[2])) {
var $tr = $(this).closest('tr');
$tr.html(
$('<td colspan=99>').html(
$('<span>').addClass('red').text('Removing and stopping..')
)
);
$('<button>').text('Stop pushes').click(function(){
if (confirm("Are you sure you want to stop all pushes matching \n\""+push[1]+' to '+push[2]+"\"?"+(push_settings.wait != 0 ? "\n\nRetrying is enabled. You'll probably want to set that to 0." : ''))) {
var $button = $(this);
$button.text('Stopping pushes..');
//also stop the matching pushes
var pushIds = [];
for (var i in d.push_list) {
@ -4158,14 +4157,11 @@ var UI = {
}
mist.send(function(){
$tr.remove();
$button.text('Stop pushes');
checkgone(pushIds);
},{
push_auto_remove:{
stream: push[1],
target: push[2]
},
push_stop: pushIds
push_stop: pushIds,
push_settings: {wait: 0}
});
}
})
@ -4799,7 +4795,9 @@ var UI = {
var $UI = $('<span>').text('Loading..');
$main.append($UI);
var saveas = {};
var saveas = {
graph: 'new'
};
var graphs = (mist.stored.get().graphs ? $.extend(true,{},mist.stored.get().graphs) : {});
var thestreams = {};
@ -4952,6 +4950,7 @@ var UI = {
if (saveas.graph == 'new') {
graph = UI.plot.addGraph(saveas,$graph_c);
graphs[graph.id] = graph;
$UI.find('input.graph_id').val('');
$UI.find('select.graph_ids').append(
$('<option>').text(graph.id)
).val(graph.id).trigger('change');
@ -5549,7 +5548,7 @@ var mist = {
},
validate: []
};
if ((type[j] == 'required') && (!('default' in ele))) {
if ((type[j] == 'required') && (!('default' in ele)) || (ele.default == '')) {
obj.validate.push('required');
}
if ('default' in ele) {

View file

@ -1,381 +0,0 @@
if (typeof mistplayers == 'undefined') {
//no need to define this if it's already there
var mistplayers = {};
//create prototype with empty functions the player should have, so that any that have not been defined return false
function MistPlayer() {
//return true if this player is to be used for this mimetype
this.formimetype = function (fullmimetype){ return false; };
this.name = 'Generic player';
//mimetype: e.g. 'video/mp4'; that is withouth the html5, flash, or whatever first part.
this.supported = function(mimetype){ return false; };
/*
shape of build options:
{
container: html DOM element,
width: (int) video width,
height: (int) video height,
name: (string) the stream name,
src: (string) the video source string,
mimetype: (string) the mimetype,
islive: (boolean) whether or not this is a live video,
autoplay: (boolean) whether or not to enable autoplay
}
*/
this.build = function(options){ return false; };
//creates the player element, including custom functions
this.element = function(tag){
var ele = document.createElement(tag);
ele.mistplay = function(){ return false; };
ele.mistpause = function(){ return false; };
//(double) value: 0 for muted, 1 for max
ele.mistsetvolume = function(value){ return false; };
//return the current position, in seconds
ele.mistposition = function(){ return false; };
return ele;
};
}
///////////////////////////////////////////////////
//ADD AVAILABLE PLAYERS TO THE MISTPLAYERS OBJECT//
///////////////////////////////////////////////////
////HTML5////////////////////////////////////////////
var html5 = new MistPlayer();
mistplayers.html5 = html5;
html5.name = 'HTML5 video element';
html5.formimetype = function(fullmimetype){
var t = fullmimetype.split('/');
return ((t[0] == 'html5') && (t[1] == 'video'));
};
html5.supported = function(mimetype) {
var support = false;
try {
var v = document.createElement('video');
if ((v) && (v.canPlayType(mimetype) != "")) {
support = v.canPlayType(mimetype);
}
} catch(e){}
return support;
}
html5.build = function(options){
var ele = this.element('video');
ele.setAttribute('width',options.width);
ele.setAttribute('height',options.height);
ele.setAttribute('src',encodeURI(options.src));
ele.setAttribute('controls','controls');
if (options.autoplay) {
ele.setAttribute('autoplay','controls');
}
ele.mistplay = function(){
this.play();
};
ele.mistpause = function(){
this.pause();
};
ele.mistsetvolume = function(value){
this.volume = value;
};
ele.mistposition = function(){
return this.currentTime;
}
options.container.appendChild(ele);
return ele;
}
////FLASH////////////////////////////////////////////
var flash = new MistPlayer();
mistplayers.flash = flash;
flash.name = 'Flash object';
flash.formimetype = function(fullmimetype){
var t = fullmimetype.split('/');
return (t[0] == 'flash');
};
flash.supported = function(mimetype) {
var version = 0;
try {
// check in the mimeTypes
version = navigator.mimeTypes['application/x-shockwave-flash'].enabledPlugin.description.replace(/([^0-9\.])/g, '').split('.')[0];
} catch(e){}
try {
// for our special friend IE
version = new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable("$version").replace(/([^0-9\,])/g, '').split(',')[0];
} catch(e){}
version = parseInt(version);
return version >= parseInt(mimetype);
}
flash.build = function(options){
var ele = this.element('object');
ele.setAttribute('id',options.name);
ele.setAttribute('width',options.width);
ele.setAttribute('height',options.height);
//set flashvars
var flashvars = {
src: encodeURIComponent(options.src),
controlBarMode: 'floating',
initialBufferTime: 5,
expandedBufferTime: 5,
minContinuousPlaybackTime: 3
};
//set param elements
var params = {
movie: 'http://fpdownload.adobe.com/strobe/FlashMediaPlayback.swf',
flashvars: [],
allowFullScreen: 'true',
allowscriptaccess: 'always',
wmode: 'direct'
};
if (options.autoplay) {
params.autoPlay = 'true';
flashvars.autoPlay = 'true';
}
if (options.islive) {
flashvars.streamType = 'live';
}
if (parseInt(options.mimetype) >= 10) {
params.movie = 'http://fpdownload.adobe.com/strobe/FlashMediaPlayback_101.swf';
}
for (var i in flashvars) {
params.flashvars.push(i+'='+flashvars[i]);
}
params.flashvars = params.flashvars.join('&');
for (var i in params) {
var param = document.createElement('param');
ele.appendChild(param);
param.setAttribute('name',i);
param.setAttribute('value',params[i]);
}
var embed = document.createElement('embed');
embed.setAttribute('name',options.name);
embed.setAttribute('src',params.movie);
embed.setAttribute('type','application/x-shockwave-flash');
embed.setAttribute('allowscriptaccess','always');
embed.setAttribute('allowfullscreen','true');
embed.setAttribute('width',options.width);
embed.setAttribute('height',options.height);
embed.setAttribute('flashvars',params.flashvars);
ele.appendChild(embed);
options.container.appendChild(ele);
return ele;
}
////SILVERLIGHT//////////////////////////////////////
var silverlight = new MistPlayer();
mistplayers.silverlight = silverlight;
silverlight.name = 'Silverlight';
silverlight.formimetype = function(fullmimetype){
return (fullmimetype == 'silverlight');
};
silverlight.supported = function(mimetype) {
var plugin;
try {
// check in the mimeTypes
plugin = navigator.plugins["Silverlight Plug-In"];
return !!plugin;
} catch(e){}
try {
// for our special friend IE
plugin = new ActiveXObject('AgControl.AgControl');
return true;
} catch(e){}
return false;
}
silverlight.build = function(options){
var ele = this.element('object');
ele.setAttribute('data','data:application/x-silverlight,'); //yes that comma needs to be there
ele.setAttribute('type','application/x-silverlight');
ele.setAttribute('width',options.width);
ele.setAttribute('height',options.height);
var params = {
source: encodeURI(options.src),
onerror: 'onSilverlightError',
autoUpgrade: 'true',
background: 'black',
enableHtmlAccess: 'true',
minRuntimeVersion: '3.0.40624.0',
initparams: []
};
var initparams = {
autoload: 'false',
enablecaptions: 'true',
joinLive: 'true',
muted: 'false',
playlist: document.createElement('playList')
};
if (options.autoplay) {
initparams.autoplay = 'true';
}
var playitems = document.createElement('playListItems');
initparams.playlist.appendChild(playitems);
var playitem = document.createElement('playListItem');
playitems.appendChild(playitem);
playitems.setAttribute('mediaSource',encodeURI(options.src));
playitems.setAttribute('adaptiveStreaming','true');
initparams.playlist = initparams.playlist.outerHTML;
for (var i in initparams) {
params.initparams.push(i+'='+initparams[i]);
}
params.initparams = params.initparams.join(',');
for (var i in params) {
var param = document.createElement('param');
ele.appendChild(param);
param.setAttribute('name',i);
param.setAttribute('value',params[i]);
}
ele.innerHTML += '<a href="http://go.microsoft.com/fwlink/?LinkID=124807" style="text-decoration: none;"><img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight" style="border-style: none" /></a>';
options.container.appendChild(ele);
return ele;
}
} //end of player definitions
function mistembed(streamname) {
function findPlayer(fullmimetype) {
for (var i in mistplayers) {
if (mistplayers[i].formimetype(fullmimetype)) {
return mistplayers[i];
}
}
return false;
}
var video = mistvideo[streamname];
container = document.createElement('div'),
scripts = document.getElementsByTagName('script'),
me = scripts[scripts.length - 1];
if (me.parentNode.hasAttribute('data-forcetype')) {
var forceType = me.parentNode.getAttribute('data-forcetype');
}
if (me.parentNode.hasAttribute('data-forcesupportcheck')) {
var forceSupportCheck = true;
}
if (me.parentNode.hasAttribute('data-autoplay')) {
var autoplay = true;
}
// create the container
me.parentNode.insertBefore(container, me);
// set the class to 'mistvideo'
container.setAttribute('class', 'mistvideo');
// remove script tag
me.parentNode.removeChild(me);
if(video.error) {
// there was an error; display it
container.innerHTML = '<strong>Error: '+video.error+'</strong>';
}
else if ((typeof video.source == 'undefined') || (video.source.length < 1)) {
// no stream sources
container.innerHTML = '<strong>Error: no protocols found</strong>';
}
else {
// no error, and sources found. Check the video types and output the best
// available video player.
var foundPlayer = false;
for (var i in video.source) {
if ((forceType) && (video.source[i].type.indexOf(forceType) < 0)) {
video.source[i].rejected = 'This source type is not the one being forced.';
continue;
}
var player = findPlayer(video.source[i].type);
var shortmime = video.source[i].type.split('/');
shortmime.shift();
shortmime = shortmime.join('/');
video.source[i].browser_support = false;
if (player) {
var support = player.supported(shortmime);
if ((support) || (forceType)) {
//either the player is supported by the browser, or this source type is being enforced
video.source[i].browser_support = Boolean(support);
if (foundPlayer === false) {
foundPlayer = {
protocol: video.source[i],
player: player,
shortmime: shortmime
};
}
if (!forceSupportCheck) {
break;
}
}
else {
video.source[i].rejected = 'The player for this source type ('+player.name+') is not supported by your browser.';
}
}
else {
video.source[i].rejected = 'No compatible player found for this source type.';
}
}
}
if (foundPlayer) {
// we support this kind of video, so build it.
//calculations for the size
videowidth = video.width || 250;
videoheight = video.height || 250;
var ratio;
var containerwidth = parseInt(container.scrollWidth);
var containerheight = parseInt(container.scrollHeight);
if(videowidth > containerwidth && containerwidth > 0) {
ratio = videowidth / containerwidth;
videowidth /= ratio;
videoheight /= ratio;
}
if(videoheight > containerheight && containerheight > 0) {
ratio = videoheight / containerheight;
videowidth /= ratio;
videoheight /= ratio;
}
video.embedded = foundPlayer.player.build({
container: container,
width: videowidth,
height: videoheight,
src: foundPlayer.protocol.url,
name: streamname,
mimetype: foundPlayer.shortmime,
islive: (video.type == 'live'),
autoplay: autoplay
});
return foundPlayer.protocol.type;
}
else {
// of all the source types given, none was supported (eg. no flash and HTML5 video). Display error
container.innerHTML = '<strong>No support for any player found</strong>';
}
return false;
}

View file

@ -1,139 +0,0 @@
<html>
<head>
<title></title>
<meta content="">
<style>
#vidcontainer {
display: flex;
flex-flow: row wrap;
justify-content: space-around;
}
#vidcontainer .track {
overflow: hidden;
display: flex;
flex-flow: column nowrap;
align-items: center;
}
#vidcontainer .track .trackname {
flex-shrink: 0;
display: none; /* comment this to show trackname */
}
</style>
</head>
<body>
<div id=vidcontainer>
</div>
<script>
var vidname = 'multibitrate'; // change this to the appropriate stream name
var embedbase = 'http://localhost:8080/'; //change this to the appropriate host (with http port)
//load the info script
var script = document.createElement('script');
script.src = embedbase+'info_'+vidname+'.js';
script.onerror = function(){
document.getElementById('vidcontainer').innerHTML = 'Error loading "'+script.src+'".';
};
script.onload = function(){
multitrack(vidname);
}
document.getElementById('vidcontainer').appendChild(script);
function multitrack(vidname) {
if (typeof mistvideo[vidname] != 'undefined') {
var vid = mistvideo[vidname];
var audio = false;
vid.elements = [];
if (typeof vid.meta.tracks != 'undefined') {
var cont = document.getElementById('vidcontainer');
var n = 0;
var width = cont.offsetWidth * .49;
for (var i in vid.meta.tracks) {
var track = vid.meta.tracks[i];
n++;
if (track.type != 'video') {
continue;
}
var child = document.createElement('div');
child.className = 'track';
child.innerHTML = '<span class=trackname>'+i+'</span>';
var sources = [];
var rtmp = '';
for (var j in vid.source) {
if (vid.source[j].type == 'flash/10') {
rtmp = vid.source[j].url+'?video='+n+'&audio='+(audio ? '0' : '-1');
}
else {
sources.push('<source src="'+vid.source[j].url+'?video='+n+'&audio='+(audio ? '0' : '-1')+'">');
}
}
//check html mp4 support
var support = false;
/*try {
var v = document.createElement('video');
if( v && v.canPlayType('video/mp4') != "" ){
support = true;
}
} catch(e){}*/
var height = width / track.width * track.height;
if (support) {
//HTML5 MP4 embed
var video = document.createElement('video');
video.setAttribute('style','width:'+width+'px; height:'+height+'px;');
if (!audio) {
video.setAttribute('controls','');
video.addEventListener('play',function(){
for (var i in vid.elements) {
if (vid.elements[i].paused) {
vid.elements[i].play();
}
}
});
video.addEventListener('pause',function(){
for (var i in vid.elements) {
if (!vid.elements[i].paused) {
vid.elements[i].pause();
}
}
});
audio = true;
}
else {
//just in case..
video.volume = 0;
}
video.innerHTML = sources.join('');
}
else {
//go for RTMP (Flash/10) instead
var video = document.createElement('object');
video.setAttribute('width',width);
video.setAttribute('height',height);
var url = encodeURIComponent(rtmp)+'&controlBarMode=floating&initialBufferTime=0.5&expandedBufferTime=5&autoPlay=true&minContinuousPlaybackTime=3' + (vid.type == 'live' ? "&streamType=live" : "");
var params = [];
params.push('<param name="movie" value="http://fpdownload.adobe.com/strobe/FlashMediaPlayback_101.swf"></param>');
params.push('<param name="flashvars" value="src='+url+'"></param>');
params.push('<param name="allowFullScreen" value="true"></param>');
params.push('<param name="allowscriptaccess" value="always"></param>');
params.push('<param name="wmode" value="direct"></param>');
params.push('<param name="autoPlay" value="true">');
params.push('<embed src="http://fpdownload.adobe.com/strobe/FlashMediaPlayback_101.swf" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="'+width+'" height="'+height+'" flashvars="src='+url+'"></embed>');
video.innerHTML = params.join('');
}
child.appendChild(video);
vid.elements.push(video);
cont.appendChild(child);
}
}
}
};
</script>
</body>
</html>

View file

@ -1,49 +0,0 @@
<html>
<head>
<title>Test the stream embedding</title>
<style></style>
<script src=plugins/jquery.js></script>
<!--<script src='../src/embed.js'></script>-->
<script src='newembed.js'></script>
<script>
var embed_settings = {};
$(function(){
$('button#embed').click(function(){
$('#embedcontainer, #button_container').html('');
var streamName = $('input[name=streamName]').val();
var embedtype = $('input[name=force]').val();
var info = document.createElement('script');
info.src = 'http://localhost:8080/info_'+streamName+'.js';
document.getElementById('embedcontainer').appendChild(info);
info.onload = function(){
if (embedtype == '') {
$('#embedcontainer').removeAttr('data-forcetype');
}
else {
$('#embedcontainer').attr('data-forcetype',embedtype);
}
$('#embedcontainer').append(
$('<div>').text('Embedded: '+mistembed(streamName))
);
console.log(mistvideo[streamName]);
};
});
});
</script>
</head>
<body>
<label>
Enter the streamname: <input type=text value=bunny name=streamName>
</label><br>
<label>
Force embed type: <input type=text name=force> (blank for auto)
</label><br>
<button id=embed>Embed</button>
<div id=button_container></div>
<div id=embedcontainer style="width: 100%; height: 35em;" data-forcesupportcheck data-autoplay>
</div>
</body>
</html>

View file

@ -1,48 +0,0 @@
<html>
<head>
<title>Test the stream embedding</title>
<style></style>
<script src=plugins/jquery.js></script>
<script src='../src/embed.js?video=0'></script>
<script>
var embed_settings = {};
$(function(){
$('button#embed').click(function(){
$('#embedcontainer, #button_container').html('');
var streamName = $('input[name=streamName]').val();
var embedtype = $('input[name=force]').val();
var info = document.createElement('script');
info.src = 'http://'+(window.location.hostname == '' ? 'localhost' : window.location.hostname)+':8080/info_'+encodeURIComponent(streamName)+'.js';
document.getElementById('embedcontainer').appendChild(info);
info.onload = function(){
if (embedtype == '') {
$('#embedcontainer').removeAttr('data-forcetype');
}
else {
$('#embedcontainer').attr('data-forcetype',embedtype);
}
$('#embedcontainer').append(
$('<div>').text('Embedded: '+mistembed(streamName))
);
console.log(mistvideo[streamName]);
};
});
});
</script>
</head>
<body>
<label>
Enter the streamname: <input type=text value=bunny name=streamName>
</label><br>
<label>
Force embed type: <input type=text name=force> (blank for auto)
</label><br>
<button id=embed>Embed</button>
<div id=button_container></div>
<div id=embedcontainer style="width: 100%; height: 35em;" data-forcesupportcheck data-autoplay>
</div>
</body>
</html>