Skip to content

Instantly share code, notes, and snippets.

@UUoocl
Last active September 26, 2023 04:00
Show Gist options
  • Save UUoocl/5c82968370559141be5ff3db5fa19486 to your computer and use it in GitHub Desktop.
Save UUoocl/5c82968370559141be5ff3db5fa19486 to your computer and use it in GitHub Desktop.
Play Google Slides transparently and connect to OBS with webSockets
const { contextBridge, ipcRenderer } = require('electron');
const cameraID = ipcRenderer.sendSync('camera-ID');
window.addEventListener('DOMContentLoaded', () => {
//console.log("cameraID ", cameraID )
const dataElement = document.createElement(`data`);
dataElement.setAttribute("id", "cameraID");
dataElement.setAttribute("data-camera-Id", cameraID);
window.document.body.insertBefore(dataElement, window.document.body.firstChild);
//window.document.body.append(dataElem);
const video = document.querySelector("video");
console.log("cameraID ", cameraID )
const constraints = {
audio: false,
video: {
deviceId: `${cameraID}`,
aspectRatio: 1.7777777778,
},
};
navigator.mediaDevices
.getUserMedia(constraints)
.then((stream) => {
const videoTracks = stream.getVideoTracks();
console.log("Got stream with constraints:", constraints);
console.log(`Using video device: ${videoTracks[0].label}`);
stream.onremovetrack = () => {
console.log("Stream ended");
};
video.srcObject = stream;
video.play();
})
.catch((error) => {
if (error.name === "OverconstrainedError") {
console.error(
`The resolution ${constraints.video.width.exact}x${constraints.video.height.exact} px is not supported by your device.`,
);
} else if (error.name === "NotAllowedError") {
console.error(
"You need to grant this page permission to access your camera and microphone.",
);
} else {
console.error(`getUserMedia error: ${error.name}`, error);
}
});
})
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
<title>Camera</title>
</head>
<body style ="overflow: hidden; padding: 0; margin: 0;">
<video style="width: 100%; height: 100%;"></video>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'">
<title>Transparent Google Slides Player</title>
</head>
<body>
<h3><label for="Link">Enter a Published Google Slide Link:</label></h3>
<input type="text" id="Link" name="Link" size=150 value="https://docs.google.com/presentation/d/e/2PACX-1vRVpsaZJbgTiremeDpWaIW3M2gt0rmSj4bf_ymuH5panELG2cZcL1dwwaKhA6jNjIMozaUBBx1sZ5gQ/pub?start=false&loop=false&delayms=3000"/><br><br>
<h4>Connect to OBS WebSocket Server? (optional)</h4>
<label for="IP">Enter IP address or "localhost":</label>
<input type="text" id="IP" name="IP" value="localhost"/><br>
<label for="Port">Enter Port Number:</label>
<input type="text" id="Port" name="Port" value="4455"/><br>
<label for="PW">Enter Password:</label>
<input type="text" id="PW" name="PW" value="YourPasswordGoesHere"/><br>
<h4><input type="checkbox" id="cameraWindow" name="cameraWindow" value=>
<label for="cameraWindow">Open Camera Window</label></h4>
<label for="installedCameras">Choose a camera:</label>
<select name="cameras" id="cameras">
<option value="">--Please choose a camera--</option></select>
<br><br>
<h4><input type="checkbox" id="poseWindow" name="poseWindow" value=>
<label for="poseWindow">Open Pose Detection Window</label></h4>
<br><br>
<input type="button" id="SubmitButton" value="submit"/>
<script src="./renderer.js"></script>
</body>
</html>
/* Transparent Google Slides player
2023 by uuoocl🪵
MIT license
An app to play Google Slides with a tranparent background
*/
// Modules to control application life and create native browser window
const { app, BrowserWindow, ipcMain} = require('electron')
const path = require('path')
let slidesWindow;
var websocketIP, websocketPort, websocketPassword, winCamera;
async function createWindow () {
// Create the browser window.
const mainWindow = new BrowserWindow({
width: 1280,
height: 720,
title: __dirname,
webPreferences: {
preload: path.join(__dirname, 'preload.js')
}
})
ipcMain.on('wsConnect-IP', (event) => {
console.log("sending websocket details to new window")
event.returnValue = websocketIP
})
ipcMain.on('wsConnect-Port', (event) => {
console.log("sending websocket details to new window")
event.returnValue = websocketPort
})
ipcMain.on('wsConnect-PW', (event) => {
console.log("sending websocket details to new window")
speakerViewWindow = event.sender;
event.returnValue = websocketPassword
})
ipcMain.on('camera-ID', (event) => {
console.log("sending camera ID to camera window")
event.returnValue = winCamera;
})
ipcMain.on('change-slide', (event, Direction) => {
if(Direction == "Next"){
console.log("sending next slide message to slide window")
slidesWindow.webContents.send('next-slide');
}else{
console.log("sending previous slide message to slide window")
slidesWindow.webContents.send('previous-slide');
}
})
ipcMain.on('open-slide-window', (event, IP, Port, PW, Link) => {
slidesWindow = new BrowserWindow({
width: 1919,
height: 1079,
frame: false,
movable: false,
titleBarOverlay: false,
backgroundThrottling: false,
transparent: true,
titleBarStyle: 'customButtonsOnHover',
webPreferences: {
preload: path.join(__dirname, 'slides-preload.js')
}
})
websocketIP = IP;
websocketPort = Port;
websocketPassword = PW;
mainLink = Link;
slidesWindow.loadURL(Link);
//slidesWindow.webContents.openDevTools()
slidesWindow.webContents.setWindowOpenHandler(({ event,url }) => {
console.log(event)
if (true) {
return {
action: 'allow',
backgroundThrottling: false,
overrideBrowserWindowOptions: {
frame: true,
fullscreenable: false,
backgroundColor: 'white',
webPreferences: {
preload: path.join(__dirname,'slides-popup-preload.js')
}
}
}
}
return { action: 'deny' }
})
console.log("sending appPath to new window")
})
ipcMain.on('open-camera-window', (event, cameraId) => {
console.log(`camera ID = ${cameraId}`)
cameraWindow = new BrowserWindow({
width: 1920,
height: 1080,
frame: false,
titleBarOverlay: false,
backgroundThrottling: false,
transparent: true,
titleBarStyle: 'customButtonsOnHover',
webPreferences: {
preload: path.join(__dirname, 'camera-preload.js')
}
})
winCamera = cameraId;
cameraWindow.loadFile('camera.html');
})
ipcMain.on('open-pose-window', (event) => {
poseWindow = new BrowserWindow({
width: 650,
height: 460,
x: 0,
y: 0,
frame: true,
titleBarOverlay: false,
backgroundThrottling: false,
transparent: true,
titleBarStyle: 'customButtonsOnHover',
webPreferences: {
preload: path.join(__dirname, 'pose-preload.js')
}
})
poseWindow.loadFile('pose.html');
})
// and load the index.html of the app.
mainWindow.loadFile('index.html')
// Open the DevTools.
// mainWindow.webContents.openDevTools()
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(() => {
createWindow()
app.on('activate', function () {
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on('window-all-closed', function () {
if (process.platform !== 'darwin') app.quit()
})
{
"name": "Transparent-Google-Slides-player",
"productName": "Transparent-Google-Slides-player",
"description": "An app to play Google Slides with a transparent background",
"keywords": [],
"main": "./main.js",
"version": "0.0.4",
"author": "UUoocl",
"scripts": {
"start": "electron ."
},
"dependencies": {},
"devDependencies": {
"electron": "26.0.0"
}
}
const { contextBridge, ipcRenderer } = require('electron')
contextBridge.exposeInMainWorld('electronAPI', {
changeSlide: (Direction) => ipcRenderer.send('change-slide', Direction)
})
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
<link href="./style.css" rel="stylesheet">
<!-- <script src="https://cdn.jsdelivr.net/npm/@mediapipe/tasks-vision/vision_bundle.js"
crossorigin="anonymous"></script> -->
<title>MediaPipe Pose</title>
</head>
<body>
<body>
<section id="demos" class="invisible">
<div class="detectOnClick">
<div id="liveView" class="videoView">
<button id="webcamButton" class="mdc-button mdc-button--raised">
<span class="mdc-button__ripple"></span>
<span class="mdc-button__label">ENABLE WEBCAM</span>
</button>
<div style="position: relative;">
<video id="webcam" style="width: 1280px; height: 720px; position: abso" autoplay playsinline></video>
<canvas class="output_canvas" id="output_canvas" width="1280" height="720" style="position: absolute; left: 0px; top: 0px;"></canvas>
</div>
</div>
</section>
<!-- You can also require other files to run in this process -->
<!-- <script src="./node_modules/@mediapipe/tasks-vision/vision_bundle.js" type="module"></script> -->
<script type="module">
import { PoseLandmarker, FilesetResolver, DrawingUtils } from "https://cdn.skypack.dev/@mediapipe/tasks-vision@0.10.0";
const demosSection = document.getElementById("demos");
let poseLandmarker = undefined;
let runningMode = "IMAGE";
let enableWebcamButton;
let webcamRunning = false;
const videoHeight = "360px";
const videoWidth = "640px";
var nextControl = "off";
var previousControl = "off";
// Before we can use PoseLandmarker class we must wait for it to finish
// loading. Machine Learning models can be large and take a moment to
// get everything needed to run.
const createPoseLandmarker = async () => {
const vision = await FilesetResolver.forVisionTasks("https://cdn.jsdelivr.net/npm/@mediapipe/tasks-vision@0.10.0/wasm");
poseLandmarker = await PoseLandmarker.createFromOptions(vision, {
baseOptions: {
modelAssetPath: `https://storage.googleapis.com/mediapipe-models/pose_landmarker/pose_landmarker_lite/float16/1/pose_landmarker_lite.task`,
delegate: "GPU"
},
runningMode: runningMode,
numPoses: 1
});
demosSection.classList.remove("invisible");
};
createPoseLandmarker();
/********************************************************************
// Demo 2: Continuously grab image from webcam stream and detect it.
********************************************************************/
const video = document.getElementById("webcam");
const canvasElement = document.getElementById("output_canvas");
const canvasCtx = canvasElement.getContext("2d");
const drawingUtils = new DrawingUtils(canvasCtx);
// Check if webcam access is supported.
const hasGetUserMedia = () => { var _a; return !!((_a = navigator.mediaDevices) === null || _a === void 0 ? void 0 : _a.getUserMedia); };
// If webcam supported, add event listener to button for when user
// wants to activate it.
if (hasGetUserMedia()) {
enableWebcamButton = document.getElementById("webcamButton");
enableWebcamButton.addEventListener("click", enableCam);
}
else {
console.warn("getUserMedia() is not supported by your browser");
}
// Enable the live webcam view and start detection.
function enableCam(event) {
if (!poseLandmarker) {
console.log("Wait! poseLandmaker not loaded yet.");
return;
}
if (webcamRunning === true) {
webcamRunning = false;
enableWebcamButton.innerText = "ENABLE PREDICTIONS";
}
else {
webcamRunning = true;
enableWebcamButton.innerText = "DISABLE PREDICTIONS";
}
// getUsermedia parameters.
const constraints = {
video: true
};
// Activate the webcam stream.
navigator.mediaDevices.getUserMedia(constraints).then((stream) => {
video.srcObject = stream;
video.addEventListener("loadeddata", predictWebcam);
});
}
let lastVideoTime = -1;
async function predictWebcam() {
canvasElement.style.height = videoHeight;
video.style.height = videoHeight;
canvasElement.style.width = videoWidth;
video.style.width = videoWidth;
// Now let's start detecting the stream.
if (runningMode === "IMAGE") {
runningMode = "VIDEO";
await poseLandmarker.setOptions({ runningMode: "VIDEO" });
}
let startTimeMs = performance.now();
if (lastVideoTime !== video.currentTime) {
lastVideoTime = video.currentTime;
poseLandmarker.detectForVideo(video, startTimeMs, (result) => {
canvasCtx.save();
canvasCtx.clearRect(0, 0, canvasElement.width, canvasElement.height);
for (const landmark of result.landmarks) {
if(landmark[16].y<landmark[0].y && nextControl == "off" && previousControl == "off"){
window.electronAPI.changeSlide("Next");
nextControl = "on";
console.log(landmark[16].y," Right ", nextControl)
}
if(landmark[15].y<landmark[0].y && nextControl == "off" && previousControl == "off"){
window.electronAPI.changeSlide("Previous");
previousControl = "on";
console.log(landmark[15].y," Left ", previousControl)
}
if(landmark[15].y > landmark[0].y){
previousControl = "off";
}
if(landmark[16].y > landmark[0].y){
nextControl = "off";
}
drawingUtils.drawLandmarks(landmark, {
radius: (data) => DrawingUtils.lerp(data.from.z, -0.15, 0.1, 5, 1)
});
drawingUtils.drawConnectors(landmark, PoseLandmarker.POSE_CONNECTIONS);
}
canvasCtx.restore();
});
}
// Call this function again to keep predicting when the browser is ready.
if (webcamRunning === true) {
window.requestAnimationFrame(predictWebcam);
}
}
</script>
</body>
</html>
const { contextBridge, ipcRenderer } = require('electron')
var windowId;
contextBridge.exposeInMainWorld('electronAPI', {
slideWindow: (IP, Port, PW, Link) => ipcRenderer.send('open-slide-window', IP, Port, PW, Link),
cameraWindow: (CameraID) => ipcRenderer.send('open-camera-window', CameraID),
poseWindow: () => ipcRenderer.send('open-pose-window'),
getCameraId: () => ipcRenderer.send('get-cameras')
})
ipcRenderer.on('SET_CAMERA_SOURCE', async (event, deviceName, deviceID) => {
console.log(deviceID)
var x = document.getElementById("cameras");
var option = document.createElement("option");
option.text = deviceName;
option.id = deviceID;
x.add(option);
window.document.body.insertBefore(windowId, window.document.body.firstChild);
})
const button = document.getElementById('SubmitButton');
window.addEventListener('DOMContentLoaded', async() => {
getCameras();
})
function getCameras(){
console.log("list of cameras")
navigator.mediaDevices
.enumerateDevices()
.then((devices) => {
devices.forEach((device) => {
if(device.kind == "videoinput"){
console.log(device)
console.log(`${device.kind}: ${device.label} id = ${device.deviceId}`);
var x = document.getElementById("cameras");
var option = document.createElement("option");
option.text = device.label;
option.id = device.deviceId;
x.add(option);
}
});
})
}
button.addEventListener("click", newWindow);
function newWindow() {
const IP = document.getElementById('IP').value;
const Port = document.getElementById('Port').value;
const PW = document.getElementById('PW').value;
const Link = document.getElementById('Link').value;
const OpenCamera = document.getElementById('cameraWindow');
console.log("OpenCamera",OpenCamera.checked)
const OpenPose = document.getElementById('poseWindow');
console.log("OpenPose", OpenPose.checked)
var e = document.getElementById("cameras");
console.log(e.value)
console.log(e.options[e.selectedIndex].text)
var value = e.value;
var CameraID = e.options[e.selectedIndex].id;
console.log(`${IP}, ${Port}, ${PW}, ${Link}, ${CameraID}`);
if(OpenCamera.checked){
window.electronAPI.cameraWindow(CameraID);
}
window.electronAPI.slideWindow(IP, Port, PW, Link);
if(OpenPose.checked){
window.electronAPI.poseWindow();
}
}
const {ipcRenderer } = require('electron');
const websocketIP = ipcRenderer.sendSync('wsConnect-IP');
const websocketPort = ipcRenderer.sendSync('wsConnect-Port');
const websocketPassword = ipcRenderer.sendSync('wsConnect-PW');
var obs;
var sceneInNotes, advSSmessage, notesScrollSpeed = 2, scaleAmount = 1, scrollPlay = true, resumeScrollSpeed, widthAmount;
window.addEventListener('DOMContentLoaded', () => {
if (window.trustedTypes && window.trustedTypes.createPolicy) {
window.trustedTypes.createPolicy('default', {
createHTML: (string) => string,
createScriptURL: string => string, // warning: this is unsafe!
createScript: string => string // warning: this is unsafe!
});
}
setTimeout(obsConnect, 2000);
setTimeout(setup, 200);
})
function setup() {
const slowScroll = document.createElement('div');
slowScroll.setAttribute("id","ScrollSlowButton");
slowScroll.innerText = "⏪";
slowScroll.setAttribute("role", "button");
slowScroll.setAttribute("class", "goog-inline-block jfk-button jfk-button-standard jfk-button-narrow jfk-button-collapse-right");
slowScroll.setAttribute("tabindex", "0");
slowScroll.setAttribute("title", "scroll slower");
slowScroll.setAttribute("value", "undefined");
slowScroll.setAttribute("style", "user-select: none;font-size: 20px");
const fastScroll = document.createElement('div');
fastScroll.setAttribute("id","ScrollfastButton");
fastScroll.innerText = "⏩";
fastScroll.setAttribute("role", "button");
fastScroll.setAttribute("class", "goog-inline-block jfk-button jfk-button-standard jfk-button-narrow jfk-button-collapse-left");
fastScroll.setAttribute("tabindex", "0");
fastScroll.setAttribute("title", "scroll slower");
fastScroll.setAttribute("value", "undefined");
fastScroll.setAttribute("style", "user-select: none;font-size: 20px");
const pauseScroll = document.createElement('div');
pauseScroll.setAttribute("id","pauseButton");
pauseScroll.innerText = "⏸️";
pauseScroll.setAttribute("role", "button");
pauseScroll.setAttribute("class", "goog-inline-block jfk-button jfk-button-standard jfk-button-narrow jfk-button-collapse-right");
pauseScroll.setAttribute("tabindex", "0");
pauseScroll.setAttribute("title", "scroll slower");
pauseScroll.setAttribute("value", "undefined");
pauseScroll.setAttribute("style", "user-select: none;font-size: 20px");
//window.document.body.div[0].append(div);
window.document.querySelector('div[class="punch-viewer-speakernotes-zoom-container"]').append(slowScroll);
window.document.querySelector('div[class="punch-viewer-speakernotes-zoom-container"]').append(pauseScroll);
window.document.querySelector('div[class="punch-viewer-speakernotes-zoom-container"]').append(fastScroll);
const pauseButton = document.getElementById('pauseButton');
const fastButton = document.getElementById('ScrollfastButton');
const slowButton = document.getElementById('ScrollSlowButton');
pauseButton.addEventListener("click",scrollPause);
fastButton.addEventListener("click",scrollFaster);
slowButton.addEventListener("click",scrollSlower);
window.addEventListener("keydown", (event) => {
console.log(event.code)
switch (event.code) {
case "F8":
scrollSlower();
break;
case "F9":
scrollPause()
break;
case "F10":
scrollFaster()
break;
case "Equal":
notesZoomIn();
break;
case "Minus":
notesZoomOut();
break;
}
})
}
function obsConnect(){
obs = new OBSWebSocket();
console.log("obs connect")
const { obsWebSocketVersion,
negotiatedRpcVersion
} = obs.connect(`ws://${websocketIP}:${websocketPort}`, websocketPassword, {
rpcVersion: 1
});
console.log(`Connected to server ${obsWebSocketVersion} (using RPC ${negotiatedRpcVersion})`)
listenforOBSchange();
setInterval(noteInspection, 500);
setInterval(notesScroll, 50);
}
function listenforOBSchange(){
console.log("turn on OBS listeners")
obs.on('CurrentProgramSceneChanged', function(event) {
console.log("I got it too")
//let SceneName = event.sceneName;
console.log(event)
})
obs.on('VendorEvent', function(event) {
console.log("WS Request received")
console.log(event)
let elem;
switch (event.eventData.message) {
case "Next":
nextSlide();
/* console.log("Right event")
elem = document.querySelectorAll('div[class="punch-viewer-speakernotes-page-next"]')[0]
elem.click(); */
/* window.focus()
keySim("39");
//setTimeout(keySim("78"),1000);
window.opener.focus(); */
break;
case "Previous":
previousSlide();
/* console.log("Left event")
elem = document.querySelectorAll('div[class="punch-viewer-speakernotes-page-previous"]')[0]
elem.click();
*/
//setTimeout(keySim("78"),1000);
//window.opener.focus();
break;
case "Notes Zoom In":
console.log("Notes Zoom In")
notesZoomIn;
break;
case "Notes Zoom Out":
console.log("Notes Zoom Out")
notesZoomOut;
break;
case "Notes Scroll Faster":
console.log("Notes Scroll Faster")
scrollFaster;
break;
case "Notes-Scroll-Slower":
console.log("Notes Scroll Slower")
scrollSlower;
break;
}
})
}
function nextSlide(){
console.log("Right event")
elem = document.querySelectorAll('div[class="punch-viewer-speakernotes-page-next"]')[0]
elem.click();
}
function previousSlide(){
console.log("Left event")
elem = document.querySelectorAll('div[class="punch-viewer-speakernotes-page-previous"]')[0]
elem.click();
}
function notesZoomIn(){
elem = document.querySelectorAll('div[class="punch-viewer-speakernotes-text-body-zoomable"]')[0];
scaleAmount = scaleAmount + .15;
widthAmount = 100000/(1000*scaleAmount);
elem.style.width = `${widthAmount}%`;
elem.style.transform = `scale(${scaleAmount})`;
}
function notesZoomOut(){
elem = document.querySelectorAll('div[class="punch-viewer-speakernotes-text-body-zoomable"]')[0]
scaleAmount = scaleAmount - .15;
widthAmount = 100000/(1000*scaleAmount);
elem.style.width = `${widthAmount}%`;
elem.style.transform = `scale(${scaleAmount})`;
}
function scrollFaster(){
if(scrollPlay == false){
notesScrollSpeed = Math.abs(resumeScrollSpeed) -.5;
}
scrollPlay = true;
notesScrollSpeed = notesScrollSpeed + .5;
}
function scrollSlower(){
if(scrollPlay == false){
notesScrollSpeed = (Math.abs(resumeScrollSpeed)*-1) + 1;
}
scrollPlay = true;
notesScrollSpeed = notesScrollSpeed - 1;
}
function scrollPause(){
console.log("Paused")
if(scrollPlay == true){
scrollPlay = false;
resumeScrollSpeed = notesScrollSpeed;
notesScrollSpeed = 0;
}else{
scrollPlay = true;
notesScrollSpeed = resumeScrollSpeed;
}
}
function noteInspection() {
const elem = document.querySelectorAll('div[class="punch-viewer-speakernotes-text-body-zoomable"]')[0];
if(elem){
//get Scene name
if(elem.textContent.includes('{{')){
var start_pos = elem.textContent.indexOf('{{') + 2;
var end_pos = elem.textContent.indexOf('}}',start_pos);
var scene_to_set = elem.textContent.substring(start_pos,end_pos);
console.log(scene_to_set);
if(scene_to_set != sceneInNotes ){
sceneInNotes = scene_to_set;
obs.call('SetCurrentProgramScene', {sceneName: sceneInNotes});
}
}
//Get message to send to Advanced Scene Switcher
if(elem.textContent.includes('||')){
start_pos = elem.textContent.indexOf('||') + 2;
end_pos = elem.textContent.indexOf('||',start_pos);
var message_to_send = elem.textContent.substring(start_pos,end_pos)
console.log(message_to_send);
if(message_to_send != advSSmessage ){
advSSmessage = message_to_send;
obs.call("CallVendorRequest", {vendorName:"AdvancedSceneSwitcher",requestType:"AdvancedSceneSwitcherMessage",requestData:{message:advSSmessage}});
console.log("WebSocket message Sent")
}
}
}
}
function notesScroll(){
//console.log("Notes scroll")
const elem = document.querySelectorAll('div[class="punch-viewer-speakernotes-text-body-scrollable"]')[0];
if(elem){
elem.scrollBy(0,notesScrollSpeed);
elem.scrollBy({
behavior: "smooth"
});
}
}
function keySim(k){
console.log(`Key press ${k}`)
document.dispatchEvent(
new KeyboardEvent("keydown", {
keyCode: k
})
);
}
//obs-ws-js library
var OBSWebSocket = (function () {
function _defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
function _createClass(Constructor, protoProps, staticProps) {
if (protoProps) _defineProperties(Constructor.prototype, protoProps);
if (staticProps) _defineProperties(Constructor, staticProps);
Object.defineProperty(Constructor, "prototype", {
writable: false
});
return Constructor;
}
function _extends() {
_extends = Object.assign ? Object.assign.bind() : function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
};
return _extends.apply(this, arguments);
}
function _inheritsLoose(subClass, superClass) {
subClass.prototype = Object.create(superClass.prototype);
subClass.prototype.constructor = subClass;
_setPrototypeOf(subClass, superClass);
}
function _getPrototypeOf(o) {
_getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) {
return o.__proto__ || Object.getPrototypeOf(o);
};
return _getPrototypeOf(o);
}
function _setPrototypeOf(o, p) {
_setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) {
o.__proto__ = p;
return o;
};
return _setPrototypeOf(o, p);
}
function _isNativeReflectConstruct() {
if (typeof Reflect === "undefined" || !Reflect.construct) return false;
if (Reflect.construct.sham) return false;
if (typeof Proxy === "function") return true;
try {
Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {}));
return true;
} catch (e) {
return false;
}
}
function _construct(Parent, args, Class) {
if (_isNativeReflectConstruct()) {
_construct = Reflect.construct.bind();
} else {
_construct = function _construct(Parent, args, Class) {
var a = [null];
a.push.apply(a, args);
var Constructor = Function.bind.apply(Parent, a);
var instance = new Constructor();
if (Class) _setPrototypeOf(instance, Class.prototype);
return instance;
};
}
return _construct.apply(null, arguments);
}
function _isNativeFunction(fn) {
return Function.toString.call(fn).indexOf("[native code]") !== -1;
}
function _wrapNativeSuper(Class) {
var _cache = typeof Map === "function" ? new Map() : undefined;
_wrapNativeSuper = function _wrapNativeSuper(Class) {
if (Class === null || !_isNativeFunction(Class)) return Class;
if (typeof Class !== "function") {
throw new TypeError("Super expression must either be null or a function");
}
if (typeof _cache !== "undefined") {
if (_cache.has(Class)) return _cache.get(Class);
_cache.set(Class, Wrapper);
}
function Wrapper() {
return _construct(Class, arguments, _getPrototypeOf(this).constructor);
}
Wrapper.prototype = Object.create(Class.prototype, {
constructor: {
value: Wrapper,
enumerable: false,
writable: true,
configurable: true
}
});
return _setPrototypeOf(Wrapper, Class);
};
return _wrapNativeSuper(Class);
}
function _objectWithoutPropertiesLoose(source, excluded) {
if (source == null) return {};
var target = {};
var sourceKeys = Object.keys(source);
var key, i;
for (i = 0; i < sourceKeys.length; i++) {
key = sourceKeys[i];
if (excluded.indexOf(key) >= 0) continue;
target[key] = source[key];
}
return target;
}
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
function createCommonjsModule(fn) {
var module = { exports: {} };
return fn(module, module.exports), module.exports;
}
function commonjsRequire (target) {
throw new Error('Could not dynamically require "' + target + '". Please configure the dynamicRequireTargets option of @rollup/plugin-commonjs appropriately for this require call to behave properly.');
}
/**
* Helpers.
*/
var s = 1000;
var m = s * 60;
var h = m * 60;
var d = h * 24;
var w = d * 7;
var y = d * 365.25;
/**
* Parse or format the given `val`.
*
* Options:
*
* - `long` verbose formatting [false]
*
* @param {String|Number} val
* @param {Object} [options]
* @throws {Error} throw an error if val is not a non-empty string or a number
* @return {String|Number}
* @api public
*/
var ms = function(val, options) {
options = options || {};
var type = typeof val;
if (type === 'string' && val.length > 0) {
return parse(val);
} else if (type === 'number' && isFinite(val)) {
return options.long ? fmtLong(val) : fmtShort(val);
}
throw new Error(
'val is not a non-empty string or a valid number. val=' +
JSON.stringify(val)
);
};
/**
* Parse the given `str` and return milliseconds.
*
* @param {String} str
* @return {Number}
* @api private
*/
function parse(str) {
str = String(str);
if (str.length > 100) {
return;
}
var match = /^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(
str
);
if (!match) {
return;
}
var n = parseFloat(match[1]);
var type = (match[2] || 'ms').toLowerCase();
switch (type) {
case 'years':
case 'year':
case 'yrs':
case 'yr':
case 'y':
return n * y;
case 'weeks':
case 'week':
case 'w':
return n * w;
case 'days':
case 'day':
case 'd':
return n * d;
case 'hours':
case 'hour':
case 'hrs':
case 'hr':
case 'h':
return n * h;
case 'minutes':
case 'minute':
case 'mins':
case 'min':
case 'm':
return n * m;
case 'seconds':
case 'second':
case 'secs':
case 'sec':
case 's':
return n * s;
case 'milliseconds':
case 'millisecond':
case 'msecs':
case 'msec':
case 'ms':
return n;
default:
return undefined;
}
}
/**
* Short format for `ms`.
*
* @param {Number} ms
* @return {String}
* @api private
*/
function fmtShort(ms) {
var msAbs = Math.abs(ms);
if (msAbs >= d) {
return Math.round(ms / d) + 'd';
}
if (msAbs >= h) {
return Math.round(ms / h) + 'h';
}
if (msAbs >= m) {
return Math.round(ms / m) + 'm';
}
if (msAbs >= s) {
return Math.round(ms / s) + 's';
}
return ms + 'ms';
}
/**
* Long format for `ms`.
*
* @param {Number} ms
* @return {String}
* @api private
*/
function fmtLong(ms) {
var msAbs = Math.abs(ms);
if (msAbs >= d) {
return plural(ms, msAbs, d, 'day');
}
if (msAbs >= h) {
return plural(ms, msAbs, h, 'hour');
}
if (msAbs >= m) {
return plural(ms, msAbs, m, 'minute');
}
if (msAbs >= s) {
return plural(ms, msAbs, s, 'second');
}
return ms + ' ms';
}
/**
* Pluralization helper.
*/
function plural(ms, msAbs, n, name) {
var isPlural = msAbs >= n * 1.5;
return Math.round(ms / n) + ' ' + name + (isPlural ? 's' : '');
}
/**
* This is the common logic for both the Node.js and web browser
* implementations of `debug()`.
*/
function setup(env) {
createDebug.debug = createDebug;
createDebug.default = createDebug;
createDebug.coerce = coerce;
createDebug.disable = disable;
createDebug.enable = enable;
createDebug.enabled = enabled;
createDebug.humanize = ms;
createDebug.destroy = destroy;
Object.keys(env).forEach(key => {
createDebug[key] = env[key];
});
/**
* The currently active debug mode names, and names to skip.
*/
createDebug.names = [];
createDebug.skips = [];
/**
* Map of special "%n" handling functions, for the debug "format" argument.
*
* Valid key names are a single, lower or upper-case letter, i.e. "n" and "N".
*/
createDebug.formatters = {};
/**
* Selects a color for a debug namespace
* @param {String} namespace The namespace string for the debug instance to be colored
* @return {Number|String} An ANSI color code for the given namespace
* @api private
*/
function selectColor(namespace) {
let hash = 0;
for (let i = 0; i < namespace.length; i++) {
hash = ((hash << 5) - hash) + namespace.charCodeAt(i);
hash |= 0; // Convert to 32bit integer
}
return createDebug.colors[Math.abs(hash) % createDebug.colors.length];
}
createDebug.selectColor = selectColor;
/**
* Create a debugger with the given `namespace`.
*
* @param {String} namespace
* @return {Function}
* @api public
*/
function createDebug(namespace) {
let prevTime;
let enableOverride = null;
let namespacesCache;
let enabledCache;
function debug(...args) {
// Disabled?
if (!debug.enabled) {
return;
}
const self = debug;
// Set `diff` timestamp
const curr = Number(new Date());
const ms = curr - (prevTime || curr);
self.diff = ms;
self.prev = prevTime;
self.curr = curr;
prevTime = curr;
args[0] = createDebug.coerce(args[0]);
if (typeof args[0] !== 'string') {
// Anything else let's inspect with %O
args.unshift('%O');
}
// Apply any `formatters` transformations
let index = 0;
args[0] = args[0].replace(/%([a-zA-Z%])/g, (match, format) => {
// If we encounter an escaped % then don't increase the array index
if (match === '%%') {
return '%';
}
index++;
const formatter = createDebug.formatters[format];
if (typeof formatter === 'function') {
const val = args[index];
match = formatter.call(self, val);
// Now we need to remove `args[index]` since it's inlined in the `format`
args.splice(index, 1);
index--;
}
return match;
});
// Apply env-specific formatting (colors, etc.)
createDebug.formatArgs.call(self, args);
const logFn = self.log || createDebug.log;
logFn.apply(self, args);
}
debug.namespace = namespace;
debug.useColors = createDebug.useColors();
debug.color = createDebug.selectColor(namespace);
debug.extend = extend;
debug.destroy = createDebug.destroy; // XXX Temporary. Will be removed in the next major release.
Object.defineProperty(debug, 'enabled', {
enumerable: true,
configurable: false,
get: () => {
if (enableOverride !== null) {
return enableOverride;
}
if (namespacesCache !== createDebug.namespaces) {
namespacesCache = createDebug.namespaces;
enabledCache = createDebug.enabled(namespace);
}
return enabledCache;
},
set: v => {
enableOverride = v;
}
});
// Env-specific initialization logic for debug instances
if (typeof createDebug.init === 'function') {
createDebug.init(debug);
}
return debug;
}
function extend(namespace, delimiter) {
const newDebug = createDebug(this.namespace + (typeof delimiter === 'undefined' ? ':' : delimiter) + namespace);
newDebug.log = this.log;
return newDebug;
}
/**
* Enables a debug mode by namespaces. This can include modes
* separated by a colon and wildcards.
*
* @param {String} namespaces
* @api public
*/
function enable(namespaces) {
createDebug.save(namespaces);
createDebug.namespaces = namespaces;
createDebug.names = [];
createDebug.skips = [];
let i;
const split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/);
const len = split.length;
for (i = 0; i < len; i++) {
if (!split[i]) {
// ignore empty strings
continue;
}
namespaces = split[i].replace(/\*/g, '.*?');
if (namespaces[0] === '-') {
createDebug.skips.push(new RegExp('^' + namespaces.slice(1) + '$'));
} else {
createDebug.names.push(new RegExp('^' + namespaces + '$'));
}
}
}
/**
* Disable debug output.
*
* @return {String} namespaces
* @api public
*/
function disable() {
const namespaces = [
...createDebug.names.map(toNamespace),
...createDebug.skips.map(toNamespace).map(namespace => '-' + namespace)
].join(',');
createDebug.enable('');
return namespaces;
}
/**
* Returns true if the given mode name is enabled, false otherwise.
*
* @param {String} name
* @return {Boolean}
* @api public
*/
function enabled(name) {
if (name[name.length - 1] === '*') {
return true;
}
let i;
let len;
for (i = 0, len = createDebug.skips.length; i < len; i++) {
if (createDebug.skips[i].test(name)) {
return false;
}
}
for (i = 0, len = createDebug.names.length; i < len; i++) {
if (createDebug.names[i].test(name)) {
return true;
}
}
return false;
}
/**
* Convert regexp to namespace
*
* @param {RegExp} regxep
* @return {String} namespace
* @api private
*/
function toNamespace(regexp) {
return regexp.toString()
.substring(2, regexp.toString().length - 2)
.replace(/\.\*\?$/, '*');
}
/**
* Coerce `val`.
*
* @param {Mixed} val
* @return {Mixed}
* @api private
*/
function coerce(val) {
if (val instanceof Error) {
return val.stack || val.message;
}
return val;
}
/**
* XXX DO NOT USE. This is a temporary stub function.
* XXX It WILL be removed in the next major release.
*/
function destroy() {
console.warn('Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.');
}
createDebug.enable(createDebug.load());
return createDebug;
}
var common = setup;
/* eslint-env browser */
var browser$1 = createCommonjsModule(function (module, exports) {
/**
* This is the web browser implementation of `debug()`.
*/
exports.formatArgs = formatArgs;
exports.save = save;
exports.load = load;
exports.useColors = useColors;
exports.storage = localstorage();
exports.destroy = (() => {
let warned = false;
return () => {
if (!warned) {
warned = true;
console.warn('Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.');
}
};
})();
/**
* Colors.
*/
exports.colors = [
'#0000CC',
'#0000FF',
'#0033CC',
'#0033FF',
'#0066CC',
'#0066FF',
'#0099CC',
'#0099FF',
'#00CC00',
'#00CC33',
'#00CC66',
'#00CC99',
'#00CCCC',
'#00CCFF',
'#3300CC',
'#3300FF',
'#3333CC',
'#3333FF',
'#3366CC',
'#3366FF',
'#3399CC',
'#3399FF',
'#33CC00',
'#33CC33',
'#33CC66',
'#33CC99',
'#33CCCC',
'#33CCFF',
'#6600CC',
'#6600FF',
'#6633CC',
'#6633FF',
'#66CC00',
'#66CC33',
'#9900CC',
'#9900FF',
'#9933CC',
'#9933FF',
'#99CC00',
'#99CC33',
'#CC0000',
'#CC0033',
'#CC0066',
'#CC0099',
'#CC00CC',
'#CC00FF',
'#CC3300',
'#CC3333',
'#CC3366',
'#CC3399',
'#CC33CC',
'#CC33FF',
'#CC6600',
'#CC6633',
'#CC9900',
'#CC9933',
'#CCCC00',
'#CCCC33',
'#FF0000',
'#FF0033',
'#FF0066',
'#FF0099',
'#FF00CC',
'#FF00FF',
'#FF3300',
'#FF3333',
'#FF3366',
'#FF3399',
'#FF33CC',
'#FF33FF',
'#FF6600',
'#FF6633',
'#FF9900',
'#FF9933',
'#FFCC00',
'#FFCC33'
];
/**
* Currently only WebKit-based Web Inspectors, Firefox >= v31,
* and the Firebug extension (any Firefox version) are known
* to support "%c" CSS customizations.
*
* TODO: add a `localStorage` variable to explicitly enable/disable colors
*/
// eslint-disable-next-line complexity
function useColors() {
// NB: In an Electron preload script, document will be defined but not fully
// initialized. Since we know we're in Chrome, we'll just detect this case
// explicitly
if (typeof window !== 'undefined' && window.process && (window.process.type === 'renderer' || window.process.__nwjs)) {
return true;
}
// Internet Explorer and Edge do not support colors.
if (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)) {
return false;
}
// Is webkit? http://stackoverflow.com/a/16459606/376773
// document is undefined in react-native: https://github.com/facebook/react-native/pull/1632
return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) ||
// Is firebug? http://stackoverflow.com/a/398120/376773
(typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) ||
// Is firefox >= v31?
// https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
(typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) ||
// Double check webkit in userAgent just in case we are in a worker
(typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/));
}
/**
* Colorize log arguments if enabled.
*
* @api public
*/
function formatArgs(args) {
args[0] = (this.useColors ? '%c' : '') +
this.namespace +
(this.useColors ? ' %c' : ' ') +
args[0] +
(this.useColors ? '%c ' : ' ') +
'+' + module.exports.humanize(this.diff);
if (!this.useColors) {
return;
}
const c = 'color: ' + this.color;
args.splice(1, 0, c, 'color: inherit');
// The final "%c" is somewhat tricky, because there could be other
// arguments passed either before or after the %c, so we need to
// figure out the correct index to insert the CSS into
let index = 0;
let lastC = 0;
args[0].replace(/%[a-zA-Z%]/g, match => {
if (match === '%%') {
return;
}
index++;
if (match === '%c') {
// We only are interested in the *last* %c
// (the user may have provided their own)
lastC = index;
}
});
args.splice(lastC, 0, c);
}
/**
* Invokes `console.debug()` when available.
* No-op when `console.debug` is not a "function".
* If `console.debug` is not available, falls back
* to `console.log`.
*
* @api public
*/
exports.log = console.debug || console.log || (() => {});
/**
* Save `namespaces`.
*
* @param {String} namespaces
* @api private
*/
function save(namespaces) {
try {
if (namespaces) {
exports.storage.setItem('debug', namespaces);
} else {
exports.storage.removeItem('debug');
}
} catch (error) {
// Swallow
// XXX (@Qix-) should we be logging these?
}
}
/**
* Load `namespaces`.
*
* @return {String} returns the previously persisted debug modes
* @api private
*/
function load() {
let r;
try {
r = exports.storage.getItem('debug');
} catch (error) {
// Swallow
// XXX (@Qix-) should we be logging these?
}
// If debug isn't set in LS, and we're in Electron, try to load $DEBUG
if (!r && typeof process !== 'undefined' && 'env' in process) {
r = process.env.DEBUG;
}
return r;
}
/**
* Localstorage attempts to return the localstorage.
*
* This is necessary because safari throws
* when a user disables cookies/localstorage
* and you attempt to access it.
*
* @return {LocalStorage}
* @api private
*/
function localstorage() {
try {
// TVMLKit (Apple TV JS Runtime) does not have a window object, just localStorage in the global context
// The Browser also has localStorage in the global context.
return localStorage;
} catch (error) {
// Swallow
// XXX (@Qix-) should we be logging these?
}
}
module.exports = common(exports);
const {formatters} = module.exports;
/**
* Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
*/
formatters.j = function (v) {
try {
return JSON.stringify(v);
} catch (error) {
return '[UnexpectedJSONParseError]: ' + error.message;
}
};
});
var eventemitter3 = createCommonjsModule(function (module) {
var has = Object.prototype.hasOwnProperty
, prefix = '~';
/**
* Constructor to create a storage for our `EE` objects.
* An `Events` instance is a plain object whose properties are event names.
*
* @constructor
* @private
*/
function Events() {}
//
// We try to not inherit from `Object.prototype`. In some engines creating an
// instance in this way is faster than calling `Object.create(null)` directly.
// If `Object.create(null)` is not supported we prefix the event names with a
// character to make sure that the built-in object properties are not
// overridden or used as an attack vector.
//
if (Object.create) {
Events.prototype = Object.create(null);
//
// This hack is needed because the `__proto__` property is still inherited in
// some old browsers like Android 4, iPhone 5.1, Opera 11 and Safari 5.
//
if (!new Events().__proto__) prefix = false;
}
/**
* Representation of a single event listener.
*
* @param {Function} fn The listener function.
* @param {*} context The context to invoke the listener with.
* @param {Boolean} [once=false] Specify if the listener is a one-time listener.
* @constructor
* @private
*/
function EE(fn, context, once) {
this.fn = fn;
this.context = context;
this.once = once || false;
}
/**
* Add a listener for a given event.
*
* @param {EventEmitter} emitter Reference to the `EventEmitter` instance.
* @param {(String|Symbol)} event The event name.
* @param {Function} fn The listener function.
* @param {*} context The context to invoke the listener with.
* @param {Boolean} once Specify if the listener is a one-time listener.
* @returns {EventEmitter}
* @private
*/
function addListener(emitter, event, fn, context, once) {
if (typeof fn !== 'function') {
throw new TypeError('The listener must be a function');
}
var listener = new EE(fn, context || emitter, once)
, evt = prefix ? prefix + event : event;
if (!emitter._events[evt]) emitter._events[evt] = listener, emitter._eventsCount++;
else if (!emitter._events[evt].fn) emitter._events[evt].push(listener);
else emitter._events[evt] = [emitter._events[evt], listener];
return emitter;
}
/**
* Clear event by name.
*
* @param {EventEmitter} emitter Reference to the `EventEmitter` instance.
* @param {(String|Symbol)} evt The Event name.
* @private
*/
function clearEvent(emitter, evt) {
if (--emitter._eventsCount === 0) emitter._events = new Events();
else delete emitter._events[evt];
}
/**
* Minimal `EventEmitter` interface that is molded against the Node.js
* `EventEmitter` interface.
*
* @constructor
* @public
*/
function EventEmitter() {
this._events = new Events();
this._eventsCount = 0;
}
/**
* Return an array listing the events for which the emitter has registered
* listeners.
*
* @returns {Array}
* @public
*/
EventEmitter.prototype.eventNames = function eventNames() {
var names = []
, events
, name;
if (this._eventsCount === 0) return names;
for (name in (events = this._events)) {
if (has.call(events, name)) names.push(prefix ? name.slice(1) : name);
}
if (Object.getOwnPropertySymbols) {
return names.concat(Object.getOwnPropertySymbols(events));
}
return names;
};
/**
* Return the listeners registered for a given event.
*
* @param {(String|Symbol)} event The event name.
* @returns {Array} The registered listeners.
* @public
*/
EventEmitter.prototype.listeners = function listeners(event) {
var evt = prefix ? prefix + event : event
, handlers = this._events[evt];
if (!handlers) return [];
if (handlers.fn) return [handlers.fn];
for (var i = 0, l = handlers.length, ee = new Array(l); i < l; i++) {
ee[i] = handlers[i].fn;
}
return ee;
};
/**
* Return the number of listeners listening to a given event.
*
* @param {(String|Symbol)} event The event name.
* @returns {Number} The number of listeners.
* @public
*/
EventEmitter.prototype.listenerCount = function listenerCount(event) {
var evt = prefix ? prefix + event : event
, listeners = this._events[evt];
if (!listeners) return 0;
if (listeners.fn) return 1;
return listeners.length;
};
/**
* Calls each of the listeners registered for a given event.
*
* @param {(String|Symbol)} event The event name.
* @returns {Boolean} `true` if the event had listeners, else `false`.
* @public
*/
EventEmitter.prototype.emit = function emit(event, a1, a2, a3, a4, a5) {
var evt = prefix ? prefix + event : event;
if (!this._events[evt]) return false;
var listeners = this._events[evt]
, len = arguments.length
, args
, i;
if (listeners.fn) {
if (listeners.once) this.removeListener(event, listeners.fn, undefined, true);
switch (len) {
case 1: return listeners.fn.call(listeners.context), true;
case 2: return listeners.fn.call(listeners.context, a1), true;
case 3: return listeners.fn.call(listeners.context, a1, a2), true;
case 4: return listeners.fn.call(listeners.context, a1, a2, a3), true;
case 5: return listeners.fn.call(listeners.context, a1, a2, a3, a4), true;
case 6: return listeners.fn.call(listeners.context, a1, a2, a3, a4, a5), true;
}
for (i = 1, args = new Array(len -1); i < len; i++) {
args[i - 1] = arguments[i];
}
listeners.fn.apply(listeners.context, args);
} else {
var length = listeners.length
, j;
for (i = 0; i < length; i++) {
if (listeners[i].once) this.removeListener(event, listeners[i].fn, undefined, true);
switch (len) {
case 1: listeners[i].fn.call(listeners[i].context); break;
case 2: listeners[i].fn.call(listeners[i].context, a1); break;
case 3: listeners[i].fn.call(listeners[i].context, a1, a2); break;
case 4: listeners[i].fn.call(listeners[i].context, a1, a2, a3); break;
default:
if (!args) for (j = 1, args = new Array(len -1); j < len; j++) {
args[j - 1] = arguments[j];
}
listeners[i].fn.apply(listeners[i].context, args);
}
}
}
return true;
};
/**
* Add a listener for a given event.
*
* @param {(String|Symbol)} event The event name.
* @param {Function} fn The listener function.
* @param {*} [context=this] The context to invoke the listener with.
* @returns {EventEmitter} `this`.
* @public
*/
EventEmitter.prototype.on = function on(event, fn, context) {
return addListener(this, event, fn, context, false);
};
/**
* Add a one-time listener for a given event.
*
* @param {(String|Symbol)} event The event name.
* @param {Function} fn The listener function.
* @param {*} [context=this] The context to invoke the listener with.
* @returns {EventEmitter} `this`.
* @public
*/
EventEmitter.prototype.once = function once(event, fn, context) {
return addListener(this, event, fn, context, true);
};
/**
* Remove the listeners of a given event.
*
* @param {(String|Symbol)} event The event name.
* @param {Function} fn Only remove the listeners that match this function.
* @param {*} context Only remove the listeners that have this context.
* @param {Boolean} once Only remove one-time listeners.
* @returns {EventEmitter} `this`.
* @public
*/
EventEmitter.prototype.removeListener = function removeListener(event, fn, context, once) {
var evt = prefix ? prefix + event : event;
if (!this._events[evt]) return this;
if (!fn) {
clearEvent(this, evt);
return this;
}
var listeners = this._events[evt];
if (listeners.fn) {
if (
listeners.fn === fn &&
(!once || listeners.once) &&
(!context || listeners.context === context)
) {
clearEvent(this, evt);
}
} else {
for (var i = 0, events = [], length = listeners.length; i < length; i++) {
if (
listeners[i].fn !== fn ||
(once && !listeners[i].once) ||
(context && listeners[i].context !== context)
) {
events.push(listeners[i]);
}
}
//
// Reset the array, or remove it completely if we have no more listeners.
//
if (events.length) this._events[evt] = events.length === 1 ? events[0] : events;
else clearEvent(this, evt);
}
return this;
};
/**
* Remove all listeners, or those of the specified event.
*
* @param {(String|Symbol)} [event] The event name.
* @returns {EventEmitter} `this`.
* @public
*/
EventEmitter.prototype.removeAllListeners = function removeAllListeners(event) {
var evt;
if (event) {
evt = prefix ? prefix + event : event;
if (this._events[evt]) clearEvent(this, evt);
} else {
this._events = new Events();
this._eventsCount = 0;
}
return this;
};
//
// Alias methods names because people roll like that.
//
EventEmitter.prototype.off = EventEmitter.prototype.removeListener;
EventEmitter.prototype.addListener = EventEmitter.prototype.on;
//
// Expose the prefix.
//
EventEmitter.prefixed = prefix;
//
// Allow `EventEmitter` to be imported as module namespace.
//
EventEmitter.EventEmitter = EventEmitter;
//
// Expose the module.
//
{
module.exports = EventEmitter;
}
});
// https://github.com/maxogden/websocket-stream/blob/48dc3ddf943e5ada668c31ccd94e9186f02fafbd/ws-fallback.js
var ws = null;
if (typeof WebSocket !== 'undefined') {
ws = WebSocket;
} else if (typeof MozWebSocket !== 'undefined') {
ws = MozWebSocket;
} else if (typeof commonjsGlobal !== 'undefined') {
ws = commonjsGlobal.WebSocket || commonjsGlobal.MozWebSocket;
} else if (typeof window !== 'undefined') {
ws = window.WebSocket || window.MozWebSocket;
} else if (typeof self !== 'undefined') {
ws = self.WebSocket || self.MozWebSocket;
}
var browser = ws;
var WebSocketOpCode;
(function (WebSocketOpCode) {
/**
* The initial message sent by obs-websocket to newly connected clients.
*
* Initial OBS Version: 5.0.0
*/
WebSocketOpCode[WebSocketOpCode["Hello"] = 0] = "Hello";
/**
* The message sent by a newly connected client to obs-websocket in response to a `Hello`.
*
* Initial OBS Version: 5.0.0
*/
WebSocketOpCode[WebSocketOpCode["Identify"] = 1] = "Identify";
/**
* The response sent by obs-websocket to a client after it has successfully identified with obs-websocket.
*
* Initial OBS Version: 5.0.0
*/
WebSocketOpCode[WebSocketOpCode["Identified"] = 2] = "Identified";
/**
* The message sent by an already-identified client to update identification parameters.
*
* Initial OBS Version: 5.0.0
*/
WebSocketOpCode[WebSocketOpCode["Reidentify"] = 3] = "Reidentify";
/**
* The message sent by obs-websocket containing an event payload.
*
* Initial OBS Version: 5.0.0
*/
WebSocketOpCode[WebSocketOpCode["Event"] = 5] = "Event";
/**
* The message sent by a client to obs-websocket to perform a request.
*
* Initial OBS Version: 5.0.0
*/
WebSocketOpCode[WebSocketOpCode["Request"] = 6] = "Request";
/**
* The message sent by obs-websocket in response to a particular request from a client.
*
* Initial OBS Version: 5.0.0
*/
WebSocketOpCode[WebSocketOpCode["RequestResponse"] = 7] = "RequestResponse";
/**
* The message sent by a client to obs-websocket to perform a batch of requests.
*
* Initial OBS Version: 5.0.0
*/
WebSocketOpCode[WebSocketOpCode["RequestBatch"] = 8] = "RequestBatch";
/**
* The message sent by obs-websocket in response to a particular batch of requests from a client.
*
* Initial OBS Version: 5.0.0
*/
WebSocketOpCode[WebSocketOpCode["RequestBatchResponse"] = 9] = "RequestBatchResponse";
})(WebSocketOpCode || (WebSocketOpCode = {}));
/* eslint-disable no-bitwise, @typescript-eslint/prefer-literal-enum-member */
var EventSubscription;
(function (EventSubscription) {
/**
* Subcription value used to disable all events.
*
* Initial OBS Version: 5.0.0
*/
EventSubscription[EventSubscription["None"] = 0] = "None";
/**
* Subscription value to receive events in the `General` category.
*
* Initial OBS Version: 5.0.0
*/
EventSubscription[EventSubscription["General"] = 1] = "General";
/**
* Subscription value to receive events in the `Config` category.
*
* Initial OBS Version: 5.0.0
*/
EventSubscription[EventSubscription["Config"] = 2] = "Config";
/**
* Subscription value to receive events in the `Scenes` category.
*
* Initial OBS Version: 5.0.0
*/
EventSubscription[EventSubscription["Scenes"] = 4] = "Scenes";
/**
* Subscription value to receive events in the `Inputs` category.
*
* Initial OBS Version: 5.0.0
*/
EventSubscription[EventSubscription["Inputs"] = 8] = "Inputs";
/**
* Subscription value to receive events in the `Transitions` category.
*
* Initial OBS Version: 5.0.0
*/
EventSubscription[EventSubscription["Transitions"] = 16] = "Transitions";
/**
* Subscription value to receive events in the `Filters` category.
*
* Initial OBS Version: 5.0.0
*/
EventSubscription[EventSubscription["Filters"] = 32] = "Filters";
/**
* Subscription value to receive events in the `Outputs` category.
*
* Initial OBS Version: 5.0.0
*/
EventSubscription[EventSubscription["Outputs"] = 64] = "Outputs";
/**
* Subscription value to receive events in the `SceneItems` category.
*
* Initial OBS Version: 5.0.0
*/
EventSubscription[EventSubscription["SceneItems"] = 128] = "SceneItems";
/**
* Subscription value to receive events in the `MediaInputs` category.
*
* Initial OBS Version: 5.0.0
*/
EventSubscription[EventSubscription["MediaInputs"] = 256] = "MediaInputs";
/**
* Subscription value to receive the `VendorEvent` event.
*
* Initial OBS Version: 5.0.0
*/
EventSubscription[EventSubscription["Vendors"] = 512] = "Vendors";
/**
* Subscription value to receive events in the `Ui` category.
*
* Initial OBS Version: 5.0.0
*/
EventSubscription[EventSubscription["Ui"] = 1024] = "Ui";
/**
* Helper to receive all non-high-volume events.
*
* Initial OBS Version: 5.0.0
*/
EventSubscription[EventSubscription["All"] = 1023] = "All";
/**
* Subscription value to receive the `InputVolumeMeters` high-volume event.
*
* Initial OBS Version: 5.0.0
*/
EventSubscription[EventSubscription["InputVolumeMeters"] = 65536] = "InputVolumeMeters";
/**
* Subscription value to receive the `InputActiveStateChanged` high-volume event.
*
* Initial OBS Version: 5.0.0
*/
EventSubscription[EventSubscription["InputActiveStateChanged"] = 131072] = "InputActiveStateChanged";
/**
* Subscription value to receive the `InputShowStateChanged` high-volume event.
*
* Initial OBS Version: 5.0.0
*/
EventSubscription[EventSubscription["InputShowStateChanged"] = 262144] = "InputShowStateChanged";
/**
* Subscription value to receive the `SceneItemTransformChanged` high-volume event.
*
* Initial OBS Version: 5.0.0
*/
EventSubscription[EventSubscription["SceneItemTransformChanged"] = 524288] = "SceneItemTransformChanged";
})(EventSubscription || (EventSubscription = {}));
/* eslint-enable no-bitwise, @typescript-eslint/prefer-literal-enum-member */
var RequestBatchExecutionType;
(function (RequestBatchExecutionType) {
/**
* Not a request batch.
*
* Initial OBS Version: 5.0.0
*/
RequestBatchExecutionType[RequestBatchExecutionType["None"] = -1] = "None";
/**
* A request batch which processes all requests serially, as fast as possible.
*
* Note: To introduce artificial delay, use the `Sleep` request and the `sleepMillis` request field.
*
* Initial OBS Version: 5.0.0
*/
RequestBatchExecutionType[RequestBatchExecutionType["SerialRealtime"] = 0] = "SerialRealtime";
/**
* A request batch type which processes all requests serially, in sync with the graphics thread. Designed to provide high accuracy for animations.
*
* Note: To introduce artificial delay, use the `Sleep` request and the `sleepFrames` request field.
*
* Initial OBS Version: 5.0.0
*/
RequestBatchExecutionType[RequestBatchExecutionType["SerialFrame"] = 1] = "SerialFrame";
/**
* A request batch type which processes all requests using all available threads in the thread pool.
*
* Note: This is mainly experimental, and only really shows its colors during requests which require lots of
* active processing, like `GetSourceScreenshot`.
*
* Initial OBS Version: 5.0.0
*/
RequestBatchExecutionType[RequestBatchExecutionType["Parallel"] = 2] = "Parallel";
})(RequestBatchExecutionType || (RequestBatchExecutionType = {}));
var _nodeResolve_empty = {};
var _nodeResolve_empty$1 = {
__proto__: null,
'default': _nodeResolve_empty
};
var core = createCommonjsModule(function (module, exports) {
(function (root, factory) {
{
// CommonJS
module.exports = factory();
}
}(commonjsGlobal, function () {
/*globals window, global, require*/
/**
* CryptoJS core components.
*/
var CryptoJS = CryptoJS || (function (Math, undefined$1) {
var crypto;
// Native crypto from window (Browser)
if (typeof window !== 'undefined' && window.crypto) {
crypto = window.crypto;
}
// Native crypto in web worker (Browser)
if (typeof self !== 'undefined' && self.crypto) {
crypto = self.crypto;
}
// Native crypto from worker
if (typeof globalThis !== 'undefined' && globalThis.crypto) {
crypto = globalThis.crypto;
}
// Native (experimental IE 11) crypto from window (Browser)
if (!crypto && typeof window !== 'undefined' && window.msCrypto) {
crypto = window.msCrypto;
}
// Native crypto from global (NodeJS)
if (!crypto && typeof commonjsGlobal !== 'undefined' && commonjsGlobal.crypto) {
crypto = commonjsGlobal.crypto;
}
// Native crypto import via require (NodeJS)
if (!crypto && typeof commonjsRequire === 'function') {
try {
crypto = _nodeResolve_empty$1;
} catch (err) {}
}
/*
* Cryptographically secure pseudorandom number generator
*
* As Math.random() is cryptographically not safe to use
*/
var cryptoSecureRandomInt = function () {
if (crypto) {
// Use getRandomValues method (Browser)
if (typeof crypto.getRandomValues === 'function') {
try {
return crypto.getRandomValues(new Uint32Array(1))[0];
} catch (err) {}
}
// Use randomBytes method (NodeJS)
if (typeof crypto.randomBytes === 'function') {
try {
return crypto.randomBytes(4).readInt32LE();
} catch (err) {}
}
}
throw new Error('Native crypto module could not be used to get secure random number.');
};
/*
* Local polyfill of Object.create
*/
var create = Object.create || (function () {
function F() {}
return function (obj) {
var subtype;
F.prototype = obj;
subtype = new F();
F.prototype = null;
return subtype;
};
}());
/**
* CryptoJS namespace.
*/
var C = {};
/**
* Library namespace.
*/
var C_lib = C.lib = {};
/**
* Base object for prototypal inheritance.
*/
var Base = C_lib.Base = (function () {
return {
/**
* Creates a new object that inherits from this object.
*
* @param {Object} overrides Properties to copy into the new object.
*
* @return {Object} The new object.
*
* @static
*
* @example
*
* var MyType = CryptoJS.lib.Base.extend({
* field: 'value',
*
* method: function () {
* }
* });
*/
extend: function (overrides) {
// Spawn
var subtype = create(this);
// Augment
if (overrides) {
subtype.mixIn(overrides);
}
// Create default initializer
if (!subtype.hasOwnProperty('init') || this.init === subtype.init) {
subtype.init = function () {
subtype.$super.init.apply(this, arguments);
};
}
// Initializer's prototype is the subtype object
subtype.init.prototype = subtype;
// Reference supertype
subtype.$super = this;
return subtype;
},
/**
* Extends this object and runs the init method.
* Arguments to create() will be passed to init().
*
* @return {Object} The new object.
*
* @static
*
* @example
*
* var instance = MyType.create();
*/
create: function () {
var instance = this.extend();
instance.init.apply(instance, arguments);
return instance;
},
/**
* Initializes a newly created object.
* Override this method to add some logic when your objects are created.
*
* @example
*
* var MyType = CryptoJS.lib.Base.extend({
* init: function () {
* // ...
* }
* });
*/
init: function () {
},
/**
* Copies properties into this object.
*
* @param {Object} properties The properties to mix in.
*
* @example
*
* MyType.mixIn({
* field: 'value'
* });
*/
mixIn: function (properties) {
for (var propertyName in properties) {
if (properties.hasOwnProperty(propertyName)) {
this[propertyName] = properties[propertyName];
}
}
// IE won't copy toString using the loop above
if (properties.hasOwnProperty('toString')) {
this.toString = properties.toString;
}
},
/**
* Creates a copy of this object.
*
* @return {Object} The clone.
*
* @example
*
* var clone = instance.clone();
*/
clone: function () {
return this.init.prototype.extend(this);
}
};
}());
/**
* An array of 32-bit words.
*
* @property {Array} words The array of 32-bit words.
* @property {number} sigBytes The number of significant bytes in this word array.
*/
var WordArray = C_lib.WordArray = Base.extend({
/**
* Initializes a newly created word array.
*
* @param {Array} words (Optional) An array of 32-bit words.
* @param {number} sigBytes (Optional) The number of significant bytes in the words.
*
* @example
*
* var wordArray = CryptoJS.lib.WordArray.create();
* var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607]);
* var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607], 6);
*/
init: function (words, sigBytes) {
words = this.words = words || [];
if (sigBytes != undefined$1) {
this.sigBytes = sigBytes;
} else {
this.sigBytes = words.length * 4;
}
},
/**
* Converts this word array to a string.
*
* @param {Encoder} encoder (Optional) The encoding strategy to use. Default: CryptoJS.enc.Hex
*
* @return {string} The stringified word array.
*
* @example
*
* var string = wordArray + '';
* var string = wordArray.toString();
* var string = wordArray.toString(CryptoJS.enc.Utf8);
*/
toString: function (encoder) {
return (encoder || Hex).stringify(this);
},
/**
* Concatenates a word array to this word array.
*
* @param {WordArray} wordArray The word array to append.
*
* @return {WordArray} This word array.
*
* @example
*
* wordArray1.concat(wordArray2);
*/
concat: function (wordArray) {
// Shortcuts
var thisWords = this.words;
var thatWords = wordArray.words;
var thisSigBytes = this.sigBytes;
var thatSigBytes = wordArray.sigBytes;
// Clamp excess bits
this.clamp();
// Concat
if (thisSigBytes % 4) {
// Copy one byte at a time
for (var i = 0; i < thatSigBytes; i++) {
var thatByte = (thatWords[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
thisWords[(thisSigBytes + i) >>> 2] |= thatByte << (24 - ((thisSigBytes + i) % 4) * 8);
}
} else {
// Copy one word at a time
for (var j = 0; j < thatSigBytes; j += 4) {
thisWords[(thisSigBytes + j) >>> 2] = thatWords[j >>> 2];
}
}
this.sigBytes += thatSigBytes;
// Chainable
return this;
},
/**
* Removes insignificant bits.
*
* @example
*
* wordArray.clamp();
*/
clamp: function () {
// Shortcuts
var words = this.words;
var sigBytes = this.sigBytes;
// Clamp
words[sigBytes >>> 2] &= 0xffffffff << (32 - (sigBytes % 4) * 8);
words.length = Math.ceil(sigBytes / 4);
},
/**
* Creates a copy of this word array.
*
* @return {WordArray} The clone.
*
* @example
*
* var clone = wordArray.clone();
*/
clone: function () {
var clone = Base.clone.call(this);
clone.words = this.words.slice(0);
return clone;
},
/**
* Creates a word array filled with random bytes.
*
* @param {number} nBytes The number of random bytes to generate.
*
* @return {WordArray} The random word array.
*
* @static
*
* @example
*
* var wordArray = CryptoJS.lib.WordArray.random(16);
*/
random: function (nBytes) {
var words = [];
for (var i = 0; i < nBytes; i += 4) {
words.push(cryptoSecureRandomInt());
}
return new WordArray.init(words, nBytes);
}
});
/**
* Encoder namespace.
*/
var C_enc = C.enc = {};
/**
* Hex encoding strategy.
*/
var Hex = C_enc.Hex = {
/**
* Converts a word array to a hex string.
*
* @param {WordArray} wordArray The word array.
*
* @return {string} The hex string.
*
* @static
*
* @example
*
* var hexString = CryptoJS.enc.Hex.stringify(wordArray);
*/
stringify: function (wordArray) {
// Shortcuts
var words = wordArray.words;
var sigBytes = wordArray.sigBytes;
// Convert
var hexChars = [];
for (var i = 0; i < sigBytes; i++) {
var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
hexChars.push((bite >>> 4).toString(16));
hexChars.push((bite & 0x0f).toString(16));
}
return hexChars.join('');
},
/**
* Converts a hex string to a word array.
*
* @param {string} hexStr The hex string.
*
* @return {WordArray} The word array.
*
* @static
*
* @example
*
* var wordArray = CryptoJS.enc.Hex.parse(hexString);
*/
parse: function (hexStr) {
// Shortcut
var hexStrLength = hexStr.length;
// Convert
var words = [];
for (var i = 0; i < hexStrLength; i += 2) {
words[i >>> 3] |= parseInt(hexStr.substr(i, 2), 16) << (24 - (i % 8) * 4);
}
return new WordArray.init(words, hexStrLength / 2);
}
};
/**
* Latin1 encoding strategy.
*/
var Latin1 = C_enc.Latin1 = {
/**
* Converts a word array to a Latin1 string.
*
* @param {WordArray} wordArray The word array.
*
* @return {string} The Latin1 string.
*
* @static
*
* @example
*
* var latin1String = CryptoJS.enc.Latin1.stringify(wordArray);
*/
stringify: function (wordArray) {
// Shortcuts
var words = wordArray.words;
var sigBytes = wordArray.sigBytes;
// Convert
var latin1Chars = [];
for (var i = 0; i < sigBytes; i++) {
var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
latin1Chars.push(String.fromCharCode(bite));
}
return latin1Chars.join('');
},
/**
* Converts a Latin1 string to a word array.
*
* @param {string} latin1Str The Latin1 string.
*
* @return {WordArray} The word array.
*
* @static
*
* @example
*
* var wordArray = CryptoJS.enc.Latin1.parse(latin1String);
*/
parse: function (latin1Str) {
// Shortcut
var latin1StrLength = latin1Str.length;
// Convert
var words = [];
for (var i = 0; i < latin1StrLength; i++) {
words[i >>> 2] |= (latin1Str.charCodeAt(i) & 0xff) << (24 - (i % 4) * 8);
}
return new WordArray.init(words, latin1StrLength);
}
};
/**
* UTF-8 encoding strategy.
*/
var Utf8 = C_enc.Utf8 = {
/**
* Converts a word array to a UTF-8 string.
*
* @param {WordArray} wordArray The word array.
*
* @return {string} The UTF-8 string.
*
* @static
*
* @example
*
* var utf8String = CryptoJS.enc.Utf8.stringify(wordArray);
*/
stringify: function (wordArray) {
try {
return decodeURIComponent(escape(Latin1.stringify(wordArray)));
} catch (e) {
throw new Error('Malformed UTF-8 data');
}
},
/**
* Converts a UTF-8 string to a word array.
*
* @param {string} utf8Str The UTF-8 string.
*
* @return {WordArray} The word array.
*
* @static
*
* @example
*
* var wordArray = CryptoJS.enc.Utf8.parse(utf8String);
*/
parse: function (utf8Str) {
return Latin1.parse(unescape(encodeURIComponent(utf8Str)));
}
};
/**
* Abstract buffered block algorithm template.
*
* The property blockSize must be implemented in a concrete subtype.
*
* @property {number} _minBufferSize The number of blocks that should be kept unprocessed in the buffer. Default: 0
*/
var BufferedBlockAlgorithm = C_lib.BufferedBlockAlgorithm = Base.extend({
/**
* Resets this block algorithm's data buffer to its initial state.
*
* @example
*
* bufferedBlockAlgorithm.reset();
*/
reset: function () {
// Initial values
this._data = new WordArray.init();
this._nDataBytes = 0;
},
/**
* Adds new data to this block algorithm's buffer.
*
* @param {WordArray|string} data The data to append. Strings are converted to a WordArray using UTF-8.
*
* @example
*
* bufferedBlockAlgorithm._append('data');
* bufferedBlockAlgorithm._append(wordArray);
*/
_append: function (data) {
// Convert string to WordArray, else assume WordArray already
if (typeof data == 'string') {
data = Utf8.parse(data);
}
// Append
this._data.concat(data);
this._nDataBytes += data.sigBytes;
},
/**
* Processes available data blocks.
*
* This method invokes _doProcessBlock(offset), which must be implemented by a concrete subtype.
*
* @param {boolean} doFlush Whether all blocks and partial blocks should be processed.
*
* @return {WordArray} The processed data.
*
* @example
*
* var processedData = bufferedBlockAlgorithm._process();
* var processedData = bufferedBlockAlgorithm._process(!!'flush');
*/
_process: function (doFlush) {
var processedWords;
// Shortcuts
var data = this._data;
var dataWords = data.words;
var dataSigBytes = data.sigBytes;
var blockSize = this.blockSize;
var blockSizeBytes = blockSize * 4;
// Count blocks ready
var nBlocksReady = dataSigBytes / blockSizeBytes;
if (doFlush) {
// Round up to include partial blocks
nBlocksReady = Math.ceil(nBlocksReady);
} else {
// Round down to include only full blocks,
// less the number of blocks that must remain in the buffer
nBlocksReady = Math.max((nBlocksReady | 0) - this._minBufferSize, 0);
}
// Count words ready
var nWordsReady = nBlocksReady * blockSize;
// Count bytes ready
var nBytesReady = Math.min(nWordsReady * 4, dataSigBytes);
// Process blocks
if (nWordsReady) {
for (var offset = 0; offset < nWordsReady; offset += blockSize) {
// Perform concrete-algorithm logic
this._doProcessBlock(dataWords, offset);
}
// Remove processed words
processedWords = dataWords.splice(0, nWordsReady);
data.sigBytes -= nBytesReady;
}
// Return processed words
return new WordArray.init(processedWords, nBytesReady);
},
/**
* Creates a copy of this object.
*
* @return {Object} The clone.
*
* @example
*
* var clone = bufferedBlockAlgorithm.clone();
*/
clone: function () {
var clone = Base.clone.call(this);
clone._data = this._data.clone();
return clone;
},
_minBufferSize: 0
});
/**
* Abstract hasher template.
*
* @property {number} blockSize The number of 32-bit words this hasher operates on. Default: 16 (512 bits)
*/
C_lib.Hasher = BufferedBlockAlgorithm.extend({
/**
* Configuration options.
*/
cfg: Base.extend(),
/**
* Initializes a newly created hasher.
*
* @param {Object} cfg (Optional) The configuration options to use for this hash computation.
*
* @example
*
* var hasher = CryptoJS.algo.SHA256.create();
*/
init: function (cfg) {
// Apply config defaults
this.cfg = this.cfg.extend(cfg);
// Set initial values
this.reset();
},
/**
* Resets this hasher to its initial state.
*
* @example
*
* hasher.reset();
*/
reset: function () {
// Reset data buffer
BufferedBlockAlgorithm.reset.call(this);
// Perform concrete-hasher logic
this._doReset();
},
/**
* Updates this hasher with a message.
*
* @param {WordArray|string} messageUpdate The message to append.
*
* @return {Hasher} This hasher.
*
* @example
*
* hasher.update('message');
* hasher.update(wordArray);
*/
update: function (messageUpdate) {
// Append
this._append(messageUpdate);
// Update the hash
this._process();
// Chainable
return this;
},
/**
* Finalizes the hash computation.
* Note that the finalize operation is effectively a destructive, read-once operation.
*
* @param {WordArray|string} messageUpdate (Optional) A final message update.
*
* @return {WordArray} The hash.
*
* @example
*
* var hash = hasher.finalize();
* var hash = hasher.finalize('message');
* var hash = hasher.finalize(wordArray);
*/
finalize: function (messageUpdate) {
// Final message update
if (messageUpdate) {
this._append(messageUpdate);
}
// Perform concrete-hasher logic
var hash = this._doFinalize();
return hash;
},
blockSize: 512/32,
/**
* Creates a shortcut function to a hasher's object interface.
*
* @param {Hasher} hasher The hasher to create a helper for.
*
* @return {Function} The shortcut function.
*
* @static
*
* @example
*
* var SHA256 = CryptoJS.lib.Hasher._createHelper(CryptoJS.algo.SHA256);
*/
_createHelper: function (hasher) {
return function (message, cfg) {
return new hasher.init(cfg).finalize(message);
};
},
/**
* Creates a shortcut function to the HMAC's object interface.
*
* @param {Hasher} hasher The hasher to use in this HMAC helper.
*
* @return {Function} The shortcut function.
*
* @static
*
* @example
*
* var HmacSHA256 = CryptoJS.lib.Hasher._createHmacHelper(CryptoJS.algo.SHA256);
*/
_createHmacHelper: function (hasher) {
return function (message, key) {
return new C_algo.HMAC.init(hasher, key).finalize(message);
};
}
});
/**
* Algorithm namespace.
*/
var C_algo = C.algo = {};
return C;
}(Math));
return CryptoJS;
}));
});
var sha256 = createCommonjsModule(function (module, exports) {
(function (root, factory) {
{
// CommonJS
module.exports = factory(core);
}
}(commonjsGlobal, function (CryptoJS) {
(function (Math) {
// Shortcuts
var C = CryptoJS;
var C_lib = C.lib;
var WordArray = C_lib.WordArray;
var Hasher = C_lib.Hasher;
var C_algo = C.algo;
// Initialization and round constants tables
var H = [];
var K = [];
// Compute constants
(function () {
function isPrime(n) {
var sqrtN = Math.sqrt(n);
for (var factor = 2; factor <= sqrtN; factor++) {
if (!(n % factor)) {
return false;
}
}
return true;
}
function getFractionalBits(n) {
return ((n - (n | 0)) * 0x100000000) | 0;
}
var n = 2;
var nPrime = 0;
while (nPrime < 64) {
if (isPrime(n)) {
if (nPrime < 8) {
H[nPrime] = getFractionalBits(Math.pow(n, 1 / 2));
}
K[nPrime] = getFractionalBits(Math.pow(n, 1 / 3));
nPrime++;
}
n++;
}
}());
// Reusable object
var W = [];
/**
* SHA-256 hash algorithm.
*/
var SHA256 = C_algo.SHA256 = Hasher.extend({
_doReset: function () {
this._hash = new WordArray.init(H.slice(0));
},
_doProcessBlock: function (M, offset) {
// Shortcut
var H = this._hash.words;
// Working variables
var a = H[0];
var b = H[1];
var c = H[2];
var d = H[3];
var e = H[4];
var f = H[5];
var g = H[6];
var h = H[7];
// Computation
for (var i = 0; i < 64; i++) {
if (i < 16) {
W[i] = M[offset + i] | 0;
} else {
var gamma0x = W[i - 15];
var gamma0 = ((gamma0x << 25) | (gamma0x >>> 7)) ^
((gamma0x << 14) | (gamma0x >>> 18)) ^
(gamma0x >>> 3);
var gamma1x = W[i - 2];
var gamma1 = ((gamma1x << 15) | (gamma1x >>> 17)) ^
((gamma1x << 13) | (gamma1x >>> 19)) ^
(gamma1x >>> 10);
W[i] = gamma0 + W[i - 7] + gamma1 + W[i - 16];
}
var ch = (e & f) ^ (~e & g);
var maj = (a & b) ^ (a & c) ^ (b & c);
var sigma0 = ((a << 30) | (a >>> 2)) ^ ((a << 19) | (a >>> 13)) ^ ((a << 10) | (a >>> 22));
var sigma1 = ((e << 26) | (e >>> 6)) ^ ((e << 21) | (e >>> 11)) ^ ((e << 7) | (e >>> 25));
var t1 = h + sigma1 + ch + K[i] + W[i];
var t2 = sigma0 + maj;
h = g;
g = f;
f = e;
e = (d + t1) | 0;
d = c;
c = b;
b = a;
a = (t1 + t2) | 0;
}
// Intermediate hash value
H[0] = (H[0] + a) | 0;
H[1] = (H[1] + b) | 0;
H[2] = (H[2] + c) | 0;
H[3] = (H[3] + d) | 0;
H[4] = (H[4] + e) | 0;
H[5] = (H[5] + f) | 0;
H[6] = (H[6] + g) | 0;
H[7] = (H[7] + h) | 0;
},
_doFinalize: function () {
// Shortcuts
var data = this._data;
var dataWords = data.words;
var nBitsTotal = this._nDataBytes * 8;
var nBitsLeft = data.sigBytes * 8;
// Add padding
dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32);
dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = Math.floor(nBitsTotal / 0x100000000);
dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = nBitsTotal;
data.sigBytes = dataWords.length * 4;
// Hash final blocks
this._process();
// Return final computed hash
return this._hash;
},
clone: function () {
var clone = Hasher.clone.call(this);
clone._hash = this._hash.clone();
return clone;
}
});
/**
* Shortcut function to the hasher's object interface.
*
* @param {WordArray|string} message The message to hash.
*
* @return {WordArray} The hash.
*
* @static
*
* @example
*
* var hash = CryptoJS.SHA256('message');
* var hash = CryptoJS.SHA256(wordArray);
*/
C.SHA256 = Hasher._createHelper(SHA256);
/**
* Shortcut function to the HMAC's object interface.
*
* @param {WordArray|string} message The message to hash.
* @param {WordArray|string} key The secret key.
*
* @return {WordArray} The HMAC.
*
* @static
*
* @example
*
* var hmac = CryptoJS.HmacSHA256(message, key);
*/
C.HmacSHA256 = Hasher._createHmacHelper(SHA256);
}(Math));
return CryptoJS.SHA256;
}));
});
var encBase64 = createCommonjsModule(function (module, exports) {
(function (root, factory) {
{
// CommonJS
module.exports = factory(core);
}
}(commonjsGlobal, function (CryptoJS) {
(function () {
// Shortcuts
var C = CryptoJS;
var C_lib = C.lib;
var WordArray = C_lib.WordArray;
var C_enc = C.enc;
/**
* Base64 encoding strategy.
*/
C_enc.Base64 = {
/**
* Converts a word array to a Base64 string.
*
* @param {WordArray} wordArray The word array.
*
* @return {string} The Base64 string.
*
* @static
*
* @example
*
* var base64String = CryptoJS.enc.Base64.stringify(wordArray);
*/
stringify: function (wordArray) {
// Shortcuts
var words = wordArray.words;
var sigBytes = wordArray.sigBytes;
var map = this._map;
// Clamp excess bits
wordArray.clamp();
// Convert
var base64Chars = [];
for (var i = 0; i < sigBytes; i += 3) {
var byte1 = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
var byte2 = (words[(i + 1) >>> 2] >>> (24 - ((i + 1) % 4) * 8)) & 0xff;
var byte3 = (words[(i + 2) >>> 2] >>> (24 - ((i + 2) % 4) * 8)) & 0xff;
var triplet = (byte1 << 16) | (byte2 << 8) | byte3;
for (var j = 0; (j < 4) && (i + j * 0.75 < sigBytes); j++) {
base64Chars.push(map.charAt((triplet >>> (6 * (3 - j))) & 0x3f));
}
}
// Add padding
var paddingChar = map.charAt(64);
if (paddingChar) {
while (base64Chars.length % 4) {
base64Chars.push(paddingChar);
}
}
return base64Chars.join('');
},
/**
* Converts a Base64 string to a word array.
*
* @param {string} base64Str The Base64 string.
*
* @return {WordArray} The word array.
*
* @static
*
* @example
*
* var wordArray = CryptoJS.enc.Base64.parse(base64String);
*/
parse: function (base64Str) {
// Shortcuts
var base64StrLength = base64Str.length;
var map = this._map;
var reverseMap = this._reverseMap;
if (!reverseMap) {
reverseMap = this._reverseMap = [];
for (var j = 0; j < map.length; j++) {
reverseMap[map.charCodeAt(j)] = j;
}
}
// Ignore padding
var paddingChar = map.charAt(64);
if (paddingChar) {
var paddingIndex = base64Str.indexOf(paddingChar);
if (paddingIndex !== -1) {
base64StrLength = paddingIndex;
}
}
// Convert
return parseLoop(base64Str, base64StrLength, reverseMap);
},
_map: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='
};
function parseLoop(base64Str, base64StrLength, reverseMap) {
var words = [];
var nBytes = 0;
for (var i = 0; i < base64StrLength; i++) {
if (i % 4) {
var bits1 = reverseMap[base64Str.charCodeAt(i - 1)] << ((i % 4) * 2);
var bits2 = reverseMap[base64Str.charCodeAt(i)] >>> (6 - (i % 4) * 2);
var bitsCombined = bits1 | bits2;
words[nBytes >>> 2] |= bitsCombined << (24 - (nBytes % 4) * 8);
nBytes++;
}
}
return WordArray.create(words, nBytes);
}
}());
return CryptoJS.enc.Base64;
}));
});
/**
* SHA256 Hashing.
*
* @param {string} [salt=''] salt.
* @param {string} [challenge=''] challenge.
* @param {string} msg Message to encode.
* @returns {string} sha256 encoded string.
*/
function authenticationHashing (salt, challenge, msg) {
var hash = encBase64.stringify(sha256(msg + salt));
return encBase64.stringify(sha256(hash + challenge));
}
var _excluded = ["authentication", "rpcVersion"];
function _catch(body, recover) {
try {
var result = body();
} catch (e) {
return recover(e);
}
if (result && result.then) {
return result.then(void 0, recover);
}
return result;
}
var debug = browser$1('obs-websocket-js');
var OBSWebSocketError = /*#__PURE__*/function (_Error) {
_inheritsLoose(OBSWebSocketError, _Error);
function OBSWebSocketError(code, message) {
var _this;
_this = _Error.call(this, message) || this;
_this.code = void 0;
_this.code = code;
return _this;
}
return OBSWebSocketError;
}( /*#__PURE__*/_wrapNativeSuper(Error));
var BaseOBSWebSocket = /*#__PURE__*/function (_EventEmitter) {
_inheritsLoose(BaseOBSWebSocket, _EventEmitter);
function BaseOBSWebSocket() {
var _this2;
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
_this2 = _EventEmitter.call.apply(_EventEmitter, [this].concat(args)) || this;
_this2._identified = false;
_this2.internalListeners = new eventemitter3();
_this2.socket = void 0;
return _this2;
}
BaseOBSWebSocket.generateMessageId = function generateMessageId() {
return String(BaseOBSWebSocket.requestCounter++);
};
var _proto = BaseOBSWebSocket.prototype;
/**
* Connect to an obs-websocket server
*
* @param url Websocket server to connect to (including ws:// or wss:// protocol)
* @param password Password
* @param identificationParams Data for Identify event
* @returns Hello & Identified messages data (combined)
*/
_proto.connect = function connect(url, password, identificationParams) {
if (url === void 0) {
url = 'ws://127.0.0.1:4455';
}
if (identificationParams === void 0) {
identificationParams = {};
}
try {
var _temp3 = function _temp3() {
return _catch(function () {
var connectionClosedPromise = _this4.internalEventPromise('ConnectionClosed');
var connectionErrorPromise = _this4.internalEventPromise('ConnectionError');
return Promise.resolve(Promise.race([function () {
try {
return Promise.resolve(_this4.createConnection(url)).then(function (hello) {
_this4.emit('Hello', hello);
return _this4.identify(hello, password, identificationParams);
});
} catch (e) {
return Promise.reject(e);
}
}(), // Choose the best promise for connection error/close
// In browser connection close has close code + reason,
// while in node error event has these
new Promise(function (resolve, reject) {
void connectionErrorPromise.then(function (e) {
if (e.message) {
reject(e);
}
});
void connectionClosedPromise.then(function (e) {
reject(e);
});
})]));
}, function (error) {
return Promise.resolve(_this4.disconnect()).then(function () {
throw error;
});
});
};
var _this4 = this;
var _temp4 = function () {
if (_this4.socket) {
return Promise.resolve(_this4.disconnect()).then(function () {});
}
}();
return Promise.resolve(_temp4 && _temp4.then ? _temp4.then(_temp3) : _temp3(_temp4));
} catch (e) {
return Promise.reject(e);
}
}
/**
* Disconnect from obs-websocket server
*/
;
_proto.disconnect = function disconnect() {
try {
var _this6 = this;
if (!_this6.socket || _this6.socket.readyState === browser.CLOSED) {
return Promise.resolve();
}
var connectionClosedPromise = _this6.internalEventPromise('ConnectionClosed');
_this6.socket.close();
return Promise.resolve(connectionClosedPromise).then(function () {});
} catch (e) {
return Promise.reject(e);
}
}
/**
* Update session parameters
*
* @param data Reidentify data
* @returns Identified message data
*/
;
_proto.reidentify = function reidentify(data) {
try {
var _this8 = this;
var identifiedPromise = _this8.internalEventPromise("op:" + WebSocketOpCode.Identified);
return Promise.resolve(_this8.message(WebSocketOpCode.Reidentify, data)).then(function () {
return identifiedPromise;
});
} catch (e) {
return Promise.reject(e);
}
}
/**
* Send a request to obs-websocket
*
* @param requestType Request name
* @param requestData Request data
* @returns Request response
*/
;
_proto.call = function call(requestType, requestData) {
try {
var _this10 = this;
var requestId = BaseOBSWebSocket.generateMessageId();
var responsePromise = _this10.internalEventPromise("res:" + requestId);
return Promise.resolve(_this10.message(WebSocketOpCode.Request, {
requestId: requestId,
requestType: requestType,
requestData: requestData
})).then(function () {
return Promise.resolve(responsePromise).then(function (_ref) {
var requestStatus = _ref.requestStatus,
responseData = _ref.responseData;
if (!requestStatus.result) {
throw new OBSWebSocketError(requestStatus.code, requestStatus.comment);
}
return responseData;
});
});
} catch (e) {
return Promise.reject(e);
}
}
/**
* Send a batch request to obs-websocket
*
* @param requests Array of Request objects (type and data)
* @param options A set of options for how the batch will be executed
* @param options.executionType The mode of execution obs-websocket will run the batch in
* @param options.haltOnFailure Whether obs-websocket should stop executing the batch if one request fails
* @returns RequestBatch response
*/
;
_proto.callBatch = function callBatch(requests, options) {
if (options === void 0) {
options = {};
}
try {
var _this12 = this;
var requestId = BaseOBSWebSocket.generateMessageId();
var responsePromise = _this12.internalEventPromise("res:" + requestId);
return Promise.resolve(_this12.message(WebSocketOpCode.RequestBatch, _extends({
requestId: requestId,
requests: requests
}, options))).then(function () {
return Promise.resolve(responsePromise).then(function (_ref2) {
var results = _ref2.results;
return results;
});
});
} catch (e) {
return Promise.reject(e);
}
}
/**
* Cleanup from socket disconnection
*/
;
_proto.cleanup = function cleanup() {
if (!this.socket) {
return;
}
this.socket.onopen = null;
this.socket.onmessage = null;
this.socket.onerror = null;
this.socket.onclose = null;
this.socket = undefined;
this._identified = false; // Cleanup leftovers
this.internalListeners.removeAllListeners();
}
/**
* Create connection to specified obs-websocket server
*
* @private
* @param url Websocket address
* @returns Promise for hello data
*/
;
_proto.createConnection = function createConnection(url) {
try {
var _this14 = this;
var connectionOpenedPromise = _this14.internalEventPromise('ConnectionOpened');
var helloPromise = _this14.internalEventPromise("op:" + WebSocketOpCode.Hello);
_this14.socket = new browser(url, _this14.protocol);
_this14.socket.onopen = _this14.onOpen.bind(_this14);
_this14.socket.onmessage = _this14.onMessage.bind(_this14);
_this14.socket.onerror = _this14.onError.bind(_this14);
_this14.socket.onclose = _this14.onClose.bind(_this14);
return Promise.resolve(connectionOpenedPromise).then(function () {
var _this14$socket;
var protocol = (_this14$socket = _this14.socket) == null ? void 0 : _this14$socket.protocol; // Browsers don't autoclose on missing/wrong protocol
if (!protocol) {
throw new OBSWebSocketError(-1, 'Server sent no subprotocol');
}
if (protocol !== _this14.protocol) {
throw new OBSWebSocketError(-1, 'Server sent an invalid subprotocol');
}
return helloPromise;
});
} catch (e) {
return Promise.reject(e);
}
}
/**
* Send identify message
*
* @private
* @param hello Hello message data
* @param password Password
* @param identificationParams Identification params
* @returns Hello & Identified messages data (combined)
*/
;
_proto.identify = function identify(_ref3, password, identificationParams) {
var authentication = _ref3.authentication,
rpcVersion = _ref3.rpcVersion,
helloRest = _objectWithoutPropertiesLoose(_ref3, _excluded);
if (identificationParams === void 0) {
identificationParams = {};
}
try {
var _this16 = this;
// Set rpcVersion if unset
var data = _extends({
rpcVersion: rpcVersion
}, identificationParams);
if (authentication && password) {
data.authentication = authenticationHashing(authentication.salt, authentication.challenge, password);
}
var identifiedPromise = _this16.internalEventPromise("op:" + WebSocketOpCode.Identified);
return Promise.resolve(_this16.message(WebSocketOpCode.Identify, data)).then(function () {
return Promise.resolve(identifiedPromise).then(function (identified) {
_this16._identified = true;
_this16.emit('Identified', identified);
return _extends({
rpcVersion: rpcVersion
}, helloRest, identified);
});
});
} catch (e) {
return Promise.reject(e);
}
}
/**
* Send message to obs-websocket
*
* @private
* @param op WebSocketOpCode
* @param d Message data
*/
;
_proto.message = function message(op, d) {
try {
var _this18 = this;
if (!_this18.socket) {
throw new Error('Not connected');
}
if (!_this18.identified && op !== 1) {
throw new Error('Socket not identified');
}
return Promise.resolve(_this18.encodeMessage({
op: op,
d: d
})).then(function (encoded) {
_this18.socket.send(encoded);
});
} catch (e) {
return Promise.reject(e);
}
}
/**
* Create a promise to listen for an event on internal listener
* (will be cleaned up on disconnect)
*
* @private
* @param event Event to listen to
* @returns Event data
*/
;
_proto.internalEventPromise = function internalEventPromise(event) {
try {
var _this20 = this;
return Promise.resolve(new Promise(function (resolve) {
_this20.internalListeners.once(event, resolve);
}));
} catch (e) {
return Promise.reject(e);
}
}
/**
* Websocket open event listener
*
* @private
* @param e Event
*/
;
_proto.onOpen = function onOpen(e) {
debug('socket.open');
this.emit('ConnectionOpened');
this.internalListeners.emit('ConnectionOpened', e);
}
/**
* Websocket message event listener
*
* @private
* @param e Event
*/
;
_proto.onMessage = function onMessage(e) {
try {
var _this22 = this;
return Promise.resolve(_catch(function () {
return Promise.resolve(_this22.decodeMessage(e.data)).then(function (_ref4) {
var op = _ref4.op,
d = _ref4.d;
debug('socket.message: %d %j', op, d);
if (op === undefined || d === undefined) {
return;
}
switch (op) {
case WebSocketOpCode.Event:
{
var eventType = d.eventType,
eventData = d.eventData; // @ts-expect-error Typescript just doesn't understand it
_this22.emit(eventType, eventData);
return;
}
case WebSocketOpCode.RequestResponse:
case WebSocketOpCode.RequestBatchResponse:
{
var requestId = d.requestId;
_this22.internalListeners.emit("res:" + requestId, d);
return;
}
default:
_this22.internalListeners.emit("op:" + op, d);
}
});
}, function (error) {
debug('error handling message: %o', error);
}));
} catch (e) {
return Promise.reject(e);
}
}
/**
* Websocket error event listener
*
* @private
* @param e ErrorEvent
*/
;
_proto.onError = function onError(e) {
debug('socket.error: %o', e);
var error = new OBSWebSocketError(-1, e.message);
this.emit('ConnectionError', error);
this.internalListeners.emit('ConnectionError', error);
}
/**
* Websocket close event listener
*
* @private
* @param e Event
*/
;
_proto.onClose = function onClose(e) {
debug('socket.close: %s (%d)', e.reason, e.code);
var error = new OBSWebSocketError(e.code, e.reason);
this.emit('ConnectionClosed', error);
this.internalListeners.emit('ConnectionClosed', error);
this.cleanup();
};
_createClass(BaseOBSWebSocket, [{
key: "identified",
get: function get() {
return this._identified;
}
}]);
return BaseOBSWebSocket;
}(eventemitter3); // https://github.com/developit/microbundle/issues/531#issuecomment-575473024
// Not using ESM export due to it also being detected and breaking rollup based bundlers (vite)
BaseOBSWebSocket.requestCounter = 1;
if (typeof exports !== 'undefined') {
Object.defineProperty(exports, '__esModule', {
value: true
});
}
var OBSWebSocket$1 = /*#__PURE__*/function (_BaseOBSWebSocket) {
_inheritsLoose(OBSWebSocket, _BaseOBSWebSocket);
function OBSWebSocket() {
var _this;
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
_this = _BaseOBSWebSocket.call.apply(_BaseOBSWebSocket, [this].concat(args)) || this;
_this.protocol = 'obswebsocket.json';
return _this;
}
var _proto = OBSWebSocket.prototype;
_proto.encodeMessage = function encodeMessage(data) {
try {
return Promise.resolve(JSON.stringify(data));
} catch (e) {
return Promise.reject(e);
}
};
_proto.decodeMessage = function decodeMessage(data) {
try {
return Promise.resolve(JSON.parse(data));
} catch (e) {
return Promise.reject(e);
}
};
return OBSWebSocket;
}(BaseOBSWebSocket);
var OBSWebSocket = /*#__PURE__*/function (_JSONOBSWebSocket) {
_inheritsLoose(OBSWebSocket, _JSONOBSWebSocket);
function OBSWebSocket() {
return _JSONOBSWebSocket.apply(this, arguments) || this;
}
return OBSWebSocket;
}(OBSWebSocket$1);
OBSWebSocket.OBSWebSocketError = OBSWebSocketError;
OBSWebSocket.WebSocketOpCode = WebSocketOpCode;
OBSWebSocket.EventSubscription = EventSubscription;
OBSWebSocket.RequestBatchExecutionType = RequestBatchExecutionType;
return OBSWebSocket;
})();
//# sourceMappingURL=obs-ws.js.map
const { contextBridge, ipcRenderer } = require('electron');
window.addEventListener('DOMContentLoaded', () => {
if (window.trustedTypes && window.trustedTypes.createPolicy) {
window.trustedTypes.createPolicy('default', {
createHTML: (string) => string,
createScriptURL: string => string, // warning: this is unsafe!
createScript: string => string // warning: this is unsafe!
});
}
setTimeout(setup, 100);
setInterval(deleteBG, 500);
keySim("83");
ipcRenderer.on('next-slide', (_event) => {
console.log("next slide message received")
keySim(39);
})
ipcRenderer.on('previous-slide', (_event) => {
console.log("next slide message received")
keySim(37);
})
})
function keySim(k){
document.dispatchEvent(
new KeyboardEvent("keydown", {
keyCode: k
})
);
}
function setup() {
const style = document.createElement('style');
style.innerHTML = `
html {
background-color: rgba(0,0,0,0) !important;
}
body {
background-color: rgba(0,0,0,0) !important;
}
.punch-viewer-content {
background: #0000;
}
:fullscreen {
background: #0000;
}
:fullscreen::backdrop {
background: #0000;
}
`;
window.document.body.append(style);
}
function deleteBG() {
const elem = document.querySelectorAll('path[fill="#abcdef"]')[0]
if(elem){
console.log(elem)
elem.previousElementSibling.remove();
elem.remove();
}
}
html, body {
margin: 0;
padding: 0;
}
canvas {
display: block;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment