Skip to content

Commit 467e23a

Browse files
committed
linux-rust: add anc control for nothing device
1 parent 33671fc commit 467e23a

3 files changed

Lines changed: 139 additions & 24 deletions

File tree

linux-rust/src/devices/enums.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ impl AirPodsNoiseControlMode {
103103
#[derive(Clone, Debug)]
104104
pub struct NothingState {
105105
pub anc_mode: NothingAncMode,
106+
pub anc_mode_state: combo_box::State<NothingAncMode>,
106107
}
107108

108109
#[derive(Clone, Debug)]

linux-rust/src/ui/nothing.rs

Lines changed: 127 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,20 @@ use std::collections::HashMap;
22
use std::sync::Arc;
33
use iced::{Background, Border, Length, Theme};
44
use iced::widget::{container, text, column, row, Space};
5-
use crate::bluetooth::att::ATTManager;
6-
use crate::devices::enums::{DeviceData, DeviceInformation, NothingState};
5+
use iced::widget::combo_box;
6+
use iced::border::Radius;
7+
use iced::overlay::menu;
8+
use iced::widget::text_input;
9+
use tokio::runtime::Runtime;
10+
use std::thread;
11+
use crate::bluetooth::att::{ATTManager, ATTHandles};
12+
use crate::devices::enums::{DeviceData, DeviceInformation, NothingState, DeviceState};
713
use crate::ui::window::Message;
814

915
pub fn nothing_view<'a>(
10-
mac: &str,
16+
mac: &'a str,
1117
devices_list: &HashMap<String, DeviceData>,
12-
state: &NothingState,
18+
state: &'a NothingState,
1319
att_manager: Arc<ATTManager>
1420
) -> iced::widget::Container<'a, Message> {
1521
let mut information_col = iced::widget::column![];
@@ -53,13 +59,116 @@ pub fn nothing_view<'a>(
5359
);
5460
}
5561
}
62+
63+
let noise_control_mode = container(row![
64+
text("Noise Control Mode").size(16).style(
65+
|theme: &Theme| {
66+
let mut style = text::Style::default();
67+
style.color = Some(theme.palette().text);
68+
style
69+
}
70+
),
71+
Space::with_width(Length::Fill),
72+
{
73+
let state_clone = state.clone();
74+
let mac = mac.clone();
75+
let att_manager_clone = att_manager.clone();
76+
combo_box(
77+
&state.anc_mode_state,
78+
"Select Noise Control Mode",
79+
Some(&state.anc_mode.clone()),
80+
{
81+
move |selected_mode| {
82+
let att_manager = att_manager_clone.clone();
83+
let selected_mode_c = selected_mode.clone();
84+
let mac_s = mac.clone();
85+
run_async_in_thread(
86+
async move {
87+
if let Err(e) = att_manager.write(
88+
ATTHandles::NothingEverything,
89+
&[
90+
0x55,
91+
0x60, 0x01,
92+
0x0F, 0xF0,
93+
0x03, 0x00,
94+
0x00, 0x01,
95+
selected_mode_c.to_byte(), 0x00,
96+
0x00, 0x00
97+
]
98+
).await {
99+
log::error!("Failed to set noise cancellation mode for device {}: {}", mac_s, e);
100+
}
101+
}
102+
);
103+
let mut state = state_clone.clone();
104+
state.anc_mode = selected_mode.clone();
105+
Message::StateChanged(mac.to_string(), DeviceState::Nothing(state))
106+
}
107+
}
108+
)
109+
.width(Length::from(200))
110+
.input_style(
111+
|theme: &Theme, _status| {
112+
text_input::Style {
113+
background: Background::Color(theme.palette().primary.scale_alpha(0.2)),
114+
border: Border {
115+
width: 1.0,
116+
color: theme.palette().text.scale_alpha(0.3),
117+
radius: Radius::from(4.0)
118+
},
119+
icon: Default::default(),
120+
placeholder: theme.palette().text,
121+
value: theme.palette().text,
122+
selection: Default::default(),
123+
}
124+
}
125+
)
126+
.padding(iced::Padding{
127+
top: 5.0,
128+
bottom: 5.0,
129+
left: 10.0,
130+
right: 10.0,
131+
})
132+
.menu_style(
133+
|theme: &Theme| {
134+
menu::Style {
135+
background: Background::Color(theme.palette().background),
136+
border: Border {
137+
width: 1.0,
138+
color: theme.palette().text,
139+
radius: Radius::from(4.0)
140+
},
141+
text_color: theme.palette().text,
142+
selected_text_color: theme.palette().text,
143+
selected_background: Background::Color(theme.palette().primary.scale_alpha(0.3)),
144+
}
145+
}
146+
)
147+
}
148+
]
149+
.align_y(iced::Alignment::Center)
150+
)
151+
.padding(iced::Padding{
152+
top: 5.0,
153+
bottom: 5.0,
154+
left: 18.0,
155+
right: 18.0,
156+
})
157+
.style(
158+
|theme: &Theme| {
159+
let mut style = container::Style::default();
160+
style.background = Some(Background::Color(theme.palette().primary.scale_alpha(0.1)));
161+
let mut border = Border::default();
162+
border.color = theme.palette().primary.scale_alpha(0.5);
163+
style.border = border.rounded(16);
164+
style
165+
}
166+
);
167+
56168
container(
57169
column![
58-
row![
59-
text("Noise Control Mode").size(18),
60-
Space::with_width(Length::Fill),
61-
// combobox here
62-
],
170+
noise_control_mode,
171+
Space::with_height(Length::from(20)),
63172
container(information_col)
64173
.style(
65174
|theme: &Theme| {
@@ -79,18 +188,12 @@ pub fn nothing_view<'a>(
79188
.height(Length::Fill)
80189
}
81190

82-
83-
// if let Err(e) = manager.write(
84-
// ATTHandles::NothingEverything,
85-
// &[
86-
// 0x55,
87-
// 0x60, 0x01,
88-
// 0x0F, 0xF0,
89-
// 0x03, 0x00,
90-
// 0x00, 0x01, // the 0x00 is an incremental counter, but it works without it
91-
// mode.to_byte(), 0x00,
92-
// 0x00, 0x00 // these both bytes were something random, 0 works too
93-
// ]
94-
// ).await {
95-
// log::error!("Failed to set noise cancellation mode for device {}: {}", mac, e);
96-
// }
191+
fn run_async_in_thread<F>(fut: F)
192+
where
193+
F: Future<Output = ()> + Send + 'static,
194+
{
195+
thread::spawn(move || {
196+
let rt = Runtime::new().unwrap();
197+
rt.block_on(fut);
198+
});
199+
}

linux-rust/src/ui/window.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,14 @@ impl App {
341341
Some(DeviceType::Nothing) => {
342342
self.device_states.insert(mac.clone(), DeviceState::Nothing(NothingState {
343343
anc_mode: NothingAncMode::Off,
344+
anc_mode_state: combo_box::State::new(vec![
345+
NothingAncMode::Off,
346+
NothingAncMode::Transparency,
347+
NothingAncMode::AdaptiveNoiseCancellation,
348+
NothingAncMode::LowNoiseCancellation,
349+
NothingAncMode::MidNoiseCancellation,
350+
NothingAncMode::HighNoiseCancellation
351+
]),
344352
}));
345353
}
346354
_ => {}
@@ -444,6 +452,9 @@ impl App {
444452
}
445453
BluetoothUIMessage::ATTNotification(mac, handle, value) => {
446454
debug!("ATT Notification for {}: handle=0x{:04X}, value={:?}", mac, handle, value);
455+
456+
// TODO: Handle Nothing's ANC Mode changes here
457+
447458
let ui_rx = Arc::clone(&self.ui_rx);
448459
let wait_task = Task::perform(
449460
wait_for_message(ui_rx),

0 commit comments

Comments
 (0)