fix: refactor to avoid circular dependencies
This commit is contained in:
+29
-386
@@ -1,16 +1,30 @@
|
||||
use std::{
|
||||
collections::HashMap, io::{Read, Write}, net::{IpAddr, SocketAddr, TcpStream}, sync::{Mutex, OnceLock}, time::Duration, fmt,
|
||||
collections::HashMap,
|
||||
fmt,
|
||||
io::{Read, Write},
|
||||
net::{IpAddr, SocketAddr, TcpStream},
|
||||
sync::{Mutex, OnceLock},
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use strum::{EnumCount, IntoEnumIterator};
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
use crate::common::errors::{DSPError, ValidationError};
|
||||
use crate::dsp408::client::types;
|
||||
use crate::dsp408::client::constants;
|
||||
use crate::dsp408::protocol::frame::extract_frame;
|
||||
use crate::dsp408::protocol::commands;
|
||||
use crate::dsp408::mapper::response::map_response;
|
||||
use crate::dsp408::mapper;
|
||||
use crate::{
|
||||
common::errors::{DSPError, ValidationError},
|
||||
dsp408::{
|
||||
mapper::{
|
||||
self,
|
||||
constants::{PRESET_INDEX_MAX, CONFIG_CHUNK_INDEX_MAX},
|
||||
response::map_response,
|
||||
},
|
||||
protocol::{
|
||||
commands,
|
||||
config::decode_config,
|
||||
frame::extract_frame,
|
||||
},
|
||||
types,
|
||||
},
|
||||
};
|
||||
|
||||
pub const SOCKET_TIMEOUT: Duration = Duration::from_secs(20);
|
||||
pub const RECV_BUFSIZE: usize = 4096;
|
||||
@@ -231,9 +245,9 @@ impl DSP408 {
|
||||
let flags = self.get_device_flags()?;
|
||||
let current_preset = self.get_current_preset()?;
|
||||
let modified = self.get_preset_modification_status()?;
|
||||
let mut preset_names = Vec::with_capacity(constants::PRESET_INDEX_MAX);
|
||||
let mut preset_names = Vec::with_capacity(PRESET_INDEX_MAX);
|
||||
|
||||
for i in 0..constants::PRESET_INDEX_MAX {
|
||||
for i in 0..PRESET_INDEX_MAX {
|
||||
preset_names.push(
|
||||
self.get_preset_name(i + 1)?
|
||||
);
|
||||
@@ -805,6 +819,7 @@ impl DSP408 {
|
||||
}
|
||||
|
||||
// Command `0x33` (Set PEQ Band)
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn set_peq_band(
|
||||
&mut self,
|
||||
channel: types::Channel,
|
||||
@@ -847,7 +862,7 @@ impl DSP408 {
|
||||
gain: gain_db,
|
||||
frequency: freq_hz,
|
||||
q,
|
||||
filter_type: filter_type,
|
||||
filter_type,
|
||||
bypass,
|
||||
};
|
||||
|
||||
@@ -1607,12 +1622,12 @@ impl DSP408 {
|
||||
fn read_config_state(&mut self) -> Result<types::DSPConfigState, DSPError> {
|
||||
let mut raw = Vec::new();
|
||||
|
||||
for i in 0..=constants::CONFIG_CHUNK_INDEX_MAX {
|
||||
for i in 0..=CONFIG_CHUNK_INDEX_MAX {
|
||||
let chunk = self.get_config_chunk(i)?;
|
||||
raw.extend_from_slice(&chunk.data);
|
||||
}
|
||||
|
||||
let config = build_config_from_chunk(&raw)?;
|
||||
let config = decode_config(&raw)?;
|
||||
|
||||
if !self.request_acknowledgement()? {
|
||||
return Err(DSPError::OperationFailed(
|
||||
@@ -1641,375 +1656,3 @@ impl fmt::Debug for DSP408 {
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
struct BinaryReader<'a> {
|
||||
data: &'a [u8],
|
||||
}
|
||||
|
||||
impl<'a> BinaryReader<'a> {
|
||||
fn new(data: &'a [u8]) -> Self {
|
||||
Self { data }
|
||||
}
|
||||
|
||||
fn pop(&mut self, n: usize) -> Result<&'a [u8], DSPError> {
|
||||
if self.data.len() < n {
|
||||
return Err(DSPError::InvalidRequest(
|
||||
"buffer underflow".into()
|
||||
));
|
||||
}
|
||||
|
||||
let (value, rest) = self.data.split_at(n);
|
||||
self.data = rest;
|
||||
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
fn read_u8(&mut self) -> Result<u8, DSPError> {
|
||||
Ok(self.pop(1)?[0])
|
||||
}
|
||||
|
||||
fn read_u16(&mut self) -> Result<u16, DSPError> {
|
||||
Ok(u16::from_le_bytes(
|
||||
self.pop(2)?.try_into().unwrap()
|
||||
))
|
||||
}
|
||||
|
||||
fn skip(&mut self, n: usize) -> Result<(), DSPError> {
|
||||
self.pop(n)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn apply_flag<T>(
|
||||
r: &mut BinaryReader,
|
||||
targets: &mut [T],
|
||||
setter: impl Fn(&mut T, bool),
|
||||
) -> Result<(), DSPError> {
|
||||
let bitmap = r.read_u16()?;
|
||||
|
||||
for (index, target) in targets.iter_mut().enumerate() {
|
||||
setter(target, bitmap & (1 << index) != 0);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn read_gate(r: &mut BinaryReader) -> Result<types::Gate, DSPError> {
|
||||
Ok(types::Gate {
|
||||
attack: mapper::raw_to_attack_ms(r.read_u16()?)?,
|
||||
release: mapper::raw_to_release_ms(r.read_u16()?)?,
|
||||
hold: mapper::raw_to_hold_ms(r.read_u16()?)?,
|
||||
threshold: mapper::raw_to_gate_threshold_db(r.read_u16()?)?,
|
||||
})
|
||||
}
|
||||
|
||||
fn read_geq(
|
||||
r: &mut BinaryReader,
|
||||
) -> Result<types::GraphicEQ, DSPError> {
|
||||
let gains = types::DiscreteFrequency::iter()
|
||||
.map(|_| {
|
||||
let raw = r.read_u16()?;
|
||||
Ok(mapper::raw_to_eq_gain(raw)?)
|
||||
})
|
||||
.collect::<Result<Vec<_>, DSPError>>()?;
|
||||
|
||||
Ok(types::GraphicEQ {
|
||||
gains,
|
||||
bypass: false,
|
||||
})
|
||||
}
|
||||
|
||||
fn read_peq_chain(
|
||||
r: &mut BinaryReader,
|
||||
band_count: usize,
|
||||
) -> Result<types::PEQChain, DSPError> {
|
||||
let bands = (0..band_count)
|
||||
.map(|_| {
|
||||
Ok(types::PEQ {
|
||||
gain: mapper::raw_to_eq_gain(r.read_u16()?)?,
|
||||
frequency: mapper::raw_to_frequency_hz(r.read_u16()?)?,
|
||||
q: mapper::raw_to_peq_q(r.read_u8()?)?,
|
||||
filter_type: mapper::raw_to_peq_filter(r.read_u8()?)?,
|
||||
bypass: false,
|
||||
})
|
||||
})
|
||||
.collect::<Result<Vec<_>, DSPError>>()?;
|
||||
|
||||
Ok(types::PEQChain {
|
||||
bands,
|
||||
bypass: false,
|
||||
})
|
||||
}
|
||||
|
||||
fn read_crossover(
|
||||
r: &mut BinaryReader,
|
||||
) -> Result<types::CrossoverFilters, DSPError> {
|
||||
let hp_freq = r.read_u16()?;
|
||||
let lp_freq = r.read_u16()?;
|
||||
let hp_filter = r.read_u8()?;
|
||||
let lp_filter = r.read_u8()?;
|
||||
Ok(types::CrossoverFilters {
|
||||
high_pass: types::Crossover {
|
||||
frequency: mapper::raw_to_frequency_hz(hp_freq)?,
|
||||
slope: mapper::raw_to_crossover_filter(hp_filter)?,
|
||||
},
|
||||
low_pass: types::Crossover {
|
||||
frequency: mapper::raw_to_frequency_hz(lp_freq)?,
|
||||
slope: mapper::raw_to_crossover_filter(lp_filter)?,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
fn read_compressor(
|
||||
r: &mut BinaryReader,
|
||||
) -> Result<types::Compressor, DSPError> {
|
||||
Ok(types::Compressor {
|
||||
ratio: mapper::raw_to_ratio(r.read_u16()?)?,
|
||||
attack: mapper::raw_to_attack_ms(r.read_u16()?)?,
|
||||
release: mapper::raw_to_release_ms(r.read_u16()?)?,
|
||||
knee: mapper::raw_to_knee_db(r.read_u16()?)?,
|
||||
threshold: mapper::raw_to_threshold_db(r.read_u16()?)?,
|
||||
})
|
||||
}
|
||||
|
||||
fn read_limiter(
|
||||
r: &mut BinaryReader,
|
||||
) -> Result<types::Limiter, DSPError> {
|
||||
let attack = mapper::raw_to_attack_ms(r.read_u16()?)?;
|
||||
let release = mapper::raw_to_release_ms(r.read_u16()?)?;
|
||||
|
||||
r.skip(2)?;
|
||||
|
||||
let threshold = mapper::raw_to_threshold_db(r.read_u16()?)?;
|
||||
|
||||
Ok(types::Limiter {
|
||||
attack,
|
||||
release,
|
||||
threshold,
|
||||
})
|
||||
}
|
||||
|
||||
fn build_config_from_chunk(payload: &[u8]) -> Result<types::DSPConfigState, DSPError> {
|
||||
let mut r = BinaryReader::new(payload);
|
||||
|
||||
r.skip(2)?; // flags (unused)
|
||||
|
||||
let _preset_name = mapper::raw_to_preset_name(r.pop(constants::PRESET_NAME_LENGTH)?)?;
|
||||
|
||||
let mut input_channels = vec![types::InputChannelState::default(); types::InputChannel::COUNT];
|
||||
|
||||
let mut output_channels = vec![types::OutputChannelState::default(); types::OutputChannel::COUNT];
|
||||
|
||||
let mut input_delays_raw: Vec<u8> = Vec::new();
|
||||
let mut output_delays_raw: Vec<u8> = Vec::new();
|
||||
|
||||
// ============================
|
||||
// INPUT CHANNELS
|
||||
// ============================
|
||||
|
||||
for (channel, inp) in types::InputChannel::iter().zip(input_channels.iter_mut()) {
|
||||
inp.name = mapper::raw_to_channel_name(r.pop(constants::CHANNEL_NAME_LENGTH)?)?;
|
||||
|
||||
inp.gate = read_gate(&mut r)?;
|
||||
|
||||
inp.geq = read_geq(&mut r)?;
|
||||
|
||||
inp.peq_chain = read_peq_chain(&mut r, constants::PEQ_INPUT_BAND_COUNT)?;
|
||||
|
||||
inp.crossover = read_crossover(&mut r)?;
|
||||
|
||||
inp.gain = mapper::raw_to_gain(r.read_u16()?)?;
|
||||
|
||||
inp.phase_inverted = r.read_u8()? != 0;
|
||||
|
||||
r.skip(2)?; // reserved
|
||||
|
||||
input_delays_raw.push(r.read_u8()?);
|
||||
|
||||
r.skip(1)?;
|
||||
|
||||
inp.linked_channels = mapper::raw_to_link_channels(mapper::channel_to_raw(types::Channel::Input(channel))?, r.read_u8()?)?;
|
||||
}
|
||||
|
||||
// ============================
|
||||
// OUTPUT CHANNELS
|
||||
// ============================
|
||||
|
||||
for (channel, out) in types::OutputChannel::iter().zip(output_channels.iter_mut()) {
|
||||
out.name = mapper::raw_to_channel_name(r.pop(constants::CHANNEL_NAME_LENGTH)?)?;
|
||||
|
||||
r.skip(1)?;
|
||||
|
||||
out.matrix_routes = types::MatrixRoutes {
|
||||
connected:
|
||||
mapper::raw_to_matrix(
|
||||
r.read_u8()?
|
||||
)?,
|
||||
|
||||
gains: (0..4)
|
||||
.map(|_| {
|
||||
let raw = r.read_u16()?;
|
||||
Ok::<f32, DSPError>(mapper::raw_to_matrix_gain(raw)?)
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()?,
|
||||
};
|
||||
|
||||
out.crossover = read_crossover(&mut r)?;
|
||||
|
||||
out.peq_chain = read_peq_chain(&mut r, constants::PEQ_OUTPUT_BAND_COUNT)?;
|
||||
|
||||
out.compressor = read_compressor(&mut r)?;
|
||||
|
||||
out.limiter = read_limiter(&mut r)?;
|
||||
|
||||
out.gain = mapper::raw_to_gain(r.read_u16()?)?;
|
||||
|
||||
out.phase_inverted = r.read_u8()? != 0;
|
||||
|
||||
r.skip(2)?; // reserved
|
||||
|
||||
output_delays_raw.push(r.read_u8()?);
|
||||
|
||||
r.skip(1)?;
|
||||
|
||||
out.linked_channels = mapper::raw_to_link_channels(mapper::channel_to_raw(types::Channel::Output(channel))?, r.read_u8()?)?;
|
||||
}
|
||||
|
||||
// ============================
|
||||
// MUTE FLAGS
|
||||
// ============================
|
||||
|
||||
apply_flag(
|
||||
&mut r,
|
||||
&mut input_channels,
|
||||
|ch, value| ch.mute = value,
|
||||
)?;
|
||||
|
||||
apply_flag(
|
||||
&mut r,
|
||||
&mut output_channels,
|
||||
|ch, value| ch.mute = value,
|
||||
)?;
|
||||
|
||||
// ============================
|
||||
// PEQ BYPASS FLAGS
|
||||
// ============================
|
||||
|
||||
for inp in &mut input_channels {
|
||||
apply_flag(
|
||||
&mut r,
|
||||
inp.peq_chain.bands.as_mut_slice(),
|
||||
|band, value| band.bypass = value,
|
||||
)?;
|
||||
}
|
||||
|
||||
for out in &mut output_channels {
|
||||
apply_flag(
|
||||
&mut r,
|
||||
out.peq_chain.bands.as_mut_slice(),
|
||||
|band, value| band.bypass = value,
|
||||
)?;
|
||||
}
|
||||
|
||||
// ============================
|
||||
// INPUT SOURCE
|
||||
// ============================
|
||||
|
||||
let input_source = types::InputSource {
|
||||
r#type: mapper::raw_to_input_source(
|
||||
r.read_u16()? as u8,
|
||||
)?,
|
||||
|
||||
frequency: mapper::raw_to_frequency_value(
|
||||
r.read_u16()? as u8,
|
||||
)?,
|
||||
};
|
||||
|
||||
// ============================
|
||||
// DELAY UNIT
|
||||
// ============================
|
||||
|
||||
let delay_unit = mapper::raw_to_delay_unit(
|
||||
r.read_u16()? as u8,
|
||||
)?;
|
||||
|
||||
// ============================
|
||||
// APPLY DELAYS
|
||||
// ============================
|
||||
|
||||
for (inp, raw_delay) in input_channels.iter_mut().zip(input_delays_raw)
|
||||
{
|
||||
inp.delay = mapper::raw_to_delay(
|
||||
raw_delay,
|
||||
delay_unit,
|
||||
)?;
|
||||
}
|
||||
|
||||
for (out, raw_delay) in output_channels.iter_mut().zip(output_delays_raw)
|
||||
{
|
||||
out.delay = mapper::raw_to_delay(
|
||||
raw_delay,
|
||||
delay_unit,
|
||||
)?;
|
||||
}
|
||||
|
||||
// ============================
|
||||
// PEQ / GEQ BYPASS
|
||||
// ============================
|
||||
|
||||
let input_peq_bitmap = r.read_u16()?;
|
||||
|
||||
for (index, inp) in input_channels.iter_mut().enumerate() {
|
||||
let bypass = input_peq_bitmap & (1 << index) != 0;
|
||||
|
||||
for peq in inp.peq_chain.bands.iter_mut() {
|
||||
peq.bypass = bypass;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
let output_peq_bitmap = r.read_u16()?;
|
||||
|
||||
for (index, out) in output_channels.iter_mut().enumerate() {
|
||||
let bypass = output_peq_bitmap & (1 << index) != 0;
|
||||
|
||||
for peq in out.peq_chain.bands.iter_mut() {
|
||||
peq.bypass = bypass;
|
||||
}
|
||||
}
|
||||
|
||||
let bitmap = r.read_u16()?;
|
||||
|
||||
for (index, inp) in input_channels.iter_mut().enumerate() {
|
||||
inp.geq.bypass = bitmap & (1 << index) != 0;
|
||||
}
|
||||
|
||||
// ============================
|
||||
// BUILD CHANNEL MAP
|
||||
// ============================
|
||||
|
||||
let mut input_states = HashMap::new();
|
||||
|
||||
for (channel, state) in types::InputChannel::iter().zip(input_channels) {
|
||||
input_states.insert(
|
||||
channel,
|
||||
state,
|
||||
);
|
||||
}
|
||||
|
||||
let mut output_states = HashMap::new();
|
||||
|
||||
for (channel, state) in types::OutputChannel::iter().zip(output_channels) {
|
||||
output_states.insert(
|
||||
channel,
|
||||
state,
|
||||
);
|
||||
}
|
||||
|
||||
Ok(types::DSPConfigState {
|
||||
input_states,
|
||||
output_states,
|
||||
delay_unit: delay_unit,
|
||||
input_source: input_source,
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user