feat: sidebar allows recall, rename and display custom names

This commit is contained in:
2026-07-28 12:39:13 +02:00
parent da322c9df1
commit 54fda168cc
9 changed files with 632 additions and 253 deletions

View File

@ -1,8 +1,6 @@
import { invoke } from '@tauri-apps/api/core';
import { useState } from 'react';
import './App.css';
import { DSP, DSPStatus, AppPage } from './types/types';
import { DSP, AppPage } from './types/types';
import TopBar from './components/Topbar/Topbar';
import DSPPage from './pages/DspPage/DspPage';
import AddDSPForm from './pages/AddDspPage/AddDspPage';
@ -10,8 +8,7 @@ import { useNotifications } from './hooks/useNotifications';
import Notifications from './components/Notifications/Notifications';
import CreditsPage from './pages/CreditsPage/CreditsPage';
import HomePage from './pages/HomePage/HomePage';
import { getDSP408State, connectDSP408, disconnectDSP408 } from './api/dsp408';
import { useDSPPolling } from './hooks/useDSPPolling';
import { useDSP408 } from './hooks/useDSP408';
function App() {
const [dsps, setDsps] = useState<DSP[]>([]);
@ -21,92 +18,14 @@ function App() {
const activeDsp = dsps.find((d) => d.id === selected) ?? null;
const connectedDspCount = dsps.filter((dsp) => dsp.status === 'connected').length;
useDSPPolling(dsps, selected, setDsps);
function setStatus(id: number, status: DSPStatus) {
setDsps((prev) => prev.map((d) => (d.id === id ? { ...d, status } : d)));
}
async function addDSP(dsp: Omit<DSP, 'id' | 'status' | 'state' | 'meters'>) {
try {
const id = await invoke<number>('create_dsp408', {
ip: dsp.ip,
port: dsp.port,
deviceId: Number(dsp.deviceId),
});
const newDsp: DSP = {
id,
...dsp,
status: 'disconnected',
state: null,
meters: null,
};
setDsps((prev) => [...prev, newDsp]);
setSelected(id);
setPage('view-dsp');
notify('Added successfully', 'success', dsp.name);
} catch (err) {
notify(`Connection failed: ${String(err)}`, 'error', dsp.name);
}
}
async function removeDSP(dsp: DSP) {
try {
let id = dsp.id;
await invoke('remove_dsp408', {
id,
});
setDsps((prev) => {
const next = prev.filter((d) => d.id !== id);
if (selected === id) {
setSelected(next.length ? next[0].id : null);
}
return next;
});
notify('Removed successfully', 'success', dsp?.name);
} catch (err) {
notify(`Remove failed: ${String(err)}`, 'error', dsp?.name);
}
}
async function connectDSP(dsp: DSP) {
setStatus(dsp.id, 'connecting');
try {
await connectDSP408(dsp.id);
setStatus(dsp.id, 'connected');
const state = await getDSP408State(dsp.id);
setDsps((prev) => prev.map((d) => (d.id === dsp.id ? { ...d, state } : d)));
notify('Connected', 'success', dsp.name);
} catch (err) {
notify(`Connection failed: ${String(err)}`, 'error', dsp.name);
setStatus(dsp.id, 'disconnected');
}
}
async function disconnectDSP(dsp: DSP) {
try {
await disconnectDSP408(dsp.id);
setStatus(dsp.id, 'disconnected');
notify('Disconnected', 'success', dsp.name);
} catch (err) {
notify(`Disconnect failed: ${String(err)}`, 'error', dsp.name);
}
}
const dsp408 = useDSP408(
dsps,
setDsps,
selected,
setSelected,
setPage,
notify
);
return (
<div className="app">
@ -128,7 +47,7 @@ function App() {
setPage('view-dsp');
}}
onRemove={removeDSP}
onRemove={dsp408.removeDSP}
onAddClick={() => {
setPage('add-dsp');
@ -139,13 +58,11 @@ function App() {
{page === 'credits' ? (
<CreditsPage />
) : page === 'add-dsp' ? (
<AddDSPForm onCancel={() => setPage('home')} onAdd={addDSP} />
<AddDSPForm onCancel={() => setPage('home')} onAdd={dsp408.addDSP} />
) : activeDsp ? (
<DSPPage
dsp={activeDsp}
onConnect={() => connectDSP(activeDsp)}
onDisconnect={() => disconnectDSP(activeDsp)}
notify={notify}
dsp408={dsp408.forDSP(activeDsp)}
/>
) : (
<HomePage

View File

@ -16,10 +16,16 @@ export const disconnectDSP408 = (id: number) => invoke('disconnect_dsp408', { id
export const getDSP408State = (id: number) => invoke<DSPState>('get_dsp_state', { id });
export const recallPreset = (id: number, presetIndex: number) =>
export const recallPresetDSP408 = (id: number, presetIndex: number) =>
invoke<boolean>('recall_preset', {
id,
presetIndex,
});
export const DSP408SetCurrentPresetName = (id: number, name: string) =>
invoke<boolean>('set_current_preset_name', {
id,
name,
});
export const getDSP408MeterLevels = (id: number) => invoke<Meters>('get_meter_levels', { id });

View File

@ -50,6 +50,7 @@ function AppCombobox({
onAppRename?: (name: string) => void;
}) {
const currentOption = appOptions.find((o) => o.id === selectedAppId) ?? appOptions[0];
const canRename = currentOption?.id !== 'f00';
const [open, setOpen] = useState(false);
const [editing, setEditing] = useState(false);
@ -91,8 +92,12 @@ function AppCombobox({
function startEditing(e: React.MouseEvent) {
e.stopPropagation();
if (!canRename) return;
setEditing(true);
setOpen(false);
requestAnimationFrame(() => {
inputRef.current?.focus();
inputRef.current?.select();
@ -100,17 +105,30 @@ function AppCombobox({
}
function commitRename() {
const trimmed = inputValue.trim();
if (!canRename) {
setInputValue(currentOption?.name ?? appName);
setEditing(false);
return;
}
const trimmed = inputValue.trim();
setEditing(false);
if (!trimmed) {
setInputValue(currentOption?.name ?? appName);
return;
}
const matched = appOptions.find((o) => o.name === trimmed);
if (matched) {
if (matched.id !== selectedAppId) onAppChange?.(matched.id);
if (matched.id !== selectedAppId) {
onAppChange?.(matched.id);
}
return;
}
if (trimmed !== currentOption?.name) {
onAppRename?.(trimmed);
}
@ -153,7 +171,8 @@ function AppCombobox({
ref={inputRef}
className="sidebar-app-input"
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
maxLength={14}
onChange={(e) => setInputValue(e.target.value.slice(0, 14))}
onBlur={commitRename}
onKeyDown={handleKeyDown}
aria-label="Rename app"

View File

@ -57,7 +57,7 @@ function ConnectionPanel({
<div className="connection-panel__spec">
<dt>Device ID</dt>
<dd className="connection-panel__mono" title={dsp.deviceId || undefined}>
<dd className="connection-panel__mono" title={String(dsp.deviceId) || undefined}>
{dsp.deviceId || '—'}
</dd>
</div>

553
src/hooks/useDSP408.ts Normal file
View File

@ -0,0 +1,553 @@
// hooks/useDSP408.ts
import { useEffect, useRef } from 'react';
import { invoke } from '@tauri-apps/api/core';
import { DSP, DSPStatus, AppPage } from '../types/types';
import {
createDSP408,
removeDSP408,
connectDSP408,
disconnectDSP408,
getDSP408State,
recallPresetDSP408,
DSP408SetCurrentPresetName,
getDSP408MeterLevels,
} from '../api/dsp408';
type NotifyFunction = (
message: string,
type: 'success' | 'error',
dspName?: string
) => void;
type SetDsps = React.Dispatch<React.SetStateAction<DSP[]>>;
// ============================================================
// Helpers
// ============================================================
function updateDSP(
setDsps: SetDsps,
dspId: number,
updater: (dsp: DSP) => DSP
) {
setDsps((prev) =>
prev.map((dsp) => (dsp.id === dspId ? updater(dsp) : dsp))
);
}
export type DSP408Device = {
connect: () => Promise<void>;
disconnect: () => Promise<void>;
recallPreset: (index: number) => Promise<boolean>;
setCurrentPresetName: (name: string) => Promise<boolean>;
};
// ============================================================
// Polling
// ============================================================
function useDSPPolling(
dsps: DSP[],
selected: number | null,
setDsps: React.Dispatch<React.SetStateAction<DSP[]>>
) {
const dspsRef = useRef(dsps);
const selectedRef = useRef(selected);
useEffect(() => {
dspsRef.current = dsps;
}, [dsps]);
useEffect(() => {
selectedRef.current = selected;
}, [selected]);
useEffect(() => {
let stopped = false;
let activeTimeout: ReturnType<typeof setTimeout> | undefined;
let inactiveTimeout: ReturnType<typeof setTimeout> | undefined;
const pollDSP = async (dsp: DSP) => {
// Don't poll paused DSPs
if (dsp.pollingPaused) {
return;
}
try {
const meters = await getDSP408MeterLevels(dsp.id);
if (stopped) return;
setDsps((prev) => prev.map((d) => (d.id === dsp.id ? { ...d, meters } : d)));
} catch (err) {
if (!stopped) {
console.error(`Meter polling failed for ${dsp.name}:`, err);
}
}
};
const activeLoop = async () => {
if (stopped) return;
const activeId = selectedRef.current;
if (activeId !== null) {
const dsp = dspsRef.current.find(
(d) => d.id === activeId && d.status === 'connected' && !d.pollingPaused
);
if (dsp) {
await pollDSP(dsp);
}
}
if (!stopped) {
activeTimeout = setTimeout(activeLoop, 500);
}
};
const inactiveLoop = async () => {
if (stopped) return;
const activeId = selectedRef.current;
const inactiveDsps = dspsRef.current.filter(
(dsp) => dsp.status === 'connected' && dsp.id !== activeId && !dsp.pollingPaused
);
await Promise.all(inactiveDsps.map((dsp) => pollDSP(dsp)));
if (!stopped) {
inactiveTimeout = setTimeout(inactiveLoop, 5000);
}
};
// Start polling
activeLoop();
inactiveLoop();
return () => {
stopped = true;
if (activeTimeout !== undefined) {
clearTimeout(activeTimeout);
}
if (inactiveTimeout !== undefined) {
clearTimeout(inactiveTimeout);
}
};
}, [setDsps]);
}
// ============================================================
// Main hook
// ============================================================
export function useDSP408(
dsps: DSP[],
setDsps: SetDsps,
selected: number | null,
setSelected: React.Dispatch<React.SetStateAction<number | null>>,
setPage: React.Dispatch<React.SetStateAction<AppPage>>,
notify: NotifyFunction
) {
// ----------------------------------------------------------
// Polling control
// ----------------------------------------------------------
const setPollingPaused = (id: number, paused: boolean) => {
updateDSP(setDsps, id, (dsp) => ({
...dsp,
pollingPaused: paused,
}));
};
// Polling is part of the hook.
useDSPPolling(dsps, selected, setDsps);
// ----------------------------------------------------------
// Generic operation wrapper
// ----------------------------------------------------------
async function withPollingPaused<T>(
dsp: DSP,
operation: () => Promise<T>
): Promise<T> {
setPollingPaused(dsp.id, true);
try {
return await operation();
} finally {
setPollingPaused(dsp.id, false);
}
}
// ==========================================================
// Connection
// ==========================================================
async function connectDSP(dsp: DSP) {
setPollingPaused(dsp.id, true);
updateDSP(setDsps, dsp.id, (d) => ({
...d,
status: 'connecting',
}));
try {
await connectDSP408(dsp.id);
const state = await getDSP408State(dsp.id);
updateDSP(setDsps, dsp.id, (d) => ({
...d,
status: 'connected',
state,
}));
notify('Connected', 'success', dsp.name);
} catch (err) {
updateDSP(setDsps, dsp.id, (d) => ({
...d,
status: 'disconnected',
}));
notify(
`Connection failed: ${String(err)}`,
'error',
dsp.name
);
} finally {
setPollingPaused(dsp.id, false);
}
}
async function disconnectDSP(dsp: DSP) {
setPollingPaused(dsp.id, true);
try {
await disconnectDSP408(dsp.id);
updateDSP(setDsps, dsp.id, (d) => ({
...d,
status: 'disconnected',
}));
notify('Disconnected', 'success', dsp.name);
} catch (err) {
// If disconnect failed, it is probably still connected.
setPollingPaused(dsp.id, false);
notify(
`Disconnect failed: ${String(err)}`,
'error',
dsp.name
);
}
}
// ==========================================================
// Add / Remove
// ==========================================================
async function addDSP(
dsp: Omit<
DSP,
'id' | 'status' | 'state' | 'meters' | 'pollingPaused'
>
) {
try {
const id = await createDSP408(
dsp.ip,
dsp.port,
dsp.deviceId
);
const newDsp: DSP = {
id,
...dsp,
status: 'disconnected',
state: null,
meters: null,
pollingPaused: true,
};
setDsps((prev) => [...prev, newDsp]);
setSelected(id);
setPage('view-dsp');
notify('Added successfully', 'success', dsp.name);
} catch (err) {
notify(
`Connection failed: ${String(err)}`,
'error',
dsp.name
);
}
}
async function removeDSP(dsp: DSP) {
setPollingPaused(dsp.id, true);
try {
await removeDSP408(dsp.id);
setDsps((prev) => {
const next = prev.filter(
(d) => d.id !== dsp.id
);
if (selected === dsp.id) {
setSelected(
next.length ? next[0].id : null
);
}
return next;
});
notify(
'Removed successfully',
'success',
dsp.name
);
} catch (err) {
setPollingPaused(dsp.id, false);
notify(
`Remove failed: ${String(err)}`,
'error',
dsp.name
);
}
}
// ==========================================================
// Presets
// ==========================================================
async function recallPreset(
dsp: DSP,
presetIndex: number
) {
return withPollingPaused(dsp, async () => {
try {
const success = await recallPresetDSP408(
dsp.id,
presetIndex
);
if (!success) {
notify(
'Failed to recall preset',
'error',
dsp.name
);
return false;
}
updateDSP(setDsps, dsp.id, (d) => {
if (!d.state) return d;
return {
...d,
state: {
...d.state,
presets: {
...d.state.presets,
current_index: presetIndex - 1,
},
},
};
});
notify(
`Preset ${presetIndex} recalled`,
'success',
dsp.name
);
return true;
} catch (err) {
notify(
`Preset recall failed: ${String(err)}`,
'error',
dsp.name
);
return false;
}
});
}
async function setCurrentPresetName(
dsp: DSP,
name: string
) {
return withPollingPaused(dsp, async () => {
try {
const paddedName = name
.slice(0, 14)
.padEnd(14, ' ');
const success =
await DSP408SetCurrentPresetName(
dsp.id,
paddedName
);
if (!success) {
notify(
'Failed to rename preset',
'error',
dsp.name
);
return false;
}
updateDSP(setDsps, dsp.id, (d) => {
if (!d.state) return d;
const presets = d.state.presets;
const index = presets.current_index;
return {
...d,
state: {
...d.state,
presets: {
...presets,
names: presets.names.map(
(presetName, i) =>
i === index
? paddedName
: presetName
),
modified: presets.modified.map(
(modified, i) =>
i === index
? true
: modified
),
},
},
};
});
notify(
'Preset renamed',
'success',
dsp.name
);
return true;
} catch (err) {
notify(
`Preset rename failed: ${String(err)}`,
'error',
dsp.name
);
return false;
}
});
}
// ==========================================================
// Gain
// ==========================================================
async function setGain(
dsp: DSP,
channel: number,
gain: number
) {
return withPollingPaused(dsp, async () => {
try {
const success = await invoke<boolean>(
'set_gain',
{
id: dsp.id,
channel,
gain,
}
);
if (!success) {
notify(
'Failed to set gain',
'error',
dsp.name
);
return false;
}
updateDSP(setDsps, dsp.id, (d) => {
if (!d.state) return d;
return {
...d,
state: {
...d.state,
// Update gain state here
},
};
});
notify(
'Gain updated',
'success',
dsp.name
);
return true;
} catch (err) {
notify(
`Gain update failed: ${String(err)}`,
'error',
dsp.name
);
return false;
}
});
}
// ==========================================================
// Return API
// ==========================================================
function forDSP(dsp: DSP): DSP408Device {
return {
connect: () => connectDSP(dsp),
disconnect: () => disconnectDSP(dsp),
recallPreset: (index: number) => recallPreset(dsp, index),
setCurrentPresetName: (name: string) =>
setCurrentPresetName(dsp, name),
// setGain: (channel, gain) =>
// setGain(dsp, channel, gain),
};
}
return {
forDSP,
addDSP,
removeDSP,
connectDSP,
disconnectDSP,
recallPreset,
setCurrentPresetName,
setGain,
};
}

View File

@ -1,82 +0,0 @@
import { useEffect, useRef } from 'react';
import { DSP } from '../types/types';
import { getDSP408MeterLevels } from '../api/dsp408';
export function useDSPPolling(
dsps: DSP[],
selected: number | null,
setDsps: React.Dispatch<React.SetStateAction<DSP[]>>
) {
const dspsRef = useRef(dsps);
const selectedRef = useRef(selected);
// Keep refs up to date without restarting the polling loops
useEffect(() => {
dspsRef.current = dsps;
}, [dsps]);
useEffect(() => {
selectedRef.current = selected;
}, [selected]);
useEffect(() => {
let stopped = false;
const pollDSP = async (dsp: DSP) => {
try {
const meters = await getDSP408MeterLevels(dsp.id);
if (stopped) return;
setDsps((prev) => prev.map((d) => (d.id === dsp.id ? { ...d, meters } : d)));
} catch (err) {
if (!stopped) {
console.error(`Meter polling failed for ${dsp.name}:`, err);
}
}
};
const activeLoop = async () => {
if (stopped) return;
const activeId = selectedRef.current;
if (activeId !== null) {
const dsp = dspsRef.current.find((d) => d.id === activeId && d.status === 'connected');
if (dsp) {
await pollDSP(dsp);
}
}
if (!stopped) {
setTimeout(activeLoop, 500);
}
};
const inactiveLoop = async () => {
if (stopped) return;
const activeId = selectedRef.current;
const inactiveDsps = dspsRef.current.filter(
(dsp) => dsp.status === 'connected' && dsp.id !== activeId
);
// Poll inactive connected DSPs
await Promise.all(inactiveDsps.map((dsp) => pollDSP(dsp)));
if (!stopped) {
setTimeout(inactiveLoop, 5000);
}
};
// Start both loops
activeLoop();
inactiveLoop();
return () => {
stopped = true;
};
}, [setDsps]);
}

View File

@ -10,18 +10,22 @@ function AddDSPForm({
onAdd,
}: {
onCancel: () => void;
onAdd: (d: Omit<DSP, 'status' | 'id' | 'state' | 'meters'>) => void;
onAdd: (d: Omit<DSP, 'status' | 'id' | 'state' | 'meters' | 'pollingPaused'>) => void;
}) {
const [form, setForm] = useState({
name: '',
type: DSP_TYPES[0].name,
ip: '192.168.1.100',
port: DSP_TYPES[0].defaultPort,
deviceId: '1',
deviceId: 1,
});
const canSubmit =
form.name.trim().length > 0 && form.ip.trim().length > 0 && form.deviceId.length > 0;
form.name.trim().length > 0 &&
form.ip.trim().length > 0 &&
Number.isInteger(form.deviceId) &&
form.deviceId >= 1 &&
form.deviceId <= 255;
function submit() {
if (!canSubmit) return;
@ -82,7 +86,7 @@ function AddDSPForm({
step={1}
placeholder="1"
value={form.deviceId}
onChange={(e) => setForm({ ...form, deviceId: e.target.value })}
onChange={(e) => setForm({ ...form, deviceId: Number(e.target.value) })}
/>
</div>
</div>

View File

@ -4,27 +4,25 @@ import Sidebar from '../../components/Sidebar/Sidebar';
import { InfoIcon, KnobGainIcon } from '../../assets/icons/AudioIcons';
import ConnectionPanel from '../../components/dsp408/ConnectionSection/ConnectionSection';
import GainSection from '../../components/dsp408/GainSection/GainSection';
import { NotificationType } from '../../types/types';
import { DSP408Device } from '../../hooks/useDSP408';
import './DspPage.css';
import GateSection from '../../components/dsp408/GateSection/GateSection';
import { invoke } from '@tauri-apps/api/core';
import LoadingOverlay from '../../components/LoadingOverlay/LoadingOverlay';
import { InputChannel, OutputChannel } from '../../types/dsp408State';
function DSPPage({
dsp,
onConnect,
onDisconnect,
notify,
dsp408,
}: {
dsp: DSP;
onConnect: () => void;
onDisconnect: () => void;
notify: (message: string, type?: NotificationType, dspName?: string) => void;
dsp408: DSP408Device;
}) {
const [activeSidebar, setActiveSidebar] = useState('overview');
const [sidebarExpanded, setSidebarExpanded] = useState(false);
const [selectedPreset, setSelectedPreset] = useState(dsp.state?.presets.current_index ?? 0);
const [presetLoading, setPresetLoading] = useState(false);
const inputStates = dsp.state?.current_config.input_states;
const outputStates = dsp.state?.current_config.output_states;
const sidebarItems = [
{
id: 'overview',
@ -68,62 +66,63 @@ function DSPPage({
},
{
id: 'ina',
label: 'In A',
label: `In A (${inputStates?.[InputChannel.InA]?.name})`,
icon: <KnobGainIcon />,
},
{
id: 'inb',
label: 'In B',
label: `In B (${inputStates?.[InputChannel.InB]?.name})`,
icon: <KnobGainIcon />,
},
{
id: 'inc',
label: 'In C',
label: `In C (${inputStates?.[InputChannel.InC]?.name})`,
icon: <KnobGainIcon />,
},
{
id: 'ind',
label: 'In D (TESTTEST)',
label: `In D (${inputStates?.[InputChannel.InD]?.name})`,
icon: <KnobGainIcon />,
},
{
id: 'out1',
label: 'Out 1',
label: `Out 1 (${outputStates?.[OutputChannel.Out1]?.name})`,
icon: <KnobGainIcon />,
},
{
id: 'out2',
label: 'Out 2',
label: `Out 2 (${outputStates?.[OutputChannel.Out2]?.name})`,
icon: <KnobGainIcon />,
},
{
id: 'out3',
label: 'Out 3',
label: `Out 3 (${outputStates?.[OutputChannel.Out3]?.name})`,
icon: <KnobGainIcon />,
},
{
id: 'out4',
label: 'Out 4',
label: `Out 4 (${outputStates?.[OutputChannel.Out4]?.name})`,
icon: <KnobGainIcon />,
},
{
id: 'out5',
label: 'Out 5',
label: `Out 5 (${outputStates?.[OutputChannel.Out5]?.name})`,
icon: <KnobGainIcon />,
},
{
id: 'out6',
label: 'Out 6',
label: `Out 6 (${outputStates?.[OutputChannel.Out6]?.name})`,
icon: <KnobGainIcon />,
},
{
id: 'out7',
label: 'Out 7',
label: `Out 7 (${outputStates?.[OutputChannel.Out7]?.name})`,
icon: <KnobGainIcon />,
},
{
id: 'out8',
label: 'Out 8',
label: `Out 8 (${outputStates?.[OutputChannel.Out8]?.name})`,
icon: <KnobGainIcon />,
},
{
@ -154,52 +153,14 @@ function DSPPage({
})),
];
const recallPreset = async (presetIndex: number) => {
try {
const success = await invoke<boolean>('recall_preset', {
id: dsp.id,
presetIndex,
});
if (success) {
notify(`Preset ${presetIndex} recalled`, 'success', dsp.name);
} else {
notify('Failed to recall preset', 'error', dsp.name);
}
return success;
} catch (err) {
notify(`Preset recall failed: ${String(err)}`, 'error', dsp.name);
return false;
}
};
const setCurrentPresetName = async (name: string) => {
try {
const success = await invoke<boolean>('set_current_preset_name', {
id: dsp.id,
name,
});
if (success) {
notify(`Preset renamed`, 'success', dsp.name);
} else {
notify('Failed to rename preset', 'error', dsp.name);
}
return success;
} catch (err) {
notify(`Preset rename failed: ${String(err)}`, 'error', dsp.name);
return false;
}
};
// const { recallPreset, setCurrentPresetName } = useDSPPresets(dsp, setDsps, notify);
const onAppChange = async (id: string) => {
const presetIndex = presets.findIndex((preset) => preset.id === id);
if (presetIndex === -1) return;
setPresetLoading(true);
const success = await recallPreset(presetIndex);
const success = await dsp408.recallPreset(presetIndex);
if (success) {
setSelectedPreset(presetIndex);
}
@ -209,13 +170,13 @@ function DSPPage({
const renderTab = () => {
switch (activeSidebar) {
case 'overview':
return <ConnectionPanel dsp={dsp} onConnect={onConnect} onDisconnect={onDisconnect} />;
return <ConnectionPanel dsp={dsp} onConnect={dsp408.connect} onDisconnect={dsp408.disconnect} />;
case 'gain':
return <GainSection dsp={dsp} notify={notify} />;
// case 'gain':
// return <GainSection dsp={dsp} notify={notify} />;
case 'gate':
return <GateSection dsp={dsp} notify={notify} />;
// case 'gate':
// return <GateSection dsp={dsp} notify={notify} />;
default:
return null;
@ -232,7 +193,7 @@ function DSPPage({
appOptions={presets}
selectedAppId={presets[selectedPreset]?.id}
onAppChange={onAppChange}
onAppRename={setCurrentPresetName}
onAppRename={dsp408.setCurrentPresetName}
expanded={sidebarExpanded}
onToggle={() => setSidebarExpanded((v) => !v)}
/>

View File

@ -8,10 +8,11 @@ export type DSP = {
type: string;
ip: string;
port: number;
deviceId: string;
deviceId: number;
status: DSPStatus;
state: DSPState | null;
meters: Meters | null;
pollingPaused: boolean;
};
export const DSP_TYPES = [