1use std::{fmt::Display, ops::Deref};
2
3use serde::{Deserialize, Serialize};
4
5use crate::{
6 error::Error,
7 internal,
8 maa_bool, CallbackHandler, MaaResult, MaaStatus,
9};
10
11#[cfg(feature = "adb")]
12#[doc(cfg(feature = "adb"))]
13pub mod adb;
14#[cfg(feature = "dbg")]
15#[doc(cfg(feature = "dbg"))]
16pub mod dbg;
17#[cfg(feature = "win32")]
18#[doc(cfg(feature = "win32"))]
19pub mod win32;
20
21#[cfg(feature = "adb")]
22use self::adb::MaaAdbControllerType;
23
24#[cfg(feature = "custom_controller")]
25use crate::custom::custom_controller::MaaCustomController;
26
27#[cfg(feature = "dbg")]
28use self::dbg::MaaDbgControllerType;
29
30#[cfg(feature = "win32")]
31use self::win32::{MaaWin32ControllerType, MaaWin32Hwnd};
32
33pub use internal::MaaCtrlId;
34
35pub struct MaaControllerInstance<T> {
41 pub(crate) handle: internal::MaaControllerHandle,
42 _phantom: std::marker::PhantomData<T>,
43}
44
45impl<T> Deref for MaaControllerInstance<T> {
46 type Target = internal::MaaControllerHandle;
47
48 fn deref(&self) -> &Self::Target {
49 &self.handle
50 }
51}
52
53unsafe impl<T> Send for MaaControllerInstance<T> {}
54unsafe impl<T> Sync for MaaControllerInstance<T> {}
55
56impl<T> MaaControllerInstance<T> {
57 #[cfg(feature = "adb")]
62 #[doc(cfg(feature = "adb"))]
63 pub fn new_adb(
64 adb_path: &str,
65 address: &str,
66 controller_type: MaaAdbControllerType,
67 config: &str,
68 agent_path: &str,
69 handler: Option<T>,
70 ) -> Self
71 where
72 T: CallbackHandler,
73 {
74 let adb_path = internal::to_cstring(adb_path);
75 let address = internal::to_cstring(address);
76 let config = internal::to_cstring(config);
77 let agent_path = internal::to_cstring(agent_path);
78
79 let handle = unsafe {
80 match handler {
81 Some(handler) => {
82 let handler = Box::new(handler);
83 let handler = Box::into_raw(handler);
84
85 internal::MaaAdbControllerCreateV2(
86 adb_path,
87 address,
88 controller_type.into(),
89 config,
90 agent_path,
91 Some(internal::callback_handler::<T>),
92 handler.cast(),
93 )
94 }
95 None => internal::MaaAdbControllerCreateV2(
96 adb_path,
97 address,
98 controller_type.into(),
99 config,
100 agent_path,
101 None,
102 std::ptr::null_mut(),
103 ),
104 }
105 };
106
107 MaaControllerInstance {
108 handle,
109 _phantom: std::marker::PhantomData,
110 }
111 }
112
113 #[cfg(feature = "win32")]
114 #[doc(cfg(feature = "win32"))]
115 pub fn new_win32(
116 hwnd: MaaWin32Hwnd,
117 controller_type: MaaWin32ControllerType,
118 handler: Option<T>,
119 ) -> Self
120 where
121 T: CallbackHandler,
122 {
123 let handle = unsafe {
124 match handler {
125 Some(handler) => {
126 let handler = Box::new(handler);
127 let handler = Box::into_raw(handler);
128
129 internal::MaaWin32ControllerCreate(
130 *hwnd,
131 controller_type.into(),
132 Some(internal::callback_handler::<T>),
133 handler.cast(),
134 )
135 }
136 None => internal::MaaWin32ControllerCreate(
137 *hwnd,
138 controller_type.into(),
139 None,
140 std::ptr::null_mut(),
141 ),
142 }
143 };
144
145 MaaControllerInstance {
146 handle,
147 _phantom: std::marker::PhantomData,
148 }
149 }
150
151 #[cfg(feature = "dbg")]
152 #[doc(cfg(feature = "dbg"))]
153 pub fn new_dbg(
154 read_path: &str,
155 write_path: &str,
156 controller_type: MaaDbgControllerType,
157 config: &str,
158 handler: Option<T>,
159 ) -> Self
160 where
161 T: CallbackHandler,
162 {
163 let read_path = internal::to_cstring(read_path);
164 let write_path = internal::to_cstring(write_path);
165 let config = internal::to_cstring(config);
166
167 let handle = unsafe {
168 match handler {
169 Some(handler) => {
170 let handler = Box::new(handler);
171 let handler = Box::into_raw(handler);
172
173 internal::MaaDbgControllerCreate(
174 read_path,
175 write_path,
176 controller_type.into(),
177 config,
178 Some(internal::callback_handler::<T>),
179 handler.cast(),
180 )
181 }
182 None => internal::MaaDbgControllerCreate(
183 read_path,
184 write_path,
185 controller_type.into(),
186 config,
187 None,
188 std::ptr::null_mut(),
189 ),
190 }
191 };
192
193 MaaControllerInstance {
194 handle,
195 _phantom: std::marker::PhantomData,
196 }
197 }
198
199 #[cfg(feature = "custom_controller")]
200 #[doc(cfg(feature = "custom_controller"))]
201 pub fn new_custom<C>(controller: C, handler: Option<T>) -> Self
202 where
203 T: CallbackHandler,
204 C: MaaCustomController,
205 {
206 use crate::custom::custom_controller;
207
208 let controller_api = internal::MaaCustomControllerAPI {
209 connect: Some(custom_controller::custom_controller_connect::<C>),
210 request_uuid: Some(custom_controller::custom_controller_request_uuid::<C>),
211 request_resolution: Some(custom_controller::custom_controller_request_resolution::<C>),
212 start_app: Some(custom_controller::custom_controller_start_app::<C>),
213 stop_app: Some(custom_controller::custom_controller_stop_app::<C>),
214 screencap: Some(custom_controller::custom_controller_screencap::<C>),
215 click: Some(custom_controller::custom_controller_click::<C>),
216 swipe: Some(custom_controller::custom_controller_swipe::<C>),
217 touch_down: Some(custom_controller::custom_controller_touch_down::<C>),
218 touch_move: Some(custom_controller::custom_controller_touch_move::<C>),
219 touch_up: Some(custom_controller::custom_controller_touch_up::<C>),
220 press_key: Some(custom_controller::custom_controller_press_key::<C>),
221 input_text: Some(custom_controller::custom_controller_input_text::<C>),
222 };
223
224 let controller_api = Box::new(controller_api);
225 let controller_api = Box::into_raw(controller_api);
226
227 let handle = unsafe {
228 match handler {
229 Some(handler) => {
230 let handler = Box::new(handler);
231 let handler = Box::into_raw(handler);
232
233 internal::MaaCustomControllerCreate(
234 controller_api,
235 &controller as *const C as *mut C as *mut std::ffi::c_void,
236 Some(internal::callback_handler::<T>),
237 handler.cast(),
238 )
239 }
240 None => internal::MaaCustomControllerCreate(
241 controller_api,
242 &controller as *const C as *mut C as *mut std::ffi::c_void,
243 None,
244 std::ptr::null_mut(),
245 ),
246 }
247 };
248
249 MaaControllerInstance {
250 handle,
251 _phantom: std::marker::PhantomData,
252 }
253 }
254
255 pub(crate) fn new_from_handle(handle: internal::MaaControllerHandle) -> Self {
256 MaaControllerInstance {
257 handle,
258 _phantom: std::marker::PhantomData,
259 }
260 }
261
262 pub fn set_controller_option(&self, option: MaaControllerOption) -> MaaResult<()> {
263 let key = option.get_inner_key();
264
265 let ret = unsafe {
266 match option {
267 MaaControllerOption::DefaultAppPackage(ref package) => {
268 let val_size = package.len() as u64;
269 let package = package.as_ptr() as *mut std::os::raw::c_void;
270 let package = package as *mut std::os::raw::c_void;
271 internal::MaaControllerSetOption(self.handle, key, package, val_size)
272 }
273 MaaControllerOption::DefaultAppPackageEntry(ref package) => {
274 let val_size = package.len() as u64;
275 let package = package.as_ptr() as *mut std::os::raw::c_void;
276 let package = package as *mut std::os::raw::c_void;
277 internal::MaaControllerSetOption(self.handle, key, package, val_size)
278 }
279 MaaControllerOption::Recording(ref package) => {
280 let val_size = std::mem::size_of::<bool>() as u64;
281 let package = package as *const bool as *mut std::os::raw::c_void;
282 internal::MaaControllerSetOption(self.handle, key, package, val_size)
283 }
284 MaaControllerOption::ScreenshotTargetLongSide(ref package) => {
285 let val_size = std::mem::size_of::<i32>() as u64;
286 let package = package as *const i32 as *mut std::os::raw::c_void;
287 internal::MaaControllerSetOption(self.handle, key, package, val_size)
288 }
289 MaaControllerOption::ScreenshotTargetShortSide(ref package) => {
290 let val_size = std::mem::size_of::<i32>() as u64;
291 let package = package as *const i32 as *mut std::os::raw::c_void;
292 internal::MaaControllerSetOption(self.handle, key, package, val_size)
293 }
294 _ => internal::MaaControllerSetOption(self.handle, key, std::ptr::null_mut(), 0),
295 }
296 };
297
298 if !maa_bool!(ret) {
299 Err(Error::MaaControllerSetOptionError(option))
300 } else {
301 Ok(())
302 }
303 }
304
305 pub fn post_connect(&self) -> MaaCtrlId {
306 unsafe { internal::MaaControllerPostConnection(self.handle) }
307 }
308
309 pub fn post_click(&self, x: i32, y: i32) -> MaaCtrlId {
310 unsafe { internal::MaaControllerPostClick(self.handle, x, y) }
311 }
312
313 pub fn post_swipe(&self, x1: i32, y1: i32, x2: i32, y2: i32, duration: i32) -> MaaCtrlId {
314 unsafe { internal::MaaControllerPostSwipe(self.handle, x1, y1, x2, y2, duration) }
315 }
316
317 pub fn post_press_key(&self, keycode: i32) -> MaaCtrlId {
318 unsafe { internal::MaaControllerPostPressKey(self.handle, keycode) }
319 }
320
321 pub fn post_input_text(&self, text: &str) -> MaaCtrlId {
322 let text = internal::to_cstring(text);
323 unsafe { internal::MaaControllerPostInputText(self.handle, text) }
324 }
325
326 pub fn post_touch_down(&self, contact: i32, x: i32, y: i32, pressure: i32) -> MaaCtrlId {
327 unsafe { internal::MaaControllerPostTouchDown(self.handle, contact, x, y, pressure) }
328 }
329
330 pub fn post_touch_move(&self, contact: i32, x: i32, y: i32, pressure: i32) -> MaaCtrlId {
331 unsafe { internal::MaaControllerPostTouchMove(self.handle, contact, x, y, pressure) }
332 }
333
334 pub fn post_touch_up(&self, contact: i32) -> MaaCtrlId {
335 unsafe { internal::MaaControllerPostTouchUp(self.handle, contact) }
336 }
337
338 pub fn post_screencap(&self) -> MaaCtrlId {
339 unsafe { internal::MaaControllerPostScreencap(self.handle) }
340 }
341
342 pub fn status(&self, id: MaaCtrlId) -> MaaResult<MaaStatus> {
343 let status = unsafe { internal::MaaControllerStatus(self.handle, id) };
344
345 MaaStatus::try_from(status)
346 }
347
348 pub fn wait(&self, id: MaaCtrlId) -> MaaResult<MaaStatus> {
349 let status = unsafe { internal::MaaControllerWait(self.handle, id) };
350
351 MaaStatus::try_from(status)
352 }
353
354 pub fn connected(&self) -> bool {
355 unsafe { maa_bool!(internal::MaaControllerConnected(self.handle)) }
356 }
357}
358
359impl<T> Drop for MaaControllerInstance<T> {
360 fn drop(&mut self) {
361 unsafe {
362 internal::MaaControllerDestroy(self.handle);
363 }
364 }
365}
366
367#[derive(Debug, Serialize, Deserialize)]
368pub enum MaaControllerOption {
369 Invalid,
370 ScreenshotTargetLongSide(i32),
371 ScreenshotTargetShortSide(i32),
372 DefaultAppPackageEntry(String),
373 DefaultAppPackage(String),
374 Recording(bool),
375}
376
377impl Display for MaaControllerOption {
378 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
379 match self {
380 MaaControllerOption::Invalid => write!(f, "Invalid"),
381 MaaControllerOption::ScreenshotTargetLongSide(val) => {
382 write!(f, "ScreenshotTargetLongSide: {}", val)
383 }
384 MaaControllerOption::ScreenshotTargetShortSide(val) => {
385 write!(f, "ScreenshotTargetShortSide: {}", val)
386 }
387 MaaControllerOption::DefaultAppPackageEntry(val) => {
388 write!(f, "DefaultAppPackageEntry: {}", val)
389 }
390 MaaControllerOption::DefaultAppPackage(val) => write!(f, "DefaultAppPackage: {}", val),
391 MaaControllerOption::Recording(val) => write!(f, "Recording: {}", val),
392 }
393 }
394}
395
396impl MaaControllerOption {
397 fn get_inner_key(&self) -> internal::MaaCtrlOption {
398 match self {
399 MaaControllerOption::Invalid => internal::MaaCtrlOptionEnum_MaaCtrlOption_Invalid,
400 MaaControllerOption::ScreenshotTargetLongSide(_) => {
401 internal::MaaCtrlOptionEnum_MaaCtrlOption_ScreenshotTargetLongSide
402 }
403 MaaControllerOption::ScreenshotTargetShortSide(_) => {
404 internal::MaaCtrlOptionEnum_MaaCtrlOption_ScreenshotTargetShortSide
405 }
406 MaaControllerOption::DefaultAppPackageEntry(_) => {
407 internal::MaaCtrlOptionEnum_MaaCtrlOption_DefaultAppPackageEntry
408 }
409 MaaControllerOption::DefaultAppPackage(_) => {
410 internal::MaaCtrlOptionEnum_MaaCtrlOption_DefaultAppPackage
411 }
412 MaaControllerOption::Recording(_) => {
413 internal::MaaCtrlOptionEnum_MaaCtrlOption_Recording
414 }
415 }
416 }
417}