Add OBS actions, refactor some code and add configuration panel
This commit is contained in:
parent
d4029c8ef0
commit
3efa1beb4d
17 changed files with 449 additions and 47 deletions
94
package-lock.json
generated
94
package-lock.json
generated
|
@ -15,6 +15,7 @@
|
|||
"materialize-css": "^1.0.0-rc.2",
|
||||
"morgan": "~1.9.1",
|
||||
"node-sass-middleware": "0.11.0",
|
||||
"obs-websocket-js": "^4.0.2",
|
||||
"pug": "2.0.0-beta11",
|
||||
"socket.io": "^3.1.2"
|
||||
},
|
||||
|
@ -1308,6 +1309,14 @@
|
|||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
||||
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
|
||||
},
|
||||
"node_modules/isomorphic-ws": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz",
|
||||
"integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==",
|
||||
"peerDependencies": {
|
||||
"ws": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/isstream": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
|
||||
|
@ -1726,6 +1735,38 @@
|
|||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/obs-websocket-js": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/obs-websocket-js/-/obs-websocket-js-4.0.2.tgz",
|
||||
"integrity": "sha512-e+tGp0DQNXSnitc5lfuzEC1dG3VdWy7VLePUVb6aq7bC33Sgjoi695k0eOg4UPTIQI71Z9aJ+yn3nvBX9dQkEg==",
|
||||
"dependencies": {
|
||||
"debug": "^4.1.0",
|
||||
"isomorphic-ws": "^4.0.1",
|
||||
"sha.js": "^2.4.9",
|
||||
"ws": "^7.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/obs-websocket-js/node_modules/debug": {
|
||||
"version": "4.3.1",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
|
||||
"integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
|
||||
"dependencies": {
|
||||
"ms": "2.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"supports-color": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/obs-websocket-js/node_modules/ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
},
|
||||
"node_modules/on-finished": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
|
||||
|
@ -2332,6 +2373,18 @@
|
|||
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
|
||||
"integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ=="
|
||||
},
|
||||
"node_modules/sha.js": {
|
||||
"version": "2.4.11",
|
||||
"resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz",
|
||||
"integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==",
|
||||
"dependencies": {
|
||||
"inherits": "^2.0.1",
|
||||
"safe-buffer": "^5.0.1"
|
||||
},
|
||||
"bin": {
|
||||
"sha.js": "bin.js"
|
||||
}
|
||||
},
|
||||
"node_modules/signal-exit": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
|
||||
|
@ -4042,6 +4095,12 @@
|
|||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
||||
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
|
||||
},
|
||||
"isomorphic-ws": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz",
|
||||
"integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==",
|
||||
"requires": {}
|
||||
},
|
||||
"isstream": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
|
||||
|
@ -4377,6 +4436,32 @@
|
|||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
|
||||
},
|
||||
"obs-websocket-js": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/obs-websocket-js/-/obs-websocket-js-4.0.2.tgz",
|
||||
"integrity": "sha512-e+tGp0DQNXSnitc5lfuzEC1dG3VdWy7VLePUVb6aq7bC33Sgjoi695k0eOg4UPTIQI71Z9aJ+yn3nvBX9dQkEg==",
|
||||
"requires": {
|
||||
"debug": "^4.1.0",
|
||||
"isomorphic-ws": "^4.0.1",
|
||||
"sha.js": "^2.4.9",
|
||||
"ws": "^7.2.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"debug": {
|
||||
"version": "4.3.1",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
|
||||
"integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
|
||||
"requires": {
|
||||
"ms": "2.1.2"
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"on-finished": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
|
||||
|
@ -4877,6 +4962,15 @@
|
|||
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
|
||||
"integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ=="
|
||||
},
|
||||
"sha.js": {
|
||||
"version": "2.4.11",
|
||||
"resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz",
|
||||
"integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==",
|
||||
"requires": {
|
||||
"inherits": "^2.0.1",
|
||||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"signal-exit": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
"materialize-css": "^1.0.0-rc.2",
|
||||
"morgan": "~1.9.1",
|
||||
"node-sass-middleware": "0.11.0",
|
||||
"obs-websocket-js": "^4.0.2",
|
||||
"pug": "2.0.0-beta11",
|
||||
"socket.io": "^3.1.2"
|
||||
},
|
||||
|
|
67
public/javascripts/settings/config.js
Normal file
67
public/javascripts/settings/config.js
Normal file
|
@ -0,0 +1,67 @@
|
|||
import { formMaker, inputFieldMaker } from "/javascripts/tools/formMaker.js"
|
||||
const socket = io();
|
||||
const collapsible = document.querySelector(".collapsible");
|
||||
|
||||
socket.on("connected", () => {
|
||||
console.log("Connected !");
|
||||
socket.emit("getType");
|
||||
});
|
||||
|
||||
socket.on("getType", data => {
|
||||
collapsible.innerHTML = "";
|
||||
for (const type of data)
|
||||
if (type.configuration) {
|
||||
const [formRow, form] = formMaker();
|
||||
for (const [name, conf] of Object.entries(type.configuration)) {
|
||||
let secondRow = document.createElement("div");
|
||||
secondRow.classList.add("row");
|
||||
form.insertAdjacentElement("beforeend", secondRow);
|
||||
secondRow.insertAdjacentElement("beforeend", inputFieldMaker(type.type, conf.type, name, conf));
|
||||
}
|
||||
|
||||
const save = document.createElement("a");
|
||||
save.classList.add("waves-effect", "waves-light", "btn", "blue");
|
||||
save.innerText = "Save";
|
||||
save.addEventListener("click", ev => {
|
||||
ev.stopPropagation();
|
||||
let data = {};
|
||||
for (const e of new FormData(form))
|
||||
data[e[0]] = e[1];
|
||||
socket.emit("setTypeConfig", {type: type.type, configuration: data})
|
||||
});
|
||||
formRow.insertAdjacentElement("beforeend", save);
|
||||
|
||||
addCollapsible(type.name, formRow);
|
||||
}
|
||||
M.updateTextFields();
|
||||
});
|
||||
|
||||
socket.on("setTypeConfig", data => {
|
||||
if (data && data.configuration) {
|
||||
for (const [name, value] of Object.entries(data.configuration))
|
||||
document.getElementById(data.type + "-" + name).value = value;
|
||||
M.updateTextFields();
|
||||
}
|
||||
});
|
||||
|
||||
function addCollapsible(title, content) {
|
||||
const li = document.createElement("li");
|
||||
const divTitle = document.createElement("div");
|
||||
divTitle.classList.add("collapsible-header");
|
||||
divTitle.innerText = title;
|
||||
li.insertAdjacentElement("beforeend", divTitle);
|
||||
const divContent = document.createElement("div");
|
||||
divContent.classList.add("collapsible-body");
|
||||
if (content)
|
||||
if (typeof content !== "string")
|
||||
divContent.insertAdjacentElement("beforeend", content);
|
||||
else
|
||||
divContent.insertAdjacentHTML("beforeend", content);
|
||||
li.insertAdjacentElement("beforeend", divContent);
|
||||
collapsible.insertAdjacentElement("beforeend", li);
|
||||
return li;
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
M.AutoInit();
|
||||
});
|
|
@ -1,3 +1,5 @@
|
|||
import { inputFieldMaker } from "/javascripts/tools/formMaker.js"
|
||||
|
||||
const socket = io();
|
||||
const deckSelect = document.getElementById("deck-select");
|
||||
const deck = document.getElementById("deck");
|
||||
|
@ -217,37 +219,13 @@ function customFields(values) {
|
|||
customs.innerHTML = "";
|
||||
let t = types.find(v => v.type === type.value);
|
||||
for (const [name, field] of Object.entries(t.fields)) {
|
||||
let e;
|
||||
switch (field.type) {
|
||||
case "text":
|
||||
e = document.createElement("input");
|
||||
e.type = "text";
|
||||
break;
|
||||
case "select":
|
||||
e = document.createElement("select");
|
||||
for (let option of field.options)
|
||||
e.insertAdjacentHTML("beforeend", `<option value="${option}">${option}</option>`);
|
||||
break;
|
||||
}
|
||||
e.name = name;
|
||||
e.id = name;
|
||||
e.required = true;
|
||||
e.classList.add("validate");
|
||||
let d = document.createElement("div");
|
||||
d.classList.add("input-field");
|
||||
d.insertAdjacentElement("beforeend", e);
|
||||
d.insertAdjacentHTML("beforeend", `<label for="${name}">${field.name}</label>`);
|
||||
if (field.helper)
|
||||
d.insertAdjacentHTML("beforeend", `<span class="helper-text">${field.helper}</span>`);
|
||||
customs.insertAdjacentElement("beforeend", d);
|
||||
if (values && name in values) {
|
||||
e.value = values[name];
|
||||
if (field.type === "select")
|
||||
e.querySelector(`option[value=${values[name]}]`).selected = true;
|
||||
}
|
||||
if (values && name in values)
|
||||
field.value = values[name];
|
||||
customs.insertAdjacentElement("beforeend", inputFieldMaker(type.value, field.type, name, field));
|
||||
if (field.type === "select") {
|
||||
M.FormSelect.init(e);
|
||||
e.style.display = "none";
|
||||
const sel = customs.querySelector("select");
|
||||
M.FormSelect.init(sel);
|
||||
sel.style.display = "none";
|
||||
}
|
||||
}
|
||||
M.updateTextFields();
|
||||
|
|
63
public/javascripts/tools/formMaker.js
Normal file
63
public/javascripts/tools/formMaker.js
Normal file
|
@ -0,0 +1,63 @@
|
|||
export function inputFieldMaker(Type, type, name, options) {
|
||||
const inputField = document.createElement("div");
|
||||
inputField.classList.add("input-field", "col", "s12");
|
||||
|
||||
let input;
|
||||
switch (type) {
|
||||
case "text":
|
||||
input = document.createElement("input");
|
||||
input.type = "text";
|
||||
break;
|
||||
case "select":
|
||||
input = document.createElement("select");
|
||||
for (const option of options.options) {
|
||||
const opt = document.createElement("option");
|
||||
opt.value = opt.innerText = option;
|
||||
input.insertAdjacentElement("beforeend", opt);
|
||||
}
|
||||
break;
|
||||
case "number":
|
||||
input = document.createElement("input");
|
||||
input.type = "number";
|
||||
break;
|
||||
case "password":
|
||||
input = document.createElement("input");
|
||||
input.type = "password";
|
||||
break;
|
||||
}
|
||||
input.id = Type + "-" + name;
|
||||
input.name = name;
|
||||
input.classList.add("validate");
|
||||
if (options.required)
|
||||
input.required = true;
|
||||
if (options.value) {
|
||||
input.value = options.value;
|
||||
if (type === "select")
|
||||
input.querySelectorAll(`option[value=${options.value}]`).forEach(o => o.selected = true);
|
||||
}
|
||||
|
||||
inputField.insertAdjacentElement("beforeend", input);
|
||||
|
||||
const label = document.createElement("label");
|
||||
label.for = input.id;
|
||||
label.innerText = name;
|
||||
inputField.insertAdjacentElement("beforeend", label);
|
||||
|
||||
if (options.helper) {
|
||||
const helper = document.createElement("span");
|
||||
helper.classList.add("helper-text");
|
||||
helper.innerText = options.helper;
|
||||
inputField.insertAdjacentElement("beforeend", helper);
|
||||
}
|
||||
|
||||
return inputField;
|
||||
}
|
||||
|
||||
export function formMaker() {
|
||||
const row = document.createElement("div");
|
||||
row.classList.add("row");
|
||||
const form = document.createElement("form");
|
||||
form.classList.add("col", "s12");
|
||||
row.insertAdjacentElement("beforeend", form);
|
||||
return [row, form];
|
||||
}
|
|
@ -1,8 +1,10 @@
|
|||
const express = require("express");
|
||||
const router = express.Router();
|
||||
|
||||
router.get("/", function(req, res) {
|
||||
res.render("settings/decks", { title: "Settings"});
|
||||
router.get("/", (req, res) => {
|
||||
res.render("settings/decks", { title: "Decks", path: "/settings"});
|
||||
}).get("/config", (req, res) => {
|
||||
res.render("settings/config", {title:"Configuration", path: "/settings/config"})
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
|
|
|
@ -6,6 +6,7 @@ module.exports = socket => {
|
|||
socket.on("setSlot", require("./setSlot")(socket));
|
||||
socket.on("addDeck", require("./addDeck")(socket));
|
||||
socket.on("deleteDeck", require("./deleteDeck")(socket));
|
||||
socket.on("setTypeConfig", require("./setTypeConfig")(socket));
|
||||
socket.on("trigger", require("./trigger")(socket));
|
||||
socket.on("uploadImage", require("./uploadImage")(socket));
|
||||
console.log("New connection !");
|
||||
|
|
21
sockets/setTypeConfig.js
Normal file
21
sockets/setTypeConfig.js
Normal file
|
@ -0,0 +1,21 @@
|
|||
const { types } = require("../types");
|
||||
|
||||
|
||||
module.exports = socket => {
|
||||
return data => {
|
||||
if (data.type && data.configuration) {
|
||||
try {
|
||||
const type = types[data.type], config = type.config();
|
||||
for (const [name, value] of Object.entries(data.configuration))
|
||||
config[name] = value;
|
||||
type.saveConfig(config);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
socket.emit("setTypeConfig", {error: err.code});
|
||||
return;
|
||||
}
|
||||
}
|
||||
socket.emit("setTypeConfig", data);
|
||||
socket.broadcast.emit("setTypeConfig", data);
|
||||
}
|
||||
};
|
|
@ -21,27 +21,33 @@ class Base {
|
|||
if (!(position[0] in db.decks[name].rows))
|
||||
db.decks[name].rows[position[0]] = {};
|
||||
db.decks[name].rows[position[0]][position[1]] = this.toJSON();
|
||||
Base.#write()
|
||||
Base.write()
|
||||
}
|
||||
|
||||
static saveConfig(type, configuration) {
|
||||
db.types[type] = configuration;
|
||||
Base.write();
|
||||
}
|
||||
|
||||
remove(name, position) {
|
||||
if (position[0] in db.decks[name].rows && position[1] in db.decks[name].rows[position[0]]) {
|
||||
delete db.decks[name].rows[position[0]][position[1]];
|
||||
Base.#write();
|
||||
Base.write();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static #write() {
|
||||
static write() {
|
||||
fs.writeFileSync("./db.json", JSON.stringify(db));
|
||||
}
|
||||
|
||||
static staticToJSON(name, type, fields) {
|
||||
static staticToJSON(name, type, fields, config) {
|
||||
return {
|
||||
"name": name,
|
||||
"type": type,
|
||||
"fields": fields
|
||||
"fields": fields,
|
||||
"configuration": config
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,9 +13,10 @@ class Deck extends Base {
|
|||
static fields() {
|
||||
return {
|
||||
deck: {
|
||||
"type": "select",
|
||||
"options": Object.keys(db.decks),
|
||||
"name": "Deck"
|
||||
type: "select",
|
||||
options: Object.keys(db.decks),
|
||||
name: "Deck",
|
||||
required: true,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -7,7 +7,8 @@ class ExecCommand extends Base {
|
|||
static fields = {
|
||||
cmd: {
|
||||
type: "text",
|
||||
name: "Command"
|
||||
name: "Command",
|
||||
required: true
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ class Keys extends Base {
|
|||
keys: {
|
||||
type: "text",
|
||||
name: "Keys",
|
||||
required: true,
|
||||
helper: "Key separated by a comma, if combo use +"
|
||||
}
|
||||
};
|
||||
|
|
155
types/OBS.js
Normal file
155
types/OBS.js
Normal file
|
@ -0,0 +1,155 @@
|
|||
const Base = require("./Base");
|
||||
const OBSWebSocket = require('obs-websocket-js');
|
||||
const db = require("../db.json");
|
||||
|
||||
class OBS extends Base {
|
||||
static name = "OBS";
|
||||
static type = "obs";
|
||||
static fields = {
|
||||
cmd: {
|
||||
type: "select",
|
||||
options: ["startStreaming", "stopStreaming", "toggleStreaming", "startRecording", "stopRecording", "toggleRecording"],
|
||||
name: "Action",
|
||||
required: true
|
||||
}
|
||||
};
|
||||
static obs = new OBSWebSocket();
|
||||
|
||||
constructor(text, image = null, options = null) {
|
||||
super(text, image, options);
|
||||
}
|
||||
|
||||
static config() {
|
||||
return {
|
||||
host: {
|
||||
type: "text",
|
||||
name: "Address",
|
||||
required: true,
|
||||
value: db.types[OBS.type].host,
|
||||
},
|
||||
port: {
|
||||
type: "number",
|
||||
name: "Port",
|
||||
required: true,
|
||||
value: db.types[OBS.type].port,
|
||||
},
|
||||
password: {
|
||||
type: "password",
|
||||
name: "password",
|
||||
value: db.types[OBS.type].password
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
static saveConfig(configuration) {
|
||||
super.saveConfig(OBS.type, configuration)
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
static staticToJSON() {
|
||||
return super.staticToJSON(OBS.name, OBS.type, OBS.fields, OBS.config());
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
toJSON() {
|
||||
return super.toJSON(OBS.type)
|
||||
}
|
||||
|
||||
static async connect() {
|
||||
const config = OBS.config();
|
||||
try {
|
||||
await OBS.obs.connect({
|
||||
address: config.host.value + ":" + config.port.value,
|
||||
password: config.password.value
|
||||
});
|
||||
return true;
|
||||
} catch (err) {
|
||||
console.error("Fail to connect !");
|
||||
console.error(err);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
async trigger(socket) {
|
||||
try {
|
||||
switch (this.options.cmd) {
|
||||
case "startStreaming":
|
||||
await OBS.obs.send("StartStreaming");
|
||||
break;
|
||||
case "stopStreaming":
|
||||
await OBS.obs.send("StopStreaming");
|
||||
break;
|
||||
case "toggleStreaming":
|
||||
try {
|
||||
await OBS.obs.send("StartStreaming");
|
||||
} catch (err) {
|
||||
if (err.error === "streaming already active")
|
||||
await OBS.obs.send("StopStreaming");
|
||||
else
|
||||
throw err;
|
||||
}
|
||||
break;
|
||||
case "startRecording":
|
||||
await OBS.obs.send("StartRecording");
|
||||
break;
|
||||
case "stopRecording":
|
||||
await OBS.obs.send("StopRecording");
|
||||
break;
|
||||
case "toggleRecording":
|
||||
try {
|
||||
await OBS.obs.send("StartRecording");
|
||||
} catch (err) {
|
||||
if (err.error === "recording already active")
|
||||
await OBS.obs.send("StopRecording");
|
||||
else
|
||||
throw err;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} catch (err) {
|
||||
switch (err.error) {
|
||||
case "There is no Socket connection available.":
|
||||
if (!await OBS.connect())
|
||||
socket.emit("trigger", {error: "failToConnectOBS"});
|
||||
else
|
||||
this.trigger(socket);
|
||||
break;
|
||||
case "streaming already active":
|
||||
console.error("Streaming already active");
|
||||
break;
|
||||
case "streaming not active":
|
||||
console.error("Streaming not active");
|
||||
break;
|
||||
case "recording already active":
|
||||
console.error("Recording already active");
|
||||
break;
|
||||
case "recording not active":
|
||||
console.error("Recording not active");
|
||||
break;
|
||||
default:
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!(OBS.type in db.types)) {
|
||||
db.types[OBS.type] = {};
|
||||
OBS.write();
|
||||
}
|
||||
|
||||
OBS.obs.on("error", err => {
|
||||
console.error("socket error:", err);
|
||||
});
|
||||
|
||||
module.exports = OBS;
|
|
@ -3,7 +3,8 @@ const db = require("../db.json");
|
|||
const types = {
|
||||
"execCommand": require("./ExecCommand"),
|
||||
"deck": require("./Deck"),
|
||||
"keys": require("./Keys")
|
||||
"keys": require("./Keys"),
|
||||
"obs": require("./OBS")
|
||||
};
|
||||
|
||||
module.exports.types = types;
|
||||
|
|
7
views/settings/config.pug
Normal file
7
views/settings/config.pug
Normal file
|
@ -0,0 +1,7 @@
|
|||
extends ./settings
|
||||
|
||||
block settings
|
||||
.container
|
||||
ul.collapsible
|
||||
|
||||
script(src="/javascripts/settings/config.js" type="module")
|
|
@ -1,9 +1,10 @@
|
|||
extends ./settings
|
||||
|
||||
block settings
|
||||
.input-field
|
||||
select#deck-select
|
||||
label Deck
|
||||
.container
|
||||
.input-field
|
||||
select#deck-select
|
||||
label Deck
|
||||
|
||||
.container#deck
|
||||
|
||||
|
@ -70,4 +71,4 @@ block settings
|
|||
button(data-target="modalAdd")#clearAdd.modal-close.waves-effect.waves-grey.btn-flat Cancel
|
||||
a#add.waves-effect.waves-green.btn-flat Save
|
||||
|
||||
script(src="/javascripts/settings/decks.js")
|
||||
script(src="/javascripts/settings/decks.js" type="module")
|
||||
|
|
|
@ -5,6 +5,8 @@ block content
|
|||
.nav-wrapper
|
||||
a.brand-logo.right(href="/") OpenDeck
|
||||
ul#nav-mobile.left.hide-on-med-and-down
|
||||
li
|
||||
li(class=path==="/settings"? "active": "")
|
||||
a(href="/settings") Decks
|
||||
li(class=path==="/settings/config"? "active": "")
|
||||
a(href="/settings/config") Configuration
|
||||
block settings
|
||||
|
|
Loading…
Reference in a new issue