mirror of
https://github.com/eliasstepanik/vdo.ninja.git
synced 2026-01-11 21:58:35 +00:00
commit
a04a37fd5f
@ -163,7 +163,7 @@ function generateInvite(){
|
||||
var href = window.location.href;
|
||||
var dir = href.substring(0, href.lastIndexOf('/')) + "/";
|
||||
|
||||
var salt = location.hostname; // "obs.ninja" is the expected default. You will want to change this if hosting dock.html locally.
|
||||
var salt = location.hostname; // "vdo.ninja" is the expected default. You will want to change this if hosting dock.html locally.
|
||||
|
||||
if (getById("invite_password").value.trim().length){
|
||||
generateHash(getById("invite_password").value.trim().replace(/[\W]+/g,"_")+salt,4).then(function(hash){
|
||||
|
||||
162
examples/chatoverlay.html
Normal file
162
examples/chatoverlay.html
Normal file
@ -0,0 +1,162 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>OBSN Chat Overlay</title>
|
||||
<style>
|
||||
|
||||
@font-face {
|
||||
font-family: 'Cousine';
|
||||
src: url('fonts/Cousine-Bold.ttf') format('truetype');
|
||||
}
|
||||
|
||||
body {
|
||||
margin:0;
|
||||
padding:0 10px;
|
||||
height:100%;
|
||||
border: 0;
|
||||
display: flex;
|
||||
flex-direction: column-reverse;
|
||||
position:absolute;
|
||||
bottom:0;
|
||||
overflow:hidden;
|
||||
max-width:100%;
|
||||
}
|
||||
|
||||
div {
|
||||
margin:0;
|
||||
background-color: black;
|
||||
padding: 8px 8px 0px 8px;
|
||||
color: white;
|
||||
font-family: Cousine, monospace;
|
||||
font-size: 3.2em;
|
||||
line-height: 1.1em;
|
||||
letter-spacing: 0.0em;
|
||||
text-transform: uppercase;
|
||||
text-shadow: 0.05em 0.05em 0px rgba(0,0,0,1);
|
||||
max-width:100%;
|
||||
word-wrap: break-word;
|
||||
overflow-wrap: break-word;
|
||||
word-break: break-all;
|
||||
hyphens: auto;
|
||||
display:inline-block;
|
||||
}
|
||||
|
||||
|
||||
|
||||
a {
|
||||
color:white;
|
||||
font-size:1.2em;
|
||||
text-transform: none;
|
||||
word-wrap: break-word;
|
||||
overflow-wrap: break-word;
|
||||
word-wrap: break-word;
|
||||
word-break: break-all;
|
||||
hyphens: auto;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
|
||||
|
||||
(function (w) {
|
||||
w.URLSearchParams =
|
||||
w.URLSearchParams ||
|
||||
function (searchString) {
|
||||
var self = this;
|
||||
self.searchString = searchString;
|
||||
self.get = function (name) {
|
||||
var results = new RegExp("[\?&]" + name + "=([^&#]*)").exec(
|
||||
self.searchString
|
||||
);
|
||||
if (results == null) {
|
||||
return null;
|
||||
} else {
|
||||
return decodeURI(results[1]) || 0;
|
||||
}
|
||||
};
|
||||
};
|
||||
})(window);
|
||||
var urlParams = new URLSearchParams(window.location.search);
|
||||
|
||||
|
||||
function loadIframe() {
|
||||
|
||||
var iframe = document.createElement("iframe");
|
||||
|
||||
var view= "";
|
||||
var room="";
|
||||
var password="";
|
||||
if (urlParams.has("view")) {
|
||||
view = "&view="+(urlParams.get("view") || "");
|
||||
} else if (urlParams.has("room")) {
|
||||
room = "&room="+urlParams.get("room");
|
||||
} else {
|
||||
var help = document.createElement("h2");
|
||||
help.innerHTML = "This app supports <i>&room, &view, </i>and<i> &password</i> URL parameters.";
|
||||
document.body.appendChild(help);
|
||||
return;
|
||||
}
|
||||
if (urlParams.has("password")) {
|
||||
password = "&password="+urlParams.get("password");
|
||||
}
|
||||
|
||||
iframe.allow = "autoplay";
|
||||
var srcString = "../?datamode&label=chatOverlay&scene"+room+view+password;
|
||||
|
||||
iframe.src = srcString;
|
||||
iframe.style.width="0";
|
||||
iframe.style.height="0";
|
||||
iframe.style.border="0";
|
||||
|
||||
document.body.appendChild(iframe);
|
||||
|
||||
//////////// LISTEN FOR EVENTS
|
||||
|
||||
var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
|
||||
var eventer = window[eventMethod];
|
||||
var messageEvent = eventMethod === "attachEvent" ? "onmessage" : "message";
|
||||
|
||||
|
||||
/// If you have a routing system setup, you could have just one global listener for all iframes instead.
|
||||
|
||||
eventer(messageEvent, function (e) {
|
||||
if (e.source != iframe.contentWindow){return} // reject messages send from other iframes
|
||||
|
||||
console.log(e);
|
||||
if ("gotChat" in e.data){
|
||||
logData(e.data.gotChat.label,e.data.gotChat.msg);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function printValues(obj) {
|
||||
var out = "";
|
||||
for (var key in obj) {
|
||||
if (typeof obj[key] === "object") {
|
||||
out += "<br />";
|
||||
out += printValues(obj[key]);
|
||||
} else {
|
||||
if (key.startsWith("_")) {
|
||||
} else {
|
||||
out += "<b>" + key + "</b>: " + obj[key] + "<br />";
|
||||
}
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
function logData(type, data) {
|
||||
var span = document.createElement('span');
|
||||
var entry = document.createElement('div');
|
||||
if (type){
|
||||
type = "<i>"+type.replace(/_/g, ' ')+"</i>";
|
||||
}
|
||||
entry.innerHTML = type + data;
|
||||
span.appendChild(entry);
|
||||
document.body.prepend(span);
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body onload="loadIframe();">
|
||||
</body>
|
||||
</html>
|
||||
@ -77,6 +77,11 @@
|
||||
<div class="description">How to have a twitch live chat side-by-side with VDO.NInja on the same
|
||||
screen</div>
|
||||
</div>
|
||||
<div>
|
||||
<h2><a href='youtube.html'>youtube</a></h2>
|
||||
<div class="description">How to have a youtube live chat side-by-side with VDO.NInja on the same
|
||||
screen</div>
|
||||
</div>
|
||||
<div>
|
||||
<h2><a href='dual.html'>dual</a></h2>
|
||||
<div class="description">how to have two VDO.Ninja windows (or any windows really) open on the same
|
||||
@ -112,7 +117,7 @@
|
||||
layout of elements. (experimental)</div>
|
||||
</div>
|
||||
<div>
|
||||
<h2><a href='chat.html'>chat</a></h2>
|
||||
<h2><a href='chatoverlay.html'>chat</a></h2>
|
||||
<div class="description">Example of a chat-only interface for VDO.Ninja; maybe
|
||||
dockable into OBS even.</div>
|
||||
</div>
|
||||
|
||||
@ -64,7 +64,7 @@ input{
|
||||
<div id="container2"></div>
|
||||
<div id="container1" ></div>
|
||||
<div id="clean">
|
||||
<input placeholder="Enter a VDON stream ID" id="viewlink" type="text" />
|
||||
<input placeholder="Enter a VDON stream ID or VDON URL" id="viewlink" type="text" />
|
||||
<input placeholder="Enter the Twitch channel name" id="twitch" type="text" />
|
||||
<button onclick="loadIframes()" style="display:block;padding:10px;margin:10px;">START</button>
|
||||
</div>
|
||||
@ -85,8 +85,13 @@ function loadIframes(url=false){
|
||||
document.getElementById("container2").style.display="inline-block";
|
||||
|
||||
var path = window.location.host+window.location.pathname.split("/").slice(0,-1).join("/");
|
||||
path = path.replace("/examples","");
|
||||
|
||||
var room1 = "https://"+path+"/?push="+roomname+"&webcam&autostart&vd=front&ad=1&transparent&noheader";
|
||||
if (roomname.startsWith("https://")){
|
||||
var room1 = roomname;
|
||||
} else {
|
||||
var room1 = "https://"+path+"/?push="+roomname+"&webcam&autostart&vd=front&ad=1&transparent&noheader";
|
||||
}
|
||||
var room2 = "https://www.twitch.tv/embed/"+twitch+"/chat?parent="+location.hostname;
|
||||
var iframe = document.createElement("iframe");
|
||||
iframe.allow = "autoplay;camera;microphone;fullscreen;picture-in-picture;";
|
||||
|
||||
129
examples/youtube.html
Normal file
129
examples/youtube.html
Normal file
@ -0,0 +1,129 @@
|
||||
<html>
|
||||
<head><title>YouTube Chat + VDON</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;
|
||||
font-family: arial;
|
||||
}
|
||||
|
||||
iframe {
|
||||
width:100%;
|
||||
height:100%;
|
||||
border:0;
|
||||
margin:0;
|
||||
padding:0;
|
||||
position:absolute;
|
||||
display:block;
|
||||
}
|
||||
|
||||
|
||||
input{
|
||||
padding:10px;
|
||||
width:80%;
|
||||
font-size:1.2em;
|
||||
z-index: 1000;
|
||||
color:black;
|
||||
}
|
||||
|
||||
|
||||
@media screen and (orientation:portrait) {
|
||||
#container2{
|
||||
width:100%;height:100%;display:none;
|
||||
}
|
||||
#container1{
|
||||
width: 50vw;height: 50vh; display:none; float:left; position: fixed; top: 0; right: 0%;
|
||||
}
|
||||
iframe{
|
||||
width:100%;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (orientation:landscape) {
|
||||
#container2{
|
||||
width:60vw;height:100%;display:none;
|
||||
z-index:5;
|
||||
}
|
||||
#container1{
|
||||
width: 50vw;height: 80vh; display:none; float:left; position: fixed; top: 0; right: -10vw;
|
||||
}
|
||||
iframe{
|
||||
max-width:60vw;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
||||
|
||||
<div id="container2"></div>
|
||||
<div id="container1" ></div>
|
||||
<div id="clean">
|
||||
<input placeholder="Enter a VDON stream ID" id="vdonlink" onchange="updateLink(event);" type="text" />
|
||||
<input placeholder="Enter the Youtube Video ID" id="youtube" type="text" />
|
||||
<button onclick="loadIframes()" style="display:block;padding:10px;margin:10px;">START</button>
|
||||
<div id="viewLink">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
|
||||
window.addEventListener("orientationchange", function() {
|
||||
// Announce the new orientation number
|
||||
// alert(window.orientation);
|
||||
}, false);
|
||||
|
||||
function updateLink(event){
|
||||
var streamid = document.getElementById("vdonlink").value;
|
||||
|
||||
|
||||
var path = window.location.host+window.location.pathname.split("/").slice(0,-1).join("/");
|
||||
path = path.replace("/examples","");
|
||||
|
||||
var viewLink = "https://"+path+"/?view="+streamid;
|
||||
document.getElementById("viewLink").innerHTML = "View link is: "+viewLink;
|
||||
}
|
||||
|
||||
function loadIframes(url=false){
|
||||
|
||||
var streamid = document.getElementById("vdonlink").value;
|
||||
var youtube = document.getElementById("youtube").value;
|
||||
|
||||
document.getElementById("clean").parentNode.removeChild(document.getElementById("clean"));
|
||||
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("/");
|
||||
path = path.replace("/examples","");
|
||||
|
||||
var room1 = "https://"+path+"/?push="+streamid+"&webcam&autostart&vd=front&ad=1&transparent&noheader";
|
||||
var room2 = "https://www.youtube.com/live_chat?is_popout=1&v="+youtube+"&embed_domain="+location.hostname;
|
||||
var iframe = document.createElement("iframe");
|
||||
iframe.allow = "autoplay;camera;microphone;fullscreen;picture-in-picture;";
|
||||
iframe.src = room1;
|
||||
var iframeContainer = document.createElement("div");
|
||||
iframeContainer.appendChild(iframe);
|
||||
document.getElementById("container1").appendChild(iframeContainer);
|
||||
|
||||
setTimeout(function(){
|
||||
var iframe = document.createElement("iframe");
|
||||
iframe.allow = "autoplay;camera;microphone;fullscreen;picture-in-picture;";
|
||||
iframe.src = room2;
|
||||
var iframeContainer = document.createElement("div");
|
||||
iframeContainer.appendChild(iframe);
|
||||
document.getElementById("container2").appendChild(iframeContainer);
|
||||
},3000);
|
||||
|
||||
}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
27
index.html
27
index.html
@ -79,7 +79,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=368"></script>
|
||||
<script type="text/javascript" crossorigin="anonymous" src="./webrtc.js?ver=396"></script>
|
||||
<input id="zoomSlider" type="range" style="display: none;" />
|
||||
<div id="header">
|
||||
|
||||
@ -149,7 +149,7 @@
|
||||
<div id="mutespeakerbutton" onmousedown="event.preventDefault(); event.stopPropagation();" title="Mute the Speaker" onclick="toggleSpeakerMute()" tabindex="17" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="advanced float" style="cursor: pointer;" alt="Toggle the speaker output.">
|
||||
<i id="mutespeakertoggle" class="toggleSize las la-volume-up my-float" style="position: relative; top: 0.5px;"></i>
|
||||
</div>
|
||||
<div id="mutebutton" onmousedown="event.preventDefault(); event.stopPropagation();" title="Mute the Mic" onclick="toggleMute()" tabindex="18" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="advanced float" style="cursor: pointer;" alt="Toggle the mic">
|
||||
<div id="mutebutton" onmousedown="toggleMute(false, event);event.preventDefault(); event.stopPropagation();" title="Mute the Mic" ontouchstart="toggleMute(false, event);event.preventDefault(); event.stopPropagation();" tabindex="18" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="advanced float" style="cursor: pointer;" alt="Toggle the mic">
|
||||
<i id="mutetoggle" class="toggleSize las la-microphone my-float" style="position: relative; top: 0.5px;"></i>
|
||||
</div>
|
||||
<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="advanced float" style="cursor: pointer;">
|
||||
@ -272,7 +272,7 @@
|
||||
<span data-translate="password-input-field">Password</span>:
|
||||
</b>
|
||||
</div>
|
||||
<input type="text" autocorrect="off" autocapitalize="none" id="passwordRoom" placeholder="Optional room password here" onkeydown="checkStrengthRoom(event, 'securityLevelRoom');" onchange="checkStrengthRoom(event, 'securityLevelRoom');" onkeyup="enterPressed(event, createRoom);" maxlength="50" style="max-width: 431px;width: 100%;font-size: 110%; padding: 5px;" />
|
||||
<input type="text" autocorrect="off" autocapitalize="none" id="passwordRoom" placeholder="Optional room password here" onkeydown="checkStrengthRoom(event, 'securityLevelRoom');" onchange="checkStrengthRoom(event, 'securityLevelRoom');" onkeyup="enterPressed(event, createRoom);" style="max-width: 431px;width: 100%;font-size: 110%; padding: 5px;" />
|
||||
</th>
|
||||
|
||||
</tr><tr >
|
||||
@ -704,13 +704,13 @@
|
||||
<h1>Warning</h1>
|
||||
<p>Media file streaming is still quite experimental. Please do not rely on it heavily for your productions. Feedback welcome.</p>
|
||||
</div>
|
||||
<div class='warning message-card'>
|
||||
<h1>Chrome users</h1>
|
||||
<p>Keep this tab visible if using Chrome, else the video playback will stop</p>
|
||||
<div class='warning message-card advanced' id='chrome_warning_fileshare'>
|
||||
<h1>Chrome/Edge users</h1>
|
||||
<p>Keep this tab visible, else the video playback will stop</p>
|
||||
</div>
|
||||
<div class='info message-card'>
|
||||
<h1>File Sharing seems to be broken on Chrome v88.</h1>
|
||||
<p>Try <a href="https://github.com/aws/amazon-chime-sdk-js/issues/1031">turning off hardware-accleration</a> in Chrome/Edge to fix the issue, or maybe use a different browser.</p>
|
||||
<div class='warning message-card advanced' id='safari_warning_fileshare'>
|
||||
<h1>Safari Users</h1>
|
||||
<p>Safari does not support this feature. Consider Chrome or Firefox instead.</p>
|
||||
</div>
|
||||
<br /><br />
|
||||
To host a file for download, rather than for streaming, try the following instead:
|
||||
@ -1863,7 +1863,7 @@
|
||||
<source src="./media/tone.mp3" type="audio/mpeg">
|
||||
<source src="./media/tone.ogg" type="audio/ogg">
|
||||
</audio>
|
||||
<div class="gone" >
|
||||
<div class="gone advanced" >
|
||||
<!-- This image is used when dragging elements -->
|
||||
<img src="./media/favicon-32x32.png" id="dragImage" loading="lazy" />
|
||||
</div>
|
||||
@ -1928,7 +1928,7 @@
|
||||
|
||||
|
||||
var session = WebRTC.Media; // session is a required global variable if configuring manually. Run before loading main.js but after webrtc.js.
|
||||
session.version = "21.1";
|
||||
session.version = "21.3";
|
||||
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
|
||||
@ -1992,13 +1992,14 @@
|
||||
// session.title // "zzzz" ; sets the title of the browser page.
|
||||
// session.introOnClean = true; // this will load the page with the webcam selection screen if &push or &room is in the URL; no need to use &webcam.
|
||||
// session.lowBitrateCutoff = 300; // Set a minimum bitrate (in kbps) before the stream is hidden. Useful for IRL streams maybe
|
||||
// session.apiserver = "wss://api.vdo.ninja:443"; // specifiy a custom websocket API URL.
|
||||
</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=264"></script>
|
||||
<script type="text/javascript" crossorigin="anonymous" id="lib-js" src="./lib.js?ver=279"></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=302"></script>
|
||||
<script type="text/javascript" crossorigin="anonymous" id="main-js" src="./main.js?ver=313"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
75
main.js
75
main.js
@ -414,6 +414,17 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
} else if (urlParams.has('forceportrait') || urlParams.has('forcedportrait')|| urlParams.has('fp')){
|
||||
session.orientation = "portrait";
|
||||
}
|
||||
|
||||
if (session.orientation && session.mobile){
|
||||
document.addEventListener('fullscreenchange', event => {
|
||||
|
||||
if (document.fullscreenElement) {
|
||||
document.exitFullscreen();
|
||||
}
|
||||
alert(JSON.stringify(event));
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
if (urlParams.has('midi') || urlParams.has('hotkeys')) {
|
||||
session.midiHotkeys = urlParams.get('midi') || urlParams.get ('hotkeys') || 1;
|
||||
@ -486,6 +497,13 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
getById("container-5").classList.remove('advanced');
|
||||
getById("container-5").classList.add("skip-animation");
|
||||
getById("container-5").classList.remove('pointer');
|
||||
|
||||
if (SafariVersion){
|
||||
getById("safari_warning_fileshare").classList.remove('advanced');
|
||||
} else if (!Firefox){
|
||||
getById("chrome_warning_fileshare").classList.remove('advanced');
|
||||
}
|
||||
|
||||
} else if (directorLanding) {
|
||||
getById("container-1").classList.remove('advanced');
|
||||
getById("container-1").classList.add("skip-animation");
|
||||
@ -888,13 +906,14 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
session.showlabels = urlParams.get('showlabels') || urlParams.get('showlabel') || urlParams.get('sl') || "";
|
||||
session.showlabels = sanitizeLabel(session.showlabels.replace(/[\W]+/g, "_").replace(/_+/g, '_'));
|
||||
//session.style = 6;
|
||||
session.showlabels = true;
|
||||
|
||||
if (session.showlabels == "") {
|
||||
session.labelstyle = false;
|
||||
} else {
|
||||
session.labelstyle = session.showlabels;
|
||||
}
|
||||
|
||||
session.showlabels = true;
|
||||
}
|
||||
|
||||
if (urlParams.has('sizelabel') || urlParams.has('labelsize') || urlParams.has('fontsize')) {
|
||||
@ -1032,8 +1051,8 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
|
||||
// Deploy your own handshake server for free; see: https://github.com/steveseguin/websocket_server
|
||||
if (urlParams.has('pie')){ // piesocket.com support is to be deprecated after dec/19/21, since piesocket is no longer a free service.
|
||||
session.customWSS = urlParams.get('pie') || false; // If session.customWSS == true, then there is no need to set parameters via URL
|
||||
if (session.customWSS){
|
||||
session.customWSS = urlParams.get('pie') || true; // If session.customWSS == true, then there is no need to set parameters via URL
|
||||
if (session.customWSS && (session.customWSS!==true)){
|
||||
session.wss = "wss://free3.piesocket.com/v3/1?api_key="+session.customWSS; // if URL param is set, it will use the API key.
|
||||
}
|
||||
}
|
||||
@ -2603,6 +2622,7 @@ 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');
|
||||
}
|
||||
@ -4057,7 +4077,8 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
});
|
||||
|
||||
document.addEventListener("keydown", event => {
|
||||
|
||||
|
||||
|
||||
if ((event.ctrlKey) || (event.metaKey)) { // detect if CTRL is pressed
|
||||
CtrlPressed = true;
|
||||
} else {
|
||||
@ -4069,19 +4090,29 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
AltPressed = false;
|
||||
}
|
||||
|
||||
if (KeyPressedTimeout){
|
||||
event.preventDefault(); event.stopPropagation();
|
||||
return;
|
||||
}
|
||||
|
||||
if (CtrlPressed && event.keyCode) {
|
||||
|
||||
if (event.keyCode == 77) { // M
|
||||
if (event.metaKey) {
|
||||
if (AltPressed) {
|
||||
toggleMute(); // macOS
|
||||
if (!KeyPressedTimeout){
|
||||
toggleMute(); // macOS
|
||||
KeyPressedTimeout = Date.now();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
toggleMute(); // Windows
|
||||
if (!KeyPressedTimeout){
|
||||
toggleMute(); // Windows
|
||||
KeyPressedTimeout = Date.now();
|
||||
}
|
||||
}
|
||||
// } else if (event.keyCode == 69) { // E
|
||||
// hangup();
|
||||
|
||||
|
||||
} else if (event.keyCode == 66) { // B
|
||||
toggleVideoMute();
|
||||
}
|
||||
@ -4099,7 +4130,8 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
});
|
||||
|
||||
document.addEventListener("keyup", event => {
|
||||
if (!((event.ctrlKey) || (event.metaKey))) {
|
||||
|
||||
if (!(event.ctrlKey || event.metaKey)) {
|
||||
if (CtrlPressed) {
|
||||
CtrlPressed = false;
|
||||
for (var i in Callbacks) {
|
||||
@ -4117,19 +4149,40 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
if (event.altKey && event.shiftKey && event.keyCode === 67 /* C */) {
|
||||
toggleControlBar();
|
||||
}
|
||||
|
||||
if (KeyPressedTimeout && ((event.keyCode == 77) || (!(event.ctrlKey || event.metaKey)))) {
|
||||
if (Date.now() - KeyPressedTimeout>300){
|
||||
toggleMute();
|
||||
}
|
||||
if (event.keyCode == 77){
|
||||
KeyPressedTimeout = 0;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
main(); // asyncronous load
|
||||
|
||||
try {
|
||||
navigator.serviceWorker.getRegistrations().then(registrations => { // getting rid of old service workers.
|
||||
try {
|
||||
log(registrations);
|
||||
for(let registration of registrations) {
|
||||
if (registration.scope != "https://"+window.location.hostname+window.location.pathname+"thirdparty/"){
|
||||
registration.unregister();
|
||||
}
|
||||
}
|
||||
} catch(e){}
|
||||
}).catch(errorlog);
|
||||
} catch(e){}
|
||||
|
||||
setTimeout(function(){ // lazy load
|
||||
var script = document.createElement('script');
|
||||
document.head.appendChild(script);
|
||||
script.onload = function() {
|
||||
var script = document.createElement('script');
|
||||
document.head.appendChild(script);
|
||||
script.src = "./thirdparty/StreamSaver.js?v=9"; // dynamically load this only if its needed. Keeps loading time down.
|
||||
script.src = "./thirdparty/StreamSaver.js?v=10"; // dynamically load this only if its needed. Keeps loading time down.
|
||||
};
|
||||
script.src = "./thirdparty/polyfill.min.js"; // dynamically load this only if its needed. Keeps loading time down.
|
||||
},0);
|
||||
55
mixer.html
55
mixer.html
@ -96,6 +96,43 @@
|
||||
ev.preventDefault();
|
||||
}
|
||||
|
||||
(function(w) {
|
||||
w.URLSearchParams = w.URLSearchParams || function(searchString) {
|
||||
var self = this;
|
||||
searchString = searchString.replace("??", "?");
|
||||
self.searchString = searchString;
|
||||
self.get = function(name) {
|
||||
var results = new RegExp('[\?&]' + name + '=([^&#]*)').exec(self.searchString);
|
||||
if (results == null) {
|
||||
return null;
|
||||
} else {
|
||||
return decodeURI(results[1]) || 0;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
})(window);
|
||||
|
||||
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 password = false;
|
||||
if (urlParams.has("password")){
|
||||
password = urlParams.get("password");
|
||||
}
|
||||
|
||||
var roomname = false;
|
||||
if (urlParams.has("room") || urlParams.has("dir") || urlParams.has("director")){
|
||||
roomname = urlParams.get("room") || urlParams.get("dir") || urlParams.get("director");
|
||||
}
|
||||
|
||||
function swapNodes(n1, n2) {
|
||||
var p1 = n1.parentNode;
|
||||
var p2 = n2.parentNode;
|
||||
@ -256,12 +293,20 @@
|
||||
var iframeContainer = document.createElement("div");
|
||||
iframe.allow = "autoplay;camera;microphone;fullscreen;picture-in-picture;display-capture;";
|
||||
|
||||
var promptRoom = prompt("Enter a room name to use");
|
||||
var additional = "";
|
||||
if (password){
|
||||
additional = "&password="+password;
|
||||
}
|
||||
if (roomname){
|
||||
var promptRoom = roomname;
|
||||
} else {
|
||||
var promptRoom = prompt("Enter a room name to use");
|
||||
}
|
||||
if (promptRoom){
|
||||
var iframesrc = "./?transparent&cleanoutput&director="+promptRoom;
|
||||
var iframesrc = "./?transparent&cleanoutput&director="+promptRoom+additional;
|
||||
} else {
|
||||
promptRoom = "testroom123312";
|
||||
var iframesrc = "./?transparent&cleanoutput&director="+promptRoom;
|
||||
var iframesrc = "./?transparent&cleanoutput&director="+promptRoom+additional;
|
||||
}
|
||||
|
||||
function remoteActivate(){
|
||||
@ -303,13 +348,13 @@
|
||||
|
||||
var a = document.createElement("a");
|
||||
a.innerHTML = "Invite Guest Link";
|
||||
a.href = "./?room="+promptRoom+"&broadcast";
|
||||
a.href = "./?room="+promptRoom+"&broadcast"+additional;
|
||||
a.target = "_blank";
|
||||
document.getElementById("sources").appendChild(a);
|
||||
|
||||
var a = document.createElement("a");
|
||||
a.innerHTML = "Scene View Link";
|
||||
a.href = "./?scene=0&room="+promptRoom;
|
||||
a.href = "./?scene=0&room="+promptRoom+additional;
|
||||
a.target = "_blank";
|
||||
document.getElementById("sources").appendChild(a);
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user