Intial somewhat working version
This commit is contained in:
92
web/app.js
Normal file
92
web/app.js
Normal file
@@ -0,0 +1,92 @@
|
||||
const state = {
|
||||
shaders: []
|
||||
};
|
||||
|
||||
const el = (id) => document.getElementById(id);
|
||||
|
||||
async function api(path, options = {}) {
|
||||
const response = await fetch(path, {
|
||||
headers: { "content-type": "application/json" },
|
||||
...options
|
||||
});
|
||||
if (!response.ok) {
|
||||
const text = await response.text();
|
||||
throw new Error(text || response.statusText);
|
||||
}
|
||||
return response.json();
|
||||
}
|
||||
|
||||
function renderStatus(status) {
|
||||
el("device").textContent = status.deviceName || "No DeckLink device selected";
|
||||
el("running").textContent = status.running ? "Running" : "Stopped";
|
||||
el("mode").textContent = status.mode || "No signal";
|
||||
el("outputFormat").textContent = status.outputFormat || "Unavailable";
|
||||
el("frames").textContent = `${status.framesCaptured ?? 0} / ${status.framesOutput ?? 0}`;
|
||||
el("frameRate").textContent = Number(status.frameRate || 0).toFixed(2);
|
||||
el("dropped").textContent = status.framesDropped ?? 0;
|
||||
el("error").textContent = status.error || "";
|
||||
}
|
||||
|
||||
function renderShaders(payload) {
|
||||
state.shaders = payload.shaders || [];
|
||||
const host = el("shaders");
|
||||
host.innerHTML = "";
|
||||
for (const shader of state.shaders) {
|
||||
const card = document.createElement("div");
|
||||
card.className = "shader";
|
||||
const amount = shader.parameters.find((p) => p.id === "amount");
|
||||
card.innerHTML = `
|
||||
<header>
|
||||
<strong>${shader.name}</strong>
|
||||
<span>${shader.type}</span>
|
||||
</header>
|
||||
<label>
|
||||
<span>${amount.label}</span>
|
||||
<input type="range" min="${amount.min}" max="${amount.max}" step="0.01" value="${amount.value}">
|
||||
<output>${Number(amount.value).toFixed(2)}</output>
|
||||
</label>
|
||||
`;
|
||||
const input = card.querySelector("input");
|
||||
const output = card.querySelector("output");
|
||||
input.addEventListener("input", async () => {
|
||||
output.textContent = Number(input.value).toFixed(2);
|
||||
await api(`/api/shaders/${shader.id}/parameters`, {
|
||||
method: "PATCH",
|
||||
body: JSON.stringify({ amount: Number(input.value) })
|
||||
});
|
||||
});
|
||||
host.appendChild(card);
|
||||
}
|
||||
}
|
||||
|
||||
async function refresh() {
|
||||
renderStatus(await api("/api/status"));
|
||||
renderShaders(await api("/api/shaders"));
|
||||
}
|
||||
|
||||
function connectWs() {
|
||||
const ws = new WebSocket(`ws://${location.host}/ws`);
|
||||
ws.addEventListener("message", (event) => {
|
||||
const message = JSON.parse(event.data);
|
||||
if (message.type === "state") {
|
||||
renderStatus(message.status);
|
||||
renderShaders(message.shaders);
|
||||
}
|
||||
});
|
||||
ws.addEventListener("close", () => setTimeout(connectWs, 1000));
|
||||
}
|
||||
|
||||
el("start").addEventListener("click", async () => {
|
||||
try {
|
||||
renderStatus(await api("/api/pipeline/start", { method: "POST" }));
|
||||
} catch (error) {
|
||||
el("error").textContent = error.message;
|
||||
}
|
||||
});
|
||||
|
||||
el("stop").addEventListener("click", async () => {
|
||||
renderStatus(await api("/api/pipeline/stop", { method: "POST" }));
|
||||
});
|
||||
|
||||
refresh();
|
||||
connectWs();
|
||||
Reference in New Issue
Block a user