From 21a6379145253ce4bdc0be72a554fb7c07798e6e Mon Sep 17 00:00:00 2001 From: Tore Sinding Bekkedal Date: Tue, 11 Jul 2023 18:37:12 +0200 Subject: [PATCH] Cleanups and tweaks, fix AUX --- .env | 2 ++ package.json | 2 ++ src/App.tsx | 36 +++++++++++++++++++---- src/AtemControl.tsx | 63 ++++++++++++++++++---------------------- src/MonitoringStream.tsx | 5 +++- vite.config.ts | 4 +++ yarn.lock | 23 +++++++++++++++ 7 files changed, 95 insertions(+), 40 deletions(-) create mode 100644 .env diff --git a/.env b/.env new file mode 100644 index 0000000..f76faf1 --- /dev/null +++ b/.env @@ -0,0 +1,2 @@ +VITE_STREAM_URL=wss://beta.frikanalen.no/api/playout/stream +VITE_ATEM_URL=https://beta.frikanalen.no/api/playout/atem \ No newline at end of file diff --git a/package.json b/package.json index a0c634d..b8f5c7e 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,8 @@ "@hookform/error-message": "^2.0.1", "@hookform/resolvers": "^3.1.1", "@mui/material": "^5.13.7", + "@tanstack/react-query": "^4.29.19", + "classnames": "^2.3.2", "date-fns": "^2.30.0", "nope-validator": "^1.0.4", "react": "^18.2.0", diff --git a/src/App.tsx b/src/App.tsx index 7e339dd..dcdee9a 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -2,12 +2,38 @@ import "./App.css"; import { MonitoringStream } from "./MonitoringStream"; import { ATEM_INPUTS, ATEMButtons, ATEMControl } from "./AtemControl"; import { TextSlideEditorDialog } from "./TextSlideEditor"; -import { useState } from "react"; +import { useEffect, useState } from "react"; import { Playout } from "./Playout.js"; +import { set } from "date-fns"; + +const API_BASE = import.meta.env.VITE_ATEM_URL; +const useAtemAux = (auxIndex: number) => { + const [input, setInputState] = useState(-1); + + useEffect(() => { + fetch(API_BASE + "/aux/" + auxIndex) + .then((res) => res.json()) + .then(({ inputId }) => setInputState(inputId)); + }, []); + + const setInput = async (index: number) => { + await fetch(API_BASE + "/aux/" + auxIndex, { + method: "put", + credentials: "include", + headers: { "content-type": "application/json" }, + body: JSON.stringify({ inputId: index }), + }); + setInputState(index); + }; + + return { input, setInput }; +}; function App() { const [isOpen, setOpen] = useState(false); + const { input: aux1Input, setInput: setAux1Input } = useAtemAux(1); + return (
@@ -19,19 +45,19 @@ function App() { inputs={[ { name: "PGM", - index: 0, + index: 10010, }, { name: "PVW", - index: 1, + index: 10011, }, { name: "Multi", index: 2, }, ]} - activeIndex={undefined} - onChange={() => {}} + activeIndex={aux1Input} + onChange={async (idx) => await setAux1Input(idx)} />
diff --git a/src/AtemControl.tsx b/src/AtemControl.tsx index 6ced078..f317e0a 100644 --- a/src/AtemControl.tsx +++ b/src/AtemControl.tsx @@ -1,9 +1,8 @@ import { useEffect, useState } from "react"; +import cx from "classnames"; + +const API_BASE = import.meta.env.VITE_ATEM_URL; -const API_BASE = import.meta.env.DEV - ? "http://localhost:8089" - : "/api/playout/atem"; -/// /api/playout/atem export const ATEM_INPUTS: MixEffectsBusInput[] = [ { index: 2, name: "TX1" }, { index: 3, name: "TX2" }, @@ -21,34 +20,29 @@ export type ATEMControlsProps = { onChange: (index: number) => void; }; -export function ATEMButtons(props: ATEMControlsProps) { - const { inputs, activeIndex, onChange } = props; - - const containerStyle = "flex gap-1 lg:gap-4"; - - const baseStyle = - "block border-2 border-black lg:p-2 font-mono w-14 lg:w-20 font-bold"; - const activeStyle = "bg-[#ee6666]"; - const inactiveStyle = "text-gray-600 bg-gray-300"; - const buttonStyle = (buttonIndex: number) => - [baseStyle, buttonIndex === activeIndex ? activeStyle : inactiveStyle].join( - " ", - ); - - return ( -
- {inputs.map((input) => ( - - ))} -
- ); -} +export const ATEMButtons = ({ + inputs, + activeIndex, + onChange, +}: ATEMControlsProps) => ( +
+ {inputs.map(({ index, name }) => ( + + ))} +
+); export const ATEMControl = () => { const [programInput, setProgramInput] = useState(-1); @@ -57,10 +51,10 @@ export const ATEMControl = () => { useEffect(() => { fetch(API_BASE + "/program") .then((res) => res.json()) - .then(({ inputIndex }) => setProgramInput(inputIndex)); + .then(({ programInput }) => setProgramInput(programInput)); fetch(API_BASE + "/preview") .then((res) => res.json()) - .then(({ inputIndex }) => setPreviewInput(inputIndex)); + .then(({ previewInput }) => setPreviewInput(previewInput)); }, []); const setProgram = async (index: number) => { @@ -82,6 +76,7 @@ export const ATEMControl = () => { }); setPreviewInput(index); }; + console.log({ programInput, previewInput }); return (
diff --git a/src/MonitoringStream.tsx b/src/MonitoringStream.tsx index 7e49b77..1fd82c6 100644 --- a/src/MonitoringStream.tsx +++ b/src/MonitoringStream.tsx @@ -7,6 +7,9 @@ export const MonitoringStream = () => { >(undefined); const containerRef = useRef(null); + if (!import.meta.env.VITE_STREAM_URL?.length) + return
Error: VITE_STREAM_URL not set
; + useEffect(() => { if (containerRef.current == null) return; @@ -14,7 +17,7 @@ export const MonitoringStream = () => { setVideoElement( new JSMpeg.VideoElement( containerRef.current, - "wss://monitoring.frikanalen.no/", + import.meta.env.VITE_STREAM_URL || "", { videoBufferSize: 512 * 1024 * 20, audioBufferSize: 128 * 1024 * 20, diff --git a/vite.config.ts b/vite.config.ts index 9d5eaa4..79cb285 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -5,4 +5,8 @@ import react from "@vitejs/plugin-react"; export default defineConfig({ plugins: [react()], base: "/playout/", + server: { + port: 3000, + host: "0.0.0.0", + }, }); diff --git a/yarn.lock b/yarn.lock index 5be3a40..872f3ce 100644 --- a/yarn.lock +++ b/yarn.lock @@ -938,6 +938,19 @@ dependencies: "@sinonjs/commons" "^3.0.0" +"@tanstack/query-core@4.29.19": + version "4.29.19" + resolved "https://registry.yarnpkg.com/@tanstack/query-core/-/query-core-4.29.19.tgz#49ccbd0606633d1e55baf3b91ab7cc7aef411b1d" + integrity sha512-uPe1DukeIpIHpQi6UzIgBcXsjjsDaLnc7hF+zLBKnaUlh7jFE/A+P8t4cU4VzKPMFB/C970n/9SxtpO5hmIRgw== + +"@tanstack/react-query@^4.29.19": + version "4.29.19" + resolved "https://registry.yarnpkg.com/@tanstack/react-query/-/react-query-4.29.19.tgz#6ba187f2d0ea36ae83ff1f67068f53c88ce7b228" + integrity sha512-XiTIOHHQ5Cw1WUlHaD4fmVUMhoWjuNJlAeJGq7eM4BraI5z7y8WkZO+NR8PSuRnQGblpuVdjClQbDFtwxTtTUw== + dependencies: + "@tanstack/query-core" "4.29.19" + use-sync-external-store "^1.2.0" + "@tootallnate/once@2": version "2.0.0" resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf" @@ -1404,6 +1417,11 @@ cjs-module-lexer@^1.0.0: resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz#6c370ab19f8a3394e318fe682686ec0ac684d107" integrity sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ== +classnames@^2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.2.tgz#351d813bf0137fcc6a76a16b88208d2560a0d924" + integrity sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw== + cliui@^8.0.1: version "8.0.1" resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" @@ -3385,6 +3403,11 @@ url-parse@^1.5.3: querystringify "^2.1.1" requires-port "^1.0.0" +use-sync-external-store@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a" + integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA== + util-deprecate@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"