+
+
+
+
+
setConfig((current) => writePath(current, "input.device", event.target.value))}
/>
-
-
);
}
diff --git a/ui/src/components/StatusPanels.jsx b/ui/src/components/StatusPanels.jsx
index 30e6b7c..546eb2a 100644
--- a/ui/src/components/StatusPanels.jsx
+++ b/ui/src/components/StatusPanels.jsx
@@ -1,11 +1,16 @@
-import { KvList } from "./KvList";
-
function formatNumber(value, digits = 3) {
return Number(value ?? 0).toFixed(digits);
}
+function formatBackend(backend) {
+ if (backend === "ndi") return "NDI";
+ if (backend === "decklink") return "DeckLink";
+ if (backend === "none") return "None";
+ return backend || "None";
+}
+
function formatEndpoint(endpoint) {
- const backend = endpoint?.backend || "none";
+ const backend = formatBackend(endpoint?.backend);
const device = endpoint?.device ? ` ${endpoint.device}` : "";
return `${backend}${device}`;
}
@@ -16,9 +21,67 @@ function formatVideoMode(endpoint) {
return `${resolution}${frameRate}`;
}
+function compactOutputStatus(videoOutput) {
+ const message = videoOutput?.statusMessage || "";
+ if (!message) return videoOutput?.enabled ? "Running" : "Disabled";
+ if (message.toLowerCase().includes("scheduled output running")) return "Running";
+ if (message.toLowerCase().includes("disabled")) return "Disabled";
+ return message;
+}
+
+function StatusRows({ rows }) {
+ return (
+
+ {rows.map((row) => (
+
+
- {row.label}
+ -
+ {row.value}
+ {row.meta && {row.meta}}
+
+
+ ))}
+
+ );
+}
+
export function StatusPanels({ app, performance, runtime, video, videoOutput }) {
const budgetUsedPercent = Math.max(0, Math.min(100, Number(performance.budgetUsedPercent) || 0));
const outputEnabled = Boolean(videoOutput?.enabled);
+ const runtimeRows = [
+ {
+ label: "Render",
+ value: `${formatNumber(performance.renderMs, 2)} ms`,
+ meta: `${formatNumber(performance.budgetUsedPercent, 1)}% of ${formatNumber(performance.frameBudgetMs, 2)} ms`,
+ },
+ {
+ label: "Layers",
+ value: `${runtime.layerCount || 0}`,
+ meta: `Temporal cap ${app.maxTemporalHistoryFrames ?? 0}`,
+ },
+ {
+ label: "Control",
+ value: `127.0.0.1:${app.serverPort}`,
+ meta: `Auto reload ${app.autoReload ? "on" : "off"}`,
+ },
+ ];
+ const videoRows = [
+ {
+ label: "Input",
+ value: formatEndpoint(app.input),
+ meta: formatVideoMode(app.input),
+ },
+ {
+ label: "Output",
+ value: formatEndpoint(app.output),
+ meta: `${formatVideoMode(app.output)} / ${video.width || 0} x ${video.height || 0}`,
+ },
+ {
+ label: "Schedule",
+ value: `${videoOutput?.scheduleFailures ?? 0} failures`,
+ meta: compactOutputStatus(videoOutput),
+ },
+ ];
return (
<>
@@ -35,44 +98,20 @@ export function StatusPanels({ app, performance, runtime, video, videoOutput })
-