mirror of
https://github.com/SrIzan10/vdo.ninja.git
synced 2026-05-01 11:05:24 +00:00
8049 lines
281 KiB
JavaScript
8049 lines
281 KiB
JavaScript
/*
|
|
* Copyright (c) 2024 Steve Seguin. All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by the APGLv3 open-source license
|
|
* that can be found in the LICENSE file in the root of the source
|
|
* tree. Alternative licencing options can be made available on request.
|
|
*
|
|
*/
|
|
/*jshint esversion: 6 */
|
|
async function main() {
|
|
// main asyncronous thread; mostly initializes the user settings.
|
|
|
|
var delayedStartupFuncs = [];
|
|
// translation stuff start ////
|
|
|
|
var ConfigSettings = getById("main-js");
|
|
|
|
try {
|
|
if (ConfigSettings) {
|
|
ln_template = ConfigSettings.getAttribute("data-translation"); // Translations
|
|
if (typeof ln_template === "undefined") {
|
|
ln_template = false;
|
|
} else if (ln_template === null) {
|
|
ln_template = false;
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("ln") || urlParams.has("language")) {
|
|
ln_template = urlParams.get("ln") || urlParams.get("language") || null;
|
|
} else if (session.language) {
|
|
ln_template = session.language;
|
|
}
|
|
} catch (e) {
|
|
errorlog(e);
|
|
}
|
|
if (ln_template === null) {
|
|
getById("mainmenu").style.opacity = 1;
|
|
} else if (ln_template !== false) {
|
|
// checking if manual lanuage override enabled
|
|
try {
|
|
log("Lang Template: " + ln_template);
|
|
await changeLg(ln_template);
|
|
//getById("mainmenu").style.opacity = 1;
|
|
} catch (error) {
|
|
errorlog(error);
|
|
getById("mainmenu").style.opacity = 1;
|
|
}
|
|
}
|
|
if (location.hostname !== "vdo.ninja" && location.hostname !== "backup.vdo.ninja" && location.hostname !== "proxy.vdo.ninja" && location.hostname !== "obs.ninja") {
|
|
errorReport = false;
|
|
|
|
if (location.hostname === "rtc.ninja") {
|
|
try {
|
|
if (session.label === false) {
|
|
document.title = "RTC.Ninja";
|
|
}
|
|
getById("qos").innerHTML = "";
|
|
getById("logoname").innerHTML = "";
|
|
getById("helpbutton").style.display = "none";
|
|
getById("helpbutton").style.opacity = 0;
|
|
getById("reportbutton").style.display = "none";
|
|
getById("reportbutton").style.opacity = 0;
|
|
getById("dropButton").classList.add("hidden");
|
|
getById("container-4").classList.add("hidden");
|
|
if (!(urlParams.has("screenshare") || urlParams.has("ss"))) {
|
|
getById("container-2").classList.add("hidden");
|
|
}
|
|
//getById("mainmenu").style.opacity = 1;
|
|
getById("mainmenu").style.margin = "30px 0";
|
|
getById("translateButton").style.display = "none";
|
|
getById("translateButton").style.opacity = 0;
|
|
getById("info").style.display = "none";
|
|
getById("info").style.opacity = 0;
|
|
getById("chatBody").innerHTML = "";
|
|
} catch (e) {}
|
|
} else if (session.label === false) {
|
|
document.title = location.hostname;
|
|
}
|
|
try {
|
|
if (ln_template === false) {
|
|
changeLg("blank");
|
|
}
|
|
//getById("mainmenu").style.opacity = 1;
|
|
|
|
getById("qos").innerHTML = '<i class="las la-plug"></i>';
|
|
getById("logoname").innerHTML = getById("qos").outerHTML;
|
|
getById("helpbutton").style.display = "none";
|
|
getById("reportbutton").style.display = "none";
|
|
getById("chatBody").innerHTML = "";
|
|
getById("qos").style.color = "#FFF0";
|
|
getById("qos").style.fontSize = "70%";
|
|
getById("logoname").style.display = "none";
|
|
getById("logoname").style.margin = "0 0 0 5px";
|
|
} catch (error) {
|
|
getById("mainmenu").style.opacity = 1;
|
|
errorlog(error);
|
|
}
|
|
} else {
|
|
// check if automatic language translation is available
|
|
getById("mainmenu").style.opacity = 1;
|
|
}
|
|
|
|
//// translation stuff ends ////
|
|
|
|
if (urlParams.has("cleanoutput") || urlParams.has("clean") || urlParams.has("cleanish")) {
|
|
session.cleanOutput = true;
|
|
}
|
|
if (urlParams.has("mutestatus") || urlParams.has("showmutestate") || urlParams.has("showmuted")){
|
|
session.showMuteState = true;
|
|
}
|
|
|
|
if (urlParams.has("cleanviewer") || urlParams.has("cv")) {
|
|
session.cleanViewer = true;
|
|
}
|
|
|
|
if (session.cleanOutput || session.cleanViewer) {
|
|
session.audioMeterGuest = false;
|
|
}
|
|
|
|
if (urlParams.has("hidehome")) {
|
|
session.hidehome = true;
|
|
}
|
|
hideHomeCheck();
|
|
|
|
if (urlParams.has("previewmode")) {
|
|
session.switchMode = true;
|
|
}
|
|
try {
|
|
if (sessionStorage.getItem("deleteWhipOnLoad")) {
|
|
let deleteWhip = sessionStorage.getItem("deleteWhipOnLoad");
|
|
deleteWhip = JSON.parse(deleteWhip);
|
|
if (deleteWhip.location) {
|
|
try {
|
|
let xhttp = new XMLHttpRequest();
|
|
xhttp.open("DELETE", deleteWhip.location, true);
|
|
if (deleteWhip.whipOutputToken) {
|
|
xhttp.setRequestHeader("Authorization", "Bearer " + deleteWhip.whipOutputToken);
|
|
}
|
|
xhttp.send();
|
|
} catch(e){
|
|
log(e);
|
|
}
|
|
}
|
|
sessionStorage.removeItem("deleteWhipOnLoad");
|
|
}
|
|
} catch (e) {
|
|
errorlog(e);
|
|
}
|
|
|
|
if (urlParams.has("director") || urlParams.has("dir")) {
|
|
session.director = urlParams.get("director") || urlParams.get("dir") || session.roomid || urlParams.get("roomid") || urlParams.get("r") || urlParams.get("room") || filename || true;
|
|
session.effect = null; // so the director can see the effects after a page refresh
|
|
getById("avatarDiv3").classList.remove("hidden"); // lets the director see the avatar option
|
|
}
|
|
|
|
if (urlParams.has("controls") || urlParams.has("videocontrols")) {
|
|
session.showControls = true; // show the video control bar
|
|
|
|
if (urlParams.get("controls") === "false") {
|
|
session.showControls = false;
|
|
} else if (urlParams.get("controls") === "0") {
|
|
session.showControls = false;
|
|
} else if (urlParams.get("controls") === "off") {
|
|
session.showControls = false;
|
|
}
|
|
}
|
|
if (urlParams.has("forcecontrols")) {
|
|
session.showControls = 2;
|
|
function keepControls() {
|
|
var tmp = document.activeElement;
|
|
document.querySelectorAll("video").forEach(ele => {
|
|
ele.focus();
|
|
ele.removeAttribute("controls");
|
|
ele.setAttribute("controls", "");
|
|
});
|
|
tmp.focus();
|
|
}
|
|
getById("main").classList.add("forcecontrols");
|
|
setInterval(function () {
|
|
keepControls();
|
|
}, 100);
|
|
}
|
|
if (urlParams.has("nocontrols")) {
|
|
session.showControls = false; // show the video control bar
|
|
}
|
|
|
|
if (!isIFrame && !window.obsstudio) {
|
|
if (ChromiumVersion === 65) {
|
|
// pass, since probably manycam and that's bugged
|
|
} else if (getStorage("redirect") == "yes") {
|
|
setStorage("redirect", "", 0);
|
|
session.sticky = true;
|
|
} else if (getStorage("settings") != "") {
|
|
var URLGOTO = getStorage("settings");
|
|
if (URLGOTO && URLGOTO.startsWith("https://")) {
|
|
if (URLGOTO === window.location.href) {
|
|
// continue, as its already matched
|
|
} else if (!session.cleanOutput) {
|
|
window.focus();
|
|
document.body.classList.remove("hidden");
|
|
|
|
session.sticky = await confirmAlt("Would you like to load your previous session?\n\nThis will redirect you to:\n\n" + URLGOTO, true);
|
|
if (!session.sticky) {
|
|
setStorage("settings", "", 0);
|
|
log("deleting cookie as user said no");
|
|
} else {
|
|
var cookieSettings = decodeURI(URLGOTO);
|
|
setStorage("redirect", "yes", 1);
|
|
window.location.replace(cookieSettings);
|
|
}
|
|
} else {
|
|
var cookieSettings = decodeURI(URLGOTO);
|
|
setStorage("redirect", "yes", 1);
|
|
window.location.replace(cookieSettings);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("sticky")) {
|
|
// won't work with iframes.
|
|
|
|
//if (getStorage("permission") == "") {
|
|
// session.sticky = confirm("Would you allow us to store a cookie to keep your session settings persistent?");
|
|
//} else {
|
|
session.sticky = true;
|
|
|
|
getById("saveRoom").style.display = "none";
|
|
//}
|
|
//if (session.sticky) {
|
|
setStorage("permission", "yes", 999);
|
|
setStorage("settings", encodeURI(window.location.href), 90);
|
|
//}
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("safemode")) {
|
|
session.safemode = true; // load defa
|
|
} else {
|
|
session.store = {};
|
|
try {
|
|
loadSettings();
|
|
} catch (e) {
|
|
errorlog(e);
|
|
}
|
|
}
|
|
|
|
if (navigator.userAgent.toLowerCase().indexOf(" electron/") > -1) {
|
|
try {
|
|
//getById("electronDragZone").style.cursor="grab";
|
|
//getById("header").style.height = "max(calc(2% + 20px), 40px)";
|
|
if (!ipcRenderer) {
|
|
ipcRenderer = require("electron").ipcRenderer;
|
|
}
|
|
if (ipcRenderer) {
|
|
window.prompt = function (title, val) {
|
|
return ipcRenderer.sendSync("prompt", { title, val }); // call if needed in the future
|
|
};
|
|
}
|
|
//ipcRenderer.sendSync('prompt', {title, val}); // call now -- but why?
|
|
} catch (e) {}
|
|
}
|
|
|
|
if (window.electronApi && window.electronApi.exposeDoSomethingInWebApp) {
|
|
window.electronApi.exposeDoSomethingInWebApp(function (fauxEventData) {
|
|
//alert("WORKS");
|
|
//errorlog("WORKS!");
|
|
session.remoteInterfaceAPI(fauxEventData);
|
|
});
|
|
window.electronApi.updateVersion(session.version);
|
|
}
|
|
|
|
if (urlParams.has("retrytimeout")) {
|
|
session.retryTimeout = parseInt(urlParams.get("retrytimeout")) || 5000;
|
|
if (session.retryTimeout < 5000) {
|
|
session.retryTimeout = 5000;
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("ptz")) {
|
|
session.ptz = true;
|
|
}
|
|
|
|
if (urlParams.has("notios")) {
|
|
iOS = false;
|
|
iPad = false;
|
|
}
|
|
|
|
if (urlParams.has("optimize")) {
|
|
session.optimize = parseInt(urlParams.get("optimize")) || 0;
|
|
}
|
|
|
|
if (urlParams.has("nosettings") || urlParams.has("ns")) {
|
|
session.screensharebutton = false;
|
|
session.showSettings = false;
|
|
}
|
|
|
|
if (urlParams.has("nomicbutton") || urlParams.has("nmb")) {
|
|
getById("mutebutton").style.setProperty("display", "none", "important");
|
|
}
|
|
|
|
if (urlParams.has("novice")) {
|
|
// Hiding advanced items
|
|
document.querySelectorAll(".advanced").forEach(element => {
|
|
element.classList.add("hide");
|
|
});
|
|
}
|
|
|
|
if (urlParams.has("userbackgroundimage") || urlParams.has("userbgimage") || urlParams.has("ubgimg")) {
|
|
// URL or data:base64 image. Becomes local to this viewer only.
|
|
let defaultMedia = urlParams.get("userbackgroundimage") || urlParams.get("userbgimage") || urlParams.get("ubgimg") || "./media/backgrounds/1.png";
|
|
if (defaultMedia) {
|
|
try {
|
|
defaultMedia = decodeURIComponent(defaultMedia);
|
|
} catch (e) {}
|
|
session.defaultMedia = defaultMedia;
|
|
try {
|
|
let fallbackImage = new Image();
|
|
fallbackImage.src = defaultMedia;
|
|
} catch (e) {}
|
|
}
|
|
}
|
|
if (urlParams.has("userforegroundimage") || urlParams.has("overlayimage") || urlParams.has("overlayimg")) {
|
|
// URL or data:base64 image. Becomes local to this viewer only.
|
|
let defaultMedia = urlParams.get("userforegroundimage") || urlParams.get("overlayimage") || urlParams.get("overlayimg") || "./media/avatar1.png";
|
|
if (defaultMedia) {
|
|
try {
|
|
defaultMedia = decodeURIComponent(defaultMedia);
|
|
} catch (e) {}
|
|
session.defaultOverlayMedia = defaultMedia;
|
|
try {
|
|
let fallbackImage = new Image();
|
|
fallbackImage.src = defaultMedia;
|
|
} catch (e) {}
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("avatarimg") || urlParams.has("bgimage") || urlParams.has("bgimg")) {
|
|
// URL or data:base64 image. Becomes local to this viewer only. This is like &avatar, but slightly different. Just CSS in this case
|
|
let avatarImg = urlParams.get("avatarimg") || urlParams.get("bgimage") || urlParams.get("bgimg") || "./media/avatar1.png";
|
|
if (avatarImg) {
|
|
try {
|
|
avatarImg = decodeURIComponent(avatarImg);
|
|
} catch (e) {}
|
|
try {
|
|
let fallbackImage = new Image();
|
|
fallbackImage.src = avatarImg;
|
|
session.style = -1;
|
|
fallbackImage.onload = function () {
|
|
document.documentElement.style.setProperty("--video-background-image", 'url("' + avatarImg + '")');
|
|
if (session.meterStyle !== 5) {
|
|
document.documentElement.style.setProperty("--video-background-image-size", "contain");
|
|
}
|
|
};
|
|
} catch (e) {}
|
|
}
|
|
}
|
|
if (urlParams.has("avatarimg2") || urlParams.has("bgimage2") || urlParams.has("bgimg2")) {
|
|
// URL or data:base64 image. Becomes local to this viewer only. This is like &avatar, but slightly different. Just CSS in this case
|
|
let avatarImg2 = urlParams.get("avatarimg2") || urlParams.get("bgimage2") || urlParams.get("bgimg2") || "./media/avatar2.png";
|
|
if (avatarImg2) {
|
|
try {
|
|
avatarImg2 = decodeURIComponent(avatarImg2);
|
|
} catch (e) {}
|
|
try {
|
|
let fallbackImage2 = new Image();
|
|
fallbackImage2.src = avatarImg2;
|
|
fallbackImage2.onload = function () {
|
|
document.documentElement.style.setProperty("--video-background-image-talking", 'url("' + avatarImg2 + '")');
|
|
if (session.meterStyle !== 5) {
|
|
document.documentElement.style.setProperty("--video-background-image-size", "contain");
|
|
}
|
|
};
|
|
session.audioEffects = true;
|
|
session.meterStyle = 4;
|
|
session.style = -1;
|
|
if (session.showControls === null) {
|
|
session.showControls = false;
|
|
}
|
|
} catch (e) {}
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("avatarimg3") || urlParams.has("bgimage3") || urlParams.has("bgimg3")) {
|
|
// URL or data:base64 image. Becomes local to this viewer only. This is like &avatar, but slightly different. Just CSS in this case
|
|
let avatarImg3 = urlParams.get("avatarimg3") || urlParams.get("bgimage3") || urlParams.get("bgimg3") || "./media/avatar3.png";
|
|
if (avatarImg3) {
|
|
try {
|
|
avatarImg3 = decodeURIComponent(avatarImg3);
|
|
} catch (e) {}
|
|
try {
|
|
let fallbackImage3 = new Image();
|
|
fallbackImage3.src = avatarImg3;
|
|
fallbackImage3.onload = function () {
|
|
document.documentElement.style.setProperty("--video-background-image-screaming", 'url("' + avatarImg3 + '")');
|
|
if (session.meterStyle !== 5) {
|
|
document.documentElement.style.setProperty("--video-background-image-size", "contain");
|
|
}
|
|
};
|
|
session.audioEffects = true;
|
|
session.meterStyle = 4;
|
|
session.style = -1;
|
|
if (session.showControls === null) {
|
|
session.showControls = false;
|
|
}
|
|
} catch (e) {}
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("background") || urlParams.has("appbg")) {
|
|
// URL or data:base64 image. Use &chroma if you want to use a color instead of image.
|
|
let background = urlParams.get("background") || urlParams.get("appbg") || false;
|
|
if (background) {
|
|
try {
|
|
background = decodeURIComponent(background);
|
|
} catch (e) {}
|
|
try {
|
|
background = 'url("' + background + '")';
|
|
document.documentElement.style.setProperty("--background-main-image", background);
|
|
} catch (e) {}
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("poster")) {
|
|
// URL or data:base64 image. Becomes local to this viewer only. This is like &avatar, but slightly different. Just CSS in this case
|
|
let posterImage = urlParams.get("poster") || "./media/avatar.webp";
|
|
if (posterImage) {
|
|
try {
|
|
posterImage = decodeURIComponent(posterImage);
|
|
session.posterImage = posterImage;
|
|
} catch (e) {}
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("hideplaybutton") || urlParams.has("hpb")) {
|
|
// URL or data:base64 image. Becomes local to this viewer only. This is like &avatar, but slightly different. Just CSS in this case
|
|
try {
|
|
document.getElementById("bigPlayButton").classList.add("hidden");
|
|
} catch (e) {}
|
|
}
|
|
|
|
if (urlParams.has("whip") || urlParams.has("whipview")) {
|
|
session.whipView = urlParams.get("whip") || urlParams.get("whipview") || false;
|
|
if (session.whipView) {
|
|
setTimeout(function () {
|
|
whipClient();
|
|
}, 1000);
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("noaudiowhipin")){
|
|
session.forceNoAudioWhipIn = true;
|
|
}
|
|
if (urlParams.has("novideowhipin")){
|
|
session.forceNoVideoWhipIn = true;
|
|
}
|
|
|
|
if (urlParams.has("autoreload")){
|
|
let refreshInterval = parseInt(urlParams.get("autoreload")) || 60;
|
|
if (refreshInterval){
|
|
refreshInterval = refreshInterval*60*1000; // minutes to milliseconds
|
|
setInterval(function(){
|
|
session.hangup(true)
|
|
}, refreshInterval);
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("autoreload24")) {
|
|
let reloadTime = urlParams.get("autoreload24");
|
|
|
|
// Parse the reload time
|
|
let [hours, minutes] = reloadTime.split(':').map(Number);
|
|
|
|
if (!isNaN(hours) && !isNaN(minutes) && hours >= 0 && hours < 24 && minutes >= 0 && minutes < 60) {
|
|
let now = new Date();
|
|
let reloadDate = new Date(now.getFullYear(), now.getMonth(), now.getDate(), hours, minutes);
|
|
|
|
// If the reload time has already passed today, schedule for tomorrow
|
|
if (reloadDate <= now) {
|
|
reloadDate.setDate(reloadDate.getDate() + 1);
|
|
}
|
|
|
|
let timeUntilReload = reloadDate.getTime() - now.getTime();
|
|
|
|
setTimeout(function() {
|
|
session.hangup(true);
|
|
}, timeUntilReload);
|
|
} else {
|
|
console.error("Invalid reload time format. Please use HH:MM in 24-hour format.");
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("cftoken") || urlParams.has("cft")) {
|
|
session.whipOutput = urlParams.get("cftoken") || urlParams.get("cft") || false;
|
|
if (session.whipOutput) {
|
|
try {
|
|
session.whipOutput = decodeURIComponent(session.whipOutput);
|
|
} catch (e) {}
|
|
session.whipOutput = "https://cloudflare.vdo.ninja/" + session.whipOutput;
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("whepwait") || urlParams.has("whepicewait")) {
|
|
// I'm going to use this for all whip/whep for the time being.
|
|
session.whepWait = urlParams.get("whepwait") || urlParams.get("whepicewait") || 2000; // how long we wait for ice candidates to collect; ms. whep out and whep in
|
|
session.whepWait = parseInt(session.whepWait);
|
|
if (session.whepWait < 0) {
|
|
session.whepWait = 0;
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("whipwait") || urlParams.has("whipicewait")) {
|
|
// I'm going to use this for all whip/whep for the time being.
|
|
session.whipWait = urlParams.get("whipwait") || urlParams.get("whipicewait") || 2000; // how long we wait for ice candidates to collect; ms. whep out and whep in
|
|
session.whipWait = parseInt(session.whipWait);
|
|
if (session.whipWait < 0) {
|
|
session.whipWait = 0;
|
|
}
|
|
} else {
|
|
session.whipWait = 2000; // REMOVE after october 2024.
|
|
}
|
|
|
|
if (urlParams.has("whipme")){ // WIP
|
|
getById("container-18").classList.remove("hidden");
|
|
}
|
|
|
|
if (urlParams.has("whippush") || urlParams.has("whipout") || urlParams.has("pushwhip")) {
|
|
// URL or data:base64 image. Becomes local to this viewer only. This is like &avatar, but slightly different. Just CSS in this case
|
|
session.whipOutput = urlParams.get("whippush") || urlParams.get("whipout") || urlParams.get("pushwhip") || null;
|
|
if (session.whipOutput) {
|
|
try {
|
|
if (session.whipOutput == "twitch") {
|
|
session.whipOutput = "https://g.webrtc.live-video.net:4443/v2/offer";
|
|
query("#publishOutToken input[type='password']").placeholder = "Twitch stream token here";
|
|
} else {
|
|
session.whipOutput = decodeURIComponent(session.whipOutput);
|
|
}
|
|
} catch (e) {
|
|
errorlog(e);
|
|
}
|
|
} else {
|
|
getById("publishOutURL").classList.remove("hidden");
|
|
}
|
|
|
|
if (urlParams.has("whippushtoken") || urlParams.has("whipouttoken") || urlParams.has("pushwhiptoken")) {
|
|
// URL or data:base64 image. Becomes local to this viewer only. This is like &avatar, but slightly different. Just CSS in this case
|
|
session.whipOutputToken = urlParams.get("whippushtoken") || urlParams.get("whipouttoken") || urlParams.get("pushwhiptoken") || false;
|
|
if (!session.whipOutputToken) {
|
|
getById("publishOutToken").classList.remove("hidden");
|
|
}
|
|
} else if (session.whipOutput !== false) {
|
|
if (!session.whipOutputToken) {
|
|
getById("publishOutToken").classList.remove("hidden");
|
|
}
|
|
}
|
|
|
|
getById("startPublishingButton").classList.remove("hidden");
|
|
}
|
|
|
|
if (urlParams.has("whipoutkeyframe") ){
|
|
session.whipOutKeyframe = parseInt(urlParams.get("whipoutkeyframe")) || 0;
|
|
}
|
|
|
|
if (urlParams.has("whipoutkeyframenewviewer") ){
|
|
session.whipOutKeyframeOnNewViewer = true;
|
|
}
|
|
|
|
|
|
if (urlParams.has("svc") || urlParams.has("scalabilitymode")) {
|
|
// Experiment with this feature here: https://webrtc.github.io/samples/src/content/extensions/svc/
|
|
session.scalabilityMode = urlParams.get("svc") || urlParams.get("scalabilitymode") || "L1T3";
|
|
if (!scalabilityModes.includes(session.scalabilityMode)) {
|
|
scalabilityModes.forEach(sca => {
|
|
if (sca.toLowerCase() === session.scalabilityMode.toLowerCase()) {
|
|
session.scalabilityMode = sca;
|
|
log("Corrected the capitalization of the SVC value. just in case thats important");
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("whepplay") || urlParams.has("whep")) {
|
|
// URL or data:base64 image. Becomes local to this viewer only. This is like &avatar, but slightly different. Just CSS in this case
|
|
if (urlParams.get("whepplay") || urlParams.has("whep")) {
|
|
try {
|
|
session.whepInput = decodeURIComponent(urlParams.get("whepplay") || urlParams.get("whep"));
|
|
if (session.whepInput) {
|
|
setTimeout(function () {
|
|
whepIn();
|
|
}, 1000);
|
|
}
|
|
} catch (e) {
|
|
errorlog(e);
|
|
}
|
|
}
|
|
}
|
|
if (urlParams.has("whepplaytoken") || urlParams.has("wheptoken")) {
|
|
// URL or data:base64 image. Becomes local to this viewer only. This is like &avatar, but slightly different. Just CSS in this case
|
|
if (urlParams.get("whepplaytoken") || urlParams.get("wheptoken")) {
|
|
try {
|
|
session.whepInputToken = urlParams.get("whepplaytoken") || urlParams.get("wheptoken");
|
|
} catch (e) {
|
|
errorlog(e);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("nomouseevents") || urlParams.has("nme")) {
|
|
session.disableMouseEvents = true;
|
|
}
|
|
if (urlParams.has("overlaycontrols")) {
|
|
session.overlayControls = true;
|
|
}
|
|
|
|
if (urlParams.has("novideobutton") || urlParams.has("nvb")) {
|
|
getById("mutevideobutton").style.setProperty("display", "none", "important");
|
|
}
|
|
|
|
if (urlParams.has("nospeakerbutton") || urlParams.has("nsb")) {
|
|
getById("mutespeakerbutton").style.setProperty("display", "none", "important");
|
|
}
|
|
|
|
if (urlParams.has("noscale") || urlParams.has("noscaling")) {
|
|
session.noScaling = true;
|
|
}
|
|
|
|
if (urlParams.has("pusheffectsdata")) {
|
|
session.pushEffectsData = true;
|
|
}
|
|
|
|
if (urlParams.has("pushloudness") || urlParams.has("getloudness")) {
|
|
// this sets the loudness IFRAME API output, if available.
|
|
session.pushLoudness = true;
|
|
}
|
|
|
|
if (urlParams.has("pushfaces") || urlParams.has("getfaces")) {
|
|
session.grabFaceData = true;
|
|
setTimeout(function () {
|
|
// give the app some time to load
|
|
getFaces();
|
|
}, 2000);
|
|
}
|
|
|
|
if (urlParams.has("notmobile")) {
|
|
session.mobile = false;
|
|
} else if (urlParams.has("mobile")) {
|
|
session.mobile = true;
|
|
session.audioEffects = false; // disable audio inbound effects also.
|
|
session.audioMeterGuest = false;
|
|
} else if (iOS || iPad) {
|
|
if (SafariVersion && SafariVersion < 17) {
|
|
getById("oldiOSWarning").classList.remove("hidden"); // update this to 17 at some point.
|
|
}
|
|
session.mobile = true;
|
|
session.audioEffects = false; // disable audio inbound effects also.
|
|
session.audioMeterGuest = false;
|
|
window.addEventListener("resize", function () {
|
|
// Safari is the new IE.
|
|
|
|
if (session.ws) {
|
|
var msg = {};
|
|
msg.requestSceneUpdate = true;
|
|
session.sendMessage(msg);
|
|
}
|
|
if (screen && screen.orientation && screen.orientation.type) {
|
|
if (screen.orientation.type.includes("portrait")) {
|
|
document.getElementsByTagName("html")[0].style.height = "100vh";
|
|
setTimeout(function () {
|
|
document.getElementsByTagName("html")[0].style.height = "100%";
|
|
}, 1000);
|
|
} else if (screen.orientation.type.includes("landscape")) {
|
|
document.getElementsByTagName("html")[0].style.height = "100vh";
|
|
setTimeout(function () {
|
|
document.getElementsByTagName("html")[0].style.height = "100%";
|
|
}, 1000);
|
|
}
|
|
} else if (window.matchMedia("(orientation: portrait)").matches) {
|
|
document.getElementsByTagName("html")[0].style.height = "100vh";
|
|
setTimeout(function () {
|
|
document.getElementsByTagName("html")[0].style.height = "100%";
|
|
}, 1000);
|
|
} else if (window.matchMedia("(orientation: landscape)").matches) {
|
|
document.getElementsByTagName("html")[0].style.height = "100vh";
|
|
setTimeout(function () {
|
|
document.getElementsByTagName("html")[0].style.height = "100%";
|
|
}, 1000);
|
|
}
|
|
});
|
|
|
|
if (/CriOS/i.test(navigator.userAgent)) {
|
|
// if runngin Chrome on iOS
|
|
if (!session.cleanOutput) {
|
|
try {
|
|
navigator.mediaDevices.getUserMedia;
|
|
} catch (e) {
|
|
warnUser("Chrome on this device does not support the required technology to use this site.\n\nPlease use Safari instead or update your iOS and browser version.");
|
|
}
|
|
}
|
|
}
|
|
} else if (/Android|Pixel|webOS|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
|
|
// not sure how accurate this is.
|
|
session.mobile = true;
|
|
session.audioEffects = false; // disable audio inbound effects also.
|
|
session.audioMeterGuest = false;
|
|
} else {
|
|
log("MAKE DRAGGABLE");
|
|
delayedStartupFuncs.push([makeDraggableElement, document.getElementById("subControlButtons")]);
|
|
if (SafariVersion && !ChromiumVersion) {
|
|
// if desktop Safari, so macOS, give a note saying it sucks
|
|
getById("SafariWarning").classList.remove("hidden");
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("broadcasttransfer") || urlParams.has("bct")) {
|
|
log("Broadcast transfer flag set");
|
|
session.broadcastTransfer = urlParams.get("broadcasttransfer") || urlParams.get("bct") || null;
|
|
if (session.broadcastTransfer === "false") {
|
|
session.broadcastTransfer = false;
|
|
} else if (session.broadcastTransfer === "0") {
|
|
session.broadcastTransfer = false;
|
|
} else if (session.broadcastTransfer === "no") {
|
|
session.broadcastTransfer = false;
|
|
} else if (session.broadcastTransfer === "off") {
|
|
session.broadcastTransfer = false;
|
|
} else {
|
|
session.broadcastTransfer = true;
|
|
}
|
|
if (transferSettings) {
|
|
transferSettings.broadcast = session.broadcastTransfer;
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("queuetransfer") || urlParams.has("qt")) {
|
|
log("Broadcast transfer flag set");
|
|
session.queueTransfer = urlParams.get("queuetransfer") || urlParams.get("qt") || null;
|
|
if (session.queueTransfer === "false") {
|
|
session.queueTransfer = false;
|
|
} else if (session.queueTransfer === "0") {
|
|
session.queueTransfer = false;
|
|
} else if (session.queueTransfer === "no") {
|
|
session.queueTransfer = false;
|
|
} else if (session.queueTransfer === "off") {
|
|
session.queueTransfer = false;
|
|
} else {
|
|
session.queueTransfer = true;
|
|
}
|
|
if (transferSettings) {
|
|
transferSettings.queue = session.queueTransfer;
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("broadcast") || urlParams.has("bc")) {
|
|
log("Broadcast flag set");
|
|
session.broadcast = urlParams.get("broadcast") || urlParams.get("bc") || null;
|
|
|
|
if (session.broadcast === "false") {
|
|
session.broadcast = false;
|
|
} else if (session.broadcast === "0") {
|
|
session.broadcast = false;
|
|
} else if (session.broadcast === "no") {
|
|
session.broadcast = false;
|
|
} else if (session.broadcast === "off") {
|
|
session.broadcast = false;
|
|
}
|
|
|
|
//if ((iOS) || (iPad)) {
|
|
// session.nopreview = false;
|
|
//} else {
|
|
// session.nopreview = true;
|
|
//}
|
|
session.minipreview = 2; // full screen if nothing else on screen.
|
|
session.style = 1;
|
|
//getById("header").style.display = "none";
|
|
//getById("header").style.opacity = 0;
|
|
session.showList = true;
|
|
}
|
|
|
|
if (urlParams.has("showlist")) {
|
|
session.showList = urlParams.get("showlist");
|
|
if (session.showList === "false") {
|
|
session.showList = false;
|
|
} else if (session.showList === "0") {
|
|
session.showList = false;
|
|
} else if (session.showList === "no") {
|
|
session.showList = false;
|
|
} else if (session.showList === "off") {
|
|
session.showList = false;
|
|
} else {
|
|
session.showList = true;
|
|
}
|
|
}
|
|
//if (session.showList===true){
|
|
// getById("hideusers").classList.add("hidden");
|
|
//}
|
|
|
|
if (urlParams.has("meshcast") && !urlParams.has("meshcastfailed")) {
|
|
session.meshcast = urlParams.get("meshcast") || "any";
|
|
meshcast(true);
|
|
}
|
|
|
|
if (urlParams.has("meshcastcode") || urlParams.has("mccode")) {
|
|
session.meshcastCode = urlParams.get("meshcastcode") || urlParams.get("mccode") || false;
|
|
}
|
|
|
|
if (urlParams.has("nomeshcast") || urlParams.has("nowhep")) {
|
|
session.noMeshcast = urlParams.get("nomeshcast") || urlParams.has("nowhep") || true;
|
|
}
|
|
|
|
if (urlParams.has("chunkcast")) {
|
|
session.chunkcast = true;
|
|
}
|
|
|
|
if (urlParams.has("drawing")) {
|
|
session.allowDrawing = urlParams.get("drawing") || true;
|
|
}
|
|
|
|
if (urlParams.has("nohistory")) {
|
|
session.nohistory = true;
|
|
}
|
|
//if (urlParams.has('callin')){
|
|
// awaitInboundCall()();
|
|
//}
|
|
|
|
//if (urlParams.has("relaywss")) {
|
|
// session.relaywss = true;
|
|
//}
|
|
|
|
if (urlParams.has("fulltalk") && urlParams.get("fulltalk").length == 6) {
|
|
listenWebsocket(urlParams.get("fulltalk"), false); // talk and hear all
|
|
} else if (urlParams.has("justtalk") && urlParams.get("justtalk").length == 6) {
|
|
joinConference(urlParams.get("justtalk")); // just talk
|
|
|
|
if (urlParams.has("hearptsn")) {
|
|
listenWebsocket(uurlParams.get("justtalk")); // hear ptsn only
|
|
}
|
|
} else if (urlParams.has("hearptsn") && urlParams.get("hearptsn").length == 6) {
|
|
listenWebsocket(urlParams.get("hearptsn")); // hear ptsn only
|
|
|
|
if (urlParams.has("justtalk")) {
|
|
joinConference(urlParams.get("hearptsn"));
|
|
}
|
|
}
|
|
|
|
var filename = false;
|
|
try {
|
|
if (!session.decrypted) {
|
|
filename = window.location.pathname.substring(window.location.pathname.lastIndexOf("/") + 1);
|
|
filename = filename.replace("??", "?");
|
|
filename2 = filename.split("?")[0];
|
|
// split at ???
|
|
if (filename.split(".").length == 1) {
|
|
if (filename2.length < 2) {
|
|
// easy win
|
|
filename = false;
|
|
} else if (filename.startsWith("&")) {
|
|
// easy win
|
|
var tmpHref = window.location.href.substring(0, window.location.href.lastIndexOf("/")) + "/?" + filename.split("&").slice(1).join("&");
|
|
log("TMP " + tmpHref);
|
|
updateURL(filename.split("&")[1], true, tmpHref);
|
|
filename = false;
|
|
} else if (filename2.split("&")[0].includes("=")) {
|
|
log("asdf " + filename.split("&")[0]);
|
|
if (history.pushState) {
|
|
var tmpHref = window.location.href.substring(0, window.location.href.lastIndexOf("/"));
|
|
tmpHref = tmpHref + "/?" + filename;
|
|
filename = false;
|
|
//warnUser("Please ensure your URL is correctly formatted.");
|
|
if (!session.nohistory){
|
|
window.history.pushState({ path: tmpHref.toString() }, "", tmpHref.toString());
|
|
}
|
|
}
|
|
} else {
|
|
filename = filename2.split("&")[0];
|
|
if (filename2 != filename) {
|
|
warnUser("Warning: Please ensure your URL is correctly formatted.");
|
|
}
|
|
}
|
|
} else {
|
|
filename = false;
|
|
}
|
|
log(filename);
|
|
}
|
|
} catch (e) {
|
|
errorlog(e);
|
|
}
|
|
|
|
var directorLanding = false;
|
|
if (session.director) {
|
|
if (session.director === true) {
|
|
// room not specified.
|
|
directorLanding = true;
|
|
}
|
|
session.meterStyle = 1;
|
|
session.signalMeter = true;
|
|
session.batteryMeter = true;
|
|
} else if (filename === "director") {
|
|
directorLanding = true;
|
|
filename = false;
|
|
session.meterStyle = 1;
|
|
session.signalMeter = true;
|
|
session.batteryMeter = true;
|
|
}
|
|
|
|
session.slotmode = false; // temporary; remove in the future TODO: ## -----------------------
|
|
if (urlParams.has("slotmode") || urlParams.has("slotsmode")) {
|
|
session.slotmode = parseInt(urlParams.get("slotmode")) || parseInt(urlParams.get("slotsmode")) || 1;
|
|
}
|
|
|
|
if (urlParams.has("signalmeter")) {
|
|
session.signalMeter = urlParams.get("signalmeter");
|
|
if (session.signalMeter === "false") {
|
|
session.signalMeter = false;
|
|
} else if (session.signalMeter === "0") {
|
|
session.signalMeter = false;
|
|
} else if (session.signalMeter === "no") {
|
|
session.signalMeter = false;
|
|
} else if (session.signalMeter === "off") {
|
|
session.signalMeter = false;
|
|
} else {
|
|
session.signalMeter = true;
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("batterymeter")) {
|
|
session.batteryMeter = urlParams.get("batterymeter");
|
|
if (session.batteryMeter === "false") {
|
|
session.batteryMeter = false;
|
|
} else if (session.batteryMeter === "0") {
|
|
session.batteryMeter = false;
|
|
} else if (session.batteryMeter === "no") {
|
|
session.batteryMeter = false;
|
|
} else if (session.batteryMeter === "off") {
|
|
session.batteryMeter = false;
|
|
} else {
|
|
session.batteryMeter = true;
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("rooms")) {
|
|
session.rooms = urlParams
|
|
.get("rooms")
|
|
.split(",")
|
|
.map(function (e) {
|
|
return sanitizeRoomName(e);
|
|
});
|
|
getById("rooms").classList.remove("hidden");
|
|
}
|
|
|
|
if (urlParams.has("leaveorientationflag")) {
|
|
session.removeOrientationFlag = false; // leave `a=extmap:3 urn:3gpp:video-orientation\r\n` alone
|
|
}
|
|
|
|
if (urlParams.has("showdirector") || urlParams.has("sd")) {
|
|
session.showDirector = parseInt(urlParams.get("showdirector")) || parseInt(urlParams.get("sd")) || true; // if 2, video only allowed. True or 1 will be video + audio allowed.
|
|
// fyi, true is the same as 1 when == is used, so assert(1==true) is true.
|
|
}
|
|
|
|
if (urlParams.has("bitratecutoff") || urlParams.has("bitcut")) {
|
|
session.lowBitrateCutoff = parseInt(urlParams.get("bitratecutoff")) || parseInt(urlParams.get("bitcut")) || 300; // low bitrate cut off.
|
|
session.hiddenSceneViewBitrate = false;
|
|
}
|
|
|
|
if (urlParams.has("motionswitch") || urlParams.has("motiondetection")) {
|
|
// switch OBS to this scene when there is motion, and "solo view" this video in the VDO.Ninja auto-mixer, if used
|
|
session.motionSwitch = parseInt(urlParams.get("motionswitch")) || parseInt(urlParams.get("motiondetection")) || 15; // threshold of motion needed to trigger
|
|
session.hiddenSceneViewBitrate = false;
|
|
}
|
|
|
|
if (urlParams.has("motionrecord") || urlParams.has("recordmotion")) {
|
|
// switch OBS to this scene when there is motion, and "solo view" this video in the VDO.Ninja auto-mixer, if used
|
|
session.motionRecord = parseInt(urlParams.get("motionrecord")) || parseInt(urlParams.get("recordmotion")) || 15; // threshold of motion needed to trigger
|
|
session.hiddenSceneViewBitrate = false;
|
|
}
|
|
|
|
if (urlParams.has("pausepreview") || urlParams.has("dpp")) {
|
|
try {
|
|
session.directorViewBitrate = 0;
|
|
document.querySelector('#controls_blank button[data-action-type="change-quality1"]').classList.add("pressed");
|
|
document.querySelector('#controls_blank button[data-action-type="change-quality2"]').classList.remove("pressed");
|
|
document.querySelector('#controls_blank button[data-action-type="change-quality3"]').classList.remove("pressed");
|
|
} catch (e) {
|
|
errorlog(e);
|
|
}
|
|
}
|
|
if (urlParams.has("locked")) {
|
|
session.locked = urlParams.get("locked");
|
|
|
|
if (session.locked == "portrait" || session.locked == "vertical") {
|
|
session.locked = 9.0 / 16.0;
|
|
} else if (session.locked == "landscape") {
|
|
session.locked = 16.0 / 9.0;
|
|
} else if (session.locked == "square") {
|
|
session.locked = 1.0;
|
|
} else {
|
|
session.locked = parseFloat(session.locked) || 16 / 9.0;
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("lowbitratescene") || urlParams.has("cutscene")) {
|
|
session.lowBitrateSceneChange = urlParams.get("lowbitratescene") || urlParams.get("cutscene") || "cutscene"; // low bitrate cut off.
|
|
session.hiddenSceneViewBitrate = false;
|
|
if (session.lowBitrateCutoff === false) {
|
|
session.lowBitrateCutoff = 300;
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("rotate")) {
|
|
session.rotate = urlParams.get("rotate") || 90;
|
|
session.rotate = parseInt(session.rotate);
|
|
}
|
|
|
|
if (urlParams.has("rotatewindow") || urlParams.has("rotatepage")) {
|
|
let rotateThis = parseInt(urlParams.get("rotatewindow")) || parseInt(urlParams.get("rotatepage")) || 90;
|
|
updateForceRotatedCSS(rotateThis);
|
|
}
|
|
|
|
if (urlParams.has("facing")) {
|
|
session.facingMode = urlParams.get("facing") || false;
|
|
}
|
|
if (session.facingMode) {
|
|
session.facingMode = session.facingMode.toLowerCase();
|
|
if (session.facingMode == "user") {
|
|
//
|
|
} else if (session.facingMode == "environment") {
|
|
//
|
|
} else if (session.facingMode == "rear") {
|
|
session.facingMode = "environment";
|
|
} else if (session.facingMode == "back") {
|
|
session.facingMode = "environment";
|
|
} else if (session.facingMode == "front") {
|
|
session.facingMode = "user";
|
|
} else {
|
|
session.facingMode = false;
|
|
}
|
|
}
|
|
|
|
// session.facingMode }; // user or environment
|
|
|
|
if (urlParams.has("forcelandscape") || urlParams.has("forcedlandscape") || urlParams.has("fl")) {
|
|
session.orientation = "landscape";
|
|
if (Firefox) {
|
|
session.fullscreen = true; // windowed mode complicates things in this mode
|
|
}
|
|
} else if (urlParams.has("forceportrait") || urlParams.has("forcedportrait") || urlParams.has("fp")) {
|
|
session.orientation = "portrait";
|
|
if (Firefox) {
|
|
session.fullscreen = true; // windowed mode complicates things in this mode
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("forceviewerlandscape")) {
|
|
session.keepIncomingVideosInLandscape = parseInt(urlParams.get("forceviewerlandscape")) || 270;
|
|
}
|
|
|
|
if (urlParams.has("forceviewerportrait")) {
|
|
session.keepIncomingVideosInPortrait = parseInt(urlParams.get("forceviewerportrait")) || 90;
|
|
}
|
|
|
|
document.addEventListener("fullscreenchange", event => {
|
|
log("full screen change event");
|
|
log(event);
|
|
|
|
if (document.getElementById("previewWebcam")) {
|
|
return;
|
|
}
|
|
|
|
if (session.orientation && session.mobile) {
|
|
if (document.fullscreenElement) {
|
|
document.exitFullscreen();
|
|
getById("fullscreenPageToggle").classList.add("la-expand-arrows-alt");
|
|
getById("fullscreenPageToggle").classList.remove("la-compress-arrows-alt");
|
|
}
|
|
return;
|
|
}
|
|
if (document.fullscreenElement) {
|
|
getById("fullscreenPageToggle").classList.remove("la-expand-arrows-alt");
|
|
getById("fullscreenPageToggle").classList.add("la-compress-arrows-alt");
|
|
} else {
|
|
getById("fullscreenPageToggle").classList.add("la-expand-arrows-alt");
|
|
getById("fullscreenPageToggle").classList.remove("la-compress-arrows-alt");
|
|
}
|
|
updateMixer();
|
|
});
|
|
|
|
if (urlParams.has("fullscreenbutton") || urlParams.has("fsb")) {
|
|
// just an alternative; might be compoundable
|
|
if (!(iOS || iPad)) {
|
|
session.fullscreenButton = true;
|
|
document.documentElement.style.setProperty("--full-screen-button", "none");
|
|
getById("fullscreenPage").classList.remove("hidden");
|
|
}
|
|
} else if (urlParams.has("nofullscreenbutton") || urlParams.has("nofsb")) {
|
|
// just an alternative; might be compoundable
|
|
session.nofullwindowbutton = true;
|
|
}
|
|
|
|
if (urlParams.has("pip2") || urlParams.has("pipall")) {
|
|
// just an alternative; might be compoundable
|
|
if (typeof documentPictureInPicture !== "undefined") {
|
|
getById("PictureInPicturePage").classList.remove("hidden");
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("midi") || urlParams.has("hotkeys")) {
|
|
session.midiHotkeys = urlParams.get("midi") || urlParams.get("hotkeys") || 1;
|
|
session.midiHotkeys = parseInt(session.midiHotkeys);
|
|
}
|
|
|
|
if (urlParams.has("disablehotkeys")) {
|
|
session.disableHotKeys = true;
|
|
}
|
|
|
|
if (urlParams.has("nohangupbutton") || urlParams.has("nohub")) {
|
|
getById("hangupbutton").style.display = "none";
|
|
session.hangupbutton = false;
|
|
}
|
|
|
|
if (urlParams.has("hangupbutton") || urlParams.has("hub") || urlParams.has("humb64")) {
|
|
session.hangupbutton = true;
|
|
}
|
|
if (urlParams.has("hangupmessage") || urlParams.has("hum") || urlParams.has("humb64")) {
|
|
let htmlmessage = urlParams.get("hangupmessage") || urlParams.get("hum") || urlParams.get("humb64");
|
|
|
|
if (urlParams.get("humb64")) {
|
|
try {
|
|
htmlmessage = atob(htmlmessage);
|
|
} catch (e) {}
|
|
}
|
|
|
|
try {
|
|
htmlmessage = htmlmessage.replace(/(\r\n|\n|\r)/gm, "");
|
|
htmlmessage = decodeURIComponent(htmlmessage);
|
|
} catch (e) {
|
|
console.error(e);
|
|
}
|
|
getById("hangupContainer").innerHTML = htmlmessage;
|
|
}
|
|
|
|
if (urlParams.has("socialstream")) {
|
|
session.socialstream = urlParams.get("socialstream") || false;
|
|
}
|
|
|
|
if (urlParams.has("midioffset")) {
|
|
session.midiOffset = urlParams.get("midioffset") || 0;
|
|
session.midiOffset = parseInt(session.midiOffset);
|
|
}
|
|
|
|
if (urlParams.has("midiremote") || urlParams.has("remotemidi")) {
|
|
if (session.director !== false) {
|
|
session.midiRemote = parseInt(urlParams.get("midiremote")) || parseInt(urlParams.get("remotemidi")) || 4;
|
|
} else {
|
|
session.midiRemote = parseInt(urlParams.get("midiremote")) || parseInt(urlParams.get("remotemidi")) || 1;
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("midipush") || urlParams.has("midiout") || urlParams.has("mo")) {
|
|
session.midiOut = parseInt(urlParams.get("midipush")) || parseInt(urlParams.get("midiout")) || parseInt(urlParams.get("mo")) || true;
|
|
}
|
|
|
|
if (urlParams.has("tc") || urlParams.has("timecode") || urlParams.has("showtimecode")) {
|
|
session.midiTimecode = urlParams.get("tc") || urlParams.get("timecode") || urlParams.get("showtimecode") || true;
|
|
}
|
|
|
|
if (urlParams.has("nochunkediframestats")) {
|
|
session.chunkIframe = false;
|
|
}
|
|
|
|
if (urlParams.has("midiiframe")) {
|
|
session.midiIframe = true;
|
|
}
|
|
|
|
if (urlParams.has("midipull") || urlParams.has("midiin") || urlParams.has("midin") || urlParams.has("mi")) {
|
|
session.midiIn = parseInt(urlParams.get("midipull")) || parseInt(urlParams.get("midiin")) || parseInt(urlParams.get("midin")) || parseInt(urlParams.get("mi")) || true;
|
|
}
|
|
|
|
if (urlParams.has("mididelay")) {
|
|
// midi-in delay
|
|
session.midiDelay = parseInt(urlParams.get("mididelay")) || 1000; // 1 second playout delay? acts as a buffer as well I guess.
|
|
}
|
|
|
|
if (urlParams.has("midichannel")) {
|
|
session.midiChannel = parseInt(urlParams.get("midichannel")) || false;
|
|
}
|
|
if (session.midiChannel) {
|
|
session.midiChannel = parseInt(session.midiChannel);
|
|
if (session.midiChannel > 16) {
|
|
session.midiChannel = false;
|
|
}
|
|
if (session.midiChannel < 1) {
|
|
session.midiChannel = false;
|
|
}
|
|
}
|
|
if (urlParams.has("mididevice")) {
|
|
session.midiDevice = parseInt(urlParams.get("mididevice")) || false;
|
|
}
|
|
|
|
if (urlParams.has("ptt")) {
|
|
if (urlParams.get("ptt")) {
|
|
setHotKeyAuto(urlParams.get("ptt"));
|
|
} else {
|
|
promptAlt("Select a hotkey", true, false, getById("pptHotKey").value, false, false, true);
|
|
}
|
|
}
|
|
|
|
if (directorLanding) {
|
|
getById("container-1").classList.remove("hidden");
|
|
getById("container-1").classList.add("skip-animation");
|
|
getById("container-1").classList.remove("pointer");
|
|
} else if (session.director) {
|
|
// if a director, webcam/screenshare/iframe auto-defaults shouldn't work
|
|
} else if (urlParams.has("webcam") || urlParams.has("wc") || urlParams.has("miconly")) {
|
|
session.webcamonly = true;
|
|
session.screensharebutton = false;
|
|
if (urlParams.has("miconly")) {
|
|
session.videoDevice = 0;
|
|
session.miconly = true;
|
|
miniTranslate(getById("add_camera"), "share-your-mic", "Share your Microphone");
|
|
getById("container-3").title = getById("add_camera").innerText;
|
|
|
|
getById("videoMenu").style.display = "none";
|
|
getById("container-3").classList.add("microphoneBackground");
|
|
getById("flipcamerabutton").style.setProperty("display", "none", "important");
|
|
getById("mutevideobutton").style.setProperty("display", "none", "important");
|
|
getById("videoMenu3").style.setProperty("display", "none", "important");
|
|
getById("previewWebcam").classList.add("miconly");
|
|
//if (session.consent){
|
|
// setTimeout(function(){
|
|
// warnUser("⚠ Privacy warning: The director of this room can remotely switch your camera or microphone without permission.", 8000);
|
|
// }, 1500);
|
|
//}
|
|
}
|
|
} else if (urlParams.has("screenshare") || urlParams.has("ss")) {
|
|
session.screenshare = true;
|
|
if (urlParams.get("screenshare") || urlParams.get("ss")) {
|
|
session.screenshare = urlParams.get("screenshare") || urlParams.get("ss");
|
|
}
|
|
} else if (urlParams.has("fileshare") || urlParams.has("fs")) {
|
|
getById("container-5").classList.remove("hidden");
|
|
getById("container-5").classList.add("skip-animation");
|
|
getById("container-5").classList.remove("pointer");
|
|
|
|
getById("sharefilebutton").style.display = "flex"; // this might be obsolete?
|
|
getById("mediafileshare").classList.remove("hidden");
|
|
|
|
if (SafariVersion) {
|
|
getById("safari_warning_fileshare").classList.remove("hidden");
|
|
} else if (!Firefox) {
|
|
getById("chrome_warning_fileshare").classList.remove("hidden");
|
|
}
|
|
} else if (!session.director && (urlParams.has("website") || urlParams.has("iframe"))) {
|
|
getById("container-6").classList.remove("hidden");
|
|
getById("container-6").classList.add("skip-animation");
|
|
getById("container-6").classList.remove("pointer");
|
|
session.website = urlParams.get("website") || urlParams.get("iframe") || false;
|
|
if (session.website) {
|
|
session.website = decodeURI(session.website);
|
|
delayedStartupFuncs.push([session.publishIFrame, session.website]);
|
|
}
|
|
} else if (urlParams.has("webcam2") || urlParams.has("wc2")) {
|
|
session.webcamonly = true;
|
|
session.screensharebutton = false;
|
|
session.introButton = true;
|
|
} else if (urlParams.has("screenshare2") || urlParams.has("ss2")) {
|
|
session.screenshare = true;
|
|
session.introButton = true;
|
|
if (urlParams.get("screenshare2") || urlParams.get("ss2")) {
|
|
session.screenshare = urlParams.get("screenshare2") || urlParams.get("ss2");
|
|
}
|
|
}
|
|
|
|
if (session.director && (urlParams.has("website") || urlParams.has("iframe"))) {
|
|
getById("container-6").classList.remove("hidden");
|
|
getById("container-6").classList.add("skip-animation");
|
|
getById("container-6").classList.remove("pointer");
|
|
session.website = urlParams.get("website") || urlParams.get("iframe") || false;
|
|
if (session.website) {
|
|
session.website = decodeURI(session.website);
|
|
delayedStartupFuncs.push([shareWebsite, session.website]);
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("sstype") || urlParams.has("screensharetype")) {
|
|
// wha type of screen sharing is used; track replace, iframe, or secondary try
|
|
session.screenshareType = urlParams.get("sstype") || urlParams.get("screensharetype");
|
|
session.screenshareType = parseInt(session.screenshareType) || false;
|
|
}
|
|
|
|
if (urlParams.has("ssstyle") || urlParams.has("screensharestyle")) {
|
|
// wha type of screen sharing is used; track replace, iframe, or secondary try
|
|
session.screenshareStyle = urlParams.get("ssstyle") || urlParams.get("screensharestyle") || 1;
|
|
session.screenshareStyle = parseInt(session.screenshareStyle) || false;
|
|
}
|
|
|
|
if (urlParams.has("suppresslocalaudio")) {
|
|
session.suppressLocalAudioPlayback = true;
|
|
}
|
|
if (urlParams.has("prefercurrenttab")) {
|
|
session.preferCurrentTab = true;
|
|
}
|
|
if (urlParams.has("selfbrowsersurface")) {
|
|
// exclude
|
|
session.selfBrowserSurface = urlParams.get("selfbrowsersurface") || "exclude";
|
|
}
|
|
if (urlParams.has("surfaceswitching")) {
|
|
session.surfaceSwitching = urlParams.get("surfaceswitching") || "exclude";
|
|
}
|
|
if (urlParams.has("systemaudio")) {
|
|
// exclude or exclude
|
|
session.systemAudio = urlParams.get("systemaudio") || "exclude";
|
|
}
|
|
if (urlParams.has("displaysurface")) {
|
|
// browser, window, or monitor (which is default selected)
|
|
session.displaySurface = urlParams.get("displaysurface") || "monitor";
|
|
}
|
|
|
|
if (urlParams.has("locksize")) {
|
|
// browser, window, or monitor (which is default selected)
|
|
session.lockWindowSize = urlParams.get("locksize") || true;
|
|
}
|
|
|
|
if (urlParams.has("intro") || urlParams.has("ib")) {
|
|
session.introButton = true;
|
|
}
|
|
|
|
if (urlParams.has("volumecontrol") || urlParams.has("volumecontrols") || urlParams.has("vc")) {
|
|
if (!(iOS || iPad)) {
|
|
session.volumeControl = true;
|
|
}
|
|
}
|
|
if (urlParams.has("controlbarspace")) {
|
|
session.dedicatedControlBarSpace = true;
|
|
} else if (urlParams.has("nocontrolbarspace")) {
|
|
session.dedicatedControlBarSpace = false;
|
|
}
|
|
|
|
if (urlParams.has("hidesolo") || urlParams.has("hs")) {
|
|
session.hidesololinks = true;
|
|
}
|
|
|
|
if (urlParams.has("mute") || urlParams.has("muted") || urlParams.has("m")) {
|
|
session.muted = true;
|
|
}
|
|
|
|
if (urlParams.has("hideguest") || urlParams.has("hidden")) {
|
|
session.directorVideoMuted = true;
|
|
}
|
|
|
|
if (urlParams.has("videomute") || urlParams.has("videomuted") || urlParams.has("vm")) {
|
|
session.videoMutedFlag = true;
|
|
}
|
|
|
|
if (urlParams.get("viewslot")) {
|
|
session.viewslot = parseInt(urlParams.get("viewslot")) || false;
|
|
session.accept_layouts = true;
|
|
session.layout = {};
|
|
session.exclusiveLayoutAudio = true;
|
|
session.hiddenSceneViewBitrate = 0;
|
|
} else if (urlParams.has("layout")) {
|
|
if (!urlParams.get("layout")) {
|
|
session.accept_layouts = true;
|
|
session.layout = {};
|
|
} else {
|
|
let decodedParam;
|
|
try {
|
|
decodedParam = decodeURIComponent(urlParams.get("layout"));
|
|
} catch (e) {
|
|
decodedParam = urlParams.get("layout");
|
|
}
|
|
try {
|
|
session.layout = JSON.parse(decodedParam);
|
|
} catch (e) {
|
|
try {
|
|
const base64Decoded = atob(decodedParam);
|
|
try {
|
|
session.layout = JSON.parse(base64Decoded);
|
|
} catch (e) {
|
|
session.layout = base64Decoded;
|
|
}
|
|
} catch (e) {
|
|
session.layout = decodedParam;
|
|
}
|
|
}
|
|
}
|
|
console.warn("Warning: If using &layout with &broadcast, only the director's video will appear in the custom layout, which is likely not intended.");
|
|
}
|
|
|
|
if (urlParams.get("exclusivelayoutaudio")) {
|
|
session.exclusiveLayoutAudio = true;
|
|
} else if (urlParams.get("inclusivelayoutaudio")) {
|
|
session.exclusiveLayoutAudio = false;
|
|
}
|
|
|
|
if (urlParams.has("layouts")) {
|
|
// an ordered array of layouts, which can be used to switch between using the API layouts action.
|
|
// ie: ?layouts=[[{"x":0,"y":0,"w":100,"h":100,"slot":0}],[{"x":0,"y":0,"w":100,"h":100,"slot":1}],[{"x":0,"y":0,"w":100,"h":100,"slot":2}],[{"x":0,"y":0,"w":100,"h":100,"slot":3}],[{"x":0,"y":0,"w":50,"h":100,"c":false,"slot":0},{"x":50,"y":0,"w":50,"h":100,"c":false,"slot":1}],[{"x":0,"y":0,"w":100,"h":100,"z":0,"c":false,"slot":1},{"x":70,"y":70,"w":30,"h":30,"z":1,"c":true,"slot":0}],[{"x":0,"y":0,"w":50,"h":50,"c":true,"slot":0},{"x":50,"y":0,"w":50,"h":50,"c":true,"slot":1},{"x":0,"y":50,"w":50,"h":50,"c":true,"slot":2},{"x":50,"y":50,"w":50,"h":50,"c":true,"slot":3}],[{"x":0,"y":16.667,"w":66.667,"h":66.667,"c":true,"slot":0},{"x":66.667,"y":0,"w":33.333,"h":33.333,"c":true,"slot":1},{"x":66.667,"y":33.333,"w":33.333,"h":33.333,"c":true,"slot":2},{"x":66.667,"y":66.667,"w":33.333,"h":33.333,"c":true,"slot":3}]]
|
|
try {
|
|
session.layouts = JSON.parse(decodeURIComponent(urlParams.get("layouts"))) || JSON.parse(urlParams.get("layouts")) || {};
|
|
} catch (e) {
|
|
try {
|
|
session.layouts = JSON.parse(urlParams.get("layouts")) || false;
|
|
} catch (e) {
|
|
session.layouts = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* if (session.layout && session.layouts && (typeof session.layout !== "object") && parseInt(session.layout) && (session.layout == parseInt(session.layout))){
|
|
try {
|
|
session.layout = session.layouts[session.layout-1];
|
|
} catch(e){
|
|
session.layout= false;
|
|
}
|
|
} */
|
|
|
|
if (urlParams.has("deaf") || urlParams.has("deafen")) {
|
|
session.directorSpeakerMuted = true; // false == true in this case.
|
|
}
|
|
|
|
if (urlParams.has("blind")) {
|
|
session.directorDisplayMuted = true; // false == true in this case.
|
|
}
|
|
|
|
if (urlParams.has("blindall")) {
|
|
session.directorBlindButton = true; // false == true in this case.
|
|
}
|
|
if (session.directorBlindButton) {
|
|
getById("blindAllGuests").classList.remove("hidden");
|
|
}
|
|
|
|
if (urlParams.has("dpi") || urlParams.has("dpr") || urlParams.has("sharper") || urlParams.has("sharpen")) {
|
|
session.devicePixelRatio = urlParams.get("dpi") || urlParams.get("dpr") || 2.0;
|
|
session.devicePixelRatio = parseFloat(session.devicePixelRatio);
|
|
} //else if (window.devicePixelRatio && window.devicePixelRatio!==1){
|
|
// session.devicePixelRatio = window.devicePixelRatio; // this annoys me to no end.
|
|
//}
|
|
|
|
if (urlParams.has("speakermute") || urlParams.has("speakermuted") || urlParams.has("mutespeaker") || urlParams.has("sm") || urlParams.has("ms")) {
|
|
var checkState = urlParams.get("speakermute") || urlParams.get("speakermuted") || urlParams.get("mutespeaker") || urlParams.get("sm") || urlParams.get("ms") || true;
|
|
|
|
if (checkState === "false") {
|
|
session.speakerMuted = false;
|
|
} else if (checkState === "0") {
|
|
session.speakerMuted = false;
|
|
} else if (checkState === "no") {
|
|
session.speakerMuted = false;
|
|
} else if (checkState === "off") {
|
|
session.speakerMuted = false;
|
|
} else {
|
|
session.speakerMuted = true;
|
|
}
|
|
|
|
session.speakerMuted_default = session.speakerMuted;
|
|
|
|
if (session.speakerMuted) {
|
|
getById("mutespeakertoggle").className = "las la-volume-mute toggleSize";
|
|
//getById("mutespeakerbutton").className="hidden float2 red";
|
|
getById("mutespeakerbutton").classList.add("red");
|
|
getById("mutespeakerbutton").classList.add("float2");
|
|
getById("mutespeakerbutton").classList.remove("float");
|
|
|
|
var sounds = document.getElementsByTagName("video");
|
|
for (var i = 0; i < sounds.length; ++i) {
|
|
sounds[i].muted = session.speakerMuted;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("chatbutton") || urlParams.has("chat") || urlParams.has("cb")) {
|
|
session.chatbutton = urlParams.get("chatbutton") || urlParams.get("chat") || urlParams.get("cb") || null;
|
|
if (session.chatbutton === "false") {
|
|
session.chatbutton = false;
|
|
} else if (session.chatbutton === "0") {
|
|
session.chatbutton = false;
|
|
} else if (session.chatbutton === "no") {
|
|
session.chatbutton = false;
|
|
} else if (session.chatbutton === "off") {
|
|
session.chatbutton = false;
|
|
} else {
|
|
session.chatbutton = true;
|
|
getById("chatbutton").classList.remove("hidden");
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("app")) {
|
|
// midi-in delay
|
|
session.screenshare = false;
|
|
getById("container-2").classList.add("hidden");
|
|
getById("logoname").classList.add("hidden");
|
|
getById("head1a").classList.remove("hidden");
|
|
getById("main").classList.add("appmode");
|
|
getById("jumptoroomButton").innerText = "Join Room";
|
|
|
|
if (getStorage("jumptoURL")) {
|
|
getById("joinbyURL").value = getStorage("jumptoURL");
|
|
}
|
|
}
|
|
|
|
if (session.screenshare !== false) {
|
|
if (session.introButton) {
|
|
getById("container-3").className = "column columnfade hidden"; // Hide screen share
|
|
getById("head1").className = "hidden";
|
|
} else {
|
|
getById("container-3").className = "column columnfade hidden"; // Hide webcam
|
|
getById("container-2").classList.add("skip-animation");
|
|
getById("container-2").classList.remove("pointer");
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("hands") || urlParams.has("hand")) {
|
|
session.raisehands = true;
|
|
}
|
|
|
|
if (urlParams.has("portrait") || urlParams.has("916") || urlParams.has("vertical")) {
|
|
// playback aspect ratio
|
|
session.aspectRatio = 1; // 9:16 (default of 0 is 16:9)
|
|
} else if (urlParams.has("square") || urlParams.has("11")) {
|
|
session.aspectRatio = 2; //1:1 ?
|
|
} else if (urlParams.has("43")) {
|
|
session.aspectRatio = 3; //1:1 ?
|
|
}
|
|
|
|
if (urlParams.has("structure")) {
|
|
session.structure = true;
|
|
}
|
|
|
|
if (urlParams.has("aspectratio") || urlParams.has("ar")) {
|
|
// capture aspect ratio
|
|
session.forceAspectRatio = urlParams.get("aspectratio") || urlParams.get("ar") || false;
|
|
if (session.forceAspectRatio) {
|
|
if (session.forceAspectRatio == "portrait" || session.forceAspectRatio == "vertical") {
|
|
session.forceAspectRatio = 9.0 / 16.0;
|
|
} else if (session.forceAspectRatio == "landscape") {
|
|
session.forceAspectRatio = 16.0 / 9.0;
|
|
} else if (session.forceAspectRatio == "square") {
|
|
session.forceAspectRatio = 1.0;
|
|
} else {
|
|
session.forceAspectRatio = parseFloat(session.forceAspectRatio) || false;
|
|
}
|
|
}
|
|
}
|
|
if (urlParams.has("screenshareaspectratio") || urlParams.has("ssar")) {
|
|
// capture aspect ratio
|
|
session.forceScreenShareAspectRatio = urlParams.get("screenshareaspectratio") || urlParams.get("ssar") || 16.0 / 9.0;
|
|
if (session.forceScreenShareAspectRatio) {
|
|
if (session.forceScreenShareAspectRatio == "portrait" || session.forceScreenShareAspectRatio == "vertical") {
|
|
session.forceScreenShareAspectRatio = 9.0 / 16.0;
|
|
} else if (session.forceScreenShareAspectRatio == "landscape") {
|
|
session.forceScreenShareAspectRatio = 16.0 / 9.0;
|
|
} else if (session.forceScreenShareAspectRatio == "square") {
|
|
session.forceScreenShareAspectRatio = 1.0;
|
|
} else {
|
|
session.forceScreenShareAspectRatio = parseFloat(session.forceScreenShareAspectRatio) || false;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("crop")) {
|
|
var crop = parseFloat(urlParams.get("crop")) || 0;
|
|
if (crop > 0) {
|
|
session.forceAspectRatio = 1.7777777778 * (crop / 100);
|
|
} else if (crop < 0) {
|
|
session.forceAspectRatio = 1.7777777778 / (crop / 100);
|
|
} else {
|
|
session.forceAspectRatio = 1.3333333333;
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("cover")) {
|
|
session.cover = true;
|
|
document.documentElement.style.setProperty("--fit-style", "cover");
|
|
document.documentElement.style.setProperty("--myvideo-max-width", "100vw");
|
|
document.documentElement.style.setProperty("--myvideo-width", "100vw");
|
|
document.documentElement.style.setProperty("--myvideo-height", "100vh");
|
|
} else if (urlParams.has("fit")) {
|
|
// not fully implemented yet.
|
|
session.cover = true;
|
|
document.documentElement.style.setProperty("--fit-style", "fit");
|
|
document.documentElement.style.setProperty("--myvideo-max-width", "100vw");
|
|
document.documentElement.style.setProperty("--myvideo-width", "100vw");
|
|
document.documentElement.style.setProperty("--myvideo-height", "100vh");
|
|
}
|
|
|
|
if (urlParams.has("record")) {
|
|
if (!session.cleanOutput) {
|
|
if (SafariVersion && !MediaRecorder) {
|
|
if (macOS) {
|
|
warnUser("Your browser may not support local media recording.\n\nTry Chrome instead if on macOS.");
|
|
} else {
|
|
warnUser("Your browser or device may not support local media recording.\n\nSafari sometimes allows the feature to be enabled via its experimental settings.");
|
|
}
|
|
} else if (SafariVersion) {
|
|
if (macOS) {
|
|
warnUser("It is recommended to use Chrome instead of Safari if doing local media recordings.");
|
|
} else if (SafariVersion <= 15) {
|
|
warnUser("Please update your device.\n\nOlder versions of Safari may crash after recording for a few minutes.");
|
|
} else {
|
|
warnUser("Local media recordings are an experimental feature on Apple devices.\n\nPlease at least test it out a few times first.");
|
|
}
|
|
}
|
|
}
|
|
session.recordLocal = urlParams.get("record");
|
|
|
|
if (session.recordLocal === "false" || session.recordLocal === "off") {
|
|
session.record = false;
|
|
session.recordLocal = false;
|
|
} else if (session.recordLocal != parseInt(session.recordLocal)) {
|
|
session.recordLocal = session.recordDefault;
|
|
} else if (session.recordLocal !== null){
|
|
session.recordLocal = parseInt(session.recordLocal);
|
|
} else {
|
|
session.recordLocal = session.recordDefault;
|
|
}
|
|
}
|
|
|
|
if (session.record === false) {
|
|
getById("recordLocalbutton").classList.add("hidden");
|
|
getById("recordLocalScreenbutton").classList.add("hidden");
|
|
try {
|
|
document.querySelectorAll('[data-action-type^="record"]').forEach(ele => {
|
|
ele.remove();
|
|
delete ele;
|
|
});
|
|
document.querySelectorAll('[data-action="Record"]').forEach(ele => {
|
|
ele.parentNode.remove();
|
|
delete ele.parentNode;
|
|
});
|
|
} catch (e) {
|
|
errorlog(e);
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("autorecord")) {
|
|
session.autorecord = true;
|
|
if (session.recordLocal === false) {
|
|
let bitautorec = urlParams.get("autorecord");
|
|
if (bitautorec !== "") {
|
|
session.recordLocal = parseInt(bitautorec);
|
|
} else {
|
|
session.recordLocal = session.recordDefault;
|
|
}
|
|
}
|
|
}
|
|
if (urlParams.has("autorecordlocal")) {
|
|
session.autorecordlocal = true;
|
|
if (session.recordLocal === false) {
|
|
session.recordLocal = urlParams.get("autorecordlocal");
|
|
if (session.recordLocal != parseInt(session.recordLocal)) {
|
|
session.recordLocal = session.recordDefault;
|
|
} else if (session.recordLocal !== ""){
|
|
session.recordLocal = parseInt(session.recordLocal);
|
|
} else {
|
|
session.recordLocal = session.recordDefault;
|
|
}
|
|
}
|
|
}
|
|
if (urlParams.has("autorecordremote")) {
|
|
session.autorecordremote = true;
|
|
if (session.recordLocal === false) {
|
|
session.recordLocal = urlParams.get("autorecordremote");
|
|
if (session.recordLocal != parseInt(session.recordLocal)) {
|
|
session.recordLocal = session.recordDefault;
|
|
} else if (session.recordLocal !== ""){
|
|
session.recordLocal = parseInt(session.recordLocal);
|
|
} else {
|
|
session.recordLocal = session.recordDefault;
|
|
}
|
|
}
|
|
}
|
|
if (urlParams.has("splitrecording")) {
|
|
// minutes
|
|
session.recordingInterval = urlParams.get("splitrecording") || 5; // 5 minutes
|
|
session.recordingInterval = parseInt(session.recordingInterval) || 1;
|
|
// For Mac: https://gist.github.com/steveseguin/8083172a20ad7c9ebcb449e22fc8fe67
|
|
// For Windows: https://gist.github.com/steveseguin/7ca1df1df9ec6042f27ecc8d258e3f30
|
|
}
|
|
if (urlParams.has("pcm")) {
|
|
session.pcm = true;
|
|
}
|
|
if (urlParams.has("recordcodec") || urlParams.has("rc")) {
|
|
session.recordingVideoCodec = urlParams.get("recordcodec") || urlParams.get("rc") || false;
|
|
}
|
|
if (urlParams.has("recordfolder")) {
|
|
session.GDRIVE_FOLDERNAME = urlParams.get("recordfolder") || "";
|
|
}
|
|
|
|
if (urlParams.has("bigbutton")) {
|
|
session.bigmutebutton = true;
|
|
getById("mutebutton").classList.add("bigbutton");
|
|
if (urlParams.get("bigbutton")) {
|
|
let bigbuttontext = document.createElement("span");
|
|
bigbuttontext.innerText = urlParams.get("bigbutton");
|
|
bigbuttontext.className = "bigbuttontext";
|
|
getById("mutebutton").appendChild(bigbuttontext);
|
|
}
|
|
}
|
|
|
|
if (urlParams.get("rows")) {
|
|
session.rows = urlParams.get("rows");
|
|
session.rows = session.rows.split(",");
|
|
}
|
|
|
|
if (urlParams.has("nosettings")) {
|
|
session.nosettings = true;
|
|
getById("settingsbutton").classList.add("hidden");
|
|
}
|
|
|
|
if (urlParams.has("publish")) {
|
|
session.publish = true;
|
|
getById("publishSettings").style.display = "block";
|
|
|
|
if (session.recordLocal !== false){
|
|
getById("startRecordingButton").classList.remove("hidden");
|
|
//session.autorecord = true;
|
|
//getById("startPublishingButton").classList.add("hidden");
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("obscontrols") || urlParams.has("remoteobs") || urlParams.has("obsremote") || urlParams.has("obs") || urlParams.has("controlobs")) {
|
|
session.obsControls = urlParams.get("obscontrols") || urlParams.get("remoteobs") || urlParams.get("obsremote") || urlParams.get("obs") || urlParams.get("controlobs");
|
|
if (session.obsControls) {
|
|
// whether to show the button or not; that's it.
|
|
session.obsControls = session.obsControls.toLowerCase();
|
|
}
|
|
if (session.obsControls == "false") {
|
|
session.obsControls = false;
|
|
} else if (session.obsControls == "0") {
|
|
session.obsControls = false;
|
|
} else if (session.obsControls == "no") {
|
|
session.obsControls = false;
|
|
} else if (session.obsControls == "off") {
|
|
session.obsControls = false;
|
|
} else if (session.obsControls == "full") {
|
|
try {
|
|
session.dataMode = true;
|
|
session.obsControls = true;
|
|
//session.doNotSeed = true;
|
|
getById("main").classList.add("fullscreenOBSControl");
|
|
toggleOBSControls();
|
|
} catch(e){errorlog(e);}
|
|
} else if (session.obsControls) {
|
|
session.obsControls = session.obsControls.toLowerCase();
|
|
} else {
|
|
session.obsControls = true;
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("nopush") || urlParams.has("noseed") || urlParams.has("viewonly") || urlParams.has("viewmode")) {
|
|
// this is like a scene; Seeding is disabled. Can be used with &showall to show all videos on load
|
|
session.doNotSeed = true;
|
|
|
|
if (session.scene === false) {
|
|
session.scene = null; // not a scene, but sorta. false vs null makes a difference here.
|
|
}
|
|
|
|
session.dataMode = true; // thios will let us connect
|
|
// session.showall = true; // this can be used to SHOW the videos. (&showall)
|
|
}
|
|
|
|
if (urlParams.has("scene") || urlParams.has("scn")) {
|
|
session.scene = urlParams.get("scene") || urlParams.get("scn") || 0;
|
|
if (typeof session.scene === "string") {
|
|
session.scene = session.scene.replace(/[\W]+/g, "_");
|
|
} else {
|
|
session.scene = (parseInt(session.scene) || 0) + "";
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("morescenes")) {
|
|
let moreScenes = urlParams.get("morescenes") || 16;
|
|
moreScenes = parseInt(moreScenes) || 0;
|
|
if (moreScenes < 8) {
|
|
moreScenes = 8;
|
|
}
|
|
session.maxScene = moreScenes;
|
|
let sceneButtonMain = document.querySelector("#controls_blank .sceneButtons button");
|
|
if (sceneButtonMain && moreScenes) {
|
|
var i = 8;
|
|
while (i < moreScenes) {
|
|
i++;
|
|
let sceneButton = sceneButtonMain.cloneNode(true);
|
|
sceneButton.dataset.scene = i;
|
|
sceneButton.title = "Add to Scene " + i;
|
|
sceneButton.innerHTML = "<span>S" + i + "</span>";
|
|
document.querySelector("#controls_blank .sceneButtons").appendChild(sceneButton);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("solo")) {
|
|
if (session.scene === false) {
|
|
session.scene = "0";
|
|
}
|
|
session.solo = true;
|
|
}
|
|
|
|
if (session.scene !== false) {
|
|
session.disableWebAudio = true;
|
|
if (session.audioEffects === null) {
|
|
session.audioEffects = false;
|
|
}
|
|
session.audioMeterGuest = false;
|
|
}
|
|
|
|
if (urlParams.has("fakeuser")) {
|
|
log("ICE FILTER ENABLED");
|
|
session.fakeUser = true;
|
|
session.dataMode = true;
|
|
session.autostart = true;
|
|
session.novideo = [];
|
|
session.noaudio = [];
|
|
session.noiframe = [];
|
|
session.cleanOutput = true;
|
|
}
|
|
|
|
if (urlParams.has("retransmit")) {
|
|
session.retransmit = true;
|
|
session.dataMode = true;
|
|
}
|
|
|
|
if (urlParams.has("datamode") || urlParams.has("dataonly")) {
|
|
// this disables all media in/out.
|
|
session.dataMode = true;
|
|
}
|
|
|
|
if (urlParams.has("pseudoguest") || urlParams.has("pseudoscene")) {
|
|
session.videoDevice = 0;
|
|
session.audioDevice = 0;
|
|
getById("mainmenu").classList.add("hidden");
|
|
getById("header").classList.add("hidden");
|
|
getById("mainmenu").style.display = "none";
|
|
getById("header").style.display = "none";
|
|
session.showList = false;
|
|
session.autostart = true;
|
|
getById("controlButtons").classList.add("hidden");
|
|
getById("controlButtons").style.display = "none";
|
|
getById("miniTaskBar").classList.add("hidden");
|
|
getById("miniTaskBar").style.display = "none";
|
|
session.dedicatedControlBarSpace = false;
|
|
session.pseudoguest = true;
|
|
}
|
|
|
|
if (session.dataMode) {
|
|
if (!(session.meshcast || session.whipOutput !== false || session.screenshare)) {
|
|
session.videoDevice = 0;
|
|
session.audioDevice = 0;
|
|
}
|
|
|
|
getById("mainmenu").classList.add("hidden");
|
|
//session.autohide = true;
|
|
//session.autostart = true;
|
|
//session.novideo = [];
|
|
//session.noaudio = [];
|
|
//session.noiframe = [];
|
|
//session.webcamonly = true;
|
|
}
|
|
|
|
if (urlParams.has("autoadd")) {
|
|
// the streams we want to view; if set, but let blank, we will request no streams to watch.
|
|
session.autoadd = urlParams.get("autoadd") || null; // this value can be comma seperated for multiple streams to pull
|
|
|
|
if (session.autoadd == null) {
|
|
session.autoadd = false;
|
|
}
|
|
if (session.autoadd) {
|
|
session.autoadd = session.autoadd.split(",");
|
|
}
|
|
}
|
|
|
|
//if (session.scene!=="1"){ // scene =0 and 1 should load instantly.
|
|
// session.hiddenSceneViewBitrate = 0; // By default this is ~ 400kbps, but if you have 10 scenes, i don't want to kill things.
|
|
//}
|
|
|
|
if (urlParams.has("hiddenscenebitrate")) {
|
|
session.hiddenSceneViewBitrate = parseInt(urlParams.get("hiddenscenebitrate")) || 0;
|
|
} else if (urlParams.has("layout") && session.scene !== false && !session.viewslot) {
|
|
session.hiddenSceneViewBitrate = false;
|
|
} else if (urlParams.has("nohiddensceneoptimization")) {
|
|
session.hiddenSceneViewBitrate = false;
|
|
}
|
|
|
|
if (urlParams.has("preloadbitrate")) {
|
|
session.preloadbitrate = parseInt(urlParams.get("preloadbitrate")) || 0; // 1000
|
|
}
|
|
|
|
if (urlParams.has("rampuptime")) {
|
|
session.rampUpTime = parseInt(urlParams.get("rampuptime")) || 10000;
|
|
}
|
|
|
|
if (urlParams.has("scenetype") || urlParams.has("type")) {
|
|
session.sceneType = parseInt(urlParams.get("scenetype")) || parseInt(urlParams.get("type")) || false;
|
|
}
|
|
|
|
if (urlParams.has("mediasettings")) {
|
|
session.forceMediaSettings = true;
|
|
}
|
|
|
|
if (urlParams.has("transcript") || urlParams.has("transcribe") || urlParams.has("trans")) {
|
|
session.transcript = urlParams.get("transcript") || urlParams.get("transcribe") || urlParams.get("trans") || "en-US";
|
|
}
|
|
|
|
if (urlParams.has("cc") || urlParams.has("closedcaptions") || urlParams.has("captions")) {
|
|
session.closedCaptions = true;
|
|
}
|
|
if (urlParams.has("nocclabels") || urlParams.has("nocclabel") || urlParams.has("nocaptionlabels") || urlParams.has("nocaptionlabel")) {
|
|
session.nocaptionlabels = true;
|
|
}
|
|
if (urlParams.has("cccolored") || urlParams.has("cccoloured") || urlParams.has("coloredcc") || urlParams.has("colorcc") || urlParams.has("cccolor")) {
|
|
session.ccColored = true;
|
|
}
|
|
|
|
|
|
if (urlParams.has("base64css") || urlParams.has("b64css") || urlParams.has("cssbase64") || urlParams.has("cssb64")) {
|
|
try {
|
|
var base64Css = urlParams.get("base64css") || urlParams.get("b64css") || urlParams.get("cssbase64") || urlParams.get("cssb64");
|
|
try {
|
|
base64Css = atob(base64Css); // window.btoa(encodeURIComponent("#mainmenu{background-color: pink;}" ));
|
|
} catch (e) {}
|
|
try {
|
|
base64Css = decodeURIComponent(base64Css); // window.btoa(encodeURIComponent("#mainmenu{background-color: pink; ❤" ));
|
|
} catch (e) {}
|
|
|
|
try {
|
|
if (["invite.cam","invitecamera.com"].includes(getParentHostname())){
|
|
session.iFramesAllowed = false;
|
|
console.warn("For security and privacy purposes, please note that you will not be allowed to use CSS injection together with IFRAMES.");
|
|
} else if ((window !== window.top) || window.obsstudio) {
|
|
// allowed
|
|
} else {
|
|
console.warn("For security and privacy purposes, please note that you will not be allowed to use CSS injection together with IFRAMES.");
|
|
session.iFramesAllowed = false;
|
|
}
|
|
} catch(e){
|
|
warnlog(e);
|
|
}
|
|
|
|
var cssStyleSheet = document.createElement("style");
|
|
cssStyleSheet.innerText = base64Css;
|
|
document.querySelector("head").appendChild(cssStyleSheet);
|
|
} catch (e) {
|
|
console.error(e);
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("css")) {
|
|
var cssURL = urlParams.get("css");
|
|
try {
|
|
cssURL = decodeURI(cssURL);
|
|
} catch(e){
|
|
warnlog(e);
|
|
}
|
|
log(cssURL);
|
|
|
|
let validURL = false;
|
|
try {
|
|
cssUrlObj = new URL(cssURL);
|
|
validURL = true;
|
|
} catch(e){
|
|
}
|
|
try {
|
|
if (validURL){
|
|
const cssDomain = cssUrlObj.hostname;
|
|
|
|
try {
|
|
if (["invite.cam","invitecamera.com"].includes(getParentHostname())){
|
|
session.iFramesAllowed = false;
|
|
console.warn("For security and privacy purposes, please note that you will not be allowed to use CSS injection together with IFRAMES.");
|
|
} else if ((window.location.hostname === cssDomain) || window.location.hostname.endsWith("."+cssDomain) || (window !== window.top) || window.obsstudio) {
|
|
if (window.location.hostname !== cssDomain){
|
|
console.warn("Third-party CSS has been injected into the site. Security cannot be ensured.");
|
|
}
|
|
} else {
|
|
console.warn("For security and privacy purposes, please note that you will not be allowed to use CSS injection together with IFRAMES.");
|
|
session.iFramesAllowed = false;
|
|
}
|
|
} catch(e){
|
|
warnlog(e);
|
|
}
|
|
|
|
var cssStylesheet = document.createElement("link");
|
|
cssStylesheet.rel = "stylesheet";
|
|
cssStylesheet.type = "text/css";
|
|
cssStylesheet.media = "screen";
|
|
cssStylesheet.href = cssURL;
|
|
document.getElementsByTagName("head")[0].appendChild(cssStylesheet);
|
|
|
|
cssStylesheet.onload = function () {
|
|
getById("main").classList.remove("hidden");
|
|
log("loaded remote style sheet");
|
|
};
|
|
|
|
cssStylesheet.onerror = function () {
|
|
getById("main").classList.remove("hidden");
|
|
errorlog("REMOTE STYLE SHEET HAD ERROR");
|
|
};
|
|
} else {
|
|
try {
|
|
if (["invite.cam","invitecamera.com"].includes(getParentHostname())){
|
|
console.warn("For security and privacy purposes, please note that you will not be allowed to use CSS injection together with IFRAMES.");
|
|
session.iFramesAllowed = false;
|
|
} else if ((window !== window.top) || window.obsstudio) {
|
|
// allowed
|
|
} else {
|
|
console.warn("For security and privacy purposes, please note that you will not be allowed to use CSS injection together with IFRAMES.");
|
|
session.iFramesAllowed = false;
|
|
}
|
|
} catch(e){
|
|
warnlog(e);
|
|
}
|
|
var cssStylesheet = document.createElement("style");
|
|
cssStylesheet.innerHTML = cssURL;
|
|
document.getElementsByTagName("head")[0].appendChild(cssStylesheet);
|
|
getById("main").classList.remove("hidden");
|
|
}
|
|
|
|
} catch(e){
|
|
warnlog(e);
|
|
}
|
|
} else {
|
|
getById("main").classList.remove("hidden");
|
|
}
|
|
|
|
if (urlParams.has("avatar")) {
|
|
var avatar = urlParams.get("avatar") || false;
|
|
if (avatar && avatar == "default") {
|
|
session.avatar = document.getElementById("defaultAvatar2");
|
|
session.avatar.ready = false;
|
|
session.avatar.onload = () => {
|
|
session.avatar.ready = true;
|
|
getById("noAvatarSelected3").classList.remove("selected");
|
|
getById("noAvatarSelected").classList.remove("selected");
|
|
getById("defaultAvatar1").classList.add("selected");
|
|
getById("defaultAvatar2").classList.add("selected");
|
|
};
|
|
if (session.avatar.complete) {
|
|
session.avatar.ready = true;
|
|
getById("noAvatarSelected3").classList.remove("selected");
|
|
getById("noAvatarSelected").classList.remove("selected");
|
|
getById("defaultAvatar1").classList.add("selected");
|
|
getById("defaultAvatar2").classList.add("selected");
|
|
}
|
|
} else if (avatar) {
|
|
try {
|
|
avatar = decodeURIComponent(avatar);
|
|
} catch (e) {}
|
|
|
|
session.avatar = getById("defaultAvatar2");
|
|
session.avatar.ready = false;
|
|
session.avatar.onload = () => {
|
|
session.avatar.ready = true;
|
|
getById("noAvatarSelected3").classList.remove("selected");
|
|
getById("noAvatarSelected").classList.remove("selected");
|
|
getById("defaultAvatar1").classList.add("selected");
|
|
getById("defaultAvatar2").classList.add("selected");
|
|
};
|
|
getById("defaultAvatar1").src = avatar;
|
|
getById("defaultAvatar2").src = avatar;
|
|
}
|
|
getById("avatarDiv3").classList.remove("hidden");
|
|
getById("avatarDiv").classList.remove("hidden");
|
|
}
|
|
|
|
if (urlParams.has("prompt") || urlParams.has("validate") || urlParams.has("approve")) {
|
|
session.promptAccess = true;
|
|
}
|
|
|
|
if (urlParams.has("js")) {
|
|
// ie: &js=https%3A%2F%2Fvdo.ninja%2Fexamples%2Ftestjs.js
|
|
try {
|
|
var jsURL = urlParams.get("js");
|
|
try {
|
|
jsURL = decodeURI(jsURL);
|
|
} catch(e){
|
|
warnlog(e);
|
|
}
|
|
log(jsURL);
|
|
|
|
const jsUrlObj = new URL(jsURL);
|
|
const jsDomain = jsUrlObj.hostname;
|
|
let allow = false;
|
|
try {
|
|
if (["invite.cam","invitecamera.com"].includes(getParentHostname())){
|
|
console.error("For security and privacy purposes, Javascript injection using Invite Cam must be consented to.");
|
|
if (!session.cleanOutput){
|
|
allow = await confirmAlt("This link wishes to inject third-party Javascript ⚠️\n\nIf you trust the link, click OK. Otherwise, click Cancel.", true);
|
|
}
|
|
} else if ((window.location.hostname === jsDomain) || window.location.hostname.endsWith("."+jsDomain) || (window !== window.top) || window.obsstudio) {
|
|
// same domains, iframes, or OBS can run javascript.
|
|
allow = true;
|
|
if (window.location.hostname !== jsDomain){
|
|
console.warn("Third-party Javascript has been injected into the code. Security cannot be ensured.");
|
|
}
|
|
} else if (!session.cleanOutput){
|
|
// to allow flexibility, we will allow it if the user consents
|
|
allow = await confirmAlt("This link wishes to inject third-party Javascript ⚠️\n\nIf you trust the link, click OK. Otherwise, click cancel.", true);
|
|
}
|
|
} catch(e){
|
|
allow = true;
|
|
warnlog(e);
|
|
}
|
|
|
|
if (allow){
|
|
// type="text/javascript" crossorigin="anonymous"
|
|
let externalJavaascript = document.createElement("script");
|
|
externalJavaascript.type = "text/javascript";
|
|
externalJavaascript.crossorigin = "anonymous";
|
|
externalJavaascript.src = jsURL;
|
|
externalJavaascript.onerror = function () {
|
|
warnlog("Third-party Javascript failed to load");
|
|
};
|
|
externalJavaascript.onload = function () {
|
|
log("Third-party Javascript loaded");
|
|
};
|
|
document.head.appendChild(externalJavaascript);
|
|
} else {
|
|
console.error("For security/privacy purposes, Javascript injection is now only allowed if used within an IFRAME or if the JS file is hosted on the same domain.");
|
|
}
|
|
} catch(e){
|
|
errorlog(e);
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("base64js") || urlParams.has("b64js") || urlParams.has("jsbase64") || urlParams.has("jsb64")) {
|
|
try {
|
|
let allow = false;
|
|
try {
|
|
if (["invite.cam","invitecamera.com"].includes(getParentHostname())){
|
|
console.error("For security and privacy purposes, Javascript injection using Invite Cam must be consented to.");
|
|
if (!session.cleanOutput){
|
|
allow = await confirmAlt("This link wishes to inject third-party Javascript ⚠️\n\nIf you trust the link, click OK. Otherwise, click Cancel.", true);
|
|
}
|
|
} else if ((window !== window.top) || window.obsstudio) {
|
|
// iframes or OBS can run javascript.
|
|
allow = true;
|
|
console.warn("Third-party Javascript has been injected into the code. Security cannot be ensured.");
|
|
} else if (!session.cleanOutput){
|
|
// to allow flexibility, we will allow it if the user consents
|
|
allow = await confirmAlt("This link wishes to inject third-party Javascript ⚠️\n\nIf you trust the link, click OK. Otherwise, click Cancel.", true);
|
|
}
|
|
} catch(e){
|
|
warnlog(e);
|
|
allow = true;
|
|
}
|
|
|
|
if (allow){
|
|
var base64js = urlParams.get("base64js") || urlParams.get("b64js") || urlParams.get("jsbase64") || urlParams.get("jsb64");
|
|
base64js = decodeURIComponent(atob(base64js)); // window.btoa(encodeURIComponent("alert('hi')")); // ?jsb64=YWxlcnQoJ2hpJyk7
|
|
var externalJavaascript = document.createElement("script");
|
|
externalJavaascript.type = "text/javascript";
|
|
externalJavaascript.crossorigin = "anonymous";
|
|
externalJavaascript.innerHTML = base64js;
|
|
externalJavaascript.onerror = function () {
|
|
errorlog("Third-party Javascript failed to load");
|
|
};
|
|
externalJavaascript.onload = function () {
|
|
log("Third-party Javascript loaded");
|
|
};
|
|
document.head.appendChild(externalJavaascript);
|
|
} else {
|
|
console.error("For security/privacy purposes, Javascript B64 injection is now only allowed if used within an IFRAME.");
|
|
}
|
|
} catch (e) {
|
|
console.error(e);
|
|
}
|
|
}
|
|
|
|
session.sitePassword = session.defaultPassword;
|
|
if (urlParams.has("password") || urlParams.has("pass") || urlParams.has("pw") || urlParams.has("p") || (session.password===null)) {
|
|
session.password = urlParams.get("password") || urlParams.get("pass") || urlParams.get("pw") || urlParams.get("p") || null;
|
|
|
|
if (!session.password) {
|
|
window.focus();
|
|
session.password = await promptAlt(getTranslation("enter-password"), true, true);
|
|
if (session.password) {
|
|
session.password = session.password.trim();
|
|
}
|
|
} else if (session.password === "false") {
|
|
session.password = false;
|
|
session.defaultPassword = false;
|
|
} else if (session.password === "0") {
|
|
session.password = false;
|
|
session.defaultPassword = false;
|
|
} else if (session.password === "off") {
|
|
session.password = false;
|
|
session.defaultPassword = false;
|
|
} else {
|
|
try {
|
|
session.password = decodeURIComponent(session.password); // will be re-encoded in a moment.
|
|
} catch (e) {
|
|
errorlog(e);
|
|
}
|
|
}
|
|
} else if (urlParams.has("nopassword") || urlParams.has("nopass") || urlParams.has("nopw") || urlParams.has("p0")) {
|
|
session.password = false;
|
|
session.defaultPassword = false;
|
|
}
|
|
|
|
if (session.password) {
|
|
getById("passwordRoom").value = session.password;
|
|
session.password = sanitizePassword(session.password);
|
|
session.defaultPassword = false;
|
|
getById("addPasswordBasic").style.display = "none";
|
|
}
|
|
|
|
if (urlParams.has("salt") && urlParams.get("salt")) {
|
|
session.salt = urlParams.get("salt");
|
|
}
|
|
|
|
if (urlParams.has("showconnections")) {
|
|
session.showConnections = true; // shows remote guest connections as a stat
|
|
}
|
|
|
|
if (urlParams.has("hash") || urlParams.has("crc") || urlParams.has("check")) {
|
|
// could be brute forced in theory, so not as safe as just not using a hash check.
|
|
session.taintedSession = null; // waiting to see if valid or not.
|
|
var hash_input = urlParams.get("hash") || urlParams.get("crc") || urlParams.get("check");
|
|
if (session.password === false) {
|
|
window.focus();
|
|
session.password = await promptAlt(getTranslation("enter-password-2"), true, true);
|
|
session.password = sanitizePassword(session.password);
|
|
getById("passwordRoom").value = session.password;
|
|
session.defaultPassword = false;
|
|
}
|
|
|
|
generateHash(session.password + session.salt, 6)
|
|
.then(function (hash) {
|
|
// million to one error. I won't
|
|
log("hash is " + hash);
|
|
if (hash.substring(0, hash_input.length) !== hash_input) {
|
|
// this hash crc check is usually just the first 4 characters, but i'll match based on whatever is provided;
|
|
// max 6 length for security. 2 could be a good option for better security but more than 6 is too big of a security concern.
|
|
generateHash(session.password + "obs.ninja", 6)
|
|
.then(function (hash2) {
|
|
// million to one error; this is to support a legacy salt used. Depreciated, and will be removed eventually
|
|
log("hash2 is " + hash2);
|
|
if (hash2.substring(0, 4) !== hash_input) {
|
|
// this legacy hash crc checks is always 4 characters
|
|
session.taintedSession = true;
|
|
if (!session.cleanOutput) {
|
|
miniTranslate(getById("request_info_prompt"), "password-incorrect");
|
|
//getById("request_info_prompt").innerHTML = getTranslation("password-incorrect");
|
|
getById("request_info_prompt").style.display = "block";
|
|
getById("mainmenu").style.display = "none";
|
|
getById("head1").style.display = "none";
|
|
session.cleanOutput = true;
|
|
} else {
|
|
getById("request_info_prompt").innerHTML = "";
|
|
getById("request_info_prompt").style.display = "block";
|
|
getById("mainmenu").style.display = "none";
|
|
getById("head1").style.display = "none";
|
|
}
|
|
} else {
|
|
session.taintedSession = false;
|
|
session.hash = hash;
|
|
}
|
|
})
|
|
.catch(errorlog);
|
|
} else {
|
|
session.taintedSession = false;
|
|
session.hash = hash;
|
|
}
|
|
})
|
|
.catch(errorlog);
|
|
}
|
|
|
|
if (session.defaultPassword !== false) {
|
|
session.password = session.defaultPassword; // no user entered password; let's use the default password if its not disabled.
|
|
}
|
|
|
|
if (urlParams.has("showlabels") || urlParams.has("showlabel") || urlParams.has("sl")) {
|
|
session.showlabels = urlParams.get("showlabels") || urlParams.get("showlabel") || urlParams.get("sl") || "";
|
|
session.showlabels = sanitizeLabel(session.showlabels.replace(/[\W]+/g, "_").replace(/_+/g, "_"));
|
|
//session.style = 6;
|
|
|
|
if (session.showlabels == "") {
|
|
session.labelstyle = false;
|
|
} else {
|
|
session.labelstyle = session.showlabels;
|
|
}
|
|
|
|
session.showlabels = true;
|
|
session.manual = session.manual === null ? false : session.manual;
|
|
session.windowed = session.windowed === null ? false : session.windowed;
|
|
}
|
|
|
|
if (urlParams.has("sizelabel") || urlParams.has("labelsize") || urlParams.has("fontsize")) {
|
|
session.labelsize = urlParams.get("sizelabel") || urlParams.get("labelsize") || urlParams.get("fontsize") || 100;
|
|
session.labelsize = parseInt(session.labelsize);
|
|
}
|
|
|
|
if (urlParams.has("label") || urlParams.has("l")) {
|
|
session.label = urlParams.get("label") || urlParams.get("l") || null;
|
|
var updateURLAsNeed = true;
|
|
if (session.label == null || session.label.length == 0) {
|
|
window.focus();
|
|
session.label = await promptAlt(getTranslation("enter-display-name"), true);
|
|
} else {
|
|
var updateURLAsNeed = false;
|
|
try {
|
|
session.label = decodeURIComponent(session.label);
|
|
} catch (e) {
|
|
errorlog(e);
|
|
}
|
|
session.label = session.label.replace(/_/g, " ");
|
|
}
|
|
if (session.label != null) {
|
|
session.label = sanitizeLabel(session.label); // alphanumeric was too strict.
|
|
document.title = session.label; // what the result is.
|
|
|
|
if (updateURLAsNeed) {
|
|
var label = encodeURIComponent(session.label);
|
|
if (urlParams.has("l")) {
|
|
updateURL("l=" + label, true, false);
|
|
} else {
|
|
updateURL("label=" + label, true, false);
|
|
}
|
|
}
|
|
}
|
|
} else if (urlParams.has("defaultlabel") || urlParams.has("labelsuggestion") || urlParams.has("ls")) {
|
|
session.label = urlParams.get("defaultlabel") || urlParams.get("labelsuggestion") || urlParams.get("ls") || null;
|
|
var updateURLAsNeed = true;
|
|
window.focus();
|
|
var label = await promptAlt(getTranslation("enter-display-name"), true);
|
|
if (label) {
|
|
session.label = sanitizeLabel(label); // alphanumeric was too strict.
|
|
} else {
|
|
session.label = sanitizeLabel(session.label);
|
|
updateURLAsNeed = false;
|
|
}
|
|
|
|
document.title = session.label; // what the result is.
|
|
|
|
if (updateURLAsNeed) {
|
|
var label = encodeURIComponent(session.label);
|
|
if (urlParams.has("l")) {
|
|
updateURL("l=" + label, true, false);
|
|
} else {
|
|
updateURL("label=" + label, true, false);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (session.label){
|
|
pokeIframeAPI("this-label", session.label);
|
|
}
|
|
|
|
if (urlParams.has("transparent") || urlParams.has("transparency")) {
|
|
// sets the window to be transparent - useful for IFRAMES?
|
|
session.transparent = true;
|
|
}
|
|
|
|
if (session.transparent) {
|
|
getById("main").style.backgroundColor = "rgba(0,0,0,0)";
|
|
document.documentElement.style.setProperty("--container-color", "#0000");
|
|
document.documentElement.style.setProperty("--background-color", "#0000");
|
|
document.documentElement.style.setProperty("--regular-margin", "0");
|
|
document.documentElement.style.setProperty("--director-margin", "0 25px 0 0");
|
|
document.documentElement.style.setProperty("--discord-grey-1a", "#0000");
|
|
getById("directorLinksButton").style.color = "black";
|
|
getById("main").style.overflow = "hidden";
|
|
}
|
|
|
|
if (urlParams.has("stereo") || urlParams.has("s") || urlParams.has("proaudio")) {
|
|
// both peers need this enabled for HD stereo to be on. If just pub, you get no echo/noise cancellation. if just viewer, you get high bitrate mono
|
|
log("STEREO ENABLED");
|
|
session.stereo = urlParams.get("stereo") || urlParams.get("s") || urlParams.get("proaudio");
|
|
|
|
if (session.stereo) {
|
|
session.stereo = session.stereo.toLowerCase();
|
|
}
|
|
|
|
//var supportedConstraints = navigator.mediaDevices.getSupportedConstraints();
|
|
//supportedConstraints.channelCount;
|
|
|
|
if (session.stereo === "false") {
|
|
session.stereo = 0;
|
|
session.audioInputChannels = 1;
|
|
} else if (session.stereo === "0") {
|
|
session.stereo = 0;
|
|
session.audioInputChannels = 1;
|
|
} else if (session.stereo === "no") {
|
|
session.stereo = 0;
|
|
session.audioInputChannels = 1;
|
|
} else if (session.stereo === "off") {
|
|
session.stereo = 0;
|
|
session.audioInputChannels = 1;
|
|
} else if (session.stereo === "1") {
|
|
session.stereo = 1;
|
|
} else if (session.stereo === "both") {
|
|
session.stereo = 1;
|
|
} else if (session.stereo === "3") {
|
|
session.stereo = 3;
|
|
} else if (session.stereo === "out") {
|
|
session.stereo = 3;
|
|
} else if (session.stereo === "mono") {
|
|
session.stereo = 3;
|
|
session.audiobitrate = 128;
|
|
} else if (session.stereo === "4") {
|
|
session.stereo = 4;
|
|
} else if (session.stereo === "multi") {
|
|
session.stereo = 4;
|
|
} else if (session.stereo === "8") {
|
|
session.stereo = 8;
|
|
} else if (session.stereo === "surround") {
|
|
session.stereo = 8;
|
|
} else if (session.stereo === "2") {
|
|
session.stereo = 2;
|
|
} else if (session.stereo === "6") {
|
|
session.stereo = 6;
|
|
} else if (session.stereo === "in") {
|
|
session.stereo = 2;
|
|
} else {
|
|
session.stereo = 5; // guests; no stereo in, no high bitrate in, but otherwise like stereo=1
|
|
}
|
|
|
|
getById("whipoutstereo").classList.add("hidden");
|
|
}
|
|
|
|
if (urlParams.has("screensharestereo") || urlParams.has("sss") || urlParams.has("ssproaudio")) {
|
|
// both peers need this enabled for HD stereo to be on. If just pub, you get no echo/noise cancellation. if just viewer, you get high bitrate mono
|
|
log("screenshare stereo ENABLED");
|
|
session.screenshareStereo = urlParams.get("screensharestereo") || urlParams.get("sss") || urlParams.get("ssproaudio");
|
|
|
|
if (session.screenshareStereo) {
|
|
session.screenshareStereo = session.screenshareStereo.toLowerCase();
|
|
}
|
|
|
|
if (session.screenshareStereo === "false") {
|
|
session.screenshareStereo = 0;
|
|
} else if (session.screenshareStereo === "0") {
|
|
session.screenshareStereo = 0;
|
|
} else if (session.screenshareStereo === "no") {
|
|
session.screenshareStereo = 0;
|
|
} else if (session.screenshareStereo === "off") {
|
|
session.screenshareStereo = 0;
|
|
} else if (session.screenshareStereo === "1") {
|
|
session.screenshareStereo = 1;
|
|
} else if (session.screenshareStereo === "both") {
|
|
session.screenshareStereo = 1;
|
|
} else if (session.screenshareStereo === "3") {
|
|
session.screenshareStereo = 3;
|
|
} else if (session.screenshareStereo === "out") {
|
|
session.screenshareStereo = 3;
|
|
} else if (session.screenshareStereo === "mono") {
|
|
session.screenshareStereo = 3;
|
|
} else if (session.screenshareStereo === "4") {
|
|
session.screenshareStereo = 4;
|
|
} else if (session.screenshareStereo === "multi") {
|
|
session.screenshareStereo = 4;
|
|
} else if (session.screenshareStereo === "2") {
|
|
session.screenshareStereo = 2;
|
|
} else if (session.screenshareStereo === "in") {
|
|
session.screenshareStereo = 2;
|
|
} else {
|
|
session.screenshareStereo = 5; // guests; no stereo in, no high bitrate in, but otherwise like stereo=1
|
|
}
|
|
}
|
|
|
|
// Deploy your own handshake server for free; see: https://github.com/steveseguin/websocket_server
|
|
if (urlParams.has("pie")) {
|
|
// piesocket.com support is to be deprecated after dec/19/21, since piesocket is no longer a free service.
|
|
session.customWSS = urlParams.get("pie") || true; // If session.customWSS == true, then there is no need to set parameters via URL
|
|
session.wssSetViaUrl = true;
|
|
if (session.customWSS && session.customWSS !== true) {
|
|
session.wss = "wss://free3.piesocket.com/v3/1?api_key=" + session.customWSS; // if URL param is set, it will use the API key.
|
|
}
|
|
}
|
|
|
|
if ((Firefox && !session.stereo) || session.stereo === 3) {
|
|
session.mono = true; // this will set the SDP to mono if firefox
|
|
}
|
|
|
|
if (urlParams.has("mono")) {
|
|
session.mono = true;
|
|
if (session.stereo == 1 || session.stereo == 4) {
|
|
session.stereo = 3;
|
|
session.audiobitrate = 128;
|
|
} else if (session.stereo == 5) {
|
|
session.stereo = 3; // stereo out only
|
|
session.audiobitrate = 128;
|
|
} else if (session.stereo == 2) {
|
|
session.stereo = 0;
|
|
session.audiobitrate = 128;
|
|
}
|
|
}
|
|
|
|
if (session.stereo == 1 || session.stereo == 3 || session.stereo == 4 || session.stereo == 5) {
|
|
session.echoCancellation = false;
|
|
session.autoGainControl = false;
|
|
session.noiseSuppression = false;
|
|
}
|
|
|
|
if (urlParams.has("channelcount") || urlParams.has("ac") || urlParams.has("inputchannels")) {
|
|
// if updates to this, see also function toggleMonoStereoMic()
|
|
session.audioInputChannels = urlParams.get("channelcount") || urlParams.get("ac") || urlParams.get("inputchannels") || 0;
|
|
session.audioInputChannels = parseInt(session.audioInputChannels);
|
|
if (!session.audioInputChannels) {
|
|
session.audioInputChannels = false;
|
|
}
|
|
} else if (urlParams.has("monomic")) {
|
|
session.audioInputChannels = 1;
|
|
}
|
|
|
|
if (session.stereo === 5 && !session.audioInputChannels) {
|
|
// allow the guest to set their mic to mono.
|
|
document.querySelectorAll(".gear_microphone").forEach(ele => {
|
|
ele.classList.remove("hidden");
|
|
});
|
|
}
|
|
|
|
if (urlParams.has("echocancellation") || urlParams.has("aec") || urlParams.has("ec")) {
|
|
session.echoCancellation = urlParams.get("echocancellation") || urlParams.get("aec") || urlParams.get("ec");
|
|
|
|
if (session.echoCancellation) {
|
|
session.echoCancellation = session.echoCancellation.toLowerCase();
|
|
}
|
|
if (session.echoCancellation == "false") {
|
|
session.echoCancellation = false;
|
|
} else if (session.echoCancellation == "0") {
|
|
session.echoCancellation = false;
|
|
} else if (session.echoCancellation == "no") {
|
|
session.echoCancellation = false;
|
|
} else if (session.echoCancellation == "off") {
|
|
session.echoCancellation = false;
|
|
} else {
|
|
session.echoCancellation = true;
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("autogain") || urlParams.has("ag") || urlParams.has("agc")) {
|
|
session.autoGainControl = urlParams.get("autogain") || urlParams.get("ag") || urlParams.get("agc");
|
|
if (session.autoGainControl) {
|
|
session.autoGainControl = session.autoGainControl.toLowerCase();
|
|
}
|
|
if (session.autoGainControl == "false") {
|
|
session.autoGainControl = false;
|
|
} else if (session.autoGainControl == "0") {
|
|
session.autoGainControl = false;
|
|
} else if (session.autoGainControl == "no") {
|
|
session.autoGainControl = false;
|
|
} else if (session.autoGainControl == "off") {
|
|
session.autoGainControl = false;
|
|
} else {
|
|
session.autoGainControl = true;
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("denoise") || urlParams.has("dn")) {
|
|
session.noiseSuppression = urlParams.get("denoise") || urlParams.get("dn");
|
|
|
|
if (session.noiseSuppression) {
|
|
session.noiseSuppression = session.noiseSuppression.toLowerCase();
|
|
}
|
|
if (session.noiseSuppression == "false") {
|
|
session.noiseSuppression = false;
|
|
} else if (session.noiseSuppression == "0") {
|
|
session.noiseSuppression = false;
|
|
} else if (session.noiseSuppression == "no") {
|
|
session.noiseSuppression = false;
|
|
} else if (session.noiseSuppression == "off") {
|
|
session.noiseSuppression = false;
|
|
} else {
|
|
session.noiseSuppression = true;
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("isolation") || urlParams.has("voiceisolation") || urlParams.has("vi")) {
|
|
session.voiceIsolation = urlParams.get("isolation") || urlParams.get("voiceisolation") || urlParams.get("vi");
|
|
|
|
if (session.voiceIsolation) {
|
|
session.voiceIsolation = session.voiceIsolation.toLowerCase();
|
|
}
|
|
if (session.voiceIsolation == "false") {
|
|
session.voiceIsolation = false;
|
|
} else if (session.voiceIsolation == "0") {
|
|
session.voiceIsolation = false;
|
|
} else if (session.voiceIsolation == "no") {
|
|
session.voiceIsolation = false;
|
|
} else if (session.voiceIsolation == "off") {
|
|
session.voiceIsolation = false;
|
|
} else {
|
|
session.voiceIsolation = true;
|
|
}
|
|
}
|
|
|
|
if (session.voiceIsolation !== null) {
|
|
getById("whipoutvoiceisolation").classList.add("hidden");
|
|
}
|
|
if (session.noiseSuppression !== null) {
|
|
getById("whipoutdenoise").classList.add("hidden");
|
|
}
|
|
if (session.autoGainControl !== null) {
|
|
// should be the last
|
|
getById("whipoutautogain").classList.add("hidden");
|
|
}
|
|
|
|
if (urlParams.has("screenshareaec") || urlParams.has("ssec") || urlParams.has("ssaec")) {
|
|
session.screenshareAEC = urlParams.get("screenshareaec") || urlParams.get("ssec") || urlParams.get("ssaec");
|
|
|
|
if (session.screenshareAEC) {
|
|
session.screenshareAEC = session.screenshareAEC.toLowerCase();
|
|
}
|
|
if (session.screenshareAEC == "false") {
|
|
session.screenshareAEC = false;
|
|
} else if (session.screenshareAEC == "0") {
|
|
session.screenshareAEC = false;
|
|
} else if (session.screenshareAEC == "no") {
|
|
session.screenshareAEC = false;
|
|
} else if (session.screenshareAEC == "off") {
|
|
session.screenshareAEC = false;
|
|
} else {
|
|
session.screenshareAEC = true;
|
|
}
|
|
}
|
|
if (urlParams.has("screenshareautogain") || urlParams.has("ssag") || urlParams.has("ssagc")) {
|
|
session.screenshareAutogain = urlParams.get("screenshareautogain") || urlParams.get("ssag") || urlParams.get("ssagc");
|
|
if (session.screenshareAutogain) {
|
|
session.screenshareAutogain = session.screenshareAutogain.toLowerCase();
|
|
}
|
|
if (session.screenshareAutogain == "false") {
|
|
session.screenshareAutogain = false;
|
|
} else if (session.screenshareAutogain == "0") {
|
|
session.screenshareAutogain = false;
|
|
} else if (session.screenshareAutogain == "no") {
|
|
session.screenshareAutogain = false;
|
|
} else if (session.screenshareAutogain == "off") {
|
|
session.screenshareAutogain = false;
|
|
} else {
|
|
session.screenshareAutogain = true;
|
|
}
|
|
}
|
|
if (urlParams.has("screensharedenoise") || urlParams.has("ssdn")) {
|
|
session.screenshareDenoise = urlParams.get("screensharedenoise") || urlParams.get("ssdn");
|
|
|
|
if (session.screenshareDenoise) {
|
|
session.screenshareDenoise = session.screenshareDenoise.toLowerCase();
|
|
}
|
|
if (session.screenshareDenoise == "false") {
|
|
session.screenshareDenoise = false;
|
|
} else if (session.screenshareDenoise == "0") {
|
|
session.screenshareDenoise = false;
|
|
} else if (session.screenshareDenoise == "no") {
|
|
session.screenshareDenoise = false;
|
|
} else if (session.screenshareDenoise == "off") {
|
|
session.screenshareDenoise = false;
|
|
} else {
|
|
session.screenshareDenoise = true;
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("roombitrate") || urlParams.has("roomvideobitrate") || urlParams.has("rbr")) {
|
|
log("Room BITRATE SET");
|
|
session.roombitrate = urlParams.get("roombitrate") || urlParams.get("rbr") || urlParams.get("roomvideobitrate");
|
|
session.roombitrate = parseInt(session.roombitrate);
|
|
if (session.roombitrate < 1) {
|
|
session.roombitrate = 0;
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("outboundaudiobitrate") || urlParams.has("oab")) {
|
|
session.outboundAudioBitrate = parseInt(urlParams.get("outboundaudiobitrate")) || parseInt(urlParams.get("oab")) || false;
|
|
}
|
|
if (urlParams.has("outboundvideobitrate") || urlParams.has("outboundbitrate") || urlParams.has("ovb")) {
|
|
session.outboundVideoBitrate = parseInt(urlParams.get("outboundvideobitrate")) || parseInt(urlParams.get("outboundbitrate")) || parseInt(urlParams.get("ovb")) || false;
|
|
}
|
|
|
|
if (urlParams.has("webp") || urlParams.has("images")) {
|
|
// deprecicating this. chunked mode will replace it.
|
|
session.webp = urlParams.get("webp") || urlParams.get("images") || "webp";
|
|
}
|
|
|
|
if (urlParams.has("webpquality") || urlParams.has("webpq") || urlParams.has("wq")) {
|
|
session.webPquality = parseInt(urlParams.get("webpquality")) || parseInt(urlParams.get("webpq")) || parseInt(urlParams.get("wq")) || 4;
|
|
}
|
|
|
|
if (urlParams.has("audiobitrate") || urlParams.has("ab")) {
|
|
// both peers need this enabled for HD stereo to be on. If just pub, you get no echo/noise cancellation. if just viewer, you get high bitrate mono
|
|
log("AUDIO BITRATE SET");
|
|
session.audiobitrate = urlParams.get("audiobitrate") || urlParams.get("ab");
|
|
session.audiobitrate = parseInt(session.audiobitrate);
|
|
if (session.audiobitrate < 1) {
|
|
session.audiobitrate = false;
|
|
} else if (session.audiobitrate > 510) {
|
|
session.audiobitrate = 510;
|
|
} // this is to just prevent abuse
|
|
}
|
|
if (iOS || iPad) {
|
|
session.audiobitrate = false; // iOS devices seem to get distortion with custom audio bitrates. Disable for now.
|
|
}
|
|
|
|
/* if (urlParams.has('whitebalance') || urlParams.has('temp')){ // Need to be applied after the camera is selected. bleh. not enforcible. remove for now.
|
|
var temperature = urlParams.get('whitebalance') || urlParams.get('temp');
|
|
try{
|
|
updateCameraConstraints('colorTemperature', parseFloat(temperature));
|
|
} catch (e){errorlog(e);}
|
|
} */
|
|
|
|
if (urlParams.has("streamid") || urlParams.has("view") || urlParams.has("v") || urlParams.has("pull")) {
|
|
// the streams we want to view; if set, but let blank, we will request no streams to watch.
|
|
session.view = urlParams.get("streamid") || urlParams.get("view") || urlParams.get("v") || urlParams.get("pull") || null; // this value can be comma seperated for multiple streams to pull
|
|
|
|
getById("headphonesDiv2").style.display = "inline-block";
|
|
getById("headphonesDiv").style.display = "inline-block";
|
|
getById("addPasswordBasic").style.display = "none";
|
|
|
|
if (session.view == null) {
|
|
session.view = "";
|
|
}
|
|
|
|
/* if (session.view){
|
|
if (urlParams.has('include') && urlParams.get('include')){
|
|
session.view += ","+urlParams.get('include');
|
|
}
|
|
} */
|
|
if (session.scene !== false && session.style === false && window.obsstudio) {
|
|
session.style = 1;
|
|
}
|
|
}
|
|
// https://vdo.ninja/?fakeguests=10&room=faketestroom123&scene&border=10&padding=20&rounded
|
|
// https://vdo.ninja/?fakeusers=10&scene&room=test12342345ff
|
|
|
|
if (urlParams.has("fakeguests") || urlParams.has("fakefeeds") || urlParams.has("fakeusers")) {
|
|
var total = parseInt(urlParams.get("fakeguests")) || parseInt(urlParams.get("fakefeeds")) || parseInt(urlParams.get("fakeusers")) || 4;
|
|
session.fakeFeeds = [];
|
|
log("Creating " + total + " fake feeds");
|
|
for (var i = 0; i < total; i++) {
|
|
let fakeElement = document.createElement("video");
|
|
fakeElement.autoplay = true;
|
|
fakeElement.loop = true;
|
|
fakeElement.muted = true;
|
|
fakeElement.src = "./media/fakesteve.webm";
|
|
fakeElement.labelText = "Fake Steve\\n@steveseguin\\nhe\/him";
|
|
fakeElement.dataset.sid = fakeElement.id = parseInt(Math.random() * 10000000000);
|
|
session.fakeFeeds.push(fakeElement);
|
|
}
|
|
if (session.view !== false || session.scene !== false || session.whepInput) {
|
|
setTimeout(function () {
|
|
updateMixer();
|
|
}, 1000);
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("directoronly") || urlParams.has("directorsonly") || urlParams.has("do")) {
|
|
session.viewDirectorOnly = true;
|
|
}
|
|
|
|
if (session.view !== false) {
|
|
session.view_set = session.view.split(",");
|
|
}
|
|
|
|
if (session.view_set) {
|
|
session.allowScreen = [];
|
|
session.allowVideos = [];
|
|
var i = session.view_set.length;
|
|
while (i--) {
|
|
var split = session.view_set[i].split(":s");
|
|
if (split.length > 1) {
|
|
session.allowScreen.push(split[0]);
|
|
session.view_set.splice(i, 1);
|
|
if (!(split[0] in session.view_set)) {
|
|
session.view_set.push(split[0]);
|
|
}
|
|
} else if (split[0]) {
|
|
session.allowVideos.push(split[0]);
|
|
} else {
|
|
session.view_set.splice(i, 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("include") && urlParams.get("include")) {
|
|
urlParams.get("include")
|
|
.split(",")
|
|
.forEach(sid => {
|
|
var sidd = sid.split(":s")[0];
|
|
if (sidd && !session.include.includes(sidd)) {
|
|
session.include.push(sidd);
|
|
}
|
|
});
|
|
}
|
|
|
|
if (urlParams.has("directorview") || urlParams.has("dv")) {
|
|
session.directorView = true;
|
|
}
|
|
if (urlParams.has("graphs")) {
|
|
session.allowGraphs = true;
|
|
}
|
|
|
|
if (urlParams.has("ruler") || urlParams.has("grid") || urlParams.has("thirds")) {
|
|
session.fullscreen = true;
|
|
if (!session.manual) {
|
|
session.manual = session.manual === null ? false : session.manual;
|
|
}
|
|
session.ruleOfThirds = urlParams.get("ruler") || urlParams.get("grid") || urlParams.get("thirds") || "./media/thirds.svg";
|
|
session.ruleOfThirds = decodeURIComponent(session.ruleOfThirds);
|
|
}
|
|
|
|
if (urlParams.has("smallshare") || urlParams.has("smallscreen")) {
|
|
session.notifyScreenShare = false;
|
|
}
|
|
|
|
if (urlParams.has("proxy")) {
|
|
// routes the wss traffic via an alternative network path. Not
|
|
session.proxy = true; // only works if session.wss is set to false
|
|
} else if (location.hostname === "proxy.vdo.ninja") {
|
|
session.proxy = true;
|
|
}
|
|
|
|
if (urlParams.has("nopreview") || urlParams.has("np")) {
|
|
log("preview OFF");
|
|
session.nopreview = true;
|
|
if (iOS || iPad) {
|
|
session.nopreview = false;
|
|
session.minipreview = 3; //
|
|
}
|
|
} else if (urlParams.has("minipreview") || urlParams.has("mini")) {
|
|
var mini = urlParams.get("minipreview") || urlParams.get("mini"); // 2 is a valid option. (3 is for iPhone with a hidden preview)
|
|
|
|
if (mini === "0") {
|
|
mini = false;
|
|
} else if (mini) {
|
|
mini = parseInt(mini);
|
|
} else {
|
|
mini = 1;
|
|
}
|
|
log("preview ON");
|
|
session.nopreview = false;
|
|
session.minipreview = mini;
|
|
if (session.manual === null) {
|
|
session.manual = session.manual === null ? false : session.manual;
|
|
}
|
|
} else if (urlParams.has("largepreview")) {
|
|
session.nopreview = false;
|
|
session.minipreview = false;
|
|
if (session.manual === null) {
|
|
session.manual = session.manual === null ? false : session.manual;
|
|
}
|
|
} else if (urlParams.has("preview") || urlParams.has("showpreview")) {
|
|
log("preview ON");
|
|
if (session.manual === null) {
|
|
session.manual = session.manual === null ? false : session.manual;
|
|
}
|
|
session.nopreview = false;
|
|
}
|
|
|
|
if (urlParams.has("minipreviewoffset") || urlParams.has("mpo")) {
|
|
// 40 would be centered
|
|
session.leftMiniPreview = urlParams.get("minipreviewoffset") || urlParams.get("mpo") || 0;
|
|
session.leftMiniPreview = parseInt(session.leftMiniPreview) || 0;
|
|
if (session.leftMiniPreview < -20) {
|
|
session.leftMiniPreview = -20;
|
|
} else if (session.leftMiniPreview > 120) {
|
|
session.leftMiniPreview = 120;
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("obsfix")) {
|
|
session.obsfix = urlParams.get("obsfix");
|
|
if (session.obsfix) {
|
|
session.obsfix = session.obsfix.toLowerCase();
|
|
}
|
|
if (session.obsfix == "false") {
|
|
session.obsfix = false;
|
|
} else if (session.obsfix == "0") {
|
|
session.obsfix = false;
|
|
} else if (session.obsfix == "no") {
|
|
session.obsfix = false;
|
|
} else if (session.obsfix == "off") {
|
|
session.obsfix = false;
|
|
} else if (parseInt(session.obsfix) > 0) {
|
|
session.obsfix = parseInt(session.obsfix);
|
|
} else {
|
|
session.obsfix = 1; // aggressive.
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("controlroombitrate") || urlParams.has("crb")) {
|
|
session.controlRoomBitrate = true;
|
|
}
|
|
|
|
if (urlParams.has("minroombitrate") || urlParams.has("mrb")) {
|
|
session.minimumRoomBitrate = urlParams.get("minroombitrate") || urlParams.get("mrb") || false;
|
|
session.minimumRoomBitrate = parseInt(session.minimumRoomBitrate) || false;
|
|
}
|
|
|
|
if (urlParams.has("remote") || urlParams.has("rem")) {
|
|
log("remote ENABLED");
|
|
session.remote = urlParams.get("remote") || urlParams.get("rem") || true;
|
|
}
|
|
|
|
if (urlParams.has("slideshow")) {
|
|
// stream labs mobile fix ?
|
|
var ssinterval = parseInt(urlParams.get("slideshow")) || 25;
|
|
ssinterval = 1000 / ssinterval;
|
|
session.manual = session.manual === null ? true : session.manual;
|
|
session.dynamicScale = false;
|
|
setInterval(function () {
|
|
try {
|
|
slideshowHack();
|
|
} catch (e) {
|
|
errorlog(e);
|
|
}
|
|
}, ssinterval);
|
|
}
|
|
|
|
if (urlParams.has("latency") || urlParams.has("al") || urlParams.has("audiolatency")) {
|
|
log("latency ENABLED");
|
|
session.audioLatency = urlParams.get("latency") || urlParams.get("al") || urlParams.get("audiolatency");
|
|
session.audioLatency = parseInt(session.audioLatency) || 0;
|
|
session.disableWebAudio = false;
|
|
}
|
|
|
|
if (urlParams.has("micdelay") || urlParams.has("delay") || urlParams.has("md")) {
|
|
log("audio gain ENABLED");
|
|
session.micDelay = urlParams.get("micdelay") || urlParams.get("delay") || urlParams.get("md") || 0;
|
|
session.micDelay = parseInt(session.micDelay) || 0;
|
|
session.disableWebAudio = false;
|
|
}
|
|
|
|
if (urlParams.has("tips")) {
|
|
getById("guestTips").style.display = "flex";
|
|
}
|
|
|
|
if (urlParams.has("audiogain") || urlParams.has("gain") || urlParams.has("g")) {
|
|
log("audio gain ENABLED");
|
|
session.audioGain = urlParams.get("audiogain") || urlParams.get("gain") || urlParams.get("g");
|
|
session.audioGain = parseInt(session.audioGain) || 0;
|
|
session.disableWebAudio = false;
|
|
}
|
|
if (urlParams.has("volume") || urlParams.has("vol")) {
|
|
// This sets the default volume for all new video playback elements; 0 to 100.
|
|
log("setting default volume for playback");
|
|
session.volume = urlParams.get("volume") || urlParams.get("vol") || 100;
|
|
session.volume = parseInt(session.volume) || 0;
|
|
session.volume = session.volume / 100; // 0 to 1.0
|
|
}
|
|
if (urlParams.has("compressor") || urlParams.has("comp")) {
|
|
log("audio gain ENABLED");
|
|
session.compressor = 1;
|
|
session.disableWebAudio = false;
|
|
} else if (urlParams.has("limiter")) {
|
|
log("audio gain ENABLED");
|
|
session.compressor = 2;
|
|
session.disableWebAudio = false;
|
|
}
|
|
if (urlParams.has("equalizer") || urlParams.has("eq")) {
|
|
session.equalizer = true;
|
|
session.disableWebAudio = false;
|
|
}
|
|
if (urlParams.has("lowcut") || urlParams.has("lc") || urlParams.has("higpass")) {
|
|
session.lowcut = urlParams.get("lowcut") || urlParams.get("lc") || urlParams.get("higpass") || 100;
|
|
session.lowcut = parseInt(session.lowcut);
|
|
session.disableWebAudio = false;
|
|
}
|
|
|
|
if (urlParams.has("pip")) {
|
|
session.pip = true; // togglePip
|
|
//session.manual=true;
|
|
//innerHTML =
|
|
}
|
|
if (urlParams.has("pip3") || urlParams.has("mypip") || urlParams.has("pipme")) {
|
|
session.pip3 = true;
|
|
}
|
|
|
|
if (urlParams.has("manual")) {
|
|
session.manual = true;
|
|
}
|
|
|
|
if (urlParams.has("keyframeinterval") || urlParams.has("keyframerate") || urlParams.has("keyframe") || urlParams.has("fki")) {
|
|
log("keyframeRate ENABLED");
|
|
session.keyframeRate = parseInt(urlParams.get("keyframeinterval") || urlParams.get("keyframerate") || urlParams.get("keyframe") || urlParams.get("fki")) || 0;
|
|
}
|
|
|
|
if (urlParams.has("obsoff") || urlParams.has("oo") || urlParams.has("disableobs")) {
|
|
log("OBS feedback disabled");
|
|
session.disableOBS = true;
|
|
getById("obsState").style.setProperty("display", "none", "important");
|
|
}
|
|
|
|
if (urlParams.has("hidecodirectors") || urlParams.has("hidecodirector") || urlParams.has("hidedirector") || urlParams.has("hidedirectors") || urlParams.has("hd")) {
|
|
document.querySelector(":root").style.setProperty("--show-codirectors", "none", "important");
|
|
session.hideDirector = true;
|
|
}
|
|
|
|
if (urlParams.has("pptcontrols") || urlParams.has("slides") || urlParams.has("ppt") || urlParams.has("powerpoint")) {
|
|
session.pptControls = true; // shows powerpoint controls to remotely control a powerpoint slide. Requires additional remote setup.
|
|
}
|
|
|
|
if (urlParams.has("allowedscenes")) {
|
|
session.filterOBSscenes = urlParams.get("allowedscenes");
|
|
if (session.filterOBSscenes) {
|
|
session.filterOBSscenes = session.filterOBSscenes.split(",");
|
|
} else {
|
|
session.filterOBSscenes = true;
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("tallyoff") || urlParams.has("notally") || urlParams.has("disabletally") || urlParams.has("to")) {
|
|
log("Tally Light off");
|
|
getById("obsState").style.setProperty("display", "none", "important");
|
|
} else if (urlParams.has("tally")) {
|
|
session.tallyStyle = 1;
|
|
getById("obsState").classList.add("larger");
|
|
}
|
|
|
|
if (urlParams.has("automute") || urlParams.has("am")) {
|
|
session.automute = urlParams.get("automute") || true;
|
|
session.micIsolatedAutoMute = []; // default auto mutes
|
|
}
|
|
|
|
if (urlParams.has("noobsstream")){
|
|
session.obsState.streaming = false;
|
|
}
|
|
if (urlParams.has("noobsvirtual")){
|
|
session.obsState.virtualcam = false;
|
|
}
|
|
if (urlParams.has("noobsrecord")){
|
|
session.obsState.recording = false;
|
|
}
|
|
if (urlParams.has("noobssourceactive")){
|
|
session.obsState.sourceActive = false;
|
|
}
|
|
if (urlParams.has("noobsvisibility")){
|
|
session.obsState.visibility = false;
|
|
}
|
|
|
|
if (window.obsstudio) {
|
|
session.disableWebAudio = true; // default true; might be useful to disable on slow or old computers?
|
|
session.audioMeterGuest = false;
|
|
|
|
getById("miniTaskBar").classList.add("hidden");
|
|
|
|
if (session.audioEffects === null) {
|
|
session.audioEffects = false;
|
|
}
|
|
if (window.obsstudio.pluginVersion) {
|
|
if (macOS) {
|
|
// if mac, no fix
|
|
//session.obsfix = false;
|
|
} else if (window.obsstudio.pluginVersion == "2.17.4") {
|
|
// if obs v27.2 beta, no fix
|
|
//session.obsfix = false;
|
|
} else {
|
|
var ver = window.obsstudio.pluginVersion.split(".");
|
|
if (ver.length >= 2) {
|
|
if (parseInt(ver[0]) <= 2) {
|
|
if (parseInt(ver[0]) == 2) {
|
|
if (parseInt(ver[1]) <= 16) {
|
|
session.obsfix = 15;
|
|
}
|
|
} else {
|
|
session.obsfix = 15;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
try {
|
|
log("OBS VERSION:" + window.obsstudio.pluginVersion);
|
|
log("macOS: " + macOS);
|
|
log(window.obsstudio);
|
|
|
|
if (!urlParams.has("streamlabs")) {
|
|
var ver1 = window.obsstudio.pluginVersion.split(".");
|
|
|
|
if (ver1.length == 3) {
|
|
// Should be 3, but disabled3
|
|
if (ver1.length == 3 && parseInt(ver1[0]) == 2 && ChromiumVersion < 76 && macOS) {
|
|
updateURL("streamlabs");
|
|
getById("main").innerHTML =
|
|
"<div style='background-color:black;color:white;' data-translate='obs-macos-not-supported'><h1>Update OBS Studio to v26.1.2 or newer; older versions and StreamLabs OBS are not supported on macOS.\
|
|
<br /><i><small><small>download here: <a href='https://github.com/obsproject/obs-studio/releases'>https://github.com/obsproject/obs-studio/releases</a></small></small></i>\
|
|
</h1> <br /><br />\
|
|
<h2>Please use the <a href='https://github.com/steveseguin/electroncapture'>Electron Capture app</a> if there are further problems or if you wish to use StreamLabs on macOS still.</h2>\
|
|
<br /> You can bypass this error message by refreshing, <a href='" +
|
|
window.location.href +
|
|
"'> Clicking Here,</a> or by adding <i>&streamlabs</i> to the URL, but it may still not actually work.\
|
|
\
|
|
<br /> Please report this problem to steve@seguin.email if you feel it is an error.\
|
|
</div>";
|
|
}
|
|
}
|
|
}
|
|
|
|
//if (navigator.userAgent.indexOf('Mac OS X') != -1) {
|
|
// session.codec = "h264"; // default the codec to h264 if OBS is on macOS (that's all it supports with hardware) // oct 2021, OBS now supports vp8 and actually breaks with h264 android devices.
|
|
//}
|
|
|
|
if (session.disableOBS === false) {
|
|
|
|
|
|
getOBSDetails();
|
|
|
|
window.addEventListener("obsSceneChanged", obsSceneChanged);
|
|
if (session.obsState.visibility!==false){
|
|
window.addEventListener("obsSourceVisibleChanged", obsSourceVisibleChanged);
|
|
if (typeof document.visibilityState !== "undefined") {
|
|
session.obsState.visibility = document.visibilityState === "visible";
|
|
}
|
|
}
|
|
if (session.obsState.sourceActive!==false){
|
|
window.addEventListener("obsSourceActiveChanged", obsSourceActiveChanged);
|
|
}
|
|
if (session.obsState.streaming!==false){
|
|
window.addEventListener("obsStreamingStarted", obsStreamingStarted);
|
|
window.addEventListener("obsStreamingStopped", obsStreamingStopped);
|
|
}
|
|
if (!session.obsState.recording!==false){
|
|
window.addEventListener("obsRecordingStarted", obsRecordingStarted);
|
|
window.addEventListener("obsRecordingStopped", obsRecordingStopped);
|
|
}
|
|
if (session.obsState.virtualcam!==false){
|
|
window.addEventListener("obsVirtualcamStarted", obsVirtualcamStarted);
|
|
window.addEventListener("obsVirtualcamStopped", obsVirtualcamStopped);
|
|
}
|
|
}
|
|
} catch (e) {
|
|
errorlog(e);
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("chroma")) {
|
|
log("Chroma ENABLED");
|
|
getById("main").style.backgroundColor = "#" + (urlParams.get("chroma") || "0F0");
|
|
//try {
|
|
// document.querySelector('meta[name="theme-color"]')?.setAttribute('content', "#" + (urlParams.get('chroma') || "0F0")); .. meh
|
|
//} catch(e){}
|
|
//const ogColor = document.querySelector('meta[name="theme-color"]')?.getAttribute('content');
|
|
} // else if (window.obsstudio || (navigator.userAgent.toLowerCase().indexOf(' electron/') > -1)){
|
|
// getById("main").style.backgroundColor = "rgba(0,0,0,0)";
|
|
//}
|
|
|
|
//if (urlParams.has('bgimg')){
|
|
//
|
|
// getById("main").style.background = "#" + (urlParams.get('chroma') || "0F0");
|
|
//}
|
|
|
|
if (urlParams.has("margin")) {
|
|
try {
|
|
session.videoMargin = urlParams.get("margin") || 10;
|
|
session.videoMargin = parseInt(session.videoMargin);
|
|
//document.querySelector(':root').style.setProperty('--video-margin', session.videoMargin+"px");
|
|
} catch (e) {
|
|
errorlog("variable css failed");
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("rounded") || urlParams.has("round")) {
|
|
try {
|
|
session.borderRadius = urlParams.get("rounded") || urlParams.get("round") || 50;
|
|
session.borderRadius = parseInt(session.borderRadius);
|
|
document.querySelector(":root").style.setProperty("--video-rounded", session.borderRadius + "px");
|
|
session.manual = session.manual === null ? false : session.manual;
|
|
session.windowed = session.windowed === null ? false : session.windowed;
|
|
} catch (e) {
|
|
errorlog("variable css failed");
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("border")) {
|
|
try {
|
|
var videoBorder = urlParams.get("border") || 10;
|
|
videoBorder = parseInt(videoBorder);
|
|
session.border = videoBorder;
|
|
videoBorder += "px";
|
|
document.querySelector(":root").style.setProperty("--video-border-color", "#000");
|
|
document.querySelector(":root").style.setProperty("--video-border", videoBorder);
|
|
|
|
session.manual = session.manual === null ? false : session.manual;
|
|
session.windowed = session.windowed === null ? false : session.windowed;
|
|
} catch (e) {
|
|
errorlog("variable css failed");
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("bordercolor")) {
|
|
try {
|
|
session.borderColor = urlParams.get("bordercolor") || "#000";
|
|
document.querySelector(":root").style.setProperty("--video-border-color", session.borderColor);
|
|
} catch (e) {
|
|
errorlog("variable css failed");
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("holdercolor")) {
|
|
try {
|
|
session.holderColor = urlParams.get("holdercolor") || session.borderColor || "#000";
|
|
if (parseInt(session.holderColor) == session.holderColor){
|
|
session.holderColor = "#"+session.holderColor;
|
|
}
|
|
document.querySelector(":root").style.setProperty("--video-holder-color", session.holderColor);
|
|
} catch (e) {
|
|
errorlog("variable css failed");
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("color")) {
|
|
session.colorVideosBackground = urlParams.get("color") || session.borderColor || "#000";
|
|
}
|
|
|
|
if (urlParams.has("retry")) {
|
|
session.forceRetry = parseInt(urlParams.get("retry")) || 30;
|
|
}
|
|
|
|
if (session.forceRetry) {
|
|
clearInterval(session.forceRetryTimeout);
|
|
session.forceRetryTimeout = setTimeout(function () {
|
|
try {
|
|
session.retryWatchInterval();
|
|
} catch (e) {
|
|
log(e);
|
|
clearTimeout(this);
|
|
}
|
|
}, session.forceRetry * 1000);
|
|
}
|
|
|
|
if (urlParams.get("dropbox")) {
|
|
loadScript("https://cdnjs.cloudflare.com/ajax/libs/dropbox.js/10.34.0/Dropbox-sdk.min.js", () => {
|
|
log("Loaded dropbox SDK");
|
|
try {
|
|
var accessToken = urlParams.get("dropbox");
|
|
session.dbx = new Dropbox.Dropbox({ accessToken: accessToken });
|
|
resumeDropbox();
|
|
} catch (e) {
|
|
errorlog(e);
|
|
}
|
|
});
|
|
}
|
|
if (urlParams.has("gdrive")) {
|
|
session.gdrive = {};
|
|
}
|
|
|
|
try {
|
|
if (urlParams.has("darkmode") || urlParams.has("nightmode") || urlParams.has("darktheme")) {
|
|
session.darkmode = urlParams.get("darkmode") || urlParams.get("nightmode") || urlParams.get("darktheme") || null;
|
|
if (session.darkmode === null || session.darkmode === "") {
|
|
session.darkmode = true;
|
|
} else if (darkmode == "false" || darkmode == "0" || darkmode == 0 || darkmode == "off") {
|
|
session.darkmode = false;
|
|
}
|
|
} else if (urlParams.has("lightmode") || urlParams.has("lighttheme")) {
|
|
session.darkmode = false;
|
|
} else if (window.obsstudio) {
|
|
session.darkmode = false; // prevent OBS from defaulting to dark mode, avoiding possible overlooked bugs.
|
|
} else if (session.darkmode === null) {
|
|
session.darkmode = getComputedStyle(document.querySelector(":root")).getPropertyValue("--color-mode").trim();
|
|
if (session.darkmode == "dark") {
|
|
session.darkmode = true;
|
|
} else {
|
|
session.darkmode = false;
|
|
}
|
|
}
|
|
|
|
if (session.darkmode) {
|
|
document.body.classList.add("darktheme");
|
|
//document.querySelector(':root').style.setProperty('--background-color',"#02050c" );
|
|
} else {
|
|
document.body.classList.remove("darktheme");
|
|
//document.querySelector(':root').style.setProperty('--background-color',"#141926" ); // already set as default.
|
|
}
|
|
} catch (e) {
|
|
errorlog(e);
|
|
}
|
|
|
|
if (urlParams.has("videodevice") || urlParams.has("vdevice") || urlParams.has("vd") || urlParams.has("device") || urlParams.has("d") || urlParams.has("vdo")) {
|
|
session.videoDevice = urlParams.get("videodevice") || urlParams.get("vdevice") || urlParams.get("vd") || urlParams.get("device") || urlParams.get("d") || urlParams.get("vdo");
|
|
|
|
if (session.videoDevice === null) {
|
|
session.videoDevice = "1";
|
|
} else if (session.videoDevice) {
|
|
session.videoDevice = normalizeDeviceLabel(session.videoDevice);
|
|
}
|
|
|
|
if (session.videoDevice == "false") {
|
|
session.videoDevice = 0;
|
|
} else if (session.videoDevice == "0") {
|
|
session.videoDevice = 0;
|
|
} else if (session.videoDevice == "no") {
|
|
session.videoDevice = 0;
|
|
} else if (session.videoDevice == "off") {
|
|
session.videoDevice = 0;
|
|
} else if (session.videoDevice == "snapcam") {
|
|
session.videoDevice = "snap_camera";
|
|
} else if (session.videoDevice == "canon") {
|
|
session.videoDevice = "eos";
|
|
} else if (session.videoDevice == "camlink") {
|
|
session.videoDevice = "cam_link";
|
|
} else if (session.videoDevice == "ndi") {
|
|
session.videoDevice = "newtek_ndi_video";
|
|
} else if (session.videoDevice == "") {
|
|
session.videoDevice = 1;
|
|
} else if (session.videoDevice == "1") {
|
|
session.videoDevice = 1;
|
|
} else if (session.videoDevice == "default") {
|
|
session.videoDevice = 1;
|
|
}
|
|
|
|
if (!urlParams.has("vdo")) {
|
|
getById("videoMenu").style.display = "none";
|
|
getById("videoMenu").classList.add("hidden");
|
|
// getById("videoMenu2").style.display = "none";
|
|
// getById("videoMenu2").classList.add("hidden");
|
|
// getById("videoMenu3").style.display = "none";
|
|
// getById("videoMenu3").classList.add("hidden");
|
|
}
|
|
log("session.videoDevice:" + session.videoDevice);
|
|
}
|
|
|
|
// audioDevice
|
|
if (urlParams.has("audiodevice") || urlParams.has("adevice") || urlParams.has("ad") || urlParams.has("device") || urlParams.has("d") || urlParams.has("ado")) {
|
|
session.audioDevice = urlParams.get("audiodevice") || urlParams.get("adevice") || urlParams.get("ad") || urlParams.get("device") || urlParams.get("d") || urlParams.get("ado");
|
|
|
|
if (session.audioDevice === null) {
|
|
session.audioDevice = "1";
|
|
} else if (session.audioDevice) {
|
|
session.audioDevice = normalizeDeviceLabel(session.audioDevice);
|
|
}
|
|
|
|
if (session.audioDevice == "false") {
|
|
session.audioDevice = 0;
|
|
} else if (session.audioDevice == "0") {
|
|
session.audioDevice = 0;
|
|
} else if (session.audioDevice == "no") {
|
|
session.audioDevice = 0;
|
|
} else if (session.audioDevice == "off") {
|
|
session.audioDevice = 0;
|
|
} else if (session.audioDevice == "") {
|
|
session.audioDevice = 1;
|
|
} else if (session.audioDevice == "1") {
|
|
session.audioDevice = 1;
|
|
} else if (session.audioDevice == "default") {
|
|
session.audioDevice = 1;
|
|
} else if (session.audioDevice == "ndi") {
|
|
session.audioDevice = ["line_newtek_ndi_audio"];
|
|
} else {
|
|
session.audioDevice = session.audioDevice.split(",");
|
|
}
|
|
|
|
getById("headphonesDiv").style.display = "none";
|
|
getById("headphonesDiv2").style.display = "none";
|
|
|
|
if (typeof session.audioDevice !== "object" && !urlParams.has("ado")) {
|
|
getById("audioMenu").style.display = "none";
|
|
getById("audioScreenShare1").style.display = "none";
|
|
getById("audioMenu").classList.add("hidden");
|
|
getById("audioScreenShare1").classList.add("hidden");
|
|
}
|
|
|
|
if (session.audioDevice) {
|
|
// 0 or false, do not triger
|
|
log("requestAudioStream..()");
|
|
try {
|
|
await requestAudioStream();
|
|
} catch (e) {
|
|
errorlog(e);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (session.videoDevice === 0) {
|
|
getById("previewWebcam").classList.add("miconly");
|
|
if (session.audioDevice === 0) {
|
|
miniTranslate(getById("add_camera"), "click-start-to-join", "Click Start to Join");
|
|
getById("container-2").className = "column columnfade hidden";
|
|
getById("container-3").classList.add("skip-animation");
|
|
getById("container-3").classList.remove("pointer");
|
|
delayedStartupFuncs.push([previewWebcam]);
|
|
session.webcamonly = true;
|
|
} else {
|
|
miniTranslate(getById("add_camera"), "share-your-mic", "Share your Microphone");
|
|
getById("container-3").classList.add("microphoneBackground");
|
|
}
|
|
getById("container-3").title = getById("add_camera").innerText;
|
|
}
|
|
|
|
if (session.mobile) {
|
|
getById("shareScreenGear").style.display = "none";
|
|
getById("dropButton").style.display = "none";
|
|
//getById("container-2").className = 'column columnfade hidden'; // Hide screen share on mobile
|
|
session.screensharebutton = false;
|
|
screensharesupport = false;
|
|
|
|
if (session.audioDevice !== 0) {
|
|
getById("flipcamerabutton").classList.remove("hidden");
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("androidfix")) {
|
|
session.AndroidFix = true;
|
|
}
|
|
|
|
if (urlParams.has("consent")) {
|
|
session.consent = true;
|
|
getById("consentWarning").classList.remove("hidden");
|
|
getById("consentWarning2").classList.remove("hidden");
|
|
}
|
|
|
|
if (urlParams.has("autojoin") || urlParams.has("autostart") || urlParams.has("aj") || urlParams.has("as")) {
|
|
session.autostart = true;
|
|
}
|
|
|
|
if (urlParams.has("blackout") || urlParams.has("blackoutmode") || urlParams.has("bo") || urlParams.has("bom")) {
|
|
getById("blackoutmode").classList.remove("hidden");
|
|
if (urlParams.get("blackout") || urlParams.get("blackoutmode") || urlParams.get("bo") || urlParams.get("bom")) {
|
|
blackoutMode();
|
|
}
|
|
}
|
|
|
|
if (session.dataMode) {
|
|
delayedStartupFuncs.push([joinDataMode]);
|
|
} else if (session.autostart) {
|
|
if (session.screenshare !== false) {
|
|
delayedStartupFuncs.push([publishScreen]);
|
|
}
|
|
if (session.consent) {
|
|
setTimeout(function () {
|
|
warnUser("⚠ Privacy warning: The director of this room can remotely switch your camera or microphone without permission.", 8000);
|
|
}, 1500);
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("noiframe") || urlParams.has("noiframes") || urlParams.has("nif") || urlParams.has("nowebsite")) {
|
|
session.noiframe = urlParams.get("noiframe") || urlParams.get("noiframes") || urlParams.get("nif") || urlParams.get("nowebsite");
|
|
|
|
if (!session.noiframe) {
|
|
session.noiframe = [];
|
|
} else {
|
|
session.noiframe = session.noiframe.split(",");
|
|
}
|
|
log("disable iframe playback");
|
|
log(session.noiframe);
|
|
}
|
|
|
|
if (urlParams.has("exclude") || urlParams.has("ex")) {
|
|
session.exclude = urlParams.get("exclude") || urlParams.get("ex");
|
|
|
|
if (!session.exclude) {
|
|
session.exclude = false;
|
|
} else {
|
|
session.exclude = session.exclude.split(",");
|
|
}
|
|
log("exclude audio/video playback");
|
|
log(session.exclude);
|
|
}
|
|
|
|
if (urlParams.has("excludeaudio") || urlParams.has("exaudio") || urlParams.has("silence")) {
|
|
session.excludeaudio = urlParams.get("excludeaudio") || urlParams.get("exaudio") || urlParams.get("silence");
|
|
|
|
if (!session.excludeaudio) {
|
|
session.excludeaudio = false;
|
|
} else {
|
|
session.excludeaudio = session.excludeaudio.split(",");
|
|
}
|
|
log("exclude audio playback");
|
|
log(session.excludeaudio);
|
|
}
|
|
|
|
if (urlParams.has("novideo") || urlParams.has("nv") || urlParams.has("hidevideo") || urlParams.has("showonly")) {
|
|
session.novideo = urlParams.get("novideo") || urlParams.get("nv") || urlParams.get("hidevideo") || urlParams.get("showonly");
|
|
|
|
if (!session.novideo) {
|
|
session.novideo = [];
|
|
} else {
|
|
session.novideo = session.novideo.split(",");
|
|
}
|
|
log("disable video playback");
|
|
log(session.novideo);
|
|
}
|
|
|
|
if (urlParams.has("noaudio") || urlParams.has("na") || urlParams.has("hideaudio")) {
|
|
session.noaudio = urlParams.get("noaudio") || urlParams.get("na") || urlParams.get("hideaudio");
|
|
|
|
if (!session.noaudio) {
|
|
session.noaudio = [];
|
|
} else {
|
|
session.noaudio = session.noaudio.split(",");
|
|
}
|
|
log("disable audio playback");
|
|
}
|
|
|
|
|
|
if (urlParams.has("nodirectoraudio")) {
|
|
session.nodirectoraudio = true;
|
|
log("disable audio playback from Directors");
|
|
}
|
|
if (urlParams.has("nodirectorvideo")) {
|
|
session.nodirectoraudio = true;
|
|
log("disable audio playback from Directors");
|
|
}
|
|
|
|
if (urlParams.has("forceios")) {
|
|
log("allow iOS to work in video group chat; for this user at least");
|
|
session.forceios = true;
|
|
}
|
|
|
|
if (urlParams.has("nocursor") || urlParams.has("hidecursor") || urlParams.has("nomouse") || urlParams.has("hidemouse")) {
|
|
// on the screen, not in screen share
|
|
session.nocursor = true;
|
|
log("DISABLE CURSOR");
|
|
var styletmp = document.createElement("style");
|
|
styletmp.innerHTML = `
|
|
video {
|
|
margin: 0;
|
|
padding: 0;
|
|
overflow: hidden;
|
|
cursor: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=), none;
|
|
user-select: none;
|
|
}
|
|
`;
|
|
document.head.appendChild(styletmp);
|
|
}
|
|
|
|
if (urlParams.has("cursor") || urlParams.has("screensharecursor")) {
|
|
session.screensharecursor = true;
|
|
}
|
|
|
|
if (urlParams.has("distort")) {
|
|
session.voicechanger = 1;
|
|
}
|
|
|
|
if (urlParams.has("dtx") || urlParams.has("usedtx")) {
|
|
session.dtx = true;
|
|
session.cbr = 0; // no point dtx on if cbr is on, right?
|
|
}
|
|
|
|
if (urlParams.has("youtube")) {
|
|
// Set with a Youtube v3 clientID + "," + API key, then run YoutubeChatInterface();
|
|
session.youtubeKey = urlParams.get("youtube") || "";
|
|
//YoutubeChatInterface(); // queries Youtube for chat messages. Forwards them to the parent IFRAME only at the moment.
|
|
}
|
|
|
|
if (urlParams.has("vbr")) {
|
|
session.cbr = 0;
|
|
getById("whipoutvbrcbr").classList.add("hidden");
|
|
} else if (urlParams.has("cbr")) {
|
|
session.cbr = 1;
|
|
getById("whipoutvbrcbr").classList.add("hidden");
|
|
}
|
|
|
|
if (urlParams.has("order")) {
|
|
session.order = parseInt(urlParams.get("order")) || 1;
|
|
}
|
|
|
|
if (urlParams.has("orderby")) {
|
|
session.orderby = urlParams.get("orderby") || "id"; // "label" also an option; the default is stream ID tho.
|
|
}
|
|
|
|
if (urlParams.has("slot")) {
|
|
session.slot = parseInt(urlParams.get("slot")) || 0;
|
|
}
|
|
|
|
if (urlParams.has("slots")) {
|
|
session.slots = parseInt(urlParams.get("slots")) || 4;
|
|
}
|
|
|
|
if (urlParams.has("alpha")) {
|
|
session.alpha = true;
|
|
}
|
|
|
|
if (urlParams.has("chunked") || urlParams.has("chunk")) {
|
|
session.chunked = parseInt(urlParams.get("chunked")) || parseInt(urlParams.get("chunk")) || 2500; // sender side; enables to allows.
|
|
// session.alpha = true;
|
|
if (Firefox || SafariVersion) {
|
|
if (!session.cleanOutput) {
|
|
warnUser("Only Chromium-based browsers support chunked mode.\n\nPlease switch to Chrome or another compatible browser to use &chunked mode.");
|
|
}
|
|
session.chunked = false;
|
|
console.warn("Disabling chunked mode since not using a compatible browser.");
|
|
}
|
|
}
|
|
if (urlParams.has("chunkedbuffer") || urlParams.has("sendingbuffer")) {
|
|
session.sendingBuffer = parseInt(urlParams.get("chunkedbuffer")) || parseInt(urlParams.get("sendingbuffer")) || 5000; // sender side; enables to allows.
|
|
}
|
|
|
|
if (urlParams.has("nochunk") || urlParams.has("nochunked")) {
|
|
// viewer side
|
|
session.nochunk = true;
|
|
}
|
|
|
|
if (urlParams.has("nochunkaudio") || urlParams.has("nochunkedaudio")) {
|
|
// viewer side
|
|
session.nochunkaudio = true;
|
|
}
|
|
|
|
if (urlParams.has("audiobuffer") || urlParams.has("bufferaudio")) {
|
|
// viewer side
|
|
session.audioBuffer = urlParams.get("audiobuffer") || urlParams.get("bufferaudio") || 0;
|
|
session.audioBuffer = parseInt(session.audioBuffer);
|
|
}
|
|
|
|
//if (urlParams.has('viewchunked') || urlParams.has('viewchunk') || urlParams.has('allowchunked') || urlParams.has('allowchunk')) { // viewer side
|
|
// session.forceChunked = true;
|
|
//}
|
|
|
|
if (urlParams.has("token")) {
|
|
session.token = urlParams.get("token") || false;
|
|
// checkToken(); // this is sycnhonous
|
|
}
|
|
|
|
if (urlParams.has("maindirectorpassword") || urlParams.has("maindirpass")) {
|
|
session.mainDirectorPassword = urlParams.get("maindirectorpassword") || urlParams.get("maindirpass") || false;
|
|
if (!session.mainDirectorPassword) {
|
|
window.focus();
|
|
session.mainDirectorPassword = await promptAlt(getTranslation("director-password"), true, true);
|
|
if (session.mainDirectorPassword) {
|
|
session.mainDirectorPassword = session.mainDirectorPassword.trim();
|
|
try {
|
|
session.mainDirectorPassword = decodeURIComponent(session.mainDirectorPassword);
|
|
} catch (e) {
|
|
errorlog(e);
|
|
}
|
|
}
|
|
}
|
|
// registerToken();
|
|
}
|
|
|
|
if (urlParams.has("debug")) {
|
|
DebugLog = true;
|
|
if (!errorReport) {
|
|
errorReport = [];
|
|
}
|
|
if (urlParams.get("debug") == "1") {
|
|
debugStart();
|
|
} else if (urlParams.get("debug")) {
|
|
debugStart(urlParams.get("debug"));
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("group") || urlParams.has("groups")) {
|
|
session.group = urlParams.get("group") || urlParams.get("groups") || "";
|
|
session.group = session.group.split(",");
|
|
}
|
|
|
|
if (urlParams.has("groupview") || urlParams.has("viewgroup") || urlParams.has("gv")) {
|
|
session.groupView = urlParams.get("groupview") || urlParams.get("viewgroup") || urlParams.get("gv") || "";
|
|
session.groupView = session.groupView.split(",");
|
|
}
|
|
|
|
if (urlParams.has("groupaudio") || urlParams.has("ga")) {
|
|
session.groupAudio = true;
|
|
}
|
|
|
|
if (urlParams.has("groupmode") || urlParams.has("gm")) {
|
|
session.allowNoGroup = true;
|
|
}
|
|
|
|
if (urlParams.has("host")) {
|
|
session.roomhost = true;
|
|
}
|
|
|
|
if (urlParams.has("sensors") || urlParams.has("sensor") || urlParams.has("gyro") || urlParams.has("gyros") || urlParams.has("accelerometer")) {
|
|
session.sensorData = urlParams.get("sensors") || urlParams.get("sensor") || urlParams.get("gyro") || urlParams.get("gyros") || urlParams.get("accelerometer") || 30;
|
|
session.sensorData = parseInt(session.sensorData);
|
|
}
|
|
if (urlParams.has("sensorfilter") || urlParams.has("sensorsfilter") || urlParams.has("filtersensor") || urlParams.has("filtersensors")) {
|
|
session.sensorDataFilter = urlParams.get("sensorfilter") || urlParams.get("sensorsfilter") || urlParams.get("filtersensor") || urlParams.get("filtersensors") || "";
|
|
session.sensorDataFilter = session.sensorDataFilter.split(","); // ["pos","lin","ori","mag","gyro","acc"];
|
|
}
|
|
|
|
if (urlParams.has("ptime")) {
|
|
session.ptime = parseInt(urlParams.get("ptime")) || 20;
|
|
if (session.ptime < 10) {
|
|
session.ptime = 10;
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("minptime")) {
|
|
session.minptime = parseInt(urlParams.get("minptime")) || 10;
|
|
if (session.minptime < 10) {
|
|
session.minptime = 10;
|
|
}
|
|
if (session.minptime > 300) {
|
|
session.minptime = 300;
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("maxptime")) {
|
|
session.maxptime = parseInt(urlParams.get("maxptime")) || 60;
|
|
if (session.maxptime < 10) {
|
|
session.maxptime = 10;
|
|
}
|
|
if (session.maxptime > 300) {
|
|
session.maxptime = 300;
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("contenthint") || urlParams.has("contenttype") || urlParams.has("content") || urlParams.has("hint")) {
|
|
session.contentHint = urlParams.get("contenthint") || urlParams.get("contenttype") || urlParams.get("content") || urlParams.get("hint") || "detail";
|
|
}
|
|
|
|
if (urlParams.has("audiocontenthint") || urlParams.has("audiocontenttype") || urlParams.has("audiocontent") || urlParams.has("audiohint")) {
|
|
session.audioContentHint = urlParams.get("audiocontenthint") || urlParams.get("audiocontenttype") || urlParams.get("audiocontent") || urlParams.get("audiohint") || "music";
|
|
}
|
|
|
|
if (urlParams.has("screensharecontenthint") || urlParams.has("sscontenthint") || urlParams.has("screensharecontenttype") || urlParams.has("sscontent") || urlParams.has("sshint")) {
|
|
session.screenshareContentHint = urlParams.get("screensharecontenthint") || urlParams.get("sscontenthint") || urlParams.get("screensharecontenttype") || urlParams.get("sscontent") || urlParams.get("sshint") || "detail";
|
|
}
|
|
|
|
if (urlParams.has("vred")) {
|
|
session.videoErrorCorrection = true;
|
|
}
|
|
if (urlParams.has("pvred")) {
|
|
session.preferredVideoErrorCorrection = true;
|
|
}
|
|
|
|
if (urlParams.has("codec") || urlParams.has("codecs") || urlParams.has("videocodec")) {
|
|
log("codecs CHANGED");
|
|
session.codecs = urlParams.get("codec") || urlParams.get("codecs") || urlParams.get("videocodec") || false;
|
|
if (session.codecs) {
|
|
session.codecs = session.codecs.toLowerCase();
|
|
session.codecs = session.codecs.split(",");
|
|
if (session.codecs.length) {
|
|
session.codec = session.codecs.shift();
|
|
if (!session.codec) {
|
|
session.codec = false;
|
|
session.codecs = false;
|
|
}
|
|
if (!session.codecs.length) {
|
|
session.codecs = false;
|
|
}
|
|
} else {
|
|
session.codecs = false;
|
|
}
|
|
}
|
|
} else if (OperaGx) {
|
|
session.codec = "vp8";
|
|
warnlog("Defaulting to VP8 manually, as H264 with remote iOS devices is not supported");
|
|
}
|
|
|
|
if (urlParams.has("redaudio")) {
|
|
// just for experimenting
|
|
session.redAudio = true;
|
|
}
|
|
if (urlParams.has("fecaudio")) {
|
|
//
|
|
session.fecAudio = true;
|
|
}
|
|
if (urlParams.has("predaudio")) {
|
|
//
|
|
session.predAudio = true;
|
|
}
|
|
if (urlParams.has("pfecaudio")) {
|
|
//
|
|
session.pfecAudio = true;
|
|
}
|
|
|
|
if (urlParams.has("audiocodec")) {
|
|
log("CODEC CHANGED");
|
|
session.audioCodec = urlParams.get("audiocodec") || false;
|
|
if (session.audioCodec) {
|
|
session.audioCodec = session.audioCodec.toLowerCase();
|
|
}
|
|
}
|
|
if (session.audioCodec && session.audioCodec == "red") {
|
|
session.audiobitratePRO = 216; // higher than this seems to break the RED mode. default 256.
|
|
}
|
|
|
|
if (urlParams.has("preferaudiocodec")) {
|
|
log("PREFER CODEC CHANGED");
|
|
session.preferAudioCodec = urlParams.get("preferaudiocodec") || false;
|
|
if (session.preferAudioCodec) {
|
|
session.preferAudioCodec = session.preferAudioCodec.toLowerCase();
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("scenelinkcodec")) {
|
|
// this is mainly for a niche iframe API use
|
|
log("codecGroupFlag CHANGED");
|
|
session.codecGroupFlag = urlParams.get("scenelinkcodec") || false;
|
|
if (session.codecGroupFlag) {
|
|
session.codecGroupFlag = "&codec=" + session.codecGroupFlag.toLowerCase();
|
|
}
|
|
}
|
|
if (session.codecGroupFlag) {
|
|
getById("codecGroupFlag").disabled = true;
|
|
}
|
|
if (urlParams.has("scenelinkbitrate")) {
|
|
// this is mainly for a niche iframe API use
|
|
log("bitrateGroupFlag CHANGED");
|
|
session.bitrateGroupFlag = urlParams.get("scenelinkbitrate") || false;
|
|
if (session.bitrateGroupFlag) {
|
|
session.bitrateGroupFlag = "&totalbitrate=" + parseInt(session.bitrateGroupFlag);
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("h264profile")) {
|
|
session.h264profile = urlParams.get("h264profile") || "42e01f"; // 42001f
|
|
session.h264profile = session.h264profile.substring(0, 6);
|
|
session.h264profile = session.h264profile.toLowerCase();
|
|
if (session.h264profile == "0") {
|
|
session.h264profile = false;
|
|
} else if (session.h264profile == "off") {
|
|
session.h264profile = false;
|
|
} else if (session.h264profile == "disabl") {
|
|
session.h264profile = false;
|
|
} else if (session.h264profile == "defaul") {
|
|
session.h264profile = false;
|
|
} else if (session.h264profile == "false") {
|
|
session.h264profile = false;
|
|
}
|
|
} else if (session.codec === "hardware" && Android) {
|
|
// same as &h264profile, but easier for me to remember. I'll try to automate this in the future.
|
|
session.codec = "h264";
|
|
session.h264profile = "42e01f";
|
|
}
|
|
|
|
if (urlParams.has("nofec")) {
|
|
// disables error control / throttling -- currently on audio
|
|
session.noFEC = true;
|
|
}
|
|
if (urlParams.has("nonacks") || urlParams.has("nonack")) {
|
|
// disables error control / throttling.
|
|
session.noNacks = true;
|
|
}
|
|
if (urlParams.has("nopli")) {
|
|
// disables error control / throttling.
|
|
session.noPLIs = true;
|
|
}
|
|
if (urlParams.has("noremb")) {
|
|
// disables Receiver Estimated Maximum Bitrate (throttling)
|
|
session.noREMB = true;
|
|
}
|
|
|
|
if (urlParams.has("scale")) {
|
|
if (urlParams.get("scale") == "false") {
|
|
} else if (urlParams.get("scale") == "0") {
|
|
} else if (urlParams.get("scale") == "no") {
|
|
} else if (urlParams.get("scale") == "off") {
|
|
} else {
|
|
log("Resolution scale requested");
|
|
session.scale = parseFloat(urlParams.get("scale")) || 100;
|
|
}
|
|
session.dynamicScale = false; // default true
|
|
} else {
|
|
if (urlParams.has("viewwidth") || urlParams.has("vw")) {
|
|
session.viewwidth = urlParams.get("viewwidth") || urlParams.get("vw") || false;
|
|
if (session.viewwidth) {
|
|
session.viewwidth = parseInt(session.viewwidth);
|
|
}
|
|
session.dynamicScale = false; // default true
|
|
}
|
|
if (urlParams.has("viewheight") || urlParams.has("vh")) {
|
|
session.viewheight = urlParams.get("viewheight") || urlParams.get("vh") || false;
|
|
session.dynamicScale = false; // default true
|
|
if (session.viewheight) {
|
|
session.viewheight = parseInt(session.viewheight);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("sharperscreen")) {
|
|
// sets scale to 100 for inbound screenshares only
|
|
session.sharperScreen = true;
|
|
}
|
|
|
|
if (urlParams.has("mcscale") || urlParams.has("meshcastscale") || urlParams.has("woscale") || urlParams.has("whipoutscale")) {
|
|
session.whipOutScale = parseFloat(urlParams.get("mcscale")) || parseFloat(urlParams.get("meshcastscale")) || parseFloat(urlParams.get("woscale")) || parseFloat(urlParams.get("whipoutscale")) || 100;
|
|
}
|
|
|
|
if (isIFrame) {
|
|
getById("helpbutton").style.display = "none";
|
|
getById("helpbutton").style.opacity = 0;
|
|
getById("reportbutton").style.display = "none";
|
|
getById("reportbutton").style.opacity = 0;
|
|
getById("calendarButton").style.display = "none";
|
|
getById("calendarButton").style.opacity = 0;
|
|
getById("chatBody").innerHTML = "";
|
|
}
|
|
|
|
if (urlParams.has("beep") || urlParams.has("notify") || urlParams.has("tone")) {
|
|
session.beepToNotify = true;
|
|
var addtone = createAudioElement();
|
|
addtone.id = "jointone";
|
|
addtone.src = "./media/join.mp3";
|
|
getById("testtone").parentNode.insertBefore(addtone, getById("testtone").nextSibling);
|
|
var addtone = createAudioElement();
|
|
addtone.id = "leavetone";
|
|
addtone.src = "./media/leave.mp3";
|
|
getById("testtone").parentNode.insertBefore(addtone, getById("testtone").nextSibling);
|
|
|
|
if (!Notification) {
|
|
warnlog("Desktop notifications are not available in your browser.");
|
|
} else if (Notification.permission !== "granted") {
|
|
Notification.requestPermission();
|
|
}
|
|
}
|
|
if (urlParams.has("r2d2")) {
|
|
/* var addtone = createAudioElement();
|
|
addtone.id = "jointone";
|
|
addtone.src = "./media/join.mp3";
|
|
getById("testtone").parentNode.insertBefore(addtone, getById("testtone").nextSibling)
|
|
var addtone = createAudioElement();
|
|
addtone.id = "leavetone";
|
|
addtone.src = "./media/leave.mp3";
|
|
getById("testtone").parentNode.insertBefore(addtone, getById("testtone").nextSibling) */
|
|
getById("testtone").innerHTML = "";
|
|
getById("testtone").src = "./media/robot.mp3";
|
|
session.beepToNotify = true;
|
|
}
|
|
|
|
if (urlParams.get("custombeep")) {
|
|
updateAudioSource(urlParams.get("custombeep"));
|
|
}
|
|
|
|
if (urlParams.has("beepvolume")) {
|
|
try {
|
|
// jointone
|
|
document.getElementById("testtone").volume = parseInt(urlParams.get("beepvolume")) / 100 || 0;
|
|
document.getElementById("jointone").volume = parseInt(urlParams.get("beepvolume")) / 100 || 0;
|
|
document.getElementById("leavetone").volume = parseInt(urlParams.get("beepvolume")) / 100 || 0;
|
|
} catch (e) {
|
|
console.error(e);
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("easyexit") || urlParams.has("ee")) {
|
|
session.noExitPrompt = true;
|
|
}
|
|
|
|
if (urlParams.has("entrymsg") || urlParams.has("welcome") || urlParams.has("welcomeb64")) {
|
|
session.welcomeMessage = urlParams.get("entrymsg") || urlParams.get("welcome") || urlParams.get("welcomeb64");
|
|
|
|
if (urlParams.get("welcomeb64")) {
|
|
try {
|
|
session.welcomeMessage = atob(session.welcomeMessage);
|
|
} catch (e) {}
|
|
}
|
|
try {
|
|
session.welcomeMessage = session.welcomeMessage.replace(/(\r\n|\n|\r)/gm, " ");
|
|
session.welcomeMessage = decodeURIComponent(session.welcomeMessage);
|
|
} catch (e) {}
|
|
}
|
|
|
|
if (urlParams.has("welcomehtml")) {
|
|
session.welcomeHTML = urlParams.get("welcomehtml");
|
|
|
|
try {
|
|
session.welcomeHTML = atob(session.welcomeHTML);
|
|
} catch (e) {}
|
|
try {
|
|
session.welcomeHTML = session.welcomeHTML.replace(/(\r\n|\n|\r)/gm, " ");
|
|
session.welcomeHTML = decodeURIComponent(session.welcomeHTML);
|
|
} catch (e) {}
|
|
}
|
|
|
|
if (urlParams.has("welcomeimage") || urlParams.has("welcomeimg")) {
|
|
session.welcomeImage = urlParams.get("welcomeimage") || urlParams.get("welcomeimg");
|
|
try {
|
|
session.welcomeImage = decodeURIComponent(session.welcomeImage);
|
|
} catch (e) {}
|
|
}
|
|
|
|
if (urlParams.has("mixminus")) {
|
|
session.mixMinus = true;
|
|
}
|
|
|
|
if (urlParams.has("clearstorage") || urlParams.has("clear")) {
|
|
clearStorage();
|
|
}
|
|
|
|
if (urlParams.has("videobitrate") || urlParams.has("bitrate") || urlParams.has("vb")) {
|
|
session.bitrate = urlParams.get("videobitrate") || urlParams.get("bitrate") || urlParams.get("vb") || 8000;
|
|
if (session.bitrate) {
|
|
if (session.view_set && session.bitrate.split(",").length > 1) {
|
|
session.bitrate_set = session.bitrate.split(",");
|
|
session.bitrate = parseInt(session.bitrate_set[0]);
|
|
} else {
|
|
session.bitrate = parseInt(session.bitrate);
|
|
}
|
|
if (session.bitrate < 1) {
|
|
session.bitrate = false;
|
|
}
|
|
log("BITRATE ENABLED");
|
|
log(session.bitrate);
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("maxvideobitrate") || urlParams.has("maxbitrate") || urlParams.has("mvb")) {
|
|
session.maxvideobitrate = urlParams.get("maxvideobitrate") || urlParams.get("maxbitrate") || urlParams.get("mvb");
|
|
session.maxvideobitrate = parseInt(session.maxvideobitrate);
|
|
|
|
if (session.maxvideobitrate < 1) {
|
|
session.maxvideobitrate = false;
|
|
}
|
|
log("maxvideobitrate ENABLED");
|
|
log(session.maxvideobitrate);
|
|
}
|
|
|
|
if (urlParams.has("totalroombitrate") || urlParams.has("totalroomvideobitrate") || urlParams.has("trb") || urlParams.has("totalbitrate") || urlParams.has("tb")) {
|
|
session.totalRoomBitrate = urlParams.get("totalroombitrate") || urlParams.get("totalroomvideobitrate") || urlParams.get("trb") || urlParams.get("totalbitrate") || urlParams.get("tb") || "";
|
|
|
|
if (session.totalRoomBitrate.split(",").length > 1) {
|
|
if (session.mobile) {
|
|
session.totalRoomBitrate = session.totalRoomBitrate.split(",")[1];
|
|
} else {
|
|
session.totalRoomBitrate = session.totalRoomBitrate.split(",")[0];
|
|
}
|
|
}
|
|
|
|
session.totalRoomBitrate = parseInt(session.totalRoomBitrate) || 0;
|
|
|
|
if (session.totalRoomBitrate < 1) {
|
|
session.totalRoomBitrate = 0;
|
|
}
|
|
log("totalRoomBitrate ENABLED");
|
|
log(session.totalRoomBitrate);
|
|
}
|
|
|
|
if (session.totalRoomBitrate === false) {
|
|
session.totalRoomBitrate = session.bitrate || session.totalRoomBitrate_default; // sneaky sneaky
|
|
} else {
|
|
session.totalRoomBitrate_default = session.totalRoomBitrate; // trb_default doesn't change dynamically, but trb can (per director I guess)
|
|
}
|
|
|
|
if (session.totalRoomBitrate_default > 4000) {
|
|
getById("trbSettingInput").max = Math.ceil(session.totalRoomBitrate_default);
|
|
}
|
|
|
|
if (urlParams.has("maxtotalscenebitrate") || urlParams.has("totalscenebitrate") || urlParams.has("mtsb") || urlParams.has("tsb") || urlParams.has("totalbitrate") || urlParams.has("tb")) {
|
|
session.totalSceneBitrate = urlParams.get("maxtotalscenebitrate") || urlParams.get("totalscenebitrate") || urlParams.get("mtsb") || urlParams.get("tsb") || urlParams.get("totalbitrate") || urlParams.get("tb") || false;
|
|
if (session.totalSceneBitrate) {
|
|
session.totalSceneBitrate = parseInt(session.totalSceneBitrate);
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("blur")) {
|
|
session.blurBackground = urlParams.get("blur") || 10;
|
|
session.blurBackground = parseInt(session.blurBackground) || 10;
|
|
if (session.blurBackground < 0) {
|
|
session.blurBackground = false;
|
|
}
|
|
session.structure = true;
|
|
}
|
|
|
|
if (urlParams.has("limittotalbitrate") || urlParams.has("ltb")) {
|
|
session.limitTotalBitrate = urlParams.get("limittotalbitrate") || urlParams.get("ltb") || "2500";
|
|
|
|
if (session.limitTotalBitrate.split(",").length > 1) {
|
|
if (session.mobile) {
|
|
session.limitTotalBitrate = session.limitTotalBitrate.split(",")[1];
|
|
} else {
|
|
session.limitTotalBitrate = session.limitTotalBitrate.split(",")[0];
|
|
}
|
|
}
|
|
session.limitTotalBitrate = parseInt(session.limitTotalBitrate);
|
|
getById("limittotalbitrate_director").classList.remove("hidden");
|
|
}
|
|
|
|
if (session.limitTotalBitrate) {
|
|
if (session.limitTotalBitrate > session.limitTotalBitrate_defaultMax) {
|
|
getById("ltbSettingInputManual").max = Math.ceil(session.limitTotalBitrate);
|
|
}
|
|
getById("ltbSettingInputManual").value = session.limitTotalBitrate;
|
|
getById("ltbSettingInput").value = session.limitTotalBitrate;
|
|
getById("ltbSettingInputFeedback").innerHTML = session.limitTotalBitrate || "Disabled";
|
|
}
|
|
|
|
if (urlParams.has("mcscreensharebitrate") || urlParams.has("mcssbitrate") || urlParams.has("whipoutscreensharebitrate") || urlParams.has("wossbitrate")) {
|
|
session.whipOutScreenShareBitrate = urlParams.get("mcscreensharebitrate") || urlParams.get("mcssbitrate") || urlParams.get("whipoutscreensharebitrate") || urlParams.get("wossbitrate") || 2500;
|
|
session.whipOutScreenShareBitrate = parseInt(session.whipOutScreenShareBitrate);
|
|
}
|
|
|
|
if (urlParams.has("mcscreensharecodec") || urlParams.has("mcsscodec") || urlParams.has("whipoutscreensharecodec") || urlParams.has("wosscodec")) {
|
|
session.whipOutScreenShareCodec = urlParams.get("mcscreensharecodec") || urlParams.get("mcsscodec") || urlParams.get("whipoutscreensharecodec") || urlParams.get("wosscodec") || false;
|
|
}
|
|
if (session.whipOutScreenShareCodec) {
|
|
session.whipOutScreenShareCodec = session.whipOutScreenShareCodec.toLowerCase();
|
|
}
|
|
|
|
if (urlParams.has("mccodec") || urlParams.has("meshcastcodec") || urlParams.has("whipoutcodec") || urlParams.has("whipoutvideocodec") || urlParams.has("woc") || urlParams.has("wovc")) {
|
|
session.whipOutCodec = urlParams.get("mccodec") || urlParams.get("meshcastcodec") || urlParams.get("whipoutcodec") || urlParams.get("whipoutvideocodec") || urlParams.get("woc") || urlParams.get("wovc") || false;
|
|
getById("whipoutcodecGroupFlag").classList.add("hidden");
|
|
}
|
|
|
|
if (session.whipOutCodec) {
|
|
session.whipOutCodec = session.whipOutCodec.toLowerCase();
|
|
if (session.whipOutCodec == "h264") {
|
|
if (Firefox) {
|
|
session.whipOutCodec = false;
|
|
}
|
|
}
|
|
if (session.whipOutCodec) {
|
|
session.whipOutCodec = session.whipOutCodec.split(",");
|
|
}
|
|
getById("whipoutcodecGroupFlag").classList.add("hidden");
|
|
}
|
|
|
|
if (urlParams.has("whipoutaudiocodec") || urlParams.has("woac")) {
|
|
session.whipOutAudioCodec = urlParams.get("whipoutaudiocodec") || urlParams.get("woac") || false;
|
|
// getById("whipoutaudiocodecGroupFlag").classList.add("hidden"); // havne't added this in yet as an actual html element
|
|
}
|
|
|
|
if (urlParams.has("mcab") || urlParams.has("mcaudiobitrate") || urlParams.has("meshcastab") || urlParams.has("meshcastaudiobitrate ") || urlParams.has("whipoutaudiobitrate") || urlParams.has("woab")) {
|
|
session.whipOutAudioBitrate = urlParams.get("mcab") || urlParams.get("mcaudiobitrate") || urlParams.get("meshcastab") || urlParams.get("meshcastaudiobitrate ") || urlParams.get("whipoutaudiobitrate") || urlParams.get("woab") || false;
|
|
if (session.whipOutAudioBitrate) {
|
|
session.whipOutAudioBitrate = parseInt(session.whipOutAudioBitrate);
|
|
}
|
|
getById("whipoutaudiobitrate").classList.add("hidden");
|
|
}
|
|
|
|
if (urlParams.has("mcb") || urlParams.has("mcbitrate") || urlParams.has("meshcastbitrate") || urlParams.has("whipoutvideobitrate") || urlParams.has("wovb")) {
|
|
session.whipOutVideoBitrate = urlParams.get("mcb") || urlParams.get("mcbitrate") || urlParams.get("meshcastbitrate") || urlParams.get("whipoutvideobitrate") || urlParams.get("wovb") || false;
|
|
if (session.whipOutVideoBitrate) {
|
|
session.whipOutVideoBitrate = parseInt(session.whipOutVideoBitrate);
|
|
}
|
|
getById("whipoutbitrateGroupFlag").classList.add("hidden");
|
|
getById("whipoutvbrcbr").classList.add("hidden");
|
|
}
|
|
|
|
if (urlParams.has("height") || urlParams.has("h")) {
|
|
session.height = urlParams.get("height") || urlParams.get("h");
|
|
session.height = parseInt(session.height);
|
|
}
|
|
|
|
if (urlParams.has("width") || urlParams.has("w")) {
|
|
session.width = urlParams.get("width") || urlParams.get("w");
|
|
session.width = parseInt(session.width);
|
|
}
|
|
|
|
if (urlParams.has("quality") || urlParams.has("q")) {
|
|
try {
|
|
session.quality = urlParams.get("quality") || urlParams.get("q") || 0;
|
|
if (session.quality.toLowerCase() == "4k") {
|
|
session.quality = -2;
|
|
} else if (session.quality.toLowerCase() == "2160p") {
|
|
session.quality = -2;
|
|
} else if (session.quality.toLowerCase() == "2160") {
|
|
session.quality = -2;
|
|
} else if (session.quality.toLowerCase() == "2k") {
|
|
session.quality = -3;
|
|
} else if (session.quality.toLowerCase() == "1440p") {
|
|
session.quality = -3;
|
|
} else if (session.quality.toLowerCase() == "1440") {
|
|
session.quality = -3;
|
|
} else if (session.quality.toLowerCase() == "hd") {
|
|
//
|
|
session.quality = 1;
|
|
} else if (session.quality.toLowerCase() == "720p") {
|
|
//
|
|
session.quality = 1;
|
|
} else if (session.quality.toLowerCase() == "720") {
|
|
//
|
|
session.quality = 1;
|
|
} else if (session.quality.toLowerCase() == "fullhd") {
|
|
session.quality = 0;
|
|
} else if (session.quality.toLowerCase() == "1080p") {
|
|
session.quality = 0;
|
|
} else if (session.quality.toLowerCase() == "1080") {
|
|
session.quality = 0;
|
|
} else if (session.quality.toLowerCase() == "high") {
|
|
session.quality = 0;
|
|
} else if (session.quality.toLowerCase() == "360p") {
|
|
session.quality = 2;
|
|
} else if (session.quality.toLowerCase() == "360") {
|
|
session.quality = 2;
|
|
} else if (session.quality.toLowerCase() == "low") {
|
|
session.quality = 2;
|
|
}
|
|
session.quality = parseInt(session.quality);
|
|
getById("gear_screen").parentNode.removeChild(getById("gear_screen"));
|
|
getById("gear_webcam").parentNode.removeChild(getById("gear_webcam"));
|
|
|
|
if (session.outboundVideoBitrate === false) {
|
|
// default is 2500
|
|
if (session.quality == -1) {
|
|
// 1080p
|
|
session.outboundVideoBitrate = 4000;
|
|
} else if (session.quality == -3) {
|
|
// 2k
|
|
session.outboundVideoBitrate = 6000;
|
|
} else if (session.quality == -2) {
|
|
// 4k
|
|
session.outboundVideoBitrate = 8000;
|
|
}
|
|
}
|
|
} catch (e) {
|
|
errorlog(e);
|
|
}
|
|
} else if (urlParams.has("fullhd") || urlParams.has("1080p")) {
|
|
session.quality = 0;
|
|
getById("gear_screen").parentNode.removeChild(getById("gear_screen"));
|
|
getById("gear_webcam").parentNode.removeChild(getById("gear_webcam"));
|
|
if (session.outboundVideoBitrate === false) {
|
|
session.outboundVideoBitrate = 4000;
|
|
}
|
|
} else if (urlParams.has("4k")) {
|
|
session.quality = -2;
|
|
getById("gear_screen").parentNode.removeChild(getById("gear_screen"));
|
|
getById("gear_webcam").parentNode.removeChild(getById("gear_webcam"));
|
|
if (session.outboundVideoBitrate === false) {
|
|
session.outboundVideoBitrate = 8000;
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("sink")) {
|
|
session.sink = urlParams.get("sink");
|
|
} else if (urlParams.has("outputdevice") || urlParams.has("od") || urlParams.has("audiooutput")) {
|
|
session.outputDevice = urlParams.get("outputdevice") || urlParams.get("od") || urlParams.get("audiooutput") || null;
|
|
|
|
if (session.outputDevice) {
|
|
session.outputDevice = normalizeDeviceLabel(session.outputDevice);
|
|
} else {
|
|
session.outputDevice = null;
|
|
getById("headphonesDiv3").style.display = "none"; //
|
|
}
|
|
|
|
if (session.outputDevice) {
|
|
try {
|
|
enumerateDevices().then(function (deviceInfos) {
|
|
for (let i = 0; i !== deviceInfos.length; ++i) {
|
|
if (deviceInfos[i].kind === "audiooutput") {
|
|
if (normalizeDeviceLabel(deviceInfos[i].label).includes(session.outputDevice)) {
|
|
session.sink = deviceInfos[i].deviceId;
|
|
log("AUDIO OUT DEVICE: " + deviceInfos[i].deviceId);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
});
|
|
} catch (e) {}
|
|
}
|
|
|
|
getById("headphonesDiv").style.display = "none";
|
|
getById("headphonesDiv2").style.display = "none";
|
|
} else if (session.sink) {
|
|
if (session.sink == "default") {
|
|
session.sink = false;
|
|
} else {
|
|
enumerateDevices().then(function (deviceInfos) {
|
|
var matched = false;
|
|
for (let i = 0; i !== deviceInfos.length; ++i) {
|
|
if (deviceInfos[i].kind === "audiooutput") {
|
|
if (deviceInfos[i].deviceId == session.sink) {
|
|
matched = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (!matched) {
|
|
session.sink = false; // make sure any saved output device exists.
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
if (window.obsstudio || navigator.userAgent.toLowerCase().indexOf(" electron/") > -1) {
|
|
session.fullscreen = true;
|
|
} else if (urlParams.has("fullscreen")) {
|
|
session.fullscreen = true;
|
|
}
|
|
|
|
if (urlParams.has("stats")) {
|
|
if (urlParams.get("stats") == "0") {
|
|
session.statsMenu = false;
|
|
} else if (urlParams.get("stats") == "false") {
|
|
session.statsMenu = false;
|
|
} else if (urlParams.get("stats") == "off") {
|
|
session.statsMenu = false;
|
|
} else {
|
|
session.statsMenu = true;
|
|
}
|
|
} else if (urlParams.has("nostats")) {
|
|
session.statsMenu = false;
|
|
}
|
|
|
|
if (session.statsMenu === false) {
|
|
// hide menu option
|
|
try {
|
|
document.queryselector('[data-action="ShowStats"]').parentNode.classList.add("hidden");
|
|
} catch (e) {}
|
|
}
|
|
|
|
if (urlParams.has("statsinterval")) {
|
|
session.statsInterval = parseInt(urlParams.get("statsinterval")) || 3000; // milliseconds. interval of requesting stats of remote guests
|
|
}
|
|
|
|
if (urlParams.has("cleandirector") || urlParams.has("cdv")) {
|
|
session.cleanDirector = true;
|
|
}
|
|
|
|
if (urlParams.has("hidetranslate")) {
|
|
getById("translateButton").style.display = "none";
|
|
}
|
|
|
|
if (session.cleanOutput) {
|
|
session.screensharebutton = false;
|
|
getById("translateButton").style.display = "none";
|
|
getById("credits").style.display = "none";
|
|
getById("header").style.display = "none";
|
|
getById("controlButtons").classList.add("hidden");
|
|
getById("helpbutton").style.display = "none";
|
|
getById("helpbutton").style.opacity = 0;
|
|
getById("reportbutton").style.display = "none";
|
|
getById("reportbutton").style.opacity = 0;
|
|
getById("calendarButton").style.display = "none";
|
|
getById("calendarButton").style.opacity = 0;
|
|
document.documentElement.style.setProperty("--myvideo-background", "#0000");
|
|
var styleTmp = document.createElement("style");
|
|
styleTmp.innerHTML = `
|
|
video {
|
|
background-image: none;
|
|
}
|
|
`;
|
|
document.head.appendChild(styleTmp);
|
|
}
|
|
getById("credits").innerHTML = "Version: " + session.version + " - " + getById("credits").innerHTML;
|
|
|
|
if (urlParams.has("ssb") || urlParams.has("screensharebutton")) {
|
|
session.screensharebutton = true;
|
|
}
|
|
|
|
if (urlParams.has("hideheader") || urlParams.has("noheader") || urlParams.has("hh")) {
|
|
// needs to happen the room and permaid applications
|
|
getById("header").style.display = "none";
|
|
getById("header").style.opacity = 0;
|
|
getById("obsState").classList.add("noheader");
|
|
} else if (urlParams.has("showheader")) {
|
|
// needs to happen the room and permaid applications
|
|
getById("header").style.display = "inherit";
|
|
getById("header").style.opacity = 1;
|
|
setTimeout(function(){
|
|
getById("header").classList.remove("hidden");
|
|
getById("head2").classList.remove("hidden");
|
|
},100);
|
|
} else if (window.obsstudio) {
|
|
getById("header").style.display = "none";
|
|
getById("header").style.opacity = 0;
|
|
}
|
|
|
|
if (urlParams.has("minidirector")) {
|
|
try {
|
|
var cssStylesheet = document.createElement("link");
|
|
cssStylesheet.rel = "stylesheet";
|
|
cssStylesheet.type = "text/css";
|
|
cssStylesheet.media = "screen";
|
|
cssStylesheet.href = "minidirector.css";
|
|
document.getElementsByTagName("head")[0].appendChild(cssStylesheet);
|
|
} catch (e) {
|
|
errorlog(e);
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("postinterval")) {
|
|
// interval to post snapimage images
|
|
session.postInterval = urlParams.get("postinterval") || session.postInterval;
|
|
session.postInterval = parseInt(session.postInterval) || 60;
|
|
if (session.postInterval < 5) {
|
|
session.postInterval = 5;
|
|
}
|
|
}
|
|
if (urlParams.has("postimage")) {
|
|
var postURL = decodeURIComponent(urlParams.get("postimage")) || session.postURL; // default will post to https://temp.vdo.ninja/images/STREAMIDHERE.jpg , at an interval. it will be cached unless using url params.
|
|
setInterval(
|
|
function (postURL) {
|
|
try {
|
|
uploadImageSnapshot(postURL);
|
|
} catch (e) {}
|
|
},
|
|
session.postInterval * 1000,
|
|
postURL
|
|
);
|
|
}
|
|
|
|
if (urlParams.has("cleanish")) {
|
|
session.cleanish = true;
|
|
}
|
|
|
|
if (session.cleanish || !session.cleanOutput) {
|
|
if (session.obsControls) {
|
|
getById("obscontrolbutton").classList.remove("hidden");
|
|
getById("controlButtons").classList.remove("hidden");
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("nocontrolbar")) {
|
|
getById("controlButtons").classList.add("hidden");
|
|
getById("controlButtons").style.display = "none";
|
|
session.dedicatedControlBarSpace = false;
|
|
}
|
|
|
|
if (urlParams.has("channels")) {
|
|
// must be loaded before channelOffset
|
|
session.audioChannels = parseInt(urlParams.get("channels")) || 8; // for audio output ; not input. see: &channelcount instead.
|
|
session.offsetChannel = 0;
|
|
log("max channels is 32; channels offset");
|
|
session.audioEffects = true;
|
|
}
|
|
if (urlParams.has("channeloffset")) {
|
|
session.offsetChannel = parseInt(urlParams.get("channeloffset"));
|
|
log("max channels is 32; channels offset");
|
|
session.audioEffects = true;
|
|
}
|
|
if (urlParams.get("playchannel")) {
|
|
// must be loaded before channelOffset
|
|
session.playChannel = parseInt(urlParams.get("playchannel")); // for audio output ; not input. see: &channelcount instead.
|
|
session.audioEffects = true;
|
|
}
|
|
if (urlParams.has("enhance")) {
|
|
//if (parseInt(urlParams.get('enhance')>0){
|
|
session.enhance = true; //parseInt(urlParams.get('enhance'));
|
|
//}
|
|
}
|
|
|
|
if (urlParams.has("degrade")) {
|
|
session.degrade = urlParams.get("degrade") || true; // Firefox, and maybe Safari, supported I think.
|
|
// the possible values are maintain-framerate, maintain-resolution, or balanced. The default value is balanced
|
|
}
|
|
|
|
if (urlParams.has("maxviewers") || urlParams.has("mv")) {
|
|
session.maxviewers = urlParams.get("maxviewers") || urlParams.get("mv");
|
|
if (session.maxviewers.length == 0) {
|
|
session.maxviewers = 1;
|
|
} else {
|
|
session.maxviewers = parseInt(session.maxviewers);
|
|
}
|
|
log("maxviewers set");
|
|
}
|
|
|
|
if (urlParams.has("maxpublishers") || urlParams.has("mp")) {
|
|
session.maxpublishers = urlParams.get("maxpublishers") || urlParams.get("mp");
|
|
if (session.maxpublishers.length == 0) {
|
|
session.maxpublishers = 1;
|
|
} else {
|
|
session.maxpublishers = parseInt(session.maxpublishers);
|
|
}
|
|
log("maxpublishers set");
|
|
}
|
|
|
|
if (urlParams.has("maxconnections") || urlParams.has("mc")) {
|
|
session.maxconnections = urlParams.get("maxconnections") || urlParams.get("maxconnections");
|
|
if (session.maxconnections.length == 0) {
|
|
session.maxconnections = 1;
|
|
} else {
|
|
session.maxconnections = parseInt(session.maxconnections);
|
|
}
|
|
|
|
log("maxconnections set");
|
|
}
|
|
|
|
if (urlParams.has("secure")) {
|
|
session.security = true;
|
|
if (!session.cleanOutput) {
|
|
delayedStartupFuncs.push([warnUser, "Enhanced Security Mode Enabled."]);
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("requireencryption")) {
|
|
session.requireencryption = true;
|
|
}
|
|
if (urlParams.has("unsafe")) {
|
|
session.unsafe = true;
|
|
}
|
|
|
|
if (urlParams.has("random") || urlParams.has("randomize")) {
|
|
session.randomize = true;
|
|
}
|
|
|
|
if (urlParams.has("frameRate") || urlParams.has("fr") || urlParams.has("fps")) {
|
|
session.frameRate = urlParams.get("frameRate") || urlParams.get("fr") || urlParams.get("fps");
|
|
session.frameRate = parseInt(session.frameRate);
|
|
log("frameRate Changed");
|
|
log(session.frameRate);
|
|
}
|
|
|
|
if (urlParams.has("tz")) {
|
|
// being depreciated, but still works with meshcast (no longer turn)
|
|
session.tz = urlParams.get("tz");
|
|
if (session.tz === null || session.tz === "") {
|
|
session.tz = false;
|
|
} else {
|
|
session.tz = parseInt(session.tz);
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("maxframerate") || urlParams.has("mfr") || urlParams.has("mfps")) {
|
|
session.maxframeRate = urlParams.get("maxframerate") || urlParams.get("mfr") || urlParams.get("mfps");
|
|
session.maxframeRate = parseInt(session.maxframeRate);
|
|
log("max frameRate assigned");
|
|
log(session.maxframeRate);
|
|
}
|
|
|
|
if (urlParams.has("buffer") || urlParams.has("buffer2")) {
|
|
// needs to be before sync
|
|
if (ChromiumVersion > 50 && ChromiumVersion < 78) {
|
|
} else {
|
|
session.buffer = parseFloat(urlParams.get("buffer")) || parseFloat(urlParams.get("buffer2")) || 0;
|
|
log("buffer Changed: " + session.buffer);
|
|
}
|
|
if (urlParams.has("buffer2")) {
|
|
session.includeRTT = true;
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("panning") || urlParams.has("pan")) {
|
|
session.panning = urlParams.get("panning") || urlParams.get("pan");
|
|
if (session.panning === "") {
|
|
session.panning = true;
|
|
}
|
|
session.audioEffects = true;
|
|
}
|
|
|
|
if (urlParams.has("sync")) {
|
|
if (ChromiumVersion > 50 && ChromiumVersion < 78) {
|
|
} else {
|
|
session.sync = parseFloat(urlParams.get("sync"));
|
|
log("sync Changed; in milliseconds. If not set, defaults to auto.");
|
|
log(session.sync);
|
|
session.audioEffects = true;
|
|
if (session.buffer === false) {
|
|
session.buffer = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("nomirror")) {
|
|
session.nomirror = true;
|
|
}
|
|
|
|
if (urlParams.has("mirror")) {
|
|
if (urlParams.get("mirror") == "3") {
|
|
getById("main").classList.add("mirror");
|
|
} else if (urlParams.get("mirror") == "2") {
|
|
session.mirrored = 2;
|
|
} else if (urlParams.get("mirror") == "0") {
|
|
session.mirrored = 0;
|
|
} else if (urlParams.get("mirror") == "false") {
|
|
session.mirrored = 0;
|
|
} else if (urlParams.get("mirror") == "off") {
|
|
session.mirrored = 0;
|
|
} else {
|
|
session.mirrored = 1;
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("flip")) {
|
|
if (urlParams.get("flip") == "0") {
|
|
session.flipped = false;
|
|
} else if (urlParams.get("flip") == "false") {
|
|
session.flipped = false;
|
|
} else if (urlParams.get("flip") == "off") {
|
|
session.flipped = false;
|
|
} else {
|
|
session.flipped = true;
|
|
}
|
|
}
|
|
|
|
if (session.mirrored && session.flipped) {
|
|
try {
|
|
log("Mirror all videos");
|
|
var mirrorStyle = document.createElement("style");
|
|
mirrorStyle.innerHTML = "video {transform: scaleX(-1) scaleY(-1); }";
|
|
document.getElementsByTagName("head")[0].appendChild(mirrorStyle);
|
|
} catch (e) {
|
|
errorlog(e);
|
|
}
|
|
} else if (session.mirrored) {
|
|
// mirror the video horizontally
|
|
try {
|
|
log("Mirror all videos");
|
|
var mirrorStyle = document.createElement("style");
|
|
mirrorStyle.innerHTML = "video {transform: scaleX(-1);}";
|
|
document.getElementsByTagName("head")[0].appendChild(mirrorStyle);
|
|
} catch (e) {
|
|
errorlog(e);
|
|
}
|
|
} else if (session.flipped) {
|
|
// mirror the video vertically
|
|
try {
|
|
log("Mirror all videos");
|
|
var mirrorStyle = document.createElement("style");
|
|
mirrorStyle.innerHTML = "video {transform: scaleY(-1);}";
|
|
document.getElementsByTagName("head")[0].appendChild(mirrorStyle);
|
|
} catch (e) {
|
|
errorlog(e);
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("icefilter")) {
|
|
log("ICE FILTER ENABLED");
|
|
session.icefilter = urlParams.get("icefilter");
|
|
}
|
|
if (urlParams.has("lanonly")) {
|
|
session.localNetworkOnly = true;
|
|
session.configuration = {
|
|
sdpSemantics: session.sdpSemantics // future-proofing
|
|
};
|
|
}
|
|
|
|
//if (!(ChromiumVersion>=57)){
|
|
// getById("effectSelector").disabled=true;
|
|
// getById("effectSelector3").disabled=true;
|
|
// getById("effectSelector").title = "Effects are only support on Chromium-based browsers";
|
|
// getById("effectSelector3").title = "Effects are only support on Chromium-based browsers";
|
|
// var elementsTmp = document.querySelectorAll('[data-effectsNotice]');
|
|
// for (let i = 0; i < elementsTmp.length; i++) {
|
|
// elementsTmp[i].style.display = "inline-block";
|
|
// }
|
|
//}
|
|
|
|
if (urlParams.has("viewereffect") || urlParams.has("viewereffects") || urlParams.has("ve")) {
|
|
session.viewereffects = parseInt(urlParams.get("viewereffect")) || parseInt(urlParams.get("ve")) || false;
|
|
}
|
|
|
|
if (urlParams.has("activespeaker") || urlParams.has("speakerview") || urlParams.has("sas")) {
|
|
session.activeSpeaker = urlParams.get("activespeaker") || urlParams.get("speakerview") || urlParams.get("sas") || 1;
|
|
session.activeSpeaker = parseInt(session.activeSpeaker);
|
|
session.style = 6;
|
|
session.audioEffects = true;
|
|
//session.audioMeterGuest = true;
|
|
session.minipreview = 2;
|
|
if (session.activeSpeaker == 1 || session.activeSpeaker == 3) {
|
|
session.animatedMoves = false;
|
|
}
|
|
session.fadein = true;
|
|
document.querySelector(":root").style.setProperty("--fadein-speed", 0.5);
|
|
session.activeSpeakerInterval = setInterval(function () {
|
|
activeSpeaker(false);
|
|
}, 100);
|
|
} else if (urlParams.has("noisegate") || urlParams.has("gating") || urlParams.has("gate") || urlParams.has("ng")) {
|
|
session.quietOthers = urlParams.get("noisegate") || urlParams.get("gating") || urlParams.get("gate") || urlParams.get("ng") || 1;
|
|
session.quietOthers = parseInt(session.quietOthers);
|
|
|
|
if (session.quietOthers == 1) {
|
|
session.quietOthers = false;
|
|
session.noisegate = true;
|
|
session.audioEffects = true;
|
|
//session.audioMeterGuest = true;
|
|
} else if (session.quietOthers == 4) {
|
|
session.quietOthers = 1;
|
|
session.audioEffects = true;
|
|
//session.audioMeterGuest = true;
|
|
session.activeSpeakerInterval = setInterval(function () {
|
|
activeSpeaker(false);
|
|
}, 100);
|
|
} else if (!session.quietOthers) {
|
|
session.noisegate = false;
|
|
session.quietOthers = false;
|
|
} else {
|
|
session.audioEffects = true;
|
|
//session.audioMeterGuest = true;
|
|
session.activeSpeakerInterval = setInterval(function () {
|
|
activeSpeaker(false);
|
|
}, 100);
|
|
}
|
|
}
|
|
if (urlParams.has("activespeakerdelay") || urlParams.has("speakerviewdelay") || urlParams.has("sasdelay")) {
|
|
session.activeSpeakerTimeout = urlParams.get("activespeakerdelay") || urlParams.get("speakerviewdelay") || urlParams.get("sasdelay") || 0;
|
|
session.activeSpeakerTimeout = parseInt(session.activeSpeakerTimeout);
|
|
}
|
|
|
|
if (urlParams.has("noisegatesettings")) {
|
|
session.noisegateSettings = urlParams.get("noisegatesettings");
|
|
session.noisegateSettings = session.noisegateSettings.split(",");
|
|
}
|
|
|
|
if (urlParams.has("fadein")) {
|
|
session.fadein = true;
|
|
if (urlParams.get("fadein") || 0) {
|
|
try {
|
|
var fadeinspeed = parseInt(urlParams.get("fadein") || 0) / 1000.0;
|
|
fadeinspeed += "s";
|
|
document.querySelector(":root").style.setProperty("--fadein-speed", fadeinspeed);
|
|
} catch (e) {
|
|
errorlog("variable css failed");
|
|
}
|
|
} else {
|
|
try {
|
|
var fadeinspeed = 0.5;
|
|
fadeinspeed += "s";
|
|
document.querySelector(":root").style.setProperty("--fadein-speed", fadeinspeed);
|
|
} catch (e) {
|
|
errorlog("variable css failed");
|
|
}
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("widget")) {
|
|
session.widget = urlParams.get("widget") || false;
|
|
|
|
if (session.widget === "false" || session.widget === "0" || session.widget === "off") {
|
|
session.noWidget = true;
|
|
session.widget = false;
|
|
} else if (session.widget) {
|
|
session.widget = decodeURI(session.widget) || false;
|
|
log(session.widget);
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("widgetleft")) {
|
|
session.widgetleft = true;
|
|
}
|
|
if (urlParams.get("widgetwidth")) { // default is 25%
|
|
try{
|
|
session.widgetwidth = parseFloat(urlParams.get("widgetwidth"));
|
|
document.querySelector(":root").style.setProperty("--widget-width", session.widgetwidth+"%");
|
|
} catch(e){
|
|
errorlog(e);
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("animated") || urlParams.has("animate")) {
|
|
session.animatedMoves = urlParams.get("animated") || urlParams.get("animate");
|
|
if (session.animatedMoves === "false") {
|
|
session.animatedMoves = false;
|
|
} else if (session.animatedMoves === "0") {
|
|
session.animatedMoves = false;
|
|
} else if (session.animatedMoves === "no") {
|
|
session.animatedMoves = false;
|
|
} else if (session.animatedMoves === "off") {
|
|
session.animatedMoves = false;
|
|
} else {
|
|
session.animatedMoves = parseInt(session.animatedMoves) || 100;
|
|
}
|
|
if (session.animatedMoves > 200) {
|
|
session.animatedMoves = 200;
|
|
}
|
|
} else if (session.mobile) {
|
|
session.animatedMoves = false;
|
|
}
|
|
|
|
if (urlParams.has("meter") || urlParams.has("meterstyle")) {
|
|
// same as also adding &style=3
|
|
session.meterStyle = urlParams.get("meter") || urlParams.get("meterstyle") || 1;
|
|
session.meterStyle = parseInt(session.meterStyle);
|
|
if (session.meterStyle < 4) {
|
|
session.style = 3; // black canvas
|
|
} else {
|
|
session.style = -1; // no canvas
|
|
}
|
|
session.audioEffects = true;
|
|
}
|
|
|
|
if (session.meterStyle == 5) {
|
|
document.documentElement.style.setProperty("--video-background-image-size-talking", "auto 35%");
|
|
document.documentElement.style.setProperty("--video-background-image-size-screaming", "auto 45%");
|
|
}
|
|
|
|
if (urlParams.has("directorchat") || urlParams.has("dc")) {
|
|
session.directorChat = true;
|
|
}
|
|
|
|
if (urlParams.has("style") || urlParams.has("st")) {
|
|
session.style = urlParams.get("style") || urlParams.get("st");
|
|
if (parseInt(session.style) === 0 || session.style == "controls") {
|
|
// no audio only
|
|
session.style = 0;
|
|
} else if (parseInt(session.style) == 1 || session.style == "justvideo") {
|
|
// no audio only
|
|
session.style = 1;
|
|
} else if (parseInt(session.style) == 2 || session.style == "waveform") {
|
|
// audio waveform
|
|
session.style = 2;
|
|
session.audioEffects = true; ////!!!!!!! Do I want to enable the audioEffects myself? or do it here?
|
|
} else if (parseInt(session.style) == 3 || session.style == "volume") {
|
|
// audio meter ; see &meterstyle , where optios include default(false), 1, and 2.
|
|
session.style = 3;
|
|
session.audioEffects = true;
|
|
} else if (parseInt(session.style) == 4) {
|
|
// black background
|
|
session.style = 4;
|
|
} else if (parseInt(session.style) == 5) {
|
|
// random colored background
|
|
session.style = 5;
|
|
} else if (parseInt(session.style) == 7) {
|
|
// shows video elements for all connections; even those without video/audio
|
|
session.style = parseInt(session.style);
|
|
session.showall = true;
|
|
} else if (parseInt(session.style)) {
|
|
// 6 is the first letter of the name, surrounded with a colored circle
|
|
session.style = parseInt(session.style);
|
|
} else {
|
|
session.style = 1;
|
|
}
|
|
}
|
|
//if (session.style){
|
|
// getById("toggleWaveformButton").classList.remove("hidden");
|
|
//}
|
|
|
|
if (urlParams.has("showall")) {
|
|
// just an alternative; might be compoundable
|
|
session.showall = true;
|
|
}
|
|
|
|
if (urlParams.has("samplerate") || urlParams.has("sr")) {
|
|
// playout sample rate
|
|
session.sampleRate = parseInt(urlParams.get("samplerate")) || parseInt(urlParams.get("samplerate")) || 48000;
|
|
if (session.audioCtx) {
|
|
session.audioCtx.close(); // close the default audio context.
|
|
}
|
|
session.audioCtx = new AudioContext({
|
|
// create a new audio context with a higher sample rate.
|
|
sampleRate: session.sampleRate // default is 48000 already
|
|
});
|
|
session.audioEffects = true;
|
|
}
|
|
|
|
if (session.audioCodec === "lyra") {
|
|
// WIP. does not work
|
|
try {
|
|
var { default: Module } = await import("./thirdparty/lyra/webassembly_codec_wrapper.js");
|
|
await Module()
|
|
.then(module => {
|
|
console.log("Initialized codec's wasmModule.");
|
|
session.lyraCodecModule = module;
|
|
})
|
|
.catch(e => {
|
|
console.log(`Module() error: ${e.name} message: ${e.message}`);
|
|
});
|
|
} catch (e) {
|
|
errorlog(e);
|
|
}
|
|
if (session.lyraCodecModule) {
|
|
console.log("Lyra module loaded");
|
|
session.micSampleRate = 16000;
|
|
session.encodedInsertableStreams = "lyra";
|
|
} else {
|
|
console.log("Lyra module failed to load");
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("e2ee")) {
|
|
session.encodedInsertableStreams = "e2ee";
|
|
} else if (urlParams.has("insertablestreams") || urlParams.has("is")) {
|
|
session.encodedInsertableStreams = urlParams.get("insertablestreams") || urlParams.get("is") || true;
|
|
}
|
|
|
|
if (urlParams.has("outboundsamplerate") || urlParams.has("obsr")) {
|
|
session.outboundSampleRate = parseInt(urlParams.get("outboundsamplerate")) || parseInt(urlParams.get("obsr")) || false; // default null
|
|
} else {
|
|
session.outboundSampleRate = null; // tmp
|
|
}
|
|
|
|
if (urlParams.has("micsamplerate") || urlParams.has("msr")) {
|
|
session.micSampleRate = parseInt(urlParams.get("micsamplerate")) || parseInt(urlParams.get("msr")) || 48000;
|
|
}
|
|
|
|
if (urlParams.has("micsamplesize")) {
|
|
session.micSampleSize = parseInt(urlParams.get("micsamplesize")) || 16;
|
|
}
|
|
|
|
if (urlParams.has("noaudioprocessing") || urlParams.has("noap")) {
|
|
session.disableWebAudio = true; // default true; might be useful to disable on slow or old computers?
|
|
session.disableViewerWebAudioPipeline = true; // this has the potential to break things.
|
|
session.audioEffects = false; // disable audio inbound effects also.
|
|
session.audioMeterGuest = false;
|
|
if (session.noisegate === null) {
|
|
session.noisegate = false;
|
|
}
|
|
}
|
|
|
|
// For info, see this: https://developer.mozilla.org/en-US/docs/Web/API/RTCIceCandidatePairStats/availableOutgoingBitrate
|
|
if (urlParams.has("maxbandwidth")) {
|
|
// limits the bitrate based on the outbound total available bandwidth; chromium-based
|
|
session.maxBandwidth = urlParams.get("maxbandwidth") || 80; // 0 to 100; will reduce bitrate as a percentage of available
|
|
session.maxBandwidth = parseInt(session.maxBandwidth);
|
|
if (session.maxBandwidth > 200) {
|
|
// will over ride default 2500kbps if no bitrate is specified
|
|
session.maxBandwidth = 200;
|
|
} else if (session.maxBandwidth < 0) {
|
|
session.maxBandwidth = 0;
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("iframetarget")) {
|
|
session.iframetarget = urlParams.get("iframetarget"); // speciifies the IFRAME Hostname target
|
|
if (session.iframetarget) {
|
|
session.iframetarget = decodeURIComponent(session.iframetarget);
|
|
} else {
|
|
session.iframetarget = (window.location.protocol === "file:") ? "*" : window.location.origin;
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("sendframes")) {
|
|
session.sendframes = urlParams.get("sendframes");
|
|
if (session.sendframes) {
|
|
try {
|
|
session.sendframes = decodeURIComponent(session.sendframes);
|
|
} catch (e) {}
|
|
} else {
|
|
session.sendframes = session.iframetarget || "*";
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("tcp")) {
|
|
// forces the TURN servers to use TCP mode; still need to add &private to force TURN also tho
|
|
session.forceTcpMode = true;
|
|
}
|
|
|
|
if (urlParams.has("stun")) {
|
|
var stunstring = urlParams.get("stun");
|
|
stunstring = stunstring.split(";");
|
|
if (stunstring[0] !== "false") {
|
|
// false disables the TURN server. Useful for debuggin
|
|
var stun = {};
|
|
if (stunstring.length == 3) {
|
|
stun.username = stunstring[0]; // myusername
|
|
stun.credential = stunstring[1]; //mypassword
|
|
stun.urls = [stunstring[2]]; // ["turn:turn.obs.ninja:443"];
|
|
} else if (stunstring.length == 1) {
|
|
stun.urls = [stunstring[0]];
|
|
}
|
|
session.stunServers = [stun];
|
|
} else {
|
|
session.stunServers = [];
|
|
}
|
|
}
|
|
if (urlParams.has("addstun")) {
|
|
var stunstring = urlParams.get("addstun");
|
|
stunstring = stunstring.split(";");
|
|
var stun = {};
|
|
if (stunstring.length == 3) {
|
|
stun.username = stunstring[0]; // myusername
|
|
stun.credential = stunstring[1]; //mypassword
|
|
stun.urls = [stunstring[2]]; // ["turn:turn.obs.ninja:443"];
|
|
} else if (stunstring.length == 1) {
|
|
stun.urls = [stunstring[0]];
|
|
}
|
|
session.stunServers = session.stunServers.concat(stun);
|
|
}
|
|
|
|
if (urlParams.has("bundle")) {
|
|
session.bundlePolicy = urlParams.get("bundle") || "max-bundle"; // default is browser default.
|
|
}
|
|
|
|
if (urlParams.has("planb")) {
|
|
session.sdpSemantics = "plan-b"; // for legacy support, or debuggin, or whatever.
|
|
}
|
|
|
|
if (urlParams.has("turn")) {
|
|
var turnstring = urlParams.get("turn");
|
|
|
|
if (turnstring == "twilio") {
|
|
// a sample function on loading remote credentials for TURN servers.
|
|
try {
|
|
session.ws = false; // prevents connection
|
|
var twillioRequest = new XMLHttpRequest();
|
|
twillioRequest.onload = function () {
|
|
if (this.status === 200) {
|
|
try {
|
|
var res = JSON.parse(this.responseText);
|
|
} catch (e) {
|
|
console.error(e);
|
|
return;
|
|
}
|
|
session.configuration = {
|
|
iceServers: [
|
|
{
|
|
username: res["1"],
|
|
credential: res["2"],
|
|
url: "turn:global.turn.twilio.com:3478?transport=tcp",
|
|
urls: "turn:global.turn.twilio.com:3478?transport=tcp"
|
|
},
|
|
{
|
|
username: res["1"],
|
|
credential: res["2"],
|
|
url: "turn:global.turn.twilio.com:443?transport=tcp",
|
|
urls: "turn:global.turn.twilio.com:443?transport=tcp"
|
|
}
|
|
],
|
|
sdpSemantics: session.sdpSemantics // future-proofing
|
|
};
|
|
if (session.ws === false) {
|
|
session.ws = null; // allows connection (clears state)
|
|
session.connect(); // connect if not already connected.
|
|
}
|
|
}
|
|
// system does not connect if twilio API does not respond.
|
|
};
|
|
twillioRequest.open("GET", "https://turn.example.com:443/twilio", true); // `false` makes the request synchronous
|
|
twillioRequest.send();
|
|
} catch (e) {
|
|
errorlog("Twilio Failed");
|
|
}
|
|
} else if (turnstring == "nostun") {
|
|
// disable TURN servers
|
|
session.configuration = {
|
|
sdpSemantics: session.sdpSemantics // future-proofing
|
|
};
|
|
} else if (turnstring == "false" || turnstring == "off" || turnstring == "0") {
|
|
// disable TURN servers
|
|
session.configuration = {
|
|
iceServers: session.stunServers,
|
|
sdpSemantics: session.sdpSemantics // future-proofing
|
|
};
|
|
} else {
|
|
try {
|
|
//session.configuration = {iceServers: [], sdpSemantics: session.sdpSemantics};
|
|
turnstring = turnstring.split(";");
|
|
if (turnstring !== "false") {
|
|
// false disables the TURN server. Useful for debuggin
|
|
var turn = {};
|
|
if (turnstring.length == 3) {
|
|
turn.username = turnstring[0]; // myusername
|
|
turn.credential = turnstring[1]; //mypassword
|
|
turn.urls = [turnstring[2]]; // ["turn:turn.obs.ninja:443"];
|
|
} else if (turnstring.length == 1) {
|
|
turn.urls = [turnstring[0]];
|
|
}
|
|
session.configuration = {
|
|
iceServers: session.stunServers,
|
|
sdpSemantics: session.sdpSemantics // future-proofing
|
|
};
|
|
|
|
session.configuration.iceServers.push(turn);
|
|
}
|
|
} catch (e) {
|
|
if (!session.cleanOutput) {
|
|
warnUser("TURN server parameters were wrong.");
|
|
}
|
|
errorlog(e);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("apiserver") && urlParams.get("apiserver")) {
|
|
// must set this after any custom TURN / STUN settings, else it might over-ride them.
|
|
session.apiserver = urlParams.get("apiserver");
|
|
}
|
|
|
|
if (urlParams.has("speedtest")) {
|
|
// must set this after any custom TURN / STUN settings, else it might over-ride them.
|
|
session.speedtest = true;
|
|
if (urlParams.get("speedtest")) {
|
|
// forces essentially UDP mode, unless TCP is specified, and some other stuff
|
|
session.speedtest = urlParams.get("speedtest").toLowerCase(); // also limits bitrate
|
|
}
|
|
setupSpeedtest();
|
|
}
|
|
|
|
if (urlParams.has("privacy") || urlParams.has("private") || urlParams.has("relay")) {
|
|
// please only use if you are also using your own TURN service.
|
|
session.privacy = urlParams.get("privacy") || urlParams.get("private") || urlParams.get("relay") || true;
|
|
|
|
try {
|
|
// I'll re-apply this in the setupSpeedtest() promise callback, just to be case.
|
|
if (session.configuration) {
|
|
// this needs to set last, otherwise it might be overridden
|
|
session.configuration.iceTransportPolicy = "relay"; // https://developer.mozilla.org/en-US/docs/Web/API/RTCIceCandidate/address
|
|
}
|
|
} catch (e) {
|
|
if (!session.cleanOutput) {
|
|
warnUser("Privacy mode failed to configure.");
|
|
}
|
|
errorlog(e);
|
|
}
|
|
|
|
if (session.speedtest) {
|
|
warnlog("Bitrate being throttled to max of 6000 kbps");
|
|
if (session.maxvideobitrate !== false) {
|
|
if (session.maxvideobitrate > 6000) {
|
|
session.maxvideobitrate = 6000; // Please feel free to get rid of this if using your own TURN servers...
|
|
}
|
|
} else {
|
|
session.maxvideobitrate = 6000; // don't let people pull more than 6000 from you
|
|
}
|
|
if (session.bitrate !== false) {
|
|
if (session.bitrate > 6000) {
|
|
session.bitrate = 6000; // Please feel free to get rid of this if using your own TURN servers...
|
|
}
|
|
}
|
|
} else {
|
|
warnlog("Bitrate being throttled to max of 4000 kbps");
|
|
if (session.maxvideobitrate !== false) {
|
|
if (session.maxvideobitrate > 4000) {
|
|
session.maxvideobitrate = 4000; // Please feel free to get rid of this if using your own TURN servers...
|
|
}
|
|
} else {
|
|
session.maxvideobitrate = 4000; // don't let people pull more than 4000 from you
|
|
}
|
|
if (session.bitrate !== false) {
|
|
if (session.bitrate > 4000) {
|
|
session.bitrate = 4000; // Please feel free to get rid of this if using your own TURN servers...
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("osc") || urlParams.has("api")) {
|
|
if (urlParams.get("osc") || urlParams.get("api")) {
|
|
session.api = urlParams.get("osc") || urlParams.get("api") || false;
|
|
if (session.api) {
|
|
setTimeout(function () {
|
|
oscClient();
|
|
}, 1000);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("postapi") || urlParams.has("posturl")) {
|
|
session.postApi = urlParams.get("postapi") || urlParams.get("posturl") || false; // ie: &postapi=https%3A%2F%2Fwebhook.site%2Fb190f5bf-e4f8-454a-bd51-78b5807df9c1
|
|
if (session.postApi) {
|
|
try {
|
|
session.postApi = decodeURI(session.postApi) || session.postApi; // needs to be SSL enabled.
|
|
} catch (e) {
|
|
console.error(e);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("queue")) {
|
|
session.queue = true;
|
|
if (urlParams.get("queue") === "false") {
|
|
session.queue = false;
|
|
} else if (urlParams.get("queue") === "0") {
|
|
session.queue = false;
|
|
} else if (urlParams.get("queue") === "off") {
|
|
session.queue = false;
|
|
} else if (urlParams.get("queue")) {
|
|
session.queue = urlParams.get("queue");
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("queue2") || urlParams.has("screen")) {
|
|
// the guest can see the director, if the director doesn't have &queue
|
|
session.queue = true;
|
|
session.queueType = 2;
|
|
}
|
|
|
|
if (urlParams.has("queue3") || urlParams.has("hold")) {
|
|
// the guest can't see the director until approved, but does get a messaging telling them to wait. The director won't see the guest's video/audio either, until activated.
|
|
session.queue = true;
|
|
session.queueType = 3;
|
|
}
|
|
|
|
if (urlParams.has("queue4") || urlParams.has("holdwithvideo")) {
|
|
// the guest can't see the director until approved, but does get a messaging telling them to wait.
|
|
session.queue = true;
|
|
session.queueType = 4;
|
|
}
|
|
|
|
// do not reference stream ID before this point, as it might change after this point.
|
|
|
|
if (urlParams.has("push") || urlParams.has("id") || urlParams.has("permaid")) {
|
|
session.permaid = urlParams.get("push") || urlParams.get("id") || urlParams.get("permaid");
|
|
|
|
if (session.permaid) {
|
|
session.permaid = sanitizeStreamID(session.permaid) || null;
|
|
session.streamID = session.permaid || session.streamID;
|
|
} else if (urlParams.has("permaid") && getStorage("permaid")) {
|
|
session.streamID = sanitizeStreamID(getStorage("permaid")) || session.streamID;
|
|
session.permaid = null;
|
|
} else {
|
|
session.permaid = null;
|
|
}
|
|
|
|
if (urlParams.has("permaid")) {
|
|
setStorage("permaid", session.streamID, 99999);
|
|
}
|
|
|
|
if (urlParams.has("push")) {
|
|
updateURL("push=" + session.streamID, true, false);
|
|
} else if (urlParams.has("id")) {
|
|
updateURL("id=" + session.streamID, true, false); // not 'officially' supporting this yet; we'll see.
|
|
} else if (urlParams.has("permaid")) {
|
|
updateURL("permaid=" + session.streamID, true, false);
|
|
} else {
|
|
updateURL("push=" + session.streamID, true, false);
|
|
}
|
|
|
|
if (session.director) {
|
|
// if I do a short form of this, it will cause duplications in the code elsewhere.
|
|
//var director_room_input = urlParams.get('director');
|
|
//director_room_input = sanitizeRoomName(director_room_input);
|
|
//createRoom(director_room_input);
|
|
session.permaid = false; // used to avoid a trigger later on.
|
|
} else {
|
|
getById("container-1").className = "column columnfade hidden";
|
|
getById("container-4").className = "column columnfade hidden";
|
|
getById("dropButton").className = "column columnfade hidden";
|
|
|
|
getById("info").innerHTML = "";
|
|
if (session.videoDevice === 0) {
|
|
miniTranslate(getById("add_camera"), "share-your-mic", "Share your Microphone");
|
|
} else {
|
|
miniTranslate(getById("add_camera"), "share-your-camera", "Share your Camera");
|
|
}
|
|
miniTranslate(getById("add_screen"), "share-your-screen", "Share your Screen");
|
|
getById("container-2").title = getById("add_screen").innerText;
|
|
getById("container-3").title = getById("add_camera").innerText;
|
|
|
|
getById("passwordRoom").value = "";
|
|
getById("videoname1").value = "";
|
|
getById("dirroomid").innerHTML = "";
|
|
getById("roomid").innerHTML = "";
|
|
|
|
getById("mainmenu").style.alignSelf = "center";
|
|
getById("mainmenu").classList.add("mainmenuclass");
|
|
getById("header").style.alignSelf = "center";
|
|
|
|
//if ((iOS) || (iPad)) {
|
|
//getById("header").style.display = "none"; // just trying to free up space.
|
|
//}
|
|
|
|
if (session.webcamonly == true) {
|
|
// mobile or manual flag 'webcam' pflag set
|
|
getById("head1").innerHTML = '<span style="color:#CCC;" data-translate="please-accept-permissions">- Please accept any camera permissions</span>';
|
|
} else {
|
|
getById("head1").innerHTML = '<br /><span style="color:#CCC" data-translate="please-select-which-to-share">- Please select which you wish to share</span>';
|
|
}
|
|
|
|
if (!session.cleanOutput) {
|
|
try {
|
|
if (window.obsstudio) {
|
|
getById("unexpectedPushLink").classList.remove("hidden");
|
|
}
|
|
} catch (e) {}
|
|
}
|
|
}
|
|
}
|
|
if (session.roomid || urlParams.has("roomid") || urlParams.has("r") || urlParams.has("room") || filename || session.permaid !== false) {
|
|
var roomid = "";
|
|
if (urlParams.has("room")) {
|
|
// needs to be first; takes priority
|
|
roomid = urlParams.get("room");
|
|
} else if (urlParams.has("roomid")) {
|
|
roomid = urlParams.get("roomid");
|
|
} else if (urlParams.has("r")) {
|
|
roomid = urlParams.get("r");
|
|
} else if (session.roomid) {
|
|
roomid = session.roomid;
|
|
} else if (filename) {
|
|
roomid = filename;
|
|
}
|
|
session.roomid = sanitizeRoomName(roomid);
|
|
if (session.director) {
|
|
if (session.director !== session.roomid) {
|
|
if (!session.cleanOutput) {
|
|
warnUser("Conflicting director and room values were provided.\n\n Check your URL parameters; there should be only &director OR &room", 5000);
|
|
}
|
|
}
|
|
session.roomid = false;
|
|
}
|
|
}
|
|
|
|
if (session.permaid === false && session.roomid === false && session.view === false && session.effect === false && session.director === false) {
|
|
session.effect = null;
|
|
}
|
|
|
|
if (session.mobile && session.permaid === false && !session.roomid) {
|
|
getById("rememberStreamID").classList.remove("hidden");
|
|
|
|
let rememberStreamIDmobile = getStorage("rememberStreamIDmobile");
|
|
if (rememberStreamIDmobile === "false") {
|
|
getById("rememberStreamIDcheck").checked = false;
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("hostwhep") || urlParams.has("whepout")) {
|
|
session.whepHost = urlParams.get("hostwhep") || urlParams.get("whepout") || session.streamID || false;
|
|
}
|
|
|
|
if (urlParams.get("mediamtx")){
|
|
session.mediamtx = urlParams.get("mediamtx");
|
|
}
|
|
|
|
if (session.mediamtx){
|
|
if (!session.mediamtx.includes(".") && !session.mediamtx.includes("localhost")){
|
|
session.mediamtx += ".com";
|
|
}
|
|
if (!session.mediamtx.includes(":")){
|
|
session.mediamtx += ":8889";
|
|
}
|
|
if (!session.whipOutput){
|
|
if (!(session.mediamtx.startsWith("https://") || session.mediamtx.startsWith("http://"))){
|
|
if (session.mediamtx.startsWith("localhost:")){
|
|
session.whipOutput = "http://"+session.mediamtx+"/"+session.streamID+"/whip";
|
|
|
|
if (!session.whipoutSettings){
|
|
session.whipoutSettings = { type: "whep", url: "http://"+session.mediamtx+"/"+session.streamID+"/whep" };
|
|
console.log("WHIP OUT: "+session.whipOutput+", WHEP SHARE: "+session.whipoutSettings.url);
|
|
}
|
|
|
|
} else {
|
|
session.whipOutput = "https://"+session.mediamtx+"/"+session.streamID+"/whip";
|
|
}
|
|
} else if (session.mediamtx.endsWith("/")){
|
|
session.whipOutput = session.mediamtx+session.streamID+"/whip";
|
|
} else {
|
|
session.whipOutput = session.mediamtx+"/"+session.streamID+"/whip";
|
|
}
|
|
}
|
|
if (!session.whipoutSettings){
|
|
session.whipoutSettings = { type: "whep", url: "https://"+session.mediamtx+"/"+session.streamID+"/whep" };
|
|
console.log("WHIP OUT: "+session.whipOutput+", WHEP SHARE: "+session.whipoutSettings.url);
|
|
}
|
|
if (session.stereo === false){
|
|
if (!session.whipOutAudioCodec || (session.whipOutAudioCodec=="opus")){
|
|
session.stereo=3;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("effects") || urlParams.has("effect")) {
|
|
session.effect = urlParams.get("effects") || urlParams.get("effect") || null;
|
|
} else if (urlParams.has("zoom") || urlParams.has("digitalzoom")) {
|
|
session.effect = "7";
|
|
}
|
|
|
|
if (session.effect && !session.cleanOutput) {
|
|
if (ChromiumVersion && ChromiumVersion === 122) {
|
|
warnUser("⚠️ Notice: A recent update to Chrome/Edge can cause the browser to crash, especially when using &effects or &zoom.\n\nBrowser updates are rolling out to fix the issue, however avoiding the use of digital video effects for now might be prudent", 30000);
|
|
}
|
|
}
|
|
|
|
if (urlParams.get("wb") || urlParams.get("whitebalance")) {
|
|
session.whiteBalance = urlParams.get("wb") || urlParams.get("whitebalance");
|
|
}
|
|
if (urlParams.get("exposure")) {
|
|
session.exposure = urlParams.get("exposure");
|
|
}
|
|
if (urlParams.get("saturation")) {
|
|
session.saturation = urlParams.get("saturation");
|
|
}
|
|
if (urlParams.get("sharpness")) {
|
|
session.sharpness = urlParams.get("sharpness");
|
|
}
|
|
if (urlParams.get("contrast")) {
|
|
session.contrast = urlParams.get("contrast");
|
|
}
|
|
if (urlParams.get("brightness")) {
|
|
session.brightness = urlParams.get("brightness");
|
|
}
|
|
if (urlParams.get("focus")) {
|
|
session.focusDistance = urlParams.get("focus");
|
|
}
|
|
|
|
if (urlParams.has("wss")) {
|
|
session.customWSS = true;
|
|
session.wssSetViaUrl = true;
|
|
if (urlParams.get("wss")) {
|
|
session.wss = urlParams.get("wss");
|
|
if (!session.wss.startsWith("wss://")) {
|
|
session.wss = "wss://" + session.wss;
|
|
}
|
|
}
|
|
} else if (urlParams.has("wss2")) {
|
|
session.wssSetViaUrl = true;
|
|
if (urlParams.get("wss2")) {
|
|
session.wss = urlParams.get("wss2");
|
|
if (!session.wss.startsWith("wss://")) {
|
|
session.wss = "wss://" + session.wss;
|
|
}
|
|
}
|
|
} else if (urlParams.get("audience")) {
|
|
session.audience = urlParams.get("audience");
|
|
if (urlParams.get("audience") && session.view !== false) {
|
|
session.wss = "wss://audience.vdo.ninja/listen/" + session.audience;
|
|
} else {
|
|
session.wss = "wss://audience.vdo.ninja/publish/" + session.audience;
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("bypass")) {
|
|
session.bypass = true;
|
|
session.customWSS = true;
|
|
}
|
|
|
|
if (window.FaceDetector !== undefined) {
|
|
document.querySelectorAll(".facetracker").forEach(ele => {
|
|
ele.disabled = null;
|
|
ele.removeAttribute("disabled");
|
|
ele.title = "Will slowly pan, tilt, and zoom in on the first face detected";
|
|
});
|
|
}
|
|
|
|
if (urlParams.has("imagelist")) {
|
|
// "&imagelist="+encodeURIComponent(JSON.stringify(["./media/bg_sample.webp", "./media/bg_sample2.webp"]))
|
|
var imageList = urlParams.get("imagelist"); //
|
|
if (imageList) {
|
|
try {
|
|
imageList = JSON.parse(decodeURIComponent(imageList));
|
|
if (imageList.length) {
|
|
session.defaultBackgroundImages = imageList; // ["./media/bg_sample.webp", "./media/bg_sample2.webp"]
|
|
} else {
|
|
warnlog("empty image array; skipping");
|
|
}
|
|
} catch (e) {
|
|
console.error(e);
|
|
try {
|
|
imageList = decodeURIComponent(imageList);
|
|
} catch (e) {
|
|
console.error(e);
|
|
}
|
|
if (imageList) {
|
|
session.defaultBackgroundImages = [imageList]; // ["./media/bg_sample.webp", "./media/bg_sample2.webp"]
|
|
} else {
|
|
warnlog("empty image array; skipping");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (session.effect !== false) {
|
|
if (session.effect === null) {
|
|
getById("effectsDiv").style.display = "inline-block";
|
|
session.effect = "0";
|
|
} else if (session.effect === "0" || session.effect === "false" || session.effect === "off" || session.effect === 0) {
|
|
session.effect = false;
|
|
getById("effectSelector3").style.display = "none";
|
|
getById("effectsDiv3").style.display = "none";
|
|
getById("effectSelector").style.display = "none";
|
|
getById("effectsDiv").style.display = "none";
|
|
}
|
|
|
|
if (session.effect === "5") {
|
|
loadTFLITEImages();
|
|
|
|
getById("effectSelector").style.display = "none";
|
|
getById("effectsDiv").style.display = "inline-block";
|
|
}
|
|
if (session.effect === "3a") {
|
|
// heavier blur
|
|
session.effectValue = 5;
|
|
session.effect = "3";
|
|
} else if (session.effect === "3") {
|
|
session.effectValue = 2;
|
|
} else if (session.effect === "7") {
|
|
session.effectValue = 1;
|
|
}
|
|
// mirror == 2
|
|
// face == 1
|
|
// blur = 3
|
|
// green = 4
|
|
// image = 5
|
|
}
|
|
|
|
if (urlParams.has("effectvalue") || urlParams.has("ev")) {
|
|
session.effectValue = parseFloat(urlParams.get("effectvalue")) || parseFloat(urlParams.get("ev")) || 0;
|
|
session.effectValue_default = session.effectValue;
|
|
}
|
|
|
|
if (session.webcamonly == true) {
|
|
if (session.introButton) {
|
|
getById("container-2").className = "column columnfade hidden"; // Hide screen share
|
|
getById("head3").classList.add("hidden");
|
|
getById("head3a").classList.add("hidden");
|
|
} else {
|
|
getById("container-2").className = "column columnfade hidden"; // Hide screen share
|
|
getById("container-3").classList.add("skip-animation");
|
|
getById("container-3").classList.remove("pointer");
|
|
delayedStartupFuncs.push([previewWebcam]);
|
|
}
|
|
}
|
|
if (session.introOnClean && session.permaid === false && session.roomid === false) {
|
|
//getById("container-2").className = 'column columnfade hidden'; // Hide screen share
|
|
getById("head3").classList.add("hidden");
|
|
getById("head3a").classList.add("hidden");
|
|
} else if (session.introOnClean && session.scene === false && (session.permaid !== false || session.roomid !== false)) {
|
|
getById("container-2").className = "column columnfade hidden"; // Hide screen share
|
|
getById("container-3").classList.add("skip-animation");
|
|
getById("container-3").classList.remove("pointer");
|
|
delayedStartupFuncs.push([previewWebcam]);
|
|
}
|
|
|
|
//if (!session.director && ((ChromiumVersion == 86) || (ChromiumVersion == 77) || (ChromiumVersion == 62) || (ChromiumVersion == 51)) && (((session.permaid===false) && session.view) || (session.scene!==false))){
|
|
// session.studioSoftware = true; // vmix
|
|
if (window.obsstudio) {
|
|
session.studioSoftware = true;
|
|
getById("saveRoom").style.display = "none"; // don't let the user save the room if in OBS
|
|
}
|
|
if (session.cleanViewer) {
|
|
if ((session.view || session.whepInput) && !session.director && session.permaid === false) {
|
|
session.cleanOutput = true;
|
|
}
|
|
}
|
|
if (urlParams.has("clock") || urlParams.has("clock24")) {
|
|
let urlClock = urlParams.get("clock") || urlParams.get("clock24");
|
|
if (urlParams.has("clock24")) {
|
|
session.clock24 = true;
|
|
}
|
|
session.showTime = true;
|
|
if (urlClock === "false") {
|
|
session.showTime = false;
|
|
} else if (urlClock === "0") {
|
|
session.showTime = false;
|
|
} else if (urlClock === "1") {
|
|
getById("overlayClockContainer2").classList.add("top");
|
|
getById("overlayClockContainer2").classList.add("left");
|
|
} else if (urlClock === "7") {
|
|
getById("overlayClockContainer2").classList.add("bottom");
|
|
getById("overlayClockContainer2").classList.add("left");
|
|
} else if (urlClock === "4") {
|
|
getById("overlayClockContainer2").classList.add("vmiddle");
|
|
getById("overlayClockContainer2").classList.add("left");
|
|
} else if (urlClock === "2") {
|
|
getById("overlayClockContainer2").classList.add("top");
|
|
getById("overlayClockContainer2").classList.add("hmiddle");
|
|
} else if (urlClock === "8") {
|
|
getById("overlayClockContainer2").classList.add("bottom");
|
|
getById("overlayClockContainer2").classList.add("hmiddle");
|
|
} else if (urlClock === "5") {
|
|
getById("overlayClockContainer2").classList.add("vmiddle");
|
|
getById("overlayClockContainer2").classList.add("hmiddle");
|
|
} else if (urlClock === "3") {
|
|
getById("overlayClockContainer2").classList.add("top");
|
|
getById("overlayClockContainer2").classList.add("right");
|
|
} else if (urlClock === "9") {
|
|
getById("overlayClockContainer2").classList.add("bottom");
|
|
getById("overlayClockContainer2").classList.add("right");
|
|
} else if (urlClock === "6") {
|
|
getById("overlayClockContainer2").classList.add("vmiddle");
|
|
getById("overlayClockContainer2").classList.add("right");
|
|
}
|
|
} else if (session.cleanOutput) {
|
|
session.showTime = false;
|
|
}
|
|
|
|
if (urlParams.has("timer")) {
|
|
if (urlParams.get("timer") === "1") {
|
|
getById("overlayClockContainer").classList.add("top");
|
|
getById("overlayClockContainer").classList.add("left");
|
|
} else if (urlParams.get("timer") === "7") {
|
|
getById("overlayClockContainer").classList.add("bottom");
|
|
getById("overlayClockContainer").classList.add("left");
|
|
} else if (urlParams.get("timer") === "4") {
|
|
getById("overlayClockContainer").classList.add("vmiddle");
|
|
getById("overlayClockContainer").classList.add("left");
|
|
} else if (urlParams.get("timer") === "2") {
|
|
getById("overlayClockContainer").classList.add("top");
|
|
getById("overlayClockContainer").classList.add("hmiddle");
|
|
} else if (urlParams.get("timer") === "8") {
|
|
getById("overlayClockContainer").classList.add("bottom");
|
|
getById("overlayClockContainer").classList.add("hmiddle");
|
|
} else if (urlParams.get("timer") === "5") {
|
|
getById("overlayClockContainer").classList.add("vmiddle");
|
|
getById("overlayClockContainer").classList.add("hmiddle");
|
|
} else if (urlParams.get("timer") === "3") {
|
|
getById("overlayClockContainer").classList.add("top");
|
|
getById("overlayClockContainer").classList.add("right");
|
|
} else if (urlParams.get("timer") === "9") {
|
|
getById("overlayClockContainer").classList.add("bottom");
|
|
getById("overlayClockContainer").classList.add("right");
|
|
} else if (urlParams.get("timer") === "6") {
|
|
getById("overlayClockContainer").classList.add("vmiddle");
|
|
getById("overlayClockContainer").classList.add("right");
|
|
} else {
|
|
getById("overlayClockContainer").classList.add("top");
|
|
getById("overlayClockContainer").classList.add("hmiddle");
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("miconlyoption") || urlParams.has("moo")) {
|
|
session.optionalMicOnly = true;
|
|
}
|
|
|
|
if (urlParams.has("hidescreenshare") || urlParams.has("hidess") || urlParams.has("sshide") || urlParams.has("screensharehide")) {
|
|
// this way I don't need to remember what it's called. I can just guess. :D
|
|
session.screenShareElementHidden = true;
|
|
}
|
|
|
|
if (urlParams.has("sspaused") || urlParams.has("sspause") || urlParams.has("ssp")) {
|
|
// this way I don't need to remember what it's called. I can just guess. :D
|
|
session.screenShareStartPaused = true;
|
|
}
|
|
|
|
if (urlParams.has("zoomedbitrate") || urlParams.has("zb")) {
|
|
// this way I don't need to remember what it's called. I can just guess. :D
|
|
session.zoomedBitrate = urlParams.get("zoomedbitrate") || urlParams.get("zb") || 2500;
|
|
session.zoomedBitrate = parseInt(session.zoomedBitrate);
|
|
}
|
|
|
|
if (urlParams.has("screenshareid") || urlParams.has("ssid")) {
|
|
if (urlParams.get("screenshareid") || urlParams.get("ssid")) {
|
|
session.screenshareid = urlParams.get("screenshareid") || urlParams.get("ssid");
|
|
session.screenshareid = sanitizeStreamID(session.screenshareid);
|
|
} else {
|
|
session.screenshareid = session.streamID + "_ss";
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("screensharevideoonly") || urlParams.has("ssvideoonly") || urlParams.has("ssvo")) {
|
|
session.screenshareVideoOnly = true;
|
|
getById("audioScreenShare1").classList.add("hidden");
|
|
}
|
|
|
|
if (urlParams.has("screensharefps") || urlParams.has("ssfps")) {
|
|
if (urlParams.get("screensharefps") || urlParams.get("ssfps")) {
|
|
session.screensharefps = urlParams.get("screensharefps") || urlParams.get("ssfps");
|
|
session.screensharefps = parseInt(session.screensharefps) || 2;
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("screensharequality") || urlParams.has("ssq")) {
|
|
session.screensharequality = urlParams.get("screensharequality") || urlParams.get("ssq") || "0";
|
|
|
|
if (session.screensharequality.toLowerCase() == "4k") {
|
|
session.screensharequality = -2;
|
|
} else if (session.screensharequality.toLowerCase() == "2160p") {
|
|
session.screensharequality = -2;
|
|
} else if (session.screensharequality.toLowerCase() == "2160") {
|
|
session.screensharequality = -2;
|
|
} else if (session.screensharequality.toLowerCase() == "2k") {
|
|
session.screensharequality = -3;
|
|
} else if (session.screensharequality.toLowerCase() == "1440p") {
|
|
session.screensharequality = -3;
|
|
} else if (session.screensharequality.toLowerCase() == "1440") {
|
|
session.screensharequality = -3;
|
|
} else if (session.screensharequality.toLowerCase() == "hd") {
|
|
session.screensharequality = 1;
|
|
} else if (session.screensharequality.toLowerCase() == "720p") {
|
|
session.screensharequality = 1;
|
|
} else if (session.screensharequality.toLowerCase() == "720") {
|
|
session.screensharequality = 1;
|
|
} else if (session.screensharequality.toLowerCase() == "fullhd") {
|
|
session.screensharequality = 0;
|
|
} else if (session.screensharequality.toLowerCase() == "1080p") {
|
|
session.screensharequality = 0;
|
|
} else if (session.screensharequality.toLowerCase() == "1080") {
|
|
session.screensharequality = 0;
|
|
} else if (session.screensharequality.toLowerCase() == "high") {
|
|
session.screensharequality = 0;
|
|
} else if (session.screensharequality.toLowerCase() == "360p") {
|
|
session.screensharequality = 2;
|
|
} else if (session.screensharequality.toLowerCase() == "360") {
|
|
session.screensharequality = 2;
|
|
} else if (session.screensharequality.toLowerCase() == "low") {
|
|
session.screensharequality = 2;
|
|
} else {
|
|
session.screensharequality = parseInt(session.screensharequality) || 0;
|
|
}
|
|
try {
|
|
getById("gear_screen").parentNode.removeChild(getById("gear_screen"));
|
|
} catch (e) {}
|
|
}
|
|
|
|
if (urlParams.has("screensharebitrate") || urlParams.has("ssbitrate")) {
|
|
session.screenShareBitrate = urlParams.get("screensharebitrate") || urlParams.get("ssbitrate");
|
|
session.screenShareBitrate = parseInt(session.screenShareBitrate) || 2500;
|
|
}
|
|
|
|
if (urlParams.has("screensharelabel") || urlParams.has("sslabel")) {
|
|
session.screenShareLabel = urlParams.get("screensharelabel") || urlParams.get("sslabel");
|
|
try {
|
|
session.screenShareLabel = decodeURIComponent(session.screenShareLabel);
|
|
} catch (e) {}
|
|
session.screenShareLabel = session.screenShareLabel.replace(/_/g, " ");
|
|
}
|
|
|
|
if (urlParams.has("whepshare") || urlParams.has("whepsrc")) {
|
|
try {
|
|
session.whepSrc = urlParams.get("whepshare") || urlParams.get("whepsrc") || null;
|
|
log("WHEP SRC: " + session.whepSrc);
|
|
if (session.whepSrc) {
|
|
try {
|
|
session.whepSrc = decodeURIComponent(session.whepSrc);
|
|
} catch (e) {
|
|
session.whepSrc = session.whepSrc;
|
|
}
|
|
} else {
|
|
session.whepSrc = await promptAlt("Enter the WHEP source as a URL");
|
|
}
|
|
if (session.whepSrc) {
|
|
session.whipoutSettings = { type: "whep", url: session.whepSrc };
|
|
}
|
|
} catch (e) {
|
|
errorlog(e);
|
|
}
|
|
}
|
|
if (urlParams.has("whepsharetoken") || urlParams.has("whepsrctoken")) {
|
|
if (session.whipoutSettings) {
|
|
try {
|
|
session.whepSrcToken = urlParams.get("whepsharetoken") || urlParams.get("whepsrctoken") || null;
|
|
log("WHEP TOKEN: " + session.whepSrcToken);
|
|
if (session.whepSrcToken) {
|
|
try {
|
|
session.whepSrcToken = decodeURIComponent(session.whepSrcToken);
|
|
} catch (e) {
|
|
session.whepSrcToken = session.whepSrcToken;
|
|
}
|
|
} else {
|
|
session.whepSrcToken = await promptAlt("Enter the WHEP source token");
|
|
}
|
|
if (session.whepSrcToken) {
|
|
session.whipoutSettings.token = session.whepSrcToken;
|
|
}
|
|
} catch (e) {
|
|
errorlog(e);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (session.roomid !== false) {
|
|
if (!session.cleanOutput) {
|
|
if (session.roomid === "test") {
|
|
if (session.password === session.defaultPassword) {
|
|
window.focus();
|
|
var testRoomResponse = confirm(getTranslation("room-test-not-good"));
|
|
if (testRoomResponse == false) {
|
|
hangup();
|
|
throw new Error("User requested to not enter room 'room'.");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (session.audioDevice === false && session.outputDevice === false) {
|
|
getById("headphonesDiv2").style.display = "inline-block";
|
|
getById("headphonesDiv").style.display = "inline-block";
|
|
}
|
|
getById("addPasswordBasic").style.display = "none";
|
|
|
|
getById("info").innerHTML = "";
|
|
getById("info").style.color = "#CCC";
|
|
getById("videoname1").value = session.roomid;
|
|
getById("dirroomid").innerText = session.roomid;
|
|
getById("roomid").innerText = session.roomid;
|
|
getById("container-1").className = "column columnfade hidden";
|
|
getById("container-4").className = "column columnfade hidden";
|
|
// container 5 is share media file; 6 is share website
|
|
getById("container-7").style.display = "none";
|
|
getById("container-8").style.display = "none";
|
|
getById("container-9").style.display = "none";
|
|
getById("container-10").style.display = "none";
|
|
getById("container-11").style.display = "none";
|
|
getById("container-12").style.display = "none";
|
|
getById("container-13").style.display = "none";
|
|
getById("container-14").style.display = "none";
|
|
getById("container-15").style.display = "none";
|
|
getById("mainmenu").style.alignSelf = "center";
|
|
getById("mainmenu").classList.add("mainmenuclass");
|
|
getById("header").style.alignSelf = "center";
|
|
|
|
if (session.webcamonly == true) {
|
|
// mobile or manual flag 'webcam' pflag set
|
|
getById("head1").innerHTML = "";
|
|
} else {
|
|
getById("head1").innerHTML = '<span style="color:#CCC" data-translate="please-select-option-to-join">Please select an option to join.</span>';
|
|
}
|
|
|
|
if (session.roomid.length > 0) {
|
|
if (session.videoDevice === 0) {
|
|
if (session.audioDevice === 0) {
|
|
miniTranslate(getById("add_camera"), "join-room", "Join Room");
|
|
} else {
|
|
miniTranslate(getById("add_camera"), "join-room-with-mic", "Join Room with Microphone");
|
|
}
|
|
} else if (session.audioDevice === 0) {
|
|
miniTranslate(getById("add_camera"), "join-room-with-camera", "Join Room with Camera");
|
|
} else if (session.optionalMicOnly) {
|
|
miniTranslate(getById("add_camera"), "join-room-with-video", "Join Room with Video");
|
|
miniTranslate(getById("add_microphone"), "join-room-with-mic-only", "Join Room with just Microphone");
|
|
getById("container-3a").classList.remove("hidden");
|
|
} else {
|
|
miniTranslate(getById("add_camera"), "join-room-with-camera", "Join Room with Camera");
|
|
}
|
|
miniTranslate(getById("add_screen"), "share-screen-with-room", "Screenshare with Room");
|
|
} else {
|
|
if (session.videoDevice === 0) {
|
|
miniTranslate(getById("add_camera"), "share-your-mic", "Share your Microphone");
|
|
} else {
|
|
miniTranslate(getById("add_camera"), "share-your-camera", "Share your Camera");
|
|
}
|
|
miniTranslate(getById("add_screen"), "share-your-screen", "Share your Screen");
|
|
}
|
|
getById("head3").classList.add("hidden");
|
|
getById("head3a").classList.add("hidden");
|
|
getById("container-2").title = getById("add_screen").innerText;
|
|
getById("container-3").title = getById("add_camera").innerText;
|
|
|
|
if (session.scene !== false) {
|
|
getById("container-4").className = "column columnfade";
|
|
getById("container-3").className = "column columnfade";
|
|
getById("container-2").className = "column columnfade";
|
|
getById("container-1").className = "column columnfade";
|
|
getById("header").className = "hidden";
|
|
getById("info").className = "hidden";
|
|
getById("head1").className = "hidden";
|
|
getById("head2").className = "hidden";
|
|
getById("mainmenu").style.display = "none";
|
|
getById("translateButton").style.display = "none";
|
|
log("Update Mixer Event on REsize SET");
|
|
window.onresize = updateMixer;
|
|
window.onorientationchange = function () {
|
|
setTimeout(updateMixer, 200);
|
|
};
|
|
joinRoom(session.roomid); // this is a scene, so we want high resolutions
|
|
getById("main").style.overflow = "hidden";
|
|
|
|
if (session.chatbutton === true) {
|
|
getById("chatbutton").classList.remove("hidden");
|
|
getById("controlButtons").classList.remove("hidden");
|
|
} else if (session.chatbutton === false) {
|
|
getById("chatbutton").classList.add("hidden");
|
|
}
|
|
} else if (session.permaid === null && session.roomid == "") {
|
|
if (!session.cleanOutput) {
|
|
// getById("head3").classList.remove('hidden');
|
|
// getById("head3a").classList.remove('hidden');
|
|
}
|
|
} else if (window.obsstudio && session.permaid === false && session.director === false && (session.view || session.whepInput) && session.roomid.length > 0) {
|
|
// we already know roomid !== false
|
|
updateURL("scene", true, false); // we also know it's not a scene, but we will assume it is in this specific case.
|
|
}
|
|
} else if (session.director) {
|
|
// if I do a short form of this, it will cause duplications in the code elsewhere.
|
|
if (directorLanding == false) {
|
|
// implies director is not true or false, but a string
|
|
try {
|
|
var director_room_input = sanitizeRoomName(session.director);
|
|
log("director_room_input:" + director_room_input);
|
|
|
|
if (urlParams.has("codirector") || urlParams.has("directorpassword") || urlParams.has("dirpass") || urlParams.has("dp")) {
|
|
session.directorPassword = urlParams.get("codirector") || urlParams.get("directorpassword") || urlParams.get("dirpass") || urlParams.get("dp");
|
|
if (!session.directorPassword) {
|
|
window.focus();
|
|
session.directorPassword = await promptAlt(getTranslation("enter-director-password"), true);
|
|
} else {
|
|
try {
|
|
session.directorPassword = decodeURIComponent(session.directorPassword);
|
|
} catch (e) {}
|
|
}
|
|
if (session.directorPassword) {
|
|
session.directorPassword = sanitizePassword(session.directorPassword);
|
|
await generateHash(session.directorPassword + session.salt + "abc123", 12)
|
|
.then(function (hash) {
|
|
// million to one error.
|
|
log("dir room hash is " + hash);
|
|
session.directorHash = hash;
|
|
return;
|
|
})
|
|
.catch(errorlog);
|
|
} else {
|
|
session.directorPassword = false;
|
|
}
|
|
}
|
|
|
|
setTimeout(
|
|
function (director_room_input) {
|
|
createRoom(director_room_input);
|
|
},
|
|
20,
|
|
director_room_input
|
|
);
|
|
} catch (e) {
|
|
directorLanding = true;
|
|
session.director = true;
|
|
}
|
|
}
|
|
if (session.chatbutton === true) {
|
|
getById("chatbutton").classList.remove("hidden");
|
|
getById("controlButtons").classList.remove("hidden");
|
|
} else if (session.chatbutton === false) {
|
|
getById("chatbutton").classList.add("hidden");
|
|
}
|
|
} else if ((session.view || session.whepInput) && session.permaid === false) {
|
|
//if (!session.activeSpeaker){
|
|
session.audioMeterGuest = false;
|
|
//}
|
|
if (session.style === false && window.obsstudio) {
|
|
session.style = 1;
|
|
}
|
|
if (session.audioEffects === null) {
|
|
session.audioEffects = false;
|
|
}
|
|
log("Update Mixer Event on REsize SET");
|
|
getById("translateButton").style.display = "none";
|
|
window.onresize = updateMixer;
|
|
window.onorientationchange = function () {
|
|
setTimeout(function () {
|
|
updateMixer();
|
|
}, 200);
|
|
};
|
|
getById("main").style.overflow = "hidden";
|
|
|
|
if (session.chatbutton === true) {
|
|
getById("chatbutton").classList.remove("hidden");
|
|
getById("controlButtons").classList.remove("hidden");
|
|
} else if (session.chatbutton === false) {
|
|
getById("chatbutton").classList.add("hidden");
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("nofileshare") || urlParams.has("nodownloads") || urlParams.has("nofiles")) {
|
|
session.hostedFiles = false;
|
|
session.nodownloads = true;
|
|
getById("sharefilebutton").style.display = "none";
|
|
getById("sharefilebutton").classList.add("hidden");
|
|
} else if (session.mobile) {
|
|
getById("sharefilebutton").style.display = "none";
|
|
getById("sharefilebutton").classList.add("hidden");
|
|
} else if (session.roomid == false) {
|
|
getById("sharefilebutton").style.display = "none";
|
|
getById("sharefilebutton").classList.add("hidden");
|
|
} else if (session.scene !== false) {
|
|
getById("sharefilebutton").style.display = "none";
|
|
getById("sharefilebutton").classList.add("hidden");
|
|
} else if (session.cleanOutput) {
|
|
getById("sharefilebutton").style.display = "none";
|
|
getById("sharefilebutton").classList.add("hidden");
|
|
}
|
|
|
|
if (session.audioEffects === null) {
|
|
session.audioEffects = true;
|
|
}
|
|
|
|
if (session.audioEffects) {
|
|
getById("channelGroup1").style.display = "block";
|
|
getById("channelGroup2").style.display = "block";
|
|
}
|
|
|
|
if (urlParams.has("hidemenu") || urlParams.has("hm")) {
|
|
// needs to happen the room and permaid applications
|
|
getById("mainmenu").style.display = "none";
|
|
getById("header").style.display = "none";
|
|
getById("mainmenu").style.opacity = 0;
|
|
getById("header").style.opacity = 0;
|
|
}
|
|
|
|
if (urlParams.has("hideusermenu") || urlParams.has("nousermenu") || urlParams.has("hum")) {
|
|
getById("advancedOptionsGeneral").classList.add("hidden");
|
|
}
|
|
|
|
if (session.view || session.whepInput) {
|
|
getById("main").className = "";
|
|
getById("credits").style.display = "none";
|
|
try {
|
|
if (session.label === false) {
|
|
if (document.title == "") {
|
|
document.title = "View=" + session.view.toString();
|
|
} else {
|
|
document.title += ", View=" + session.view.toString();
|
|
}
|
|
}
|
|
} catch (e) {
|
|
errorlog(e);
|
|
}
|
|
}
|
|
|
|
if (urlParams.get("auth")) {
|
|
session.auth = urlParams.get("auth");
|
|
}
|
|
|
|
if (urlParams.has("waitimage")) {
|
|
session.waitImage = urlParams.get("waitimage") || false;
|
|
}
|
|
|
|
if (((session.view || session.whepInput) && session.roomid === false) || (session.waitImage && session.scene !== false)) {
|
|
getById("container-4").className = "column columnfade";
|
|
getById("container-3").className = "column columnfade";
|
|
getById("container-2").className = "column columnfade";
|
|
getById("container-1").className = "column columnfade";
|
|
//getById("header").className = 'hidden';
|
|
getById("info").className = "hidden";
|
|
getById("header").className = "hidden";
|
|
getById("head1").className = "hidden";
|
|
getById("head2").className = "hidden";
|
|
getById("head3").classList.add("hidden");
|
|
getById("head3a").classList.add("hidden");
|
|
|
|
getById("mainmenu").style.backgroundRepeat = "no-repeat";
|
|
getById("mainmenu").style.backgroundPosition = "bottom center";
|
|
getById("mainmenu").style.minHeight = "100%";
|
|
getById("mainmenu").style.minWidth = "100%";
|
|
getById("mainmenu").style.backgroundSize = "100px 100px";
|
|
getById("mainmenu").innerHTML = "";
|
|
getById("mainmenu").classList.remove("row");
|
|
getById("mainmenu").style.display = "block";
|
|
|
|
if (urlParams.has("waittimeout")) {
|
|
session.waitImageTimeout = parseInt(urlParams.get("waittimeout")) || 0;
|
|
}
|
|
if (!session.fakeFeeds) {
|
|
session.waitImageTimeoutObject = setTimeout(function () {
|
|
session.waitImageTimeoutObject = true;
|
|
try {
|
|
if (session.view || session.whepInput) {
|
|
if (document.getElementById("mainmenu")) {
|
|
if (session.waitImage) {
|
|
getById("mainmenu").innerHTML += '<img id="retryimage"/>';
|
|
getById("retryimage").src = decodeURIComponent(session.waitImage);
|
|
getById("retryimage").onerror = function () {
|
|
this.style.display = "none";
|
|
};
|
|
|
|
if (session.cover) {
|
|
getById("retryimage").style.objectFit = "cover";
|
|
}
|
|
} else if (!session.cleanOutput) {
|
|
getById("mainmenu").innerHTML += '<div class="retry-spinner" id="retrySpinner"></div>';
|
|
getById("retrySpinner").onclick = function () {
|
|
updateURL("cleanoutput");
|
|
location.reload();
|
|
};
|
|
getById("retrySpinner").title = getTranslation("waiting-for-the-stream");
|
|
}
|
|
if (urlParams.has("waitmessage")) {
|
|
getById("mainmenu").innerHTML += '<div id="retrymessage"></div>';
|
|
getById("retrymessage").innerText = urlParams.get("waitmessage");
|
|
getById("retrySpinner").title = urlParams.get("waitmessage");
|
|
}
|
|
}
|
|
}
|
|
} catch (e) {
|
|
errorlog(e);
|
|
}
|
|
}, session.waitImageTimeout);
|
|
}
|
|
|
|
log("auto request videos");
|
|
if ((iPad || iOS) && navigator.userAgent.indexOf("Safari") != -1 && navigator.userAgent.indexOf("Chrome") == -1 && SafariVersion > 13) {
|
|
// Modern iOS doesn't need pop up
|
|
play();
|
|
} else if (navigator.userAgent.indexOf("Safari") != -1 && navigator.userAgent.indexOf("Chrome") == -1) {
|
|
// Safari on Desktop does require pop up
|
|
if (!session.cleanOutput) {
|
|
warnUser("Safari requires us to ask for an audio permission to use peer-to-peer technology. You will need to accept it in a moment if asked to view this live video", 20000);
|
|
}
|
|
navigator.mediaDevices
|
|
.getUserMedia({
|
|
audio: true
|
|
})
|
|
.then(function () {
|
|
closeModal();
|
|
play();
|
|
})
|
|
.catch(function () {
|
|
play();
|
|
});
|
|
} else {
|
|
// everything else is OK.
|
|
play();
|
|
}
|
|
} else if (session.roomid) {
|
|
try {
|
|
if (session.label === false) {
|
|
if (document.title == "") {
|
|
document.title = "Room=" + session.roomid.toString();
|
|
} else {
|
|
document.title += ": " + session.roomid.toString();
|
|
}
|
|
}
|
|
} catch (e) {
|
|
errorlog(e);
|
|
}
|
|
} else {
|
|
try {
|
|
let reloadOldRoom = getStorage("directorOtherSettings");
|
|
if (reloadOldRoom && reloadOldRoom.roomid) {
|
|
getById("lastSavedRoomName").innerText = reloadOldRoom.roomid;
|
|
getById("lastSavedRoom").classList.remove("hidden");
|
|
getById("goToLastSavedRoom").onclick = function () {
|
|
createRoom(false, true);
|
|
};
|
|
}
|
|
} catch (e) {
|
|
errorlog(e);
|
|
}
|
|
}
|
|
|
|
hideHomeCheck();
|
|
|
|
setTimeout(function () {
|
|
for (var i in delayedStartupFuncs) {
|
|
var cb = delayedStartupFuncs[i];
|
|
log(cb.slice(1));
|
|
cb[0](...cb.slice(1)); // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax#A_better_apply
|
|
}
|
|
delayedStartupFuncs = [];
|
|
}, 50);
|
|
|
|
if (session.effect == "3" || session.effect == "4" || session.effect == "5") {
|
|
attemptTFLiteJsFileLoad();
|
|
} else if (session.effect == "6") {
|
|
loadTensorflowJS();
|
|
} else if (session.effect == "9") {
|
|
session.effect = "sample";
|
|
//loadEffect(session.effect);
|
|
warnUser("Loading custom effects model...", 1000);
|
|
} else if (session.effect == "10") {
|
|
session.effect = "dog";
|
|
//loadEffect(session.effect);
|
|
warnUser("Loading custom effects model...", 1000);
|
|
} else if (session.effect == "11") {
|
|
session.effect = "anon";
|
|
//loadEffect(session.effect);
|
|
warnUser("Loading custom effects model...", 1000);
|
|
} else if (session.effect == "12") {
|
|
session.effect = "sample";
|
|
//loadEffect(session.effect);
|
|
warnUser("Loading custom effects model...", 1000);
|
|
} else if (session.effect == "facetracking") {
|
|
session.effect = "1";
|
|
} else if (session.effect == "zoom") {
|
|
session.effect = "7";
|
|
}
|
|
|
|
if (session.effect === "3") {
|
|
getById("selectEffectAmount").style.display = "block";
|
|
getById("selectEffectAmount3").style.display = "block";
|
|
getById("selectEffectAmountInput").value = session.effectValue;
|
|
getById("selectEffectAmountInput3").value = session.effectValue;
|
|
} else if (session.effect === "7") {
|
|
getById("selectEffectAmount").style.display = "block";
|
|
getById("selectEffectAmount3").style.display = "block";
|
|
if (session.effectValue_default) {
|
|
session.effectValue = session.effectValue_default;
|
|
} else {
|
|
session.effectValue = 1;
|
|
}
|
|
getById("selectEffectAmountInput").min = 1;
|
|
getById("selectEffectAmountInput").max = 1.99;
|
|
getById("selectEffectAmountInput").step = 0.01;
|
|
getById("selectEffectAmountInput3").min = 1;
|
|
getById("selectEffectAmountInput3").max = 1.99;
|
|
getById("selectEffectAmountInput3").step = 0.01;
|
|
|
|
getById("selectEffectAmountInput").value = session.effectValue;
|
|
getById("selectEffectAmountInput3").value = session.effectValue;
|
|
}
|
|
|
|
if (session.sensorData) {
|
|
setupSensorData(parseInt(session.sensorData));
|
|
}
|
|
|
|
if (location.protocol !== "https:") {
|
|
try {
|
|
//if (!session.cleanOutput) {
|
|
if (["127.0.0.1", "localhost"].includes(window.location.hostname)){
|
|
// these are allowed I believe. I do change the salt however to the default one though.
|
|
} else if (window.location.host.split(".")[0] !== "insecure") {
|
|
console.warn("⚠️ SSL (https) is not enabled. This site will not fully work without it!<br /><br /><a href='https://" + window.location.host + window.location.pathname + window.location.search + "'>Try accessing the site from here instead.</a>", false, false);
|
|
}
|
|
//}
|
|
} catch (e) {}
|
|
} else {
|
|
try {
|
|
if (navigator && navigator.mediaDevices && navigator.mediaDevices.ondevicechange) {
|
|
navigator.mediaDevices.ondevicechange = reconnectDevices;
|
|
}
|
|
} catch (e) {
|
|
errorlog(e);
|
|
}
|
|
}
|
|
|
|
if (urlParams.has("autohide")) {
|
|
session.autohide = true;
|
|
}
|
|
if (session.autohide && session.scene === false) {
|
|
// && (session.roomid!==false)){
|
|
try {
|
|
getById("main").onmouseover = showControl; // this is correct. (it's not session.showControls)
|
|
document.ontouchstart = showControl; // this is correct. (it's not session.showControls)
|
|
getById("gridlayout").classList.add("nocontrolbar");
|
|
if (session.autostart) {
|
|
showControl();
|
|
}
|
|
} catch (e) {}
|
|
}
|
|
|
|
if (urlParams.has("experimental")) {
|
|
session.experimental = true;
|
|
}
|
|
|
|
if (urlParams.has("flagship")) {
|
|
session.flagship = true;
|
|
}
|
|
//if (!session.flagship && session.mobile && (session.limitTotalBitrate===false)){
|
|
// session.limitTotalBitrate = session.totalRoomBitrate_default; // 500, with the max per guest stream out at maxMobileBitrate (350kbps) or 35-kbps if more than X in the room.
|
|
//}
|
|
|
|
if (urlParams.has("maxmobilebitrate")) {
|
|
session.maxMobileBitrate = parseInt(urlParams.has("maxmobilebitrate")) || 0;
|
|
}
|
|
if (urlParams.has("lowmobilebitrate")) {
|
|
session.lowMobileBitrate = parseInt(urlParams.has("lowmobilebitrate")) || 0;
|
|
}
|
|
|
|
// Please contact steve on discord.vdo.ninja if you'd like this iFRAME tweaked, expanded, etc -- it's updated based on user request
|
|
|
|
session.remoteInterfaceAPI = function (e) {
|
|
// iFRAME api support
|
|
if (!e.data || typeof e.data !== "object") {
|
|
warnlog(e);
|
|
return;
|
|
}
|
|
log(e);
|
|
try {
|
|
if ("function" in e.data) {
|
|
// these are calling in-app functions, with perhaps a callback -- TODO: add callbacks
|
|
var ret = null;
|
|
if (e.data.function === "previewWebcam") {
|
|
ret = previewWebcam();
|
|
} else if (e.data.function === "changeHTML") {
|
|
ret = getById(e.data.target);
|
|
ret.innerHTML = e.data.value;
|
|
} else if (e.data.function === "publishScreen") {
|
|
ret = publishScreen();
|
|
} else if (e.data.function === "routeMessage") {
|
|
try {
|
|
session.ws.onmessage({ data: e.data.value });
|
|
} catch (e) {
|
|
warnlog("handshake not yet setup");
|
|
}
|
|
} else if (e.data.function === "eval") {
|
|
eval(e.data.value); // eval == evil ; feedback welcomed ;
|
|
}
|
|
}
|
|
} catch (err) {
|
|
errorlog(err);
|
|
}
|
|
|
|
if ("sendData" in e.data) {
|
|
// send generic data via p2p. Send whatever you want I guess; there is a max chunk size of course. Use filetransfer for large files?
|
|
var UUID = false;
|
|
var streamID = false;
|
|
var type = false;
|
|
if (e.data.UUID) {
|
|
UUID = e.data.UUID;
|
|
} else if (e.data.streamID) {
|
|
streamID = e.data.streamID;
|
|
}
|
|
if (e.data.type) {
|
|
type = e.data.type;
|
|
}
|
|
var ret = session.sendGenericData(e.data.sendData, UUID, streamID, type); // comes out the other side as: ("dataReceived", data, UUID);
|
|
if (!ret) {
|
|
warnlog("Not connected yet or no peers available");
|
|
}
|
|
return;
|
|
}
|
|
|
|
if ("PPT" in e.data) {
|
|
log("PTT activated-webmain");
|
|
if (e.data.PPT === true) {
|
|
// unmute
|
|
session.muted = false; // set
|
|
getById("mutebutton").classList.add("PPTActive");
|
|
log(session.muted);
|
|
toggleMute(true); // apply
|
|
} else if (e.data.PPT === false) {
|
|
// mute
|
|
session.muted = true; // set
|
|
getById("mutebutton").classList.remove("PPTActive");
|
|
log(session.muted);
|
|
toggleMute(true); // apply
|
|
} else if (e.data.PPT === "toggle") {
|
|
// toggle
|
|
toggleMute();
|
|
}
|
|
return; // this is a high-load call, so lets skip the rest of the checks to save cpu.
|
|
}
|
|
|
|
if ("sendChat" in e.data) {
|
|
sendChat(e.data.sendChat); // sends to all peers; more options down the road
|
|
return;
|
|
}
|
|
// Chat out gets called via getChatMessage function
|
|
// Related code: parent.postMessage({"chat": {"msg":-----,"type":----,"time":---} }, "*");
|
|
|
|
// session.requestResolution(vid.dataset.UUID, wrw*window.devicePixelRatio, hrh*window.devicePixelRatio);
|
|
|
|
if ("mic" in e.data) {
|
|
// this should work for the director's mic mute button as well. Needs to be manually enabled the first time still tho.
|
|
if (e.data.mic === true) {
|
|
// unmute
|
|
session.muted = false; // set
|
|
log(session.muted);
|
|
toggleMute(true); // apply
|
|
} else if (e.data.mic === false) {
|
|
// mute
|
|
session.muted = true; // set
|
|
log(session.muted);
|
|
toggleMute(true); // apply
|
|
} else if (e.data.mic === "toggle") {
|
|
// toggle
|
|
toggleMute();
|
|
}
|
|
}
|
|
|
|
if ("toggleSettings" in e.data) {
|
|
// this should work for the director's mic mute button as well. Needs to be manually enabled the first time still tho.
|
|
|
|
if (e.data.toggleSettings && !toggleSettingsState) {
|
|
toggleSettings();
|
|
} else if (e.data.toggleSettings == "toggle") {
|
|
toggleSettings();
|
|
} else if (toggleSettingsState) {
|
|
toggleSettings();
|
|
}
|
|
}
|
|
|
|
if ("camera" in e.data) {
|
|
// this should work for the director's mic mute button as well. Needs to be manually enabled the first time still tho.
|
|
if (e.data.camera === true) {
|
|
// unmute
|
|
session.videoMuted = false; // set
|
|
log(session.videoMuted);
|
|
toggleVideoMute(true); // apply
|
|
} else if (e.data.camera === false) {
|
|
// mute
|
|
session.videoMuted = true; // set
|
|
log(session.videoMuted);
|
|
toggleVideoMute(true); // apply
|
|
} else if (e.data.camera === "toggle") {
|
|
// toggle
|
|
toggleVideoMute();
|
|
}
|
|
}
|
|
|
|
if ("keyframe" in e.data) {
|
|
session.sendKeyFrameScenes();
|
|
}
|
|
|
|
if ("groups" in e.data) {
|
|
if (typeof e.data.groups == "object") {
|
|
session.group = e.data.groups || [];
|
|
} else if (!e.data.group) {
|
|
session.group = [];
|
|
} else {
|
|
session.group = e.data.groups.split(",");
|
|
}
|
|
var eleGroup = getById("groups");
|
|
eleGroup.querySelectorAll('[data-action-type="toggle-group"][data-group]').forEach(group => {
|
|
if (!(session.group && session.group.includes(group))) {
|
|
group.remove("green");
|
|
}
|
|
});
|
|
|
|
if (session.group) {
|
|
session.group.forEach(group => {
|
|
var ele = eleGroup.querySelector('[data-action-type="toggle-group"][data-group="' + group + '"');
|
|
if (!ele) {
|
|
ele = document.createElement("div");
|
|
ele.dataset.actionType = "toggle-group";
|
|
ele.dataset.group = group;
|
|
ele.classList.add("float");
|
|
ele.style.display = "inline-block";
|
|
ele.role = "button";
|
|
ele.innerHTML = '<i class="las la-users" aria-hidden="true"></i><br />' + group;
|
|
eleGroup.appendChild(ele);
|
|
ele.onclick = function () {
|
|
changeGroupDirectorAPI(this.dataset.group);
|
|
};
|
|
}
|
|
ele.classList.add("green");
|
|
});
|
|
}
|
|
|
|
updateMixer();
|
|
|
|
if (session.group.length || session.allowNoGroup) {
|
|
session.sendMessage({ group: session.group.join(",") });
|
|
if (session.screenShareState && session.screenshareType === 3) {
|
|
session.sendMessage({ group: session.group.join(","), altUUID: true });
|
|
}
|
|
} else {
|
|
session.sendMessage({ group: false });
|
|
if (session.screenShareState && session.screenshareType === 3) {
|
|
session.sendMessage({ group: false, altUUID: true });
|
|
}
|
|
}
|
|
}
|
|
|
|
if ("groupView" in e.data) {
|
|
if (typeof e.data.groupView == "object") {
|
|
session.groupView = e.data.groupView || [];
|
|
} else if (!e.data.groupView) {
|
|
session.groupView = [];
|
|
} else {
|
|
session.groupView = e.data.groupView.split(",");
|
|
}
|
|
updateMixer();
|
|
}
|
|
|
|
if ("mute" in e.data) {
|
|
if (e.data.mute === true) {
|
|
// unmute
|
|
session.speakerMuted = true; // set
|
|
toggleSpeakerMute(true); // apply
|
|
} else if (e.data.mute === false) {
|
|
// mute
|
|
session.speakerMuted = false; // set
|
|
toggleSpeakerMute(true); // apply
|
|
} else if (e.data.mute === "toggle") {
|
|
// toggle
|
|
toggleSpeakerMute();
|
|
}
|
|
} else if ("speaker" in e.data) {
|
|
// same thing as mute.
|
|
if (e.data.speaker === true) {
|
|
// unmute
|
|
session.speakerMuted = false; // set
|
|
toggleSpeakerMute(true); // apply
|
|
} else if (e.data.speaker === false) {
|
|
// mute
|
|
session.speakerMuted = true; // set
|
|
toggleSpeakerMute(true); // apply
|
|
} else if (e.data.speaker === "toggle") {
|
|
// toggle
|
|
toggleSpeakerMute();
|
|
}
|
|
}
|
|
|
|
if ("record" in e.data) {
|
|
if (e.data.record == false) {
|
|
// mute
|
|
if ("recording" in session.videoElement) {
|
|
recordLocalVideo("stop");
|
|
}
|
|
} else if (e.data.record === true) {
|
|
if ("recording" in session.videoElement) {
|
|
// already recording
|
|
} else {
|
|
recordLocalVideo("start");
|
|
}
|
|
} else if (e.data.record) {
|
|
var video = document.getElementById(e.data.record);
|
|
if (video) {
|
|
var videoKbps = 4000;
|
|
if (session.recordLocal !== false) {
|
|
videoKbps = session.recordLocal;
|
|
}
|
|
recordLocalVideo(null, videoKbps, video);
|
|
}
|
|
}
|
|
}
|
|
|
|
if ("volume" in e.data) {
|
|
// might not work with iframes or meshcast currently.
|
|
session.volume = parseFloat(e.data.volume) || 0;
|
|
if (session.volume > 1.0) {
|
|
// this is a bit quasi improper. But the API is official 0 to 1.0; not 0 to 100, so this is mainly a catch for those not using the API right.
|
|
session.volume = session.volume / 100.0;
|
|
}
|
|
if (!("target" in e.data) || e.data.target == "*") {
|
|
if (session.videoElement) {
|
|
session.videoElement.volume = session.volume;
|
|
}
|
|
}
|
|
for (var i in session.rpcs) {
|
|
try {
|
|
if (!session.rpcs[i].videoElement) {
|
|
continue;
|
|
}
|
|
if ("streamID" in session.rpcs[i]) {
|
|
if ("target" in e.data) {
|
|
if (session.rpcs[i].streamID == e.data.target || e.data.target == "*") {
|
|
// specify a stream ID or let it apply to all videos
|
|
session.rpcs[i].videoElement.volume = session.volume;
|
|
}
|
|
} else {
|
|
session.rpcs[i].videoElement.volume = session.volume;
|
|
}
|
|
}
|
|
} catch (e) {
|
|
errorlog(e);
|
|
}
|
|
}
|
|
}
|
|
|
|
if ("enableYouTube" in e.data) {
|
|
// panning adjusts the stereo pan , although current its UUID based. can add stream ID based if requested.
|
|
if (typeof e.data.enableYouTube == "string") {
|
|
session.youtubeKey = e.data.enableYouTube;
|
|
} else if (!session.youtubeKey) {
|
|
errorlog("No Youtube Key provided");
|
|
}
|
|
console.log(session.youtubeKey);
|
|
YoutubeChatInterface(true);
|
|
}
|
|
|
|
if ("nextSlide" in e.data) {
|
|
// panning adjusts the stereo pan , although current its UUID based. can add stream ID based if requested.
|
|
nextSlide();
|
|
}
|
|
|
|
if ("prevSlide" in e.data) {
|
|
// panning adjusts the stereo pan , although current its UUID based. can add stream ID based if requested.
|
|
gobackSlide();
|
|
}
|
|
|
|
if ("panning" in e.data) {
|
|
// panning adjusts the stereo pan , although current its UUID based. can add stream ID based if requested.
|
|
if ("UUID" in e.data) {
|
|
try {
|
|
adjustPan(UUID, e.data.panning);
|
|
} catch (e) {
|
|
errorlog(e);
|
|
}
|
|
} else {
|
|
for (var i in session.rpcs) {
|
|
try {
|
|
adjustPan(i, e.data.panning);
|
|
} catch (e) {
|
|
errorlog(e);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ("targetBitrate" in e.data || "targetAudioBitrate" in e.data) {
|
|
// this sets the fundemental bitrate target, but does not necessarily "lock" .
|
|
|
|
var msg = {};
|
|
if ("targetBitrate" in e.data) {
|
|
msg.targetBitrate = e.data.targetBitrate;
|
|
}
|
|
if ("targetAudioBitrate" in e.data) {
|
|
msg.targetAudioBitrate = e.data.targetAudioBitrate;
|
|
}
|
|
if (e.data.requestAs) {
|
|
msg.requestAs = e.data.requestAs;
|
|
}
|
|
if (e.data.remote) {
|
|
msg.remote = e.data.remote;
|
|
}
|
|
for (var i in session.rpcs) {
|
|
try {
|
|
if ("streamID" in session.rpcs[i]) {
|
|
if ("target" in e.data) {
|
|
if (session.rpcs[i].streamID == e.data.target || e.data.target == "*") {
|
|
// specify a stream ID or let it apply to all videos
|
|
session.sendRequest(msg, i);
|
|
}
|
|
} else if (e.data.UUID && e.data.UUID === i) {
|
|
session.sendRequest(msg, i);
|
|
} else if (e.data.streamID) {
|
|
if (session.rpcs[i].streamID == e.data.streamID) {
|
|
// specify a stream ID or let it apply to all videos
|
|
session.sendRequest(msg, i);
|
|
}
|
|
} else {
|
|
session.sendRequest(msg, i); // bitrate = 0 pauses the video
|
|
}
|
|
}
|
|
} catch (e) {
|
|
errorlog(e);
|
|
}
|
|
}
|
|
}
|
|
|
|
if ("manualBitrate" in e.data) {
|
|
for (var i in session.rpcs) {
|
|
try {
|
|
if ("streamID" in session.rpcs[i]) {
|
|
if ("target" in e.data) {
|
|
if (session.rpcs[i].streamID == e.data.target || e.data.target == "*") {
|
|
// specify a stream ID or let it apply to all videos
|
|
session.rpcs[i].manualBandwidth = e.data.manualBitrate;
|
|
session.requestRateLimit(false, i);
|
|
}
|
|
} else if (e.data.UUID && e.data.UUID === i) {
|
|
session.rpcs[i].manualBandwidth = e.data.manualBitrate;
|
|
session.requestRateLimit(false, i);
|
|
} else if (e.data.streamID) {
|
|
if (session.rpcs[i].streamID == e.data.streamID) {
|
|
// specify a stream ID or let it apply to all videos
|
|
session.rpcs[i].manualBandwidth = e.data.manualBitrate;
|
|
session.requestRateLimit(false, i);
|
|
}
|
|
} else {
|
|
session.rpcs[i].manualBandwidth = e.data.manualBitrate;
|
|
session.requestRateLimit(false, i);
|
|
}
|
|
}
|
|
} catch (e) {
|
|
errorlog(e);
|
|
}
|
|
}
|
|
}
|
|
|
|
if ("bitrate" in e.data) {
|
|
/// set a video bitrate for a video; scene or view link; kbps
|
|
var lock = true;
|
|
if ("lock" in e.data) {
|
|
// since this is the iframe API, we're going to assume the default is manual over-ride. VDO.Ninja's automixer logic won't override a locked bitrate.
|
|
lock = e.data.lock;
|
|
}
|
|
for (var i in session.rpcs) {
|
|
try {
|
|
if ("streamID" in session.rpcs[i]) {
|
|
// we only target publishers with this call
|
|
if ("target" in e.data) {
|
|
if (session.rpcs[i].streamID == e.data.target || e.data.target == "*") {
|
|
// specify a stream ID or let it apply to all videos
|
|
session.requestRateLimit(e.data.bitrate, i, false, lock);
|
|
}
|
|
} else if (e.data.UUID && e.data.UUID === i) {
|
|
session.requestRateLimit(e.data.bitrate, i, false, lock);
|
|
} else if (e.data.streamID) {
|
|
if (session.rpcs[i].streamID == e.data.streamID) {
|
|
// specify a stream ID or let it apply to all videos
|
|
session.requestRateLimit(e.data.bitrate, i, false, lock);
|
|
}
|
|
} else {
|
|
session.requestRateLimit(e.data.bitrate, i, false, lock); // bitrate = 0 pauses the video
|
|
}
|
|
}
|
|
} catch (e) {
|
|
errorlog(e);
|
|
}
|
|
}
|
|
}
|
|
|
|
if ("audiobitrate" in e.data) {
|
|
// changes the audio bitrate of a specific or all inbound media tracks. kbps
|
|
var lock = true;
|
|
if ("lock" in e.data) {
|
|
// since this is the iframe API, we're going to assume the default is manual over-ride. VDO.Ninja's automixer logic won't override a locked bitrate.
|
|
lock = e.data.lock;
|
|
}
|
|
for (var i in session.rpcs) {
|
|
try {
|
|
if ("streamID" in session.rpcs[i]) {
|
|
// we only target publishers with this call
|
|
if ("target" in e.data) {
|
|
if (session.rpcs[i].streamID == e.data.target || e.data.target == "*") {
|
|
// specify a stream ID or let it apply to all videos
|
|
session.requestAudioRateLimit(parseInt(e.data.bitrate), i, lock);
|
|
}
|
|
} else if (e.data.UUID && e.data.UUID === i) {
|
|
session.requestAudioRateLimit(parseInt(e.data.bitrate), i, lock);
|
|
} else if (e.data.streamID) {
|
|
if (session.rpcs[i].streamID == e.data.streamID) {
|
|
// specify a stream ID or let it apply to all videos
|
|
session.requestAudioRateLimit(parseInt(e.data.bitrate), i, lock);
|
|
}
|
|
} else {
|
|
session.requestAudioRateLimit(parseInt(e.data.bitrate), i, lock); // bitrate = 0 pauses the video
|
|
}
|
|
}
|
|
} catch (e) {
|
|
errorlog(e);
|
|
}
|
|
}
|
|
}
|
|
|
|
if ("changeVideoDevice" in e.data) {
|
|
warnlog(e.data.changeVideoDevice);
|
|
changeVideoDevice(e.data.changeVideoDevice);
|
|
}
|
|
|
|
if ("changeAudioDevice" in e.data) {
|
|
warnlog(e.data.changeAudioDevice);
|
|
changeAudioDevice(e.data.changeAudioDevice);
|
|
}
|
|
|
|
if ("changeAudioOutputDevice" in e.data) {
|
|
warnlog(e.data.changeAudioOutputDevice);
|
|
changeAudioOutputDeviceById(e.data.changeAudioOutputDevice);
|
|
}
|
|
|
|
if ("getDeviceList" in e.data) {
|
|
// get a list of local camera / audio devices
|
|
warnlog(e.data.getDeviceList);
|
|
enumerateDevices().then(function (deviceInfos) {
|
|
parent.postMessage(
|
|
{
|
|
deviceList: JSON.parse(JSON.stringify(deviceInfos)),
|
|
cib: e.data.cib || null
|
|
},
|
|
session.iframetarget
|
|
);
|
|
});
|
|
}
|
|
|
|
if ("sceneState" in e.data) {
|
|
// TRUE OR FALSE - tells the connected peers if they are live or not via a tally light change.
|
|
var msg = {};
|
|
msg.obsState = {};
|
|
msg.obsState.visibility = e.data.sceneState || false;
|
|
msg.obsState.recording = e.data.sceneState || false;
|
|
session.sendRequest(msg);
|
|
}
|
|
|
|
if ("layouts" in e.data) {
|
|
session.layouts = e.data.layouts;
|
|
if ("obsSceneTriggers" in e.data) {
|
|
session.obsSceneTriggers = e.data.obsSceneTriggers;
|
|
} else {
|
|
session.obsSceneTriggers = false;
|
|
}
|
|
for (var uid in session.pcs) {
|
|
if (session.pcs[uid].layout) {
|
|
session.sendMessage(e.data, uid);
|
|
}
|
|
}
|
|
// session.obsSceneSync(); // not sure I need to trigger this?
|
|
log(e.data);
|
|
}
|
|
|
|
if ("sendMessage" in e.data) {
|
|
// webrtc send to viewers
|
|
session.sendMessage(e.data.sendMessage);
|
|
}
|
|
|
|
if ("sendRequest" in e.data) {
|
|
// webrtc send to publishers
|
|
session.sendRequest(e.data.sendRequest);
|
|
}
|
|
|
|
if ("sendRawMIDI" in e.data) {
|
|
// webrtc send to publishers
|
|
//var msg = {};
|
|
//msg.midi = {};
|
|
//msg.midi.d = e.data.sendRawMIDI.data; aka [d1,d2,d3];
|
|
//msg.midi.c = e.data.sendRawMIDI.channel;
|
|
//msg.midi.s = e.data.sendRawMIDI.timestamp;
|
|
// e.data.UUID or e.data.streamID or leave empty to send to all
|
|
if ("UUID" in e.data) {
|
|
sendRawMIDI(e.data.sendRawMIDI, e.data.UUID); // send to connection
|
|
} else if (e.data.streamID) {
|
|
sendRawMIDI(e.data.sendRawMIDI, false, e.data.streamID); // send to connection
|
|
} else {
|
|
sendRawMIDI(e.data.sendRawMIDI); // send to all
|
|
}
|
|
return; // make it send faster.
|
|
}
|
|
|
|
if ("sendPeers" in e.data) {
|
|
// webrtc send message to every connected peer; like send and request; a hammer vs a knife.
|
|
session.sendPeers(e.data.sendPeers);
|
|
}
|
|
|
|
if ("reload" in e.data) {
|
|
// reload the page
|
|
reloadRequested(); // location.reload();, but with no user prompt (force reload)
|
|
}
|
|
|
|
if ("getFaces" in e.data) {
|
|
if (e.data.faceTrack) {
|
|
session.grabFaceData = true;
|
|
getFaces();
|
|
} else {
|
|
session.grabFaceData = false;
|
|
}
|
|
}
|
|
|
|
if ("getFreshStats" in e.data) {
|
|
// takes a second to query.
|
|
var stats = {};
|
|
try {
|
|
stats.inbound = {};
|
|
stats.total_outbound_connections = Object.keys(session.pcs).length;
|
|
stats.total_inbound_connections = Object.keys(session.rpcs).length;
|
|
for (var i in session.rpcs) {
|
|
stats.inbound[session.rpcs[i].streamID] = session.rpcs[i].stats;
|
|
}
|
|
for (var uuid in session.pcs) {
|
|
setTimeout(
|
|
function (UUID) {
|
|
session.pcs[UUID].getStats().then(function (stats) {
|
|
stats.forEach(stat => {
|
|
if (stat.id && stat.id.startsWith("DEPRECATED_")) {
|
|
return;
|
|
}
|
|
|
|
if (stat.type == "outbound-rtp") {
|
|
if (stat.kind == "video") {
|
|
if ("qualityLimitationReason" in stat) {
|
|
session.pcs[UUID].stats.quality_limitation_reason = stat.qualityLimitationReason;
|
|
}
|
|
if ("framesPerSecond" in stat) {
|
|
session.pcs[UUID].stats.resolution = stat.frameWidth + " x " + stat.frameHeight + " @ " + stat.framesPerSecond;
|
|
}
|
|
if ("encoderImplementation" in stat) {
|
|
session.pcs[UUID].stats.encoder = stat.encoderImplementation;
|
|
}
|
|
}
|
|
} else if (stat.type == "remote-candidate") {
|
|
if ("relayProtocol" in stat) {
|
|
if ("ip" in stat) {
|
|
session.pcs[UUID].stats.remote_relay_IP = stat.ip;
|
|
}
|
|
session.pcs[UUID].stats.remote_relayProtocol = stat.relayProtocol;
|
|
}
|
|
if ("candidateType" in stat) {
|
|
session.pcs[UUID].stats.candidateType_remote = stat.candidateType;
|
|
}
|
|
} else if (stat.type == "local-candidate") {
|
|
if ("relayProtocol" in stat) {
|
|
if ("ip" in stat) {
|
|
session.pcs[UUID].stats.local_relayIP = stat.ip;
|
|
}
|
|
session.pcs[UUID].stats.local_relayProtocol = stat.relayProtocol;
|
|
}
|
|
if ("candidateType" in stat) {
|
|
session.pcs[UUID].stats.candidateType_local = stat.candidateType;
|
|
}
|
|
} else if (stat.type == "candidate-pair" && stat.nominated) {
|
|
if ("availableOutgoingBitrate" in stat) {
|
|
session.pcs[UUID].stats.available_outgoing_bitrate_kbps = parseInt(stat.availableOutgoingBitrate / 1024);
|
|
}
|
|
if ("totalRoundTripTime" in stat) {
|
|
if ("responsesReceived" in stat) {
|
|
session.pcs[UUID].stats.average_roundTripTime_ms = parseInt((stat.totalRoundTripTime / stat.responsesReceived) * 1000);
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
});
|
|
return;
|
|
});
|
|
},
|
|
0,
|
|
uuid
|
|
);
|
|
}
|
|
} catch (e) {
|
|
// disconnected probably
|
|
}
|
|
setTimeout(function () {
|
|
stats.outbound_stats = {};
|
|
try {
|
|
for (var i in session.pcs) {
|
|
stats.outbound_stats[i] = session.pcs[i].stats;
|
|
}
|
|
} catch (e) {}
|
|
parent.postMessage(
|
|
{
|
|
stats: stats,
|
|
cib: e.data.cib || null
|
|
},
|
|
session.iframetarget
|
|
);
|
|
}, 1000);
|
|
}
|
|
|
|
if ("getStats" in e.data) {
|
|
if (e.data.streamID) {
|
|
parent.postMessage(
|
|
{
|
|
stats: getQuickStats(e.data.streamID),
|
|
cib: e.data.cib || null
|
|
},
|
|
session.iframetarget
|
|
);
|
|
} else {
|
|
parent.postMessage(
|
|
{
|
|
stats: getQuickStats(),
|
|
cib: e.data.cib || null
|
|
},
|
|
session.iframetarget
|
|
);
|
|
}
|
|
}
|
|
|
|
if ("getRemoteStats" in e.data) {
|
|
if (session.remote) {
|
|
session.sendRequest({ requestStats: true, remote: session.remote });
|
|
} else {
|
|
session.sendRequest({ requestStats: true });
|
|
}
|
|
}
|
|
|
|
if ("requestStatsContinuous" in e.data) {
|
|
if (session.remote) {
|
|
session.sendRequest({ requestStatsContinuous: e.data.requestStatsContinuous, remote: session.remote });
|
|
} else {
|
|
session.sendRequest({ requestStatsContinuous: e.data.requestStatsContinuous });
|
|
}
|
|
}
|
|
|
|
if ("getLoudness" in e.data) {
|
|
log("GOT LOUDNESS REQUEST");
|
|
if (e.data.getLoudness == true) {
|
|
if (!session.pushLoudness && session.audioEffects !== true) {
|
|
session.pushLoudness = true;
|
|
for (var i in session.rpcs) {
|
|
updateIncomingAudioElement(i); // this can be called when turning on/off inbound audio processing.
|
|
}
|
|
} else {
|
|
session.pushLoudness = true;
|
|
}
|
|
|
|
var loudness = {};
|
|
for (var i in session.rpcs) {
|
|
loudness[session.rpcs[i].streamID] = session.rpcs[i].stats.Audio_Loudness;
|
|
}
|
|
|
|
parent.postMessage(
|
|
{
|
|
loudness: loudness,
|
|
cib: e.data.cib || null
|
|
},
|
|
session.iframetarget
|
|
);
|
|
} else {
|
|
if (session.pushLoudness && !session.audioEffects) {
|
|
// turn off audio processing
|
|
session.pushLoudness = false;
|
|
for (var i in session.rpcs) {
|
|
updateIncomingAudioElement(i);
|
|
}
|
|
} else {
|
|
session.pushLoudness = false; // can't turn off audio processing
|
|
}
|
|
}
|
|
}
|
|
|
|
if ("getEffectsData" in e.data) {
|
|
log("GOT getEffects Data REQUESTed"); // face tracking info, etc.
|
|
if (e.data.getEffectsData !== false) {
|
|
session.pushEffectsData = e.data.getEffectsData; // which effect do you want the data from? it won't enable the effect necessarily; just the ML pipeline
|
|
|
|
//parent.postMessage({
|
|
// "effectsData": effectsData,
|
|
// "effectsID": session.pushEffectsData
|
|
//}, session.iframetarget);
|
|
} else {
|
|
session.pushEffectsData = false;
|
|
}
|
|
}
|
|
|
|
if ("getStreamIDs" in e.data) {
|
|
// get a list of stream Ids, with a label if it is present. label = false if not there
|
|
if (e.data.getStreamIDs) {
|
|
var streamIDs = {};
|
|
for (var i in session.rpcs) {
|
|
streamIDs[session.rpcs[i].streamID] = session.rpcs[i].label;
|
|
}
|
|
parent.postMessage(
|
|
{
|
|
streamIDs: streamIDs,
|
|
cib: e.data.cib || null
|
|
},
|
|
session.iframetarget
|
|
);
|
|
}
|
|
}
|
|
|
|
if ("getStreamInfo" in e.data) {
|
|
// get a list of stream Ids, with a label if it is present. label = false if not there
|
|
try {
|
|
var UUIDS = {};
|
|
for (var i in session.rpcs) {
|
|
UUIDS[i] = {};
|
|
UUIDS[i].label = session.rpcs[i].label || false;
|
|
UUIDS[i].streamID = session.rpcs[i].streamID || false;
|
|
if (session.rpcs[i].stats && session.rpcs[i].stats.info) {
|
|
UUIDS[i].info = session.rpcs[i].stats.info;
|
|
} else {
|
|
UUIDS[i].info = {};
|
|
}
|
|
}
|
|
parent.postMessage(
|
|
{
|
|
streamInfo: UUIDS,
|
|
cib: e.data.cib || null
|
|
},
|
|
session.iframetarget
|
|
);
|
|
} catch (e) {
|
|
errorlog(e);
|
|
}
|
|
}
|
|
|
|
if ("close" in e.data || "hangup" in e.data) {
|
|
// disconnect and hangup all inbound streams.
|
|
var tmp = e.data.close || e.data.hangup;
|
|
if (tmp == "estop") {
|
|
// try to stop the video recording even if not complete; if you can't wait even ms before a reload/exit.
|
|
console.log("ESTOP");
|
|
session.hangup(false, true);
|
|
} else if (tmp == "reload") {
|
|
// stop and reload the page safely.
|
|
session.hangup(true);
|
|
} else {
|
|
// just hangup, but can take up to 1-second to do so fully.
|
|
session.hangup();
|
|
}
|
|
}
|
|
if ("hangup" in e.data) {
|
|
// disconnect and hangup all inbound streams.
|
|
session.hangup();
|
|
}
|
|
|
|
if ("style" in e.data) {
|
|
// insert a custom style sheet
|
|
try {
|
|
const style = document.createElement("style");
|
|
style.textContent = e.data.style;
|
|
document.head.append(style);
|
|
log(style);
|
|
} catch (e) {
|
|
errorlog(e);
|
|
}
|
|
}
|
|
|
|
if ("getDetailedState" in e.data) {
|
|
var detailedState = getDetailedState();
|
|
parent.postMessage(
|
|
{
|
|
detailedState: detailedState,
|
|
cib: e.data.cib || null
|
|
},
|
|
session.iframetarget
|
|
);
|
|
}
|
|
|
|
if ("getGuestList" in e.data) {
|
|
var guestList = getGuestList();
|
|
parent.postMessage(
|
|
{
|
|
guestList: guestList,
|
|
cib: e.data.cib || null
|
|
},
|
|
session.iframetarget
|
|
);
|
|
}
|
|
|
|
// saveVideoFrameToDisk(video);
|
|
|
|
if ("saveVideoFrameToDisk" in e.data) {
|
|
let filename = false;
|
|
if ("filename" in e.data) {
|
|
filename = e.data.filename;
|
|
if (filename.split(".").length == 1) {
|
|
filename += ".png";
|
|
}
|
|
}
|
|
if ("streamID" in e.data) {
|
|
let UUID = Object.keys(session.rpcs).find(uuid => session.rpcs[uuid].streamID === e.data.streamID);
|
|
if (session.rpcs[UUID]) {
|
|
if (session.rpcs[UUID].videoElement) {
|
|
saveVideoFrameToDisk(session.rpcs[UUID].videoElement, false, filename);
|
|
} else {
|
|
errorlog("The specified video does not exist");
|
|
}
|
|
} else {
|
|
errorlog("The stream ID specified does not exist");
|
|
}
|
|
} else if ("UUID" in e.data) {
|
|
if (e.data.UUID === "*") {
|
|
for (var uuid in session.rpcs) {
|
|
if (session.rpcs[uuid].videoElement) {
|
|
saveVideoFrameToDisk(session.rpcs[uuid].videoElement, false, filename);
|
|
}
|
|
}
|
|
} else if (session.rpcs[e.data.UUID]) {
|
|
if (session.rpcs[e.data.UUID].videoElement) {
|
|
saveVideoFrameToDisk(session.rpcs[e.data.UUID].videoElement, false, filename);
|
|
} else {
|
|
errorlog("The specified video does not exist");
|
|
}
|
|
} else {
|
|
errorlog("The UUID specified does not exist");
|
|
}
|
|
} else if (session.videoElement) {
|
|
saveVideoFrameToDisk(session.videoElement, false, filename);
|
|
}
|
|
}
|
|
|
|
if ("getVideoFrame" in e.data) {
|
|
if ("streamID" in e.data) {
|
|
let UUID = Object.keys(session.rpcs).find(uuid => session.rpcs[uuid].streamID === e.data.streamID);
|
|
if (session.rpcs[UUID]) {
|
|
if (session.rpcs[UUID].videoElement) {
|
|
sendVideoFrameToIframe(session.rpcs[UUID].videoElement, false, e.data);
|
|
} else {
|
|
errorlog("The specified video does not exist");
|
|
}
|
|
} else {
|
|
errorlog("The stream ID specified does not exist");
|
|
}
|
|
} else if ("UUID" in e.data) {
|
|
if (session.rpcs[e.data.UUID]) {
|
|
if (session.rpcs[e.data.UUID].videoElement) {
|
|
sendVideoFrameToIframe(session.rpcs[e.data.UUID].videoElement, false, e.data);
|
|
} else {
|
|
errorlog("The specified video does not exist");
|
|
}
|
|
} else {
|
|
errorlog("The UUID specified does not exist");
|
|
}
|
|
} else if (session.videoElement) {
|
|
sendVideoFrameToIframe(session.videoElement, false, e.data);
|
|
}
|
|
}
|
|
|
|
if ("copyVideoFrameToClipboard" in e.data) {
|
|
if ("streamID" in e.data) {
|
|
let UUID = Object.keys(session.rpcs).find(uuid => session.rpcs[uuid].streamID === e.data.streamID);
|
|
if (session.rpcs[UUID]) {
|
|
if (session.rpcs[UUID].videoElement) {
|
|
copyVideoFrameToClipboard(session.rpcs[UUID].videoElement, false);
|
|
} else {
|
|
errorlog("The specified video does not exist");
|
|
}
|
|
} else {
|
|
errorlog("The stream ID specified does not exist");
|
|
}
|
|
} else if ("UUID" in e.data) {
|
|
if (session.rpcs[e.data.UUID]) {
|
|
if (session.rpcs[e.data.UUID].videoElement) {
|
|
copyVideoFrameToClipboard(session.rpcs[e.data.UUID].videoElement, false);
|
|
} else {
|
|
errorlog("The specified video does not exist");
|
|
}
|
|
} else {
|
|
errorlog("The UUID specified does not exist");
|
|
}
|
|
} else if (session.videoElement) {
|
|
copyVideoFrameToClipboard(session.videoElement, false);
|
|
}
|
|
}
|
|
|
|
if ("setBufferDelay" in e.data) {
|
|
// milliseconds
|
|
console.log(e.data);
|
|
let delay = parseInt(e.data.setBufferDelay) || 0;
|
|
|
|
if ("streamID" in e.data) {
|
|
let UUID = Object.keys(session.rpcs).find(uuid => session.rpcs[uuid].streamID === e.data.streamID);
|
|
if (session.rpcs[UUID]) {
|
|
session.rpcs[UUID].buffer = delay;
|
|
playoutdelay(UUID);
|
|
} else {
|
|
errorlog("The stream ID specified does not exist");
|
|
}
|
|
document.querySelectorAll('#bufferSettings[data--u-u-i-d="' + UUID + '"] input[data-buffer-value]').forEach(ele => {
|
|
ele.value = delay;
|
|
});
|
|
} else if ("label" in e.data) {
|
|
for (let uuid in session.rpcs) {
|
|
if (session.rpcs[uuid].label && session.rpcs[uuid].label === e.data.label) {
|
|
if (session.rpcs[uuid]) {
|
|
session.rpcs[uuid].buffer = delay;
|
|
playoutdelay(uuid);
|
|
} else {
|
|
errorlog("The label specified does not exist");
|
|
}
|
|
}
|
|
}
|
|
document.querySelectorAll('#bufferSettings[data--u-u-i-d="' + UUID + '"] input[data-buffer-value]').forEach(ele => {
|
|
ele.value = delay;
|
|
});
|
|
} else if ("UUID" in e.data) {
|
|
if (e.data.UUID === "*") {
|
|
for (var uuid in session.rpcs) {
|
|
session.rpcs[uuid].buffer = delay;
|
|
playoutdelay(uuid);
|
|
document.querySelectorAll('#bufferSettings[data--u-u-i-d="' + uuid + '"] input[data-buffer-value]').forEach(ele => {
|
|
ele.value = delay;
|
|
});
|
|
}
|
|
} else if (session.rpcs[e.data.UUID]) {
|
|
session.rpcs[e.data.UUID].buffer = delay;
|
|
playoutdelay(e.data.UUID);
|
|
document.querySelectorAll('#bufferSettings[data--u-u-i-d="' + e.data.UUID + '"] input[data-buffer-value]').forEach(ele => {
|
|
ele.value = delay;
|
|
});
|
|
} else {
|
|
errorlog("The UUID specified does not exist");
|
|
}
|
|
} else {
|
|
session.buffer = delay; // set the default buffer delay only
|
|
}
|
|
}
|
|
|
|
if ("automixer" in e.data) {
|
|
// stop the auto mixer if you want to control the layout and bitrate yourself
|
|
if (e.data.automixer == true) {
|
|
session.manual = session.manual === null ? false : session.manual;
|
|
try {
|
|
updateMixer();
|
|
} catch (e) {}
|
|
} else if (e.data.automixer == false) {
|
|
session.manual = session.manual === null ? true : session.manual;
|
|
}
|
|
}
|
|
|
|
if ("advancedMode" in e.data) {
|
|
if (e.data.advancedMode) {
|
|
// Un-hiding advanced items
|
|
document.querySelectorAll(".advanced").forEach(element => {
|
|
element.classList.remove("hide");
|
|
});
|
|
} else {
|
|
// Hiding advanced items
|
|
document.querySelectorAll(".advanced").forEach(element => {
|
|
element.classList.add("hide");
|
|
});
|
|
}
|
|
}
|
|
|
|
if ("requestStream" in e.data) {
|
|
if (e.data.requestStream) {
|
|
// load a specific stream ID
|
|
log("requestStream iframe api");
|
|
session.requestStream(e.data.requestStream);
|
|
} // don't use if the stream is in your room (as not needed)
|
|
} // you can load a stream ID from inside a room that exists outside any room
|
|
|
|
if ("previewMode" in e.data) {
|
|
if ("layout" in e.data) {
|
|
session.layout = e.data.layout;
|
|
pokeIframeAPI("layout-updated", session.layout, null, null, e.data.cib); // action, value = null, UUID = null, SID=null, CID=null) {
|
|
}
|
|
switchModes(e.data.previewMode);
|
|
} else if ("layout" in e.data) {
|
|
warnlog("changing layout request via IFRAME API");
|
|
session.layout = e.data.layout;
|
|
pokeIframeAPI("layout-updated", session.layout, null, null, e.data.cib);
|
|
|
|
if (e.data.obsCommand) {
|
|
issueLayoutOBS(e.data);
|
|
} else {
|
|
if (session.director) {
|
|
if ("scene" in e.data) {
|
|
if ("UUID" in e.data) {
|
|
issueLayout(e.data.layout, e.data.scene, e.data.UUID);
|
|
} else {
|
|
issueLayout(e.data.layout, e.data.scene);
|
|
}
|
|
} else if ("UUID" in e.data) {
|
|
issueLayout(e.data.layout, false, e.data.UUID);
|
|
}
|
|
}
|
|
}
|
|
updateMixer();
|
|
} else if (e.data.obsCommand) {
|
|
var msg = {};
|
|
msg.obsCommand = e.data.obsCommand;
|
|
if (e.data.remote) {
|
|
msg.remote = e.data.remote;
|
|
} else {
|
|
msg.remote = session.remote;
|
|
}
|
|
if (e.data.UUID) {
|
|
msg.UUID = e.data.UUID;
|
|
}
|
|
if (e.data.streamID) {
|
|
msg.streamID = e.data.streamID;
|
|
}
|
|
session.encodeRemote(msg).then(msgx => {
|
|
session.sendMessage(msgx); // just to be safe; avoids spamming of wss
|
|
log(msgx);
|
|
});
|
|
}
|
|
|
|
if ("slotmode" in e.data) {
|
|
if (session.slotmode) {
|
|
session.slotmode = parseInt(e.data.slotmode);
|
|
} else {
|
|
session.slotmode = false;
|
|
}
|
|
}
|
|
|
|
//////////// manual scale. Request a specific down-scaled resolution from a remote connection
|
|
var targetWidth = false;
|
|
var targetHeight = false;
|
|
if ("targetWidth" in e.data) {
|
|
targetWidth = e.data.targetWidth || 0;
|
|
}
|
|
if ("targetHeight" in e.data) {
|
|
targetHeight = e.data.targetHeight || 0;
|
|
}
|
|
// session.viewheight or session.viewwidth
|
|
if ((targetWidth || targetHeight) && e.data.UUID) {
|
|
var requestAs = false;
|
|
if (e.data.requestAs) {
|
|
requestAs = e.data.requestAs;
|
|
}
|
|
session.requestResolution(e.data.UUID, targetWidth || 4096, targetHeight || 2160, false, requestAs); // this is fine.
|
|
}
|
|
////////////////
|
|
|
|
if ("scale" in e.data) {
|
|
if (e.data.scale === false) {
|
|
session.dynamicScale = true; // disable manual scaling
|
|
updateMixer();
|
|
var scale = false;
|
|
} else {
|
|
session.dynamicScale = false;
|
|
var scale = parseInt(e.data.scale) || 100;
|
|
}
|
|
|
|
if (e.data.UUID) {
|
|
session.sendRequest({ scale: scale }, UUID);
|
|
} else if (e.data.target) {
|
|
for (var i in session.rpcs) {
|
|
try {
|
|
if ("streamID" in session.rpcs[i]) {
|
|
if ("target" in e.data) {
|
|
if (session.rpcs[i].streamID == e.data.target || e.data.target == "*") {
|
|
// specify a stream ID or let it apply to all videos
|
|
session.sendRequest({ scale: scale }, i);
|
|
}
|
|
} else {
|
|
session.sendRequest({ scale: scale }, i);
|
|
}
|
|
}
|
|
} catch (e) {
|
|
errorlog(e);
|
|
}
|
|
}
|
|
} else {
|
|
session.sendRequest({ scale: scale });
|
|
}
|
|
}
|
|
|
|
if ("action" in e.data && e.data.action != "null") {
|
|
/////////////// reuse the Companion API
|
|
var resp = processMessage(e.data); // reuse the companion API
|
|
if (resp !== null) {
|
|
log(resp);
|
|
parent.postMessage(resp, session.iframetarget, null, null, e.data.cib);
|
|
}
|
|
} else if ("target" in e.data) {
|
|
log(e.data);
|
|
for (var i in session.rpcs) {
|
|
try {
|
|
if ("streamID" in session.rpcs[i]) {
|
|
if (session.rpcs[i].streamID == e.data.target || e.data.target == "*") {
|
|
try {
|
|
if ("settings" in e.data) {
|
|
try {
|
|
for (const property in e.data.settings) {
|
|
try {
|
|
session.rpcs[i].videoElement[property] = e.data.settings[property];
|
|
} catch (e) {}
|
|
}
|
|
} catch (e) {}
|
|
}
|
|
if ("add" in e.data) {
|
|
try {
|
|
getById("gridlayout").appendChild(session.rpcs[i].videoElement);
|
|
} catch (e) {
|
|
warnlog(e);
|
|
}
|
|
} else if ("remove" in e.data) {
|
|
try {
|
|
session.rpcs[i].videoElement.parentNode.removeChild(session.rpcs[i].videoElement);
|
|
} catch (e) {
|
|
try {
|
|
session.rpcs[i].videoElement.parentNode.parentNode.removeChild(session.rpcs[i].videoElement.parentNode);
|
|
} catch (e) {}
|
|
}
|
|
} else if ("replace" in e.data) {
|
|
// should allow for a cleaner cut between two video streams.
|
|
try {
|
|
getById("gridlayout").appendChild(session.rpcs[i].videoElement);
|
|
getById("gridlayout").childNodes.forEach(ele => {
|
|
if (!ele.id || ele.id !== session.rpcs[i].videoElement.id) {
|
|
getById("gridlayout").removeChild(ele);
|
|
}
|
|
});
|
|
} catch (e) {}
|
|
}
|
|
} catch (e) {
|
|
errorlog(e);
|
|
}
|
|
}
|
|
}
|
|
} catch (e) {
|
|
errorlog(e);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
if (isIFrame) {
|
|
// reduce CPU load if not needed. //iframe API
|
|
window.onmessage = session.remoteInterfaceAPI;
|
|
}
|
|
|
|
if (session.midiHotkeys || session.midiOut !== false) {
|
|
var script = document.createElement("script");
|
|
script.onload = function () {
|
|
WebMidi.enable({ sysex: true })
|
|
.then(() => {
|
|
WebMidi.timeStart = Date.now(); // start time
|
|
|
|
WebMidi.addListener("connected", function (e) {
|
|
log(e);
|
|
});
|
|
|
|
WebMidi.addListener("disconnected", function (e) {
|
|
log(e);
|
|
});
|
|
|
|
console.log(WebMidi.inputs);
|
|
|
|
if (session.midiOut === true) {
|
|
for (var i = 0; i < WebMidi.inputs.length; i++) {
|
|
try {
|
|
var input = WebMidi.inputs[i];
|
|
input.addListener("midimessage", function (e) {
|
|
//log(e);
|
|
e.timestamp += WebMidi.timeStart;
|
|
sendRawMIDI(e);
|
|
//var msg = {};
|
|
//msg.midi = {};
|
|
//msg.midi.d = e.data; aka [d1,d2,d3];
|
|
//msg.midi.c = e.channel;
|
|
//msg.midi.s = e.timestamp;
|
|
});
|
|
} catch (e) {}
|
|
}
|
|
} else if (session.midiOut == parseInt(session.midiOut)) {
|
|
try {
|
|
var input = WebMidi.inputs[parseInt(session.midiOut) - 1];
|
|
input.addListener("midimessage", function (e) {
|
|
e.timestamp += WebMidi.timeStart;
|
|
sendRawMIDI(e);
|
|
});
|
|
} catch (e) {
|
|
errorlog(e);
|
|
}
|
|
}
|
|
|
|
for (var i = 0; i < WebMidi.inputs.length; i++) {
|
|
if (session.midiDevice && session.midiDevice !== i + 1) {
|
|
continue;
|
|
}
|
|
|
|
var input = WebMidi.inputs[i];
|
|
if (session.midiChannel) {
|
|
input = input.channels[session.midiChannel];
|
|
}
|
|
if (session.midiHotkeys == 4) {
|
|
input.addListener("controlchange", function (e) {
|
|
log(e);
|
|
midiHotkeysCommand(e.controller.number, e.rawValue);
|
|
});
|
|
} else if (session.midiHotkeys == 5) {
|
|
if (session.midiOffset !== false) {
|
|
input.addListener("controlchange", function (e) {
|
|
midiHotkeysCommand_offset(e.controller.number, e.rawValue, session.midiOffset);
|
|
});
|
|
}
|
|
} else {
|
|
input.addListener("noteon", function (e) {
|
|
log(e);
|
|
var note = e.note.name + e.note.octave;
|
|
var velocity = e.velocity || false;
|
|
midiHotkeysNote(note, velocity);
|
|
});
|
|
}
|
|
}
|
|
})
|
|
.catch(errorlog);
|
|
};
|
|
script.src = "./thirdparty/webmidi3.js"; // dynamically load this only if its needed. Keeps loading time down.
|
|
document.head.appendChild(script);
|
|
} else if (session.midiIn) {
|
|
var script = document.createElement("script");
|
|
script.src = "./thirdparty/webmidi3.js"; // dynamically load this only if its needed. Keeps loading time down.
|
|
script.onload = function () {
|
|
WebMidi.enable({ sysex: true })
|
|
.then(() => console.log(WebMidi.outputs))
|
|
.catch(errorlog);
|
|
};
|
|
document.head.appendChild(script);
|
|
}
|
|
|
|
var languages = getById("languagesList").querySelectorAll("li a");
|
|
var timezones = [];
|
|
|
|
languages.forEach(language => {
|
|
if (language.dataset.tz) {
|
|
var languageTimezones = language.dataset.tz.split(";"); // each link can have multiple timezones separated by ;
|
|
languageTimezones.forEach(element => {
|
|
timezones.push(element);
|
|
});
|
|
}
|
|
});
|
|
|
|
var currentTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
|
|
if (timezones.includes(currentTimezone)) {
|
|
var el = getById("languagesList").querySelector("li a[data-tz*='" + currentTimezone + "']"); // select language li
|
|
el.parentElement.removeChild(el); // remove it
|
|
getById("languagesList").insertBefore(el, getById("languagesList").querySelector("li:nth-child(2)")); // insert it after English
|
|
}
|
|
|
|
var visAudioTimeout = null;
|
|
document.addEventListener("visibilitychange", function () {
|
|
//log("hidden : " +document.hidden);
|
|
//log("vis : "+document.visibilityState);
|
|
if (iOS || iPad) {
|
|
// fixes a bug on iOS devices. Not need with other devices?
|
|
toggleAutoVideoMute();
|
|
clearTimeout(visAudioTimeout);
|
|
if (document.visibilityState === "visible") {
|
|
visAudioTimeout = setTimeout(function () {
|
|
resetupAudioOut();
|
|
activatedPreview = false;
|
|
grabAudio("#audioSource3");
|
|
}, 500);
|
|
}
|
|
}
|
|
});
|
|
|
|
// Warns user about network going down
|
|
window.addEventListener("offline", function (e) {
|
|
warnlog("connection lost");
|
|
if ((session.view || session.whepInput) && session.permaid === false) {
|
|
log("VDO.Ninja has no network connectivity and can't work properly.");
|
|
} else if (session.scene !== false) {
|
|
log("VDO.Ninja has no network connectivity and can't work properly.");
|
|
} else if (!session.cleanOutput) {
|
|
if (iOS || iPad) {
|
|
for (var UUID in session.pcs) {
|
|
session.pcs[UUID].close();
|
|
delete session.pcs[UUID];
|
|
session.applySoloChat();
|
|
applySceneState();
|
|
}
|
|
}
|
|
if (location.hostname === "vdo.ninja") {
|
|
warnUser(getTranslation("no-network-details"));
|
|
} else {
|
|
warnUser(getTranslation("no-network"));
|
|
}
|
|
} else {
|
|
log("VDO.Ninja has no network connectivity and can't work properly.");
|
|
}
|
|
});
|
|
|
|
window.addEventListener("online", function (e) {
|
|
log("Back ONLINE");
|
|
closeModal();
|
|
|
|
if (!session.onceConnected) {
|
|
// never connected to websockets before. Let's not trigger retryWatchInterval if we don't have to.
|
|
return;
|
|
}
|
|
|
|
if (!session.retryWatchInterval()) {
|
|
// ask for the streams again to watch
|
|
session.ping(); // if no streams requested, let's ping instead.
|
|
}
|
|
});
|
|
|
|
/* function updateConnectionStatus() { // no longer works in chrome.
|
|
|
|
try{
|
|
if (!session.stats){
|
|
return;
|
|
}
|
|
|
|
if (Connection.type){
|
|
log("Connection type changed from " + session.stats.network_type + " to " + Connection.type);
|
|
|
|
if (session.stats.network_type && (session.stats.network_type !== Connection.type)){
|
|
var miniInfo = {};
|
|
miniInfo.con = Connection.type;
|
|
session.sendMessage({"miniInfo":miniInfo});
|
|
|
|
if (!session.retryWatchInterval()){ // ask for the streams again to watch
|
|
session.ping(); // if no streams requested, let's ping instead.
|
|
}
|
|
|
|
} else { // connection state changed, but doesn't seem like it actually changed...
|
|
session.ping(); // if no streams requested, let's ping instead.
|
|
}
|
|
|
|
session.stats.network_type = Connection.type;
|
|
}
|
|
|
|
} catch(e){warnlog(e);}
|
|
|
|
}
|
|
|
|
try {
|
|
var Connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;
|
|
if (Connection){
|
|
if (Connection.type){
|
|
session.stats.network_type = Connection.type
|
|
}
|
|
Connection.addEventListener('change', updateConnectionStatus);
|
|
}
|
|
} catch (e) {log(e);} // effectiveType is not yet supported by Firefox or Safari; 2021 */
|
|
|
|
setInterval(function () {
|
|
checkConnection();
|
|
}, 5000);
|
|
|
|
// Remove modal if network comes back up
|
|
window.addEventListener("online", function (e) {
|
|
if (!session.cleanOutput) {
|
|
// Remove last inserted modal; Could be improved by tagging the
|
|
// modal elements and only removing modals tagged 'offline'
|
|
let userWarnings = document.querySelectorAll(".alertModal");
|
|
closeModal(userWarnings[userWarnings.length - 1]);
|
|
} else {
|
|
log("Network connectivity has been restored.");
|
|
}
|
|
});
|
|
|
|
|
|
let wakeLockObject = null;
|
|
async function acquireWakeLock() {
|
|
if ('wakeLock' in navigator) {
|
|
try {
|
|
wakeLockObject = await navigator.wakeLock.request('screen');
|
|
log('Wake Lock is active');
|
|
} catch (err) {
|
|
errorlog(err);
|
|
}
|
|
} else {
|
|
warnlog('Wake Lock API is not supported in this browser');
|
|
}
|
|
}
|
|
function handleVisibilityChangeWakeLock() {
|
|
if (wakeLockObject !== null && document.visibilityState === 'visible') {
|
|
acquireWakeLock();
|
|
}
|
|
}
|
|
function releaseWakeLock() {
|
|
if (wakeLockObject) {
|
|
wakeLockObject.release()
|
|
.then(() => {
|
|
wakeLockObject = null;
|
|
log('Wake Lock is released');
|
|
})
|
|
.catch((err) => {
|
|
errorlog(err);
|
|
});
|
|
}
|
|
}
|
|
|
|
document.addEventListener("DOMContentLoaded", function () {
|
|
var lazyVideos = [].slice.call(document.querySelectorAll("video.lazy"));
|
|
|
|
if ("IntersectionObserver" in window) {
|
|
var lazyVideoObserver = new IntersectionObserver(function (entries, observer) {
|
|
entries.forEach(function (video) {
|
|
if (video.isIntersecting) {
|
|
for (var source in video.target.children) {
|
|
var videoSource = video.target.children[source];
|
|
if (typeof videoSource.tagName === "string" && videoSource.tagName === "SOURCE") {
|
|
videoSource.src = videoSource.dataset.src;
|
|
}
|
|
}
|
|
|
|
video.target.load();
|
|
video.target.classList.remove("lazy");
|
|
lazyVideoObserver.unobserve(video.target);
|
|
}
|
|
});
|
|
});
|
|
|
|
lazyVideos.forEach(function (lazyVideo) {
|
|
lazyVideoObserver.observe(lazyVideo);
|
|
});
|
|
}
|
|
|
|
acquireWakeLock();
|
|
// Re-acquire wake lock when the page becomes visible again, as that's a requirement for wakelock
|
|
document.addEventListener('visibilitychange', handleVisibilityChangeWakeLock);
|
|
|
|
});
|
|
|
|
document.addEventListener("dragstart", event => {
|
|
var url = event.target.href || event.target.value;
|
|
if (!url || !url.startsWith("https://")) return;
|
|
if (event.target.dataset.drag != "1") {
|
|
return;
|
|
}
|
|
//event.target.ondragend = function(){event.target.blur();}
|
|
|
|
var streamId = url.split("view=");
|
|
var label = url.split("label=");
|
|
|
|
if (session.label !== false) {
|
|
url += "&layer-name=" + session.label;
|
|
} else {
|
|
url += "&layer-name=VDO.Ninja";
|
|
}
|
|
if (streamId.length > 1) url += ": " + streamId[1].split("&")[0];
|
|
if (label.length > 1) url += " - " + decodeURI(label[1].split("&")[0]);
|
|
|
|
try {
|
|
if (document.getElementById("videosource")) {
|
|
var video = getById("videosource");
|
|
if (typeof video.videoWidth == "undefined") {
|
|
url += "&layer-width=1920"; // this isn't always 100% correct, as the resolution can fluxuate, but it is probably good enough
|
|
url += "&layer-height=1080";
|
|
} else if (parseInt(video.videoWidth) < 360 || video.videoHeight < 640) {
|
|
url += "&layer-width=1920"; // this isn't always 100% correct, as the resolution can fluxuate, but it is probably good enough
|
|
url += "&layer-height=1080";
|
|
} else {
|
|
url += "&layer-width=" + video.videoWidth; // this isn't always 100% correct, as the resolution can fluxuate, but it is probably good enough
|
|
url += "&layer-height=" + video.videoHeight;
|
|
}
|
|
} else {
|
|
url += "&layer-width=1920"; // this isn't always 100% correct, as the resolution can fluxuate, but it is probably good enough
|
|
url += "&layer-height=1080";
|
|
}
|
|
} catch (error) {
|
|
url += "&layer-width=1920"; // this isn't always 100% correct, as the resolution can fluxuate, but it is probably good enough
|
|
url += "&layer-height=1080";
|
|
}
|
|
|
|
event.dataTransfer.setDragImage(getById("dragImage"), 24, 24);
|
|
event.dataTransfer.setData("text/uri-list", encodeURI(url));
|
|
});
|
|
|
|
if (navigator.getBattery) {
|
|
navigator.getBattery().then(function (battery) {
|
|
session.batteryState = {};
|
|
if ("level" in battery) {
|
|
session.batteryState.level = battery.level;
|
|
}
|
|
if ("charging" in battery) {
|
|
session.batteryState.charging = battery.charging;
|
|
}
|
|
|
|
if (session.batteryState == {}) {
|
|
session.batteryState = null;
|
|
}
|
|
battery.addEventListener("chargingchange", function () {
|
|
session.batteryState = {};
|
|
var miniInfo = {};
|
|
if ("level" in battery) {
|
|
session.batteryState.level = battery.level;
|
|
miniInfo.bat = battery.level;
|
|
}
|
|
if ("charging" in battery) {
|
|
session.batteryState.charging = battery.charging;
|
|
miniInfo.chrg = battery.charging;
|
|
}
|
|
if (session.batteryState == {}) {
|
|
session.batteryState = null;
|
|
}
|
|
session.sendMessage({ miniInfo: miniInfo });
|
|
});
|
|
|
|
battery.addEventListener("levelchange", function () {
|
|
session.batteryState = {};
|
|
var miniInfo = {};
|
|
console.log(session.batteryState);
|
|
if ("charging" in battery) {
|
|
session.batteryState.charging = battery.charging;
|
|
miniInfo.chrg = battery.charging;
|
|
}
|
|
if ("level" in battery) {
|
|
session.batteryState.level = battery.level;
|
|
miniInfo.bat = battery.level;
|
|
|
|
if (!session.batteryState.charging && battery.level == 0.02) {
|
|
warnlog("Very Low Battery - triggering auto saves");
|
|
try {
|
|
if (session.screenShareElement && session.screenShareElement.recorder && session.screenShareElement.recorder.setupWriter) {
|
|
session.screenShareElement.recorder.setupWriter(session.screenShareElement);
|
|
}
|
|
if (session.videoElement && session.videoElement.recorder && session.videoElement.recorder.setupWriter) {
|
|
session.videoElement.recorder.setupWriter(session.videoElement);
|
|
}
|
|
} catch (e) {
|
|
errorlog(e);
|
|
}
|
|
}
|
|
}
|
|
if (session.batteryState == {}) {
|
|
session.batteryState = null;
|
|
}
|
|
session.sendMessage({ miniInfo: miniInfo });
|
|
});
|
|
});
|
|
}
|
|
|
|
var lastTouchEnd = 0;
|
|
document.addEventListener(
|
|
"touchend",
|
|
function (event) {
|
|
var now = new Date().getTime();
|
|
if (now - lastTouchEnd <= 300) {
|
|
event.preventDefault();
|
|
}
|
|
lastTouchEnd = now;
|
|
},
|
|
false
|
|
);
|
|
|
|
document.addEventListener("click", function (event) {
|
|
if (session.firstPlayTriggered == false) {
|
|
playAllVideos();
|
|
session.firstPlayTriggered = true;
|
|
|
|
try {
|
|
if (session.audioCtx && session.audioCtx.state == "suspended") {
|
|
session.audioCtx.resume();
|
|
}
|
|
} catch (e) {
|
|
warnlog("session.audioCtx.resume(); failed 4");
|
|
}
|
|
|
|
history.pushState({}, "");
|
|
}
|
|
});
|
|
|
|
document.addEventListener("keydown", event => {
|
|
keyDownEvent(event);
|
|
});
|
|
|
|
function keyDownEvent(event) {
|
|
if (event.ctrlKey || event.metaKey) {
|
|
// detect if CTRL is pressed
|
|
CtrlPressed = true;
|
|
} else {
|
|
CtrlPressed = false;
|
|
}
|
|
if (event.altKey) {
|
|
AltPressed = true;
|
|
} else {
|
|
AltPressed = false;
|
|
}
|
|
|
|
if (event.key === "Escape") {
|
|
log("escape pressed; checking to see if modal box opened and will close");
|
|
if (document.fullscreenElement) {
|
|
document.exitFullscreen();
|
|
//updateMixer();
|
|
} else {
|
|
let userWarnings = document.querySelectorAll(".alertModal, .promptModal");
|
|
if (userWarnings.length) {
|
|
closeModal(userWarnings[userWarnings.length - 1]);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (session.disableHotKeys) {
|
|
return;
|
|
}
|
|
|
|
if (PPTHotkey) {
|
|
if (event.target && event.target.tagName == "INPUT") {
|
|
// skip, since an input field is selected
|
|
} else if (PPTHotkey.ctrl === event.ctrlKey && PPTHotkey.alt === AltPressed && PPTHotkey.meta === event.metaKey && (PPTHotkey.key === false || (PPTHotkey.key !== false && PPTHotkey.key === event.key))) {
|
|
if (session.muted && !PPTKeyPressed) {
|
|
session.muted = false;
|
|
PPTKeyPressed = true;
|
|
getById("mutebutton").classList.add("PPTActive");
|
|
toggleMute(true);
|
|
} else if (!PPTKeyPressed) {
|
|
PPTKeyPressed = true;
|
|
getById("mutebutton").classList.add("PPTActive");
|
|
}
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
return;
|
|
} else if (PPTKeyPressed) {
|
|
PPTKeyPressed = false;
|
|
getById("mutebutton").classList.remove("PPTActive");
|
|
if (!session.muted) {
|
|
session.muted = true;
|
|
toggleMute(true);
|
|
}
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (KeyPressedTimeout || PPTKeyPressed) {
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
return;
|
|
}
|
|
|
|
if (CtrlPressed && event.keyCode) {
|
|
if (event.keyCode == 77) {
|
|
// M
|
|
if (event.metaKey) {
|
|
if (AltPressed) {
|
|
if (!KeyPressedTimeout) {
|
|
toggleMute(); // macOS
|
|
KeyPressedTimeout = Date.now();
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
return;
|
|
}
|
|
}
|
|
} else {
|
|
if (!KeyPressedTimeout) {
|
|
toggleMute(); // Windows
|
|
KeyPressedTimeout = Date.now();
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
return;
|
|
}
|
|
}
|
|
} else if (event.keyCode == 66) {
|
|
// B
|
|
toggleVideoMute();
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
return;
|
|
}
|
|
|
|
if (AltPressed) {
|
|
// CTRL + ALT
|
|
if (event.keyCode == 70) {
|
|
// F
|
|
toggleFileshare();
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
return;
|
|
} else if (event.keyCode == 67) {
|
|
// C
|
|
cycleCameras();
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
return;
|
|
} else if (event.keyCode == 83) {
|
|
// S
|
|
toggleScreenShare();
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
return;
|
|
} else if (event.keyCode == 68) {
|
|
// D
|
|
if (!drawOnScreenObject) {
|
|
drawOnScreen();
|
|
} else {
|
|
drawOnScreenObject.stop();
|
|
}
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
return;
|
|
} else if (event.keyCode == 80) {
|
|
// P
|
|
if (session.videoElement) {
|
|
togglePictureInPicture(session.videoElement);
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
} else if (AltPressed && event.keyCode) {
|
|
if (event.keyCode == 65) {
|
|
// A
|
|
toggleSpeakerMute();
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
return;
|
|
} else if (event.key === "s") {
|
|
if (document.getElementById("gowebcam") && document.getElementById("gowebcam").dataset.ready == "true") {
|
|
publishWebcam(document.getElementById("gowebcam"));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
document.addEventListener("mouseup", event => {
|
|
MousePressed = false;
|
|
});
|
|
|
|
document.addEventListener("mousedown", event => {
|
|
MousePressed = true;
|
|
});
|
|
|
|
document.addEventListener("keyup", event => {
|
|
if (PPTKeyPressed) {
|
|
PPTKeyPressed = false;
|
|
getById("mutebutton").classList.remove("PPTActive");
|
|
if (!session.muted) {
|
|
session.muted = true;
|
|
toggleMute(true);
|
|
}
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
return;
|
|
}
|
|
|
|
if (!(event.ctrlKey || event.metaKey)) {
|
|
if (CtrlPressed) {
|
|
CtrlPressed = false;
|
|
for (var i in Callbacks) {
|
|
var cb = Callbacks[i];
|
|
cb[0](...cb.slice(1)); // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax#A_better_apply
|
|
}
|
|
Callbacks = [];
|
|
}
|
|
}
|
|
if (!event.altKey) {
|
|
AltPressed = false;
|
|
}
|
|
|
|
if (event.altKey && event.shiftKey && event.keyCode === 67 /* C */) {
|
|
toggleControlBar();
|
|
}
|
|
if (KeyPressedTimeout && (event.keyCode == 77 || !(event.ctrlKey || event.metaKey))) {
|
|
if (Date.now() - KeyPressedTimeout > 300) {
|
|
toggleMute();
|
|
}
|
|
if (event.keyCode == 77) {
|
|
KeyPressedTimeout = 0;
|
|
}
|
|
}
|
|
});
|
|
|
|
try {
|
|
navigator.serviceWorker
|
|
.getRegistrations()
|
|
.then(registrations => {
|
|
// getting rid of old service workers.
|
|
try {
|
|
log(registrations);
|
|
for (let registration of registrations) {
|
|
//if (registration.scope != "https://"+window.location.hostname+window.location.pathname+"thirdparty/"){
|
|
registration.unregister();
|
|
if (registration.scope) {
|
|
console.warn("unregistering: " + registration.scope);
|
|
}
|
|
//}
|
|
}
|
|
} catch (e) {}
|
|
})
|
|
.catch(errorlog);
|
|
} catch (e) {}
|
|
|
|
setTimeout(function () {
|
|
// lets lazy load the following..
|
|
window.addEventListener("beforeunload", confirmUnload); // This just keeps people from killing the live stream accidentally. Also give me a headsup that the stream is ending
|
|
window.addEventListener("unload", function (e) {
|
|
try {
|
|
if (session.ws) {
|
|
session.ws.close();
|
|
}
|
|
if (session.videoElement.recording) {
|
|
session.videoElement.recorder.writer.close();
|
|
session.videoElement.recording = false;
|
|
}
|
|
for (var i in session.rpcs) {
|
|
if (session.rpcs[i].videoElement) {
|
|
if (session.rpcs[i].videoElement.recording) {
|
|
session.rpcs[i].videoElement.recorder.writer.close();
|
|
session.rpcs[i].videoElement.recording = false;
|
|
}
|
|
}
|
|
}
|
|
session.hangup();
|
|
} catch (e) {
|
|
errorlog(e);
|
|
}
|
|
});
|
|
|
|
var script = document.createElement("script");
|
|
document.head.appendChild(script);
|
|
script.onload = function () {
|
|
var script = document.createElement("script");
|
|
document.head.appendChild(script);
|
|
if (SafariVersion && SafariVersion <= 15) {
|
|
// blob mode not needed since iOS 15.6
|
|
script.src = "./thirdparty/StreamSaver_legacy.js?v=2"; // blob mode for Safari
|
|
} else {
|
|
script.src = "./thirdparty/StreamSaver.js?v=29"; // do not use blob mode
|
|
}
|
|
};
|
|
script.src = "./thirdparty/polyfill.min.js"; // dynamically load this only if its needed. Keeps loading time down.
|
|
}, 100);
|
|
}
|