From 54fda168cc9adc4c46d615f2c567bb2e93ea9f20 Mon Sep 17 00:00:00 2001 From: LucasDLTG Date: Tue, 28 Jul 2026 12:39:13 +0200 Subject: [PATCH] feat: sidebar allows recall, rename and display custom names --- src/App.tsx | 109 +--- src/api/dsp408.ts | 8 +- src/components/Sidebar/Sidebar.tsx | 23 +- .../ConnectionSection/ConnectionSection.tsx | 2 +- src/hooks/useDSP408.ts | 553 ++++++++++++++++++ src/hooks/useDSPPolling.ts | 82 --- src/pages/AddDspPage/AddDspPage.tsx | 12 +- src/pages/DspPage/DspPage.tsx | 93 +-- src/types/types.ts | 3 +- 9 files changed, 632 insertions(+), 253 deletions(-) create mode 100644 src/hooks/useDSP408.ts delete mode 100644 src/hooks/useDSPPolling.ts diff --git a/src/App.tsx b/src/App.tsx index 6463494..654a234 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -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([]); @@ -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) { - try { - const id = await invoke('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 (
@@ -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' ? ( ) : page === 'add-dsp' ? ( - setPage('home')} onAdd={addDSP} /> + setPage('home')} onAdd={dsp408.addDSP} /> ) : activeDsp ? ( connectDSP(activeDsp)} - onDisconnect={() => disconnectDSP(activeDsp)} - notify={notify} + dsp408={dsp408.forDSP(activeDsp)} /> ) : ( invoke('disconnect_dsp408', { id export const getDSP408State = (id: number) => invoke('get_dsp_state', { id }); -export const recallPreset = (id: number, presetIndex: number) => +export const recallPresetDSP408 = (id: number, presetIndex: number) => invoke('recall_preset', { id, presetIndex, }); +export const DSP408SetCurrentPresetName = (id: number, name: string) => + invoke('set_current_preset_name', { + id, + name, + }); + export const getDSP408MeterLevels = (id: number) => invoke('get_meter_levels', { id }); diff --git a/src/components/Sidebar/Sidebar.tsx b/src/components/Sidebar/Sidebar.tsx index 16c4aed..7c1746e 100644 --- a/src/components/Sidebar/Sidebar.tsx +++ b/src/components/Sidebar/Sidebar.tsx @@ -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() { + 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" diff --git a/src/components/dsp408/ConnectionSection/ConnectionSection.tsx b/src/components/dsp408/ConnectionSection/ConnectionSection.tsx index ef1b689..29b2569 100644 --- a/src/components/dsp408/ConnectionSection/ConnectionSection.tsx +++ b/src/components/dsp408/ConnectionSection/ConnectionSection.tsx @@ -57,7 +57,7 @@ function ConnectionPanel({
Device ID
-
+
{dsp.deviceId || '—'}
diff --git a/src/hooks/useDSP408.ts b/src/hooks/useDSP408.ts new file mode 100644 index 0000000..e769d23 --- /dev/null +++ b/src/hooks/useDSP408.ts @@ -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>; + +// ============================================================ +// 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; + disconnect: () => Promise; + recallPreset: (index: number) => Promise; + setCurrentPresetName: (name: string) => Promise; +}; + +// ============================================================ +// Polling +// ============================================================ + +function useDSPPolling( + dsps: DSP[], + selected: number | null, + setDsps: React.Dispatch> +) { + 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 | undefined; + let inactiveTimeout: ReturnType | 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>, + setPage: React.Dispatch>, + 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( + dsp: DSP, + operation: () => Promise + ): Promise { + 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( + '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, + }; +} \ No newline at end of file diff --git a/src/hooks/useDSPPolling.ts b/src/hooks/useDSPPolling.ts deleted file mode 100644 index 3e8609c..0000000 --- a/src/hooks/useDSPPolling.ts +++ /dev/null @@ -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> -) { - 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]); -} diff --git a/src/pages/AddDspPage/AddDspPage.tsx b/src/pages/AddDspPage/AddDspPage.tsx index 0a1fa09..dbb24d2 100644 --- a/src/pages/AddDspPage/AddDspPage.tsx +++ b/src/pages/AddDspPage/AddDspPage.tsx @@ -10,18 +10,22 @@ function AddDSPForm({ onAdd, }: { onCancel: () => void; - onAdd: (d: Omit) => void; + onAdd: (d: Omit) => 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) })} />
diff --git a/src/pages/DspPage/DspPage.tsx b/src/pages/DspPage/DspPage.tsx index a37edf4..b2973b4 100644 --- a/src/pages/DspPage/DspPage.tsx +++ b/src/pages/DspPage/DspPage.tsx @@ -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: , }, { id: 'inb', - label: 'In B', + label: `In B (${inputStates?.[InputChannel.InB]?.name})`, icon: , }, { id: 'inc', - label: 'In C', + label: `In C (${inputStates?.[InputChannel.InC]?.name})`, icon: , }, { id: 'ind', - label: 'In D (TESTTEST)', + label: `In D (${inputStates?.[InputChannel.InD]?.name})`, icon: , }, + { id: 'out1', - label: 'Out 1', + label: `Out 1 (${outputStates?.[OutputChannel.Out1]?.name})`, icon: , }, { id: 'out2', - label: 'Out 2', + label: `Out 2 (${outputStates?.[OutputChannel.Out2]?.name})`, icon: , }, { id: 'out3', - label: 'Out 3', + label: `Out 3 (${outputStates?.[OutputChannel.Out3]?.name})`, icon: , }, { id: 'out4', - label: 'Out 4', + label: `Out 4 (${outputStates?.[OutputChannel.Out4]?.name})`, icon: , }, { id: 'out5', - label: 'Out 5', + label: `Out 5 (${outputStates?.[OutputChannel.Out5]?.name})`, icon: , }, { id: 'out6', - label: 'Out 6', + label: `Out 6 (${outputStates?.[OutputChannel.Out6]?.name})`, icon: , }, { id: 'out7', - label: 'Out 7', + label: `Out 7 (${outputStates?.[OutputChannel.Out7]?.name})`, icon: , }, { id: 'out8', - label: 'Out 8', + label: `Out 8 (${outputStates?.[OutputChannel.Out8]?.name})`, icon: , }, { @@ -154,52 +153,14 @@ function DSPPage({ })), ]; - const recallPreset = async (presetIndex: number) => { - try { - const success = await invoke('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('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 ; + return ; - case 'gain': - return ; + // case 'gain': + // return ; - case 'gate': - return ; + // case 'gate': + // return ; 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)} /> diff --git a/src/types/types.ts b/src/types/types.ts index a78763f..967bd40 100644 --- a/src/types/types.ts +++ b/src/types/types.ts @@ -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 = [