Merge branch 'development' into LTS_development

This commit is contained in:
Thulinma 2018-12-19 15:47:22 +01:00
commit c926637aec
62 changed files with 9123 additions and 49744 deletions

View file

@ -1,327 +0,0 @@
function mistembed(streamname) {
//find the current script
var me;
if (('currentScript' in document) && (document.currentScript)) {
me = document.currentScript;
//not supported in old browsers :(
}
else {
var scripts = document.getElementsByTagName('script');
me = scripts[scripts.length - 1];
//not correct if the script is inserted dynamically, but this is how it used to be
}
// return the current flash version
function flash_version() {
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){}
return parseInt(version, 10);
};
// return true if silverlight is installed
function silverlight_installed() {
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;
};
// return true if the browser thinks it can play the mimetype
function html5_video_type(type) {
var support = false;
if (type == 'video/mp4') {
if ((navigator.userAgent.indexOf('MSIE') > -1) && (parseInt(navigator.userAgent.split('MSIE')[1]) <= 9)) {
//IE <= 9 doesn't support MP4, Firefox seems to correctly see it now.
return false;
}
if (navigator.userAgent.indexOf('Firefox') > -1) {
//firefox claims to support MP4 but doesn't when:
// - under win xp
// - the stream is live
if (video.type == 'live') {
return false;
}
//find "Windows NT X;" in user userAgent
//sorry, I don't like regexes.. I avoid them when I can :$
var s = navigator.userAgent.split('Windows NT ');
if (s.length > 1) {
s = s[1].split(';');
s = s[0];
if (Number(s) <= 5.1) {
return false;
}
}
}
}
try {
var v = document.createElement('video');
if( v && v.canPlayType(type) != "" )
{
support = true; // true-ish, anyway
}
} catch(e){}
return support;
}
//return true if rtsp is supported
function rtsp_support() {
var plugin;
try {
// check in the mimeTypes
plugin = navigator.mimeTypes["application/x-google-vlc-plugin"];
return !!plugin;
} catch(e){}
try {
// for our special friend IE
plugin = new ActiveXObject('VideoLAN.Vlcplugin.1');
return true;
} catch(e){}
return false;
}
// parse a "type" string from the controller. Format:
// xxx/# (e.g. flash/3) or xxx/xxx/xxx (e.g. html5/application/ogg)
function parseType(type) {
var split = type.split('/');
if( split.length > 2 ) {
split[1] += '/' + split[2];
}
return split;
}
// return true if a type is supported
function hasSupport(type) {
var typemime = parseType(type);
switch(typemime[0]) {
case 'flash': return flash_version() >= parseInt(typemime[1], 10); break;
case 'html5': return html5_video_type(typemime[1]); break;
case 'rtsp': return rtsp_support(); break;
case 'silverlight': return silverlight_installed(); break;
default: return false; break;
}
}
// build HTML for certain kinds of types
function buildPlayer(src, container, videowidth, videoheight, vtype) {
// used to recalculate the width/height
var ratio;
// get the container's width/height
var containerwidth = parseInt(container.clientWidth, 10);
var containerheight = parseInt(container.clientHeight, 10);
if(videowidth > containerwidth && containerwidth > 0) {
ratio = videowidth / containerwidth;
videowidth /= ratio;
videoheight /= ratio;
}
if(videoheight > containerheight && containerheight > 0) {
ratio = videoheight / containerheight;
videowidth /= ratio;
videoheight /= ratio;
}
var maintype = parseType(src.type);
mistvideo[streamname].embedded = src;
switch(maintype[0]) {
case 'flash':
// maintype[1] is already checked (i.e. user has version > maintype[1])
var flashplayer,
url = encodeURIComponent(src.url) + '&controlBarMode=floating&initialBufferTime=0.5&expandedBufferTime=5&minContinuousPlaybackTime=3' + (vtype == 'live' ? "&streamType=live" : "") + (autoplay ? '&autoPlay=true' : '');
/*
if( parseInt(maintype[1], 10) >= 10 ) {
flashplayer = 'http://fpdownload.adobe.com/strobe/FlashMediaPlayback_101.swf';
}
else {
flashplayer = 'http://fpdownload.adobe.com/strobe/FlashMediaPlayback.swf';
}
*/
flashplayer = src.player_url;
container.innerHTML += '<object width="' + videowidth + '" height="' + videoheight + '">' +
'<param name="movie" value="' + flashplayer + '"></param>' +
'<param name="flashvars" value="src=' + url + '"></param>' +
'<param name="allowFullScreen" value="true"></param>' +
'<param name="allowscriptaccess" value="always"></param>' +
'<param name="wmode" value="direct"></param>' +
(autoplay ? '<param name="autoPlay" value="true">' : '') +
'<embed src="' + flashplayer + '" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="' + videowidth + '" height="' + videoheight + '" flashvars="src=' + url + '"></embed>' +
'</object>';
break;
case 'html5':
container.innerHTML += '<video width="' + videowidth + '" height="' + videoheight + '" src="' + src.url + '" controls="controls" '+(autoplay ? 'autoplay="autoplay"' : '')+'><strong>No HTML5 video support</strong></video>';
break;
case 'rtsp':
/*container.innerHTML += '<object classid="clsid:CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA" width="'+videowidth+'" height="'+videoheight+'">'+
'<param name="src" value="'+encodeURI(src.url)+'">'+
'<param name="console" value="video1">'+
'<param name="controls" value="All">'+
'<param name="autostart" value="false">'+
'<param name="loop" value="false">'+
'<embed name="myMovie" src="'+encodeURI(src.url)+'" width="'+videowidth+'" height="'+videoheight+'" autostart="false" loop="false" nojava="true" console="video1" controls="All"></embed>'+
'<noembed>Something went wrong.</noembed>'+
'</object>'; //realplayer, doesnt work */
container.innerHTML += '<embed type="application/x-google-vlc-plugin"'+
'pluginspage="http://www.videolan.org"'+
'width="'+videowidth+'"'+
'height="'+videoheight+'"'+
'target="'+encodeURI(src.url)+'"'+
'autoplay="'+(autoplay ? 'yes' : 'no')+'"'+
'>'+
'</embed>'+
'<object classid="clsid:9BE31822-FDAD-461B-AD51-BE1D1C159921" codebase="http://downloads.videolan.org/pub/videolan/vlc/latest/win32/axvlc.cab">'+
'</object>'; //vlc, seems to work, sort of. it's trying anyway
break;
case 'silverlight':
container.innerHTML += '<object data="data:application/x-silverlight," type="application/x-silverlight" width="' + videowidth + '" height="' + videoheight + '">'+
'<param name="source" value="' + encodeURI(src.url) + '/player.xap"/>'+
'<param name="onerror" value="onSilverlightError" />'+
'<param name="autoUpgrade" value="true" />'+
'<param name="background" value="white" />'+
'<param name="enableHtmlAccess" value="true" />'+
'<param name="minRuntimeVersion" value="3.0.40624.0" />'+
'<param name="initparams" value =\'autoload=false,'+(autoplay ? 'autoplay=true' : 'autoplay=false')+',displaytimecode=false,enablecaptions=true,joinLive=true,muted=false,playlist=<playList><playListItems><playListItem title="Test" description="testing" mediaSource="' + encodeURI(src.url) + '" adaptiveStreaming="true" thumbSource="" frameRate="25.0" width="" height=""></playListItem></playListItems></playList>\' />'+
'<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>'+
'</object>';
break;
default:
container.innerHTML += '<strong>Missing embed code for output type "'+src.type+'"</strong>';
video.error = 'Missing embed code for output type "'+src.type;
}
}
var video = mistvideo[streamname],
container = document.createElement('div'),
forceType = false,
forceSupportCheck = false,
autoplay = true,
urlappend = false;
if (me.parentNode.hasAttribute('data-forcetype')) {
forceType = me.parentNode.getAttribute('data-forcetype');
}
if (me.parentNode.hasAttribute('data-forcesupportcheck')) {
forceSupportCheck = true;
}
if (me.parentNode.hasAttribute('data-noautoplay')) {
autoplay = false;
}
if (me.parentNode.hasAttribute('data-urlappend')) {
urlappend = me.parentNode.getAttribute('data-urlappend');
}
if (video.width == 0) { video.width = 250; }
if (video.height == 0) { video.height = 250; }
// 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
if (video.on_error){
container.innerHTML = video.on_error;
}else{
container.innerHTML = ['<strong>Error: ', video.error, '</strong>'].join('');
}
}
else if ((typeof video.source == 'undefined') || (video.source.length < 1)) {
// no stream sources
if (video.on_error){
container.innerHTML = video.on_error;
}else{
container.innerHTML = '<strong>Error: no active source or compatible protocols for this stream</strong>';
}
}
else {
// no error, and sources found. Check the video types and output the best
// available video player.
var i,
vtype = (video.type ? video.type : 'unknown'),
foundPlayer = false,
len = video.source.length;
for (var i in video.source) {
var support = hasSupport(video.source[i].type);
video.source[i].browser_support = support;
if ((support) || (forceType)) {
if ((!forceType) || ((forceType) && (video.source[i].type.indexOf(forceType) >= 0))) {
if (foundPlayer === false) {
foundPlayer = i;
if (!forceSupportCheck) {
break;
}
}
}
}
}
if (foundPlayer === false) {
// of all the streams given, none was supported (eg. no flash and HTML5 video). Display error
container.innerHTML = '<strong>No support for any player found</strong>';
}
else {
// we support this kind of video, so build it.
var source = video.source[foundPlayer];
if (urlappend) {
source.url += urlappend;
source.relurl += urlappend;
}
else if (me.src.indexOf('?') != -1) {
var params = me.src.split('?');
params.shift();
params.join('?');
source.url += '?'+params;
source.relurl += '?'+params;
}
buildPlayer(source, container, video.width, video.height, vtype);
}
}
return (mistvideo[streamname].embedded ? mistvideo[streamname].embedded.type : false);
//keep empty line at end of file
}

View file

@ -123,9 +123,12 @@ namespace Mist {
capa["url_match"].append("/info_$.js");
capa["url_match"].append("/json_$.js");
capa["url_match"].append("/player.js");
capa["url_match"].append("/player.css");
capa["url_match"].append("/videojs.js");
capa["url_match"].append("/dashjs.js");
capa["url_match"].append("/webrtc.js");
capa["url_match"].append("/skins/default.css");
capa["url_match"].append("/skins/dev.css");
capa["url_match"].append("/skins/videojs.css");
capa["url_match"].append("/embed_$.js");
capa["url_match"].append("/flashplayer.swf");
capa["url_match"].append("/oldflashplayer.swf");
@ -133,15 +136,11 @@ namespace Mist {
capa["optional"]["wrappers"]["help"] = "Which players are attempted and in what order.";
capa["optional"]["wrappers"]["default"] = "";
capa["optional"]["wrappers"]["type"] = "ord_multi_sel";
/*capa["optional"]["wrappers"]["allowed"].append("theoplayer");
capa["optional"]["wrappers"]["allowed"].append("jwplayer");*/
capa["optional"]["wrappers"]["allowed"].append("html5");
capa["optional"]["wrappers"]["allowed"].append("videojs");
capa["optional"]["wrappers"]["allowed"].append("dashjs");
//capa["optional"]["wrappers"]["allowed"].append("polytrope"); //currently borked
capa["optional"]["wrappers"]["allowed"].append("webrtc");
capa["optional"]["wrappers"]["allowed"].append("flash_strobe");
capa["optional"]["wrappers"]["allowed"].append("silverlight");
capa["optional"]["wrappers"]["allowed"].append("img");
capa["optional"]["wrappers"]["option"] = "--wrappers";
capa["optional"]["wrappers"]["short"] = "w";
cfg->addConnectorOptions(8080, capa);
@ -326,6 +325,10 @@ namespace Mist {
}
/*LTS-END*/
std::string uAgent = H.GetHeader("User-Agent");
std::string devSkin = "";
if (H.GetVar("dev").size()) { devSkin = ",skin:\"dev\""; }
H.Clean();
H.SetHeader("Content-Type", "text/html");
H.SetHeader("Server", "MistServer/" PACKAGE_VERSION);
@ -339,7 +342,7 @@ namespace Mist {
std::string hlsUrl = "/hls/"+streamName+"/index.m3u8";
std::string mp4Url = "/"+streamName+".mp4";
H.SetBody("<!DOCTYPE html><html><head><title>"+streamName+"</title><style>body{color:white;background:black;}</style></head><body><div class=mistvideo id=\""+streamName+"\"><noscript><video controls autoplay><source src=\""+hlsUrl+"\" type=\"application/vnd.apple.mpegurl\"><source src=\""+mp4Url+"\" type=\"video/mp4\"><a href=\""+hlsUrl+"\">Click here to play the video [Apple]</a><br><a href=\""+mp4Url+"\">Click here to play the video [MP4]</a></video></noscript><script src=\"player.js\"></script><script>mistPlay('"+streamName+"',{host:'"+fullURL.getUrl()+"',target:document.getElementById('"+streamName+"')})</script></div></body></html>");
H.SetBody("<!DOCTYPE html><html><head><title>"+streamName+"</title><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><style>html{margin:0;padding:0;display:table;width:100%;height:100%;}body{color:white;background:#0f0f0f;margin:0;padding:0;display:table-cell;vertical-align:middle;text-align:center}body>div>div{text-align:left;}</style></head><body><div class=mistvideo id=\""+streamName+"\"><noscript><video controls autoplay><source src=\""+hlsUrl+"\" type=\"application/vnd.apple.mpegurl\"><source src=\""+mp4Url+"\" type=\"video/mp4\"><a href=\""+hlsUrl+"\">Click here to play the video [Apple]</a><br><a href=\""+mp4Url+"\">Click here to play the video [MP4]</a></video></noscript><script src=\"player.js\"></script><script>mistPlay('"+streamName+"',{host:'"+fullURL.getUrl()+"',target:document.getElementById('"+streamName+"')"+devSkin+"})</script></div></body></html>");
if ((uAgent.find("iPad") != std::string::npos) || (uAgent.find("iPod") != std::string::npos) || (uAgent.find("iPhone") != std::string::npos)) {
H.SetHeader("Location",hlsUrl);
H.SendResponse("307", "HLS redirect", myConn);
@ -613,7 +616,7 @@ namespace Mist {
return;
}
if ((H.url.length() > 9 && H.url.substr(0, 6) == "/info_" && H.url.substr(H.url.length() - 3, 3) == ".js") || (H.url.length() > 10 && H.url.substr(0, 7) == "/embed_" && H.url.substr(H.url.length() - 3, 3) == ".js") || (H.url.length() > 9 && H.url.substr(0, 6) == "/json_" && H.url.substr(H.url.length() - 3, 3) == ".js")){
if ((H.url.length() > 9 && H.url.substr(0, 6) == "/info_" && H.url.substr(H.url.length() - 3, 3) == ".js") || (H.url.length() > 9 && H.url.substr(0, 6) == "/json_" && H.url.substr(H.url.length() - 3, 3) == ".js")){
if (websocketHandler()){return;}
std::string reqHost = HTTP::URL(H.GetHeader("Host")).host;
std::string useragent = H.GetVar("ua");
@ -645,24 +648,13 @@ namespace Mist {
}else{
response = json_resp.toString();
}
if (rURL.substr(0, 7) == "/embed_" && !json_resp.isMember("error")){
#include "embed.js.h"
response.append("\n(");
if (embed_js[embed_js_len - 2] == ';'){//check if we have a trailing ;\n or just \n
response.append((char*)embed_js, (size_t)embed_js_len - 2); //remove trailing ";\n" from xxd conversion
}else{
response.append((char*)embed_js, (size_t)embed_js_len - 1); //remove trailing "\n" from xxd conversion
}
response.append("(\"" + streamName + "\"));\n");
}
H.SetBody(response);
H.SendResponse("200", "OK", myConn);
H.Clean();
return;
} //embed code generator
if (H.url == "/player.js"){
if ((H.url == "/player.js") || ((H.url.substr(0, 7) == "/embed_") && (H.url.length() > 10) && (H.url.substr(H.url.length() - 3, 3) == ".js"))){
HTTP::URL fullURL(H.GetHeader("Host"));
if (!fullURL.protocol.size()){
fullURL.protocol = getProtocolForPort(fullURL.getPort());
@ -681,7 +673,7 @@ namespace Mist {
H.Clean();
H.SetHeader("Server", "MistServer/" PACKAGE_VERSION);
H.setCORSHeaders();
H.SetHeader("Content-Type", "application/javascript");
H.SetHeader("Content-Type", "application/javascript; charset=utf-8");
if(method == "OPTIONS" || method == "HEAD"){
H.SendResponse("200", "OK", myConn);
H.Clean();
@ -689,8 +681,10 @@ namespace Mist {
}
response.append("if (typeof mistoptions == 'undefined') { mistoptions = {}; }\nif (!('host' in mistoptions)) { mistoptions.host = '"+fullURL.getUrl()+"'; }\n");
#include "core.js.h"
response.append((char*)core_js, (size_t)core_js_len);
#include "player.js.h"
response.append((char*)player_js, (size_t)player_js_len);
jsonForEach(config->getOption("wrappers",true),it){
bool used = false;
if (it->asStringRef() == "html5"){
@ -703,26 +697,6 @@ namespace Mist {
response.append((char*)flash_strobe_js, (size_t)flash_strobe_js_len);
used = true;
}
if (it->asStringRef() == "silverlight"){
#include "silverlight.js.h"
response.append((char*)silverlight_js, (size_t)silverlight_js_len);
used = true;
}
if (it->asStringRef() == "theoplayer"){
#include "theoplayer.js.h"
response.append((char*)theoplayer_js, (size_t)theoplayer_js_len);
used = true;
}
if (it->asStringRef() == "jwplayer"){
#include "jwplayer.js.h"
response.append((char*)jwplayer_js, (size_t)jwplayer_js_len);
used = true;
}
if (it->asStringRef() == "polytrope"){
#include "polytrope.js.h"
response.append((char*)polytrope_js, (size_t)polytrope_js_len);
used = true;
}
if (it->asStringRef() == "dashjs"){
#include "dashjs.js.h"
response.append((char*)dash_js, (size_t)dash_js_len);
@ -733,9 +707,9 @@ namespace Mist {
response.append((char*)video_js, (size_t)video_js_len);
used = true;
}
if (it->asStringRef() == "img"){
#include "img.js.h"
response.append((char*)img_js, (size_t)img_js_len);
if (it->asStringRef() == "webrtc"){
#include "webrtc.js.h"
response.append((char*)webrtc_js, (size_t)webrtc_js_len);
used = true;
}
if (!used) {
@ -743,6 +717,10 @@ namespace Mist {
}
}
if ((rURL.substr(0, 7) == "/embed_") && (rURL.length() > 10) && (rURL.substr(rURL.length() - 3, 3) == ".js")){
response.append("var container = document.createElement(\"div\");\ncontainer.id = \""+streamName+"\";\ndocument.write(container.outerHTML);\nmistPlay(\""+streamName+"\",{target:document.getElementById(\""+streamName+"\")});");
}
H.SetBody(response);
H.SendResponse("200", "OK", myConn);
H.Clean();
@ -750,8 +728,9 @@ namespace Mist {
}
if (H.url == "/player.css"){
if (H.url.substr(0, 7) == "/skins/"){
std::string response;
std::string url = H.url;
H.Clean();
H.SetHeader("Server", "MistServer/" PACKAGE_VERSION);
H.setCORSHeaders();
@ -762,8 +741,24 @@ namespace Mist {
return;
}
#include "mist.css.h"
response.append((char*)mist_css, (size_t)mist_css_len);
if (url == "/skins/default.css") {
#include "skin_default.css.h"
response.append((char*)skin_default_css, (size_t)skin_default_css_len);
}
else if (url == "/skins/dev.css") {
#include "skin_dev.css.h"
response.append((char*)skin_dev_css, (size_t)skin_dev_css_len);
}
else if (url == "/skins/videojs.css") {
#include "skin_videojs.css.h"
response.append((char*)skin_videojs_css, (size_t)skin_videojs_css_len);
}
else {
H.SetBody("Unknown stylesheet: "+url);
H.SendResponse("404", "Unknown stylesheet", myConn);
H.Clean();
return;
}
H.SetBody(response);
H.SendResponse("200", "OK", myConn);
@ -782,10 +777,8 @@ namespace Mist {
return;
}
#include "playervideo.js.h"
response.append((char*)playervideo_js, (size_t)playervideo_js_len);
#include "playerhlsvideo.js.h"
response.append((char*)playerhlsvideo_js, (size_t)playerhlsvideo_js_len);
#include "player_video.js.h"
response.append((char*)player_video_js, (size_t)player_video_js_len);
H.SetBody(response);
H.SendResponse("200", "OK", myConn);
@ -804,10 +797,30 @@ namespace Mist {
return;
}
#include "playerdashlic.js.h"
response.append((char*)playerdashlic_js, (size_t)playerdashlic_js_len);
#include "playerdash.js.h"
response.append((char*)playerdash_js, (size_t)playerdash_js_len);
#include "player_dash_lic.js.h"
response.append((char*)player_dash_lic_js, (size_t)player_dash_lic_js_len);
#include "player_dash.js.h"
response.append((char*)player_dash_js, (size_t)player_dash_js_len);
H.SetBody(response);
H.SendResponse("200", "OK", myConn);
H.Clean();
return;
}
if (H.url == "/webrtc.js"){
std::string response;
H.Clean();
H.SetHeader("Server", "MistServer/" PACKAGE_VERSION);
H.setCORSHeaders();
H.SetHeader("Content-Type", "application/javascript");
if (method == "OPTIONS" || method == "HEAD"){
H.SendResponse("200", "OK", myConn);
H.Clean();
return;
}
#include "player_webrtc.js.h"
response.append((char*)player_webrtc_js, (size_t)player_webrtc_js_len);
H.SetBody(response);
H.SendResponse("200", "OK", myConn);