fix: WS protocol — send positional args from React, add OutputRoutingPanel, add deleteScene handler
This commit is contained in:
+10
-1
@@ -1407,7 +1407,16 @@ public:
|
||||
std::string result = this->mixerApi.listScenes();
|
||||
this->JsonReply(replyTo, "mixerGetScenes", result.c_str());
|
||||
}
|
||||
REGISTER_MESSAGE_HANDLER(mixerGetScenes)
|
||||
REGISTER_MESSAGE_HANDLER(mixerGetScenes)
|
||||
|
||||
void handle_mixerDeleteScene(int replyTo, json_reader *pReader)
|
||||
{
|
||||
int64_t sceneId;
|
||||
pReader->read(&sceneId);
|
||||
bool ok = this->mixerApi.deleteScene(std::to_string(sceneId));
|
||||
this->Reply(replyTo, "mixerDeleteScene", ok);
|
||||
}
|
||||
REGISTER_MESSAGE_HANDLER(mixerDeleteScene)
|
||||
|
||||
/************************************************************************/
|
||||
/* Mixer Output Routing Messages */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Generated
+2
-2
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"name": "pipedal",
|
||||
"name": "op-pedal",
|
||||
"version": "0.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "pipedal",
|
||||
"name": "op-pedal",
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"@emotion/react": "^11.14.0",
|
||||
|
||||
@@ -113,7 +113,7 @@ const MixerPage: React.FC<MixerPageProps> = ({ onClose }) => {
|
||||
const handleLearnTarget = useCallback(
|
||||
(targetType: string, targetId: number) => {
|
||||
if (learnModeActive) {
|
||||
ws.send("mixerSetMidiLearnTarget", { targetType, targetId }).catch(() => {});
|
||||
ws.send("mixerSetMidiLearnTarget", [targetType, targetId]).catch(() => {});
|
||||
}
|
||||
},
|
||||
[ws, learnModeActive],
|
||||
@@ -123,42 +123,42 @@ const MixerPage: React.FC<MixerPageProps> = ({ onClose }) => {
|
||||
|
||||
const handleChannelVolume = useCallback(
|
||||
(channelIndex: number, volume: number) => {
|
||||
ws.send("mixerSetChannelVolume", { channelIndex, volume }).catch(() => {});
|
||||
ws.send("mixerSetChannelVolume", [channelIndex, volume]).catch(() => {});
|
||||
},
|
||||
[ws]
|
||||
);
|
||||
|
||||
const handleChannelPan = useCallback(
|
||||
(channelIndex: number, pan: number) => {
|
||||
ws.send("mixerSetChannelPan", { channelIndex, pan }).catch(() => {});
|
||||
ws.send("mixerSetChannelPan", [channelIndex, pan]).catch(() => {});
|
||||
},
|
||||
[ws]
|
||||
);
|
||||
|
||||
const handleChannelMute = useCallback(
|
||||
(channelIndex: number, mute: boolean) => {
|
||||
ws.send("mixerSetChannelMute", { channelIndex, mute }).catch(() => {});
|
||||
ws.send("mixerSetChannelMute", [channelIndex, mute]).catch(() => {});
|
||||
},
|
||||
[ws]
|
||||
);
|
||||
|
||||
const handleChannelSolo = useCallback(
|
||||
(channelIndex: number, solo: boolean) => {
|
||||
ws.send("mixerSetChannelSolo", { channelIndex, solo }).catch(() => {});
|
||||
ws.send("mixerSetChannelSolo", [channelIndex, solo]).catch(() => {});
|
||||
},
|
||||
[ws]
|
||||
);
|
||||
|
||||
const handleBusVolume = useCallback(
|
||||
(busId: number, volume: number) => {
|
||||
ws.send("mixerSetBusVolume", { busId, volume }).catch(() => {});
|
||||
ws.send("mixerSetBusVolume", [busId, volume]).catch(() => {});
|
||||
},
|
||||
[ws]
|
||||
);
|
||||
|
||||
const handleBusMute = useCallback(
|
||||
(busId: number, mute: boolean) => {
|
||||
ws.send("mixerSetBusMute", { busId, mute }).catch(() => {});
|
||||
ws.send("mixerSetBusMute", [busId, mute]).catch(() => {});
|
||||
},
|
||||
[ws]
|
||||
);
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
// OutputRoutingPanel - configure which hardware output channels each bus routes to
|
||||
import React from "react";
|
||||
import type { MixerBusState, MixerOutputRouteState } from "./useMixerWS";
|
||||
|
||||
interface Props {
|
||||
buses: MixerBusState[];
|
||||
routes: MixerOutputRouteState[];
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
export default function OutputRoutingPanel({ buses, routes, onClose }: Props) {
|
||||
return (
|
||||
<div style={{
|
||||
position: "fixed", top: 0, left: 0, right: 0, bottom: 0,
|
||||
background: "rgba(0,0,0,0.7)", display: "flex",
|
||||
alignItems: "center", justifyContent: "center", zIndex: 1000
|
||||
}}>
|
||||
<div style={{
|
||||
background: "#1a1a2e", borderRadius: 12, padding: 24,
|
||||
minWidth: 480, maxHeight: "80vh", overflow: "auto",
|
||||
color: "#e0e0e0", fontFamily: "system-ui, sans-serif"
|
||||
}}>
|
||||
<h2 style={{ margin: "0 0 16px", color: "#a78bfa" }}>Output Routing</h2>
|
||||
{routes.length === 0 && (
|
||||
<p style={{ color: "#888", fontStyle: "italic" }}>No output routes configured.</p>
|
||||
)}
|
||||
{routes.map((route, idx) => (
|
||||
<div key={idx} style={{
|
||||
display: "flex", gap: 12, alignItems: "center",
|
||||
padding: "8px 0", borderBottom: "1px solid #333"
|
||||
}}>
|
||||
<span style={{ minWidth: 80, fontWeight: 600 }}>
|
||||
{buses.find(b => b.id === route.sourceBusId)?.name ?? ("Bus " + String(route.sourceBusId))}
|
||||
</span>
|
||||
<span style={{ color: "#888" }}>CH {route.sourceStartChannel}</span>
|
||||
<span style={{ color: "#555" }}>{"->"}</span>
|
||||
<span style={{ color: "#888" }}>Out {route.targetStartChannel}</span>
|
||||
<span style={{ color: "#555", marginLeft: 8 }}>({route.channels} ch)</span>
|
||||
</div>
|
||||
))}
|
||||
<div style={{ marginTop: 20, display: "flex", gap: 8, justifyContent: "flex-end" }}>
|
||||
<button onClick={onClose} style={{
|
||||
padding: "8px 20px", border: "1px solid #555",
|
||||
borderRadius: 6, background: "transparent", color: "#ccc",
|
||||
cursor: "pointer"
|
||||
}}>Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -39,7 +39,15 @@ export interface MixerRouteState {
|
||||
sourceType: string; // "channel" | "bus"
|
||||
}
|
||||
|
||||
export interface MixerOutputRouteState {
|
||||
sourceBusId: number;
|
||||
sourceStartChannel: number;
|
||||
targetStartChannel: number;
|
||||
channels: number;
|
||||
}
|
||||
|
||||
export interface MixerState {
|
||||
outputRoutes?: MixerOutputRouteState[];
|
||||
channels: MixerChannelState[];
|
||||
buses: MixerBusState[];
|
||||
routes: MixerRouteState[];
|
||||
@@ -237,7 +245,7 @@ export function useMixerWS(wsUrl: string = DEFAULT_WS_URL): MixerWsHandle {
|
||||
|
||||
// Build message in PiPedalSocket format: [header, body?]
|
||||
const header: Record<string, unknown> = { message: command, replyTo };
|
||||
const msg = params !== undefined ? [header, params] : [header];
|
||||
const msg = params !== undefined ? [header, ...(Array.isArray(params) ? params : [params])] : [header];
|
||||
|
||||
// Register the reply handler before sending (race-safe).
|
||||
replyMapRef.current.set(replyTo, (value: unknown) => {
|
||||
|
||||
Reference in New Issue
Block a user