mirror of
https://github.com/eliasstepanik/vdo.ninja.git
synced 2026-01-11 13:48:38 +00:00
minor fixes and a couple new URL options
This commit is contained in:
parent
d30e1a1f35
commit
e5f07b0b18
@ -64,7 +64,7 @@
|
||||
var button = document.createElement("a");
|
||||
button.innerHTML = "Invite "+listOfStreamIDs[i];
|
||||
button.target = "_blank";
|
||||
button.href = "../?room=teststeve123&password=1234&broadcast&transparent&autostart&nmb&nvb&gain=0&webcam&l=stevetest&push="+listOfStreamIDs[i]+"_pov";
|
||||
button.href = "../?room=teststeve123&password=1234&broadcast&transparent&autostart&nmb&nvb&gain=0&webcam&l=stevetest&push="+listOfStreamIDs[i];
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
@ -74,12 +74,12 @@
|
||||
iframe.contentWindow.postMessage({
|
||||
action: "addScene",
|
||||
value: "1",
|
||||
target: listOfStreamIDs[i],
|
||||
target: this.dataset.sid
|
||||
}, '*');
|
||||
iframe.contentWindow.postMessage({
|
||||
action: "mic",
|
||||
value: true,
|
||||
target: listOfStreamIDs[i],
|
||||
target: this.dataset.sid
|
||||
}, '*');
|
||||
|
||||
}; // target can be a stream ID or * for all.
|
||||
@ -126,7 +126,19 @@
|
||||
|
||||
|
||||
<div id="container">
|
||||
|
||||
<button onclick="loadIframe();">Go to Directors Room</button>
|
||||
<br />
|
||||
The password for guests is 1234<br />
|
||||
<br />
|
||||
<br />
|
||||
Custom guest invites and toggles for add/removing from scene=1 are on the bottom.
|
||||
<br />
|
||||
<br />
|
||||
Scene=1 link: <a target="_blank" href="https://vdo.ninja/?scene=1&room=teststeve123&password=1234">https://vdo.ninja/?scene=1&room=teststeve123&password=1234</a>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</body>
|
||||
|
||||
@ -88,6 +88,22 @@
|
||||
page;
|
||||
Picture-in-Picture style</div>
|
||||
</div>
|
||||
<div>
|
||||
<h2><a href='multi.html?rooms=room1xx,room2xx,room3xx'>Multiple rooms</a></h2>
|
||||
<div class="description">how to have multiple director rooms open in a single tab; note the URL's ?rooms=xx,yy command</div>
|
||||
</div>
|
||||
<div>
|
||||
<h2><a href='https://versus.cam'>versus.cam</a></h2>
|
||||
<div class="description">How to use the IFRAME API to transport audio and video to the parent frame in Chrome</div>
|
||||
</div>
|
||||
<div>
|
||||
<h2><a href='addtoscene.html'>add to scene</a></h2>
|
||||
<div class="description">How to use the IFRAME API to add/remove guests to a scene remotely</div>
|
||||
</div>
|
||||
<div>
|
||||
<h2><a href='bigmutebutton.html'>big mute button</a></h2>
|
||||
<div class="description">Mobile-friendly big-button for muting yourself easily</div>
|
||||
</div>
|
||||
<div>
|
||||
<h2><a href='sensors.html'>sensors</a></h2>
|
||||
<div class="media">
|
||||
@ -99,6 +115,12 @@
|
||||
it to canvas.
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h2><a href='sensoroverlay.html'>sensor overlay</a></h2>
|
||||
|
||||
<div class="description">Overlay the incoming speed from remote mobile sensor data onto your video
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h2><a href='../midi.html'>midi</a></h2>
|
||||
<div class="media">
|
||||
|
||||
86
index.html
86
index.html
@ -57,7 +57,7 @@
|
||||
<meta property="twitter:image" content="./media/vdoNinja_logo_full.png" />
|
||||
<meta name="msapplication-TileColor" content="#da532c" />
|
||||
<meta name="theme-color" content="#ffffff" />
|
||||
<link rel="stylesheet" href="./main.css?ver=174" />
|
||||
<link rel="stylesheet" href="./main.css?ver=176" />
|
||||
<script type="text/javascript" crossorigin="anonymous" src="./thirdparty/adapter.min.js"></script>
|
||||
<style id="lightbox-animations" type="text/css"></style>
|
||||
<!-- <link rel="manifest" href="manifest.json" /> -->
|
||||
@ -82,7 +82,7 @@
|
||||
<link itemprop="url" href="./media/vdoNinja_logo_full.png" />
|
||||
</span>
|
||||
<script type="text/javascript" crossorigin="anonymous" src="./thirdparty/CodecsHandler.js?ver=37"></script>
|
||||
<script type="text/javascript" crossorigin="anonymous" src="./webrtc.js?ver=495"></script>
|
||||
<script type="text/javascript" crossorigin="anonymous" src="./webrtc.js?ver=503"></script>
|
||||
<input id="zoomSlider" type="range" style="display: none;" />
|
||||
<span id="electronDragZone" style="pointer-events: none; z-index:-10; position:absolute;top:0;left:0;width:100%;height:2%;-webkit-app-region: drag;min-height:20px;"></span>
|
||||
<div id="header">
|
||||
@ -159,13 +159,13 @@
|
||||
<div id="mutevideobutton" onmousedown="event.preventDefault(); event.stopPropagation();" title="Disable the Camera" alt="Disable the Camera" onclick="toggleVideoMute()" tabindex="19" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="hidden float" style="cursor: pointer;">
|
||||
<i id="mutevideotoggle" onmousedown="event.preventDefault(); event.stopPropagation();" class="toggleSize las la-video my-float"></i>
|
||||
</div>
|
||||
<div id="screensharebutton" onmousedown="event.preventDefault(); event.stopPropagation();" title="Share a Screen with others" alt="Share a Screen with others" onclick="screenshareTypeDecider(1)" tabindex="20" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="float hidden" style="cursor: pointer;">
|
||||
<div id="screensharebutton" onmousedown="event.preventDefault(); event.stopPropagation();" title="Share a Screen with others" alt="Share a Screen with others" onclick="screenshareTypeDecider(1)" tabindex="20" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="float hidden task" data-menu="context-menu-screen-share" style="cursor: pointer;">
|
||||
<i id="screensharetoggle" onmousedown="event.preventDefault(); event.stopPropagation();" class="toggleSize las la-desktop my-float"></i>
|
||||
</div>
|
||||
<div id="screenshare2button" onmousedown="event.preventDefault(); event.stopPropagation();" title="Create a Secondary Stream" alt="Create a Secondary Stream" onclick="screenshareTypeDecider(2)" tabindex="20" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="float hidden" style="cursor: pointer;">
|
||||
<div id="screenshare2button" onmousedown="event.preventDefault(); event.stopPropagation();" title="Create a Secondary Stream" alt="Create a Secondary Stream" onclick="screenshareTypeDecider(2)" tabindex="20" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="float hidden task" data-menu="context-menu-screen-share" style="cursor: pointer;">
|
||||
<i id="screenshare2toggle" onmousedown="event.preventDefault(); event.stopPropagation();" class="toggleSize las la-tv my-float"></i>
|
||||
</div>
|
||||
<div id="screenshare3button" onmousedown="event.preventDefault(); event.stopPropagation();" title="Create a Third Stream" alt="Create a Third Stream" onclick="screenshareTypeDecider(3)" tabindex="20" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="float hidden" style="cursor: pointer;">
|
||||
<div id="screenshare3button" onmousedown="event.preventDefault(); event.stopPropagation();" title="Create a Third Stream" alt="Create a Third Stream" onclick="screenshareTypeDecider(3)" tabindex="20" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="float hidden task" data-menu="context-menu-screen-share" style="cursor: pointer;">
|
||||
<i id="screenshare3toggle" onmousedown="event.preventDefault(); event.stopPropagation();" class="toggleSize las la-tv my-float"></i>
|
||||
</div>
|
||||
<div id="websitesharebutton" onmousedown="event.preventDefault(); event.stopPropagation();" title="Share a website with your guests (IFRAME)" alt="Share a website with your guests (IFRAME)" onclick="shareWebsite(false, event)" tabindex="21" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="float hidden" style="cursor: pointer;">
|
||||
@ -962,7 +962,7 @@
|
||||
<label class="switch" title="Disables Echo Cancellation and improves audio quality">
|
||||
<input type="checkbox" data-param="&s" onchange="updateLink(1,this);">
|
||||
<span class="slider"></span>
|
||||
</label><font class="tooltip" style='cursor: help;position:relative;bottom:2px;font-family:"Noto Color Emoji", "Apple Color Emoji", "Segoe UI Emoji", Times, Symbola, Aegyptus, Code2000, Code2001, Code2002, Musica, serif, LastResort;'>⚠<span class="tooltiptext" style="width: 16em;">This can cause guests to be too quiet or cause feedback issues</span></font> <span data-translate="pro-audio-mode">Pro-audio mode</span>
|
||||
</label><font class="tooltip" style='cursor: help;position:relative;bottom:2px;font-family:"Noto Color Emoji", "Apple Color Emoji", "Segoe UI Emoji", Times, Symbola, Aegyptus, Code2000, Code2001, Code2002, Musica, serif, LastResort;'>⚠<span class="tooltiptext" style="width: 16em;">This can cause guests to be too quiet or have feedback/echo issues</span></font> <span data-translate="pro-audio-mode">Pro-audio mode</span>
|
||||
<Br />
|
||||
<label class="switch" title="Audio-only sources are visually hidden from scenes">
|
||||
<input type="checkbox" data-param="&st" onchange="updateLink(1,this);">
|
||||
@ -1015,7 +1015,7 @@
|
||||
<input type="checkbox" data-param="&q" onchange="updateLink(1,this);">
|
||||
<span class="slider"></span>
|
||||
</label>
|
||||
<font class="tooltip" style='cursor: help;position:relative;bottom:2px;font-family:"Noto Color Emoji", "Apple Color Emoji", "Segoe UI Emoji", Times, Symbola, Aegyptus, Code2000, Code2001, Code2002, Musica, serif, LastResort;'>⚠<span class="tooltiptext">This can cause video playback to lag</span></font> 1080p60 Video if Available
|
||||
<font class="tooltip" style='cursor: help;position:relative;bottom:2px;font-family:"Noto Color Emoji", "Apple Color Emoji", "Segoe UI Emoji", Times, Symbola, Aegyptus, Code2000, Code2001, Code2002, Musica, serif, LastResort;'>⚠<span class="tooltiptext">This can cause video playback to lag</span></font><span data-translate="1080p60-if-available">1080p60 Video if Available</span>
|
||||
<Br />
|
||||
<label class="switch" title="The default microphone will be pre-selected for the guest">
|
||||
<input type="checkbox" data-param="&ad" onchange="updateLink(1,this);">
|
||||
@ -1175,29 +1175,27 @@
|
||||
<div style="display:inline-block;margin-top: 12px; position: relative;">
|
||||
|
||||
<label class="switch">
|
||||
<input type="checkbox" data-param="&st" onchange="updateLink(3,this);">
|
||||
<input type="checkbox" data-param="&st" onchange="updateLink(3,this, true);">
|
||||
<span class="slider"></span>
|
||||
</label>
|
||||
<span data-translate="hide-audio-only-sources">Hide audio-only sources</span>
|
||||
<br />
|
||||
|
||||
<label class="switch">
|
||||
<input type="checkbox" data-param="&s" onchange="updateLink(3,this);">
|
||||
<input type="checkbox" data-param="&s" onchange="updateLink(3,this, true);">
|
||||
<span class="slider"></span>
|
||||
</label><font class="tooltip" style='cursor: help;position:relative;bottom:2px;font-family:"Noto Color Emoji", "Apple Color Emoji", "Segoe UI Emoji", Times, Symbola, Aegyptus, Code2000, Code2001, Code2002, Musica, serif, LastResort;'>⚠<span class="tooltiptext" style="width: 10em;">This can cause audio clicking issues</span></font>
|
||||
<span data-translate="pro-audio-mode">Pro-audio mode</span>
|
||||
<br />
|
||||
|
||||
<label class="switch">
|
||||
<input type="checkbox" id="codech264toggle" data-param="&codec=h264" onchange="updateLink(3,this);">
|
||||
<input type="checkbox" id="codech264toggle" data-param="&codec=h264" onchange="updateLink(3,this, true);">
|
||||
<span class="slider"></span>
|
||||
</label><font class="tooltip" style='cursor: help;position:relative;bottom:2px;font-family:"Noto Color Emoji", "Apple Color Emoji", "Segoe UI Emoji", Times, Symbola, Aegyptus, Code2000, Code2001, Code2002, Musica, serif, LastResort;'>💉<span class="tooltiptext" style="width: 10em; background-color: #77C"><span data-translate="this-can-reduce-packet-loss">Can reduce packet loss video corruption in OBS on PC</span></span></font>
|
||||
<span data-translate="use-h264-codec">Use H264 codec</span>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<div style="display:inline-block;margin-top: 12px; position: relative; margin-right:10px; ">
|
||||
<div style="display:inline-block;margin-top: 12px; position: relative; margin-right:10px; ">
|
||||
|
||||
<label class="switch" title="The active speakers are made visible automatically">
|
||||
<input type="checkbox" data-param="&sas" onchange="updateLink(3,this);">
|
||||
@ -1207,19 +1205,17 @@
|
||||
<br />
|
||||
|
||||
<label class="switch" title="Set the background color to bright green">
|
||||
<input type="checkbox" data-param="&chroma" onchange="updateLink(3,this);">
|
||||
<input type="checkbox" data-param="&chroma" onchange="updateLink(3,this, true);">
|
||||
<span class="slider"></span>
|
||||
</label>
|
||||
<span data-translate="green-background">Green background</span>
|
||||
|
||||
<br />
|
||||
|
||||
<label class="switch" title="Fade videos in over 500ms">
|
||||
<input type="checkbox" data-param="&fadein" onchange="updateLink(3,this);">
|
||||
<input type="checkbox" data-param="&fadein" onchange="updateLink(3,this, true);">
|
||||
<span class="slider"></span>
|
||||
</label>
|
||||
<span data-translate="fade-videos-in">Fade-in videos</span>
|
||||
|
||||
<br />
|
||||
|
||||
<label class="switch" title="Videos use an animated transition when being remixed">
|
||||
@ -1232,7 +1228,7 @@
|
||||
|
||||
<div style="display:inline-block;margin-top: 12px; position: relative; margin-right:10px;">
|
||||
<label class="switch">
|
||||
<input type="checkbox" data-param="&sl" onchange="updateLink(3,this);">
|
||||
<input type="checkbox" data-param="&sl" onchange="updateLink(3,this, true);">
|
||||
<span class="slider"></span>
|
||||
</label>
|
||||
<span data-translate="show-display-names">Show display names</span>
|
||||
@ -1244,36 +1240,40 @@
|
||||
</label>
|
||||
<span data-translate="add-margin">Add margin to videos</span>
|
||||
<br />
|
||||
|
||||
<label class="switch">
|
||||
<input type="checkbox" data-param="&vb=20000" onchange="updateLink(3,this);">
|
||||
<input type="checkbox" data-param="&vb=20000" onchange="updateLink(3,this, true);">
|
||||
<span class="slider"></span>
|
||||
</label>
|
||||
<font class="tooltip" style='cursor: help;position:relative;bottom:2px;font-family:"Noto Color Emoji", "Apple Color Emoji", "Segoe UI Emoji", Times, Symbola, Aegyptus, Code2000, Code2001, Code2002, Musica, serif, LastResort;'>⚠<span class="tooltiptext">This can cause video playback to lag</span></font> Unlock Video Bitrate
|
||||
|
||||
<font class="tooltip" style='cursor: help;position:relative;bottom:2px;font-family:"Noto Color Emoji", "Apple Color Emoji", "Segoe UI Emoji", Times, Symbola, Aegyptus, Code2000, Code2001, Code2002, Musica, serif, LastResort;'>⚠<span class="tooltiptext">This can cause video playback to lag</span></font>
|
||||
<span data-translate="unlock-video-bitrate">unlock Video Bitrate</span>
|
||||
<br />
|
||||
|
||||
<label class="switch" title="Disable fit-to-window optmized video scaling for added sharpness; increases CPU / Network load though.">
|
||||
<input type="checkbox" data-param="&scale=100" onchange="updateLink(3,this);">
|
||||
<input type="checkbox" data-param="&scale=100" onchange="updateLink(3,this, true);">
|
||||
<span class="slider"></span>
|
||||
</label>
|
||||
<span data-translate="disable-downscaling">Viewer-side downscaling</span>
|
||||
<font class="tooltip" style='cursor: help;position:relative;bottom:2px;font-family:"Noto Color Emoji", "Apple Color Emoji", "Segoe UI Emoji", Times, Symbola, Aegyptus, Code2000, Code2001, Code2002, Musica, serif, LastResort;'>⚠<span class="tooltiptext">This can cause higher CPU load for everyone in the room</span></font>
|
||||
<span data-translate="disable-downscaling">Increase sharpness</span>
|
||||
</div>
|
||||
|
||||
<div style="display:inline-block;margin-top: 12px; position: relative; ">
|
||||
<label class="switch" title="Playback the video with mono-channel audio">
|
||||
<input type="checkbox" data-param="&mono" onchange="updateLink(3,this);">
|
||||
<input type="checkbox" data-param="&mono" onchange="updateLink(3,this, true);">
|
||||
<span class="slider"></span>
|
||||
</label>
|
||||
<span data-translate="force-mono-audio">Force mono audio</span>
|
||||
<br />
|
||||
|
||||
<label class="switch" title="Have the videos fit their respective areas, even if it means cropping a bit">
|
||||
<input type="checkbox" data-param="&cover" onchange="updateLink(3,this);">
|
||||
<input type="checkbox" data-param="&cover" onchange="updateLink(3,this, true);">
|
||||
<span class="slider"></span>
|
||||
</label>
|
||||
<span data-translate="fill-video-space">Crop video to fit</span>
|
||||
<br />
|
||||
|
||||
<label class="switch" title="Have videos be aligned with sizing designed for vertical video">
|
||||
<input type="checkbox" data-param="&916" onchange="updateLink(3,this);">
|
||||
<input type="checkbox" data-param="&916" onchange="updateLink(3,this, true);">
|
||||
<span class="slider"></span>
|
||||
</label>
|
||||
<span data-translate="vertical-aspect-ratio">Vertical video mode</span>
|
||||
@ -1794,6 +1794,34 @@
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<nav id="context-menu-screen-share" class="context-menu">
|
||||
<ul class="context-menu__items">
|
||||
<li class="context-menu__item">
|
||||
<a href="#" class="context-menu__link" data-action="SSNewTab">
|
||||
<i class="las la-external-link"></i>
|
||||
<span data-translate="open-ss-in-new-tab">Share from a new tab</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="context-menu__item hidden">
|
||||
<a href="#" class="context-menu__link" data-action="ss1">
|
||||
1📷
|
||||
<span data-translate="ss-mode-1" >Screen Share Mode 1</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="context-menu__item hidden">
|
||||
<a href="#" class="context-menu__link" data-action="ss2">
|
||||
2📷
|
||||
<span data-translate="ss-mode-2" >Screen Share Mode 2</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="context-menu__item hidden">
|
||||
<a href="#" class="context-menu__link" data-action="ss3">
|
||||
3📷
|
||||
<span data-translate="ss-mode-3" >Screen Share Mode 3</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<nav id="context-menu-video" class="context-menu">
|
||||
<ul class="context-menu__items">
|
||||
<li class="context-menu__item">
|
||||
@ -2140,7 +2168,7 @@
|
||||
session.streamID = session.generateStreamID(); // randomly generates a streamID for this session. You can set your own programmatically if needed
|
||||
|
||||
session.defaultPassword = "someEncryptionKey123"; // Change this password if self-deploying for added security/privacy
|
||||
session.salt = location.hostname; // used only if password is not == False. You can change to "session.salt = location.hostname+location.pathname;" for greater deployment isolation
|
||||
// session.salt = location.hostname; // used only if password is not == False. You can change to "session.salt = location.hostname+location.pathname;" for greater deployment isolation
|
||||
|
||||
session.stunServers = [{ urls: ["stun:stun.l.google.com:19302", "stun:stun4.l.google.com:19302"]}]; // google stun servers. default
|
||||
|
||||
@ -2208,11 +2236,11 @@
|
||||
// session.defaultBackgroundImages = ["./media/bg_sample1.webp", "./media/bg_sample2.webp"]; // for &effects=5 (virtual backgrounds)
|
||||
</script>
|
||||
<script type="text/javascript" crossorigin="anonymous" src="./thirdparty/aes.js"></script>
|
||||
<script type="text/javascript" crossorigin="anonymous" id="lib-js" src="./lib.js?ver=390"></script>
|
||||
<script type="text/javascript" crossorigin="anonymous" id="lib-js" src="./lib.js?ver=405"></script>
|
||||
<!--
|
||||
// If you wish to change branding, blank offers a good clean start.
|
||||
<script type="text/javascript" id="main-js" src="./main.js" data-translation="blank"></script>
|
||||
-->
|
||||
<script type="text/javascript" crossorigin="anonymous" id="main-js" src="./main.js?ver=404"></script>
|
||||
<script type="text/javascript" crossorigin="anonymous" id="main-js" src="./main.js?ver=417"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
31
main.css
31
main.css
@ -2534,7 +2534,9 @@ button.toggleSettings{
|
||||
|
||||
#minipreview > #videosource {
|
||||
height:auto!important;
|
||||
width:auto!important;;
|
||||
width:auto!important;
|
||||
max-height:100%!important;
|
||||
max-width:100%!important;
|
||||
}
|
||||
|
||||
#videoSourceSelect {
|
||||
@ -3445,7 +3447,18 @@ div.message-card a {
|
||||
border-left: 4px solid #aacefd;
|
||||
background: #e6e8f0;
|
||||
}
|
||||
|
||||
.darktheme #guestTips {
|
||||
background-color: #414141;
|
||||
}
|
||||
.darktheme #guestTips .las {
|
||||
color: #FFF;
|
||||
}
|
||||
.darktheme .message-card {
|
||||
background-color: #000;
|
||||
}
|
||||
.darktheme input[type='file'] {
|
||||
background-color: #000;
|
||||
}
|
||||
.message-card h1 {
|
||||
display: block;
|
||||
font-size: 110%;
|
||||
@ -3689,9 +3702,8 @@ input:checked + .slider:before {
|
||||
border-radius: 10px;
|
||||
font-weight: bold;
|
||||
z-index:32;
|
||||
min-width:360px;
|
||||
max-width:90%;
|
||||
overflow-wrap: break-word;
|
||||
width: 240px;
|
||||
}
|
||||
|
||||
#connectUsers{
|
||||
@ -3781,12 +3793,6 @@ input:checked + .slider:before {
|
||||
font-size: 100%;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 390px) {
|
||||
.alertModal {
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.iframeDetails {
|
||||
margin: 10px;
|
||||
@ -4040,7 +4046,7 @@ input:checked + .slider:before {
|
||||
content: "\f0c0"; }
|
||||
.la-spinner:before {
|
||||
content: "\f110"; }
|
||||
.la.la-external-link:before {
|
||||
.la-external-link:before {
|
||||
content: "\f35d"; }
|
||||
.la-pen:before {
|
||||
content: "\f304"; }
|
||||
@ -4115,7 +4121,8 @@ body.darktheme h2 {
|
||||
body.darktheme button {
|
||||
filter: brightness(0.70);
|
||||
}
|
||||
body.darktheme .las {
|
||||
body.darktheme .column .las {
|
||||
color: black;
|
||||
}
|
||||
body.darktheme label {
|
||||
filter: brightness(0.85);
|
||||
|
||||
146
main.js
146
main.js
@ -43,7 +43,7 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
getById("mainmenu").style.opacity = 1;
|
||||
}
|
||||
}
|
||||
if (location.hostname !== "vdo.ninja" && location.hostname !== "backup.vdo.ninja" && location.hostname !== "obs.ninja") {
|
||||
if (location.hostname !== "vdo.ninja" && location.hostname !== "backup.vdo.ninja" && location.hostname !== "proxy.vdo.ninja" && location.hostname !== "obs.ninja") {
|
||||
if (location.hostname === "rtc.ninja"){
|
||||
try {
|
||||
if (session.label === false) {
|
||||
@ -168,7 +168,11 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
session.safemode = true; // load defa
|
||||
} else {
|
||||
session.store = {};
|
||||
loadSettings();
|
||||
try {
|
||||
loadSettings();
|
||||
} catch(e){
|
||||
errorlog(e);
|
||||
}
|
||||
}
|
||||
|
||||
if (navigator.userAgent.toLowerCase().indexOf(' electron/') > -1) {
|
||||
@ -436,7 +440,7 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
|
||||
session.slotmode = false; // temporary; remove in the future TODO: ## -----------------------
|
||||
if (urlParams.has('slotmode')){
|
||||
session.slotmode = true;
|
||||
session.slotmode = parseInt(urlParams.get('slotmode')) || 1;
|
||||
}
|
||||
|
||||
|
||||
@ -530,6 +534,11 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
|
||||
if (urlParams.has('nohangupbutton') || urlParams.has('nohub')){
|
||||
getById("hangupbutton").style.display = "none";
|
||||
session.hangupbutton = false;
|
||||
}
|
||||
|
||||
if (urlParams.has('hangupbutton') || urlParams.has('hub')){
|
||||
session.hangupbutton = true;
|
||||
}
|
||||
|
||||
if (urlParams.has('socialstream')){
|
||||
@ -669,13 +678,16 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
|
||||
if (urlParams.has('layout')) {
|
||||
try {
|
||||
session.layout = JSON.parse(decodeURIComponent(urlParams.get('layout'))) || JSON.parse(urlParams.get('layout')) || false;
|
||||
session.layout = JSON.parse(decodeURIComponent(urlParams.get('layout'))) || JSON.parse(urlParams.get('layout')) || {};
|
||||
} catch(e){
|
||||
session.layout = null
|
||||
try {
|
||||
session.layout = JSON.parse(urlParams.get('layout')) || {};
|
||||
} catch(e){
|
||||
session.layout = {};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (urlParams.has('deaf') || urlParams.has('deafen')) {
|
||||
session.directorSpeakerMuted=true; // false == true in this case.
|
||||
}
|
||||
@ -691,7 +703,7 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
getById("blindAllGuests").classList.remove("hidden");
|
||||
}
|
||||
|
||||
if (urlParams.has('dpi') || urlParams.has('dpr')) {
|
||||
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){
|
||||
@ -788,6 +800,20 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
}
|
||||
}
|
||||
}
|
||||
if (urlParams.has('screenshareaspectratio') || urlParams.has('ssar')) { // capture aspect ratio
|
||||
session.forceScreenShareAspectRatio = urlParams.get('screenshareaspectratio') || urlParams.get('ssar') || false;
|
||||
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;
|
||||
@ -895,6 +921,16 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
} else {
|
||||
session.scene = (parseInt(session.scene) || 0) + "";
|
||||
}
|
||||
}
|
||||
|
||||
if (urlParams.has('solo')){
|
||||
if (session.scene===false){
|
||||
session.scene = "0";
|
||||
}
|
||||
session.solo = true;
|
||||
}
|
||||
|
||||
if (session.scene!==false){
|
||||
session.disableWebAudio = true;
|
||||
session.audioEffects = false;
|
||||
session.audioMeterGuest = false;
|
||||
@ -1583,11 +1619,12 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
}
|
||||
|
||||
if (urlParams.has('ruler') || urlParams.has('grid') || urlParams.has('thirds')) {
|
||||
session.ruleOfThirds=true;
|
||||
session.fullscreen = true;
|
||||
if (!session.manual){
|
||||
session.manual = false;
|
||||
}
|
||||
session.ruleOfThirds = urlParams.get('ruler') || urlParams.get('grid') || urlParams.get('thirds') || "./media/thirds.svg";
|
||||
session.ruleOfThirds = decodeURIComponent(session.ruleOfThirds);
|
||||
}
|
||||
|
||||
if (urlParams.has('smallshare')){
|
||||
@ -1596,6 +1633,8 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
|
||||
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')) {
|
||||
@ -2169,6 +2208,7 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
session.alpha = true;
|
||||
}
|
||||
|
||||
|
||||
if (urlParams.has('debug')){
|
||||
session.debug=true;
|
||||
debugStart();
|
||||
@ -2295,6 +2335,10 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
}
|
||||
}
|
||||
|
||||
if (urlParams.has('sharperscreen')) { // sets scale to 100 for inbound screenshares only
|
||||
session.sharperScreen = true;
|
||||
}
|
||||
|
||||
if (urlParams.has('mcscale') || urlParams.has('meshcastscale')) {
|
||||
session.meshcastScale = parseFloat(urlParams.get('mcscale')) || parseFloat(urlParams.get('meshcastscale')) || 100;
|
||||
}
|
||||
@ -2534,6 +2578,10 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
session.cleanDirector = true;
|
||||
}
|
||||
|
||||
if (urlParams.has('hidetranslate')) {
|
||||
getById("translateButton").style.display = "none";
|
||||
}
|
||||
|
||||
if (session.cleanOutput){
|
||||
getById("translateButton").style.display = "none";
|
||||
getById("credits").style.display = "none";
|
||||
@ -2556,6 +2604,14 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
}
|
||||
getById("credits").innerHTML = "Version: " + session.version + " - " + getById("credits").innerHTML;
|
||||
|
||||
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;
|
||||
} else if (urlParams.has('showheader')) { // needs to happen the room and permaid applications
|
||||
getById("header").style.display = "inherit";
|
||||
getById("header").style.opacity = 1;
|
||||
}
|
||||
|
||||
if (urlParams.has('minidirector')) {
|
||||
try {
|
||||
var cssStylesheet = document.createElement('link');
|
||||
@ -2803,7 +2859,7 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
session.audioEffects = true;
|
||||
session.audioMeterGuest = true;
|
||||
session.minipreview = 2;
|
||||
if (session.activeSpeaker==1){
|
||||
if ((session.activeSpeaker==1) || (session.activeSpeaker==3)){
|
||||
session.animatedMoves = false;
|
||||
}
|
||||
session.fadein=true;
|
||||
@ -2970,7 +3026,7 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
if (urlParams.has('stun')) {
|
||||
var stunstring = urlParams.get('stun');
|
||||
stunstring = stunstring.split(";");
|
||||
if (stunstring !== "false") { // false disables the TURN server. Useful for debuggin
|
||||
if (stunstring[0] !== "false") { // false disables the TURN server. Useful for debuggin
|
||||
var stun = {};
|
||||
if (stunstring.length==3){
|
||||
stun.username = stunstring[0]; // myusername
|
||||
@ -3137,7 +3193,10 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
if (urlParams.has('wss')) {
|
||||
session.customWSS = true;
|
||||
if (urlParams.get('wss')) {
|
||||
session.wss = "wss://" + urlParams.get('wss');
|
||||
session.wss = urlParams.get('wss');
|
||||
if (!session.wss.startsWith("wss://")){
|
||||
session.wss = "wss://" + session.wss;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3578,12 +3637,6 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
getById("header").style.opacity = 0;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (session.view) {
|
||||
getById("main").className = "";
|
||||
@ -3999,19 +4052,19 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
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].manualBitrate = e.data.manualBitrate;
|
||||
session.rpcs[i].manualBandwidth = e.data.manualBitrate;
|
||||
session.requestRateLimit(false, i);
|
||||
}
|
||||
} else if (e.data.UUID && (e.data.UUID===i)) {
|
||||
session.rpcs[i].manualBitrate = e.data.manualBitrate;
|
||||
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].manualBitrate = e.data.manualBitrate
|
||||
session.rpcs[i].manualBandwidth = e.data.manualBitrate
|
||||
session.requestRateLimit(false, i);
|
||||
}
|
||||
} else {
|
||||
session.rpcs[i].manualBitrate = e.data.manualBitrate;
|
||||
session.rpcs[i].manualBandwidth = e.data.manualBitrate;
|
||||
session.requestRateLimit(false, i);
|
||||
}
|
||||
}
|
||||
@ -4102,9 +4155,15 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
}
|
||||
|
||||
if ("sceneState" in e.data) { // TRUE OR FALSE - tells the connected peers if they are live or not via a tally light change.
|
||||
if (session.obsState.visibility !== e.data.sceneState) { // only move forward if there is a change; the event likes to double fire you see.
|
||||
session.obsStateSync();
|
||||
}
|
||||
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 ("sendMessage" in e.data) { // webrtc send to viewers
|
||||
@ -4359,13 +4418,6 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
}
|
||||
}
|
||||
|
||||
if ("previewMode" in e.data){
|
||||
if ("layout" in e.data){
|
||||
session.layout = e.data.layout;
|
||||
}
|
||||
switchModes(e.data.previewMode);
|
||||
}
|
||||
|
||||
if ("advancedMode" in e.data){
|
||||
if (e.data.advancedMode){
|
||||
document.documentElement.style.setProperty('--advanced-mode', "inline-block"); // show advanced items
|
||||
@ -4381,14 +4433,38 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
} // 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 (("scene" in e.data) && ("layout" in e.data)){
|
||||
if ("previewMode" in e.data){
|
||||
if ("layout" in e.data){
|
||||
session.layout = e.data.layout;
|
||||
pokeIframeAPI("layout-updated", session.layout);
|
||||
}
|
||||
switchModes(e.data.previewMode);
|
||||
} else if ("layout" in e.data){
|
||||
warnlog("changing layout request via IFRAME API");
|
||||
issueLayout(e.data.layout, e.data.scene);
|
||||
session.layout = e.data.layout;
|
||||
pokeIframeAPI("layout-updated", session.layout);
|
||||
if (session.director){
|
||||
session.layout = e.data.layout; // not sure this is ideal, but whatever.
|
||||
updateMixer();
|
||||
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();
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
BIN
media/permissions_chrome.jpg
Normal file
BIN
media/permissions_chrome.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
@ -1,11 +1,8 @@
|
||||
<svg width="800" height="600" xmlns="http://www.w3.org/2000/svg">
|
||||
|
||||
<g>
|
||||
<title>Layer 1</title>
|
||||
<line stroke-width="2" stroke-dasharray="5,5" stroke="#000" stroke-linecap="undefined" stroke-linejoin="undefined" id="svg_1" y2="200.2" x2="798.00001" y1="200.2" x1="2.99999" fill="none"/>
|
||||
<line stroke="#000" stroke-linecap="undefined" stroke-linejoin="undefined" id="svg_3" y2="616.2" x2="266" y1="2.2" x1="266" stroke-dasharray="5,5" stroke-width="2" fill="none"/>
|
||||
<line stroke-width="2" stroke-dasharray="5,5" stroke="#000" stroke-linecap="undefined" stroke-linejoin="undefined" id="svg_4" y2="200.2" x2="798.00001" y1="200.2" x1="2.99999" fill="none"/>
|
||||
<line stroke="#000" stroke-linecap="undefined" stroke-linejoin="undefined" id="svg_5" y2="616.2" x2="534" y1="2.2" x1="534" stroke-dasharray="5,5" stroke-width="2" fill="none"/>
|
||||
<ellipse ry="132" rx="135" id="svg_6" cy="200.43469" cx="400" stroke-dasharray="5,5" stroke-width="2" stroke="#000" fill="none"/>
|
||||
</g>
|
||||
</svg>
|
||||
<svg viewBox="0 0 800 600" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="none" style="width:100%;height:100%;"><g>
|
||||
<line stroke-width="2" stroke-dasharray="5,5" stroke="#FFF1" stroke-linecap="undefined" stroke-linejoin="undefined" id="svg_1" y2="200" x2="799" y1="200" x1="1" fill="none"/>
|
||||
<line stroke="#FFF5" stroke-linecap="undefined" stroke-linejoin="undefined" id="svg_3" y2="616" x2="266" y1="1" x1="266" stroke-dasharray="5,5" stroke-width="2" fill="none"/>
|
||||
<line stroke-width="2" stroke-dasharray="5,5" stroke="#FFF1" stroke-linecap="undefined" stroke-linejoin="undefined" id="svg_4" y2="200" x2="799" y1="200" x1="1" fill="none"/>
|
||||
<line stroke="#FFF5" stroke-linecap="undefined" stroke-linejoin="undefined" id="svg_5" y2="616" x2="534" y1="1" x1="534" stroke-dasharray="5,5" stroke-width="2" fill="none"/>
|
||||
<line stroke-width="2" stroke-dasharray="5,5" stroke="#FFF1" stroke-linecap="undefined" stroke-linejoin="undefined" id="svg_2" y2="400" x2="799" y1="400" x1="1" fill="none"/>
|
||||
<line stroke-width="2" stroke-dasharray="5,5" stroke="#FFF1" stroke-linecap="undefined" stroke-linejoin="undefined" id="svg_6" y2="400" x2="799" y1="400" x1="1" fill="none"/>
|
||||
</g></svg>
|
||||
|
Before Width: | Height: | Size: 985 B After Width: | Height: | Size: 1.2 KiB |
532
mixer.html
532
mixer.html
@ -20,12 +20,12 @@
|
||||
--chat-width: 450px;
|
||||
}
|
||||
|
||||
body{
|
||||
body {
|
||||
padding:0;
|
||||
margin:0;
|
||||
background-color: #c9c9c9;
|
||||
font-family: 'Sora', sans-serif;
|
||||
overflow: hidden;
|
||||
overflow: auto;
|
||||
position: absolute;
|
||||
border-radius: 50px;
|
||||
background: #2e445c;
|
||||
@ -60,7 +60,7 @@
|
||||
position:absolute;
|
||||
top: -150px;
|
||||
}
|
||||
#modal{
|
||||
.modal{
|
||||
overflow:auto;
|
||||
}
|
||||
.message{
|
||||
@ -111,6 +111,16 @@
|
||||
background: transparent; /* make scrollbar transparent */
|
||||
}
|
||||
|
||||
|
||||
.xbutton{
|
||||
float: right;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
color: white;
|
||||
font-size: 150%;
|
||||
font-family: Verdana;
|
||||
line-height: 14px;
|
||||
}
|
||||
#chatModule {
|
||||
bottom: 0;
|
||||
position: fixed;
|
||||
@ -122,6 +132,7 @@
|
||||
height: calc(100vh - 40px);
|
||||
overflow: hidden;
|
||||
right:0;
|
||||
background:#0001;
|
||||
border: solid 2px #0005;
|
||||
border-radius: 10px;
|
||||
padding: 10px;
|
||||
@ -146,23 +157,7 @@
|
||||
button[data-state='true']{
|
||||
background-color:#CEF !important;
|
||||
}
|
||||
#inviteOptions{
|
||||
border: 0;
|
||||
padding: 0;
|
||||
display: block;
|
||||
height: calc(100vh - 80px);
|
||||
width: calc(100vw - 160px);
|
||||
max-width:100%;
|
||||
padding: 20px;
|
||||
margin:0;
|
||||
border:0;
|
||||
display: inline-block;
|
||||
background-color: #DDD;
|
||||
border-radius: 18px;
|
||||
background: #5b748f;
|
||||
box-shadow: inset 20px 20px 40px #556c85,
|
||||
inset -20px -20px 40px #617c99;
|
||||
}
|
||||
|
||||
input[type="checkbox"] {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
@ -201,13 +196,12 @@
|
||||
#iframeContainer{
|
||||
position: absolute;
|
||||
left: 160px;
|
||||
height: 100%;
|
||||
width: calc(100vw - var(--chat-width) - 160px);
|
||||
box-shadow: 1px 1px 3px #1b1b1b, -1px -1px 3px #1d1d1d;
|
||||
}
|
||||
#vdoninja {
|
||||
max-width: calc(100vw - 160px - var(--chat-width));
|
||||
width: 100vw;
|
||||
height: calc(100vh - 90px);
|
||||
}
|
||||
|
||||
#viewlink {
|
||||
@ -437,23 +431,7 @@
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
#sceneSettings{
|
||||
height: calc(100vh - 80px);
|
||||
width: calc(100vw - 160px);
|
||||
padding: 20px;
|
||||
margin:0;
|
||||
border:0;
|
||||
display: inline-block;
|
||||
background-color: #DDD;
|
||||
border-radius: 18px;
|
||||
background: #5b748f;
|
||||
box-shadow: inset 20px 20px 40px #556c85,
|
||||
inset -20px -20px 40px #617c99;
|
||||
}
|
||||
|
||||
#sceneSettings > h2{
|
||||
margin: 4px;
|
||||
}
|
||||
|
||||
.settings {
|
||||
display: block;
|
||||
@ -596,7 +574,6 @@
|
||||
}
|
||||
|
||||
.modal {
|
||||
display: none;
|
||||
position: fixed;
|
||||
padding-top: 50px;
|
||||
left: 0;
|
||||
@ -606,12 +583,12 @@
|
||||
background-color: rgb(0, 0, 0);
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
z-Index: 20;
|
||||
|
||||
}
|
||||
.modal-content {
|
||||
position: relative;
|
||||
padding: 20px;
|
||||
margin: auto;
|
||||
margin: auto;
|
||||
margin-bottom: 100px;
|
||||
width: 75%;
|
||||
-webkit-animation-name: animatetop;
|
||||
-webkit-animation-duration: 0.4s;
|
||||
@ -622,16 +599,18 @@
|
||||
background-image: url("data:image/svg+xml,%3Csvg width='6' height='6' viewBox='0 0 6 6' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='%239C92AC' fill-opacity='0.1' fill-rule='evenodd'%3E%3Cpath d='M5 0h1L0 6V5zM6 5v1H5z'/%3E%3C/g%3E%3C/svg%3E");
|
||||
}
|
||||
.close-btn {
|
||||
float: right;
|
||||
color: lightgray;
|
||||
color: #333;
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
user-select: none;
|
||||
}
|
||||
.close-btn:hover {
|
||||
color: darkgray;
|
||||
color: black;
|
||||
cursor:pointer;
|
||||
}
|
||||
span.close-btn {
|
||||
float: right;
|
||||
}
|
||||
@-webkit-keyframes animatetop {
|
||||
from {top:-300px; opacity:0}
|
||||
to {top:0; opacity:1}
|
||||
@ -862,9 +841,9 @@
|
||||
<div id="container">
|
||||
<div id="containermenu"></div>
|
||||
<div id="containermenu2" class="hidden">
|
||||
<button onclick="addElement();">➕ Add Item</button>
|
||||
<button onclick="addElement();">➕ Add Element to Scene</button>
|
||||
<button onclick="saveScene(false, event);">💾 Save Scene</button>
|
||||
<button onclick="saveScene(true, event);">💾<span style="position:relative;right:12px;top:2px;width:12px;display: inline-block;">💾</span>Duplicate</button>
|
||||
<button onclick="saveScene(true, event);">💾<span style="position:relative;right:12px;top:2px;width:12px;display: inline-block;">💾</span>Duplicate Scene</button>
|
||||
<button onclick="copyJSON();" title="This can be used with &format directly in VDO.Ninja without the mixer app.">Show as JSON</button>
|
||||
<button onclick="removeScene();">🗑️ Remove Scene</button>
|
||||
<button id="saveAndClose" onclick="saveScene(false, event);closeScene();">💾❌ Save and Close</button>
|
||||
@ -873,7 +852,7 @@
|
||||
</div>
|
||||
<div id="chatModuleButton" class="hidden" onclick="toggleChat();" style="user-select: none;position: fixed;top: 10px;right: 10px;cursor: pointer;" title="Show the chat window">💬</div>
|
||||
<div id="chatModule" class="hidden">
|
||||
<div style="float: right;cursor: pointer;user-select: none;" onclick="toggleChat();" title="Hide the chat window">x</div>
|
||||
<div class="xbutton" onclick="toggleChat();" title="Hide the chat window">x</div>
|
||||
<div id="chatBody" class="message">
|
||||
<div class="inMessage" data-translate='welcome-to-vdo-ninja-chat'>
|
||||
Welcome to VDO.Ninja! You can send text messages directly to connected peers from here.
|
||||
@ -918,17 +897,32 @@
|
||||
<div id="iframeContainer" class="tFadeStart">
|
||||
<div id='canvas' class="hidden">
|
||||
</div>
|
||||
<div id='sceneSettings' class="hidden2">
|
||||
</div>
|
||||
<!--
|
||||
<div class="modal" >
|
||||
|
||||
<span class="close-btn">×</span>
|
||||
<div id="modal-content">
|
||||
<p>this is the text inside the modal</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
-->
|
||||
<div id='sceneSettings' class="hidden modal">
|
||||
<div class="modal-content">
|
||||
<span class="close-btn">×</span>
|
||||
<h2>General Settings</h2>
|
||||
<h4>Aspect Ratio</h4>
|
||||
<input type="checkbox" class="aspectbutton" onchange="changeAspectRatio(16/9.0, this);">16:9
|
||||
<input type="checkbox" checked class="aspectbutton" onchange="changeAspectRatio(16/9.0, this);">16:9
|
||||
<input type="checkbox" class="aspectbutton" onchange="changeAspectRatio(9.0/16, this);">9:16
|
||||
<input type="checkbox" class="aspectbutton" onchange="changeAspectRatio(1.0, this);">1:1
|
||||
<br /><small><i>This just impacts the aspect ratio of the local preview.</i></small><br />
|
||||
|
||||
<h4>Layout switching</h4>
|
||||
<input type="checkbox" title="When a user is assigned a slot or switches slots, the last active layout is re-applied automatically" id="updateOnSlotChange" checked onchange="submitChange(this)";>Update layout on a slot change
|
||||
|
||||
<h4>Slot assignment</h4>
|
||||
<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
|
||||
<h4>Show advanced controls</h4>
|
||||
<input type="checkbox" title="Shows more director control options" onchange="toggleAdvanced(this)";>Show the advanced director control options
|
||||
|
||||
@ -941,37 +935,36 @@
|
||||
<button onclick="exportSession();">Export all scenes and settings to disk</button><br />
|
||||
<h4>📥 Import settings </h4>
|
||||
Import scenes and settings from local file:<br /><input type="file" accept=".json" onchange="importSession(event);"/><br /><br />
|
||||
<button onclick="getById('modal-content').innerHTML = '';modal.style.display = 'none';">Close Settings</button>
|
||||
<button class='close-btn'>Close Settings</button>
|
||||
</div>
|
||||
<div id='roomSettings' class="hidden2">
|
||||
</div>
|
||||
<div id='roomSettings' class="hidden modal">
|
||||
<div class="modal-content">
|
||||
<span class="close-btn">×</span>
|
||||
<h2>Room Setup</h2>
|
||||
|
||||
<br /><br />
|
||||
<button onclick="showSettings();">Close</button>
|
||||
</div>
|
||||
<div id='inviteOptions' class="hidden">
|
||||
</div>
|
||||
<div id='inviteOptions' class="hidden modal">
|
||||
<div class="modal-content">
|
||||
<span class="close-btn">×</span>
|
||||
<h2>Invite options</h2>
|
||||
<h4>Your room name is: <b class="roomname">ROOMNAME</b></h4>
|
||||
<h3>Create new invite</h3>
|
||||
<a class="inviteLink" target="_blank">Invite Link</a><i class="inviteLink"></i><br />
|
||||
<span class="hidden">
|
||||
<input type="checkbox" /><label>Prompt user for a display name?</label><br />
|
||||
<input type="checkbox" /><label>Guest can see other guests? (higher CPU for guest)</label><br />
|
||||
<input type="checkbox" /><label>Guest will join muted? (director can remotely unmute)</label><br />
|
||||
</span>
|
||||
<i>You can manually customize the invite link further; see the documentation at <a href="docs.vdo.ninja" target="_blank">docs.vdo.ninja</a></i>
|
||||
<h3>Copy invite to clipboard</h3>
|
||||
<a class="inviteLink" target="_blank">Invite Link</a><i class="inviteLink"></i>
|
||||
<br /><br />
|
||||
<button onclick="getById('modal-content').innerHTML = '';modal.style.display = 'none';">Close</button>
|
||||
<h3>Customize invite link</h3>
|
||||
<span >
|
||||
<input type="checkbox" id="toggleLabel" onclick="updateInviteLinks(event)" /><label>Prompt user for a display name</label><br />
|
||||
<input type="checkbox" id="toggleBroadcast" onclick="updateInviteLinks(event)"/><label>Guest can see other guests and the active layout <small>(higher CPU for guest)</small></label><br />
|
||||
</span>
|
||||
<i>You can manually customize the invite link further; see the documentation at <a href="https://docs.vdo.ninja" target="_blank">docs.vdo.ninja</a></i>
|
||||
<br /><br />
|
||||
<button class='close-btn'>Close</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="modal" class="modal" >
|
||||
<div class="modal-content">
|
||||
<span class="close-btn">×</span>
|
||||
<div id="modal-content">
|
||||
<p>this is the text inside the modal</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="gone" >
|
||||
<!-- This image is used when dragging elements -->
|
||||
<img src="./media/favicon-32x32.png" style="pointer-events: none;" id="dragImage" loading="lazy" />
|
||||
@ -1048,6 +1041,7 @@
|
||||
}
|
||||
return roomid;
|
||||
}
|
||||
|
||||
|
||||
var urlEdited = window.location.search.replace(/\?\?/g, "?");
|
||||
urlEdited = urlEdited.replace(/\?/g, "&");
|
||||
@ -1059,24 +1053,33 @@
|
||||
}
|
||||
var urlParams = new URLSearchParams(urlEdited);
|
||||
|
||||
var api = false;
|
||||
if (urlParams.has('osc') || urlParams.has('api')) {
|
||||
if (urlParams.get('osc') || urlParams.get('api')) {
|
||||
api = urlParams.get('osc') || urlParams.get('api');
|
||||
}
|
||||
}
|
||||
|
||||
var streamIDs = [];
|
||||
var slotsNeeded = 1;
|
||||
var lastLayout = false;
|
||||
var lastLayout = {"scene":"0", "layout":false};
|
||||
var lastLayoutRaw = false;
|
||||
var updateOnSlotChange = true;
|
||||
var assignSlotToGuest = true;
|
||||
var toggleLabel = false;
|
||||
var toggleBroadcast = true;
|
||||
|
||||
var password = false;
|
||||
if (urlParams.has("password")){
|
||||
password = urlParams.get("password");
|
||||
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');
|
||||
}
|
||||
|
||||
var aspectRatio = 16/9.0;
|
||||
document.documentElement.style.setProperty('--aspect-ratio', aspectRatio);
|
||||
|
||||
var roomname = false;
|
||||
if (urlParams.has("room") || urlParams.has("dir") || urlParams.has("director")){
|
||||
roomname = urlParams.get("room") || urlParams.get("dir") || urlParams.get("director");
|
||||
if (urlParams.has("room") || urlParams.has("r") ||urlParams.has("dir") || urlParams.has("director")){
|
||||
roomname = urlParams.get("room") || urlParams.get("r") ||urlParams.get("dir") || urlParams.get("director");
|
||||
roomname = sanitizeRoomName(roomname);
|
||||
}
|
||||
var savedLastRoom = getStorage("savedRoom");
|
||||
@ -1191,8 +1194,6 @@
|
||||
return "Seconds ago";
|
||||
}
|
||||
|
||||
|
||||
|
||||
function updateMessages(message = false){
|
||||
if (message){
|
||||
var time = timeSince(message.time);
|
||||
@ -1558,17 +1559,20 @@
|
||||
{x:0, y:0, w:100, h:100}
|
||||
];
|
||||
initialLayouts.layouts.push(data);
|
||||
|
||||
var data = [
|
||||
null,
|
||||
{x:0, y:0, w:100, h:100}
|
||||
];
|
||||
initialLayouts.layouts.push(data);
|
||||
|
||||
var data = [
|
||||
null,
|
||||
null,
|
||||
{x:0, y:0, w:100, h:100}
|
||||
];
|
||||
initialLayouts.layouts.push(data);
|
||||
|
||||
var data = [
|
||||
null,
|
||||
null,
|
||||
@ -1576,6 +1580,7 @@
|
||||
{x:0, y:0, w:100, h:100}
|
||||
];
|
||||
initialLayouts.layouts.push(data);
|
||||
|
||||
var data = [
|
||||
{x:0, y:0, w:50, h:100, c:false},
|
||||
{x:50, y:0, w:50, h:100, c:false}
|
||||
@ -1584,7 +1589,7 @@
|
||||
|
||||
var data = [
|
||||
{x:70, y:70, w:30, h:30, z:1, c:true},
|
||||
{x:0, y:0, w:100, h:100,z:0, c:false}
|
||||
{x:0, y:0, w:100, h:100, z:0, c:false}
|
||||
];
|
||||
initialLayouts.layouts.push(data);
|
||||
|
||||
@ -1595,6 +1600,7 @@
|
||||
{x:50, y:50, w:50, h:50, c:true}
|
||||
];
|
||||
initialLayouts.layouts.push(data);
|
||||
|
||||
var data = [
|
||||
{x:0, y:16.667, w:66.667, h:66.667, c:true},
|
||||
{x:66.667, y:0, w:33.333, h:33.333, c:true},
|
||||
@ -1610,6 +1616,42 @@
|
||||
getById("updateOnSlotChange").value = "off";
|
||||
getById("updateOnSlotChange").checked = false;
|
||||
getById("updateOnSlotChange").removeAttribute('checked');
|
||||
} else {
|
||||
getById("updateOnSlotChange").value = "on";
|
||||
getById("updateOnSlotChange").checked = true;
|
||||
}
|
||||
}
|
||||
if (savedSession.settings && ("assignSlotToGuest" in savedSession.settings)){
|
||||
assignSlotToGuest = savedSession.settings.assignSlotToGuest;
|
||||
if (!assignSlotToGuest){
|
||||
getById("assignSlotToGuest").value = "off";
|
||||
getById("assignSlotToGuest").checked = false;
|
||||
getById("assignSlotToGuest").removeAttribute('checked');
|
||||
} else {
|
||||
getById("assignSlotToGuest").value = "on";
|
||||
getById("assignSlotToGuest").checked = true;
|
||||
}
|
||||
}
|
||||
if (savedSession.settings && ("toggleLabel" in savedSession.settings)){
|
||||
toggleLabel = savedSession.settings.toggleLabel;
|
||||
if (!toggleLabel){
|
||||
getById("toggleLabel").value = "off";
|
||||
getById("toggleLabel").checked = false;
|
||||
getById("toggleLabel").removeAttribute('checked');
|
||||
} else {
|
||||
getById("toggleLabel").value = "on";
|
||||
getById("toggleLabel").checked = true;
|
||||
}
|
||||
}
|
||||
if (savedSession.settings && ("toggleBroadcast" in savedSession.settings)){
|
||||
toggleBroadcast = savedSession.settings.toggleBroadcast;
|
||||
if (!toggleBroadcast){
|
||||
getById("toggleBroadcast").value = "off";
|
||||
getById("toggleBroadcast").checked = false;
|
||||
getById("toggleBroadcast").removeAttribute('checked');
|
||||
} else {
|
||||
getById("toggleBroadcast").value = "on";
|
||||
getById("toggleBroadcast").checked = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1623,6 +1665,10 @@
|
||||
savedSession = initialLayouts;
|
||||
}
|
||||
|
||||
if (iframe){
|
||||
iframe.contentWindow.postMessage({ layouts: savedSession.layouts }, "*");
|
||||
}
|
||||
|
||||
var guestPositions = {};
|
||||
|
||||
function submitChange(element){
|
||||
@ -1635,6 +1681,19 @@
|
||||
saveSession();
|
||||
}
|
||||
|
||||
function submitChange2(element){
|
||||
if (element.checked){
|
||||
assignSlotToGuest=true;
|
||||
iframe.contentWindow.postMessage({"slotmode":1}, '*');
|
||||
} else { // do not assign guests to slots automatically
|
||||
element.removeAttribute('checked');
|
||||
assignSlotToGuest=false
|
||||
iframe.contentWindow.postMessage({"slotmode":2}, '*');;
|
||||
}
|
||||
|
||||
saveSession();
|
||||
}
|
||||
|
||||
function toggleAdvanced(element){
|
||||
if (element.checked){
|
||||
iframe.contentWindow.postMessage({"advancedMode":true}, '*');
|
||||
@ -1644,8 +1703,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function exportSession() {
|
||||
var content = JSON.stringify(savedSession);
|
||||
var fileName = roomname + ".json";
|
||||
@ -1733,9 +1790,6 @@
|
||||
background: #2e445c;
|
||||
box-shadow: 20px 20px 60px #182430, -20px -20px 60px #283c52;
|
||||
}
|
||||
label {
|
||||
color: #fff;
|
||||
}
|
||||
`;
|
||||
|
||||
injectCSS = encodeURIComponent(btoa(injectCSS));
|
||||
@ -1880,20 +1934,27 @@
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
var iframe = null;
|
||||
|
||||
function loadIframe(){
|
||||
if (iframe){return;}
|
||||
iframe = document.createElement("iframe");
|
||||
|
||||
var additional = "";
|
||||
var additional = ""; // guest/scene links also
|
||||
if (password){
|
||||
additional = "&password="+password;
|
||||
}
|
||||
|
||||
var additional2 = ""; // this iframe only
|
||||
if (api){
|
||||
additional2 += "&api="+api;
|
||||
}
|
||||
|
||||
if (assignSlotToGuest){
|
||||
additional2+="&slotmode";
|
||||
} else {
|
||||
additional2+="&slotmode=2";
|
||||
}
|
||||
roomname = sanitizeRoomName(roomname);
|
||||
|
||||
|
||||
@ -1901,13 +1962,12 @@
|
||||
iframe.allow = "autoplay;camera;microphone;fullscreen;picture-in-picture;display-capture;";
|
||||
iframe.id = "vdoninja";
|
||||
|
||||
if (roomname){
|
||||
var iframesrc = "./index.html?novice<b=350&transparent&cleanoutput&slotmode&director="+roomname+additional+"&b64css="+injectCSS;
|
||||
} else {
|
||||
if (!roomname){
|
||||
roomname = generateString(10);
|
||||
var iframesrc = "./index.html?novice<b=350&transparent&cleanoutput&slotmode&director="+roomname+additional+"&b64css="+injectCSS;
|
||||
}
|
||||
|
||||
var iframesrc = "./index.html?novice<b=350&transparent&hideheader&hidetranslate&cleandirector&chatbutton=0&director="+roomname+additional+additional2+"&b64css="+injectCSS;
|
||||
|
||||
if (roomname!==false){
|
||||
setStorage("savedRoom", {roomname:roomname,password:password}, 9999);
|
||||
}
|
||||
@ -1937,7 +1997,7 @@
|
||||
button.onclick = function(){
|
||||
this.state = !this.state;
|
||||
this.dataset.state = this.state;
|
||||
iframe.contentWindow.postMessage({"previewMode":this.state, "layout":currentLayout, "bitrate":35, "target": "*"}, '*');
|
||||
iframe.contentWindow.postMessage({"previewMode":this.state, "layout":currentLayout.layouts, "bitrate":35, "target": "*"}, '*');
|
||||
if (this.state){
|
||||
this.innerHTML = "Director View ↻";
|
||||
iframe.classList.add("aspectRatio");
|
||||
@ -1998,14 +2058,16 @@
|
||||
|
||||
var a = document.createElement("a");
|
||||
a.innerHTML = "Invite Guest Link 📎";
|
||||
a.href = "./index.html?room="+roomname+"&sstype=3&broadcast"+additional;
|
||||
a.href = "./?room="+roomname+"&sstype=3&broadcast"+additional;
|
||||
a.target = "_blank";
|
||||
a.onclick = function(evt){copyFunction(this, evt);};
|
||||
document.getElementById("sources").appendChild(a);
|
||||
|
||||
var a = document.createElement("a");
|
||||
a.innerHTML = "Scene View Link 📎";
|
||||
a.href = "./index.html?scene=0&layout=%7B%7D&room="+roomname+additional;
|
||||
a.innerHTML = "Scene View Link 📎";
|
||||
a.href = "./?scene=0&layout&room="+roomname+additional;
|
||||
a.target = "_blank";
|
||||
a.onclick = function(evt){copyFunction(this, evt);};
|
||||
document.getElementById("sources").appendChild(a);
|
||||
|
||||
|
||||
@ -2026,6 +2088,10 @@
|
||||
|
||||
document.getElementById("chatModule").classList.remove("hidden");
|
||||
|
||||
iframe.onload = function(){
|
||||
iframe.contentWindow.postMessage({ layouts: savedSession.layouts }, "*");
|
||||
}
|
||||
|
||||
iframe.src = iframesrc;
|
||||
iframeContainer.appendChild(iframe);
|
||||
document.getElementById("container").appendChild(iframeContainer);
|
||||
@ -2044,7 +2110,7 @@
|
||||
eventer(messageEvent, function (e) {
|
||||
if (e.source != iframe.contentWindow){return} // reject messages send from other iframes
|
||||
|
||||
console.log(e.data);
|
||||
//console.log(e.data);
|
||||
|
||||
if ("action" in e.data){
|
||||
///var outputWindow = document.createElement("div");
|
||||
@ -2085,6 +2151,23 @@
|
||||
|
||||
if (e.data.action && (e.data.action == "scene-connected")){
|
||||
if (lastLayout && lastLayout.scene == e.data.value){
|
||||
var layoutIssue = {};
|
||||
layoutIssue.layout = lastLayout.layout;
|
||||
if (e.data.UUID){
|
||||
layoutIssue.UUID = e.data.UUID;
|
||||
}
|
||||
layoutIssue.scene = lastLayout.scene
|
||||
iframe.contentWindow.postMessage(lastLayout, '*');
|
||||
}
|
||||
}
|
||||
|
||||
if (e.data.action && (e.data.action == "guest-connected")){
|
||||
if (lastLayout){
|
||||
var layoutIssue = {};
|
||||
layoutIssue.layout = lastLayout.layout;
|
||||
if (e.data.UUID){
|
||||
layoutIssue.UUID = e.data.UUID;
|
||||
}
|
||||
iframe.contentWindow.postMessage(lastLayout, '*');
|
||||
}
|
||||
}
|
||||
@ -2136,18 +2219,37 @@
|
||||
}
|
||||
|
||||
function showSettings(){
|
||||
document.getElementById("modal").style.display = "block";
|
||||
applySettings();
|
||||
document.getElementById("modal-content").innerHTML = document.getElementById("sceneSettings").innerHTML;
|
||||
document.getElementById("sceneSettings").classList.remove("hidden");
|
||||
}
|
||||
|
||||
function showInviteOptions(){
|
||||
document.getElementById("modal").style.display = "block";
|
||||
document.getElementById("modal-content").innerHTML = document.getElementById("inviteOptions").innerHTML;
|
||||
|
||||
|
||||
function showInviteOptions(event=false){
|
||||
document.getElementById("inviteOptions").classList.remove("hidden");
|
||||
updateInviteLinks();
|
||||
}
|
||||
var toggleBroadcast = false;
|
||||
|
||||
function updateInviteLinks(event=false){
|
||||
var additional = "";
|
||||
|
||||
if (password){
|
||||
additional = "&password="+password;
|
||||
additional += "&password="+password;
|
||||
}
|
||||
|
||||
if (document.getElementById("toggleLabel").checked){
|
||||
additional += "&label";
|
||||
toggleLabel = true;
|
||||
} else {
|
||||
toggleLabel= false;
|
||||
}
|
||||
|
||||
if (!document.getElementById("toggleBroadcast").checked){
|
||||
additional += "&broadcast";
|
||||
toggleBroadcast = true;
|
||||
} else {
|
||||
additional += "&layout";
|
||||
toggleBroadcast = false;
|
||||
}
|
||||
|
||||
document.querySelectorAll(".roomname").forEach(ele=>{
|
||||
@ -2156,15 +2258,24 @@
|
||||
|
||||
document.querySelectorAll(".inviteLink").forEach(ele=>{
|
||||
if (ele.tagName == "A"){
|
||||
ele.href = "./index.html?room="+roomname+"&broadcast"+additional;
|
||||
ele.href = "./?room="+roomname+additional;
|
||||
} else if (ele.tagName == "I"){
|
||||
ele.innerHTML = "URL + ?room="+roomname+"&broadcast"+additional;
|
||||
ele.innerHTML = "URL + ?room="+roomname+additional;
|
||||
}
|
||||
ele.onclick = function(evt){copyFunction(this, evt);};
|
||||
});
|
||||
|
||||
|
||||
if (event){
|
||||
document.querySelectorAll(".inviteLink").forEach(ele=>{
|
||||
ele.classList.remove("shake");
|
||||
ele.classList.add("shake");
|
||||
setTimeout(function(ele){ele.classList.remove("shake");},500,ele);
|
||||
});
|
||||
saveSession();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function addLayout(){
|
||||
var layout = prompt("Enter your new layout as a JSON string", '[{"x":0,"y":0,"w":100,"h":100}]');
|
||||
layout = JSON.parse(layout);
|
||||
@ -2214,9 +2325,22 @@
|
||||
});
|
||||
}
|
||||
|
||||
function compareZ( a, b ) { // sorts layout based on z-index.
|
||||
var aa = a.z || a.zIndex || 0;
|
||||
var bb = b.z || b.zIndex || 0;
|
||||
if ( aa > bb ){
|
||||
return 1;
|
||||
}
|
||||
if ( aa < bb ){
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
function drawLayout(layoutOriginal, sceneName=false){
|
||||
|
||||
var layout = [];
|
||||
|
||||
for (var i=0;i<layoutOriginal.length;i++){
|
||||
if (!layoutOriginal[i]){
|
||||
continue;
|
||||
@ -2227,18 +2351,7 @@
|
||||
layout.push(layoutOriginal[i]);
|
||||
}
|
||||
|
||||
function compare( a, b ) { // sorts layout based on z-index.
|
||||
var aa = a.z || 0;
|
||||
var bb = b.z || 0;
|
||||
if ( aa > bb ){
|
||||
return 1;
|
||||
}
|
||||
if ( aa < bb ){
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
layout.sort(compare);
|
||||
layout.sort(compareZ);
|
||||
|
||||
var canvas = document.createElement('canvas');
|
||||
canvas.width="80";
|
||||
@ -2492,27 +2605,21 @@
|
||||
for (var i=0;i<object.length;i++){
|
||||
if (object[i] == null){continue;}
|
||||
var slot = parseInt(object[i].slot) || 0;
|
||||
<!-- ele.w = parseInt(compute.width)/1280*100; -->
|
||||
<!-- ele.h = parseInt(compute.height)/720*100; -->
|
||||
<!-- ele.x = parseInt(compute.left)/1280*100; -->
|
||||
<!-- ele.y = parseInt(compute.top)/720*100; -->
|
||||
|
||||
<!-- ele.z = object[i].zIndex; -->
|
||||
<!-- ele.bg = object[i].backgroundColor; -->
|
||||
<!-- ele.bt = object[i].borderThickness; -->
|
||||
<!-- ele.bc = object[i].borderColor; -->
|
||||
<!-- ele.bm = object[i].backgroundMedia; -->
|
||||
<!-- ele.margin = object[i].margin; -->
|
||||
<!-- ele.r = object[i].rounded; -->
|
||||
<!-- ele.m = object[i].muted; -->
|
||||
|
||||
var color = colors[slot];
|
||||
var container = document.createElement("div");
|
||||
|
||||
container.className = "widget ui-widget-content draggable resizable";
|
||||
container.slot = slot;
|
||||
container.cover = object[i].cover || false;
|
||||
container.zIndex = parseInt(object[i].z) || 0;
|
||||
|
||||
if ("cover" in object[i]){
|
||||
container.cover = object[i].cover || false;
|
||||
} else if ("c" in object[i]){
|
||||
container.cover = object[i].c || false;
|
||||
} else {
|
||||
container.cover = true;
|
||||
}
|
||||
container.zIndex = parseInt(object[i].zIndex) || parseInt(object[i].z) || 0;
|
||||
//container.backgroundColor = object[i].backgroundColor || "#000";
|
||||
container.borderThickness = object[i].borderThickness || 0;
|
||||
container.animated = object[i].animated || 0;
|
||||
@ -2613,7 +2720,7 @@
|
||||
}
|
||||
|
||||
var color = colors[slot];
|
||||
var container = document.createElement("div");
|
||||
var container = document.createElement("div"); // we use the long-form of meta attributes for container elements.
|
||||
container.className = "widget ui-widget-content draggable resizable";
|
||||
container.slot = slot;
|
||||
|
||||
@ -2683,7 +2790,36 @@
|
||||
$(function(){
|
||||
$(".resizable").resizable({ snap: true , grid: [ 10, 10] });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function combinedLayout(layout){
|
||||
var combined = {};
|
||||
console.log(layout);
|
||||
|
||||
for (var i=0;i<layout.length;i++){
|
||||
console.log(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;
|
||||
}
|
||||
console.log(stream);
|
||||
if (!stream){
|
||||
if (layout[i].defaultStreamID){
|
||||
combined[layout[i].defaultStreamID] = layout[i];
|
||||
}
|
||||
continue;
|
||||
}
|
||||
combined[stream] = layout[i];
|
||||
}
|
||||
console.log(combined);
|
||||
return combined;
|
||||
}
|
||||
|
||||
function remoteActivate(event=null, layout=null){
|
||||
console.log(this);
|
||||
@ -2698,45 +2834,19 @@
|
||||
event.target.parentNode.classList.add("pressed");
|
||||
}
|
||||
|
||||
var combined = false;
|
||||
|
||||
lastLayoutRaw = layout;
|
||||
|
||||
var combined = false;
|
||||
if (layout){
|
||||
layout = JSON.parse(layout);
|
||||
console.log(layout);
|
||||
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;
|
||||
}
|
||||
console.log(stream);
|
||||
console.log(i);
|
||||
console.log(layout);
|
||||
|
||||
if (!stream){
|
||||
if (layout[i].defaultStreamID){
|
||||
combined[layout[i].defaultStreamID] = layout[i];
|
||||
}
|
||||
continue;
|
||||
}
|
||||
combined[stream] = layout[i];
|
||||
}
|
||||
combined = combinedLayout(layout);
|
||||
}
|
||||
|
||||
console.log(combined);
|
||||
currentLayout = combined; // global current state
|
||||
lastLayout = {"scene":"0", "layout":combined};
|
||||
|
||||
iframe.contentWindow.postMessage({"scene":"0", "layout":combined}, '*');
|
||||
|
||||
|
||||
}
|
||||
|
||||
function deleteElement(event){
|
||||
@ -2927,9 +3037,16 @@
|
||||
ele.y = parseFloat(compute.top)/hh*100;
|
||||
|
||||
try {
|
||||
ele.z = parseInt(eles[i].zIndex) || 0;
|
||||
|
||||
ele.slot = parseInt(eles[i].slot) || i;
|
||||
ele.cover = eles[i].cover || false;
|
||||
ele.zIndex = parseInt(eles[i].zIndex) || 0;
|
||||
|
||||
if ("cover" in eles[i]){
|
||||
ele.cover = eles[i].cover || false;
|
||||
} else {
|
||||
ele.cover = true;
|
||||
}
|
||||
|
||||
//ele.backgroundColor = eles[i].backgroundColor || "#000";
|
||||
ele.borderThickness = parseInt(eles[i].borderThickness) || 0;
|
||||
@ -2943,37 +3060,9 @@
|
||||
} catch(e){errorlog(e);}
|
||||
layout.push(ele);
|
||||
}
|
||||
var combined = {};
|
||||
for (var i=0;i<layout.length;i++){
|
||||
//layout[i].z = i;
|
||||
if (!layout[i]){continue;}
|
||||
if (!("slot" in layout[i])){
|
||||
//console.log("no slot");
|
||||
//if (!(null in combined)){
|
||||
// combined[null] = [];
|
||||
//}
|
||||
//combined[null].push(layout[i]);
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
var stream = document.querySelector(".thing[data-slot='"+(parseInt(layout[i].slot)+1)+"'");
|
||||
} catch(e){
|
||||
errorlog(e);
|
||||
continue;
|
||||
}
|
||||
console.log(stream);
|
||||
console.log(i);
|
||||
console.log(layout);
|
||||
if (!stream){
|
||||
if (layout[i].defaultStreamID){
|
||||
if (!document.querySelector(".thing[data-slot][data-sid='"+layout[i].defaultStreamID+"']")){
|
||||
combined[layout[i].defaultStreamID] = layout[i];
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
combined[stream.dataset.sid] = layout[i];
|
||||
}
|
||||
|
||||
var combined = combinedLayout(layout);
|
||||
|
||||
prompt("Layout as URL-encoded JSON. StreamIDs are based on current and default values.", encodeURIComponent(JSON.stringify(combined)));
|
||||
}
|
||||
|
||||
@ -2994,8 +3083,14 @@
|
||||
ele.y = parseFloat(eles[i].style.top)/hh*100;
|
||||
|
||||
try {
|
||||
ele.slot = parseInt(eles[i].slot) || i;
|
||||
ele.cover = eles[i].cover || false;
|
||||
if ("slot" in eles[i]){
|
||||
ele.slot = parseInt(eles[i].slot);
|
||||
}
|
||||
if ("cover" in eles[i]){
|
||||
ele.cover = eles[i].cover || false;
|
||||
} else {
|
||||
ele.cover = true;
|
||||
}
|
||||
ele.zIndex = parseInt(eles[i].zIndex) || 0;
|
||||
|
||||
//ele.backgroundColor = eles[i].backgroundColor || "#000";
|
||||
@ -3054,11 +3149,14 @@
|
||||
saveSession();
|
||||
}
|
||||
|
||||
function saveSession(){
|
||||
function saveSession(){
|
||||
var layouts = document.querySelectorAll(".canvasContainer>canvas");
|
||||
savedSession.layouts = [];
|
||||
savedSession.settings = {};
|
||||
savedSession.settings.updateOnSlotChange = updateOnSlotChange;
|
||||
savedSession.settings.assignSlotToGuest = assignSlotToGuest;
|
||||
savedSession.settings.toggleLabel = toggleLabel;
|
||||
savedSession.settings.toggleBroadcast = toggleBroadcast;
|
||||
savedSession.version = 1;
|
||||
|
||||
for (var i=0;i<layouts.length;i++){
|
||||
@ -3070,6 +3168,10 @@
|
||||
}
|
||||
}
|
||||
setStorage("savedSession", JSON.stringify(savedSession));
|
||||
|
||||
if (iframe){
|
||||
iframe.contentWindow.postMessage({ layouts: savedSession.layouts }, "*");
|
||||
}
|
||||
console.log(getStorage("savedSession"));
|
||||
}
|
||||
|
||||
@ -3083,25 +3185,21 @@
|
||||
document.documentElement.style.setProperty('--aspect-ratio', ar);
|
||||
}
|
||||
|
||||
let modal = document.querySelector("#modal");
|
||||
let closeBtn = document.querySelector(".close-btn");
|
||||
closeBtn.onclick = function(){
|
||||
document.getElementById("modal-content").innerHTML = "";
|
||||
modal.style.display = "none";
|
||||
}
|
||||
window.onclick = function(e){
|
||||
if (e.target == modal){
|
||||
document.getElementById("modal-content").innerHTML = "";
|
||||
modal.style.display = "none";
|
||||
//let modal = document.querySelector("#modal");
|
||||
document.querySelectorAll(".close-btn").forEach(ele2=>{
|
||||
ele2.onclick = function(){
|
||||
document.querySelectorAll(".modal").forEach(ele=>{
|
||||
ele.classList.add("hidden");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
modal.onclick = function(e){
|
||||
if (e.target == modal){
|
||||
document.getElementById("modal-content").innerHTML = "";
|
||||
modal.style.display = "none";
|
||||
});
|
||||
document.querySelectorAll(".modal").forEach(ele=>{
|
||||
ele.onclick = function(e){
|
||||
if (e.target.classList.contains("modal")){
|
||||
e.target.classList.add("hidden");
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (roomname){
|
||||
loadIframe();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user