refactor: folders/files to group dsp logic

This commit is contained in:
2026-08-11 23:17:47 +02:00
parent d91bcaa20f
commit 34fad6f905
35 changed files with 194 additions and 337 deletions
+34 -108
View File
@@ -1,24 +1,17 @@
use dsp_thomann::dsp408::types::DelayUnit;
use tauri::State;
use crate::state::{AppState, DSPDevice};
use dsp_thomann::dsp408::{DSP408, types};
use std::{net::IpAddr, str::FromStr};
use dsp_thomann::dsp408::types::DelayUnit;
use dsp_thomann::dsp408::{types, DSP408};
use std::sync::{Arc, Mutex};
use std::{net::IpAddr, str::FromStr};
use tauri::State;
impl AppState {
pub fn with_device_mut<F, R>(
&self,
id: u64,
f: F,
) -> Result<R, String>
pub fn with_device_mut<F, R>(&self, id: u64, f: F) -> Result<R, String>
where
F: FnOnce(&mut DSPDevice) -> Result<R, String>,
{
let device = {
let devices = self
.devices
.lock()
.map_err(|e| e.to_string())?;
let devices = self.devices.lock().map_err(|e| e.to_string())?;
devices
.get(&id)
@@ -26,22 +19,14 @@ impl AppState {
.ok_or_else(|| "DSP not found".to_string())?
};
let mut device = device
.lock()
.map_err(|e| e.to_string())?;
let mut device = device.lock().map_err(|e| e.to_string())?;
f(&mut device)
}
pub fn remove_device(
&self,
id: u64,
) -> Result<(), String> {
pub fn remove_device(&self, id: u64) -> Result<(), String> {
let device = {
let mut devices = self.devices
.lock()
.map_err(|e| e.to_string())?;
let mut devices = self.devices.lock().map_err(|e| e.to_string())?;
devices
.remove(&id)
@@ -63,50 +48,29 @@ pub fn create_dsp408(
port: u16,
device_id: u8,
) -> Result<u64, String> {
let ip = IpAddr::from_str(&ip).map_err(|e| e.to_string())?;
let ip = IpAddr::from_str(&ip)
.map_err(|e| e.to_string())?;
let dsp = DSP408::new(ip, port, device_id).map_err(|e| e.to_string())?;
let dsp = DSP408::new(ip, port, device_id)
.map_err(|e| e.to_string())?;
let mut next_id = state
.next_id
.lock()
.map_err(|e| e.to_string())?;
let mut next_id = state.next_id.lock().map_err(|e| e.to_string())?;
let id = *next_id;
*next_id += 1;
let device = DSPDevice {
dsp,
};
let device = DSPDevice { dsp };
let mut devices = state
.devices
.lock()
.map_err(|e| e.to_string())?;
let mut devices = state.devices.lock().map_err(|e| e.to_string())?;
devices.insert(
id,
Arc::new(Mutex::new(device)),
);
devices.insert(id, Arc::new(Mutex::new(device)));
Ok(id)
}
#[tauri::command]
pub async fn remove_dsp408(
state: State<'_, AppState>,
id: u64,
) -> Result<(), String> {
pub async fn remove_dsp408(state: State<'_, AppState>, id: u64) -> Result<(), String> {
state.with_device_mut(id, |device| {
if device.dsp.connected() {
device.dsp
.disconnect()
.map_err(|e| e.to_string())?;
device.dsp.disconnect().map_err(|e| e.to_string())?;
}
Ok(())
@@ -118,28 +82,14 @@ pub async fn remove_dsp408(
}
#[tauri::command]
pub async fn connect_dsp408(
state: State<'_, AppState>,
id: u64,
) -> Result<(), String> {
state.with_device_mut(id, |device| {
device.dsp
.connect()
.map_err(|e| e.to_string())
})
pub async fn connect_dsp408(state: State<'_, AppState>, id: u64) -> Result<(), String> {
state.with_device_mut(id, |device| device.dsp.connect().map_err(|e| e.to_string()))
}
#[tauri::command]
pub async fn disconnect_dsp408(
state: State<'_, AppState>,
id: u64,
) -> Result<(), String> {
pub async fn disconnect_dsp408(state: State<'_, AppState>, id: u64) -> Result<(), String> {
state.with_device_mut(id, |device| {
device.dsp
.disconnect()
.map_err(|e| e.to_string())
device.dsp.disconnect().map_err(|e| e.to_string())
})
}
@@ -148,11 +98,8 @@ pub async fn get_dsp_state(
state: State<'_, AppState>,
id: u64,
) -> Result<dsp_thomann::dsp408::types::DSPState, String> {
state.with_device_mut(id, |device| {
let dsp_state = device.dsp
.state()
.map_err(|e| e.to_string())?;
let dsp_state = device.dsp.state().map_err(|e| e.to_string())?;
Ok(dsp_state.clone())
})
@@ -166,7 +113,8 @@ pub async fn set_channel_gain(
db: f32,
) -> Result<bool, String> {
state.with_device_mut(id, |device| {
let r = device.dsp
let r = device
.dsp
.set_channel_gain(channel, db)
.map_err(|e| e.to_string())?;
@@ -182,7 +130,8 @@ pub async fn set_mute(
muted: bool,
) -> Result<bool, String> {
state.with_device_mut(id, |device| {
let r = device.dsp
let r = device
.dsp
.set_mute(channel, muted)
.map_err(|e| e.to_string())?;
@@ -198,7 +147,8 @@ pub async fn set_channel_inverse_gain(
inverted: bool,
) -> Result<bool, String> {
state.with_device_mut(id, |device| {
let r = device.dsp
let r = device
.dsp
.set_channel_inverse_gain(channel, inverted)
.map_err(|e| e.to_string())?;
@@ -228,10 +178,7 @@ pub async fn get_meter_levels(
id: u64,
) -> Result<dsp_thomann::dsp408::types::Meters, String> {
state.with_device_mut(id, |device| {
device
.dsp
.get_meter_levels()
.map_err(|e| e.to_string())
device.dsp.get_meter_levels().map_err(|e| e.to_string())
})
}
@@ -281,14 +228,7 @@ pub async fn set_compressor(
state.with_device_mut(id, |device| {
device
.dsp
.set_compressor(
channel,
ratio,
attack,
release,
knee,
threshold,
)
.set_compressor(channel, ratio, attack, release, knee, threshold)
.map_err(|e| e.to_string())
})
}
@@ -317,10 +257,7 @@ pub async fn set_delay_unit(
unit: types::DelayUnit,
) -> Result<bool, String> {
state.with_device_mut(id, |device| {
device
.dsp
.set_delay_unit(unit)
.map_err(|e| e.to_string())
device.dsp.set_delay_unit(unit).map_err(|e| e.to_string())
})
}
@@ -330,7 +267,7 @@ pub async fn set_delay(
id: u64,
channel: types::Channel,
delay: f32,
unit: DelayUnit
unit: DelayUnit,
) -> Result<bool, String> {
state.with_device_mut(id, |device| {
device
@@ -449,15 +386,7 @@ pub async fn set_peq_band(
state.with_device_mut(id, |device| {
device
.dsp
.set_peq_band(
channel,
band,
gain_db,
freq_hz,
q,
filter_type,
bypass,
)
.set_peq_band(channel, band, gain_db, freq_hz, q, filter_type, bypass)
.map_err(|e| e.to_string())
})
}
@@ -484,10 +413,7 @@ pub async fn factory_reset(
force: bool,
) -> Result<bool, String> {
state.with_device_mut(id, |device| {
device
.dsp
.factory_reset(force)
.map_err(|e| e.to_string())
device.dsp.factory_reset(force).map_err(|e| e.to_string())
})
}
+2 -7
View File
@@ -1,5 +1,5 @@
mod state;
mod commands;
mod state;
use state::AppState;
@@ -12,17 +12,14 @@ pub fn run() {
commands::create_dsp408,
commands::remove_dsp408,
commands::get_dsp_state,
commands::connect_dsp408, // 0x10
commands::disconnect_dsp408, // 0x11
commands::set_delay_unit, // 0x15
commands::recall_preset, // 0x20
commands::store_current_configuration, // 0x21
commands::factory_reset, // 0x23
commands::set_current_preset_name, // 0x26
commands::copy_channel, // 0x2A
commands::set_compressor, // 0x30
commands::set_low_pass, // 0x31
commands::set_high_pass, // 0x32
@@ -38,13 +35,11 @@ pub fn run() {
commands::set_channel_name, // 0x3D
commands::set_gate, // 0x3E
commands::set_limiter, // 0x3F
commands::get_meter_levels, // 0x40
commands::set_matrix_gain, // 0x41
commands::set_geq_band, // 0x48
commands::set_geq_bypass, // 0x49
]
)
])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
+2 -2
View File
@@ -1,6 +1,6 @@
use std::sync::{Mutex, Arc};
use std::collections::HashMap;
use dsp_thomann::dsp408::DSP408;
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
pub struct DSPDevice {
pub dsp: DSP408,
+2 -2
View File
@@ -1,6 +1,6 @@
import { useState, useEffect, useRef, useMemo } from 'react';
import { useState, useEffect, useRef } from 'react';
import './App.css';
import { DSP, AppPage } from './types/types';
import { DSP, AppPage } from './types';
import TopBar from './components/Topbar/Topbar';
import DSPPage from './pages/DspPage/DspPage';
import AddDSPForm from './pages/AddDspPage/AddDspPage';
@@ -1,4 +1,4 @@
import type { Notification } from '../../types/types';
import type { Notification } from '../../types';
import './Notifications.css';
type Props = {
+1 -1
View File
@@ -1,5 +1,5 @@
import { useEffect, useRef } from 'react';
import { DSP, AppPage } from '../../types/types';
import { DSP, AppPage } from '../../types';
import AnimatedLogo from '../../assets/icons/AnimatedLogo';
import { PlusIcon } from '../../assets/icons/PlusIcon';
import { CrownIcon } from '../../assets/icons/CrownIcon';
+3 -3
View File
@@ -1,7 +1,7 @@
import { DSP, DSPTypes, AppPage } from '../types/types';
import { DSP, DSPTypes, AppPage } from '../types';
import { SetDsps, NotifyFn } from './dspShared';
import { forDSP408, create as createDSP408 } from './dsp408';
import { DSP408Api } from './dsp408';
import { forDSP408, create as createDSP408 } from '../features/dsp408/dsp408';
import { DSP408Api } from '../features/dsp408/dsp408';
// import { forDSP204 } from './dsp204';
export type DSPInstance = { dsp: Extract<DSP, { type: 'DSP408' }>; api: DSP408Api };
+1 -1
View File
@@ -1,4 +1,4 @@
import { DSP, DSPTypes } from '../types/types';
import { DSP, DSPTypes } from '../types';
import { stopPollingFor } from './pollRegistry';
export type SetDsps = React.Dispatch<React.SetStateAction<DSP[]>>;
+1 -1
View File
@@ -1,4 +1,4 @@
import { DSPTypes } from '../types/types';
import { DSPTypes } from '../types';
const stoppers = new Map<DSPTypes, (id: number) => void>();
@@ -1,13 +1,13 @@
// CompressorSection.tsx
import VerticalSlider from '../../VerticalSlider/VerticalSlider';
import { OutputChannel, Ratio } from '../../../types/dsp408';
import { DSP408 as DSP } from '../../../types/types';
import Button from '../../Button/Button';
import ChannelGroup from '../../ChannelGroup/ChannelGroup';
import { LinearGraph } from '../../LinearGraph/LinearGraph';
import MeterBar from '../../MeterBar/MeterBar';
import VerticalSlider from '../../../../components/VerticalSlider/VerticalSlider';
import { OutputChannel, Ratio } from '../../types';
import { DSP408 as DSP } from '../../../../types';
import Button from '../../../../components/Button/Button';
import ChannelGroup from '../../../../components/ChannelGroup/ChannelGroup';
import { LinearGraph } from '../../../../components/LinearGraph/LinearGraph';
import MeterBar from '../../../../components/MeterBar/MeterBar';
import { useMemo, useState, useEffect } from 'react';
import { TriangleUpIcon, TriangleDownIcon } from '../../../assets/icons/Triangle';
import { TriangleUpIcon, TriangleDownIcon } from '../../../../assets/icons/Triangle';
import './CompressorSection.css';
// Enum order defines stepper order (1:1 -> Limit).
@@ -1,7 +1,7 @@
import { DSP } from '../../../types/types';
import Button from '../../Button/Button';
import Card from '../../Card/Card';
import Led from '../../Led/Led';
import { DSP } from '../../../../types';
import Button from '../../../../components/Button/Button';
import Card from '../../../../components/Card/Card';
import Led from '../../../../components/Led/Led';
import './ConnectionSection.css';
@@ -1,20 +1,20 @@
import { useState } from 'react';
import { DSP } from '../../types/types';
import Sidebar from '../../components/Sidebar/Sidebar';
import { InfoIcon, KnobGainIcon, TextIcon } from '../../assets/icons/AudioIcons';
import ConnectionPanel from '../../components/dsp408/ConnectionSection/ConnectionSection';
import GainSection from '../../components/dsp408/GainSection/GainSection';
import CompressorSection from '../../components/dsp408/CompressorSection/CompressorSection';
import GateSection from '../../components/dsp408/GateSection/GateSection';
import LimiterSection from '../../components/dsp408/LimiterSection/LimiterSection';
import DelaySection from '../../components/dsp408/DelaySection/DelaySection';
import LoadingOverlay from '../../components/LoadingOverlay/LoadingOverlay';
import { InputChannel, OutputChannel } from '../../types/dsp408';
import MatrixSection from '../../components/dsp408/Matrixsection/Matrixsection';
import GeqSection from '../../components/dsp408/GeqSection/GeqSection';
import InputSection from '../../components/dsp408/InputSection/InputSection';
import { DSP408Api } from '../../dsp/dsp408';
import '../DspPage/DspPage.css';
import { DSP } from '../../../../types';
import Sidebar from '../../../../components/Sidebar/Sidebar';
import { InfoIcon, KnobGainIcon, TextIcon } from '../../../../assets/icons/AudioIcons';
import ConnectionPanel from '../ConnectionSection/ConnectionSection';
import GainSection from '../GainSection/GainSection';
import CompressorSection from '../CompressorSection/CompressorSection';
import GateSection from '../GateSection/GateSection';
import LimiterSection from '../LimiterSection/LimiterSection';
import DelaySection from '../DelaySection/DelaySection';
import LoadingOverlay from '../../../../components/LoadingOverlay/LoadingOverlay';
import { InputChannel, OutputChannel } from '../../types';
import MatrixSection from '../Matrixsection/Matrixsection';
import GeqSection from '../GeqSection/GeqSection';
import InputSection from '../InputSection/InputSection';
import { DSP408Api } from '../../dsp408';
import './DSP408Panel.css';
type DSP408 = Extract<DSP, { type: 'DSP408' }>;
@@ -132,15 +132,8 @@ function DSP408Panel({ dsp, api }: { dsp: DSP408; api: DSP408Api }) {
case 'limiter':
return <LimiterSection dsp={dsp} set_limiter={api.setLimiter} />;
// case 'delay':
// return (
// <DelaySection
// dsp={dsp}
// setDelay={api.setDelay}
// setDelayUnit={api.setDelayUnit}
// setDSPState={api.setDSPState}
// />
// );
case 'delay':
return <DelaySection dsp={dsp} setDelay={api.setDelay} setDelayUnit={api.setDelayUnit} />;
case 'ina':
return (
@@ -1,17 +1,12 @@
import VerticalSlider from '../../VerticalSlider/VerticalSlider';
import { InputChannel, Channel, OutputChannel, DelayUnit } from '../../../types/dsp408';
import { DSP408 as DSP } from '../../../types/types';
import Button from '../../Button/Button';
import ChannelGroup from '../../ChannelGroup/ChannelGroup';
import { LinearGraph } from '../../LinearGraph/LinearGraph';
import VerticalSlider from '../../../../components/VerticalSlider/VerticalSlider';
import { InputChannel, Channel, OutputChannel, DelayUnit } from '../../types';
import { DSP408 as DSP } from '../../../../types';
import Button from '../../../../components/Button/Button';
import ChannelGroup from '../../../../components/ChannelGroup/ChannelGroup';
import { LinearGraph } from '../../../../components/LinearGraph/LinearGraph';
import { useMemo, useState } from 'react';
import './DelaySection.css';
const DELAY_RANGES: Record<DelayUnit, [number, number]> = {
[DelayUnit.Millisecond]: [0, 680.0],
[DelayUnit.Meter]: [0, 233.58],
[DelayUnit.Feet]: [0, 766.329],
};
import { DELAY_RANGES } from '../../types';
const UNIT_LABEL: Record<DelayUnit, string> = {
[DelayUnit.Millisecond]: 'ms',
@@ -155,12 +150,10 @@ function DelaySection({
dsp,
setDelay,
setDelayUnit,
setDSPState,
}: {
dsp: DSP;
setDelay: SetDelayFn;
setDelayUnit: (unit: DelayUnit) => Promise<boolean>;
setDSPState: (updater: (dsp: DSP) => DSP) => void;
}) {
const unit = dsp.state?.current_config.delay_unit ?? DelayUnit.Millisecond;
@@ -224,93 +217,10 @@ function DelaySection({
return committedDelay(channel);
};
function convertDelayUnit(value: number, from: DelayUnit, to: DelayUnit): number {
const [, fromMax] = DELAY_RANGES[from];
const [, toMax] = DELAY_RANGES[to];
if (fromMax === 0) return 0;
const ratio = value / fromMax;
return ratio * toMax;
}
const handleUnitChange = async (newUnit: DelayUnit) => {
if (newUnit === unit) return;
const success = await setDelayUnit(newUnit);
if (!success) return;
setDSPState((d) => {
if (!d.state) return d;
const currentConfig = d.state.current_config;
return {
...d,
state: {
...d.state,
current_config: {
...currentConfig,
delay_unit: newUnit,
input_states: {
...currentConfig.input_states,
[InputChannel.InA]: {
...currentConfig.input_states[InputChannel.InA],
delay: convertDelayUnit(
currentConfig.input_states[InputChannel.InA].delay,
unit,
newUnit
),
},
[InputChannel.InB]: {
...currentConfig.input_states[InputChannel.InB],
delay: convertDelayUnit(
currentConfig.input_states[InputChannel.InB].delay,
unit,
newUnit
),
},
[InputChannel.InC]: {
...currentConfig.input_states[InputChannel.InC],
delay: convertDelayUnit(
currentConfig.input_states[InputChannel.InC].delay,
unit,
newUnit
),
},
[InputChannel.InD]: {
...currentConfig.input_states[InputChannel.InD],
delay: convertDelayUnit(
currentConfig.input_states[InputChannel.InD].delay,
unit,
newUnit
),
},
},
output_states: {
...currentConfig.output_states,
...Object.fromEntries(
Object.values(OutputChannel).map((channel) => [
channel,
{
...currentConfig.output_states[channel],
delay: convertDelayUnit(
currentConfig.output_states[channel].delay,
unit,
newUnit
),
},
])
),
},
},
},
};
});
await setDelayUnit(newUnit);
};
const inputRows = inputs.map((channel) => ({
@@ -1,9 +1,9 @@
import VerticalSlider from '../../VerticalSlider/VerticalSlider';
import { InputChannel, Channel, OutputChannel } from '../../../types/dsp408';
import { DSP408 as DSP } from '../../../types/types';
import Button from '../../Button/Button';
import ChannelGroup from '../../ChannelGroup/ChannelGroup';
import { LinearGraph } from '../../LinearGraph/LinearGraph';
import VerticalSlider from '../../../../components/VerticalSlider/VerticalSlider';
import { InputChannel, Channel, OutputChannel } from '../../types';
import { DSP408 as DSP } from '../../../../types';
import Button from '../../../../components/Button/Button';
import ChannelGroup from '../../../../components/ChannelGroup/ChannelGroup';
import { LinearGraph } from '../../../../components/LinearGraph/LinearGraph';
import './GainSection.css';
function GainPanel({
@@ -1,10 +1,10 @@
// GateSection.tsx
import VerticalSlider from '../../VerticalSlider/VerticalSlider';
import { InputChannel } from '../../../types/dsp408';
import { DSP408 as DSP } from '../../../types/types';
import ChannelGroup from '../../ChannelGroup/ChannelGroup';
import { LinearGraph } from '../../LinearGraph/LinearGraph';
import MeterBar from '../../MeterBar/MeterBar';
import VerticalSlider from '../../../../components/VerticalSlider/VerticalSlider';
import { InputChannel } from '../../types';
import { DSP408 as DSP } from '../../../../types';
import ChannelGroup from '../../../../components/ChannelGroup/ChannelGroup';
import { LinearGraph } from '../../../../components/LinearGraph/LinearGraph';
import MeterBar from '../../../../components/MeterBar/MeterBar';
import { useMemo, useState } from 'react';
import './GateSection.css';
@@ -1,9 +1,9 @@
import VerticalSlider from '../../VerticalSlider/VerticalSlider';
import { InputChannel, DiscreteFrequency } from '../../../types/dsp408';
import { DSP408 as DSP } from '../../../types/types';
import Button from '../../Button/Button';
import ChannelGroup from '../../ChannelGroup/ChannelGroup';
import { LinearGraph } from '../../LinearGraph/LinearGraph';
import VerticalSlider from '../../../../components/VerticalSlider/VerticalSlider';
import { InputChannel, DiscreteFrequency } from '../../types';
import { DSP408 as DSP } from '../../../../types';
import Button from '../../../../components/Button/Button';
import ChannelGroup from '../../../../components/ChannelGroup/ChannelGroup';
import { LinearGraph } from '../../../../components/LinearGraph/LinearGraph';
import { useMemo, useState } from 'react';
import './GeqSection.css';
@@ -1,17 +1,17 @@
// InputSection.tsx
import VerticalSlider from '../../VerticalSlider/VerticalSlider';
import VerticalSlider from '../../../../components/VerticalSlider/VerticalSlider';
// ASSUMPTION: an InputChannel enum exists alongside OutputChannel, mapping
// input pages 1-8 similarly (In1 -> 0, In2 -> 1, ...). Adjust import/values
// if the actual enum differs.
import { InputChannel, Channel, PEQBand, PEQFilter, PEQ, Meter } from '../../../types/dsp408';
import { DSP408 as DSP } from '../../../types/types';
import { CrossoverFilter } from '../../../types/dsp408';
import { LinearGraph } from '../../LinearGraph/LinearGraph';
import { InputChannel, Channel, PEQBand, PEQFilter, PEQ, Meter } from '../../types';
import { DSP408 as DSP } from '../../../../types';
import { CrossoverFilter } from '../../types';
import { LinearGraph } from '../../../../components/LinearGraph/LinearGraph';
import { useRef, useState } from 'react';
import './InputSection.css';
import ChannelGroup from '../../ChannelGroup/ChannelGroup';
import Button from '../../Button/Button';
import MeterBar from '../../MeterBar/MeterBar';
import ChannelGroup from '../../../../components/ChannelGroup/ChannelGroup';
import Button from '../../../../components/Button/Button';
import MeterBar from '../../../../components/MeterBar/MeterBar';
const FREQ_MIN = 20;
const FREQ_MAX = 20000;
@@ -1,10 +1,10 @@
// LimiterSection.tsx
import VerticalSlider from '../../VerticalSlider/VerticalSlider';
import { OutputChannel } from '../../../types/dsp408';
import { DSP408 as DSP } from '../../../types/types';
import ChannelGroup from '../../ChannelGroup/ChannelGroup';
import { LinearGraph } from '../../LinearGraph/LinearGraph';
import MeterBar from '../../MeterBar/MeterBar';
import VerticalSlider from '../../../../components/VerticalSlider/VerticalSlider';
import { OutputChannel } from '../../types';
import { DSP408 as DSP } from '../../../../types';
import ChannelGroup from '../../../../components/ChannelGroup/ChannelGroup';
import { LinearGraph } from '../../../../components/LinearGraph/LinearGraph';
import MeterBar from '../../../../components/MeterBar/MeterBar';
import { useMemo, useState } from 'react';
import './LimiterSection.css';
@@ -1,7 +1,7 @@
// MatrixSection.tsx
import { Fragment, useRef, useState } from 'react';
import { InputChannel, OutputChannel } from '../../../types/dsp408';
import { DSP408 as DSP } from '../../../types/types';
import { InputChannel, OutputChannel } from '../../types';
import { DSP408 as DSP } from '../../../../types';
import './MatrixSection.css';
// ASSUMPTION: an InputChannel enum exists alongside OutputChannel in
@@ -1,5 +1,5 @@
import { invoke } from '@tauri-apps/api/core';
import { DSP } from '../types/types';
import { DSP } from '../../types';
import {
Channel,
InputChannel,
@@ -11,10 +11,11 @@ import {
PEQFilter,
PEQBand,
InputSource,
} from '../types/dsp408';
import { SetDsps, NotifyFn, updateDSP, setPollingPaused } from './dspShared';
import { registerPollStopper } from './pollRegistry';
import { defaultDSPState, defaultMeters } from '../types/dsp408';
} from './types';
import { SetDsps, NotifyFn, updateDSP, setPollingPaused } from '../../dsp/dspShared';
import { registerPollStopper } from '../../dsp/pollRegistry';
import { defaultDSPState, defaultMeters } from './types';
import { DELAY_RANGES } from './types';
type DSP408 = Extract<DSP, { type: 'DSP408' }>;
@@ -737,16 +738,42 @@ export function forDSP408(dsp: DSP408, setDsps: SetDsps, notify: NotifyFn) {
async setDelayUnit(unit: DelayUnit): Promise<boolean> {
const updateDelayUnit = () => {
function convertDelayUnit(value: number, from: DelayUnit, to: DelayUnit): number {
if (from === to) return value;
const [, fromMax] = DELAY_RANGES[from];
const [, toMax] = DELAY_RANGES[to];
if (fromMax === 0) return 0;
const ratio = value / fromMax;
return ratio * toMax;
}
updateDSP(setDsps, dsp.id, (d) => {
if (!d.state) return d;
const currentConfig = d.state.current_config;
const oldUnit = currentConfig.delay_unit;
const convertAll = <T extends Record<string, { delay: number }>>(states: T): T =>
Object.fromEntries(
Object.entries(states).map(([channel, s]) => [
channel,
{ ...s, delay: convertDelayUnit(s.delay, oldUnit, unit) },
])
) as T;
return {
...d,
state: {
...d.state,
current_config: {
...d.state.current_config,
...currentConfig,
delay_unit: unit,
input_states: convertAll(currentConfig.input_states),
output_states: convertAll(currentConfig.output_states),
},
},
};
@@ -420,3 +420,9 @@ const createDefaultMeter = (): Meter => ({
export const defaultMeters: Meters = {
channels: Array.from({ length: 12 }, createDefaultMeter),
};
export const DELAY_RANGES: Record<DelayUnit, [number, number]> = {
[DelayUnit.Millisecond]: [0, 680.0],
[DelayUnit.Meter]: [0, 233.58],
[DelayUnit.Feet]: [0, 766.329],
};
+1 -1
View File
@@ -1,5 +1,5 @@
import { useState, useCallback, useRef } from 'react';
import { NotificationType, Notification } from '../types/types';
import { NotificationType, Notification } from '../types';
export function useNotifications() {
const [notifications, setNotifications] = useState<Notification[]>([]);
+1 -1
View File
@@ -1,5 +1,5 @@
import { useState } from 'react';
import { DSP, DSP_DEFAULT_PARAMETERS, DSPTypes } from '../../types/types';
import { DSP, DSP_DEFAULT_PARAMETERS, DSPTypes } from '../../types';
import Button from '../../components/Button/Button';
import Card from '../../components/Card/Card';
+1 -1
View File
@@ -1,5 +1,5 @@
import { DSPInstance } from '../../dsp/dspApi';
import DSP408Panel from '../DSP408Panel/DSP408Panel';
import DSP408Panel from '../../features/dsp408/components/DSP408Panel/DSP408Panel';
function DSPPage({ instance }: { instance: DSPInstance }) {
if (instance.dsp.type === 'DSP408') {
+1 -1
View File
@@ -1,4 +1,4 @@
import { DSPState as DSP408State, Meters as DSP408Meters } from './dsp408';
import { DSPState as DSP408State, Meters as DSP408Meters } from './features/dsp408/types';
export type DSPStatus = 'connected' | 'connecting' | 'disconnected';