maa_framework/
toolkit.rs

1use serde::{Deserialize, Serialize};
2
3use crate::{error::Error, instance::MaaInstance, internal, maa_bool, string, MaaResult};
4
5#[cfg(feature = "win32")]
6use crate::controller::win32::MaaWin32Hwnd;
7
8#[cfg(feature = "adb")]
9use crate::controller::adb::MaaAdbControllerType;
10
11pub struct MaaToolkit;
12
13impl MaaToolkit {
14    /// Initialize the MaaToolkit
15    ///
16    /// # Errors
17    ///
18    /// Returns an error if the toolkit initialization fails
19    #[deprecated(since = "0.4.0", note = "Use `MaaToolkit::new_with_options` instead")]
20    pub fn new() -> MaaResult<Self> {
21        let toolkit_init_ret = unsafe { internal::MaaToolkitInit() };
22
23        if !maa_bool!(toolkit_init_ret) {
24            return Err(Error::MaaToolkitInitError);
25        }
26
27        Ok(Self)
28    }
29
30    pub fn new_with_options<T: Serialize>(user_path: String, config: T) -> MaaResult<Self> {
31        let user_path = internal::to_cstring(&user_path);
32        let config = internal::to_cstring(&serde_json::to_string(&config).unwrap());
33
34        let toolkit_init_ret = unsafe { internal::MaaToolkitInitOptionConfig(user_path, config) };
35
36        if !maa_bool!(toolkit_init_ret) {
37            return Err(Error::MaaToolkitInitError);
38        }
39
40        Ok(Self)
41    }
42
43    /// Find all the devices
44    ///
45    /// # Errors
46    ///
47    /// Return an error if fails to convert MaaStringView to String
48    #[cfg(feature = "adb")]
49    #[doc(cfg(feature = "adb"))]
50    pub fn find_adb_device(&self) -> MaaResult<Vec<AdbDeviceInfo>> {
51        let ret = unsafe { internal::MaaToolkitPostFindDevice() };
52
53        if !maa_bool!(ret) {
54            return Err(Error::MaaToolkitPostFindDeviceError);
55        }
56
57        let device_count = unsafe { internal::MaaToolkitWaitForFindDeviceToComplete() };
58
59        self.get_adb_devices_info(device_count)
60    }
61
62    /// Find all the devices with a given adb path
63    ///
64    /// # Errors
65    ///
66    /// Return an error if fails to convert MaaStringView to String
67    #[cfg(feature = "adb")]
68    #[doc(cfg(feature = "adb"))]
69    pub fn find_adb_device_with_adb(&self, adb_path: &str) -> MaaResult<Vec<AdbDeviceInfo>> {
70        let adb_path = internal::to_cstring(adb_path);
71        let ret = unsafe { internal::MaaToolkitPostFindDeviceWithAdb(adb_path) };
72
73        if !maa_bool!(ret) {
74            return Err(Error::MaaToolkitPostFindDeviceError);
75        }
76
77        let device_count = unsafe { internal::MaaToolkitWaitForFindDeviceToComplete() };
78
79        self.get_adb_devices_info(device_count)
80    }
81
82    #[cfg(feature = "adb")]
83    #[doc(cfg(feature = "adb"))]
84    fn get_adb_devices_info(&self, device_count: u64) -> MaaResult<Vec<AdbDeviceInfo>> {
85        let mut devices = Vec::with_capacity(device_count as usize);
86
87        for i in 0..device_count {
88            let name = unsafe { internal::MaaToolkitGetDeviceName(i) };
89            let adb_path = unsafe { internal::MaaToolkitGetDeviceAdbPath(i) };
90            let adb_serial = unsafe { internal::MaaToolkitGetDeviceAdbSerial(i) };
91            let adb_controller_type = unsafe { internal::MaaToolkitGetDeviceAdbControllerType(i) };
92            let adb_config = unsafe { internal::MaaToolkitGetDeviceAdbConfig(i) };
93
94            let name = string!(name);
95            let adb_path = string!(adb_path);
96            let adb_serial = string!(adb_serial);
97            let adb_config = string!(adb_config);
98            let adb_controller_type = MaaAdbControllerType::try_from(adb_controller_type)?;
99
100            devices.push(AdbDeviceInfo {
101                name,
102                adb_path,
103                adb_serial,
104                adb_controller_type,
105                adb_config,
106            });
107        }
108
109        Ok(devices)
110    }
111
112    pub fn register_custom_recognizer_executor<T>(
113        &self,
114        handle: MaaInstance<T>,
115        recognizer_name: &str,
116        recognizer_exec_path: &str,
117        recognizer_exec_params: Vec<String>,
118    ) -> MaaResult<()> {
119        let recognizer_name = internal::to_cstring(recognizer_name);
120        let recognizer_exec_path = internal::to_cstring(recognizer_exec_path);
121
122        let param_size = recognizer_exec_params.len() as u64;
123        let mut params: Vec<_> = recognizer_exec_params
124            .into_iter()
125            .map(|s| internal::to_cstring(&s))
126            .collect();
127        params.shrink_to_fit();
128        let params_ptr = params.as_ptr();
129        std::mem::forget(params);
130
131        let ret = unsafe {
132            internal::MaaToolkitRegisterCustomRecognizerExecutor(
133                *handle,
134                recognizer_name,
135                recognizer_exec_path,
136                params_ptr,
137                param_size,
138            )
139        };
140
141        if !maa_bool!(ret) {
142            return Err(Error::MaaToolkitRegisterCustomRecognizerExecutorError);
143        }
144
145        Ok(())
146    }
147
148    pub fn unregister_custom_recognizer_executor<T>(
149        &self,
150        handle: MaaInstance<T>,
151        recognizer_name: &str,
152    ) -> MaaResult<()> {
153        let recognizer_name = internal::to_cstring(recognizer_name);
154
155        let ret = unsafe {
156            internal::MaaToolkitUnregisterCustomRecognizerExecutor(*handle, recognizer_name)
157        };
158
159        if !maa_bool!(ret) {
160            return Err(Error::MaaToolkitUnregisterCustomRecognizerExecutorError);
161        }
162
163        Ok(())
164    }
165
166    pub fn register_custom_action_executor<T>(
167        &self,
168        handle: MaaInstance<T>,
169        action_name: &str,
170        action_exec_path: &str,
171        action_exec_params: Vec<String>,
172    ) -> MaaResult<()> {
173        let action_name = internal::to_cstring(action_name);
174        let action_exec_path = internal::to_cstring(action_exec_path);
175
176        let param_size = action_exec_params.len() as u64;
177        let mut params: Vec<_> = action_exec_params
178            .into_iter()
179            .map(|s| internal::to_cstring(&s))
180            .collect();
181        params.shrink_to_fit();
182        let params_ptr = params.as_ptr();
183        std::mem::forget(params);
184
185        let ret = unsafe {
186            internal::MaaToolkitRegisterCustomActionExecutor(
187                *handle,
188                action_name,
189                action_exec_path,
190                params_ptr,
191                param_size,
192            )
193        };
194
195        if !maa_bool!(ret) {
196            return Err(Error::MaaToolkitRegisterCustomRecognizerExecutorError);
197        }
198
199        Ok(())
200    }
201
202    pub fn unregister_custom_action_executor<T>(
203        &self,
204        handle: MaaInstance<T>,
205        action_name: &str,
206    ) -> MaaResult<()> {
207        let action_name = internal::to_cstring(action_name);
208
209        let ret =
210            unsafe { internal::MaaToolkitUnregisterCustomActionExecutor(*handle, action_name) };
211
212        if !maa_bool!(ret) {
213            return Err(Error::MaaToolkitUnregisterCustomRecognizerExecutorError);
214        }
215
216        Ok(())
217    }
218
219    /// Find all the windows with a given class name and window name
220    ///
221    /// # Parameters
222    /// - `class_name`: The class name of the window
223    /// - `window_name`: The window name of the window
224    /// - `find`: If true, find the window using system win32 api, otherwise search the window with text match
225    #[cfg(feature = "win32")]
226    #[doc(cfg(feature = "win32"))]
227    pub fn find_win32_window(
228        &self,
229        class_name: &str,
230        window_name: &str,
231        find: bool,
232    ) -> Vec<MaaWin32Hwnd> {
233        let class_name = internal::to_cstring(class_name);
234        let window_name = internal::to_cstring(window_name);
235
236        let hwnd_count = unsafe {
237            if find {
238                internal::MaaToolkitFindWindow(class_name, window_name)
239            } else {
240                internal::MaaToolkitSearchWindow(class_name, window_name)
241            }
242        };
243
244        let mut hwnds = Vec::with_capacity(hwnd_count as usize);
245
246        for i in 0..hwnd_count {
247            let hwnd = unsafe { internal::MaaToolkitGetWindow(i) };
248            hwnds.push(MaaWin32Hwnd(hwnd));
249        }
250
251        hwnds
252    }
253
254    #[cfg(feature = "win32")]
255    #[doc(cfg(feature = "win32"))]
256    pub fn get_cursor_window(&self) -> MaaWin32Hwnd {
257        let hwnd = unsafe { internal::MaaToolkitGetCursorWindow() };
258        MaaWin32Hwnd(hwnd)
259    }
260
261    #[cfg(feature = "win32")]
262    #[doc(cfg(feature = "win32"))]
263    pub fn get_desktop_window(&self) -> MaaWin32Hwnd {
264        let hwnd = unsafe { internal::MaaToolkitGetDesktopWindow() };
265        MaaWin32Hwnd(hwnd)
266    }
267
268    #[cfg(feature = "win32")]
269    #[doc(cfg(feature = "win32"))]
270    pub fn get_foreground_window(&self) -> MaaWin32Hwnd {
271        let hwnd = unsafe { internal::MaaToolkitGetForegroundWindow() };
272        MaaWin32Hwnd(hwnd)
273    }
274
275    #[cfg(feature = "win32")]
276    #[doc(cfg(feature = "win32"))]
277    pub fn list_windows(&self) -> Vec<MaaWin32Hwnd> {
278        let hwnd_count = unsafe { internal::MaaToolkitListWindows() };
279        let mut hwnds = Vec::with_capacity(hwnd_count as usize);
280
281        for i in 0..hwnd_count {
282            let hwnd = unsafe { internal::MaaToolkitGetWindow(i) };
283            hwnds.push(MaaWin32Hwnd(hwnd));
284        }
285
286        hwnds
287    }
288}
289
290unsafe impl Send for MaaToolkit {}
291unsafe impl Sync for MaaToolkit {}
292
293#[derive(Serialize, Deserialize)]
294#[cfg(feature = "adb")]
295pub struct AdbDeviceInfo {
296    pub name: String,
297    pub adb_path: String,
298    pub adb_serial: String,
299    pub adb_controller_type: MaaAdbControllerType,
300    pub adb_config: String,
301}