MaaFw 4.4.0b1__py3-none-manylinux2014_x86_64.whl → 5.4.0__py3-none-manylinux2014_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of MaaFw might be problematic. Click here for more details.
- maa/agent/agent_server.py +221 -3
- maa/agent_client.py +170 -2
- maa/bin/libMaaAdbControlUnit.so +0 -0
- maa/bin/libMaaAgentClient.so +0 -0
- maa/bin/libMaaAgentServer.so +0 -0
- maa/bin/libMaaCustomControlUnit.so +0 -0
- maa/bin/libMaaFramework.so +0 -0
- maa/bin/libMaaToolkit.so +0 -0
- maa/bin/libMaaUtils.so +0 -0
- maa/bin/libc++.so.1 +0 -0
- maa/bin/libc++abi.so.1 +0 -0
- maa/bin/libfastdeploy_ppocr.so +0 -0
- maa/bin/libonnxruntime.so.1 +0 -0
- maa/bin/{libopencv_world4.so.408 → libopencv_world4.so.411} +0 -0
- maa/bin/libunwind.so.1 +0 -0
- maa/bin/plugins/libMaaPluginDemo.so +0 -0
- maa/buffer.py +168 -0
- maa/context.py +402 -10
- maa/controller.py +685 -44
- maa/custom_action.py +43 -0
- maa/custom_recognition.py +61 -9
- maa/define.py +450 -20
- maa/event_sink.py +103 -0
- maa/job.py +77 -1
- maa/library.py +118 -50
- maa/pipeline.py +509 -0
- maa/resource.py +430 -21
- maa/tasker.py +630 -90
- maa/toolkit.py +52 -91
- {maafw-4.4.0b1.dist-info → maafw-5.4.0.dist-info}/METADATA +90 -45
- maafw-5.4.0.dist-info/RECORD +35 -0
- {maafw-4.4.0b1.dist-info → maafw-5.4.0.dist-info}/WHEEL +1 -1
- maa/bin/libMaaDbgControlUnit.so +0 -0
- maa/notification_handler.py +0 -197
- maafw-4.4.0b1.dist-info/RECORD +0 -30
- {maafw-4.4.0b1.dist-info → maafw-5.4.0.dist-info}/licenses/LICENSE.md +0 -0
maa/resource.py
CHANGED
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
import ctypes
|
|
2
2
|
import pathlib
|
|
3
3
|
import json
|
|
4
|
-
from typing import
|
|
4
|
+
from typing import Optional, Union, List, Dict
|
|
5
|
+
from dataclasses import dataclass, field
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
import numpy
|
|
8
|
+
|
|
9
|
+
from .event_sink import EventSink, NotificationType
|
|
7
10
|
from .define import *
|
|
8
11
|
from .job import Job
|
|
9
12
|
from .library import Library
|
|
10
|
-
from .buffer import StringBuffer, StringListBuffer
|
|
13
|
+
from .buffer import StringBuffer, StringListBuffer, ImageBuffer
|
|
14
|
+
from .pipeline import JPipelineData, JPipelineParser
|
|
11
15
|
|
|
12
16
|
|
|
13
17
|
class Resource:
|
|
14
|
-
_notification_handler: Optional[NotificationHandler]
|
|
15
18
|
_handle: MaaResourceHandle
|
|
16
19
|
_own: bool
|
|
17
20
|
|
|
@@ -19,19 +22,24 @@ class Resource:
|
|
|
19
22
|
|
|
20
23
|
def __init__(
|
|
21
24
|
self,
|
|
22
|
-
notification_handler: Optional[NotificationHandler] = None,
|
|
23
25
|
handle: Optional[MaaResourceHandle] = None,
|
|
24
26
|
):
|
|
27
|
+
"""创建资源 / Create resource
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
handle: 可选的外部句柄 / Optional external handle
|
|
31
|
+
|
|
32
|
+
Raises:
|
|
33
|
+
RuntimeError: 如果创建失败
|
|
34
|
+
"""
|
|
35
|
+
|
|
25
36
|
self._set_api_properties()
|
|
26
37
|
|
|
27
38
|
if handle:
|
|
28
39
|
self._handle = handle
|
|
29
40
|
self._own = False
|
|
30
41
|
else:
|
|
31
|
-
self.
|
|
32
|
-
self._handle = Library.framework().MaaResourceCreate(
|
|
33
|
-
*NotificationHandler._gen_c_param(self._notification_handler)
|
|
34
|
-
)
|
|
42
|
+
self._handle = Library.framework().MaaResourceCreate()
|
|
35
43
|
self._own = True
|
|
36
44
|
|
|
37
45
|
if not self._handle:
|
|
@@ -45,20 +53,110 @@ class Resource:
|
|
|
45
53
|
Library.framework().MaaResourceDestroy(self._handle)
|
|
46
54
|
|
|
47
55
|
def post_bundle(self, path: Union[pathlib.Path, str]) -> Job:
|
|
48
|
-
|
|
56
|
+
"""异步加载资源 / Asynchronously load resources from path
|
|
57
|
+
|
|
58
|
+
这是一个异步操作,会立即返回一个 Job 对象
|
|
59
|
+
This is an asynchronous operation that immediately returns a Job object
|
|
60
|
+
|
|
61
|
+
Args:
|
|
62
|
+
path: 资源路径 / Resource path
|
|
63
|
+
|
|
64
|
+
Returns:
|
|
65
|
+
Job: 作业对象,可通过 status/wait 查询状态 / Job object, can query status via status/wait
|
|
66
|
+
"""
|
|
67
|
+
res_id = Library.framework().MaaResourcePostBundle(
|
|
49
68
|
self._handle, str(path).encode()
|
|
50
69
|
)
|
|
51
|
-
return Job(
|
|
70
|
+
return Job(res_id, self._status, self._wait)
|
|
71
|
+
|
|
72
|
+
def post_ocr_model(self, path: Union[pathlib.Path, str]) -> Job:
|
|
73
|
+
"""异步加载 OCR 模型 / Asynchronously load OCR model from path
|
|
74
|
+
|
|
75
|
+
这是一个异步操作,会立即返回一个 Job 对象
|
|
76
|
+
This is an asynchronous operation that immediately returns a Job object
|
|
77
|
+
|
|
78
|
+
Args:
|
|
79
|
+
path: OCR 模型目录路径 / OCR model directory path
|
|
80
|
+
|
|
81
|
+
Returns:
|
|
82
|
+
Job: 作业对象,可通过 status/wait 查询状态 / Job object, can query status via status/wait
|
|
83
|
+
"""
|
|
84
|
+
res_id = Library.framework().MaaResourcePostOcrModel(
|
|
85
|
+
self._handle, str(path).encode()
|
|
86
|
+
)
|
|
87
|
+
return Job(res_id, self._status, self._wait)
|
|
88
|
+
|
|
89
|
+
def post_pipeline(self, path: Union[pathlib.Path, str]) -> Job:
|
|
90
|
+
"""异步加载 Pipeline / Asynchronously load pipeline from path
|
|
91
|
+
|
|
92
|
+
这是一个异步操作,会立即返回一个 Job 对象
|
|
93
|
+
This is an asynchronous operation that immediately returns a Job object
|
|
94
|
+
|
|
95
|
+
支持加载目录或单个 json/jsonc 文件
|
|
96
|
+
Supports loading a directory or a single json/jsonc file
|
|
97
|
+
|
|
98
|
+
Args:
|
|
99
|
+
path: Pipeline 目录或文件路径 / Pipeline directory or file path
|
|
100
|
+
|
|
101
|
+
Returns:
|
|
102
|
+
Job: 作业对象,可通过 status/wait 查询状态 / Job object, can query status via status/wait
|
|
103
|
+
"""
|
|
104
|
+
res_id = Library.framework().MaaResourcePostPipeline(
|
|
105
|
+
self._handle, str(path).encode()
|
|
106
|
+
)
|
|
107
|
+
return Job(res_id, self._status, self._wait)
|
|
108
|
+
|
|
109
|
+
def post_image(self, path: Union[pathlib.Path, str]) -> Job:
|
|
110
|
+
"""异步加载图片资源 / Asynchronously load image resources from path
|
|
111
|
+
|
|
112
|
+
这是一个异步操作,会立即返回一个 Job 对象
|
|
113
|
+
This is an asynchronous operation that immediately returns a Job object
|
|
114
|
+
|
|
115
|
+
支持加载目录或单个图片文件
|
|
116
|
+
Supports loading a directory or a single image file
|
|
117
|
+
|
|
118
|
+
Args:
|
|
119
|
+
path: 图片目录或文件路径 / Image directory or file path
|
|
120
|
+
|
|
121
|
+
Returns:
|
|
122
|
+
Job: 作业对象,可通过 status/wait 查询状态 / Job object, can query status via status/wait
|
|
123
|
+
"""
|
|
124
|
+
res_id = Library.framework().MaaResourcePostImage(
|
|
125
|
+
self._handle, str(path).encode()
|
|
126
|
+
)
|
|
127
|
+
return Job(res_id, self._status, self._wait)
|
|
52
128
|
|
|
53
129
|
def override_pipeline(self, pipeline_override: Dict) -> bool:
|
|
130
|
+
"""覆盖 pipeline / Override pipeline_override
|
|
131
|
+
|
|
132
|
+
Args:
|
|
133
|
+
pipeline_override: 用于覆盖的 json / JSON for overriding
|
|
134
|
+
|
|
135
|
+
Returns:
|
|
136
|
+
bool: 是否成功 / Whether successful
|
|
137
|
+
"""
|
|
138
|
+
pipeline_json = json.dumps(pipeline_override, ensure_ascii=False)
|
|
139
|
+
|
|
54
140
|
return bool(
|
|
55
141
|
Library.framework().MaaResourceOverridePipeline(
|
|
56
142
|
self._handle,
|
|
57
|
-
|
|
143
|
+
pipeline_json.encode(),
|
|
58
144
|
)
|
|
59
145
|
)
|
|
60
146
|
|
|
61
147
|
def override_next(self, name: str, next_list: List[str]) -> bool:
|
|
148
|
+
"""覆盖任务的 next 列表 / Override the next list of task
|
|
149
|
+
|
|
150
|
+
注意:此方法会直接设置 next 列表,即使节点不存在也会创建
|
|
151
|
+
Note: This method directly sets the next list, creating the node if it doesn't exist
|
|
152
|
+
|
|
153
|
+
Args:
|
|
154
|
+
name: 任务名 / Task name
|
|
155
|
+
next_list: next 列表 / Next list
|
|
156
|
+
|
|
157
|
+
Returns:
|
|
158
|
+
bool: 总是返回 True / Always returns True
|
|
159
|
+
"""
|
|
62
160
|
list_buffer = StringListBuffer()
|
|
63
161
|
list_buffer.set(next_list)
|
|
64
162
|
|
|
@@ -67,14 +165,40 @@ class Resource:
|
|
|
67
165
|
self._handle, name.encode(), list_buffer._handle
|
|
68
166
|
)
|
|
69
167
|
)
|
|
70
|
-
|
|
71
|
-
def
|
|
168
|
+
|
|
169
|
+
def override_image(self, image_name: str, image: numpy.ndarray) -> bool:
|
|
170
|
+
"""覆盖图片 / Override the image corresponding to image_name
|
|
171
|
+
|
|
172
|
+
Args:
|
|
173
|
+
image_name: 图片名 / Image name
|
|
174
|
+
image: 图片数据 / Image data
|
|
175
|
+
|
|
176
|
+
Returns:
|
|
177
|
+
bool: 总是返回 True / Always returns True
|
|
178
|
+
"""
|
|
179
|
+
image_buffer = ImageBuffer()
|
|
180
|
+
image_buffer.set(image)
|
|
181
|
+
|
|
182
|
+
return bool(
|
|
183
|
+
Library.framework().MaaResourceOverrideImage(
|
|
184
|
+
self._handle, image_name.encode(), image_buffer._handle
|
|
185
|
+
)
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
def get_node_data(self, name: str) -> Optional[Dict]:
|
|
189
|
+
"""获取任务当前的定义 / Get the current definition of task
|
|
190
|
+
|
|
191
|
+
Args:
|
|
192
|
+
name: 任务名 / Task name
|
|
193
|
+
|
|
194
|
+
Returns:
|
|
195
|
+
Optional[Dict]: 任务定义字典,如果不存在则返回 None / Task definition dict, or None if not exists
|
|
196
|
+
"""
|
|
72
197
|
string_buffer = StringBuffer()
|
|
73
198
|
if not Library.framework().MaaResourceGetNodeData(
|
|
74
199
|
self._handle, name.encode(), string_buffer._handle
|
|
75
200
|
):
|
|
76
201
|
return None
|
|
77
|
-
|
|
78
202
|
data = string_buffer.get()
|
|
79
203
|
if not data:
|
|
80
204
|
return None
|
|
@@ -84,25 +208,80 @@ class Resource:
|
|
|
84
208
|
except json.JSONDecodeError:
|
|
85
209
|
return None
|
|
86
210
|
|
|
211
|
+
def get_node_object(self, name: str) -> Optional[JPipelineData]:
|
|
212
|
+
"""获取任务当前的定义(解析为对象) / Get the current definition of task (parsed as object)
|
|
213
|
+
|
|
214
|
+
Args:
|
|
215
|
+
name: 任务名 / Task name
|
|
216
|
+
|
|
217
|
+
Returns:
|
|
218
|
+
Optional[JPipelineData]: 任务定义对象,如果不存在则返回 None / Task definition object, or None if not exists
|
|
219
|
+
"""
|
|
220
|
+
node_data = self.get_node_data(name)
|
|
221
|
+
|
|
222
|
+
if not node_data:
|
|
223
|
+
return None
|
|
224
|
+
|
|
225
|
+
return JPipelineParser.parse_pipeline_data(node_data)
|
|
226
|
+
|
|
87
227
|
@property
|
|
88
228
|
def loaded(self) -> bool:
|
|
229
|
+
"""判断是否加载正常 / Check if resources loaded normally
|
|
230
|
+
|
|
231
|
+
Returns:
|
|
232
|
+
bool: 是否已加载 / Whether loaded
|
|
233
|
+
"""
|
|
89
234
|
return bool(Library.framework().MaaResourceLoaded(self._handle))
|
|
90
235
|
|
|
91
236
|
def clear(self) -> bool:
|
|
237
|
+
"""清除已加载内容 / Clear loaded content
|
|
238
|
+
|
|
239
|
+
如果资源正在加载中,此方法会失败
|
|
240
|
+
This method will fail if resources are currently loading
|
|
241
|
+
|
|
242
|
+
Returns:
|
|
243
|
+
bool: 成功返回 True,如果正在加载中则返回 False / Returns True on success, False if currently loading
|
|
244
|
+
"""
|
|
92
245
|
return bool(Library.framework().MaaResourceClear(self._handle))
|
|
93
246
|
|
|
94
247
|
def use_cpu(self) -> bool:
|
|
248
|
+
"""使用 CPU 进行推理 / Use CPU for inference
|
|
249
|
+
|
|
250
|
+
Returns:
|
|
251
|
+
bool: 是否成功 / Whether successful
|
|
252
|
+
"""
|
|
95
253
|
return self.set_inference(
|
|
96
254
|
MaaInferenceExecutionProviderEnum.CPU, MaaInferenceDeviceEnum.CPU
|
|
97
255
|
)
|
|
98
256
|
|
|
99
257
|
def use_directml(self, device_id: int = MaaInferenceDeviceEnum.Auto) -> bool:
|
|
258
|
+
"""使用 DirectML 进行推理 / Use DirectML for inference
|
|
259
|
+
|
|
260
|
+
Args:
|
|
261
|
+
device_id: 设备 id,默认为自动选择 / Device id, default is Auto
|
|
262
|
+
|
|
263
|
+
Returns:
|
|
264
|
+
bool: 是否成功 / Whether successful
|
|
265
|
+
"""
|
|
100
266
|
return self.set_inference(MaaInferenceExecutionProviderEnum.DirectML, device_id)
|
|
101
267
|
|
|
102
268
|
def use_coreml(self, coreml_flag: int = MaaInferenceDeviceEnum.Auto) -> bool:
|
|
269
|
+
"""使用 CoreML 进行推理 / Use CoreML for inference
|
|
270
|
+
|
|
271
|
+
Args:
|
|
272
|
+
coreml_flag: CoreML 标志,默认为自动选择 / CoreML flag, default is Auto
|
|
273
|
+
|
|
274
|
+
Returns:
|
|
275
|
+
bool: 是否成功 / Whether successful
|
|
276
|
+
"""
|
|
103
277
|
return self.set_inference(MaaInferenceExecutionProviderEnum.CoreML, coreml_flag)
|
|
104
278
|
|
|
105
279
|
def use_auto_ep(self) -> bool:
|
|
280
|
+
"""自动选择推理执行提供者 / Auto select inference execution provider
|
|
281
|
+
|
|
282
|
+
Returns:
|
|
283
|
+
bool: 是否成功 / Whether successful
|
|
284
|
+
"""
|
|
106
285
|
return self.set_inference(
|
|
107
286
|
MaaInferenceExecutionProviderEnum.Auto, MaaInferenceDeviceEnum.Auto
|
|
108
287
|
)
|
|
@@ -132,6 +311,14 @@ class Resource:
|
|
|
132
311
|
return self.use_auto_ep()
|
|
133
312
|
|
|
134
313
|
def custom_recognition(self, name: str):
|
|
314
|
+
"""自定义识别器装饰器 / Custom recognition decorator
|
|
315
|
+
|
|
316
|
+
Args:
|
|
317
|
+
name: 识别器名称,需与 Pipeline 中的 custom_recognition 字段匹配 / Recognition name, should match the custom_recognition field in Pipeline
|
|
318
|
+
|
|
319
|
+
Returns:
|
|
320
|
+
装饰器函数 / Decorator function
|
|
321
|
+
"""
|
|
135
322
|
|
|
136
323
|
def wrapper_recognition(recognition):
|
|
137
324
|
self.register_custom_recognition(name=name, recognition=recognition())
|
|
@@ -142,7 +329,15 @@ class Resource:
|
|
|
142
329
|
def register_custom_recognition(
|
|
143
330
|
self, name: str, recognition: "CustomRecognition" # type: ignore
|
|
144
331
|
) -> bool:
|
|
332
|
+
"""注册自定义识别器 / Register a custom recognizer
|
|
145
333
|
|
|
334
|
+
Args:
|
|
335
|
+
name: 名称 / Name
|
|
336
|
+
recognition: 自定义识别器 / Custom recognizer
|
|
337
|
+
|
|
338
|
+
Returns:
|
|
339
|
+
bool: 是否成功 / Whether successful
|
|
340
|
+
"""
|
|
146
341
|
# avoid gc
|
|
147
342
|
self._custom_recognition_holder[name] = recognition
|
|
148
343
|
|
|
@@ -156,6 +351,14 @@ class Resource:
|
|
|
156
351
|
)
|
|
157
352
|
|
|
158
353
|
def unregister_custom_recognition(self, name: str) -> bool:
|
|
354
|
+
"""移除自定义识别器 / Remove the custom recognizer
|
|
355
|
+
|
|
356
|
+
Args:
|
|
357
|
+
name: 名称 / Name
|
|
358
|
+
|
|
359
|
+
Returns:
|
|
360
|
+
bool: 是否成功 / Whether successful
|
|
361
|
+
"""
|
|
159
362
|
self._custom_recognition_holder.pop(name, None)
|
|
160
363
|
|
|
161
364
|
return bool(
|
|
@@ -166,6 +369,11 @@ class Resource:
|
|
|
166
369
|
)
|
|
167
370
|
|
|
168
371
|
def clear_custom_recognition(self) -> bool:
|
|
372
|
+
"""移除所有自定义识别器 / Remove all custom recognizers
|
|
373
|
+
|
|
374
|
+
Returns:
|
|
375
|
+
bool: 是否成功 / Whether successful
|
|
376
|
+
"""
|
|
169
377
|
self._custom_recognition_holder.clear()
|
|
170
378
|
|
|
171
379
|
return bool(
|
|
@@ -175,6 +383,14 @@ class Resource:
|
|
|
175
383
|
)
|
|
176
384
|
|
|
177
385
|
def custom_action(self, name: str):
|
|
386
|
+
"""自定义动作装饰器 / Custom action decorator
|
|
387
|
+
|
|
388
|
+
Args:
|
|
389
|
+
name: 动作名称,需与 Pipeline 中的 custom_action 字段匹配 / Action name, should match the custom_action field in Pipeline
|
|
390
|
+
|
|
391
|
+
Returns:
|
|
392
|
+
装饰器函数 / Decorator function
|
|
393
|
+
"""
|
|
178
394
|
|
|
179
395
|
def wrapper_action(action):
|
|
180
396
|
self.register_custom_action(name=name, action=action())
|
|
@@ -183,6 +399,15 @@ class Resource:
|
|
|
183
399
|
return wrapper_action
|
|
184
400
|
|
|
185
401
|
def register_custom_action(self, name: str, action: "CustomAction") -> bool: # type: ignore
|
|
402
|
+
"""注册自定义操作 / Register a custom action
|
|
403
|
+
|
|
404
|
+
Args:
|
|
405
|
+
name: 名称 / Name
|
|
406
|
+
action: 自定义操作 / Custom action
|
|
407
|
+
|
|
408
|
+
Returns:
|
|
409
|
+
bool: 是否成功 / Whether successful
|
|
410
|
+
"""
|
|
186
411
|
# avoid gc
|
|
187
412
|
self._custom_action_holder[name] = action
|
|
188
413
|
|
|
@@ -196,6 +421,14 @@ class Resource:
|
|
|
196
421
|
)
|
|
197
422
|
|
|
198
423
|
def unregister_custom_action(self, name: str) -> bool:
|
|
424
|
+
"""移除自定义操作 / Remove the custom action
|
|
425
|
+
|
|
426
|
+
Args:
|
|
427
|
+
name: 名称 / Name
|
|
428
|
+
|
|
429
|
+
Returns:
|
|
430
|
+
bool: 是否成功 / Whether successful
|
|
431
|
+
"""
|
|
199
432
|
self._custom_action_holder.pop(name, None)
|
|
200
433
|
|
|
201
434
|
return bool(
|
|
@@ -206,6 +439,11 @@ class Resource:
|
|
|
206
439
|
)
|
|
207
440
|
|
|
208
441
|
def clear_custom_action(self) -> bool:
|
|
442
|
+
"""移除所有自定义操作 / Remove all custom actions
|
|
443
|
+
|
|
444
|
+
Returns:
|
|
445
|
+
bool: 是否成功 / Whether successful
|
|
446
|
+
"""
|
|
209
447
|
self._custom_action_holder.clear()
|
|
210
448
|
|
|
211
449
|
return bool(
|
|
@@ -216,21 +454,103 @@ class Resource:
|
|
|
216
454
|
|
|
217
455
|
@property
|
|
218
456
|
def node_list(self) -> list[str]:
|
|
219
|
-
"""
|
|
220
|
-
|
|
457
|
+
"""获取任务列表 / Get task list
|
|
458
|
+
|
|
459
|
+
Returns:
|
|
460
|
+
list[str]: 任务名列表 / List of task names
|
|
461
|
+
|
|
462
|
+
Raises:
|
|
463
|
+
RuntimeError: 如果获取失败
|
|
221
464
|
"""
|
|
222
465
|
buffer = StringListBuffer()
|
|
223
466
|
if not Library.framework().MaaResourceGetNodeList(self._handle, buffer._handle):
|
|
224
467
|
raise RuntimeError("Failed to get node list.")
|
|
225
468
|
return buffer.get()
|
|
226
469
|
|
|
470
|
+
@property
|
|
471
|
+
def custom_recognition_list(self) -> list[str]:
|
|
472
|
+
"""获取已注册的自定义识别器列表 / Get registered custom recognizer list
|
|
473
|
+
|
|
474
|
+
Returns:
|
|
475
|
+
list[str]: 自定义识别器名列表 / List of custom recognizer names
|
|
476
|
+
|
|
477
|
+
Raises:
|
|
478
|
+
RuntimeError: 如果获取失败
|
|
479
|
+
"""
|
|
480
|
+
buffer = StringListBuffer()
|
|
481
|
+
if not Library.framework().MaaResourceGetCustomRecognitionList(
|
|
482
|
+
self._handle, buffer._handle
|
|
483
|
+
):
|
|
484
|
+
raise RuntimeError("Failed to get custom recognition list.")
|
|
485
|
+
return buffer.get()
|
|
486
|
+
|
|
487
|
+
@property
|
|
488
|
+
def custom_action_list(self) -> list[str]:
|
|
489
|
+
"""获取已注册的自定义操作列表 / Get registered custom action list
|
|
490
|
+
|
|
491
|
+
Returns:
|
|
492
|
+
list[str]: 自定义操作名列表 / List of custom action names
|
|
493
|
+
|
|
494
|
+
Raises:
|
|
495
|
+
RuntimeError: 如果获取失败
|
|
496
|
+
"""
|
|
497
|
+
buffer = StringListBuffer()
|
|
498
|
+
if not Library.framework().MaaResourceGetCustomActionList(
|
|
499
|
+
self._handle, buffer._handle
|
|
500
|
+
):
|
|
501
|
+
raise RuntimeError("Failed to get custom action list.")
|
|
502
|
+
return buffer.get()
|
|
503
|
+
|
|
227
504
|
@property
|
|
228
505
|
def hash(self) -> str:
|
|
506
|
+
"""获取资源 hash / Get resource hash
|
|
507
|
+
|
|
508
|
+
Returns:
|
|
509
|
+
str: 资源 hash / Resource hash
|
|
510
|
+
|
|
511
|
+
Raises:
|
|
512
|
+
RuntimeError: 如果获取失败
|
|
513
|
+
"""
|
|
229
514
|
buffer = StringBuffer()
|
|
230
515
|
if not Library.framework().MaaResourceGetHash(self._handle, buffer._handle):
|
|
231
516
|
raise RuntimeError("Failed to get hash.")
|
|
232
517
|
return buffer.get()
|
|
233
518
|
|
|
519
|
+
_sink_holder: Dict[int, "ResourceEventSink"] = {}
|
|
520
|
+
|
|
521
|
+
def add_sink(self, sink: "ResourceEventSink") -> Optional[int]:
|
|
522
|
+
"""添加资源事件监听器 / Add resource event listener
|
|
523
|
+
|
|
524
|
+
Args:
|
|
525
|
+
sink: 事件监听器 / Event sink
|
|
526
|
+
|
|
527
|
+
Returns:
|
|
528
|
+
Optional[int]: 监听器 id,失败返回 None / Listener id, or None if failed
|
|
529
|
+
"""
|
|
530
|
+
sink_id = int(
|
|
531
|
+
Library.framework().MaaResourceAddSink(
|
|
532
|
+
self._handle, *EventSink._gen_c_param(sink)
|
|
533
|
+
)
|
|
534
|
+
)
|
|
535
|
+
if sink_id == MaaInvalidId:
|
|
536
|
+
return None
|
|
537
|
+
|
|
538
|
+
self._sink_holder[sink_id] = sink
|
|
539
|
+
return sink_id
|
|
540
|
+
|
|
541
|
+
def remove_sink(self, sink_id: int) -> None:
|
|
542
|
+
"""移除资源事件监听器 / Remove resource event listener
|
|
543
|
+
|
|
544
|
+
Args:
|
|
545
|
+
sink_id: 监听器 id / Listener id
|
|
546
|
+
"""
|
|
547
|
+
Library.framework().MaaResourceRemoveSink(self._handle, sink_id)
|
|
548
|
+
self._sink_holder.pop(sink_id)
|
|
549
|
+
|
|
550
|
+
def clear_sinks(self) -> None:
|
|
551
|
+
"""清除所有资源事件监听器 / Clear all resource event listeners"""
|
|
552
|
+
Library.framework().MaaResourceClearSinks(self._handle)
|
|
553
|
+
|
|
234
554
|
### private ###
|
|
235
555
|
|
|
236
556
|
def set_inference(self, execution_provider: int, device_id: int) -> bool:
|
|
@@ -267,10 +587,7 @@ class Resource:
|
|
|
267
587
|
Resource._api_properties_initialized = True
|
|
268
588
|
|
|
269
589
|
Library.framework().MaaResourceCreate.restype = MaaResourceHandle
|
|
270
|
-
Library.framework().MaaResourceCreate.argtypes = [
|
|
271
|
-
MaaNotificationCallback,
|
|
272
|
-
ctypes.c_void_p,
|
|
273
|
-
]
|
|
590
|
+
Library.framework().MaaResourceCreate.argtypes = []
|
|
274
591
|
|
|
275
592
|
Library.framework().MaaResourceDestroy.restype = None
|
|
276
593
|
Library.framework().MaaResourceDestroy.argtypes = [MaaResourceHandle]
|
|
@@ -281,6 +598,24 @@ class Resource:
|
|
|
281
598
|
ctypes.c_char_p,
|
|
282
599
|
]
|
|
283
600
|
|
|
601
|
+
Library.framework().MaaResourcePostOcrModel.restype = MaaResId
|
|
602
|
+
Library.framework().MaaResourcePostOcrModel.argtypes = [
|
|
603
|
+
MaaResourceHandle,
|
|
604
|
+
ctypes.c_char_p,
|
|
605
|
+
]
|
|
606
|
+
|
|
607
|
+
Library.framework().MaaResourcePostPipeline.restype = MaaResId
|
|
608
|
+
Library.framework().MaaResourcePostPipeline.argtypes = [
|
|
609
|
+
MaaResourceHandle,
|
|
610
|
+
ctypes.c_char_p,
|
|
611
|
+
]
|
|
612
|
+
|
|
613
|
+
Library.framework().MaaResourcePostImage.restype = MaaResId
|
|
614
|
+
Library.framework().MaaResourcePostImage.argtypes = [
|
|
615
|
+
MaaResourceHandle,
|
|
616
|
+
ctypes.c_char_p,
|
|
617
|
+
]
|
|
618
|
+
|
|
284
619
|
Library.framework().MaaResourceStatus.restype = MaaStatus
|
|
285
620
|
Library.framework().MaaResourceStatus.argtypes = [
|
|
286
621
|
MaaResourceHandle,
|
|
@@ -312,6 +647,13 @@ class Resource:
|
|
|
312
647
|
MaaStringListBufferHandle,
|
|
313
648
|
]
|
|
314
649
|
|
|
650
|
+
Library.framework().MaaResourceOverrideImage.restype = MaaBool
|
|
651
|
+
Library.framework().MaaResourceOverrideImage.argtypes = [
|
|
652
|
+
MaaResourceHandle,
|
|
653
|
+
ctypes.c_char_p,
|
|
654
|
+
MaaImageBufferHandle,
|
|
655
|
+
]
|
|
656
|
+
|
|
315
657
|
Library.framework().MaaResourceGetNodeData.restype = MaaBool
|
|
316
658
|
Library.framework().MaaResourceGetNodeData.argtypes = [
|
|
317
659
|
MaaContextHandle,
|
|
@@ -376,3 +718,70 @@ class Resource:
|
|
|
376
718
|
MaaResourceHandle,
|
|
377
719
|
MaaStringListBufferHandle,
|
|
378
720
|
]
|
|
721
|
+
|
|
722
|
+
Library.framework().MaaResourceGetCustomRecognitionList.restype = MaaBool
|
|
723
|
+
Library.framework().MaaResourceGetCustomRecognitionList.argtypes = [
|
|
724
|
+
MaaResourceHandle,
|
|
725
|
+
MaaStringListBufferHandle,
|
|
726
|
+
]
|
|
727
|
+
|
|
728
|
+
Library.framework().MaaResourceGetCustomActionList.restype = MaaBool
|
|
729
|
+
Library.framework().MaaResourceGetCustomActionList.argtypes = [
|
|
730
|
+
MaaResourceHandle,
|
|
731
|
+
MaaStringListBufferHandle,
|
|
732
|
+
]
|
|
733
|
+
|
|
734
|
+
Library.framework().MaaResourceAddSink.restype = MaaSinkId
|
|
735
|
+
Library.framework().MaaResourceAddSink.argtypes = [
|
|
736
|
+
MaaResourceHandle,
|
|
737
|
+
MaaEventCallback,
|
|
738
|
+
ctypes.c_void_p,
|
|
739
|
+
]
|
|
740
|
+
|
|
741
|
+
Library.framework().MaaResourceRemoveSink.restype = None
|
|
742
|
+
Library.framework().MaaResourceRemoveSink.argtypes = [
|
|
743
|
+
MaaResourceHandle,
|
|
744
|
+
MaaSinkId,
|
|
745
|
+
]
|
|
746
|
+
|
|
747
|
+
Library.framework().MaaResourceClearSinks.restype = None
|
|
748
|
+
Library.framework().MaaResourceClearSinks.argtypes = [MaaResourceHandle]
|
|
749
|
+
|
|
750
|
+
|
|
751
|
+
class ResourceEventSink(EventSink):
|
|
752
|
+
|
|
753
|
+
@dataclass
|
|
754
|
+
class ResourceLoadingDetail:
|
|
755
|
+
res_id: int
|
|
756
|
+
path: str
|
|
757
|
+
type: str
|
|
758
|
+
hash: str
|
|
759
|
+
|
|
760
|
+
def on_resource_loading(
|
|
761
|
+
self,
|
|
762
|
+
resource: Resource,
|
|
763
|
+
noti_type: NotificationType,
|
|
764
|
+
detail: ResourceLoadingDetail,
|
|
765
|
+
):
|
|
766
|
+
pass
|
|
767
|
+
|
|
768
|
+
def on_raw_notification(self, resource: Resource, msg: str, details: dict):
|
|
769
|
+
pass
|
|
770
|
+
|
|
771
|
+
def _on_raw_notification(self, handle: ctypes.c_void_p, msg: str, details: dict):
|
|
772
|
+
|
|
773
|
+
resource = Resource(handle=handle)
|
|
774
|
+
self.on_raw_notification(resource, msg, details)
|
|
775
|
+
|
|
776
|
+
noti_type = EventSink._notification_type(msg)
|
|
777
|
+
if msg.startswith("Resource.Loading"):
|
|
778
|
+
detail = self.ResourceLoadingDetail(
|
|
779
|
+
res_id=details["res_id"],
|
|
780
|
+
path=details["path"],
|
|
781
|
+
type=details.get("type", "Bundle"),
|
|
782
|
+
hash=details["hash"],
|
|
783
|
+
)
|
|
784
|
+
self.on_resource_loading(resource, noti_type, detail)
|
|
785
|
+
|
|
786
|
+
else:
|
|
787
|
+
self.on_unknown_notification(resource, msg, details)
|