Skip to main content

maa_framework/
agent_server.rs

1//! Agent server for hosting custom components.
2//!
3//! This module allows hosting custom recognition and action components
4//! in a separate process, which can be connected to by AgentClient.
5
6use crate::{callback, common, sys, MaaError, MaaResult};
7use std::ffi::CString;
8
9/// Static functions for AgentServer management.
10///
11/// AgentServer hosts custom recognitions and actions that can be
12/// accessed remotely by AgentClient instances.
13pub struct AgentServer;
14
15impl AgentServer {
16    /// Register a custom recognition with the AgentServer.
17    ///
18    /// The recognition will be available to connected AgentClients.
19    pub fn register_custom_recognition(
20        name: &str,
21        reco: Box<dyn crate::custom::CustomRecognition>,
22    ) -> MaaResult<()> {
23        let c_name = CString::new(name)?;
24        let reco_ptr = Box::into_raw(Box::new(reco));
25        let reco_ptr_void = reco_ptr as *mut std::ffi::c_void;
26
27        unsafe {
28            let ret = sys::MaaAgentServerRegisterCustomRecognition(
29                c_name.as_ptr(),
30                Some(crate::custom::custom_recognition_trampoline),
31                reco_ptr_void,
32            );
33            if ret == 0 {
34                let _ = Box::from_raw(reco_ptr);
35                return Err(MaaError::FrameworkError(0));
36            }
37        }
38
39        Ok(())
40    }
41
42    /// Register a custom action with the AgentServer.
43    ///
44    /// The action will be available to connected AgentClients.
45    pub fn register_custom_action(
46        name: &str,
47        action: Box<dyn crate::custom::CustomAction>,
48    ) -> MaaResult<()> {
49        let c_name = CString::new(name)?;
50        let action_ptr = Box::into_raw(Box::new(action));
51        let action_ptr_void = action_ptr as *mut std::ffi::c_void;
52
53        unsafe {
54            let ret = sys::MaaAgentServerRegisterCustomAction(
55                c_name.as_ptr(),
56                Some(crate::custom::custom_action_trampoline),
57                action_ptr_void,
58            );
59            if ret == 0 {
60                let _ = Box::from_raw(action_ptr);
61                return Err(MaaError::FrameworkError(0));
62            }
63        }
64        Ok(())
65    }
66
67    /// Add a resource event sink.
68    pub fn add_resource_sink<F>(callback: F) -> MaaResult<sys::MaaSinkId>
69    where
70        F: Fn(&str, &str) + Send + Sync + 'static,
71    {
72        let (cb, arg) = callback::EventCallback::new(callback);
73        let sink_id = unsafe { sys::MaaAgentServerAddResourceSink(cb, arg) };
74        if sink_id != 0 {
75            Ok(sink_id)
76        } else {
77            unsafe { callback::EventCallback::drop_callback(arg) };
78            Err(MaaError::FrameworkError(0))
79        }
80    }
81
82    /// Add a controller event sink.
83    pub fn add_controller_sink<F>(callback: F) -> MaaResult<sys::MaaSinkId>
84    where
85        F: Fn(&str, &str) + Send + Sync + 'static,
86    {
87        let (cb, arg) = callback::EventCallback::new(callback);
88        let sink_id = unsafe { sys::MaaAgentServerAddControllerSink(cb, arg) };
89        if sink_id != 0 {
90            Ok(sink_id)
91        } else {
92            unsafe { callback::EventCallback::drop_callback(arg) };
93            Err(MaaError::FrameworkError(0))
94        }
95    }
96
97    /// Add a tasker event sink.
98    pub fn add_tasker_sink<F>(callback: F) -> MaaResult<sys::MaaSinkId>
99    where
100        F: Fn(&str, &str) + Send + Sync + 'static,
101    {
102        let (cb, arg) = callback::EventCallback::new(callback);
103        let sink_id = unsafe { sys::MaaAgentServerAddTaskerSink(cb, arg) };
104        if sink_id != 0 {
105            Ok(sink_id)
106        } else {
107            unsafe { callback::EventCallback::drop_callback(arg) };
108            Err(MaaError::FrameworkError(0))
109        }
110    }
111
112    /// Add a context event sink.
113    pub fn add_context_sink<F>(callback: F) -> MaaResult<sys::MaaSinkId>
114    where
115        F: Fn(&str, &str) + Send + Sync + 'static,
116    {
117        let (cb, arg) = callback::EventCallback::new(callback);
118        let sink_id = unsafe { sys::MaaAgentServerAddContextSink(cb, arg) };
119        if sink_id != 0 {
120            Ok(sink_id)
121        } else {
122            unsafe { callback::EventCallback::drop_callback(arg) };
123            Err(MaaError::FrameworkError(0))
124        }
125    }
126
127    /// Start the AgentServer.
128    ///
129    /// # Arguments
130    /// * `identifier` - Connection identifier for clients to connect to
131    pub fn start_up(identifier: &str) -> MaaResult<()> {
132        let c_id = CString::new(identifier)?;
133        let ret = unsafe { sys::MaaAgentServerStartUp(c_id.as_ptr()) };
134        common::check_bool(ret)
135    }
136
137    /// Shut down the AgentServer.
138    pub fn shut_down() {
139        unsafe { sys::MaaAgentServerShutDown() }
140    }
141
142    /// Block until the server shuts down.
143    pub fn join() {
144        unsafe { sys::MaaAgentServerJoin() }
145    }
146
147    /// Detach the server to run in background.
148    pub fn detach() {
149        unsafe { sys::MaaAgentServerDetach() }
150    }
151}