mirror of
https://github.com/eliasstepanik/vdo.ninja.git
synced 2026-01-10 21:28:34 +00:00
fixes, features, and darkmode=true fix
This commit is contained in:
parent
70262002db
commit
7ee9653dfd
94
index.html
94
index.html
@ -56,7 +56,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=335" />
|
||||
<link rel="stylesheet" href="./main.css?ver=342" />
|
||||
<script type="text/javascript" crossorigin="anonymous" src="./thirdparty/adapter.js"></script>
|
||||
<style id="lightbox-animations" type="text/css"></style>
|
||||
<!-- <link rel="manifest" href="manifest.json" /> -->
|
||||
@ -83,7 +83,7 @@
|
||||
|
||||
<script type="text/javascript" crossorigin="anonymous" src="./thirdparty/CodecsHandler.js?ver=47"></script>
|
||||
<script type="text/javascript" crossorigin="anonymous" src="./thirdparty/aes.js"></script>
|
||||
<script type="text/javascript" crossorigin="anonymous" src="./webrtc.js?ver=645"></script>
|
||||
<script type="text/javascript" crossorigin="anonymous" src="./webrtc.js?ver=662"></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">
|
||||
@ -144,6 +144,7 @@
|
||||
</div>
|
||||
<input type="text" id="chatInput" placeholder="Enter chat message to send here" onkeypress="EnterButtonChat(event)" />
|
||||
<button class="chatBarInputButton" onclick="sendChatMessage()" data-translate='send-chat'>Send</button>
|
||||
<button onclick="toggleFileshare()" data-translate='upload-chat'><i class="las la-file-upload"></i> Upload File</button>
|
||||
</div>
|
||||
<div id="subControlButtons">
|
||||
|
||||
@ -186,7 +187,7 @@
|
||||
</div>
|
||||
<div id="websitesharebutton2" onmousedown="event.preventDefault(); event.stopPropagation();" title="Hold CTRL (or CMD) and click to spotlight this video" alt="Share a website as an embedded iFRAME" aria-label="Share a website" onclick="shareWebsite(false, event)" tabindex="21" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="float2 orange shake hidden" style="cursor: pointer;max-width: 200px;margin: auto;padding: 0 10px;">
|
||||
<i onmousedown="event.preventDefault(); event.stopPropagation();" class="toggleSize las la-window-close" style="display: inline-block;"></i>
|
||||
<div style="display: inline-block;width: 85px;line-height: 1; font-size: 0.9em;">
|
||||
<div style="display: inline-block;width: 85px;line-height: 1; font-size: 0.9em; background-color: unset;box-shadow: unset;">
|
||||
Stop Sharing Website
|
||||
</div>
|
||||
</div>
|
||||
@ -356,7 +357,7 @@
|
||||
</table>
|
||||
|
||||
<span style="margin: 0 auto; width: 470px; max-width:100%;display: block;">
|
||||
<button onclick="createRoom()" class="gobutton" style="width:100%;" alt="Enter the room as the group's director" title="You'll enter as the room's director">
|
||||
<button onclick="createRoom()" class="gobutton gowebcam" style="width:100%;" alt="Enter the room as the group's director" title="You'll enter as the room's director">
|
||||
<span data-translate="enter-the-rooms-control">Enter the room's Control Center in the director's role</span>
|
||||
</button>
|
||||
<br />
|
||||
@ -379,7 +380,7 @@
|
||||
<i data-translate="looking-to-just-chat-and-not-direct">Looking to just chat and not direct?</i>
|
||||
<br />
|
||||
<br />
|
||||
<button onclick="jumptoroom2()" class="gobutton" style="width:100%;" alt="Enter the room as the group's director" title="You'll enter as the room's director">
|
||||
<button onclick="jumptoroom2()" class="gobutton gowebcam" style="width:100%;" alt="Enter the room as the group's director" title="You'll enter as the room's director">
|
||||
<span data-translate="join-the-room-basic">Join the room as a Participant, rather than a director</span>
|
||||
</button>
|
||||
</span>
|
||||
@ -555,6 +556,11 @@
|
||||
Safari is more prone to having audio issues</span></p>
|
||||
</div>
|
||||
|
||||
<div id="oldiOSWarning" class="startupWarning hidden">
|
||||
<i class="las la-exclamation-circle"></i>
|
||||
<p><span data-translate="update-your-device">We've detected that you are using an old version of Apple iOS, which is known to have many issues.<br /><br />Please consider updating.</span></p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="outer close">
|
||||
<div class="inner">
|
||||
@ -894,6 +900,36 @@
|
||||
<i style="margin-top:30px;font-size:600%;overflow:hidden;" class="largeDarkIcon las la-heartbeat"></i>
|
||||
</div>
|
||||
|
||||
<div id="container-16" class="column columnfade pointer rounded card hidden" style=" overflow-y: auto;">
|
||||
<h2><span data-translate="share-whepsrc">Share WHEP Media Source</span></h2>
|
||||
<i style="margin-top:30px;font-size:560%;overflow:hidden;" class="largeDarkIcon las la-broadcast-tower"></i>
|
||||
<div class="container-inner">
|
||||
<br />
|
||||
<div id="previewWhepSource"></div>
|
||||
<br />
|
||||
<span data-translate="enter-the-whep-URL-you-wish-to-share">Enter the WHEP URL you wish to share.</span><br /><br />
|
||||
<input type="text" autocorrect="off" id="whepURL" autocapitalize="none" style="margin:10px; border:2px solid; padding:10px; width:400px;" title="Enter an HTTPS URL" multiple/><br />
|
||||
<button onclick="previewIframe(getById('whepURL').value);" >Preview WHEP Stream</button>
|
||||
<button onclick="this.innerHTML = 'Update'; session.publishIFrame(getById('iframeURL').value);" >Start Sharing</button><br />
|
||||
<div class="message-card info">
|
||||
<h1>Usage information</h1>
|
||||
<p></p>
|
||||
<ul style="text-align: left;">
|
||||
<li>WHEP sources are expected to support multiple viewers; simulcasting will be used if possible.</li>
|
||||
<li>Remote URLs must allows cross-origin requests (CORS), along with having SSL (https).</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="outer close">
|
||||
<div class="inner">
|
||||
<label class="labelclass">
|
||||
<span data-translate="back">Back</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<p></p>
|
||||
<div id="info" class="fullcolumn columnfade">
|
||||
<center>
|
||||
@ -1007,7 +1043,7 @@
|
||||
<div class='directorBlock' style="background-color: var(--green-accent);" >
|
||||
<h2 title="Use this link in the OBS Browser Source to capture the video or audio" style="margin-left: 1px;margin-top: 5px;"><i class="las la-th-large director-link-icons" style="margin-right: 6px;" ></i> <span data-translate="capture-a-group-scene">CAPTURE A GROUP SCENE</span></h2>
|
||||
<span style="margin:5px; line-height: 1.6;" data-translate='this-is-obs-browser-source-link'>Use in OBS or other studio software to capture the group video mix</span>
|
||||
<a onclick='copyFunction(this,event)' data-drag="1" draggable="true" id="director_block_3" data-menu="context-menu" class='task grabLinks' style='cursor:grab;background-color: #0003;'></a>
|
||||
<a onclick='copyFunction(this,event)' data-drag="1" draggable="true" id="director_block_3" data-menu="context-menu" class='task grabLinks publish' style='cursor:grab;background-color: #0003;'></a>
|
||||
<span style="display:block;">
|
||||
<span style="bottom: 0; margin: 0 0 0 10px; top: 22px; position: relative; display:inline-block; max-width: 45%;">
|
||||
<label class="switch" title="If disabled, you must manually add a video to a scene for it to appear.">
|
||||
@ -1562,6 +1598,11 @@
|
||||
<i class="las la-file-upload"></i>
|
||||
<span data-translate="mirror-guest"> Mirror Video</span>
|
||||
</button>
|
||||
|
||||
<button class="mainonly advanced" data-action-type="force-keyframe" style=" background-image: linear-gradient(90deg, #C9F0FF 0%, #FFDFB9 39%, #FFDFDF 70%, #D9FFEC 100%);" title="Force the remote sender to issue a keyframe to all scenes, fixing Pixel Smearing issues." onclick="requestKeyframeScene(this);">
|
||||
<span data-translate="force-keyframe"> Rainbow Puke Fix</span>
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Row of Channels -->
|
||||
@ -1815,7 +1856,7 @@
|
||||
|
||||
</div>
|
||||
<div id="selectEffectAmount3" style="display:none;margin-top:10px;">
|
||||
<label for="selectEffectAmountInput" style="width: 113px;display: inline-block;">Effect amount:</label>
|
||||
<label for="selectEffectAmountInput3" style="width: 113px;display: inline-block;">Effect amount:</label>
|
||||
<input id="selectEffectAmountInput3" style="display: inline-block;width: 350px; max-width: 60%;margin:6px 0;" name="selectEffectAmountInput3" title="Adjust the amount of effect applied" type="range" oninput="changeEffectAmount(event, this)" onchange="changeEffectAmount(event, this)" min="0" step="1" max="20">
|
||||
</div>
|
||||
|
||||
@ -1897,6 +1938,12 @@
|
||||
<span data-translate="edit-url" >Edit URL manually</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="context-menu__item hidden">
|
||||
<a href="#" class="context-menu__link" data-action="Publish">
|
||||
<i class="las la-tv"></i>
|
||||
<span data-translate="publish-url" >Publish via WHIP</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="context-menu__item">
|
||||
<a href="#" class="context-menu__link" data-action="QRCode">
|
||||
📷
|
||||
@ -2017,7 +2064,6 @@
|
||||
<span data-translate="save-current-frame">Save frame to disk</span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="context-menu__item">
|
||||
<a href="#" class="context-menu__link" data-action="ShowStats">
|
||||
<i class="las la-external-link"></i>
|
||||
@ -2171,6 +2217,32 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="publishSettings" style="display:none; user-select: none;">
|
||||
<div class="promptModalInner">
|
||||
<h3 data-translate="publish-settings">Publish setup</h3>
|
||||
<br />
|
||||
<small>To publish this browser window, click the start publishing button below and then select the current browser window, with audio-selected if desired. The stream will go live afterwards, automatically.</small>
|
||||
|
||||
<div id="publishOutURL" class="hidden">
|
||||
<br />
|
||||
I'm publishing to Twitch: <input type="checkbox" onchange="twitchSelect(this)"; />
|
||||
<br/> or
|
||||
<br />
|
||||
Custom WHIP URL: <input type="text" size="30" placeholder="WHIP URL to publish to goes here">
|
||||
</div>
|
||||
<div id="publishOutToken" class="hidden">
|
||||
<br />
|
||||
Stream token: <input type="password" placeholder="Stream or auth token here">
|
||||
</div>
|
||||
<br />
|
||||
<br />
|
||||
<button onclick='startPublishing();'>🎦 Select window and start publishing</button>
|
||||
<br /><br />
|
||||
|
||||
<i>note: To stop the stream, simply close this browser window.</i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="remoteOBSControl" class="customModelPopup" style="display:none;">
|
||||
<div class="promptModalInner">
|
||||
<span class='modalClose' onclick="toggleOBSControls();">×</span>
|
||||
@ -2376,7 +2448,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 = "23.4";
|
||||
session.version = "23.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
|
||||
@ -2489,11 +2561,11 @@
|
||||
// session.hidehome = true; // If used, 'hide home' will make the landing page inaccessible, along with hiding a few go-home elements.
|
||||
// session.record = false; // uncomment to block users from being able to record via vdo.ninja's built in recording function
|
||||
</script>
|
||||
<script type="text/javascript" crossorigin="anonymous" id="lib-js" src="./lib.js?ver=821"></script>
|
||||
<script type="text/javascript" crossorigin="anonymous" id="lib-js" src="./lib.js?ver=833"></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=639"></script>
|
||||
<script type="text/javascript" crossorigin="anonymous" id="main-js" src="./main.js?ver=650"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
314
lib.js
314
lib.js
@ -81,6 +81,7 @@ var miscTranslations = {
|
||||
"share-a-screen": "Share a screen",
|
||||
"stop-screen-sharing": "Stop screen sharing",
|
||||
"you-have-been-transferred": "You've been transferred to a different room",
|
||||
"you-have-been-activated": "The director has allowed you to see others in the room now",
|
||||
"you-are-no-longer-a-co-director": "You are no longer a co-director as you were transferred.",
|
||||
"transferred": "Transferred",
|
||||
"room-changed": "Your room has changed",
|
||||
@ -873,8 +874,8 @@ async function promptAlt(inputText, block=false, asterix=false, value=false, tim
|
||||
return result;
|
||||
}
|
||||
|
||||
async function promptTransfer(value=null, bcmode = null, updateurl = null){
|
||||
var result = {room:null};
|
||||
async function promptTransfer(value=null, bcmode = null, updateurl = null, queueMode = null){
|
||||
var result = {roomid:null};
|
||||
if (session.beepToNotify){
|
||||
playtone();
|
||||
}
|
||||
@ -898,6 +899,7 @@ async function promptTransfer(value=null, bcmode = null, updateurl = null){
|
||||
<input id="input_${promptID}" data-pid="${promptID}" type="text" autocorrect="off" autocapitalize="none" class="largeTextEntry" />
|
||||
<span class='promptModalLabel'><input id="private_${promptID}" data-pid="${promptID}" type="checkbox" title="Note: this won't work fully if using obfuscated links" /> Allow the guest to rejoin the transfer room on their own</span>
|
||||
<span class='promptModalLabel'><input id="broadcast_${promptID}" data-pid="${promptID}" type="checkbox" /> Guest will arrive in the new room in <i>broadcast</i> mode</span>
|
||||
<span class='promptModalLabel'><input id="queued_${promptID}" data-pid="${promptID}" type="checkbox" /> Guest will arrive in the new room in <i>queue</i> mode</span>
|
||||
<button id="submit_${promptID}" data-pid="${promptID}" style="width:120px; background-color: #fff; position: relative;border: 1px solid #999; margin: 0 0 0 55px;" data-translate='ok'>✔ OK</button>
|
||||
<button id="cancel_${promptID}" data-pid="${promptID}" style="width:120px; background-color: #fff; position: relative;border: 1px solid #999; margin: 0;" data-translate='cancel'>❌ Cancel</button>
|
||||
</div>
|
||||
@ -916,6 +918,9 @@ async function promptTransfer(value=null, bcmode = null, updateurl = null){
|
||||
if (bcmode!==null){
|
||||
document.getElementById("broadcast_"+promptID).checked = bcmode;
|
||||
}
|
||||
if (queueMode!==null){
|
||||
document.getElementById("queued_"+promptID).checked = queueMode;
|
||||
}
|
||||
|
||||
if (updateurl!==null){
|
||||
document.getElementById("private_"+promptID).checked = updateurl;
|
||||
@ -927,10 +932,11 @@ async function promptTransfer(value=null, bcmode = null, updateurl = null){
|
||||
var room = document.getElementById("input_"+pid).value;
|
||||
var updateurl = document.getElementById("private_"+pid).checked;
|
||||
var broadcast = document.getElementById("broadcast_"+pid).checked;
|
||||
var queue = document.getElementById("queued_"+pid).checked;
|
||||
document.getElementById("modal_"+pid).remove();
|
||||
document.getElementById("modalBackdrop_"+pid).remove();
|
||||
Prompts[pid].resolve();
|
||||
result = {roomid:room, updateurl:updateurl, broadcast:broadcast};
|
||||
result = {roomid:room, updateurl:updateurl, broadcast:broadcast, queue:queue};
|
||||
}
|
||||
});
|
||||
|
||||
@ -939,11 +945,11 @@ async function promptTransfer(value=null, bcmode = null, updateurl = null){
|
||||
var room = document.getElementById("input_"+pid).value;
|
||||
var updateurl = document.getElementById("private_"+pid).checked;
|
||||
var broadcast = document.getElementById("broadcast_"+pid).checked;
|
||||
|
||||
var queue = document.getElementById("queued_"+pid).checked;
|
||||
document.getElementById("modal_"+pid).remove();
|
||||
document.getElementById("modalBackdrop_"+pid).remove();
|
||||
Prompts[pid].resolve();
|
||||
result = {roomid:room, updateurl:updateurl, broadcast:broadcast};
|
||||
result = {roomid:room, updateurl:updateurl, broadcast:broadcast, queue:queue};
|
||||
});
|
||||
|
||||
document.getElementById("cancel_"+promptID).addEventListener("click", function(event){
|
||||
@ -985,6 +991,11 @@ function youveBeenTransferred(){
|
||||
hideHomeCheck();
|
||||
}
|
||||
|
||||
function youveBeenActivated(){
|
||||
getChatMessage( miscTranslations["you-have-been-activated"], label = false, director = false, overlay = true); // "you-have-been-transferred"
|
||||
hideHomeCheck();
|
||||
}
|
||||
|
||||
async function confirmAlt(inputText, block=false){
|
||||
var result = null;
|
||||
if (session.beepToNotify){
|
||||
@ -2116,6 +2127,40 @@ function compare_vids( a, b ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
function compare_vids_sid( a, b ) {
|
||||
var aa = a.dataset.sid || 0;
|
||||
var bb = b.dataset.sid || 0;
|
||||
if ( aa > bb ){
|
||||
return 1;
|
||||
}
|
||||
if ( aa < bb ){
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
function compare_vids_label( a, b ) {
|
||||
if (a.dataset.UUID && session.rpcs[a.dataset.UUID] && session.rpcs[a.dataset.UUID].label){
|
||||
var aa = session.rpcs[a.dataset.UUID].label.toLowerCase();
|
||||
} else {
|
||||
var aa = 0;
|
||||
}
|
||||
|
||||
if (b.dataset.UUID && session.rpcs[b.dataset.UUID] && session.rpcs[b.dataset.UUID].label){
|
||||
var bb = session.rpcs[b.dataset.UUID].label.toLowerCase();
|
||||
} else {
|
||||
var bb = 0;
|
||||
}
|
||||
|
||||
if ( aa > bb ){
|
||||
return 1;
|
||||
}
|
||||
if ( aa < bb ){
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
function sortByZ(mediaPool, layout) {
|
||||
function sortABZ( a, b ) {
|
||||
if (layout[a.dataset.sid]){
|
||||
@ -2216,9 +2261,15 @@ function makeMiniDraggableElement(elmnt) {
|
||||
miniPerformerX = window.innerWidth-elmnt.clientWidth;
|
||||
}
|
||||
|
||||
miniPerformerX = 100 * miniPerformerX/window.innerWidth;
|
||||
miniPerformerX = 100 * miniPerformerX/window.innerWidth ;
|
||||
miniPerformerY = 100 * miniPerformerY/window.innerHeight;
|
||||
|
||||
if (session.widget && !session.leftMiniPreview){
|
||||
if (miniPerformerX>74){
|
||||
miniPerformerX = 74;
|
||||
}
|
||||
}
|
||||
|
||||
if (miniPerformerY<0){
|
||||
miniPerformerY=0;
|
||||
} else if (miniPerformerY>100){
|
||||
@ -3503,6 +3554,11 @@ function createRichVideoElement(UUID){ // this function is used to check and gen
|
||||
applyMirrorGuest(session.rpcs[UUID].mirrorState, session.rpcs[UUID].videoElement);
|
||||
}
|
||||
|
||||
|
||||
if (session.posterImage){
|
||||
session.rpcs[UUID].videoElement.poster = session.posterImage;
|
||||
}
|
||||
|
||||
setupIncomingVideoTracking(session.rpcs[UUID].videoElement, UUID);
|
||||
pokeIframeAPI("video-element-created", "videosource_"+UUID, UUID);
|
||||
}
|
||||
@ -4503,6 +4559,15 @@ function updateMixerRun(e=false){ // this is the main auto-mixing code. It's a
|
||||
}
|
||||
|
||||
if (!session.layout){
|
||||
if (session.orderby){
|
||||
if (session.orderby=="id"){
|
||||
mediaPool.sort(compare_vids_sid);
|
||||
} else if (session.orderby=="label"){
|
||||
mediaPool.sort(compare_vids_label);
|
||||
} else {
|
||||
mediaPool.sort(compare_vids_sid);
|
||||
}
|
||||
}
|
||||
mediaPool.sort(compare_vids);
|
||||
}
|
||||
|
||||
@ -4785,10 +4850,18 @@ function updateMixerRun(e=false){ // this is the main auto-mixing code. It's a
|
||||
container.style.top = miniPerformerY + "%";
|
||||
}
|
||||
if (miniPerformerX !== null){
|
||||
if (session.widget && !session.leftMiniPreview){
|
||||
if (miniPerformerX>74){
|
||||
miniPerformerX = 74;
|
||||
}
|
||||
}
|
||||
container.style.left = miniPerformerX + "%";
|
||||
} else if (session.leftMiniPreview!==false){
|
||||
container.style.left = session.leftMiniPreview + "%";
|
||||
togglePreview.style.left = session.leftMiniPreview + "%";
|
||||
} else if (session.widget){
|
||||
container.style.right = "25%";
|
||||
togglePreview.style.right = "25%";
|
||||
} else {
|
||||
container.style.right = "2vw";
|
||||
togglePreview.style.right = "2vw";
|
||||
@ -5732,7 +5805,7 @@ function updateMixerRun(e=false){ // this is the main auto-mixing code. It's a
|
||||
|
||||
if (!session.cleanOutput && !session.nocursor){
|
||||
if ((session.roomid!==false) && (session.scene===false)){
|
||||
if (!((vid.id === "videosource") && (miniPreview))){
|
||||
if (!((vid.id === "videosource") && miniPreview) && !session.infocusForceMode){
|
||||
|
||||
if (!holder.button){
|
||||
var button = document.createElement("div");
|
||||
@ -5835,7 +5908,7 @@ function updateMixerRun(e=false){ // this is the main auto-mixing code. It's a
|
||||
container.style.backgroundColor= null;
|
||||
button.style.opacity="10%";
|
||||
};
|
||||
} else if ((vid.id === "videosource") && miniPreview && soloVideo==true){
|
||||
} else if ((vid.id === "videosource") && miniPreview && soloVideo==true && !session.infocusForceMode){
|
||||
|
||||
if (!holder.button){
|
||||
var button = document.createElement("div");
|
||||
@ -5875,6 +5948,12 @@ function updateMixerRun(e=false){ // this is the main auto-mixing code. It's a
|
||||
}
|
||||
};
|
||||
|
||||
} else if (session.infocusForceMode && holder.button){
|
||||
try{
|
||||
holder.button.remove();
|
||||
} catch(e){
|
||||
errorlog(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -8601,11 +8680,11 @@ function plotData(info, UUID, uuid) { // type = "bitrate" or "nacks"
|
||||
canvas.history_bitrate = [];
|
||||
canvas.target = 4000;
|
||||
if (info.scene){
|
||||
canvas.title = "Scene: "+info.scene+". Red/orange implies packet loss. Y-axis is 0 to 4000-kbps.";
|
||||
canvas.title = "Scene: "+info.scene+". Red/orange implies packet loss. Y-axis is marked with 2500-kbps increments.";
|
||||
} else if (info.label){
|
||||
canvas.title = "Label: "+info.label+". Red/orange implies packet loss. Y-axis is 0 to 4000-kbps.";
|
||||
canvas.title = "Label: "+info.label+". Red/orange implies packet loss. Y-axis is marked with 2500-kbps increments";
|
||||
} else {
|
||||
canvas.title = "Red/orange implies packet loss. Y-axis is 0 to 4000-kbps.";
|
||||
canvas.title = "Red/orange implies packet loss. Y-axis is marked with 2500-kbps increments";
|
||||
}
|
||||
|
||||
canvas.dataset.uid = uuid;
|
||||
@ -8872,9 +8951,11 @@ function processStats(UUID){
|
||||
}
|
||||
|
||||
var validTrackIds = [];
|
||||
session.rpcs[UUID].videoElement.srcObject.getTracks().forEach(trk=>{
|
||||
validTrackIds.push(trk.id);
|
||||
});
|
||||
if (session.rpcs[UUID].videoElement){
|
||||
session.rpcs[UUID].videoElement.srcObject.getTracks().forEach(trk=>{
|
||||
validTrackIds.push(trk.id);
|
||||
});
|
||||
}
|
||||
|
||||
if (node.getStats){
|
||||
node.getStats().then(function(stats){
|
||||
@ -11778,10 +11859,17 @@ async function directMigrate(ele, event, room=false) { // everyone in the room w
|
||||
broadcastMode = transferSettings.broadcast;
|
||||
} else if (session.rpcs[ele.dataset.UUID] && session.rpcs[ele.dataset.UUID].stats.info && ("broadcast_mode" in session.rpcs[ele.dataset.UUID].stats.info)){
|
||||
broadcastMode = session.rpcs[ele.dataset.UUID].stats.info.broadcast_mode;
|
||||
} else if (session.broadcastTransfer){
|
||||
} else if (session.broadcastTransfer!==null){
|
||||
broadcastMode = session.broadcastTransfer;
|
||||
}
|
||||
|
||||
var queuedMode = null;
|
||||
if ("queue" in transferSettings){
|
||||
queuedMode = transferSettings.queue;
|
||||
} else if (session.queueTransfer){
|
||||
queuedMode = session.queueTransfer;
|
||||
}
|
||||
|
||||
var updateurl = null;
|
||||
if ("updateurl" in transferSettings){
|
||||
updateurl = transferSettings.updateurl;
|
||||
@ -11789,7 +11877,7 @@ async function directMigrate(ele, event, room=false) { // everyone in the room w
|
||||
window.focus();
|
||||
|
||||
|
||||
var response = await promptTransfer(previousRoom, broadcastMode, updateurl);
|
||||
var response = await promptTransfer(previousRoom, broadcastMode, updateurl, queuedMode);
|
||||
var migrateRoom = response.roomid;
|
||||
if (migrateRoom !== null){
|
||||
transferSettings = response;
|
||||
@ -14509,6 +14597,121 @@ session.publishIFrame = function(iframeURL){
|
||||
return container;
|
||||
} // publishIframe
|
||||
|
||||
|
||||
session.publishWhepSrc = function(){
|
||||
|
||||
if (!session.whepSrc){errorlog("no WHEP Src");return;}
|
||||
|
||||
if (!session.cleanOutput){
|
||||
getById("websitesharebutton2").classList.remove('hidden');
|
||||
}
|
||||
|
||||
var UUID = whepIn(session.whepSrc);
|
||||
|
||||
var container = document.createElement("div");
|
||||
iframe.container = container;
|
||||
container.id = "container_iframe";
|
||||
container.appendChild(iframe);
|
||||
getById("gridlayout").appendChild(container);
|
||||
|
||||
if (session.iframeSrc.startsWith("https://www.youtube.com/")){ // special handler.
|
||||
setTimeout(function(iframe_id){YoutubeListen(iframe_id);}, 1000, iframe.id);
|
||||
}
|
||||
|
||||
if (session.cover){
|
||||
container.style.setProperty('height', '100%', 'important');
|
||||
}
|
||||
|
||||
if (session.roomid!==false){
|
||||
if ((session.roomid==="") && ((!(session.view)) || (session.view===""))){
|
||||
|
||||
} else {
|
||||
log("ROOMID EANBLED");
|
||||
getById("head3").classList.add('hidden');
|
||||
getById("head3a").classList.add('hidden');
|
||||
joinRoom(session.roomid);
|
||||
}
|
||||
|
||||
} else {
|
||||
getById("head3").classList.remove('hidden');
|
||||
getById("head3a").classList.remove('hidden');
|
||||
getById("logoname").style.display = 'none';
|
||||
}
|
||||
getById("head1").className = 'hidden';
|
||||
|
||||
updatePushId()
|
||||
|
||||
getById("head1").className = 'hidden';
|
||||
getById("head2").className = 'hidden';
|
||||
|
||||
if (!(session.cleanOutput)){
|
||||
getById("chatbutton").className="float";
|
||||
getById("hangupbutton").className="float";
|
||||
getById("controlButtons").classList.remove("hidden");
|
||||
getById('sharefilebutton').classList.remove("hidden"); // we won't override "display:none", if set, though.
|
||||
getById("helpbutton").style.display = "inherit";
|
||||
getById("reportbutton").style.display = "";
|
||||
} else {
|
||||
getById("controlButtons").classList.add("hidden");
|
||||
}
|
||||
|
||||
if (session.chatbutton === false) {
|
||||
getById("chatbutton").classList.add("hidden");
|
||||
}
|
||||
|
||||
if (session.director){
|
||||
//
|
||||
} else if (session.scene!==false){
|
||||
updateMixer();
|
||||
} else if (session.roomid!==false){
|
||||
if (session.roomid===""){
|
||||
if (!(session.view) || (session.view==="")){
|
||||
session.windowed = true;
|
||||
container.classList.add("vidcon");
|
||||
|
||||
getById("mutespeakerbutton").classList.add("hidden");
|
||||
container.style.width="100%";
|
||||
container.style.height="100%";
|
||||
container.style.alignItems = "center";
|
||||
container.style.maxWidth= "100%";
|
||||
container.style.maxHeight= "100%";
|
||||
container.style.verticalAlign= "middle";
|
||||
container.style.margin= "auto";
|
||||
container.style.backgroundColor = "#666";
|
||||
container.style.border = "2px solid";
|
||||
|
||||
} else {
|
||||
session.windowed = false;
|
||||
window.onresize = updateMixer;
|
||||
updateMixer();
|
||||
}
|
||||
} else {
|
||||
window.onresize = updateMixer;
|
||||
session.windowed = false;
|
||||
updateMixer();
|
||||
}
|
||||
} else {
|
||||
window.onresize = updateMixer;
|
||||
container.style.maxHeight= "1280px";
|
||||
container.style.maxWidth= "720px";
|
||||
container.style.verticalAlign= "middle";
|
||||
container.style.height="100%";
|
||||
container.style.width= "100%";
|
||||
container.style.margin= "auto";
|
||||
container.style.alignItems = "center";
|
||||
container.style.backgroundColor = "#666";
|
||||
}
|
||||
|
||||
session.seeding=true;
|
||||
|
||||
updateReshareLink();
|
||||
pokeIframeAPI('started-iframe-share');
|
||||
session.seedStream();
|
||||
|
||||
return container;
|
||||
} // publishWhepSrc
|
||||
|
||||
|
||||
function outboundAudioPipeline(){ // this function isn't letting me change the audio source
|
||||
|
||||
if (session.disableWebAudio) {
|
||||
@ -15527,7 +15730,7 @@ function joinRoom(roomname) {
|
||||
}
|
||||
|
||||
if (!session.cleanOutput){
|
||||
if (session.roomhost){
|
||||
if (session.roomhost){
|
||||
if (session.defaultPassword===false){
|
||||
if (session.password === false){
|
||||
var invite = "https://"+location.host+location.pathname+"?room="+session.roomid+"&password=false"+token;
|
||||
@ -16285,7 +16488,7 @@ async function createRoomCallback(passAdd, passAdd2) {
|
||||
var container = getById("rooms");
|
||||
container.innerHTML += '<span style="display:inline-block">Arm Transfer: </span>';
|
||||
session.rooms.forEach(function (r) {
|
||||
if(session.roomid == r) return; //don't include self
|
||||
// if(session.roomid == r) return; //don't include self
|
||||
container.innerHTML += '<button id="roomselect_' + r + '" onmousedown="event.preventDefault(); event.stopPropagation();" style="display:inline-block" class="float btnArmTransferRoom" onclick="handleRoomSelect(\'' + r + '\');" title="Arm/disarm transfer to this room" tabindex="' + tabindex + '"><i class="las la-paper-plane"></i>' + r + '</button>';
|
||||
tabindex++;
|
||||
});
|
||||
@ -17250,7 +17453,15 @@ function swapNodes(n1, n2) {
|
||||
p2.insertBefore(n1, p2.children[i2]);
|
||||
}
|
||||
|
||||
function createControlBox(UUID, soloLink, streamID) {
|
||||
function remoteRemoveQueue(ele){
|
||||
let ts = {...transferSettings};
|
||||
ts.justResetting = true;
|
||||
session.directMigrateIssue(session.roomid, ts, ele.dataset.UUID);
|
||||
|
||||
ele.classList.add("hidden");
|
||||
}
|
||||
|
||||
function createControlBox(UUID, soloLink, streamID, slot_init=false) {
|
||||
if (document.getElementById("deleteme")) {
|
||||
getById("deleteme").parentNode.removeChild(getById("deleteme"));
|
||||
}
|
||||
@ -17336,7 +17547,7 @@ function createControlBox(UUID, soloLink, streamID) {
|
||||
controls.innerHTML += "<div id='advanced_video_director_" + UUID + "' class='hidden advancedVideoSettings'></div>";
|
||||
|
||||
var handsID = "hands_" + UUID;
|
||||
|
||||
|
||||
// controls.innerHTML += "<div class='flexBreak'><span data-translate='links'>Links</span></div>"; //Seems to create an empty div.
|
||||
|
||||
if (session.hidesololinks==false){
|
||||
@ -17347,11 +17558,18 @@ function createControlBox(UUID, soloLink, streamID) {
|
||||
</div>";
|
||||
}
|
||||
|
||||
controls.innerHTML += "<button data-action-type=\"hand-raised\" id='" + handsID + "' class='hidden lowerRaisedHand' title=\"This guest raised their hand. Click this to clear notification.\" onclick=\"remoteLowerhands('" + UUID + "');\">\
|
||||
controls.innerHTML += "<button data-action-type=\"hand-raised\" data--u-u-i-d='"+UUID+"' id='" + handsID + "' class='hidden lowerRaisedHand' title=\"This guest raised their hand. Click this to clear notification.\" onclick=\"remoteLowerhands('" + UUID + "');\">\
|
||||
<i class=\"las la-hand-paper\"></i>\
|
||||
<span data-translate=\"user-raised-hand\">Lower Raised Hand</span>\
|
||||
</button>\
|
||||
</div>";
|
||||
|
||||
|
||||
controls.innerHTML += "<button data-action-type=\"remove-queue\" data--u-u-i-d='"+UUID+"' class='hidden removeFromQueue' title=\"Takes the guest out of queue mode; they will then join as a normal guest.\" onclick=\"remoteRemoveQueue(this);\">\
|
||||
<i class=\"las la-plus\"></i>\
|
||||
<span data-translate=\"remove-from-queue\">Activate Guest</span>\
|
||||
</button>\
|
||||
</div>";
|
||||
|
||||
controls.querySelectorAll('[data-action-type]').forEach((ele) => { // give action buttons some self-reference
|
||||
ele.dataset.UUID = UUID;
|
||||
@ -17363,7 +17581,13 @@ function createControlBox(UUID, soloLink, streamID) {
|
||||
var slots = document.querySelectorAll("div.slotsbar[data-slot]");
|
||||
var biggestSlot=0;
|
||||
|
||||
|
||||
var slotDefault = null;
|
||||
|
||||
if (slot_init && (session.slotmode==1)){
|
||||
slotDefault = slot_init || null;
|
||||
}
|
||||
|
||||
if (streamID in session.pastSlots){
|
||||
slotDefault = session.pastSlots[streamID];
|
||||
}
|
||||
@ -17373,15 +17597,18 @@ function createControlBox(UUID, soloLink, streamID) {
|
||||
if (parseInt(slots[i].dataset.slot)>biggestSlot){
|
||||
biggestSlot = parseInt(slots[i].dataset.slot);
|
||||
}
|
||||
if (slotDefault===parseInt(slots[i].dataset.slot)){
|
||||
if (slotDefault===parseInt(slots[i].dataset.slot)){ // already taken
|
||||
slotDefault = null;
|
||||
}
|
||||
}
|
||||
biggestSlot+=1;
|
||||
}
|
||||
if (slotDefault!==null){
|
||||
if (slotDefault!==null){ // the default slot is avialable
|
||||
biggestSlot = slotDefault;
|
||||
}
|
||||
} else if (slot_init && (session.slotmode==1)){ // was manually set, so can't be something else but 0; 0 or false would still end up with 0
|
||||
biggestSlot = 0;
|
||||
} // else, if slotmode==1, we'll go for the biggest slot available
|
||||
|
||||
var slotName = "slot: "+biggestSlot;
|
||||
if (!biggestSlot){
|
||||
slotName = "unset";
|
||||
@ -23369,6 +23596,10 @@ session.postPublish = async function(){
|
||||
if (session.whipOutput){
|
||||
whipOut();
|
||||
}
|
||||
if (session.whepHost){
|
||||
whepOut();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -28648,6 +28879,7 @@ async function shareWebsite(autostart=false, evt=false){
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function screenshareTypeDecider(sstype=1){
|
||||
if (session.screenshareType){
|
||||
sstype = session.screenshareType;
|
||||
@ -33325,7 +33557,6 @@ function audioMeterGuest(mediaStreamSource, UUID, trackid){
|
||||
|
||||
function updateLevels() {
|
||||
|
||||
if (!session.rpcs || !(UUID in session.rpcs)){return;}
|
||||
try {
|
||||
session.rpcs[UUID].inboundAudioPipeline[trackid].analyser.getByteFrequencyData(dataArray);
|
||||
var total = 0;
|
||||
@ -33409,6 +33640,7 @@ function audioMeterGuest(mediaStreamSource, UUID, trackid){
|
||||
|
||||
} catch(e){
|
||||
warnlog(e);
|
||||
// fail as an exception; this is a control close.
|
||||
return;
|
||||
}
|
||||
};
|
||||
@ -34641,11 +34873,13 @@ async function processWHIP(data){ // LISTEN FOR REMOTE WHIP
|
||||
return sdpAnswer; // return SDP answer for the remote WHIP request
|
||||
}
|
||||
|
||||
async function whepIn(){ // PLAY WHEP
|
||||
async function whepIn(whepInput=false,whepInputToken, UUID=false){ // PLAY WHEP
|
||||
var candidates = [];
|
||||
var responseLocation = false;
|
||||
var UUID = session.generateRandomString(25); // fake
|
||||
UUID = UUID+"_whep" || session.generateRandomString(25); // fake
|
||||
|
||||
whepInput = whepInput || session.whepInput;
|
||||
whepInputToken = whepInputToken || session.whepInputToken;
|
||||
async function whepConnect(){
|
||||
try {
|
||||
|
||||
@ -34667,7 +34901,7 @@ async function whepIn(){ // PLAY WHEP
|
||||
}
|
||||
var config = {...session.configuration};
|
||||
|
||||
if (session.whepInput.includes("cloudflare")){
|
||||
if (whepInput.includes("cloudflare")){
|
||||
config.iceTransportPolicy = "relay"; // oof. Doesn't work with Cloudflare without this?
|
||||
}
|
||||
|
||||
@ -34814,17 +35048,17 @@ async function whepIn(){ // PLAY WHEP
|
||||
};
|
||||
if (type==="trickle-ice-sdpfrag"){
|
||||
if (responseLocation){
|
||||
xhttp.open("PATCH", session.whepInput, true);
|
||||
xhttp.open("PATCH", whepInput, true);
|
||||
} else {
|
||||
xhttp.open("PATCH", session.whepInput, true);
|
||||
xhttp.open("PATCH", whepInput, true);
|
||||
}
|
||||
} else {
|
||||
xhttp.open("POST", session.whepInput, true);
|
||||
xhttp.open("POST", whepInput, true);
|
||||
}
|
||||
xhttp.setRequestHeader('Content-Type', 'application/'+type);
|
||||
|
||||
if (session.whepInputToken){
|
||||
xhttp.setRequestHeader('Authorization', 'Bearer ' + session.whepInputToken);
|
||||
if (whepInputToken){
|
||||
xhttp.setRequestHeader('Authorization', 'Bearer ' + whepInputToken);
|
||||
}
|
||||
xhttp.onerror = function(e) {
|
||||
errorlog(e);
|
||||
@ -34836,11 +35070,12 @@ async function whepIn(){ // PLAY WHEP
|
||||
}
|
||||
|
||||
whepConnect();
|
||||
return UUID;
|
||||
}
|
||||
////////
|
||||
function whepOut(){ // publish to whip.vdo.ninja with obs, to use. experimental
|
||||
if (!session.whipView){return;}
|
||||
warnlog("WHIP Client started");
|
||||
function whepOut(){ // publish to whep.vdo.ninja with obs, to use. experimental
|
||||
if (!session.whepHost){return;}
|
||||
warnlog("WHEP Client started");
|
||||
|
||||
var socket = null;
|
||||
var connecting = false;
|
||||
@ -34876,7 +35111,7 @@ function whepOut(){ // publish to whip.vdo.ninja with obs, to use. experimental
|
||||
failedCount = 0;
|
||||
try{
|
||||
var settings = {};
|
||||
socket.send(JSON.stringify({"join":session.whipView}));
|
||||
socket.send(JSON.stringify({"join":session.whepHost}));
|
||||
} catch(e){
|
||||
connecting = setTimeout(function(){connect();},1);
|
||||
}
|
||||
@ -34919,11 +35154,6 @@ async function processWHEPout(data){ // LISTEN FOR REMOTE WHIP
|
||||
// msg.session = session.generateRandomString(5);
|
||||
msg.UUID = session.generateRandomString(25); // fake
|
||||
|
||||
if (data.streamID){
|
||||
msg.streamID = data.streamID;
|
||||
} else {
|
||||
msg.streamID = session.generateRandomString(15); // fake
|
||||
}
|
||||
log("setupoutgoing");
|
||||
|
||||
try {
|
||||
|
||||
23
main.css
23
main.css
@ -2464,11 +2464,23 @@ span[data-action-type="stats-graphs-details-container"]>span{
|
||||
|
||||
.lowerRaisedHand{
|
||||
margin: auto;
|
||||
margin-top: 5px;
|
||||
margin-left: 5px;
|
||||
margin-bottom: 10px;
|
||||
background-color: yellow;
|
||||
width: calc(100% - 10px);
|
||||
margin-bottom: 5px;
|
||||
background-color: yellow!important;
|
||||
width: 100%;
|
||||
color:black!important;
|
||||
}
|
||||
|
||||
.removeFromQueue{
|
||||
margin: auto;
|
||||
margin-top: 5px;
|
||||
margin-left: 5px;
|
||||
margin-bottom: 5px;
|
||||
background-color: #ff00b8!important;
|
||||
width: 100%
|
||||
}
|
||||
|
||||
.float {
|
||||
opacity: 0.8;
|
||||
min-width: 45px;
|
||||
@ -3415,9 +3427,7 @@ div#roomnotes2 {
|
||||
margin: 0 var(--regular-margin) 10px var(--regular-margin);
|
||||
width: 100%;
|
||||
}
|
||||
.directorsgrid button {
|
||||
text-transform: capitalize;
|
||||
}
|
||||
|
||||
|
||||
#yourDirectorStatus {
|
||||
color: var(--discord-text);
|
||||
@ -3431,6 +3441,7 @@ div#roomnotes2 {
|
||||
background-color: #606383 !important;
|
||||
display: var(--show-codirectors) !important;
|
||||
}
|
||||
|
||||
/* ---- DIRECTORS PAGE - Guest Controls Box ---- */
|
||||
.controlsGrid {
|
||||
display: flex;
|
||||
|
||||
107
main.js
107
main.js
@ -141,7 +141,7 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
session.showControls = false; // show the video control bar
|
||||
}
|
||||
|
||||
if (!isIFrame){
|
||||
if (!isIFrame && !window.obsstudio){
|
||||
if (ChromeVersion===65){
|
||||
// pass, since probably manycam and that's bugged
|
||||
} else if (getStorage("redirect") == "yes") {
|
||||
@ -285,6 +285,24 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
}
|
||||
}
|
||||
|
||||
if (urlParams.has('poster')) { // URL or data:base64 image. Becomes local to this viewer only. This is like &avatar, but slightly different. Just CSS in this case
|
||||
var posterImage = urlParams.get('poster') || "./media/avatar.webp";
|
||||
if (posterImage){
|
||||
try {
|
||||
posterImage = decodeURIComponent(posterImage);
|
||||
session.posterImage = posterImage;
|
||||
} catch(e){}
|
||||
}
|
||||
}
|
||||
|
||||
if (urlParams.has('hideplaybutton') || urlParams.has('hpb')) { // URL or data:base64 image. Becomes local to this viewer only. This is like &avatar, but slightly different. Just CSS in this case
|
||||
try {
|
||||
document.getElementById("bigPlayButton").classList.add("hidden");
|
||||
} catch(e){
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (urlParams.has('whip') || urlParams.has('whipview')) {
|
||||
session.whipView = urlParams.get('whip') || urlParams.get('whipview') || false;
|
||||
if (session.whipView){
|
||||
@ -339,15 +357,8 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (urlParams.has('whepplaytoken')) { // URL or data:base64 image. Becomes local to this viewer only. This is like &avatar, but slightly different. Just CSS in this case
|
||||
if (urlParams.get('whepplaytoken')){
|
||||
try {
|
||||
session.whepInputToken = urlParams.get('whepplaytoken')
|
||||
} catch(e){
|
||||
errorlog(e);
|
||||
}
|
||||
}
|
||||
if (urlParams.has("hostwhep")){
|
||||
session.whepHost = urlParams.get("hostwhep") || session.streamID || false;
|
||||
}
|
||||
|
||||
if (urlParams.has('nomouseevents') || urlParams.has('nme')) {
|
||||
@ -391,6 +402,9 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
session.audioEffects = false; // disable audio inbound effects also.
|
||||
session.audioMeterGuest = false;
|
||||
} else if (iOS || iPad) {
|
||||
if (SafariVersion<16){
|
||||
getById("oldiOSWarning").classList.remove('hidden');
|
||||
}
|
||||
session.mobile = true;
|
||||
session.audioEffects = false; // disable audio inbound effects also.
|
||||
session.audioMeterGuest = false;
|
||||
@ -456,6 +470,25 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
}
|
||||
}
|
||||
|
||||
if (urlParams.has('queuetransfer') || urlParams.has('qt')) {
|
||||
log("Broadcast transfer flag set");
|
||||
session.queueTransfer = urlParams.get('queuetransfer') || urlParams.get('qt') || null;
|
||||
if (session.queueTransfer === "false") {
|
||||
session.queueTransfer = false;
|
||||
} else if (session.queueTransfer=== "0") {
|
||||
session.queueTransfer = false;
|
||||
} else if (session.queueTransfer === "no") {
|
||||
session.queueTransfer = false;
|
||||
} else if (session.queueTransfer === "off") {
|
||||
session.queueTransfer = false;
|
||||
} else {
|
||||
session.queueTransfer = true;
|
||||
}
|
||||
if (transferSettings){
|
||||
transferSettings.queue = session.queueTransfer;
|
||||
}
|
||||
}
|
||||
|
||||
if (urlParams.has('broadcast') || urlParams.has('bc')) {
|
||||
log("Broadcast flag set");
|
||||
session.broadcast = urlParams.get('broadcast') || urlParams.get('bc') || null;
|
||||
@ -2129,8 +2162,9 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
getById("obsState").style.setProperty("display", "none", "important");
|
||||
}
|
||||
|
||||
if (urlParams.has('hidecodirectors')){
|
||||
if (urlParams.has('hidecodirectors') || urlParams.has('hidecodirector') || urlParams.has('hidedirector') || urlParams.has('hidedirectors') || urlParams.has('hd')){
|
||||
document.querySelector(':root').style.setProperty("--show-codirectors", "none", "important");
|
||||
session.hideDirector = true;
|
||||
}
|
||||
|
||||
if (urlParams.has('pptcontrols') || urlParams.has('slides') || urlParams.has('ppt') || urlParams.has('powerpoint')){
|
||||
@ -2345,7 +2379,7 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
session.darkmode = false;
|
||||
} else if (window.obsstudio){
|
||||
session.darkmode = false; // prevent OBS from defaulting to dark mode, avoiding possible overlooked bugs.
|
||||
} else {
|
||||
} else if (session.darkmode===null){
|
||||
session.darkmode = getComputedStyle(document.querySelector(':root')).getPropertyValue('--color-mode').trim();
|
||||
if (session.darkmode == "dark"){
|
||||
session.darkmode = true;
|
||||
@ -2609,7 +2643,7 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
}
|
||||
|
||||
if (urlParams.has('orderby')) {
|
||||
session.orderby = urlParams.get('orderby') || "id";
|
||||
session.orderby = urlParams.get('orderby') || "id"; // "label" also an option; the default is stream ID tho.
|
||||
}
|
||||
|
||||
if (urlParams.has('slot')) {
|
||||
@ -3171,6 +3205,7 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
session.cleanish = true;
|
||||
}
|
||||
|
||||
|
||||
if (session.cleanish || !session.cleanOutput){
|
||||
if (session.obsControls){
|
||||
getById("obscontrolbutton").classList.remove("hidden");
|
||||
@ -3266,8 +3301,8 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
}
|
||||
}
|
||||
|
||||
if (urlParams.has('maxframeRate') || urlParams.has('mfr') || urlParams.has('mfps')) {
|
||||
session.maxframeRate = urlParams.get('maxframeRate') || urlParams.get('mfr') || urlParams.get('mfps');
|
||||
if (urlParams.has('maxframerate') || urlParams.has('mfr') || urlParams.has('mfps')) {
|
||||
session.maxframeRate = urlParams.get('maxframerate') || urlParams.get('mfr') || urlParams.get('mfps');
|
||||
session.maxframeRate = parseInt(session.maxframeRate);
|
||||
log("max frameRate assigned");
|
||||
log(session.maxframeRate);
|
||||
@ -3826,6 +3861,13 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
|
||||
if (urlParams.has('queue')) {
|
||||
session.queue = true;
|
||||
if (urlParams.get('queue') === "false"){
|
||||
session.queue = false;
|
||||
} else if (urlParams.get('queue') === "0"){
|
||||
session.queue = false;
|
||||
} else if (urlParams.get('queue') === "off"){
|
||||
session.queue = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -4017,6 +4059,7 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
// session.studioSoftware = true; // vmix
|
||||
if (window.obsstudio){
|
||||
session.studioSoftware = true;
|
||||
getById("saveRoom").style.display = "none"; // don't let the user save the room if in OBS
|
||||
}
|
||||
if (session.cleanViewer){
|
||||
if (session.view && !session.director && session.permaid===false){
|
||||
@ -4155,22 +4198,30 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
session.screenShareLabel = session.screenShareLabel.replace(/_/g, " ")
|
||||
}
|
||||
|
||||
// this is not the same as creating a whep source
|
||||
if (urlParams.has('whepshare') || urlParams.has('whepsrc')) { // URL or data:base64 image. Becomes local to this viewer only. This is like &avatar, but slightly different. Just CSS in this case
|
||||
try {
|
||||
|
||||
session.whepSrc = urlParams.get('whepshare') || urlParams.get('whepsrc') || false;
|
||||
console.log(session.whepSrc);
|
||||
if (!session.whepSrc){
|
||||
session.whepSrc = await promptAlt("Enter the WHEP source as a URL");
|
||||
} else {
|
||||
session.whepSrc = decodeURIComponent(session.whepSrc, true);
|
||||
}
|
||||
getById("container-6").classList.remove('hidden');
|
||||
getById("container-6").classList.add("skip-animation");
|
||||
getById("container-6").classList.remove('pointer');
|
||||
|
||||
session.whepSrc = urlParams.get('whepshare') || urlParams.get('whepsrc') || null;
|
||||
log("WHEP SRC: "+session.whepSrc);
|
||||
if (session.whepSrc){
|
||||
delayedStartupFuncs.push([shareWebsite, session.whepSrc]);
|
||||
try {
|
||||
session.whepSrc = decodeURIComponent(session.whepSrc);
|
||||
} catch(e){
|
||||
session.whepSrc=null;
|
||||
}
|
||||
}
|
||||
if (!session.whepSrc && session.autostart){
|
||||
session.whepSrc = await promptAlt("Enter the WHEP source as a URL");
|
||||
}
|
||||
if (session.whepSrc){
|
||||
getById("whepURL").value = session.whepSrc;
|
||||
}
|
||||
getById("container-16").classList.remove('hidden');
|
||||
getById("container-16").classList.add("skip-animation");
|
||||
getById("container-16").classList.remove('pointer');
|
||||
|
||||
if (session.autostart && session.whepSrc){
|
||||
delayedStartupFuncs.push([session.publishWhepSrc, session.whepSrc]);
|
||||
}
|
||||
} catch(e){
|
||||
errorlog(e);
|
||||
|
||||
16
whip.html
16
whip.html
@ -185,6 +185,17 @@
|
||||
div.urlInput {
|
||||
padding: 0 0 4vh 0;
|
||||
}
|
||||
|
||||
|
||||
@media only screen and (max-height: 839px) {
|
||||
body{
|
||||
zoom: 0.74;
|
||||
-moz-transform: scale(0.74);
|
||||
-moz-transform-origin: 0 0;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 940px) {
|
||||
body{
|
||||
zoom: 0.74;
|
||||
@ -353,7 +364,9 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="urlInput4" style="display:none;" class="urlInput" title="Put the link you want to load here">
|
||||
<div id="urlInput4" class="urlInput" title="Put the link you want to load here">
|
||||
|
||||
<h3>Host a stream as a WHEP sourceP</h3>
|
||||
|
||||
<div class="inputCombo" id="inputCombo4">
|
||||
<label for="changeText">
|
||||
@ -365,6 +378,7 @@
|
||||
</div>
|
||||
|
||||
<div id="history" title="History of past links used. You can clear this history using the button to the left">
|
||||
<h3 style='cursor:pointer;' onclick="resetHistory()">Clear History</h3>
|
||||
<label for="lastUrls" onclick="resetHistory()">
|
||||
<i class="las la-history"></i>
|
||||
</label>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user