ajazz_sdk/
asynchronous.rs1use std::sync::Arc;
5use std::time::Duration;
6
7use hidapi::{HidApi, HidResult};
8use image::DynamicImage;
9use tokio::sync::Mutex;
10use tokio::task::block_in_place;
11use tokio::time::sleep;
12
13use crate::{AjazzError, AjazzInput, DeviceState, Event, Kind};
14use crate::device::{handle_input_state_change, Ajazz};
15use crate::hid::list_devices;
16use crate::images::convert_image_async;
17
18pub fn refresh_device_list_async(hidapi: &mut HidApi) -> HidResult<()> {
20 block_in_place(move || hidapi.refresh_devices())
21}
22
23pub fn list_devices_async(hidapi: &HidApi) -> Vec<(Kind, String)> {
28 block_in_place(move || list_devices(hidapi))
29}
30
31#[derive(Clone)]
34pub struct AsyncAjazz {
35 kind: Kind,
36 device: Arc<Mutex<Ajazz>>,
37}
38
39impl AsyncAjazz {
41 pub fn connect(
43 hidapi: &HidApi,
44 kind: Kind,
45 serial: &str,
46 ) -> Result<AsyncAjazz, AjazzError> {
47 let device = block_in_place(move || Ajazz::connect(hidapi, kind, serial))?;
48
49 Ok(AsyncAjazz {
50 kind,
51 device: Arc::new(Mutex::new(device)),
52 })
53 }
54
55 pub fn connect_with_retries(
57 hidapi: &HidApi,
58 kind: Kind,
59 serial: &str,
60 attempts: u8,
61 ) -> Result<AsyncAjazz, AjazzError> {
62 let device = block_in_place(move || {
63 Ajazz::connect_with_retries(hidapi, kind, serial, attempts)
64 })?;
65
66 Ok(AsyncAjazz {
67 kind,
68 device: Arc::new(Mutex::new(device)),
69 })
70 }
71}
72
73impl AsyncAjazz {
75 pub fn kind(&self) -> Kind {
77 self.kind
78 }
79
80 pub async fn manufacturer(&self) -> Result<String, AjazzError> {
82 let device = self.device.lock().await;
83 block_in_place(move || device.manufacturer())
84 }
85
86 pub async fn product(&self) -> Result<String, AjazzError> {
88 let device = self.device.lock().await;
89 block_in_place(move || device.product())
90 }
91
92 pub async fn serial_number(&self) -> Result<String, AjazzError> {
94 let device = self.device.lock().await;
95 block_in_place(move || device.serial_number())
96 }
97
98 pub async fn firmware_version(&self) -> Result<String, AjazzError> {
100 let device = self.device.lock().await;
101 block_in_place(move || device.firmware_version())
102 }
103
104 pub async fn read_input(&self, poll_rate: f32) -> Result<AjazzInput, AjazzError> {
107 loop {
108 let device = self.device.lock().await;
109 let data = block_in_place(move || device.read_input(None))?;
110
111 if !data.is_empty() {
112 return Ok(data);
113 }
114
115 sleep(Duration::from_secs_f32(1.0 / poll_rate)).await;
116 }
117 }
118
119 pub async fn reset(&self) -> Result<(), AjazzError> {
121 let device = self.device.lock().await;
122 block_in_place(move || device.reset())
123 }
124
125 pub async fn set_brightness(&self, percent: u8) -> Result<(), AjazzError> {
127 let device = self.device.lock().await;
128 block_in_place(move || device.set_brightness(percent))
129 }
130
131 pub async fn clear_button_image(&self, key: u8) -> Result<(), AjazzError> {
134 let device = self.device.lock().await;
135 block_in_place(move || device.clear_button_image(key))
136 }
137
138 pub async fn clear_all_button_images(&self) -> Result<(), AjazzError> {
141 let device = self.device.lock().await;
142 block_in_place(move || device.clear_all_button_images())
143 }
144
145 pub async fn set_button_image(
148 &self,
149 key: u8,
150 image: DynamicImage,
151 ) -> Result<(), AjazzError> {
152 let image = convert_image_async(self.kind, image)?;
153
154 let device = self.device.lock().await;
155 block_in_place(move || device.set_button_image_data(key, &image))
156 }
157
158 pub async fn set_button_image_data(
161 &self,
162 key: u8,
163 image_data: &[u8],
164 ) -> Result<(), AjazzError> {
165 let device = self.device.lock().await;
166 block_in_place(move || device.set_button_image_data(key, image_data))
167 }
168
169 pub async fn set_logo_image(&self, image: DynamicImage) -> Result<(), AjazzError> {
171 let device = self.device.lock().await;
172 block_in_place(move || device.set_logo_image(image))
173 }
174
175 pub async fn sleep(&self) -> Result<(), AjazzError> {
177 let device = self.device.lock().await;
178 block_in_place(move || device.sleep())
179 }
180
181 pub async fn keep_alive(&self) -> Result<(), AjazzError> {
183 let device = self.device.lock().await;
184 block_in_place(move || device.keep_alive())
185 }
186
187 pub async fn shutdown(&self) -> Result<(), AjazzError> {
189 let device = self.device.lock().await;
190 block_in_place(move || device.shutdown())
191 }
192
193 pub async fn flush(&self) -> Result<(), AjazzError> {
195 let device = self.device.lock().await;
196 block_in_place(move || device.flush())
197 }
198
199 pub fn get_reader(&self) -> Arc<AsyncDeviceStateReader> {
201 Arc::new(AsyncDeviceStateReader {
202 device: self.clone(),
203 states: Mutex::new(DeviceState {
204 buttons: vec![false; self.kind.key_count() as usize],
205 encoders: vec![false; self.kind.encoder_count() as usize],
206 }),
207 })
208 }
209}
210
211pub struct AsyncDeviceStateReader {
213 device: AsyncAjazz,
214 states: Mutex<DeviceState>,
215}
216
217impl AsyncDeviceStateReader {
218 pub async fn read(&self, poll_rate: f32) -> Result<Vec<Event>, AjazzError> {
220 let input = self.device.read_input(poll_rate).await?;
221 let mut current_state = self.states.lock().await;
222
223 let updates = handle_input_state_change(input, &mut current_state)?;
224 Ok(updates)
225 }
226}