1use std::iter::zip;
5use std::sync::Arc;
6use std::time::Duration;
7
8use hidapi::{HidApi, HidResult};
9use image::DynamicImage;
10use tokio::sync::Mutex;
11use tokio::task::block_in_place;
12use tokio::time::sleep;
13
14use crate::{DeviceState, DeviceStateUpdate, Kind, list_devices, Ajazz, AjazzError, AjazzInput};
15use crate::images::{convert_image_async, ImageRect};
16
17pub fn refresh_device_list_async(hidapi: &mut HidApi) -> HidResult<()> {
19 block_in_place(move || hidapi.refresh_devices())
20}
21
22pub fn list_devices_async(hidapi: &HidApi) -> Vec<(Kind, String)> {
27 block_in_place(move || list_devices(hidapi))
28}
29
30#[derive(Clone)]
33pub struct AsyncAjazz {
34 kind: Kind,
35 device: Arc<Mutex<Ajazz>>,
36}
37
38impl AsyncAjazz {
40 pub fn connect(hidapi: &HidApi, kind: Kind, serial: &str) -> Result<AsyncAjazz, AjazzError> {
42 let device = block_in_place(move || Ajazz::connect(hidapi, kind, serial))?;
43
44 Ok(AsyncAjazz {
45 kind,
46 device: Arc::new(Mutex::new(device)),
47 })
48 }
49}
50
51impl AsyncAjazz {
53 pub fn kind(&self) -> Kind {
55 self.kind
56 }
57
58 pub async fn manufacturer(&self) -> Result<String, AjazzError> {
60 let device = self.device.lock().await;
61 block_in_place(move || device.manufacturer())
62 }
63
64 pub async fn product(&self) -> Result<String, AjazzError> {
66 let device = self.device.lock().await;
67 block_in_place(move || device.product())
68 }
69
70 pub async fn serial_number(&self) -> Result<String, AjazzError> {
72 let device = self.device.lock().await;
73 block_in_place(move || device.serial_number())
74 }
75
76 pub async fn firmware_version(&self) -> Result<String, AjazzError> {
78 let device = self.device.lock().await;
79 block_in_place(move || device.firmware_version())
80 }
81
82 pub async fn read_input(&self, poll_rate: f32) -> Result<AjazzInput, AjazzError> {
85 loop {
86 let device = self.device.lock().await;
87 let data = block_in_place(move || device.read_input(None))?;
88
89 if !data.is_empty() {
90 return Ok(data);
91 }
92
93 sleep(Duration::from_secs_f32(1.0 / poll_rate)).await;
94 }
95 }
96
97 pub async fn reset(&self) -> Result<(), AjazzError> {
99 let device = self.device.lock().await;
100 block_in_place(move || device.reset())
101 }
102
103 pub async fn set_brightness(&self, percent: u8) -> Result<(), AjazzError> {
105 let device = self.device.lock().await;
106 block_in_place(move || device.set_brightness(percent))
107 }
108
109 pub async fn write_image(&self, key: u8, image_data: &[u8]) -> Result<(), AjazzError> {
112 let device = self.device.lock().await;
113 block_in_place(move || device.write_image(key, image_data))
114 }
115
116 pub async fn clear_button_image(&self, key: u8) -> Result<(), AjazzError> {
119 let device = self.device.lock().await;
120 block_in_place(move || device.clear_button_image(key))
121 }
122
123 pub async fn clear_all_button_images(&self) -> Result<(), AjazzError> {
126 let device = self.device.lock().await;
127 block_in_place(move || device.clear_all_button_images())
128 }
129
130 pub async fn set_button_image(&self, key: u8, image: DynamicImage) -> Result<(), AjazzError> {
133 let image = convert_image_async(self.kind, image)?;
134
135 let device = self.device.lock().await;
136 block_in_place(move || device.write_image(key, &image))
137 }
138
139 pub async fn set_logo_image(&self, image: DynamicImage) -> Result<(), AjazzError> {
141 let device = self.device.lock().await;
142 block_in_place(move || device.set_logo_image(image))
143 }
144
145 pub async fn sleep(&self) -> Result<(), AjazzError> {
147 let device = self.device.lock().await;
148 block_in_place(move || device.sleep())
149 }
150
151 pub async fn keep_alive(&self) -> Result<(), AjazzError> {
153 let device = self.device.lock().await;
154 block_in_place(move || device.keep_alive())
155 }
156
157 pub async fn shutdown(&self) -> Result<(), AjazzError> {
159 let device = self.device.lock().await;
160 block_in_place(move || device.shutdown())
161 }
162
163 pub async fn flush(&self) -> Result<(), AjazzError> {
165 let device = self.device.lock().await;
166 block_in_place(move || device.flush())
167 }
168
169 pub fn get_reader(&self) -> Arc<AsyncDeviceStateReader> {
171 Arc::new(AsyncDeviceStateReader {
172 device: self.clone(),
173 states: Mutex::new(DeviceState {
174 buttons: vec![false; self.kind.key_count() as usize],
175 encoders: vec![false; self.kind.encoder_count() as usize],
176 }),
177 })
178 }
179}
180
181pub struct AsyncDeviceStateReader {
183 device: AsyncAjazz,
184 states: Mutex<DeviceState>,
185}
186
187impl AsyncDeviceStateReader {
188 pub async fn read(&self, poll_rate: f32) -> Result<Vec<DeviceStateUpdate>, AjazzError> {
190 let input = self.device.read_input(poll_rate).await?;
191 let mut my_states = self.states.lock().await;
192
193 let mut updates = vec![];
194
195 match input {
196 AjazzInput::ButtonStateChange(buttons) => {
197 for (index, is_changed) in buttons.iter().enumerate() {
198 if !is_changed {
199 continue;
200 }
201
202 my_states.buttons[index] = !my_states.buttons[index];
203 if my_states.buttons[index] {
204 updates.push(DeviceStateUpdate::ButtonDown(index as u8));
205 } else {
206 updates.push(DeviceStateUpdate::ButtonUp(index as u8));
207 }
208 }
209 }
210
211 AjazzInput::EncoderStateChange(encoders) => {
212 for (index, is_changed) in encoders.iter().enumerate() {
213 if !is_changed {
214 continue;
215 }
216
217 my_states.encoders[index] = !my_states.encoders[index];
218 if my_states.encoders[index] {
219 updates.push(DeviceStateUpdate::EncoderDown(index as u8));
220 } else {
221 updates.push(DeviceStateUpdate::EncoderUp(index as u8));
222 }
223 }
224 }
225
226 AjazzInput::EncoderTwist(twist) => {
227 for (index, change) in twist.iter().enumerate() {
228 if *change != 0 {
229 updates.push(DeviceStateUpdate::EncoderTwist(index as u8, *change));
230 }
231 }
232 }
233
234 _ => {}
235 }
236
237 drop(my_states);
238
239 Ok(updates)
240 }
241}