diff --git a/convert.html b/convert.html index d06ebfe..acf2860 100644 --- a/convert.html +++ b/convert.html @@ -1,230 +1,235 @@ - - - - - - - -
-
-

Web-based Media Conversion Tools

- -
-

WebM to MP4 (fixed 1280x720 resolution) (very slow!)

-
- The same as: fmpeg -i input.webm -vf scale=1280:720 output.mp4 - -
-
-
-

MKV to MP4 (no transcoding)

-
- The same as: fmpeg -i INPUTFILE -vcodec copy -acodec copy output.mp4 - -
-
-
-

WebM MP4 files (no transcoding, attempts to force high resolutions)

-
- -
-
-
-

WebM to Audio-only files (opus or wav)

-
- -
-
-
- - - -
-
- - - + + + + + + + +
+
+

Web-based Media Conversion Tools

+
+

WebM to MP4 (fixed 1280x720 resolution) (very slow!)

+
+ The same as: fmpeg -i input.webm -vf scale=1280:720 output.mp4 + +
+
+
+

MKV to MP4 (no transcoding)

+
+ The same as: fmpeg -i INPUTFILE -vcodec copy -acodec copy output.mp4 + +
+
+
+

WebM MP4 files (no transcoding, attempts to force high resolutions)

+
+ +
+
+
+

WebM to Audio-only files (opus or wav)

+
+ +
+
+
+ + + +
+
+ + + + + \ No newline at end of file diff --git a/electron.html b/electron.html index 15623cc..cbaf502 100644 --- a/electron.html +++ b/electron.html @@ -290,7 +290,7 @@
- +
@@ -364,11 +364,9 @@ function resetHistory(){ var urlParams = new URLSearchParams(window.location.search); -if (navigator.userAgent.indexOf('Mac OS X') != -1){ - document.getElementById("warning4mac").style.display="block"; -} else if (location.hostname.toLowerCase() == "obs.ninja"){ +if ((location.hostname.toLowerCase() == "vdo.ninja") || (location.hostname.toLowerCase() == "obs.ninja")){ try { - if (navigator.userAgent.toLowerCase().indexOf(' electron/') > -1) { // for now, just PC or Linux versions only. + if (navigator.userAgent.toLowerCase().indexOf(' electron/') > -1) { function compareVersions(version){ version = version.split("."); fetch('https://api.github.com/repos/steveseguin/electroncapture/releases/latest') diff --git a/examples/changepass.html b/examples/changepass.html new file mode 100644 index 0000000..097f777 --- /dev/null +++ b/examples/changepass.html @@ -0,0 +1,25 @@ + \ No newline at end of file diff --git a/examples/dual.html b/examples/dual.html new file mode 100644 index 0000000..d968048 --- /dev/null +++ b/examples/dual.html @@ -0,0 +1,331 @@ + +Dual Input + + + + + + +You can drag and resize the generated windows; multiple can be created. + +
+ + + + \ No newline at end of file diff --git a/examples/mini.css b/examples/mini.css new file mode 100644 index 0000000..6a4100f --- /dev/null +++ b/examples/mini.css @@ -0,0 +1,3 @@ +.tile { + max-width:200px !important; +} \ No newline at end of file diff --git a/examples/status.html b/examples/status.html new file mode 100644 index 0000000..e9eb89d --- /dev/null +++ b/examples/status.html @@ -0,0 +1,172 @@ + + + + + OBSN Chat Overlay + + + + + + + + + diff --git a/examples/webhid.html b/examples/webhid.html new file mode 100644 index 0000000..9bda785 --- /dev/null +++ b/examples/webhid.html @@ -0,0 +1,133 @@ + + + + + WebHID Demo + + + +

STREAMDECK DEMO

+
+ + +
+
+ + + + + diff --git a/examples/zoom.html b/examples/zoom.html new file mode 100644 index 0000000..8c8969a --- /dev/null +++ b/examples/zoom.html @@ -0,0 +1,182 @@ + + + + + + +
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + diff --git a/index.html b/index.html index 44e7ba7..3fc6160 100644 --- a/index.html +++ b/index.html @@ -17,7 +17,7 @@ - + @@ -55,8 +55,9 @@ } - + + @@ -67,11 +68,11 @@ - +
-   Control center for room:
@@ -107,11 +107,12 @@ You are in room:
+
Only the director can hear you currently.
+
The director has muted you.
-
ACTIVE
- +
ACTIVE
@@ -306,7 +311,7 @@ -
@@ -495,6 +500,8 @@ +
+ For application-specific audio capture, see here
@@ -605,7 +612,7 @@
See the documentation for more options and info.

- Try out the advanced invite generator here also. + Try out the advanced invite generator here also.
@@ -638,10 +645,7 @@

File Sharing seems to be broken on Chrome v88.

-

Using The Electron Capture app instead of Chrome should work: - GET IT HERE -
- You can also turn off hardware-accleration in Chrome/Edge to fix the issue.

+

Try turning off hardware-accleration in Chrome/Edge to fix the issue, or maybe use a different browser.

@@ -687,7 +691,7 @@ -
+

Browse the Guides

@@ -714,22 +718,25 @@
  • - If you have "pixel smearing" or corrupted video, try adding &codec=h264 or &codec=vp9 to the OBS view link. Using Wi-Fi will make the issue worse. + Some devices that use H264 hardware encoding can experience video glitching; switching to VP8 or VP9 as a codec can help. +
  • +
  • + If using multiple group scenes at a time, iOS devices may fail to work if the hardware encoders max out. Perhaps try VP8 as a codec instead.
  • A list of less common issues can be found here.

  • - 👋 👀 Welcome to our new domain! We've started to rebrand to VDO.Ninja. 📼 Nothing else is changing and we're staying 100% free. + 👋 👀 Welcome to VDO Ninja! We've rebranded! 📼 Nothing else is changing and we're staying 100% free.


    - 🌻 Site Updated on June 6th. The new v18 release notes are here. If new issues occur, the previous version can also be found here. + 🌻 Site Updated on July 8th. The v18.3 release notes are here. If new issues occur, the previous version can also be found here.

    - 🛠 For support, see the sub-reddit or join the Discord . The documentation is here and my personal email is steve@seguin.email + 🛠 For support, see the sub-reddit or join the Discord . The documentation is here and my personal email is steve@seguin.email

    @@ -877,6 +884,7 @@ Show active speakers +
    Uses more CPU and freezes the video if the guest doesn't keep the tab visible. Virtual backgrounds +
    + + + Animate mixing +
    Enable equalizer as option
    -
    💉Can reduce packet loss video corruption in OBS on PC Use H264 codec +
    @@ -1045,6 +1067,14 @@ Fade-in videos +
    + + + Animate mixing +
    @@ -1090,8 +1120,8 @@ - -
    Learn more about URL parameters at params.obs.ninja + +
    Learn more about URL parameters at params.vdo.ninja
    @@ -1124,10 +1154,10 @@ Hangup - - + + Record + + + + +
    `; + + + document.body.insertAdjacentHTML("beforeend", modalTemplate); // Insert modal at body end + + document.getElementById("input_"+promptID).focus(); + + document.getElementById("input_"+promptID).addEventListener("keyup", function(event) { + if (event.key === "Enter") { + var pid = event.target.dataset.pid; + result = document.getElementById("input_"+pid).value; + document.getElementById("modal_"+pid).remove(); + document.getElementById("modalBackdrop_"+pid).remove(); + Prompts[pid].resolve(); + } + }); + + document.getElementById("submit_"+promptID).addEventListener("click", function(event){ + var pid = event.target.dataset.pid; + result = document.getElementById("input_"+pid).value; + document.getElementById("modal_"+pid).remove(); + document.getElementById("modalBackdrop_"+pid).remove(); + Prompts[pid].resolve(); + }); + + document.getElementById("cancel_"+promptID).addEventListener("click", function(event){ + var pid = event.target.dataset.pid; + document.getElementById("modal_"+pid).remove(); + document.getElementById("modalBackdrop_"+pid).remove(); + Prompts[pid].resolve(); + }); + + document.getElementById("close_"+promptID).addEventListener("click", function(event){ + var pid = event.target.dataset.pid; + document.getElementById("modal_"+pid).remove(); + document.getElementById("modalBackdrop_"+pid).remove(); + Prompts[pid].resolve(); + }); + + getById("modal_"+promptID).addEventListener("click", function(e) { + e.stopPropagation(); + return false; + }); + return; + }); + return result; +} + +async function confirmAlt(inputText, block=false){ + var result = null; + if (session.beepToNotify){ + playtone(); + } + await new Promise((resolve, reject) => { + var promptID = "pid_"+Math.random().toString(36).substr(2, 9); + Prompts[promptID] = {}; + Prompts[promptID].resolve = resolve; + Prompts[promptID].reject = reject; + + var zindex = 30 + document.querySelectorAll('.promptModal').length; + + if (block){ + var backdropClass = "opaqueBackdrop"; + } else { + var backdropClass = "modalBackdrop"; + } + + inputText = ""+inputText.replace("\n","
    ")+""; + inputText = inputText.replace(/\n/g,"
    "); + + modalTemplate = + ` +
    `; + + + document.body.insertAdjacentHTML("beforeend", modalTemplate); // Insert modal at body end + + document.getElementById("submit_"+promptID).focus(); + + document.getElementById("submit_"+promptID).addEventListener("click", function(event){ + var pid = event.target.dataset.pid; + result = true; + document.getElementById("modalBackdrop_"+pid).remove(); + document.getElementById("modal_"+pid).remove(); + Prompts[pid].resolve(); + }); + + document.getElementById("cancel_"+promptID).addEventListener("click", function(event){ + var pid = event.target.dataset.pid; + document.getElementById("modalBackdrop_"+pid).remove(); + document.getElementById("modal_"+pid).remove(); + Prompts[pid].resolve(); + }); + + document.getElementById("close_"+promptID).addEventListener("click", function(event){ + var pid = event.target.dataset.pid; + document.getElementById("modalBackdrop_"+pid).remove(); + document.getElementById("modal_"+pid).remove(); + Prompts[pid].resolve(); + }); + + getById("modal_"+promptID).addEventListener("click", function(e) { + e.stopPropagation(); + return false; + }); + return; + }); + return result; +} + +var warnUserTimeout=null; +function warnUser(message, timeout=false){ + // Allows for multiple alerts to stack better. + // Every modal and backdrop has an increasing z-index + // to block the previous modal + if (document.getElementById("modalBackdrop")){ + getById("alertModal").innerHTML = ''; // Delete modal + getById("alertModal").remove(); + getById("modalBackdrop").innerHTML = ''; // Delete modal + getById("modalBackdrop").remove(); + } + + zindex = 31 + document.querySelectorAll('.alertModal').length; + try{ + message = message.replace(/\n/g,"
    "); + } catch(e){ + errorlog(message); + } + modalTemplate = + `
    +
    + × + ${message} +
    +
    +
    `; + document.body.insertAdjacentHTML("beforeend", modalTemplate); // Insert modal at body end + + document.getElementById("modalBackdrop").addEventListener("click", closeModal); + + clearTimeout(warnUserTimeout); + if (timeout){ + warnUserTimeout = setTimeout(closeModal, timeout); + } + getById("alertModal").addEventListener("click", function(e) { + e.stopPropagation(); + return false; + }); + +} +function closeModal(){ + getById("modalBackdrop").innerHTML = ''; // Delete modal + getById("modalBackdrop").remove(); + getById("alertModal").innerHTML = ''; // Delete modal + getById("alertModal").remove(); + getById("promptModal").innerHTML = ''; // Delete modal + getById("promptModal").remove(); +} + +var sanitizeStreamID = function(streamID) { + streamID = streamID.trim(); + + if (streamID.length < 1) { + streamID = session.generateStreamID(8); + if (!(session.cleanOutput)) { + warnUser(miscTranslations["no-streamID-provided"] + streamID); + } + } + var streamID_sanitized = streamID.replace(/[\W]+/g, "_"); + if (streamID !== streamID_sanitized) { + if (!(session.cleanOutput)) { + warnUser(miscTranslations["alphanumeric-only"]); + } + } + if (streamID_sanitized.length > 44) { + streamID_sanitized = streamID_sanitized.substring(0, 44); + if (!(session.cleanOutput)) { + warnUser(miscTranslations["stream-id-too-long"]); + } + } + return streamID_sanitized; +}; + +var checkStrength = function(string) { + var matcher = /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{7,30}$/; + if (string.match(matcher)) { + return true; + } else if (string.length > 20) { + return true; + } else { + return false; + } +}; + +var checkStrengthRoom = function() { + var result1 = checkStrength(getById('videoname1').value); + var result2 = getById('passwordRoom').value.length; + var target = getById('securityLevelRoom'); + target.style.display = "block"; + if (result1) { + if (result2) { + target.innerHTML = ""+miscTranslations["share-with-trusted"]+""; + } else { + target.innerHTML = ""+miscTranslations["pass-recommended"]+""; + } + } else { + target.innerHTML = ""+miscTranslations["insecure-room-name"]+" "+miscTranslations["allowed-chars"]+": A-Z, a-z, 0-9, _"; + } +}; + +var emojiShortCodes ={":joy:":"😂",":heart:":"❤️",":heart_eyes:":"😍",":sob:":"😭",":blush:":"😊",":unamused:":"😒",":two_hearts:":"💕",":weary:":"😩",":ok_hand:":"👌",":pensive:":"😔",":smirk:":"😏",":grin:":"😁",":wink:":"😉",":thumbsup:":"👍",":pray:":"🙏",":relieved:":"😌",":notes:":"🎶",":flushed:":"😳",":raised_hands:":"🙌",":see_no_evil:":"🙈",":cry:":"😢",":sunglasses:":"😎",":v:":"✌️",":eyes:":"👀",":sweat_smile:":"😅",":sparkles:":"✨",":sleeping:":"😴",":smile:":"😄",":purple_heart:":"💜",":broken_heart:":"💔",":blue_heart:":"💙",":confused:":"😕",":disappointed:":"😞",":yum:":"😋",":neutral_face:":"😐",":sleepy:":"😪",":clap:":"👏",":cupid:":"💘",":heartpulse:":"💗",":kiss:":"💋",":point_right:":"👉",":scream:":"😱",":fire:":"🔥",":rage:":"😡",":smiley:":"😃",":tada:":"🎉",":tired_face:":"😫",":camera:":"📷",":rose:":"🌹",":muscle:":"💪",":skull:":"💀",":sunny:":"☀️",":yellow_heart:":"💛",":triumph:":"😤",":laughing:":"😆",":sweat:":"😓",":point_left:":"👈",":grinning:":"😀",":mask:":"😷",":green_heart:":"💚",":wave:":"👋",":persevere:":"😣",":heartbeat:":"💓",":crown:":"👑",":innocent:":"😇",":headphones:":"🎧",":confounded:":"😖",":angry:":"😠",":grimacing:":"😬",":star2:":"🌟",":gun:":"🔫",":raising_hand:":"🙋",":thumbsdown:":"👎",":dancer:":"💃",":musical_note:":"🎵",":no_mouth:":"😶",":dizzy:":"💫",":fist:":"✊",":point_down:":"👇",":no_good:":"🙅",":boom:":"💥",":tongue:":"👅",":poop:":"💩",":cold_sweat:":"😰",":gem:":"💎",":ok_woman:":"🙆",":pizza:":"🍕",":joy_cat:":"😹",":leaves:":"🍃",":sweat_drops:":"💦",":penguin:":"🐧",":zzz:":"💤",":walking:":"🚶",":airplane:":"✈️",":balloon:":"🎈",":star:":"⭐",":ribbon:":"🎀",":worried:":"😟",":underage:":"🔞",":fearful:":"😨",":hibiscus:":"🌺",":microphone:":"🎤",":open_hands:":"👐",":ghost:":"👻",":palm_tree:":"🌴",":nail_care:":"💅",":alien:":"👽",":bow:":"🙇",":cloud:":"☁",":soccer:":"⚽",":angel:":"👼",":dancers:":"👯",":snowflake:":"❄️",":point_up:":"☝️",":rainbow:":"🌈",":gift_heart:":"💝",":gift:":"🎁",":beers:":"🍻",":anguished:":"😧",":earth_africa:":"🌍",":movie_camera:":"🎥",":anchor:":"⚓",":zap:":"⚡",":runner:":"🏃",":sunflower:":"🌻",":bouquet:":"💐",":dog:":"🐶",":moneybag:":"💰",":herb:":"🌿",":couple:":"👫",":fallen_leaf:":"🍂",":tulip:":"🌷",":birthday:":"🎂",":cat:":"🐱",":coffee:":"☕",":dizzy_face:":"😵",":point_up_2:":"👆",":open_mouth:":"😮",":hushed:":"😯",":basketball:":"🏀",":ring:":"💍",":astonished:":"😲",":hear_no_evil:":"🙉",":dash:":"💨",":cactus:":"🌵",":hotsprings:":"♨️",":telephone:":"☎️",":maple_leaf:":"🍁",":princess:":"👸",":massage:":"💆",":love_letter:":"💌",":trophy:":"🏆",":blossom:":"🌼",":lips:":"👄",":fries:":"🍟",":doughnut:":"🍩",":frowning:":"😦",":ocean:":"🌊",":bomb:":"💣",":cyclone:":"🌀",":rocket:":"🚀",":umbrella:":"☔",":couplekiss:":"💏",":lollipop:":"🍭",":clapper:":"🎬",":pig:":"🐷",":smiling_imp:":"😈",":imp:":"👿",":bee:":"🐝",":kissing_cat:":"😽",":anger:":"💢",":santa:":"🎅",":earth_asia:":"🌏",":football:":"🏈",":guitar:":"🎸",":panda_face:":"🐼",":strawberry:":"🍓",":smirk_cat:":"😼",":banana:":"🍌",":watermelon:":"🍉",":snowman:":"⛄",":smile_cat:":"😸",":eggplant:":"🍆",":crystal_ball:":"🔮",":calling:":"📲",":iphone:":"📱",":partly_sunny:":"⛅",":warning:":"⚠️",":scream_cat:":"🙀",":baby:":"👶",":feet:":"🐾",":footprints:":"👣",":beer:":"🍺",":wine_glass:":"🍷",":video_camera:":"📹",":rabbit:":"🐰",":smoking:":"🚬",":peach:":"🍑",":snake:":"🐍",":turtle:":"🐢",":cherries:":"🍒",":kissing:":"😗",":frog:":"🐸",":milky_way:":"🌌",":closed_book:":"📕",":candy:":"🍬",":hamburger:":"🍔",":bear:":"🐻",":tiger:":"🐯",":icecream:":"🍦",":pineapple:":"🍍",":ear_of_rice:":"🌾",":syringe:":"💉",":tv:":"📺",":pill:":"💊",":octopus:":"🐙",":grapes:":"🍇",":smiley_cat:":"😺",":cd:":"💿",":cocktail:":"🍸",":cake:":"🍰",":video_game:":"🎮",":lipstick:":"💄",":whale:":"🐳",":cookie:":"🍪",":dolphin:":"🐬",":loud_sound:":"🔊",":man:":"👨",":monkey:":"🐒",":books:":"📚",":guardsman:":"💂",":loudspeaker:":"📢",":scissors:":"✂️",":girl:":"👧",":mortar_board:":"🎓",":baseball:":"⚾️",":woman:":"👩",":fireworks:":"🎆",":stars:":"🌠",":mushroom:":"🍄",":pouting_cat:":"😾",":left_luggage:":"🛅",":high_heel:":"👠",":dart:":"🎯",":swimmer:":"🏊",":key:":"🔑",":bikini:":"👙",":family:":"👪",":pencil2:":"✏",":elephant:":"🐘",":droplet:":"💧",":seedling:":"🌱",":apple:":"🍎",":dollar:":"💵",":book:":"📖",":haircut:":"💇",":computer:":"💻",":bulb:":"💡",":boy:":"👦",":tangerine:":"🍊",":sunrise:":"🌅",":poultry_leg:":"🍗",":shaved_ice:":"🍧",":bird:":"🐦",":eyeglasses:":"👓",":goat:":"🐐",":older_woman:":"👵",":new_moon:":"🌑",":customs:":"🛃",":house:":"🏠",":full_moon:":"🌕",":lemon:":"🍋",":baby_bottle:":"🍼",":spaghetti:":"🍝",":wind_chime:":"🎐",":fish_cake:":"🍥",":nose:":"👃",":pig_nose:":"🐽",":fish:":"🐟",":koala:":"🐨",":ear:":"👂",":shower:":"🚿",":bug:":"🐛",":ramen:":"🍜",":tophat:":"🎩",":fuelpump:":"⛽",":horse:":"🐴",":watch:":"⌚",":monkey_face:":"🐵",":baby_symbol:":"🚼",":sparkler:":"🎇",":corn:":"🌽",":tennis:":"🎾",":battery:":"🔋",":wolf:":"🐺",":moyai:":"🗿",":cow:":"🐮",":mega:":"📣",":older_man:":"👴",":dress:":"👗",":link:":"🔗",":chicken:":"🐔",":whale2:":"🐋",":bento:":"🍱",":pushpin:":"📌",":dragon:":"🐉",":hamster:":"🐹",":golf:":"⛳",":surfer:":"🏄",":mouse:":"🐭",":blue_car:":"🚙",":bread:":"🍞",":cop:":"👮",":tea:":"🍵",":bike:":"🚲",":rice:":"🍚",":radio:":"📻",":baby_chick:":"🐤",":sheep:":"🐑",":lock:":"🔒",":green_apple:":"🍏",":racehorse:":"🐎",":fried_shrimp:":"🍤",":volcano:":"🌋",":rooster:":"🐓",":inbox_tray:":"📥",":wedding:":"💒",":sushi:":"🍣",":ice_cream:":"🍨",":tomato:":"🍅",":rabbit2:":"🐇",":beetle:":"🐞",":bath:":"🛀",":no_entry:":"⛔",":crocodile:":"🐊",":dog2:":"🐕",":cat2:":"🐈",":hammer:":"🔨",":meat_on_bone:":"🍖",":shell:":"🐚",":poodle:":"🐩",":stew:":"🍲",":jeans:":"👖",":honey_pot:":"🍯",":unlock:":"🔓",":black_nib:":"✒",":snowboarder:":"🏂",":white_flower:":"💮",":necktie:":"👔",":womens:":"🚺",":ant:":"🐜",":city_sunset:":"🌇",":dragon_face:":"🐲",":snail:":"🐌",":dvd:":"📀",":shirt:":"👕",":game_die:":"🎲",":dolls:":"🎎",":8ball:":"🎱",":bus:":"🚌",":custard:":"🍮",":camel:":"🐫",":curry:":"🍛",":hospital:":"🏥",":bell:":"🔔",":pear:":"🍐",":door:":"🚪",":saxophone:":"🎷",":church:":"⛪",":bicyclist:":"🚴",":dango:":"🍡",":office:":"🏢",":rowboat:":"🚣",":womans_hat:":"👒",":mans_shoe:":"👞",":love_hotel:":"🏩",":mount_fuji:":"🗻",":handbag:":"👜",":hourglass:":"⌛",":trumpet:":"🎺",":school:":"🏫",":cow2:":"🐄",":toilet:":"🚽",":pig2:":"🐖",":violin:":"🎻",":credit_card:":"💳",":ferris_wheel:":"🎡",":bowling:":"🎳",":barber:":"💈",":purse:":"👛",":rat:":"🐀",":date:":"📅",":ram:":"🐏",":tokyo_tower:":"🗼",":kimono:":"👘",":ship:":"🚢",":mag_right:":"🔎",":mag:":"🔍",":fire_engine:":"🚒",":police_car:":"🚓",":black_joker:":"🃏",":package:":"📦",":calendar:":"📆",":horse_racing:":"🏇",":tiger2:":"🐅",":boot:":"👢",":ambulance:":"🚑",":boar:":"🐗",":pound:":"💷",":ox:":"🐂",":rice_ball:":"🍙",":sandal:":"👡",":tent:":"⛺",":seat:":"💺",":taxi:":"🚕",":briefcase:":"💼",":newspaper:":"📰",":circus_tent:":"🎪",":mens:":"🚹",":flashlight:":"🔦",":foggy:":"🌁",":bamboo:":"🎍",":ticket:":"🎫",":helicopter:":"🚁",":minidisc:":"💽",":oncoming_bus:":"🚍",":melon:":"🍈",":notebook:":"📓",":no_bell:":"🔕",":oden:":"🍢",":flags:":"🎏",":blowfish:":"🐡",":sweet_potato:":"🍠",":ski:":"🎿",":construction:":"🚧",":satellite:":"📡",":euro:":"💶",":ledger:":"📒",":leopard:":"🐆",":truck:":"🚚",":sake:":"🍶",":railway_car:":"🚃",":speedboat:":"🚤",":vhs:":"📼",":yen:":"💴",":mute:":"🔇",":wheelchair:":"♿",":paperclip:":"📎",":atm:":"🏧",":telescope:":"🔭",":rice_scene:":"🎑",":blue_book:":"📘",":postbox:":"📮",":e-mail:":"📧",":mouse2:":"🐁",":nut_and_bolt:":"🔩",":hotel:":"🏨",":wc:":"🚾",":green_book:":"📗",":tractor:":"🚜",":fountain:":"⛲",":metro:":"🚇",":clipboard:":"📋",":no_smoking:":"🚭",":slot_machine:":"🎰",":bathtub:":"🛁",":scroll:":"📜",":station:":"🚉",":rice_cracker:":"🍘",":bank:":"🏦",":wrench:":"🔧",":bar_chart:":"📊",":minibus:":"🚐",":tram:":"🚊",":microscope:":"🔬",":bookmark:":"🔖",":pouch:":"👝",":fax:":"📠",":sound:":"🔉",":chart:":"💹",":floppy_disk:":"💾",":post_office:":"🏣",":speaker:":"🔈",":japan:":"🗾",":mahjong:":"🀄",":orange_book:":"📙",":restroom:":"🚻",":train:":"🚋",":trolleybus:":"🚎",":postal_horn:":"📯",":factory:":"🏭",":train2:":"🚆",":pager:":"📟",":outbox_tray:":"📤",":mailbox:":"📫",":light_rail:":"🚈",":busstop:":"🚏",":file_folder:":"📁",":card_index:":"📇",":monorail:":"🚝",":no_bicycles:":"🚳",":hugging:":"🤗",":thinking:":"🤔",":nerd:":"🤓",":zipper_mouth:":"🤐",":rolling_eyes:":"🙄",":upside_down:":"🙃",":slight_smile:":"🙂",":writing_hand:":"✍",":eye:":"👁",":man_in_suit:":"🕴",":golfer:":"🏌",":golfer_woman:":"🏌‍♀",":anger_right:":"🗯",":coffin:":"⚰",":gear:":"⚙",":alembic:":"⚗",":scales:":"⚖",":keyboard:":"⌨",":shield:":"🛡",":bed:":"🛏",":ballot_box:":"🗳",":compression:":"🗜",":wastebasket:":"🗑",":file_cabinet:":"🗄",":trackball:":"🖲",":printer:":"🖨",":joystick:":"🕹",":hole:":"🕳",":candle:":"🕯",":prayer_beads:":"📿",":amphora:":"🏺",":label:":"🏷",":film_frames:":"🎞",":level_slider:":"🎚",":thermometer:":"🌡",":motorway:":"🛣",":synagogue:":"🕍",":mosque:":"🕌",":kaaba:":"🕋",":stadium:":"🏟",":desert:":"🏜",":cityscape:":"🏙",":camping:":"🏕",":rosette:":"🏵",":volleyball:":"🏐",":medal:":"🏅",":popcorn:":"🍿",":champagne:":"🍾",":hot_pepper:":"🌶",":burrito:":"🌯",":taco:":"🌮",":hotdog:":"🌭",":shamrock:":"☘",":comet:":"☄",":turkey:":"🦃",":scorpion:":"🦂",":lion_face:":"🦁",":crab:":"🦀",":spider_web:":"🕸",":spider:":"🕷",":chipmunk:":"🐿",":fog:":"🌫",":chains:":"⛓",":pick:":"⛏",":stopwatch:":"⏱",":ferry:":"⛴",":mountain:":"⛰",":ice_skate:":"⛸",":skier:":"⛷",":sad:":"😥",":egg:":"🥚",":drum:":"🥁"}; + +function convertShortcodes(string){ + if (string.split(":").length>2){ + for (var i in emojiShortCodes) { + if (string.includes(i)) { + string = string.replaceAll(i, emojiShortCodes[i]); + } + } + } + return string; +} + +var sanitizeChat = function(string) { + var temp = document.createElement('div'); + temp.innerText = string; + temp.innerText = temp.innerHTML; + temp = temp.textContent || temp.innerText || ""; + temp = temp.substring(0, Math.min(temp.length, 500)); + return temp.trim(); +}; + +var sanitizeString = function(str) { + str = str.replace(/[^a-z0-9áéíóúñü \.,_-]/gim, ""); + return str.trim(); +}; + +var sanitizeLabel = function(string) { + let temp = document.createElement("div"); + temp.innerText = string; + temp.innerText = temp.innerHTML; + temp = temp.textContent || temp.innerText || ""; + temp = temp.substring(0, Math.min(temp.length, 50)); + return temp.trim(); +}; + +var sanitizeRoomName = function(roomid) { + roomid = roomid.trim(); + if (roomid === "") { + return roomid; + } else if (roomid === false) { + return roomid; + } + + var sanitized = roomid.replace(/[\W]+/g, "_"); + if (sanitized !== roomid) { + if (!(session.cleanOutput)) { + warnUser("Info: Only AlphaNumeric characters should be used for the room name.\n\nThe offending characters have been replaced by an underscore"); + } + } + if (sanitized.length > 30) { + sanitized = sanitized.substring(0, 30); + if (!(session.cleanOutput)) { + warnUser("The Room name should be less than 31 alPhaNuMeric characters long.\n\nWe will trim it to length."); + } + } + return sanitized; +}; + +var sanitizePassword = function(passwrd) { + if (passwrd === "") { + return passwrd; + } else if (passwrd === false) { + return passwrd; + } else if (passwrd === null) { + return passwrd; + } + passwrd = passwrd.trim(); + if (passwrd.length < 1) { + if (!(session.cleanOutput)) { + warnUser("The password provided was blank."); + } + } + var sanitized = encodeURIComponent(passwrd);//.replace(/[\W]+/g, "_"); + //if (sanitized !== passwrd) { + // if (!(session.cleanOutput)) { + // warnUser("Info: Only AlphaNumeric characters should be used in the password.\n\nThe offending characters have been replaced by an underscore"); + // } + //} + return sanitized; +}; + +function isOperaGX(){ + return (!!window.opr && !!opr.addons) || !!window.opera || navigator.userAgent.indexOf(' OPR/75') >= 0; +} + +function getChromeVersion() { + var raw = navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./); + return raw ? parseInt(raw[2], 10) : false; +} + +function checkConnection() { + if (session.ws === null) { + return; + } + if (!session.cleanOutput){ + if (document.getElementById("qos")) { // true or false; null might cause problems? + getById("logoname").style.display = "unset"; + if ((session.ws) && (session.ws.readyState === WebSocket.OPEN)) { + getById("qos").style.color = "white"; + } else { + getById("qos").style.color = "red"; + } + } + } +} + +function safariVersion() { + var ver = 0; + try { + ver = navigator.appVersion.split("Version/"); + if (ver.length > 1) { + ver = ver[1].split(" Safari"); + } + if (ver.length > 1) { + ver = ver[0].split("."); + } + if (ver.length > 1) { + ver = parseInt(ver[0]); + } else { + ver = 0; + } + } catch (e) { + return 0; + } + return ver; +} + +function obsSceneChanged(event){ + log(event.detail.name); + window.obsstudio.getCurrentScene(function(scene) { + log("OBS SCENE"); + log(scene); + }); +} +function obsStreamingStarted(event){ + session.obsState.streaming = true; + session.obsStateSync(); +} +function obsStreamingStopped(event){ + session.obsState.streaming = false; + session.obsStateSync(); +} +function obsRecordingStarted(event){ + session.obsState.recording = true; + session.obsStateSync(); +} +function obsRecordingStopped(event){ + session.obsState.recording = false; + session.obsStateSync(); +} +function obsSourceActiveChanged(event){ + warnlog("obsSourceActiveChanged"); + warnlog( event.detail); + + try { + if (typeof event==="boolean"){var sourceActive = event;} + else if (typeof event.detail === "boolean"){var sourceActive = event.detail;} + else if (typeof event.detail.active === "boolean"){var sourceActive = event.detail.active;} + else {var sourceActive = event.detail.active;} + + if (typeof sourceActive === "undefined"){return;} // Just fail. + + if (session.obsState.sourceActive!==sourceActive){ // only move forward if there is a change; the event likes to double fire you see. + session.obsState.sourceActive = sourceActive; + session.obsStateSync(); + } + + } catch (e){errorlog(e);} +} + +function obsSourceVisibleChanged(event){ // accounts for visible in VDO.Ninja scene AND visible in OBS scene + warnlog("obsSourceVisibleChanged"); + warnlog(event.detail); + try { + if (typeof event==="boolean"){var visibility = event;} + else if (typeof event.detail === "boolean"){var visibility = event.detail;} + else if (typeof event.detail.visible === "boolean"){var visibility = event.detail.visible;} + else {var visibility = event.detail.visible;} + + if (typeof visibility === "undefined"){ // fall back + if (typeof document.visibilityState !== "undefined"){ + visibility = document.visibilityState==="visible"; // modern + } else if (typeof document.hidden !== "undefined"){ + visibility = !document.hidden; // legacy + } else { + return; // ... unknown input? fail. + } + } + + errorlog("visibility: "+visibility); + + if (session.obsState.visibility!==visibility){ // only move forward if there is a change; the event likes to double fire you see. + session.obsState.visibility = visibility; + session.obsStateSync(); + } + + } catch (e){errorlog(e);} +} + + + +function manageSceneState(data, UUID){ + if (session.disableOBS){return;} + var processNeeded = false + try{ + if ("sceneDisplay" in data){ + processNeeded=true; + session.pcs[UUID].sceneDisplay = data.sceneDisplay; + } + if ("sceneMute" in data){ + processNeeded=true; + session.pcs[UUID].sceneMute = data.sceneMute; + } + if ("obsSourceActive" in data){ + processNeeded=true; + session.pcs[UUID].obsSourceActive = data.obsSourceActive; + } + if ("obsVisibility" in data){ + processNeeded=true; + session.pcs[UUID].obsVisibility = data.obsVisibility; + session.optimizeBitrate(UUID); // &optimize flag; sets video bitrate to target value if this flag == HIDDEN (if optimize=0, disables both audio and video) + } + if ("obsStreaming" in data){ + processNeeded=true; + session.pcs[UUID].obsStreaming = data.obsStreaming; + } + if ("obsRecording" in data){ + processNeeded=true; + session.pcs[UUID].obsRecording = data.obsRecording; + } + } catch(e){} // just in case the client has disconnected. + + if (processNeeded){ + applySceneState(); + } +} + +function applySceneState(){ + if (session.disableOBS){return;} + if (session.cleanOutput===false){ + if (document.getElementById("videosource")){ + var visibility = false; + var ondeck = false; + var recording = false; + for (var uid in session.pcs){ + + if (session.pcs[uid].obsSourceActive!==false && session.pcs[uid].obsVisibility && (session.pcs[uid].sceneDisplay!==false)){ + visibility=true; + } else if (session.pcs[uid].obsVisibility && (session.pcs[uid].sceneDisplay!==false)){ + ondeck=true; + } + if ((session.pcs[uid].obsRecording || session.pcs[uid].obsStreaming) && (session.pcs[uid].obsSourceActive!==false && session.pcs[uid].obsVisibility && (session.pcs[uid].sceneDisplay!==false))){ // the scene that is recording must be visible also. + recording=true; + } + } + + if (recording){ + getById("obsState").classList.remove("ondeck"); + getById("obsState").classList.add("recording"); // TODO: this needs to check all peers to make sure it's valid + getById("obsState").innerHTML = "ON AIR"; + } else if (ondeck && !visibility){ + getById("obsState").classList.remove("recording"); + getById("obsState").classList.add("ondeck"); // TODO: this needs to check all peers to make sure it's valid + getById("obsState").innerHTML = "STAND BY"; + } else { + getById("obsState").classList.remove("recording"); + getById("obsState").classList.remove("ondeck"); + getById("obsState").innerHTML = "ACTIVE"; + } + + if (visibility){ // BASIC TALLY LIGHT (on deck disabled) + getById("obsState").classList.add("onair"); // LIVE + } else { + getById("obsState").classList.remove("onair"); + + } + } + } +} + +window.onpopstate = function() { + if (session.firstPlayTriggered) { + window.location.reload(true); + } +}; + +var miniPerformerX = null; +var miniPerformerY = null; +function makeMiniDraggableElement(elmnt) { + try { + elmnt.dragElement = false; + elmnt.style.bottom = "auto"; + elmnt.style.cursor = "grab"; + + elmnt.stashonmouseup = null; + elmnt.stashonmousemove = null; + + } catch (e) { + errorlog(e); + return; + } + + var pos1 = 0; + var pos2 = 0; + var pos3 = 0; + var pos4 = 0; + + var timestamp = false; + + function elementDrag(e) { // ON DRAG + timestamp = false; + if (session.infocus){return;} + try { + e = e || window.event; + + if (e.type !== "touchmove"){ + if (e.button !== 0){return;} + + e.preventDefault(); + } + e.stopPropagation(); + + elmnt.dragElement = true; + + if (e.type === "touchmove"){ + pos1 = pos3 - e.touches[0].clientX; + pos2 = pos4 - e.touches[0].clientY; + pos3 = e.touches[0].clientX; + pos4 = e.touches[0].clientY; + } else { + pos1 = pos3 - e.clientX; + pos2 = pos4 - e.clientY; + pos3 = e.clientX; + pos4 = e.clientY; + } + + var topDrag = (elmnt.offsetTop - pos2 ); + if (topDrag > (-3 + (window.innerHeight - elmnt.clientHeight))){ + topDrag = (-3 + (window.innerHeight - elmnt.clientHeight)); + } + + miniPerformerY = topDrag; + miniPerformerX = elmnt.offsetLeft - pos1; + + if (miniPerformerY > window.innerHeight-elmnt.clientHeight){ + miniPerformerY = window.innerHeight-elmnt.clientHeight; + } + if (miniPerformerX > window.innerWidth-elmnt.clientWidth){ + miniPerformerX = window.innerWidth-elmnt.clientWidth; + } + + miniPerformerX = 100 * miniPerformerX/window.innerWidth; + miniPerformerY = 100 * miniPerformerY/window.innerHeight; + + if (miniPerformerY<0){ + miniPerformerY=0; + } else if (miniPerformerY>100){ + miniPerformerY=100; + } + if (miniPerformerX<0){ + miniPerformerX=0; + } else if (miniPerformerX>100){ + miniPerformerX=100; + } + + elmnt.style.right = "unset"; + elmnt.style.top = miniPerformerY + "%"; + elmnt.style.left = miniPerformerX + "%"; + + + } catch(e){errorlog(e);} + } + + + function closeDragElement(e) { // TOUCH END + e = e || window.event; + + if (e.type !== "touchend"){ + if (e.button !== 0){return;} + document.onmouseup = elmnt.stashonmouseup; + document.onmousemove = elmnt.stashonmousemove; + } + + + if (session.infocus){return;} + e.preventDefault(); + + if (timestamp && (Date.now()- timestamp>500)){ // long hold, so this is a drag + e.stopPropagation(); + if (e.type === "touchend"){ + if (session.infocus === true){ + session.infocus = false; + } else { + session.infocus = true; + log("session: myself"); + } + setTimeout(()=>updateMixer(),10); + } + } else if (timestamp && (e.type !== "touchend")){ + if (session.infocus === true){ + session.infocus = false; + } else { + session.infocus = true; + log("session: myself"); + } + setTimeout(()=>updateMixer(),10); + } + } + + function dragMouseDown(e) { ////// TOUCH START + + if (event.ctrlKey || event.metaKey) {return;} + + timestamp = Date.now(); + + e = e || window.event; + if (session.infocus){return;} + + e.preventDefault(); + if (e.type === "touchstart"){ + pos3 = e.touches[0].clientX; + pos4 = e.touches[0].clientY; + + elmnt.ontouchend = closeDragElement; + elmnt.ontouchmove = elementDrag; + } else { + if (e.button !== 0){return;} + pos3 = e.clientX; + pos4 = e.clientY; + elmnt.stashonmouseup = document.onmouseup; // I don't want to interfere with other drag events. + elmnt.stashonmousemove = document.onmousemove; + + document.onmouseup = closeDragElement; + document.onmousemove = elementDrag; + } + + } + + elmnt.onmousedown = dragMouseDown; + elmnt.ontouchstart = dragMouseDown; +} + +function makeDraggableElement(elmnt, absolute=false) { + try { + elmnt.dragElement = false; + elmnt.style.bottom = "auto"; + elmnt.style.cursor = "grab"; + elmnt.stashonmouseup = null; + elmnt.stashonmousemove = null; + + } catch (e) { + errorlog(e); + return; + } + + var pos1 = 0; + var pos2 = 0; + var pos3 = 0; + var pos4 = 0; + + var timestamp = false; + + function dragMouseDown(e) { + timestamp = Date.now(); + + e = e || window.event; + e.preventDefault(); + + pos3 = e.clientX; + pos4 = e.clientY; + elmnt.stashonmouseup = document.onmouseup; // I don't want to interfere with other drag events. + elmnt.stashonmousemove = document.onmousemove; + + document.onmouseup = closeDragElement; + document.onmousemove = elementDrag; + } + + function elementDrag(e) { + e = e || window.event; + e.preventDefault(); + + elmnt.dragElement = true; + pos1 = pos3 - e.clientX; + pos2 = pos4 - e.clientY; + pos3 = e.clientX; + pos4 = e.clientY; + + var topDrag = (elmnt.offsetTop - pos2 ); + if (absolute){ + if (topDrag > (-3 + (window.innerHeight - elmnt.clientHeight))){ + topDrag = (-3 + (window.innerHeight - elmnt.clientHeight)); + } + } else { + if (topDrag > -3){ + topDrag = -3; + } + } + elmnt.style.top = topDrag + "px"; + elmnt.style.left = (elmnt.offsetLeft - pos1) + "px"; + + } + + elmnt.onmousedown = dragMouseDown; + function closeDragElement(e) { + document.onmouseup = elmnt.stashonmouseup; + document.onmousemove = elmnt.stashonmousemove; + } +} + +function setStorage(cname, cvalue, exdays=999){ // not actually a cookie + var now = new Date(); + var item = { + value: cvalue, + expiry: now.getTime() + (exdays * 24 * 60 * 60 * 1000), + }; + localStorage.setItem(cname, JSON.stringify(item)); +} + +function getStorage(cname) { + var itemStr = localStorage.getItem(cname); + if (!itemStr) { + return ""; + } + var item = JSON.parse(itemStr); + var now = new Date(); + if (now.getTime() > item.expiry) { + localStorage.removeItem(cname); + return ""; + } + return item.value; +} + +function setupIncomingVideoTracking(v, UUID){ // video element. + + if (session.directorUUID===UUID){ + v.muted=false; + } else { + v.muted = session.speakerMuted; + } + + v.onpause = (event) => { // prevent things from pausing; human or other + if (!((event.ctrlKey) || (event.metaKey) )){ + warnlog("Video paused; force it to play again"); + //return; + //session.audioCtx.resume(); + //log("ctx resume"); + + event.currentTarget.play().then(_ => { + log("playing"); + }).catch(error => { + warnlog("didnt play 1"); + }); + + } + } + + v.onplay = function(){ + try { + var bigPlayButton = document.getElementById("bigPlayButton"); + if (bigPlayButton){ + bigPlayButton.parentNode.removeChild(bigPlayButton); + } + } catch(e){} + if (session.pip){ + if (v.readyState >= 3){ + if (!(v.pip)){ + v.pip=true; + toggleSystemPip(v, true); + } + } + } + + } + + if (session.pip){ + v.onloadedmetadata = function(){ + if (!v.paused){ + if (!(v.pip)){ + v.pip=true; + toggleSystemPip(v, true); + } + } + } + } + + + v.addEventListener('resize', (e) => { + log("resize event"); + var aspectRatio = parseFloat(e.target.videoWidth/e.target.videoHeight); + if (v.dataset.aspectRatio){ + if (aspectRatio != v.dataset.aspectRatio){ + setTimeout(function(){updateMixer();},1); // We don't want to run this on the first resize? just subsequent ones. + } + } else { + log("ASPECT RATIO CHANGED"); + setTimeout(function(){updateMixer();},1); + } + v.dataset.aspectRatio = parseFloat(e.target.videoWidth/e.target.videoHeight); + }); + + v.volume = 1.0; // play audio automatically + v.autoplay = true; + v.controls = false; + v.classList.add("tile"); + v.setAttribute("playsinline",""); + v.controlTimer = null; + + changeAudioOutputDevice(v); // if enabled, changes to desired output audio device. + + if (document.getElementById("mainmenu")){ + var m = getById("mainmenu"); + m.remove(); + } + + if (session.director){ + v.controls = true; + var container = getById("videoContainer_"+UUID); + v.disablePictureInPicture = false + v.setAttribute("controls","controls") + container.appendChild(v); + session.requestRateLimit(session.directorViewBitrate,UUID); /// limit resolution for director + + if (session.beepToNotify) { + playtone(); + } + + } else if (session.scene!==false){ + v.controls = false; + + if (session.view){ // specific video to be played + v.style.display="block"; + } else if (session.scene==="0"){ + v.style.display="block"; + } else { // group scene I guess; needs to be added manually + v.style.display="none"; + v.muted= true; + } + + setTimeout(function(){updateMixer();},1); + } else if (session.roomid!==false){ + if (session.cleanOutput){ + v.controls = false; + } else if (window.obsstudio) { + v.controls = false; + } else { + v.controls = true; + } + if ((session.roomid==="") && (session.bitrate)){ + // let's keep the default bitrates, since this isn't a real room and bitrates are specified. + } else if (session.novideo !== false){ + if (session.novideo.includes(session.rpcs[UUID].streamID)){ + session.requestRateLimit(0,UUID);// limit resolution for guests see ln: 1804 in main.js also + } + } else { + session.requestRateLimit(0,UUID);// limit resolution for guests see ln: 1804 in main.js also + } + setTimeout(function(){updateMixer();},1); + } else { + v.style.display="block"; + if (window.obsstudio) { + v.controls = false; + } + setTimeout(function(){updateMixer();},1); + } + + + v.addEventListener('click', function(e) { // show stats of video if double clicked + log("clicked"); + try { + if ((e.ctrlKey)||(e.metaKey)){ + e.preventDefault(); + var uid = e.currentTarget.dataset.UUID; + if ("stats" in session.rpcs[uid]){ + + var [menu, innerMenu] = statsMenuCreator(); + + printViewStats(innerMenu, uid ); + + menu.interval = setInterval(printViewStats,3000, innerMenu, uid); + + + } + e.stopPropagation(); + return false; + } + } catch(e){errorlog(e);} + }); + + if (session.statsMenu){ + if ("stats" in session.rpcs[UUID]){ + + if (getById("menuStatsBox")){ + clearInterval(getById("menuStatsBox").interval); + getById("menuStatsBox").remove(); + } + + var [menu, innerMenu] = statsMenuCreator(); + + printViewStats(innerMenu, UUID ); + + menu.interval = setInterval(printViewStats,3000, innerMenu, UUID); + + } + } + + + v.touchTimeOut = null; + v.touchLastTap = 0; + v.touchCount = 0; + v.addEventListener('touchend', function(event) { + log("touched"); + + document.ontouchup = null; + document.onmouseup = null; + document.onmousemove = null; + document.ontouchmove = null; + + var currentTime = new Date().getTime(); + var tapLength = currentTime - v.touchLastTap; + clearTimeout(v.touchTimeOut); + if (tapLength < 500 && tapLength > 0) { + /// + log("double touched"); + v.touchCount+=1; + event.preventDefault(); + if (v.touchCount<5){ + v.touchLastTap = currentTime; + return false; + } + v.touchLastTap = 0; + v.touchCount=0; + + log("double touched"); + var uid = event.currentTarget.dataset.UUID; + if ("stats" in session.rpcs[uid]){ + + var [menu, innerMenu] = statsMenuCreator(); + + printViewStats(innerMenu, uid ); + + menu.interval = setInterval(printViewStats,3000, innerMenu, uid); + + + } + event.stopPropagation(); + return false; + ////// + } else { + v.touchCount=1; + v.touchTimeOut = setTimeout(function(vv) { + clearTimeout(vv.touchTimeOut); + vv.touchLastTap = 0; + vv.touchCount=0; + }, 5000, v); + v.touchLastTap = currentTime; + } + + }); + + + if (session.remote){ + v.addEventListener("wheel", session.remoteControl); + } + + if (v.controls == false){ + v.addEventListener("click", function () { + if (v.paused){ + log("PLAYING MANUALLY?"); + v.play().then(_ => { + log("playing"); + }).catch(warnlog); + } + }); + if (session.nocursor==false){ // we do not want to show the controls. This is because MacOS + OBS does not work; so electron app needs this. + if (!(session.cleanOutput)){ + if (!(window.obsstudio)){ + if (session.scene===false){ + if (session.permaid!==false){ + if (v.controlTimer){ + clearInterval(v.controlTimer); + } + v.controlTimer = setTimeout(showControlBar.bind(null,v),3000); + //v.controlTimer = setTimeout(function (){v.controls=true;},3000); // 3 seconds before I enable the controls automatically. This way it doesn't auto appear during loading. 3s enough, right? + } + } + } + } + } + } + + if (session.fadein){ + v.addEventListener('animationend', function(e) { + v.classList.remove("fadein"); // allows the video to fade in. + }); + v.classList.add("fadein"); // allows the video to fade in. + } + + setTimeout(session.processStats, 1000, UUID); + +} + +function showControlBar(vel){ + try { + vel.controls=true; + } catch(e){errorlog(e);} +} + + +function updateMixerRun(e=false){ // this is the main auto-mixing code. It's a giant function that runs when there are changes to screensize, video track statuses, etc. + if (getById("subControlButtons").dragElement){ + if (parseInt(getById("subControlButtons").style.top) > 0){ + getById("subControlButtons").style.top = "0px"; + } else if (parseInt(getById("subControlButtons").style.top) < parseInt(50 - window.innerHeight) ){ + getById("subControlButtons").style.top = parseInt( 50 - window.innerHeight)+"px"; + } + if (parseInt(getById("subControlButtons").style.left) < 0){ + getById("subControlButtons").style.left = "0px"; + } else if (parseInt(getById("subControlButtons").style.left) > parseInt( window.innerWidth - getById("subControlButtons").offsetWidth) ){ + getById("subControlButtons").style.left = parseInt( window.innerWidth -getById("subControlButtons").offsetWidth )+"px"; + } + } + if (session.director){return;} + if (session.manual === true){return;} + + var header = getById("header"); + + var hi = header.offsetHeight ; + var w = window.innerWidth; + var h = window.innerHeight - hi; + + if ( window.innerHeight<=700 ){ + if (document.getElementById("controlButtons")){ + var h = window.innerHeight - hi - document.getElementById("controlButtons").offsetHeight; + } else { + var h = window.innerHeight - hi; + } + } + + var arW = 16.0; + var arH = 9.0; + + if (session.aspectratio){ + if (session.aspectratio==1){ + arW = 9.0; + arH = 16.0; + } else if (session.aspectratio==2){ + arW = 12.0; // square root; cause why not. + arH = 12.0; + } + } + + var ww = w/arW; + var hh = h/arH; + + var mediaPool = []; + var mediaPool_invisible = []; + + if (session.videoElement){ // I, myself, exist + if (session.videoElement.style.display!="none"){ // local feed + if (session.minipreview && (session.infocus!==true)){ + + /* session.videoElement.onclick = function(){ + if (session.infocus === true){ + session.infocus = false; + } else { + session.infocus = true; + log("session: myself"); + } + setTimeout(()=>updateMixer(),10); + }; */ + + } else { + if (session.order!==false){ + session.videoElement.order=session.order; + } else { + session.videoElement.order=0; + } + if (session.activeSpeaker && (!session.activelySpeaking)){ + mediaPool_invisible.push(session.videoElement); + } else { + mediaPool.push(session.videoElement); + } + } + } + } + + if (session.screenShareElement){ // I, myself, exist + if (session.screenShareElement.style.display!="none"){ // local feed + if (session.order!==false){ + session.screenShareElement.order=session.order; + } else { + session.screenShareElement.order=0; + } + + if (session.infocus!==false){ + mediaPool_invisible.push(session.screenShareElement); + } else if (session.activeSpeaker && (!session.activelySpeaking)){ + mediaPool_invisible.push(session.screenShareElement); + } else { + mediaPool.push(session.screenShareElement); + } + } + } + + if (session.iframeEle){ // I, myself, exist + if (session.iframeEle.style.display!="none"){ // local feed + if (session.order!==false){ + session.iframeEle.order=session.order; + } else { + session.iframeEle.order=0; + } + if (session.activeSpeaker && (!session.activelySpeaking)){ + mediaPool_invisible.push(session.iframeEle); + } else { + mediaPool.push(session.iframeEle); + } + } + } + + + if ((session.infocus) && (session.infocus in session.rpcs)){ // remote guest being full screened; infocus == UUID + log(session.infocus+" set fullscreen"); + mediaPool = []; // remove myself from fullscreen + for (var j in session.rpcs){ + if (j != session.infocus){ + session.requestRateLimit(0, j); // disable the video of non-fullscreen videos + try { + if (session.rpcs[j].videoElement.style.display!="none"){ // Add it if not hidden + mediaPool_invisible.push(session.rpcs[j].videoElement); + } + } catch(e){} + } else { // in focus video + //////// + try { + if (session.rpcs[j].order!==false){ + session.rpcs[j].videoElement.order=session.rpcs[j].order; + } else { + session.rpcs[j].videoElement.order=0; + } + /////////// + if (session.activeSpeaker && (!session.rpcs[j].activelySpeaking)){ + mediaPool_invisible.push(session.rpcs[j].videoElement); + } else { + mediaPool.push(session.rpcs[j].videoElement); + } + + session.rpcs[j].videoElement.style.visibility = "visible"; + if ((session.rpcs[j].targetBandwidth!==-1) && (session.rpcs[j].targetBandwidth