diff --git a/manager-app/src/async_bridge/command.rs b/manager-app/src/async_bridge/command.rs
index cb5673b..fa08c8b 100644
--- a/manager-app/src/async_bridge/command.rs
+++ b/manager-app/src/async_bridge/command.rs
@@ -22,3 +22,11 @@ pub struct SetSoundModePayload {
pub addr: BluetoothAdrr,
pub sound_mode: SoundMode,
}
+
+#[derive(Debug, Deserialize, Clone)]
+#[typeshare]
+#[serde(rename_all = "camelCase")]
+pub enum SetEqualizerPayload {
+ SetCustomEqualizer,
+ SetEqualizerPreset,
+}
\ No newline at end of file
diff --git a/manager-ui/src/components/EqualizerCard/equalizer.tsx b/manager-ui/src/components/EqualizerCard/equalizer.tsx
index 5ac9a92..d45e73b 100644
--- a/manager-ui/src/components/EqualizerCard/equalizer.tsx
+++ b/manager-ui/src/components/EqualizerCard/equalizer.tsx
@@ -1,18 +1,19 @@
-import { ChartData } from 'chart.js';
-import { useCallback, useState } from 'react';
-import { Line } from 'react-chartjs-2';
-import 'chartjs-plugin-dragdata';
import {
- Chart as ChartJS,
CategoryScale,
+ Chart as ChartJS,
+ ChartData,
+ Filler,
+ Legend,
LinearScale,
- PointElement,
LineElement,
+ PointElement,
Title,
- Tooltip,
- Legend,
- Filler
+ Tooltip
} from 'chart.js';
+import { useCallback, useState } from 'react';
+import { Line } from 'react-chartjs-2';
+import 'chartjs-plugin-dragdata';
+import { Button } from '@mui/material';
ChartJS.register(
CategoryScale,
@@ -66,6 +67,12 @@ export const Equalizer = ({ bands, input, onEqualizerChange }: EqualizerProps):
console.log('Equalizer output:', newDataSet);
};
+ const onResetClick = () => {
+ const newDataSet = Array(bands).fill(0);
+ setDataSet(newDataSet);
+ onEqualizerChange(newDataSet);
+ };
+
//@ts-expect-error: no type found for this event
const onHover = useCallback((e) => {
const point = e?.chart.getElementsAtEventForMode(e, 'nearest', { intersect: true }, false);
@@ -111,6 +118,7 @@ export const Equalizer = ({ bands, input, onEqualizerChange }: EqualizerProps):
return (
<>
+
>
);
};
diff --git a/manager-ui/src/components/EqualizerCard/equalizerCard.tsx b/manager-ui/src/components/EqualizerCard/equalizerCard.tsx
index 0b87a3b..de96b76 100644
--- a/manager-ui/src/components/EqualizerCard/equalizerCard.tsx
+++ b/manager-ui/src/components/EqualizerCard/equalizerCard.tsx
@@ -1,6 +1,6 @@
-import { Paper } from '@mui/material';
+import { Collapse, MenuItem, Paper, Select, SelectChangeEvent, Stack } from '@mui/material';
import { Equalizer } from './equalizer';
-import { SoundcoreDeviceState } from '@generated-types/soundcore-lib';
+import { EQProfile, SoundcoreDeviceState } from '@generated-types/soundcore-lib';
import { useCallback } from 'react';
export interface EqualizerCardProps {
@@ -8,11 +8,15 @@ export interface EqualizerCardProps {
}
export const EqualizerCard = ({ state }: EqualizerCardProps): JSX.Element => {
- const onEqualizerChange = useCallback((output: number[]) => {
+ const onCustomEqualizerChange = useCallback((output: number[]) => {
console.log('Equalizer output:', output);
console.log('Equalizer output mapped:', mapRangeArray(output, -6, 6, 0, 240));
}, []);
+ const onSelectedEqProfileChange = (e: SelectChangeEvent) => {
+ console.log('Selected EQ profile:', e.target.value);
+ };
+
const mapRange = (
value: number,
inMin: number,
@@ -40,21 +44,35 @@ export const EqualizerCard = ({ state }: EqualizerCardProps): JSX.Element => {
} else {
valueArr = state.eqConfiguration.value.eq.values;
}
- console.log('EQ values:', valueArr);
return mapRangeArray(valueArr, 0, 240, -6, 6);
};
- console.log('Mapped EQ values:', getMappedEqValues());
+ const eqProfiles = Object.keys(EQProfile).filter((item) => {
+ return isNaN(Number(item));
+ });
+
+ const isOnCustom = state.eqConfiguration.value.profile === EQProfile.Custom;
return (
- {state.featureSet.equalizerFeatures && (
-
- )}
+
+
+ {state.featureSet.equalizerFeatures && (
+
+
+
+ )}
+
);
};
diff --git a/manager-ui/src/types/tauri-backend.d.ts b/manager-ui/src/types/tauri-backend.d.ts
index 7462b55..b67c9c1 100644
--- a/manager-ui/src/types/tauri-backend.d.ts
+++ b/manager-ui/src/types/tauri-backend.d.ts
@@ -24,6 +24,11 @@ export type BridgeCommand =
| { command: 'disconnectAll'; payload?: undefined }
| { command: 'setSoundMode'; payload: SetSoundModePayload };
+export enum SetEqualizerPayload {
+ SetCustomEqualizer = 'setCustomEqualizer',
+ SetEqualizerPreset = 'setEqualizerPreset'
+}
+
export type BridgeResponse =
| { kind: 'scanResult'; payload: DiscoveredDevice[] }
| { kind: 'connectionEstablished'; payload: TaggedStateResponse }
diff --git a/soundcore-lib/src/devices/a3040/eq_update_command.rs b/soundcore-lib/src/devices/a3040/eq_update_command.rs
index 2fa402f..5312531 100644
--- a/soundcore-lib/src/devices/a3040/eq_update_command.rs
+++ b/soundcore-lib/src/devices/a3040/eq_update_command.rs
@@ -10,11 +10,13 @@ impl Packet for A3040EqUpdateCommand {
fn command(&self) -> [u8; 7] {
match self.bass_up.0 {
true => [0x08, 0xEE, 0x00, 0x00, 0x00, 0x02, 0x84],
- false => todo!(),
+ false => [0x08, 0xEE, 0x00, 0x00, 0x00, 0x03, 0x87],
}
}
fn payload(&self) -> Vec {
+ // 2 bytes profile - FEFE - Custom
+ //
todo!()
}
}
diff --git a/soundcore-lib/src/main.rs b/soundcore-lib/src/main.rs
new file mode 100644
index 0000000..dba710e
--- /dev/null
+++ b/soundcore-lib/src/main.rs
@@ -0,0 +1,33 @@
+use env_logger::{Builder, Target};
+use log::LevelFilter;
+
+use soundcore_lib::ble::{BLEConnectionFactory, BLEConnectionManager};
+use soundcore_lib::device_manager::create_device_manager;
+
+#[tokio::main]
+async fn main() -> Result<(), Box> {
+ Builder::new()
+ .target(Target::Stdout)
+ .filter_level(LevelFilter::Trace)
+ .init();
+ let manager = create_device_manager().await;
+ let scan_res = manager.ble_scan(None).await?;
+ println!("{:?}", scan_res);
+ let device = scan_res
+ .iter()
+ .find(|d| d.descriptor.name.contains("Q45"))
+ .unwrap();
+ let connection = manager.connect(device.clone()).await?;
+
+ let mut state_channel = connection.state_channel().await;
+
+ while let Ok(()) = state_channel.changed().await {
+ println!("{:?}", state_channel.borrow_and_update());
+ }
+ // let registry = BtlePlugDeviceRegistry::new().await?;
+ // let scan_res = registry.scan(None).await?;
+ // println!("{:?}", scan_res);
+ // let q45 = scan_res.iter().find(|d| d.name.contains("Q45")).unwrap();
+ // let _connection = registry.connect(q45.clone(), None).await?;
+ Ok(())
+}
diff --git a/soundcore-lib/src/parsers/packet_header.rs b/soundcore-lib/src/parsers/packet_header.rs
index 8bc53bb..45c977b 100644
--- a/soundcore-lib/src/parsers/packet_header.rs
+++ b/soundcore-lib/src/parsers/packet_header.rs
@@ -34,7 +34,7 @@ fn parse_packet_kind<'a, E: ParseError<'a>>(bytes: &'a [u8]) -> ParseResult {
+ // TODO: Assert state
+ assert_eq!(state.tag, SupportedModels::A3040);
+ println!("{:?}", state.data);
+ }
+ Err(err) => panic!("Failed to parse state update packet, error: {:X?}", err),
+ _ => panic!("Parsed as wrong packet type"),
+ }
+}
+
+#[test]
+fn should_parse_sound_mode_update_packet() {
+ // Normal
+ // {
+ // let packet = ResponsePacket::from_bytes(&test_data::a3040::SOUND_MODE_UPDATE_NORMAL);
+ // match packet {
+ // Ok(ResponsePacket::SoundModeUpdate(state)) => {
+ // assert_eq!(state.0.current, CurrentSoundMode::Normal);
+ // }
+ // Err(_err) => panic!("Failed to parse state update packet"),
+ // _ => panic!("Parsed as wrong packet type"),
+ // }
+ // }
+ // // Noise Cancelling
+ // {
+ // let packet = ResponsePacket::from_bytes(&test_data::a3040::SOUND_MODE_UPDATE_NOISE_CANCELLING);
+ // match packet {
+ // Ok(ResponsePacket::SoundModeUpdate(state)) => {
+ // todo!()
+ // }
+ // Err(_err) => panic!("Failed to parse state update packet"),
+ // _ => panic!("Parsed as wrong packet type"),
+ // }
+ // }
+ // // Transparency
+ // {
+ // let packet = ResponsePacket::from_bytes(&test_data::a3040::SOUND_MODE_UPDATE_TRANSPARENCY);
+ // match packet {
+ // Ok(ResponsePacket::SoundModeUpdate(state)) => {
+ // todo!()
+ // }
+ // Err(_err) => panic!("Failed to parse state update packet"),
+ // _ => panic!("Parsed as wrong packet type"),
+ // }
+ // }
+}
diff --git a/test_data/src/a3040.rs b/test_data/src/a3040.rs
index 467dfca..b5b9974 100644
--- a/test_data/src/a3040.rs
+++ b/test_data/src/a3040.rs
@@ -10,6 +10,18 @@ pub const A3040_STATE_UPDATE_BYTES: [u8; 152] = [
0x78, 0x78, 0x78, 0x78, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x57,
];
+pub const UNKN: [u8; 152] = [
+ 0x9, 0xFF, 0x0, 0x0, 0x1, 0x1, 0x1, 0x98, 0x0, 0x5, 0xFF, 0x30, 0x36, 0x2E, 0x33, 0x34, 0x33,
+ 0x30, 0x34, 0x30, 0x45, 0x41, 0x43, 0x33, 0x35, 0x36, 0x43, 0x43, 0x45, 0x45, 0x45, 0x38, 0x2,
+ 0x0, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x0, 0x0, 0x78, 0x78, 0x78, 0x78, 0x78,
+ 0x78, 0x78, 0x78, 0x0, 0x0, 0x4, 0x4, 0x7, 0x7, 0x1, 0x51, 0x1, 0x0, 0x0, 0x3, 0xFF, 0x0, 0x0,
+ 0xFF, 0x1, 0x31, 0x0, 0x1, 0xFF, 0x0, 0x1, 0x1, 0x0, 0x5A, 0x0, 0x1, 0x1, 0x0, 0x2, 0x0, 0x32,
+ 0xFF, 0x0, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x0, 0x0, 0x3C, 0x3C, 0x3C, 0x3C,
+ 0x3C, 0x3C, 0x3C, 0x3C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3C, 0x3C, 0x3C, 0x3C, 0xB4, 0x3C,
+ 0xB4, 0x3C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x78, 0x78, 0x78, 0x78,
+ 0x78, 0x78, 0x78, 0x78, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5C,
+];
+
pub const anc: [u8; 152] = [
0x9, 0xFF, 0x0, 0x0, 0x1, 0x1, 0x1, 0x98, 0x0, 0x2, 0xFF, 0x30, 0x36, 0x2E, 0x33, 0x34, 0x33,
0x30, 0x34, 0x30, 0x45, 0x41, 0x43, 0x33, 0x35, 0x36, 0x43, 0x43, 0x45, 0x45, 0x45, 0x38, 0x0,
@@ -59,8 +71,17 @@ pub const max_eq: [u8; 152] = [
0x7C, 0x7C, 0x7C, 0x7E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x77,
];
-pub const SOUND_MODE_UPDATE_NOISE_CANCELLING: [u8; 16] = [0x9, 0xFF, 0x0, 0x0, 0x1, 0x6, 0x1, 0x10, 0x0, 0x0, 0x51, 0x1, 0x1, 0x0, 0x5, 0x78];
-pub const SOUND_MODE_UPDATE_TRANSPARENCY: [u8; 16] = [0x9, 0xFF, 0x0, 0x0, 0x1, 0x6, 0x1, 0x10, 0x0, 0x1, 0x50, 0x1, 0x1, 0x0, 0x5, 0x78];
-pub const SOUND_MODE_UPDATE_NORMAL: [u8; 16] = [0x9, 0xFF, 0x0, 0x0, 0x1, 0x6, 0x1, 0x10, 0x0, 0x2, 0x50, 0x1, 0x1, 0x0, 0x5, 0x79];
-pub const BASS_UP_UPDATE_ENABLE: [u8; 12] = [0x9, 0xFF, 0x0, 0x0, 0x1, 0x2, 0x1, 0xC, 0x0, 0x2, 0x0, 0x1A];
-pub const BASS_UP_UPDATE_DISABLE: [u8; 12] = [0x9, 0xFF, 0x0, 0x0, 0x1, 0x2, 0x1, 0xC, 0x0, 0xFE, 0xFE, 0x14];
\ No newline at end of file
+pub const SOUND_MODE_UPDATE_NOISE_CANCELLING: [u8; 16] = [
+ 0x9, 0xFF, 0x0, 0x0, 0x1, 0x6, 0x1, 0x10, 0x0, 0x0, 0x51, 0x1, 0x1, 0x0, 0x5, 0x78,
+];
+pub const SOUND_MODE_UPDATE_TRANSPARENCY: [u8; 16] = [
+ 0x9, 0xFF, 0x0, 0x0, 0x1, 0x6, 0x1, 0x10, 0x0, 0x1, 0x50, 0x1, 0x1, 0x0, 0x5, 0x78,
+];
+pub const SOUND_MODE_UPDATE_NORMAL: [u8; 16] = [
+ 0x9, 0xFF, 0x0, 0x0, 0x1, 0x6, 0x1, 0x10, 0x0, 0x2, 0x50, 0x1, 0x1, 0x0, 0x5, 0x79,
+];
+pub const BASS_UP_UPDATE_ENABLE: [u8; 12] =
+ [0x9, 0xFF, 0x0, 0x0, 0x1, 0x2, 0x1, 0xC, 0x0, 0x2, 0x0, 0x1A];
+pub const BASS_UP_UPDATE_DISABLE: [u8; 12] = [
+ 0x9, 0xFF, 0x0, 0x0, 0x1, 0x2, 0x1, 0xC, 0x0, 0xFE, 0xFE, 0x14,
+];
diff --git a/test_data/src/lib.rs b/test_data/src/lib.rs
index 07c375f..b5838d8 100644
--- a/test_data/src/lib.rs
+++ b/test_data/src/lib.rs
@@ -1,2 +1,2 @@
+pub mod a3040;
pub mod a3951;
-pub mod a3040;
\ No newline at end of file