mirror of
https://github.com/FeloDeck/obs-tools.git
synced 2026-11-01 17:33:29 +01:00
123 lines
5.7 KiB
JavaScript
123 lines
5.7 KiB
JavaScript
// Second page: monitoring, set volume, scene above, and an OpenDeck multi action.
|
|
// Needs the profile from layout-extra.json.
|
|
import { ObsClient } from "../../de.felitendo.obs-tools.sdPlugin/plugin/lib/obs.js";
|
|
import { readLocalObsConfig } from "../../de.felitendo.obs-tools.sdPlugin/plugin/lib/connections.js";
|
|
import { faderToDb } from "../../de.felitendo.obs-tools.sdPlugin/plugin/lib/volume.js";
|
|
|
|
const DECK = process.env.VIRTUAL_DECK_URL || "http://127.0.0.1:57190";
|
|
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
const press = (key, ms = 80) => fetch(`${DECK}/api/key/${key}/press?ms=${ms}`, { method: "POST" });
|
|
const cfg = readLocalObsConfig();
|
|
const obs = new ObsClient({ port: cfg.port, password: cfg.password });
|
|
await new Promise((resolve) => (obs.once("connected", resolve), obs.start()));
|
|
const call = (t, d) => obs.call(t, d);
|
|
async function waitFor(what, fn, timeout = 5000) {
|
|
const until = Date.now() + timeout;
|
|
let last;
|
|
while (Date.now() < until) {
|
|
if ((last = await fn())) return last;
|
|
await sleep(100);
|
|
}
|
|
throw new Error(`timeout waiting for ${what}`);
|
|
}
|
|
let failed = 0;
|
|
async function test(name, fn) {
|
|
try {
|
|
await fn();
|
|
console.log(`ok ${name}`);
|
|
} catch (error) {
|
|
failed++;
|
|
console.log(`FAIL ${name}: ${error.message}`);
|
|
}
|
|
}
|
|
const input = "Desktop-Audio";
|
|
|
|
await call("SetCurrentProgramScene", { sceneName: "Szene" });
|
|
await call("SetInputAudioMonitorType", { inputName: input, monitorType: "OBS_MONITORING_TYPE_NONE" });
|
|
await sleep(500);
|
|
|
|
await test("monitor set, press again turns it off", async () => {
|
|
await press(0);
|
|
await waitFor("monitor only", async () => (await call("GetInputAudioMonitorType", { inputName: input })).monitorType === "OBS_MONITORING_TYPE_MONITOR_ONLY");
|
|
await sleep(300);
|
|
await press(0);
|
|
await waitFor("monitor off", async () => (await call("GetInputAudioMonitorType", { inputName: input })).monitorType === "OBS_MONITORING_TYPE_NONE");
|
|
});
|
|
|
|
await test("set volume to 50% of the fader", async () => {
|
|
await call("SetInputVolume", { inputName: input, inputVolumeDb: 0 });
|
|
await press(8);
|
|
const target = faderToDb(0.5);
|
|
await waitFor(`${target.toFixed(2)} dB`, async () => Math.abs((await call("GetInputVolume", { inputName: input })).inputVolumeDb - target) < 0.05);
|
|
await call("SetInputVolume", { inputName: input, inputVolumeDb: 0 });
|
|
});
|
|
|
|
await test("scene above (previous in the list)", async () => {
|
|
const { scenes } = await call("GetSceneList");
|
|
const order = [...scenes].sort((a, b) => b.sceneIndex - a.sceneIndex).map((s) => s.sceneName);
|
|
const expected = order[(order.indexOf("Szene") - 1 + order.length) % order.length];
|
|
await press(5);
|
|
await waitFor(`program = ${expected}`, async () => (await call("GetCurrentProgramScene")).sceneName === expected);
|
|
await call("SetCurrentProgramScene", { sceneName: "Szene" });
|
|
await sleep(300);
|
|
});
|
|
|
|
await test("multi action: studio on, mute, scene goes live directly", async () => {
|
|
await call("SetStudioModeEnabled", { studioModeEnabled: false });
|
|
await call("SetInputMute", { inputName: input, inputMuted: false });
|
|
await sleep(300);
|
|
await press(9);
|
|
await waitFor("studio mode on", async () => (await call("GetStudioModeEnabled")).studioModeEnabled);
|
|
await waitFor("muted", async () => (await call("GetInputMute", { inputName: input })).inputMuted);
|
|
await waitFor("program = Scene 2", async () => (await call("GetCurrentProgramScene")).sceneName === "Scene 2", 6000);
|
|
// "enable" and "mute" must not toggle back on a second run.
|
|
await sleep(500);
|
|
await press(9);
|
|
await sleep(1200);
|
|
if (!(await call("GetStudioModeEnabled")).studioModeEnabled) throw new Error("second run turned studio mode off");
|
|
if (!(await call("GetInputMute", { inputName: input })).inputMuted) throw new Error("second run unmuted");
|
|
await call("SetStudioModeEnabled", { studioModeEnabled: false });
|
|
await call("SetInputMute", { inputName: input, inputMuted: false });
|
|
await call("SetCurrentProgramScene", { sceneName: "Szene" });
|
|
});
|
|
|
|
await test("image source: picture per key, auto hide, press again hides", async () => {
|
|
const { sceneItemId } = await call("GetSceneItemId", { sceneName: "Szene", sourceName: "Picture" });
|
|
const shown = async () => (await call("GetSceneItemEnabled", { sceneName: "Szene", sceneItemId })).sceneItemEnabled;
|
|
const file = async () => (await call("GetInputSettings", { inputName: "Picture" })).inputSettings.file;
|
|
await call("SetSceneItemEnabled", { sceneName: "Szene", sceneItemId, sceneItemEnabled: false });
|
|
await sleep(300);
|
|
await press(12);
|
|
await waitFor("GG shown", async () => (await shown()) && (await file()).endsWith("obstools-gg.png"));
|
|
await waitFor("hidden after 2 s", async () => !(await shown()), 4000);
|
|
await press(13);
|
|
await waitFor("BRB shown", async () => (await shown()) && (await file()).endsWith("obstools-brb.png"));
|
|
await sleep(400);
|
|
await press(13);
|
|
await waitFor("hidden by second press", async () => !(await shown()));
|
|
});
|
|
|
|
await test("set text: count down from 3, stops at 0, double press, hold", async () => {
|
|
const text = async () => (await call("GetInputSettings", { inputName: "Title Text" })).inputSettings.text;
|
|
const pressAndWait = async (expected, ms) => {
|
|
await press(14, ms);
|
|
await waitFor(expected, async () => (await text()) === expected);
|
|
// A pause, or the next press would make a double press.
|
|
await sleep(500);
|
|
};
|
|
await pressAndWait("Live in 3", 1000);
|
|
await pressAndWait("Live in 2");
|
|
await pressAndWait("Live in 1");
|
|
await pressAndWait("Live in 0");
|
|
await pressAndWait("Live in 0");
|
|
await press(14);
|
|
await press(14);
|
|
await waitFor("Live in 1 (double press counts up)", async () => (await text()) === "Live in 1");
|
|
await sleep(500);
|
|
await pressAndWait("Live in 3", 1000);
|
|
});
|
|
|
|
obs.stop();
|
|
console.log(failed ? `${failed} failed` : "all passed");
|
|
process.exit(failed ? 1 : 0);
|