maa_framework/lib.rs
1//! # MaaFramework Rust Bindings
2//!
3//! High-performance, safe Rust bindings for [MaaFramework](https://github.com/MaaXYZ/MaaFramework),
4//! a game automation framework based on image recognition.
5//!
6//! ## Quick Start
7//!
8//! ```no_run
9//! use maa_framework::toolkit::Toolkit;
10//! use maa_framework::controller::Controller;
11//! use maa_framework::resource::Resource;
12//! use maa_framework::tasker::Tasker;
13//!
14//! fn main() -> Result<(), Box<dyn std::error::Error>> {
15//! // 0. Load library (Dynamic only)
16//! #[cfg(feature = "dynamic")]
17//! maa_framework::load_library(std::path::Path::new("MaaFramework.dll"))?;
18//!
19//! // 1. Find devices
20//! let devices = Toolkit::find_adb_devices()?;
21//! let device = devices.first().expect("No device found");
22//!
23//! // 2. Create controller
24//! let controller = Controller::new_adb(
25//! device.adb_path.to_str().unwrap(),
26//! &device.address,
27//! "{}",
28//! None,
29//! )?;
30//!
31//! // 3. Create resource and tasker
32//! let resource = Resource::new()?;
33//! let tasker = Tasker::new()?;
34//!
35//! // 4. Bind and run
36//! tasker.bind(&resource, &controller)?;
37//! let job = tasker.post_task("StartTask", "{}")?;
38//! job.wait();
39//!
40//! Ok(())
41//! }
42//! ```
43//!
44//! ## Core Modules
45//!
46//! | Module | Description |
47//! |--------|-------------|
48//! | [`tasker`] | Task execution and pipeline management |
49//! | [`resource`] | Resource loading (images, models, pipelines) |
50//! | [`controller`] | Device control (ADB, Win32, PlayCover) |
51//! | [`context`] | Task execution context for custom components |
52//! | [`toolkit`] | Device discovery utilities |
53//! | [`pipeline`] | Pipeline configuration types |
54//! | [`job`] | Asynchronous job management |
55//! | [`event_sink`] | Event sink system for typed callbacks |
56//! | [`buffer`] | Safe data buffers for FFI |
57//! | [`custom`] | Custom recognizer and action traits |
58//! | [`custom_controller`] | Custom controller implementation |
59//! | [`notification`] | Structured event notification parsing |
60//! | [`common`] | Common types and data structures |
61//! | [`error`] | Error types and handling |
62//! | [`util`] | Miscellaneous utility functions |
63//! | [`agent_client`] | Remote custom component client |
64//! | [`agent_server`] | Remote custom component server |
65//!
66//! ## Feature Flags
67//!
68//! - `adb` - ADB controller support (default)
69//! - `win32` - Win32 controller support (Windows only)
70//! - `custom` - Custom recognizer/action/controller support
71//! - `toolkit` - Device discovery utilities
72//! - `image` - Integration with the `image` crate
73
74#![allow(non_upper_case_globals)]
75#![allow(non_camel_case_types)]
76#![allow(non_snake_case)]
77
78pub mod agent_client;
79pub mod agent_server;
80pub mod buffer;
81pub mod callback;
82pub mod common;
83pub mod context;
84pub mod controller;
85pub mod custom;
86pub mod custom_controller;
87pub mod error;
88pub mod event_sink;
89pub mod job;
90pub mod notification;
91pub mod pipeline;
92pub mod resource;
93pub mod tasker;
94pub mod toolkit;
95pub mod util;
96
97pub use common::ControllerFeature;
98pub use common::MaaStatus;
99pub use error::{MaaError, MaaResult};
100
101pub use maa_framework_sys as sys;
102
103use std::ffi::CString;
104
105/// Get the MaaFramework version string.
106///
107/// # Example
108/// ```no_run
109/// println!("MaaFramework version: {}", maa_framework::maa_version());
110/// ```
111pub fn maa_version() -> &'static str {
112 unsafe {
113 std::ffi::CStr::from_ptr(sys::MaaVersion())
114 .to_str()
115 .unwrap_or("unknown")
116 }
117}
118
119/// Set a global framework option.
120///
121/// Low-level function for setting global options. Consider using the
122/// convenience wrappers like [`configure_logging`], [`set_debug_mode`], etc.
123pub fn set_global_option(
124 key: sys::MaaGlobalOption,
125 value: *mut std::ffi::c_void,
126 size: u64,
127) -> MaaResult<()> {
128 let ret = unsafe { sys::MaaGlobalSetOption(key, value, size) };
129 common::check_bool(ret)
130}
131
132/// Configure the log output directory.
133///
134/// # Arguments
135/// * `log_dir` - Path to the directory where logs should be stored
136pub fn configure_logging(log_dir: &str) -> MaaResult<()> {
137 let c_dir = CString::new(log_dir)?;
138 set_global_option(
139 sys::MaaGlobalOptionEnum_MaaGlobalOption_LogDir as i32,
140 c_dir.as_ptr() as *mut _,
141 c_dir.as_bytes().len() as u64,
142 )
143}
144
145/// Enable or disable debug mode.
146///
147/// In debug mode:
148/// - Recognition details include raw images and draws
149/// - All tasks are treated as focus tasks and produce callbacks
150///
151/// # Arguments
152/// * `enable` - `true` to enable debug mode
153pub fn set_debug_mode(enable: bool) -> MaaResult<()> {
154 let mut val_bool = if enable { 1u8 } else { 0u8 };
155 set_global_option(
156 sys::MaaGlobalOptionEnum_MaaGlobalOption_DebugMode as i32,
157 &mut val_bool as *mut _ as *mut _,
158 std::mem::size_of::<u8>() as u64,
159 )
160}
161
162/// Set the log level for stdout output.
163///
164/// # Arguments
165/// * `level` - Logging level (use `sys::MaaLoggingLevel*` constants)
166pub fn set_stdout_level(level: sys::MaaLoggingLevel) -> MaaResult<()> {
167 let mut val = level;
168 set_global_option(
169 sys::MaaGlobalOptionEnum_MaaGlobalOption_StdoutLevel as i32,
170 &mut val as *mut _ as *mut _,
171 std::mem::size_of::<sys::MaaLoggingLevel>() as u64,
172 )
173}
174
175/// Enable/disable saving recognition visualizations to log directory.
176pub fn set_save_draw(enable: bool) -> MaaResult<()> {
177 let mut val: u8 = if enable { 1 } else { 0 };
178 set_global_option(
179 sys::MaaGlobalOptionEnum_MaaGlobalOption_SaveDraw as i32,
180 &mut val as *mut _ as *mut _,
181 std::mem::size_of::<u8>() as u64,
182 )
183}
184
185/// Enable/disable saving screenshots on error.
186pub fn set_save_on_error(enable: bool) -> MaaResult<()> {
187 let mut val: u8 = if enable { 1 } else { 0 };
188 set_global_option(
189 sys::MaaGlobalOptionEnum_MaaGlobalOption_SaveOnError as i32,
190 &mut val as *mut _ as *mut _,
191 std::mem::size_of::<u8>() as u64,
192 )
193}
194
195/// Set JPEG quality for saved draw images (0-100, default 85).
196pub fn set_draw_quality(quality: i32) -> MaaResult<()> {
197 let mut val = quality;
198 set_global_option(
199 sys::MaaGlobalOptionEnum_MaaGlobalOption_DrawQuality as i32,
200 &mut val as *mut _ as *mut _,
201 std::mem::size_of::<i32>() as u64,
202 )
203}
204
205/// Set the recognition image cache limit (default 4096).
206pub fn set_reco_image_cache_limit(limit: u64) -> MaaResult<()> {
207 let mut val = limit;
208 set_global_option(
209 sys::MaaGlobalOptionEnum_MaaGlobalOption_RecoImageCacheLimit as i32,
210 &mut val as *mut _ as *mut _,
211 std::mem::size_of::<u64>() as u64,
212 )
213}
214
215/// Load a plugin from the specified path.
216pub fn load_plugin(path: &str) -> MaaResult<()> {
217 let c_path = CString::new(path)?;
218 let ret = unsafe { sys::MaaGlobalLoadPlugin(c_path.as_ptr()) };
219 common::check_bool(ret)
220}
221
222/// Loads the MaaFramework dynamic library.
223///
224/// You **must** call this function successfully before using any other APIs when the `dynamic`
225/// feature is enabled.
226///
227/// # Arguments
228///
229/// * `path` - Path to the dynamic library file (e.g., `MaaFramework.dll`, `libMaaFramework.so`).
230///
231/// # Errors
232///
233/// Returns an error if:
234/// * The library file cannot be found or loaded.
235/// * The library has already been loaded (multiple initialization is not supported).
236/// * Required symbols are missing from the library.
237///
238/// # Panics
239///
240/// Subsequent calls to any MaaFramework API will panic if the library has not been initialized.
241///
242/// # Safety
243///
244/// This function is `unsafe` because:
245/// * It executes arbitrary initialization code (e.g., `DllMain`) inside the loaded library.
246/// * The caller must ensure `path` points to a valid MaaFramework binary compatible with these bindings.
247#[cfg(feature = "dynamic")]
248pub fn load_library(path: &std::path::Path) -> Result<(), String> {
249 unsafe { sys::load_library(path) }
250}