diff --git a/docker-compose.yml b/docker-compose.yml index 124e4e0..71a38e6 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -11,4 +11,11 @@ services: context: . dockerfile: Dockerfile.server ports: - - "3001:3001" \ No newline at end of file + - "3001:3001" + env_file: + - .env + environment: + - X32_IP=${X32_IP} + - X32_PORT=${X32_PORT} + - CONFIG_PATH=${CONFIG_PATH} + - POLLING_INTERVAL=${POLLING_INTERVAL} \ No newline at end of file diff --git a/src/OSCWebServer/server.js b/src/OSCWebServer/server.js index f99ceef..824d822 100644 --- a/src/OSCWebServer/server.js +++ b/src/OSCWebServer/server.js @@ -22,6 +22,9 @@ console.log(`Connecting to X32 at ${x32IP}:${x32Port}`) udpPort.open(); +// increase max listeners +udpPort.setMaxListeners(50); + udpPort.on("ready", () => { console.log("OSC connection is ready!"); }); @@ -70,6 +73,7 @@ wss.on("connection", (ws) => { if (action === "sendValue" && path && value !== undefined) { // Send OSC command + console.log(`Sending OSC message: ${path} ${value}`); udpPort.send({address: path, args: [{type: "f", value}]}); ws.send( JSON.stringify({ diff --git a/src/app/components/Fader.tsx b/src/app/components/Fader.tsx index 0ccdeae..ffaf090 100644 --- a/src/app/components/Fader.tsx +++ b/src/app/components/Fader.tsx @@ -51,7 +51,7 @@ const Fader: React.FC = ({id, path, pollingInterval}) => { id={`${id}-${path}-fader`} min={0} max={1} - step={0.01} + step={0.001} value={faderValue ? [faderValue,] : [0,]} onValueChange={(newValue) => handleFaderChange(path, newValue[0])} style={{ diff --git a/src/app/components/MainMix.tsx b/src/app/components/MainMix.tsx index 4dade88..777ea94 100644 --- a/src/app/components/MainMix.tsx +++ b/src/app/components/MainMix.tsx @@ -30,7 +30,7 @@ const MainMix = () => { id={input.id} name={input.name} basePath={`/ch/${input.channels[0].toString().padStart(2, "0")}/mix`} - appConfig={appConfig} faderControlSuffix={undefined} muteControlSuffix={undefined} /> + appConfig={appConfig} faderControlSuffix={undefined} muteControlSuffix={undefined}/> )) } diff --git a/src/app/lib/x32CommunicationManager.ts b/src/app/lib/x32CommunicationManager.ts index 6c43d84..adb53fd 100644 --- a/src/app/lib/x32CommunicationManager.ts +++ b/src/app/lib/x32CommunicationManager.ts @@ -4,7 +4,7 @@ dotenv.config(); // A global manager (no React hooks) let ws: WebSocket | null = null; -let isConnected = false; +export let isConnected = false; // Your choice: store responses in memory, or just call callbacks let messageCallbacks: Array<(msg: string) => void> = []; diff --git a/src/app/page.tsx b/src/app/page.tsx index 21055ed..2bc7278 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -6,7 +6,7 @@ import BusControlTabs from "@/app/components/BusControlTabs"; import MainMix from "@/app/components/MainMix"; // initialize global websocket connection -import {initConnection} from "@/app/lib/x32CommunicationManager"; +import {initConnection, isConnected} from "@/app/lib/x32CommunicationManager"; const WEBSOCKET_PORT = 3001; @@ -14,6 +14,8 @@ const Page = () => { const [appConfig, setAppConfig] = useState(null); const [activeTab, setActiveTab] = useState("mainMix"); + const [webSocketConnected, setWebSocketConnected] = useState(false); + useEffect(() => { initConnection(`ws://${window.location.hostname}:${WEBSOCKET_PORT}`); fetchConfig().then(config => { @@ -21,6 +23,18 @@ const Page = () => { }); }, []); + // periodically check if the websocket connection is still alive + useEffect(() => { + const interval = setInterval(() => { + if (!isConnected) { + initConnection(`ws://${window.location.hostname}:${WEBSOCKET_PORT}`); + } + setWebSocketConnected(isConnected); + }, 1000); + return () => clearInterval(interval); + }, []); + + const tabComponents = useMemo(() => { return [ { @@ -45,6 +59,10 @@ const Page = () => { return

Error fetching config

; } + if (!webSocketConnected) { + return

WebSocket or Mixer not connected

; + } + return (