Merge branch 'develop' into message-box

This commit is contained in:
Steve Seguin 2023-01-30 14:57:53 -05:00 committed by GitHub
commit 3c04d4a947
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 2761 additions and 662 deletions

3
.gitignore vendored
View File

@ -1,2 +1,3 @@
node_modules/
package-lock.json
package-lock.json
turn-credentials.php

View File

@ -304,6 +304,8 @@
)[0].style.display = "inline";
logData({"timestart": Date.now()});
var showdetails = document.createElement("button");
showdetails.onclick = function(){
document.getElementById("graphs").classList.toggle('hidden');

View File

@ -41,7 +41,7 @@
height: 100%;
width: 1280px;
max-height: calc(100vh - 95px);
max-height: calc(100vh - 92px);
background-color: #0002;
border-radius: 3px;
@ -52,8 +52,8 @@
}
iframe.aspectRatio{
max-height: min(calc(100vh - 80px), calc(100vw - var(--chat-width)) / var(--aspect-ratio))) !important;
max-width: min(calc((100vh - 80px) * var(--aspect-ratio)), calc(100vw - var(--chat-width))) !important;
max-height: min(calc(100vh - 92px), calc(100vw - 160px - var(--chat-width)) / var(--aspect-ratio)) !important;
max-width: min(calc((100vh - 92px) * var(--aspect-ratio)), calc(100vw - 160px - var(--chat-width))) !important;
height: 720px;
width: 1280px;
}
@ -128,20 +128,20 @@
bottom: 0;
position: fixed;
margin: 10px;
margin-left:0;
align-self: center;
width: var(--chat-width);
max-width: calc(100% - 40px);
width: 400px;
max-width: 100%;
z-index:3;
height: calc(100vh - 40px);
overflow: hidden;
right:0;
background:#0008;
background:#0001;
border: solid 2px #0005;
border-radius: 10px;
padding: 10px;
transition: all .05s ease-in-out;
max-height: 95vh;
}
#chatInput {
display: inline-block;
@ -149,8 +149,8 @@
background-color: #FFFE;
width: 324px;
font-size: 105%;
margin-left: 3px;
max-width: calc(100% - 76px);
margin-left: 7px;
}
#chatSendBar{
display: inline-block;
@ -182,7 +182,30 @@
input[type="checkbox"]:checked {
transform: scale(1.1);
}
.groupview{
position: absolute;
right: 0;
bottom: 0;
width: 24px;
height: 24px;
display: block;
background-color: #000;
opacity: 30%;
border: 2px solid #222;
z-index: 2;
border-radius: 50%;
padding:2px;
}
.groupview::before{
content: '👁️';
}
.view > .groupview {
opacity: 100%;
background-color: #FFF3;
border: 2px solid #DDD;
}
label {
margin: 0 0px 6px 0;
@ -199,7 +222,7 @@
#containerMenu{
position: absolute;
left: 0px;
width: calc(100vw - var(--chat-width));
width: calc(100vw - var(--chat-width) - 40px + var(--chat-filler));
display: flex;
top: 0;
height: 100px;
@ -214,7 +237,7 @@
#vdoninja {
max-width: calc(100vw - 54px - var(--chat-width) + var(--chat-filler));
width: 100vw;
height: calc(100vh - 117px);
height: calc(100vh - 112px);
}
#viewlink {
@ -306,7 +329,7 @@
border-radius: 10px;
box-shadow: 2px 2px 6px #273a4e, -2px -2px 6px #354e6a;
width: 135px;
height: 60px;
height: 50px;
background-color: #0004;
display: inline-block;
margin: 5px 10px 0 10px;
@ -328,7 +351,8 @@
}
::-webkit-scrollbar {
width: 15px;
width: 12px;
height: 12px;
}
::-webkit-scrollbar-track {
@ -372,7 +396,7 @@
top: 92px;
}
.tFadeStart{
top: 107px;
top: 102px;
}
@keyframes tFadeOut {
@ -443,6 +467,9 @@
position: absolute;
}
h3 {
margin-bottom: 6px;
}
.settings {
display: block;
background: #c0e3ff;
@ -731,45 +758,42 @@
background-color:#0000;
}
#containermenu>div:nth-child(1)>div::before {
content: "0";
color: #a4a4a4;
}
#containermenu>div:nth-child(2)>div::before {
content: "1";
color: #a4a4a4;
}
#containermenu>div:nth-child(3)>div::before {
#containermenu>div:nth-child(2)>div::before {
content: "2";
color: #a4a4a4;
}
#containermenu>div:nth-child(4)>div::before {
#containermenu>div:nth-child(3)>div::before {
content: "3";
color: #a4a4a4;
}
#containermenu>div:nth-child(5)>div::before {
#containermenu>div:nth-child(4)>div::before {
content: "4";
color: #a4a4a4;
}
#containermenu>div:nth-child(6)>div::before {
#containermenu>div:nth-child(5)>div::before {
content: "5";
color: #a4a4a4;
}
#containermenu>div:nth-child(7)>div::before {
#containermenu>div:nth-child(6)>div::before {
content: "6";
color: #a4a4a4;
}
#containermenu>div:nth-child(8)>div::before {
#containermenu>div:nth-child(7)>div::before {
content: "7";
color: #a4a4a4;
}
#containermenu>div:nth-child(9)>div::before {
#containermenu>div:nth-child(8)>div::before {
content: "8";
color: #a4a4a4;
}
#containermenu>div:nth-child(10)>div::before {
#containermenu>div:nth-child(9)>div::before {
content: "9";
color: #a4a4a4;
}
#containermenu>div>div {
width: 15px;
height: 15px;
@ -1003,7 +1027,7 @@
if (document.getElementById("chatModule").classList.contains("hidden")){
document.documentElement.style.setProperty('--chat-width', "0px");
document.documentElement.style.setProperty('--chat-filler', "33px");
document.documentElement.style.setProperty('--chat-filler', "40px");
} else {
document.documentElement.style.setProperty('--chat-width', "400px");
@ -1465,6 +1489,7 @@
initialgroups.settings = {};
initialgroups.activeGroups = [];
initialgroups.activeViewGroups = [];
initialgroups.groups = [];
@ -1472,6 +1497,15 @@
if (savedSession){
initialgroups = JSON.parse(savedSession);
if (!("activeViewGroups" in initialgroups)){
initialgroups.activeViewGroups = [];
} else {
initialgroups.activeViewGroups.forEach(group=>{
if (!initialgroups.groups.includes(group)){
initialgroups.groups.push(group);
}
});
}
} else {
var data = "1";
initialgroups.groups.push(data);
@ -1493,6 +1527,8 @@
}
if (urlParams.has("group") || urlParams.has("groups")){
var groups = urlParams.get("group") || urlParams.get("groups");
if (groups){
@ -1506,6 +1542,19 @@
});
}
}
if (urlParams.has("groupview") || urlParams.has("gv")){
var viewgroups = urlParams.get("groupview") || urlParams.get("gv");
if (viewgroups){
viewgroups.split(",").forEach(group=>{
if (!initialgroups.groups.includes(group)){
initialgroups.groups.push(group);
}
initialgroups.activeViewGroups.push(group);
});
}
}
var streamID = "";
if (urlParams.has("push") || urlParams.has("sid")){
streamID = urlParams.get("push") || urlParams.get("sid") || "";
@ -1517,10 +1566,10 @@
label += "=" + (urlParams.get("label") || urlParams.get("l") || "");
}
savedSession = initialgroups;
savedSession = initialgroups;
if (iframe){
iframe.contentWindow.postMessage({ groups: savedSession.activeGroups }, "*");
iframe.contentWindow.postMessage({ groups: savedSession.activeGroups , groupView: savedSession.activeViewGroups }, "*");
}
function exportSession() {
@ -1559,6 +1608,9 @@
#dropButton{
display:none;
}
#groups{
display:none;
}
`;
injectCSS = encodeURIComponent(btoa(injectCSS));
@ -1689,11 +1741,11 @@
function hotkeyCheck(event){
if (event.target && (event.target.tagName == "INPUT")){warnlog("input in focus; return");return;}
var value = parseInt(event.key);
if (value == event.key){
var value = parseInt(event.key)-1;
if (value+1 == event.key){
try {
if (document.querySelector("#containermenu").children[value]){
document.querySelector("#containermenu").children[value].querySelector("group").click();
document.querySelector("#containermenu").children[value].querySelector(".group").click();
document.querySelector("#containermenu").children[value].classList.add("shake");
setTimeout(function(ele){ele.classList.remove("shake");},500,document.querySelector("#containermenu").children[value]);
}
@ -1764,7 +1816,7 @@
}
iframe.onload = function(){
iframe.contentWindow.postMessage({ groups: savedSession.groups }, "*");
iframe.contentWindow.postMessage({ groups: savedSession.activeGroups , groupView: savedSession.activeViewGroups }, "*");
}
iframe.src = iframesrc;
@ -1787,7 +1839,6 @@
eventer(messageEvent, function (e) {
if (e.source != iframe.contentWindow){return} // reject messages send from other iframes
if ("gotChat" in e.data){
messageList.push(e.data.gotChat);
messageList = messageList.slice(-100);
@ -1797,6 +1848,8 @@
updateMessages();
}
console.log(e.data);
if (e.data.action && "action" in e.data){
if (e.data.action === "local-camera-event"){
@ -1874,6 +1927,9 @@
if (savedSession.activeGroups){
iframe.contentWindow.postMessage({"groups":savedSession.activeGroups}, '*');
}
if (savedSession.activeViewGroups){
iframe.contentWindow.postMessage({"groupView":savedSession.activeViewGroups}, '*');
}
}
}
if (("group-set-updated" == e.data.action) && e.data.value){
@ -1881,25 +1937,48 @@
if (e.data.value && (typeof e.data.value == "object")){
savedSession.activeGroups = e.data.value;
} else if (e.data.value){
savedSession.activeGroups = e.data.value.split(",")
} else if (e.data.value){
savedSession.activeGroups = [];
savedSession.activeGroups = e.data.value.split(",") || [];
}
document.querySelectorAll(".pressed>[data-group]").forEach(ele=>{
if (ele){
if (!savedSession.activeGroups.includes(ele.dataset.group)){
ele.parentNode.classList.remove("pressed");
}
document.querySelectorAll("[data-group]").forEach(ele=>{
if (!savedSession.activeGroups.includes(ele.dataset.group)){
ele.parentNode.classList.remove("pressed");
} else {
ele.parentNode.classList.add("pressed");
}
});
savedSession.activeGroups.forEach(group=>{
if (!savedSession.groups.includes(group)){
savedSession.groups.push(group);
drawGroup(group);
}
drawGroup(group);
});
}
if (("group-view-set-updated" == e.data.action) && e.data.value){
savedSession.activeViewGroups = [];
if (e.data.value && (typeof e.data.value == "object")){
savedSession.activeViewGroups = e.data.value;
} else if (e.data.value){
savedSession.activeViewGroups = e.data.value.split(",") || [];
}
document.querySelectorAll("[data-group]").forEach(ele=>{
if (!savedSession.activeViewGroups.includes(ele.dataset.group)){
ele.classList.remove("view");
} else {
ele.classList.add("view");
}
});
savedSession.activeViewGroups.forEach(group=>{
if (!savedSession.groups.includes(group)){
savedSession.groups.push(group);
drawGroup(group);
}
});
}
@ -2004,7 +2083,7 @@
<!-- }); -->
<!-- this.dataset.state = "active"; -->
<!-- addgroup2(this); -->
<!-- addOldElement(JSON.parse(this.parentNode.querySelector("group").group)); -->
<!-- addOldElement(JSON.parse(this.parentNode.querySelector(".group").group)); -->
<!-- } -->
var hotkey = document.createElement("div");
@ -2015,17 +2094,45 @@
groupsize.classList = "groupsize";
var groupview = document.createElement("div");
groupview.classList = "groupview";
groupview.title = "View this group, without needing to publish to it";
groupview.onclick = function(e){
e.preventDefault();
e.stopPropagation();
var index = savedSession.activeViewGroups.indexOf(this.parentNode.dataset.group);
console.log(index);
if (index > -1){
savedSession.activeViewGroups.splice(index, 1);
this.parentNode.classList.remove("view");
} else {
savedSession.activeViewGroups.push(this.parentNode.dataset.group);
this.parentNode.classList.add("view");
}
if (iframe){
iframe.contentWindow.postMessage({"groupView":savedSession.activeViewGroups}, '*');
}
saveSession();
return false;
}
var groupContainer = document.createElement("div");
//groupContainer.appendChild(editButton);
groupContainer.appendChild(group);
groupContainer.appendChild(hotkey);
group.appendChild(groupsize);
group.appendChild(groupview);
groupContainer.classList.add("groupContainer");
if (savedSession.activeGroups.includes(groupID)){
groupContainer.classList.add("pressed");
}
if (savedSession.activeViewGroups.includes(groupID)){
group.classList.add("view");
}
var eles = document.getElementById("containermenu").children;
for (var i =0;i<eles.length;i++){ // replace if existing
var t = eles[i].querySelector(".group");
@ -2074,6 +2181,7 @@
function remoteActivate(event=null, group=null){
console.log("remoteActivate");
if (event.target && group===null){
group = event.target.dataset.group;
event.target.parentNode.classList.toggle("pressed");
@ -2103,6 +2211,7 @@
var groups = document.querySelectorAll(".groupContainer>.group");
savedSession.groups = [];
savedSession.activeGroups = [];
savedSession.activeViewGroups = [];
savedSession.settings = {};
savedSession.version = 1;
@ -2119,11 +2228,18 @@
errorlog(e);
}
}
if (groups[i].classList.contains("view")){
try {
savedSession.activeViewGroups.push(groups[i].dataset.group);
} catch(e){
errorlog(e);
}
}
}
setStorage("savedSession_comms", JSON.stringify(savedSession));
if (iframe){
iframe.contentWindow.postMessage({ groups: savedSession.activeGroups }, "*");
iframe.contentWindow.postMessage({ groups: savedSession.activeGroups , groupView: savedSession.activeViewGroups}, "*");
}
}

View File

@ -54,7 +54,7 @@ function loadIframes(url=false){
var room2 = "https://"+path+"/../?room="+roomname+"&push="+roomname+"_rear&webcam&autostart&vd=back&ad=0&view&cleanoutput&nosettings&transparent";
var iframe = document.createElement("iframe");
iframe.allow = "autoplay;camera;microphone;fullscreen;picture-in-picture;";
iframe.allow = "document-domain;encrypted-media;sync-xhr;usb;web-share;cross-origin-isolated;accelerometer;midi;geolocation;autoplay;camera;microphone;fullscreen;picture-in-picture;display-capture;";
iframe.src = room1;
var iframeContainer = document.createElement("div");
iframeContainer.appendChild(iframe);

146
examples/overlay.html Normal file
View File

@ -0,0 +1,146 @@
<html>
<head><title>overlay + Video</title>
<meta name="viewport" content="width=device-width, initial-scale=0.7, maximum-scale=1.0, user-scalable=yes" />
<meta content="text/html;charset=utf-8" http-equiv="Content-Type" />
<style>
body{
padding:0;
margin:0;
background-color:#003;
width:100%;
height:100%;
color:white;
}
iframe {
width:100vw;
height:100vh;
border:0;
margin:0;
padding:0;
position:fixed;
top:0;
left:0
}
input{
padding:10px;
width:80%;
font-size:1.2em;
z-index: 1000;
}
h1{
color: white;
font-family: verdana;
margin: 10px;
}
</style>
</head>
<body>
<div id="clean">
<h1>Apply an Overlay to VDO.Ninja</h1>
<input placeholder="Enter a VDON URL here" id="viewlink" type="text" />
<input placeholder="Enter the Overlay page here" id="overlay" type="text" />
<button onclick="loadIframes()" style="display:block;padding:10px;margin:10px;">START</button>(Leave blank and press start to see a default sample result)
</div>
<script>
window.addEventListener("orientationchange", function() {
// Announce the new orientation number
// alert(window.orientation);
}, false);
function removeStorage(cname){
localStorage.removeItem(cname);
}
function setStorage(cname, cvalue, hours=9999){ // not actually a cookie
var now = new Date();
var item = {
value: cvalue,
expiry: now.getTime() + (hours * 60 * 60 * 1000),
};
try{
localStorage.setItem(cname, JSON.stringify(item));
}catch(e){errorlog(e);}
}
function getStorage(cname) {
try {
var itemStr = localStorage.getItem(cname);
} catch(e){
errorlog(e);
return;
}
if (!itemStr) {
return "";
}
var item = JSON.parse(itemStr);
var now = new Date();
if (now.getTime() > item.expiry) {
localStorage.removeItem(cname);
return "";
}
return item.value;
}
if (getStorage("overlayChatLink")){
document.getElementById("overlay").value = getStorage("overlayChatLink");
}
if (getStorage("vdoNinjaoverlayURL")){
document.getElementById("viewlink").value = getStorage("vdoNinjaoverlayURL");
}
function loadIframes(url=false){
var roomname = document.getElementById("viewlink").value;
var overlay = document.getElementById("overlay").value;
document.getElementById("clean").parentNode.removeChild(document.getElementById("clean"));
if (!roomname){
var room1 = "../";
} else if (roomname.startsWith("https://")){
var room1 = roomname;
} else {
var room1 = "https://"+roomname;
}
var iframe = document.createElement("iframe");
iframe.allow = "document-domain;encrypted-media;sync-xhr;usb;web-share;cross-origin-isolated;accelerometer;midi;geolocation;autoplay;camera;microphone;fullscreen;picture-in-picture;display-capture;";
iframe.src = room1;
document.body.appendChild(iframe);
if (!overlay){
var room2 = "./test_overlay";
} else if (overlay.startsWith("https://")){
var room2 = overlay;
} else {
var room2 = "https://"+overlay;
}
var iframe = document.createElement("iframe");
iframe.allow = "document-domain;encrypted-media;sync-xhr;usb;web-share;cross-origin-isolated;accelerometer;midi;geolocation;autoplay;camera;microphone;fullscreen;picture-in-picture;display-capture;";
iframe.src = room2;
iframe.style.pointerEvents = "none";
iframe.style.backgroundColor = "#0000";
iframe.style.width = "25vw";
iframe.style.height = "25vh";
iframe.style.overflow = "hidden";
document.body.appendChild(iframe);
if (roomname && overlay){
setStorage("overlayChatLink", room2);
setStorage("vdoNinjaoverlayURL", room1);
}
}
</script>
</body>
</html>

136
examples/powerpoint.html Normal file
View File

@ -0,0 +1,136 @@
<html>
<head><title>PowerPoint Remote Controller</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<meta content="text/html;charset=utf-8" http-equiv="Content-Type" />
<style>
body{
padding:0;
margin:0;
background-color:#003;
width:100%;
height:100%;
color:white;
font-family: tahoma, arial;
}
a {
color:white
}
iframe {
width:100%;
height:100%;
border:0;
margin:0;
padding:0;
display:block;
}
input{
padding:10px;
width:80%;
font-size:1.2em;
z-index: 1000;
}
div{
border:0;
margin:0;
padding:0;
text-align: center;
}
button{
border:0;
margin:0;
padding:0;
width:49%;
height:100%;
}
</style>
</head>
<body>
<div id="container1" style="width:100%;height:89%;display:none;"></div>
<div id="container2" style="width:100%;height:10%;display:none;">
<button onclick="prevSlide()" style='background-color:red'>Previous Slide</button>
<button onclick="nextSlide()" style='background-color:green'>Next Slide</button>
</div>
<div>
<h2>PowerPoint Remote Control interface</h2>
<input placeholder="Enter a Room name" id="viewlink" type="text" onchange="loadIframes()" /><br>
<br>
This app is a custom remote client for VDO.Ninja's PowerPoint remote control feature.
<br><br>
For this to work, the remote VDO.Ninja peer will need <b> &midiin </b> added to their URL, a virtual MIDI loopback device installed, PowerPoint running as an application, and the AutoHotKey script <a href='https://github.com/steveseguin/powerpoint_remote'>found here</a> running, with the MIDI loopback device selected as a MIDI Input device.
</div>
<script>
var iframe;
function nextSlide(){
if (iframe){
iframe.contentWindow.postMessage({"sendRawMIDI":{data:[176, 110, 11]}}, '*');
/// OR AS OF V22.12 YOU CAN DO:
//iframe.contentWindow.postMessage({"nextSlide":true}, '*');
}
}
function prevSlide(){
if (iframe){
iframe.contentWindow.postMessage({"sendRawMIDI":{data:[176, 110, 10]}}, '*');
/// OR AS OF V22.12 YOU CAN DO:
//iframe.contentWindow.postMessage({"prevSlide":true}, '*');
}
}
function customCommand(){ // just an example of what you can do to make a custom action.
if (iframe){
iframe.contentWindow.postMessage({"sendRawMIDI":{data:[176, 110, 12]}}, '*'); // You'll need to have autohotkey be updated to respond to this though.
}
}
var urlEdited = window.location.search.replace(/\?\?/g, "?");
urlEdited = urlEdited.replace(/\?/g, "&");
urlEdited = urlEdited.replace(/\&/, "?");
if (urlEdited !== window.location.search){
warnlog(window.location.search + " changed to " + urlEdited);
window.history.pushState({path: urlEdited.toString()}, '', urlEdited.toString());
}
var urlParams = new URLSearchParams(urlEdited);
var room = false;
if (urlParams.has("room") || urlParams.has("r")){
room = urlParams.get("room") || urlParams.get("r") || false;
}
if (room){
loadIframes(room);
}
function loadIframes(roomname=false){
if (!roomname){
roomname = document.getElementById("viewlink").value;
}
document.getElementById("viewlink").parentNode.parentNode.removeChild(document.getElementById("viewlink").parentNode);
document.getElementById("container1").style.display="inline-block";
document.getElementById("container2").style.display="inline-block";
var path = window.location.host+window.location.pathname.split("/").slice(0,-1).join("/");
var room1 = "https://"+path+"/../?room="+roomname+"&push="+roomname+"_controller&webcam&autostart&minipreview";
iframe = document.createElement("iframe");
iframe.allow = "document-domain;encrypted-media;sync-xhr;usb;web-share;cross-origin-isolated;accelerometer;midi;geolocation;autoplay;camera;microphone;fullscreen;picture-in-picture;display-capture;";
iframe.src = room1;
document.getElementById("container1").appendChild(iframe);
}
</script>
</body>
</html>

View File

@ -0,0 +1,22 @@
<html>
<head>
<style>
body {
background-color:#0000;
object-fit: contain;
width: 100%;
height: 100%;
overflow: hidden;
}
img {
object-fit: contain;
width: 100%;
height: 100%;
overflow: hidden;
}
</style>
</head>
<body>
<img src='../media/vdoNinja_logo_full.png'>
</body>
</html>

View File

@ -34,7 +34,7 @@
</head>
<body>
<h1>STREAMDECK DEMO</h1>
<img src="./media/streamdeck.png" /><br />
<img src="../media/streamdeck.png" /><br />
<input class="button" type="button" id="connectButton" value="Connect" />
<input class="button" type="button" id="disconnectButton" style="display:none" value="Disconnect" />
<div id="connected" style>

2090
lib.js

File diff suppressed because it is too large Load Diff

View File

@ -3330,6 +3330,20 @@ button[data-action-type="messaging-box-send"] {
top: 0;
}
.advanced {
display: var(--advanced-mode);
}
.controlCenterBox{
margin-top:2px;
}
#widget {
position: absolute;
width: 25%;
height: 100%;
right: 0;
top: 0;
}
.pull-right {
float: right;
right: 0;

188
main.js
View File

@ -140,26 +140,28 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
session.sticky = true;
} else if (getStorage("settings") != "") {
var URLGOTO = getStorage("settings");
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");
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);
}
} else {
var cookieSettings = decodeURI(URLGOTO);
setStorage("redirect", "yes", 1);
window.location.replace(cookieSettings);
}
}
@ -499,6 +501,14 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
session.lowBitrateCutoff = parseInt(urlParams.get('bitratecutoff')) || parseInt(urlParams.get('bitcut')) || 300; // low bitrate cut off.
}
if (urlParams.has('lowbitratescene') || urlParams.has('cutscene')) {
session.lowBitrateSceneChange = urlParams.get('lowbitratescene') || urlParams.get('cutscene') || "cutscene"; // low bitrate cut off.
if (session.lowBitrateCutoff===false){
session.lowBitrateCutoff=300;
}
}
if (urlParams.has("statsinterval")){
session.statsInterval = parseInt(urlParams.get("statsinterval")) || 3000; // milliseconds. interval of requesting stats of remote guests
}
@ -562,6 +572,7 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
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");
}
}
@ -610,6 +621,10 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
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;
@ -668,17 +683,14 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
} else if (!Firefox){
getById("chrome_warning_fileshare").classList.remove('hidden');
}
} else if (urlParams.has('website') || urlParams.has('iframe')) {
} 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){
if (session.director){
delayedStartupFuncs.push([shareWebsite, session.website]);
} else {
delayedStartupFuncs.push([session.publishIFrame, session.website]);
}
session.website = decodeURI(session.website);
delayedStartupFuncs.push([session.publishIFrame, session.website]);
}
} else if (urlParams.has('webcam2') || urlParams.has('wc2')) {
session.webcamonly = true;
@ -692,6 +704,17 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
}
}
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;
@ -933,7 +956,12 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
if (urlParams.has('autorecord')) {
session.autorecord=true;
if (session.recordLocal===false){
session.recordLocal = 6000;
let bitautorec = urlParams.get('autorecord');
if (bitautorec!==null){
session.recordLocal = parseInt(bitautorec);
} else {
session.recordLocal = 6000;
}
}
}
if (urlParams.has('autorecordlocal')) {
@ -1769,6 +1797,7 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
} else if (location.hostname === "proxy.vdo.ninja"){
session.proxy=true;
}
if (urlParams.has('nopreview') || urlParams.has('np')) {
log("preview OFF");
@ -1903,6 +1932,10 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
document.querySelector(':root').style.setProperty("--show-codirectors", "none", "important");
}
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('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.
@ -2157,7 +2190,7 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
} //else if (session.audioDevice) {
// session.audioDevice = session.audioDevice.toLowerCase().replace(/[\W]+/g, "_");
//}
if (session.audioDevice == "false") {
session.audioDevice = 0;
} else if (session.audioDevice == "0") {
@ -2188,6 +2221,13 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
getById("audioMenu").style.display = "none";
getById("audioScreenShare1").style.display = "none";
}
if (session.audioDevice!==false){
log("requestAudioStream..()");
try {
await requestAudioStream();
} catch(e){errorlog(e);}
}
}
if (session.videoDevice === 0) {
@ -2354,10 +2394,29 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
}
if (urlParams.has('chunked')) {
session.chunked = parseInt(urlParams.get('chunked')) || 3000;
session.chunked = parseInt(urlParams.get('chunked')) || 2500;
session.alpha = 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(miscTranslations["director-password"], true, true);
if (session.mainDirectorPassword){
session.mainDirectorPassword = session.mainDirectorPassword.trim();
session.mainDirectorPassword = decodeURIComponent(session.mainDirectorPassword);
}
}
// registerToken();
}
if (urlParams.has('debug')){
session.debug=true;
@ -2369,6 +2428,11 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
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;
}
@ -2506,12 +2570,18 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
session.dynamicScale = false; // default true
} else {
if (urlParams.has('viewwidth') || urlParams.has('vw')) {
session.viewwidth = urlParams.get('viewwidth') || urlParams.get('vw') ||false;
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.viewheight = urlParams.get('viewheight') || urlParams.get('vh') || false;
session.dynamicScale = false; // default true
if (session.viewheight){
session.viewheight = parseInt(session.viewheight);
}
}
}
@ -2936,16 +3006,17 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
log(session.maxframeRate);
}
if (urlParams.has('buffer')) { // needs to be before sync
if (urlParams.has('buffer') || urlParams.has('buffer2')) { // needs to be before sync
if ((ChromeVersion > 50) && (ChromeVersion< 78)){
} else {
session.buffer = parseFloat(urlParams.get('buffer')) || 0;
session.buffer = parseFloat(urlParams.get('buffer')) || parseFloat(urlParams.get('buffer2')) || 0;
log("buffer Changed: " + session.buffer);
//session.sync = 0;
//session.audioEffects = true;
}
}
if (urlParams.has('buffer2')){
session.includeRTT = true;
}
}
if (urlParams.has('panning') || urlParams.has('pan')) {
session.panning = urlParams.get('panning') || urlParams.get('pan');
@ -3109,6 +3180,19 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
} 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('animated') || urlParams.has('animate')){
session.animatedMoves = urlParams.get('animated') || urlParams.get('animate');
@ -3293,7 +3377,10 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
session.stunServers = session.stunServers.concat(stun);
}
if (urlParams.has('bundle')){
session.bundlePolicy = urlParams.get('bundle') || "MaxBundle"; // default is browser default.
}
if (urlParams.has('turn')) {
var turnstring = urlParams.get('turn');
@ -3301,11 +3388,14 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
try {
session.ws = false; // prevents connection
var twillioRequest = new XMLHttpRequest();
twillioRequest.onreadystatechange = function() {
if (twillioRequest.status === 200) {
twillioRequest.onload = function() {
if (this.status === 200) {
try{
var res = JSON.parse(twillioRequest.responseText);
} catch(e){return;}
var res = JSON.parse(this.responseText);
} catch(e){
console.error(e);
return;
}
session.configuration = {
iceServers: [{
"username": res["1"],
@ -3686,6 +3776,7 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
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')) {
@ -4280,6 +4371,18 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
}
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
@ -4351,6 +4454,13 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
}
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){
@ -4974,6 +5084,8 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
script.onload = function() {
WebMidi.enable().then(() =>{
WebMidi.timeStart = Date.now(); // start time
WebMidi.addListener("connected", function(e) {
log(e);
});
@ -4989,6 +5101,7 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
try {
var input = WebMidi.inputs[i];
input.addListener("midimessage", function(e) {
e.timestamp += WebMidi.timeStart;
sendRawMIDI(e);
//var msg = {};
//msg.midi = {};
@ -5002,6 +5115,7 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
try{
var input = WebMidi.inputs[parseInt(session.midiOut)-1];
input.addListener("midimessage", function(e) {
e.timestamp += WebMidi.timeStart;
sendRawMIDI(e);
});
} catch(e){errorlog(e);};

View File

@ -53,8 +53,8 @@
}
iframe.aspectRatio{
max-height: min(calc(100vh - 92px), calc(100vw - 160px - var(--chat-width)) / var(--aspect-ratio)) !important;
max-width: min(calc((100vh - 92px) * var(--aspect-ratio)), calc(100vw - 160px - var(--chat-width))) !important;
max-height: min(calc(100vh - 92px), calc(100vw - 160px - var(--chat-width)) / var(--aspect-ratio-widget)) !important;
max-width: min(calc((100vh - 92px) * var(--aspect-ratio-widget)), calc(100vw - 160px - var(--chat-width))) !important;
height: var(--iframe-height) !important;
width: var(--iframe-width) !important;
}
@ -107,7 +107,10 @@
bottom: 45px;
position: absolute;
}
.ui-widget-content {
border-left:0;
border-top:0;
}
#chatBody::-webkit-scrollbar {
width: 0px;
background: transparent; /* make scrollbar transparent */
@ -151,6 +154,22 @@
font-size: 105%;
margin-left: 7px;
}
.part0{
display:inline-block;
cursor:default;
}
.part{
display:inline-block;
cursor:pointer;
}
.part:hover{
text-shadow: 0 0 black;
}
.dimensions{
cursor:default;
background-color: #FFF9;
z-index:1;
}
#chatSendBar{
display: inline-block;
bottom: 0px;
@ -426,6 +445,8 @@
.widget {
background-color: #DDD;
position: absolute;
width:100%;
height:100%;
}
#canvas{
background-color: #000;
@ -524,6 +545,7 @@
z-index: 2;
padding: 6px 0;
width: 28px;
margin: 2px;
height: 28px;
line-height: 0px;
border-radius: 14px;
@ -574,6 +596,11 @@
border-radius: 6px;
cursor:pointer;
}
[title]{
cursor: help;
}
#delete {
background-color: rgb(191 191 191);
text-align: center;
@ -948,6 +975,8 @@
<input type="checkbox" title="A guest is assigned a slot when they join, automatically. If disabled, they must be assigned a slot manually." id="assignSlotToGuest" checked onchange="submitChange2(this)";>Assign a slot to new guests automatically
<h3>Show advanced controls</h3>
<input type="checkbox" title="Shows more director control options" id="advancedMode" onchange="toggleAdvanced(this)";>Show the advanced director control options
<h3>Show director</h3>
<input type="checkbox" checked title="If disabled, the director will not be visible or audible in scene links" id="showDirector" onchange="submitChange4(this)";>The director can be visable and audible in scenes
<h3>🗑 Remove all Layouts</h3>
<button onclick="wipeLayouts();">This will remove all the scene layouts from the current session.</button><br />
@ -1029,7 +1058,7 @@
function getById(id){
var ele = document.getElementById(id);
if (!ele){
console.warn(id+" not found.");
warnlog(id+" not found.");
return document.createElement("span");
} else {
return ele;
@ -1129,6 +1158,8 @@
var messageList = [];
var password = false;
var syncOBS = false;
var showDirector = true;
if (urlParams.has('password') || urlParams.has('pass') || urlParams.has('pw') || urlParams.has('p')) {
password = urlParams.get('password') || urlParams.get('pass') || urlParams.get('pw') || urlParams.get('p');
}
@ -1136,6 +1167,8 @@
var aspectRatio = 16/9.0;
var pixelDensity = 720;
document.documentElement.style.setProperty('--aspect-ratio', aspectRatio);
document.documentElement.style.setProperty('--aspect-ratio-widget', aspectRatio);
var absolutePixel = false;
var advancedMode = false;
@ -1267,7 +1300,7 @@
var time = timeSince(message.time);
var msg = document.createElement("div");
////// KEEP THIS IN /////////
console.log(message.msg); // Display Recieved messages for View-Only clients.
log(message.msg); // Display Recieved messages for View-Only clients.
/////////////////////////////
var label = "";
if (message.label){
@ -1297,7 +1330,7 @@
var time = timeSince(messageList[i].time);
var msg = document.createElement("div");
////// KEEP THIS IN /////////
console.log(messageList[i].msg); // Display Recieved messages for View-Only clients.
log(messageList[i].msg); // Display Recieved messages for View-Only clients.
/////////////////////////////
var label = "";
if (messageList[i].label){
@ -1721,10 +1754,24 @@
getById("syncOBS").checked = true;
}
}
if (savedSession.settings && ("showDirector" in savedSession.settings)){
showDirector = savedSession.settings.showDirector;
if (!showDirector){
getById("showDirector").value = "off";
getById("showDirector").checked = false;
getById("showDirector").removeAttribute('checked');
} else {
getById("showDirector").value = "on";
getById("showDirector").checked = true;
}
}
if (savedSession.settings && ("aspectRatio" in savedSession.settings)){
aspectRatio = savedSession.settings.aspectRatio;
document.documentElement.style.setProperty('--aspect-ratio', aspectRatio);
changeAspectRatio(aspectRatio,false);
document.querySelectorAll(".aspectbutton").forEach(ele=>{
if ((ele.dataset.value == "169") && (aspectRatio == 16/9.0)){
ele.checked = true;
@ -1796,7 +1843,8 @@
var hh = pixelDensity;
var ww = parseInt((pixelDensity*16/9) * (aspectRatio/(16/9)));
document.documentElement.style.setProperty('--aspect-ratio', aspectRatio);
changeAspectRatio(aspectRatio,false);
document.documentElement.style.setProperty('--iframe-width', ww+"px");
document.documentElement.style.setProperty('--iframe-height', hh+"px");
@ -1818,6 +1866,13 @@
savedSession = initialLayouts;
}
if (urlParams.has("hidedirector")){
showDirector = false;
if (savedSession.settings){
savedSession.settings.showDirector = false;
}
}
if (iframe){
iframe.contentWindow.postMessage({ layouts: savedSession.layouts }, "*");
}
@ -1856,6 +1911,20 @@
saveSession();
}
function submitChange4(element){
if (element.checked){
showDirector=true;
} else { // do not assign guests to slots automatically
element.removeAttribute('checked');
showDirector=false
}
saveSession();
if (document.getElementById("vdoninja")){
document.getElementById("vdoninja").src = createIframeURL();
}
}
function toggleAdvanced(element){
if (element.checked){
iframe.contentWindow.postMessage({"advancedMode":true}, '*');
@ -2129,10 +2198,7 @@
var iframe = null;
function loadIframe(){
if (iframe){return;}
iframe = document.createElement("iframe");
function createIframeURL(){
var additional = ""; // guest/scene links also
if (password){
additional = "&password="+password;
@ -2148,27 +2214,51 @@
} else {
additional2+="&slotmode=2";
}
roomname = sanitizeRoomName(roomname);
if (!advancedMode){
additional2+="&novice";
}
if (showDirector){
additional2+="&showdirector";
}
var iframeContainer = document.getElementById("iframeContainer");
var iframesrc = "./index.html?ltb=350&sstype=3&transparent&hideheader&hidetranslate&cleandirector&chatbutton=0&director="+roomname+additional+additional2+"&b64css="+injectCSS;
var params = window.location.search || "";
if (params.startsWith("?")){
params = params.slice(1);
iframesrc = iframesrc + "&" + params
} else {
iframesrc = iframesrc + params
}
return iframesrc
}
function loadIframe(){
if (iframe){return;}
iframe = document.createElement("iframe");
iframe.allow = "autoplay;camera;microphone;fullscreen;picture-in-picture;display-capture;";
iframe.id = "vdoninja";
roomname = sanitizeRoomName(roomname);
if (!roomname){
roomname = generateString(10);
}
var iframesrc = "./index.html?showdirector&ltb=350&transparent&hideheader&hidetranslate&cleandirector&chatbutton=0&director="+roomname+additional+additional2+"&b64css="+injectCSS;
if (roomname!==false){
setStorage("savedRoom", {roomname:roomname,password:password}, 9999);
}
var iframesrc = createIframeURL();
var additional = ""; // guest/scene links also
if (password){
additional = "&password="+password;
}
document.title = "Mixer: "+roomname;
<!-- var button = document.createElement("button"); -->
@ -2194,7 +2284,8 @@
button.onclick = function(){
this.state = !this.state;
this.dataset.state = this.state;
iframe.contentWindow.postMessage({"previewMode":this.state, "layout":currentLayout.layouts, "bitrate":35, "target": "*"}, '*');
iframe.contentWindow.postMessage({"previewMode":this.state, "layout":currentLayout, "bitrate":35, "target": "*"}, '*');
if (this.state){
this.innerHTML = "Director View &#x21bb;";
iframe.classList.add("aspectRatio");
@ -2293,6 +2384,7 @@
}
iframe.src = iframesrc;
var iframeContainer = document.getElementById("iframeContainer");
iframeContainer.appendChild(iframe);
document.getElementById("container").appendChild(iframeContainer);
@ -2320,6 +2412,15 @@
}
if ("action" in e.data){
if (e.data.action === "widget-src"){
if (e.data.value){
widgetSrc = true;
} else {
widgetSrc = false;
}
changeAspectRatio(aspectRatio,false);
}
///var outputWindow = document.createElement("div");
//outputWindow.innerHTML = "event: "+e.data.action+"<br />";
//outputWindow.style.border="1px dotted black";
@ -2342,6 +2443,8 @@
<!-- } -->
<!-- } -->
// view-connection
if (e.data.action === "slot-updated"){
for (var i in guestPositions){
if (guestPositions[i] === e.data.streamID){
@ -2379,6 +2482,35 @@
}
}
if (e.data.action && (e.data.action == "view-connection")){
if (!e.data.value && e.data.streamID){
for (var i in guestPositions){
if (guestPositions[i] === e.data.streamID){
delete guestPositions[i];
}
}
if (updateOnSlotChange){
remoteActivate(false, lastLayoutRaw);
}
}
}
if (e.data.action && (e.data.action == "director-share")){
if (!e.data.value && e.data.streamID){
for (var i in guestPositions){
if (guestPositions[i] === e.data.streamID){
delete guestPositions[i];
}
}
if (updateOnSlotChange){
remoteActivate(false, lastLayoutRaw);
}
}
}
<!-- if ("streamIDs" in e.data){ -->
<!-- streamIDs = []; -->
<!-- for (var key in e.data.streamIDs){ -->
@ -2491,6 +2623,9 @@
}
function addLayout2(item=false){
closeScene();
//document.getElementById("containermenu").classList.add("hidden");
iframe.classList.add("hidden");
document.getElementById("containermenu2").classList.add("hFadeIn");
@ -2505,9 +2640,18 @@
document.getElementById("canvas").classList.remove("hidden");
//if (item.target){
// item = item.target;
//}
try {
var obsSceneName = item.parentNode.querySelector("canvas").obsSceneName;
document.getElementById("canvas").obsSceneName = obsSceneName;
if (!item.target){
var obsSceneName = item.parentNode.querySelector("canvas").obsSceneName;
document.getElementById("canvas").obsSceneName = obsSceneName;
} else {
document.getElementById("canvas").obsSceneName = parseInt(Math.random()*1000000000);
document.getElementById("canvas").sceneName = parseInt(Math.random()*1000000000);
}
} catch(e){
document.getElementById("canvas").obsSceneName = "";
errorlog(e);
@ -2532,6 +2676,7 @@
document.getElementById("containermenu2").classList.add("hFadeOut");
//document.getElementById("containermenu2").classList.add("hidden");
document.getElementById("canvas").classList.add("hidden");
document.getElementById("canvas").innerHTML = "";
document.getElementById("iframeContainer").classList.remove("tFadeIn");
document.getElementById("iframeContainer").classList.add("tFadeout");
@ -2790,10 +2935,8 @@
function pullUp(event){
this.parentNode.zIndex = parseInt(this.parentNode.zIndex || 0) + 1;
this.parentNode.style.opacity = "0.9";
this.parentNode.style.zIndex=this.parentNode.zIndex;
this.parentNode.dimensions.innerHTML = parseInt(this.parentNode.style.width) +"x"+parseInt(this.parentNode.style.height);
this.parentNode.dimensions.innerHTML += " : " + parseInt(this.parentNode.style.left) +"x"+parseInt(this.parentNode.style.top);
this.parentNode.dimensions.innerHTML += " , layer: "+parseInt(this.parentNode.style.zIndex);
this.parentNode.parent.style.zIndex=this.parentNode.zIndex;
this.parentNode.dimensions = updateSize(this.parentNode);
}
function pushDown(event){
@ -2804,10 +2947,110 @@
} else {
this.parentNode.style.opacity = "0.9";
}
this.parentNode.style.zIndex=this.parentNode.zIndex;
this.parentNode.dimensions.innerHTML = parseInt(this.parentNode.style.width) +"x"+parseInt(this.parentNode.style.height);
this.parentNode.dimensions.innerHTML += " : " + parseInt(this.parentNode.style.left) +"x"+parseInt(this.parentNode.style.top);
this.parentNode.dimensions.innerHTML += " , layer: "+parseInt(this.parentNode.style.zIndex);
this.parentNode.parent.style.zIndex=this.parentNode.zIndex;
this.parentNode.dimensions = updateSize(this.parentNode);
}
function updateSize(supercontainer){
var container = supercontainer.container || supercontainer;
supercontainer = container.parent;
if (container.dimensions){
var dimensions = container.dimensions;
} else {
var dimensions = document.createElement("div");
dimensions.className = "dimensions";
container.dimensions = dimensions;
}
dimensions.innerHTML = "";
var part = document.createElement("div");
dimensions.appendChild(part);
part.className = "part";
part.innerHTML = parseInt(supercontainer.style.width);
part.onclick = function(){
var value = prompt("Change the width",this.innerHTML);
if (value!==null){
value=parseInt(value);
}
if (value>=0){
supercontainer.style.width = value+"px";
updateSize(supercontainer);
}
};
var part = document.createElement("div");
dimensions.appendChild(part);
part.className = "part0";
part.innerHTML = "x";
var part = document.createElement("div");
dimensions.appendChild(part);
part.className = "part";
part.innerHTML = parseInt(supercontainer.style.height);
part.onclick = function(){
var value = prompt("Change the height",this.innerHTML);
if (value!==null){
value=parseInt(value);
}
if (value>=0){
supercontainer.style.height = value+"px";
updateSize(supercontainer);
}
};
var part = document.createElement("div");
dimensions.appendChild(part);
part.className = "part0";
part.innerText = ":";
part.style.margin = "0px 5px";
var part = document.createElement("div");
dimensions.appendChild(part);
part.className = "part";
part.innerHTML += parseInt(supercontainer.style.left);
part.onclick = function(){
var value = prompt("Left offset",this.innerHTML);
if (value!==null){
value=parseInt(value);
}
if (value>=0){
supercontainer.style.left = value+"px";
updateSize(supercontainer);
}
};
var part = document.createElement("div");
dimensions.appendChild(part);
part.className = "part0";
part.innerHTML = "x";
var part = document.createElement("div");
dimensions.appendChild(part);
part.className = "part";
part.innerHTML += parseInt(supercontainer.style.top);
part.onclick = function(){
var value = prompt("Top offset",this.innerHTML);
if (value!==null){
value=parseInt(value);
}
if (value>=0){
supercontainer.style.top = value+"px";
updateSize(supercontainer);
}
};
var part = document.createElement("div");
dimensions.appendChild(part);
part.className = "part0";
part.innerHTML += " , layer: "+parseInt(container.zIndex);
dimensions.style = "position:absolute;left:10px;bottom:0;max-width:250px;height:20px;";
return dimensions;
}
function addOldElement(object){
@ -2825,9 +3068,19 @@
var slot = parseInt(object[i].slot) || 0;
var color = colors[slot];
var container = document.createElement("div");
container.className = "widget ui-widget-content draggable resizable";
var containerSuper = document.createElement("div");
document.getElementById("canvas").appendChild(containerSuper);
var container = document.createElement("div");
containerSuper.appendChild(container);
containerSuper.container = container;
container.parent = containerSuper;
container.className = "widget ui-widget-content";
containerSuper.className = "draggable resizable";
container.slot = slot;
if ("cover" in object[i]){
@ -2840,9 +3093,10 @@
container.zIndex = parseInt(object[i].zIndex) || parseInt(object[i].z) || 0;
//container.backgroundColor = object[i].backgroundColor || "#0000";
container.borderThickness = object[i].borderThickness || 0;
container.animated = object[i].animated || 0;
container.animated = parseInt(object[i].animated) || 0;
container.borderColor = object[i].borderColor || "#0000";
container.backgroundMedia = object[i].backgroundMedia || "";
container.iframeSrc = object[i].iframeSrc || "";
container.defaultStreamID = object[i].defaultStreamID || "";
container.margin = object[i].margin || 0;
container.muted = object[i].muted || false;
@ -2856,7 +3110,9 @@
var w = object[i].w*ww/100 || object[i].wp || 0;
var h = object[i].h*hh/100 || object[i].hp || 0;
container.style = "z-index:"+container.zIndex+";left:"+xoffset+"px;top:"+yoffset+"px;width:"+w+"px;height:"+h+"px;background-color:"+color+";";
containerSuper.style = "z-index:"+container.zIndex+";position: absolute;left:"+xoffset+"px;top:"+yoffset+"px;width:"+w+"px;height:"+h+"px;";
container.style = "background-color:"+color+";";
var h3 = document.createElement("h3");
h3.className = "ui-widget-header";
@ -2887,27 +3143,22 @@
button.innerHTML = "Push Back";
button.onclick = pushDown;
container.appendChild(button);
container.dimensions = dimensions;
var dimensions = document.createElement("div");
container.dimensions = dimensions;
dimensions.innerHTML = parseInt(container.style.width) +"x"+parseInt(container.style.height);
dimensions.innerHTML += " : " + parseInt(container.style.left) +"x"+parseInt(container.style.top);
dimensions.innerHTML += " , layer: "+parseInt(container.style.zIndex);
dimensions.style = "position:absolute;left:10px;bottom:0;max-width:250px;height:20px;";
//part.onclick = function(){console.log(this.innerHTML);};
var dimensions = updateSize(container);
container.appendChild(dimensions);
container.ondrag = function(e){
this.dimensions.innerHTML = parseInt(this.style.width) +"x"+parseInt(this.style.height);
this.dimensions.innerHTML += " : " + parseInt(this.style.left) +"x"+parseInt(this.style.top);
this.dimensions.innerHTML += " , layer: "+parseInt(this.style.zIndex);
container.dimensions = dimensions;
containerSuper.ondrag = function(e){
updateSize(this);
}
container.onresize = function(e){
this.dimensions.innerHTML = parseInt(this.style.width) +"x"+parseInt(this.style.height);
this.dimensions.innerHTML += " : " + parseInt(this.style.left) +"x"+parseInt(this.style.top);
this.dimensions.innerHTML += " , layer: "+parseInt(this.style.zIndex);
containerSuper.onresize = function(e){
updateSize(this);
}
document.getElementById("canvas").appendChild(container);
$(function(){
$(".draggable").draggable({ snap: true , grid: [ 10,10 ] });
@ -2938,16 +3189,34 @@
}
}
var color = colors[slot];
var container = document.createElement("div"); // we use the long-form of meta attributes for container elements.
container.className = "widget ui-widget-content draggable resizable";
var containerSuper = document.createElement("div");
document.getElementById("canvas").appendChild(containerSuper);
var container = document.createElement("div");
containerSuper.appendChild(container);
containerSuper.container = container;
container.parent = containerSuper;
container.className = "widget ui-widget-content";
containerSuper.className = "draggable resizable";
container.slot = slot;
container.zIndex = 10;
var yoffset = 20*(slot+1);
var xoffset = 20*(slot+1);
var w = 640;
var h = 360;
containerSuper.style = "z-index:"+container.zIndex+";position: absolute;left:"+xoffset+"px;top:"+yoffset+"px;width:"+w+"px;height:"+h+"px;";
container.style = "background-color:"+color+";";
container.style = "z-Index:10;left:"+xoffset+"px;top:"+yoffset+"px;width:640px;height:360px;background-color:"+color+";";
container.zIndex = 10;
var h3 = document.createElement("h3");
h3.className = "ui-widget-header";
h3.innerHTML = "drag/resize me";
@ -2978,32 +3247,18 @@
button.onclick = pushDown;
container.appendChild(button);
var dimensions = document.createElement("div");
container.dimensions = dimensions;
dimensions.innerHTML = parseInt(container.style.width) +"x"+parseInt(container.style.height);
dimensions.innerHTML += " : " + parseInt(container.style.left) +"x"+parseInt(container.style.top);
dimensions.style = "position:absolute;left:10px;bottom:0;max-width:250px;height:20px;";
dimensions.innerHTML += " , layer: "+parseInt(container.style.zIndex);
var dimensions = updateSize(container);
container.appendChild(dimensions);
container.ondrag = function(e){
this.dimensions.innerHTML = parseInt(this.style.width) +"x"+parseInt(this.style.height);
this.dimensions.innerHTML += " : " + parseInt(this.style.left) +"x"+parseInt(this.style.top);
this.dimensions.innerHTML += " , layer: "+parseInt(this.style.zIndex);
container.dimensions = dimensions;
containerSuper.ondrag = function(e){
updateSize(this);
}
container.onresize = function(e){
this.dimensions.innerHTML = parseInt(this.style.width) +"x"+parseInt(this.style.height);
this.dimensions.innerHTML += " : " + parseInt(this.style.left) +"x"+parseInt(this.style.top);
this.dimensions.innerHTML += " , layer: "+parseInt(this.style.zIndex);
containerSuper.onresize = function(e){
updateSize(this);
}
document.getElementById("canvas").appendChild(container);
container.style.zIndex = "10";
container.zIndex = 10;
$(function(){
$(".draggable").draggable({ snap: true , grid: [ 10,10 ] });
});
@ -3014,27 +3269,30 @@
function combinedLayout(layout){
var combined = {};
for (var i=0;i<layout.length;i++){
if (!layout[i]){continue;}
if (!("slot" in layout[i])){
continue;
}
try {
var stream = guestPositions[parseInt(layout[i].slot)+1]; // slot 1 is index of 0, but slot 0 is considered NULL; I need to stream line this a bit
} catch(e){
errorlog(e);
continue;
var stream = null;
if ("slot" in layout[i]){
try {
stream = guestPositions[parseInt(layout[i].slot)+1]; // slot 1 is index of 0, but slot 0 is considered NULL; I need to stream line this a bit
} catch(e){
errorlog(e);
stream = null;
}
}
if (!stream){
if (layout[i].defaultStreamID){
combined[layout[i].defaultStreamID] = layout[i];
//if (layout[i].defaultStreamID){
// combined[layout[i].defaultStreamID] = layout[i];
//} else
if (combined[""]){
combined[""].push(layout[i]);
} else {
combined[""] = [layout[i]];
}
continue;
} else {
combined[stream] = layout[i];
}
combined[stream] = layout[i];
}
log(combined);
return combined;
}
@ -3084,8 +3342,12 @@
}
var setEle = document.createElement("div");
parent.appendChild(setEle);
setEle.parent = parent;
parent.setting = setEle;
parent.parent.appendChild(setEle);
setEle.className = "settings";
setEle.innerHTML = "";
@ -3094,10 +3356,25 @@
setEle.style.margin = "5px";
setEle.style.padding = "10px";
var br = document.createElement("br");
setEle.appendChild(br);
var label = document.createElement("label");
label.innerHTML = "IFrame (URL)";
label.title = "If no video stream is present, load the specified website here as an IFRAME instead";
setEle.appendChild(label);
var input = document.createElement("input");
input.style.width = "200px";
setEle.appendChild(input);
input.value = parent.iframeSrc || "";
input.onchange = function(){
parent.iframeSrc = this.value;
}
var br = document.createElement("br");
setEle.appendChild(br);
var label = document.createElement("label");
label.innerHTML = "Background Image (URL)";
label.title = "Set a background image for this space";
setEle.appendChild(label);
var input = document.createElement("input");
input.style.width = "200px";
@ -3111,7 +3388,7 @@
setEle.appendChild(br);
var label = document.createElement("label");
label.innerHTML = "Default Stream ID";
label.title = "If the slot is empty, this will be the default stream ID used.";
label.title = "If the specified stream is connected, and both it and this element are unassigned, load that stream here.";
setEle.appendChild(label);
var input = document.createElement("input");
input.style.width = "200px";
@ -3196,6 +3473,7 @@
setEle.appendChild(br);
var label = document.createElement("label");
label.innerHTML = "Media fully cover area?" ;
label.title = "This applies to the background image and video element.";
setEle.appendChild(label);
var checkbox = document.createElement("input");
checkbox.type = "checkbox";
@ -3213,17 +3491,49 @@
setEle.appendChild(br);
var br = document.createElement("br");
setEle.appendChild(br);
var label = document.createElement("label");
label.innerHTML = "Animated transitions";
setEle.appendChild(label);
var input = document.createElement("input");
var checkbox = document.createElement("input");
checkbox.type = "checkbox";
checkbox.linked = input;
input.linked = checkbox;
setEle.appendChild(checkbox);
if (parent.animated===true){
parent.animated = 300;
}
if (parent.animated){
checkbox.checked = true;
} else {
input.disabled = true;
}
checkbox.onchange = function(){
parent.animated = this.checked;
if (this.checked){
this.linked.disabled = null;
delete this.linked.disabled;
parent.animated = this.linked.value || 300;
} else {
this.linked.disabled = true;
parent.animated = 0;
}
}
var label = document.createElement("label");
label.innerHTML = "Speed (ms)";
label.style.marginLeft = "10px";
setEle.appendChild(label);
input.type = "number";
input.style.width = "70px";
setEle.appendChild(input);
input.value = parent.animated || 0;
input.onchange = function(){
parent.animated = this.value;
}
@ -3242,15 +3552,16 @@
function copyJSON(){
var layout = [];
var pos = document.getElementById("canvas").getBoundingClientRect();
var bodyRect = document.body.getBoundingClientRect();
var hh = parseInt(document.getElementById("canvas").style.height);
var ww = parseInt(document.getElementById("canvas").style.width);
var compute = window.getComputedStyle(document.getElementById("canvas"));
var hh = parseInt(compute.height);
var ww = parseInt(compute.width);
var eles = document.querySelectorAll(".widget");
for (var i=0;i<eles.length;i++){
var compute = window.getComputedStyle(eles[i]);
compute = window.getComputedStyle(eles[i].parent);
var ele = {};
if (absolutePixel){
@ -3282,6 +3593,7 @@
ele.animated = eles[i].animated || 0;
ele.borderColor = eles[i].borderColor || "#0000";
ele.backgroundMedia = eles[i].backgroundMedia || "";
ele.iframeSrc = eles[i].iframeSrc || "";
ele.defaultStreamID = eles[i].defaultStreamID || "";
ele.margin = parseInt(eles[i].margin) || 0;
ele.rounded = parseInt(eles[i].rounded) || 0;
@ -3289,7 +3601,7 @@
} catch(e){errorlog(e);}
layout.push(ele);
}
log(layout);
var combined = combinedLayout(layout);
prompt("Layout as URL-encoded JSON. StreamIDs are based on current and default values.", encodeURIComponent(JSON.stringify(combined)));
@ -3316,15 +3628,15 @@
var ele = {};
if (absolutePixel){
ele.wp = parseFloat(eles[i].style.width) || 0;
ele.hp = parseFloat(eles[i].style.height) || 0;
ele.xp = parseFloat(eles[i].style.left) || 0;
ele.yp = parseFloat(eles[i].style.top) || 0;
ele.wp = parseFloat(eles[i].parent.style.width) || 0;
ele.hp = parseFloat(eles[i].parent.style.height) || 0;
ele.xp = parseFloat(eles[i].parent.style.left) || 0;
ele.yp = parseFloat(eles[i].parent.style.top) || 0;
} else {
ele.w = parseFloat(eles[i].style.width)/ww*100 || 0;
ele.h = parseFloat(eles[i].style.height)/hh*100 || 0;
ele.x = parseFloat(eles[i].style.left)/ww*100 || 0;
ele.y = parseFloat(eles[i].style.top)/hh*100 || 0;
ele.w = parseFloat(eles[i].parent.style.width)/ww*100 || 0;
ele.h = parseFloat(eles[i].parent.style.height)/hh*100 || 0;
ele.x = parseFloat(eles[i].parent.style.left)/ww*100 || 0;
ele.y = parseFloat(eles[i].parent.style.top)/hh*100 || 0;
}
//ele.w = parseFloat(eles[i].style.width)/ww*100;
@ -3348,6 +3660,7 @@
ele.animated = eles[i].animated || 0;
ele.borderColor = eles[i].borderColor || "#0000";
ele.backgroundMedia = eles[i].backgroundMedia || "";
ele.iframeSrc = eles[i].iframeSrc || "";
ele.defaultStreamID = eles[i].defaultStreamID || "";
ele.margin = parseInt(eles[i].margin) || 0;
ele.rounded = parseInt(eles[i].rounded) || 0;
@ -3357,7 +3670,7 @@
scene.push(ele);
//scene[sid] = ele;
}
console.log(scene);
log(scene);
if (makenew){
var canvasContainer = drawLayout(scene);
@ -3376,7 +3689,7 @@
} else {
var sceneName = document.getElementById("canvas").sceneName || parseInt(Math.random()*1000000000);
var obsSceneName = document.getElementById("canvas").obsSceneName || "";
console.log("'sceneName: "+sceneName);
log("'sceneName: "+sceneName);
drawLayout(scene, sceneName, obsSceneName);
popupMessage(event, "Scene saved");
}
@ -3413,6 +3726,7 @@
savedSession.settings.aspectRatio = aspectRatio;
savedSession.settings.pixelDensity = pixelDensity;
savedSession.settings.absolutePixel = absolutePixel;
savedSession.settings.showDirector = showDirector;
savedSession.settings.advancedMode = advancedMode;
@ -3436,16 +3750,27 @@
}
log(getStorage("savedSession"));
}
function changeAspectRatio(ar, button){
document.querySelectorAll(".aspectbutton").forEach(ele=>{
if (ele == button){return;}
ele.checked = false;
ele.value = false;
});
aspectRatio = ar;
saveSession();
var widgetSrc = false;
function changeAspectRatio(ar, button=false){
if (button){
document.querySelectorAll(".aspectbutton").forEach(ele=>{
if (ele == button){return;}
ele.checked = false;
ele.value = false;
});
aspectRatio = ar;
saveSession();
}
document.documentElement.style.setProperty('--aspect-ratio', ar);
if (widgetSrc){
document.documentElement.style.setProperty('--aspect-ratio-widget', ar/0.75);
} else {
document.documentElement.style.setProperty('--aspect-ratio-widget', ar);
}
}
function changeAbsolutePosition(value, button){
@ -3471,7 +3796,8 @@
var hh = pixelDensity;
var ww = parseInt((pixelDensity*16/9) * (aspectRatio/(16/9)));
document.documentElement.style.setProperty('--aspect-ratio', aspectRatio);
changeAspectRatio(aspectRatio,false);
document.documentElement.style.setProperty('--iframe-width', ww+"px");
document.documentElement.style.setProperty('--iframe-height', hh+"px");

View File

@ -156,6 +156,25 @@
}
function timeConverter(UNIX_timestamp){
var a = new Date(UNIX_timestamp);
var months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
var year = a.getFullYear();
var month = months[a.getMonth()];
var date = a.getDate();
var hours = a.getHours();
var minutes = a.getMinutes();
var ampm = hours >= 12 ? 'pm' : 'am';
hours = hours % 12;
hours = hours ? hours : 12; // the hour '0' should be '12'
minutes = minutes < 10 ? '0'+minutes : minutes;
var strTime = hours + ':' + minutes + ' ' + ampm;
var time = date + ' ' + month + ' ' + year + ' ' + hours + ':' + minutes + ampm;
return time;
}
function printValues(obj) {
var out = "";
for (var key in obj) {
@ -238,12 +257,16 @@
if (data.packetloss!==null){
PAK += parseFloat(data.packetloss) || 0;
PAKCCC += 1;
}
}
if (data.timestart){
document.getElementById("details").innerHTML += "<br /><b>Test start time:</b> "+timeConverter(data.timestart)+"<br />";
}
if ("resolution" in data){
updateData("resolution", data.resolution);
}
if ("QLR" in data){
if (data.QLR == "none"){
QLR_1 +=1;

View File

@ -0,0 +1,19 @@
<?php
// If using static-auth-secret for your turn server, modify this file as needed; also rename to "turn-credentials.php"
$expiry = 86400;
$username = time() + $expiry;
$secret = '<static-auth-secret>';
$password = base64_encode ( hash_hmac ( 'sha1', $username, $secret, true ) );
$turn_server = "turns:<turn-server>:<https-turn-port>"; // "turns" or "turn", depending on your turn server setup
$stun_server = "stun:<stun-server>:<stun-port>"; // We're assuming our turn server also offers stun; uses the same username/password
$arr = array($username, $password, $turn_server, $stun_server);
// $arr = array($username, $password, $turn_server); // We can use this instead if using Google STUN
echo json_encode($arr);
// sample output: [1674572313,"iTofoKaflP\/pjyJOgUwstTUoT2Q=","turns:<turn-server>:<https-turn-port>","stun:<stun-server>:<stun-port>"]
?>

File diff suppressed because one or more lines are too long