1use serde::{Deserialize, Serialize};
4
5use crate::{common, sys, MaaError, MaaResult};
6use std::ffi::{CStr, CString};
7use std::path::PathBuf;
8
9#[derive(Debug, Clone, Serialize, Deserialize)]
11pub struct AdbDevice {
12 pub name: String,
14 pub adb_path: PathBuf,
16 pub address: String,
18 pub screencap_methods: u64,
20 pub input_methods: u64,
22 pub config: serde_json::Value,
24}
25
26#[derive(Debug, Clone, Serialize, Deserialize)]
28pub struct DesktopWindow {
29 pub hwnd: usize,
31 pub class_name: String,
33 pub window_name: String,
35}
36
37pub struct Toolkit;
39
40impl Toolkit {
41 pub fn init_option(user_path: &str, default_config: &str) -> MaaResult<()> {
47 let c_path = CString::new(user_path)?;
48 let c_config = CString::new(default_config)?;
49 let ret = unsafe { sys::MaaToolkitConfigInitOption(c_path.as_ptr(), c_config.as_ptr()) };
50 common::check_bool(ret)
51 }
52
53 pub fn find_adb_devices() -> MaaResult<Vec<AdbDevice>> {
60 Self::find_adb_devices_impl(None)
61 }
62
63 pub fn find_adb_devices_with_adb(adb_path: &str) -> MaaResult<Vec<AdbDevice>> {
71 Self::find_adb_devices_impl(Some(adb_path))
72 }
73
74 fn find_adb_devices_impl(specified_adb: Option<&str>) -> MaaResult<Vec<AdbDevice>> {
75 let list = unsafe { sys::MaaToolkitAdbDeviceListCreate() };
76 if list.is_null() {
77 return Err(MaaError::NullPointer);
78 }
79
80 let _guard = AdbDeviceListGuard(list);
81
82 unsafe {
83 let ret = if let Some(adb_path) = specified_adb {
84 let c_path = CString::new(adb_path)?;
85 sys::MaaToolkitAdbDeviceFindSpecified(c_path.as_ptr(), list)
86 } else {
87 sys::MaaToolkitAdbDeviceFind(list)
88 };
89 common::check_bool(ret)?;
90
91 let count = sys::MaaToolkitAdbDeviceListSize(list);
92 let mut devices = Vec::with_capacity(count as usize);
93
94 for i in 0..count {
95 let device_ptr = sys::MaaToolkitAdbDeviceListAt(list, i);
96 if device_ptr.is_null() {
97 continue;
98 }
99
100 let name = CStr::from_ptr(sys::MaaToolkitAdbDeviceGetName(device_ptr))
101 .to_string_lossy()
102 .into_owned();
103
104 let adb_path_str = CStr::from_ptr(sys::MaaToolkitAdbDeviceGetAdbPath(device_ptr))
105 .to_string_lossy()
106 .into_owned();
107
108 let address = CStr::from_ptr(sys::MaaToolkitAdbDeviceGetAddress(device_ptr))
109 .to_string_lossy()
110 .into_owned();
111
112 let screencap_methods =
113 sys::MaaToolkitAdbDeviceGetScreencapMethods(device_ptr) as u64;
114 let input_methods = sys::MaaToolkitAdbDeviceGetInputMethods(device_ptr) as u64;
115
116 let config_str =
117 CStr::from_ptr(sys::MaaToolkitAdbDeviceGetConfig(device_ptr)).to_string_lossy();
118 let config = serde_json::from_str(&config_str).unwrap_or(serde_json::Value::Null);
119
120 devices.push(AdbDevice {
121 name,
122 adb_path: PathBuf::from(adb_path_str),
123 address,
124 screencap_methods,
125 input_methods,
126 config,
127 });
128 }
129 Ok(devices)
130 }
131 }
132
133 pub fn find_desktop_windows() -> MaaResult<Vec<DesktopWindow>> {
138 let list = unsafe { sys::MaaToolkitDesktopWindowListCreate() };
139 if list.is_null() {
140 return Err(MaaError::NullPointer);
141 }
142
143 let _guard = DesktopWindowListGuard(list);
144
145 unsafe {
146 let ret = sys::MaaToolkitDesktopWindowFindAll(list);
147 common::check_bool(ret)?;
148
149 let count = sys::MaaToolkitDesktopWindowListSize(list);
150 let mut windows = Vec::with_capacity(count as usize);
151
152 for i in 0..count {
153 let win_ptr = sys::MaaToolkitDesktopWindowListAt(list, i);
154 if win_ptr.is_null() {
155 continue;
156 }
157
158 let hwnd = sys::MaaToolkitDesktopWindowGetHandle(win_ptr) as usize;
159
160 let class_name = CStr::from_ptr(sys::MaaToolkitDesktopWindowGetClassName(win_ptr))
161 .to_string_lossy()
162 .into_owned();
163
164 let window_name =
165 CStr::from_ptr(sys::MaaToolkitDesktopWindowGetWindowName(win_ptr))
166 .to_string_lossy()
167 .into_owned();
168
169 windows.push(DesktopWindow {
170 hwnd,
171 class_name,
172 window_name,
173 });
174 }
175 Ok(windows)
176 }
177 }
178}
179
180struct AdbDeviceListGuard(*mut sys::MaaToolkitAdbDeviceList);
181impl Drop for AdbDeviceListGuard {
182 fn drop(&mut self) {
183 unsafe { sys::MaaToolkitAdbDeviceListDestroy(self.0) }
184 }
185}
186
187struct DesktopWindowListGuard(*mut sys::MaaToolkitDesktopWindowList);
188impl Drop for DesktopWindowListGuard {
189 fn drop(&mut self) {
190 unsafe { sys::MaaToolkitDesktopWindowListDestroy(self.0) }
191 }
192}