From 686d312ec18db9defe2d29d0bb0c0dc344c0f990 Mon Sep 17 00:00:00 2001 From: MistEO Date: Sun, 3 Dec 2023 21:26:17 +0800 Subject: [PATCH 01/23] =?UTF-8?q?feat:=20=E5=AE=8C=E6=88=90exec=5Fagent?= =?UTF-8?q?=E6=B3=A8=E5=86=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExecAgent/MaaToolKitExecAgent.h | 24 ++++ include/MaaToolKit/MaaToolKitAPI.h | 1 + include/MaaToolKit/MaaToolKitDef.h | 11 ++ source/MaaToolKit/API/MaaToolKitExecAgent.cpp | 128 ++++++++++++++++++ .../MaaToolKit/ExecAgent/ActionExecAgent.cpp | 35 +++++ source/MaaToolKit/ExecAgent/ActionExecAgent.h | 31 +++++ source/MaaToolKit/ExecAgent/ExecAgentBase.cpp | 76 +++++++++++ source/MaaToolKit/ExecAgent/ExecAgentBase.h | 36 +++++ source/MaaToolKit/ExecAgent/ExecAgentType.h | 54 ++++++++ .../ExecAgent/RecognizerExecAgent.cpp | 33 +++++ .../ExecAgent/RecognizerExecAgent.h | 33 +++++ 11 files changed, 462 insertions(+) create mode 100644 include/MaaToolKit/ExecAgent/MaaToolKitExecAgent.h create mode 100644 source/MaaToolKit/API/MaaToolKitExecAgent.cpp create mode 100644 source/MaaToolKit/ExecAgent/ActionExecAgent.cpp create mode 100644 source/MaaToolKit/ExecAgent/ActionExecAgent.h create mode 100644 source/MaaToolKit/ExecAgent/ExecAgentBase.cpp create mode 100644 source/MaaToolKit/ExecAgent/ExecAgentBase.h create mode 100644 source/MaaToolKit/ExecAgent/ExecAgentType.h create mode 100644 source/MaaToolKit/ExecAgent/RecognizerExecAgent.cpp create mode 100644 source/MaaToolKit/ExecAgent/RecognizerExecAgent.h diff --git a/include/MaaToolKit/ExecAgent/MaaToolKitExecAgent.h b/include/MaaToolKit/ExecAgent/MaaToolKitExecAgent.h new file mode 100644 index 000000000..5566608bb --- /dev/null +++ b/include/MaaToolKit/ExecAgent/MaaToolKitExecAgent.h @@ -0,0 +1,24 @@ +#pragma once + +#include "../MaaToolKitDef.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + MaaBool MAA_TOOLKIT_API MaaToolKitRegisterCustomRecognizerExecutor( // + MaaInstanceHandle handle, MaaStringView recognizer_name, MaaStringView recognizer_exec_path, + MaaStringView recognizer_exec_param_json, MaaToolKitExecAgentArgvTransferMode argv_mode); + MaaBool MAA_TOOLKIT_API MaaToolKitUnregisterCustomRecognizerExecutor( // + MaaInstanceHandle handle, MaaStringView recognizer_name); + + MaaBool MAA_TOOLKIT_API MaaToolKitRegisterCustomActionExecutor( // + MaaInstanceHandle handle, MaaStringView action_name, MaaStringView action_exec_path, + MaaStringView action_exec_param_json, MaaToolKitExecAgentArgvTransferMode argv_mode); + MaaBool MAA_TOOLKIT_API MaaToolKitUnregisterCustomActionExecutor( // + MaaInstanceHandle handle, MaaStringView action_name); + +#ifdef __cplusplus +} +#endif diff --git a/include/MaaToolKit/MaaToolKitAPI.h b/include/MaaToolKit/MaaToolKitAPI.h index 16dc43ba8..15030d904 100644 --- a/include/MaaToolKit/MaaToolKitAPI.h +++ b/include/MaaToolKit/MaaToolKitAPI.h @@ -4,4 +4,5 @@ #include "Config/MaaToolKitConfig.h" #include "Device/MaaToolKitDevice.h" +#include "ExecAgent/MaaToolKitExecAgent.h" #include "Win32/MaaToolKitWin32Window.h" diff --git a/include/MaaToolKit/MaaToolKitDef.h b/include/MaaToolKit/MaaToolKitDef.h index d34bafda5..065d94e2e 100644 --- a/include/MaaToolKit/MaaToolKitDef.h +++ b/include/MaaToolKit/MaaToolKitDef.h @@ -7,3 +7,14 @@ typedef struct MaaToolKitConfigAPI* MaaToolKitConfigHandle; struct MaaToolKitTaskAPI; typedef struct MaaToolKitTaskAPI* MaaToolKitTaskHandle; + +typedef int32_t MaaToolKitExecAgentArgvTransferMode; +enum MaaToolKitExecAgentArgvTransferModeEnum +{ + MaaToolKitExecAgentArgvTransferMode_Text_StdIO = 1, + // MaaToolKitExecAgentArgvTransferMode_Text_FileIO = 2, + MaaToolKitExecAgentArgvTransferMode_Text_Mask = 0xFF, + + MaaToolKitExecAgentArgvTransferMode_Image_FileIO = 1 << 8, + MaaToolKitExecAgentArgvTransferMode_Image_Mask = 0xFF00, +}; diff --git a/source/MaaToolKit/API/MaaToolKitExecAgent.cpp b/source/MaaToolKit/API/MaaToolKitExecAgent.cpp new file mode 100644 index 000000000..62eb902b8 --- /dev/null +++ b/source/MaaToolKit/API/MaaToolKitExecAgent.cpp @@ -0,0 +1,128 @@ +#include "MaaToolKit/ExecAgent/MaaToolKitExecAgent.h" + +#include + +#include + +#include "ExecAgent/ActionExecAgent.h" +#include "ExecAgent/RecognizerExecAgent.h" +#include "Utils/Logger.h" + +using namespace MAA_TOOLKIT_NS; + +enum class ExecutorType +{ + Recognizer, + Action, +}; +std::ostream& operator<<(std::ostream& os, ExecutorType type) +{ + switch (type) { + case ExecutorType::Recognizer: + os << "Recognizer"; + break; + case ExecutorType::Action: + os << "Action"; + break; + } + return os; +} + +MaaBool RegisterExecutor(ExecutorType type, MaaInstanceHandle handle, MaaStringView name, MaaStringView exec_path, + MaaStringView exec_param_json, MaaToolKitExecAgentArgvTransferMode argv_mode) +{ + LogFunc << VAR(type) << VAR_VOIDP(handle) << VAR(name) << VAR(exec_path) << VAR(exec_param_json) << VAR(argv_mode); + + if (!handle) { + LogError << "handle is null"; + return false; + } + if (std::string_view(name).empty()) { + LogError << "name is empty"; + return false; + } + + auto path = MAA_NS::path(exec_path); + if (!std::filesystem::exists(path)) { + LogError << "exec path not exists:" << path; + return false; + } + + auto params_opt = json::parse(exec_param_json); + if (!params_opt) { + LogError << "exec param json parse failed:" << exec_param_json; + return false; + } + if (!params_opt->is_array() || + !MAA_RNS::ranges::all_of(params_opt->as_array(), [](const auto& v) { return v.is_string(); })) { + LogError << "exec param json is not array of string:" << exec_param_json; + return false; + } + auto params = params_opt->to_vector(); + + TextTransferMode text_mode = + static_cast(MaaToolKitExecAgentArgvTransferMode_Text_Mask & argv_mode); + ImageTransferMode image_mode = + static_cast(MaaToolKitExecAgentArgvTransferMode_Image_Mask & argv_mode); + + switch (type) { + case ExecutorType::Recognizer: + return RecognizerExecAgent::get_instance().register_executor( // + handle, name, std::move(path), std::move(params), text_mode, image_mode); + case ExecutorType::Action: + return ActionExecAgent::get_instance().register_executor( // + handle, name, std::move(path), std::move(params), text_mode, image_mode); + } + + return false; +} + +MaaBool UnregisterExecutor(ExecutorType type, MaaInstanceHandle handle, MaaStringView name) +{ + LogFunc << VAR(type) << VAR_VOIDP(handle) << VAR(name); + + if (!handle) { + LogError << "handle is null"; + return false; + } + if (std::string_view(name).empty()) { + LogError << "name is empty"; + return false; + } + + switch (type) { + case ExecutorType::Recognizer: + return RecognizerExecAgent::get_instance().unregister_executor(handle, name); + + case ExecutorType::Action: + return ActionExecAgent::get_instance().unregister_executor(handle, name); + } + + return false; +} + +MaaBool MaaToolKitRegisterCustomRecognizerExecutor( // + MaaInstanceHandle handle, MaaStringView recognizer_name, MaaStringView recognizer_exec_path, + MaaStringView recognizer_exec_param_json, MaaToolKitExecAgentArgvTransferMode argv_mode) +{ + return RegisterExecutor(ExecutorType::Recognizer, handle, recognizer_name, recognizer_exec_path, + recognizer_exec_param_json, argv_mode); +} + +MaaBool MaaToolKitUnregisterCustomRecognizerExecutor(MaaInstanceHandle handle, MaaStringView recognizer_name) +{ + return UnregisterExecutor(ExecutorType::Recognizer, handle, recognizer_name); +} + +MaaBool MaaToolKitRegisterCustomActionExecutor( // + MaaInstanceHandle handle, MaaStringView action_name, MaaStringView action_exec_path, + MaaStringView action_exec_param_json, MaaToolKitExecAgentArgvTransferMode argv_mode) +{ + return RegisterExecutor(ExecutorType::Action, handle, action_name, action_exec_path, action_exec_param_json, + argv_mode); +} + +MaaBool MaaToolKitUnregisterCustomActionExecutor(MaaInstanceHandle handle, MaaStringView action_name) +{ + return UnregisterExecutor(ExecutorType::Action, handle, action_name); +} diff --git a/source/MaaToolKit/ExecAgent/ActionExecAgent.cpp b/source/MaaToolKit/ExecAgent/ActionExecAgent.cpp new file mode 100644 index 000000000..c9211c029 --- /dev/null +++ b/source/MaaToolKit/ExecAgent/ActionExecAgent.cpp @@ -0,0 +1,35 @@ +#include "ActionExecAgent.h" + +#include + +#include "MaaFramework/MaaAPI.h" +#include "Utils/Logger.h" + +MAA_TOOLKIT_NS_BEGIN + +ActionExecAgent::ActionExecAgent() +{ + custom_action_.run = &ActionExecAgent::action_run; + custom_action_.stop = &ActionExecAgent::action_stop; +} + +bool ActionExecAgent::register_for_maa_inst(MaaInstanceHandle handle, std::string_view name) +{ + return MaaRegisterCustomAction(handle, name.data(), &custom_action_, this); +} + +bool ActionExecAgent::unregister_for_maa_inst(MaaInstanceHandle handle, std::string_view name) +{ + return MaaUnregisterCustomAction(handle, name.data()); +} + +MaaBool ActionExecAgent::action_run(MaaSyncContextHandle sync_context, MaaStringView task_name, + MaaStringView custom_action_param, MaaRectHandle cur_box, + MaaStringView cur_rec_detail, MaaTransparentArg action_arg) +{ + return MaaBool(); +} + +void ActionExecAgent::action_stop(MaaTransparentArg action_arg) {} + +MAA_TOOLKIT_NS_END diff --git a/source/MaaToolKit/ExecAgent/ActionExecAgent.h b/source/MaaToolKit/ExecAgent/ActionExecAgent.h new file mode 100644 index 000000000..64a71a5b7 --- /dev/null +++ b/source/MaaToolKit/ExecAgent/ActionExecAgent.h @@ -0,0 +1,31 @@ +#pragma once + +#include "Conf/Conf.h" +#include "ExecAgentBase.h" + +#include "MaaFramework/Task/MaaCustomAction.h" +#include "Utils/SingletonHolder.hpp" + +MAA_TOOLKIT_NS_BEGIN + +class ActionExecAgent final : public ExecAgentBase, public SingletonHolder +{ +public: + ActionExecAgent(); + virtual ~ActionExecAgent() = default; + +private: // from ExecAgentBase + virtual bool register_for_maa_inst(MaaInstanceHandle handle, std::string_view name) override; + virtual bool unregister_for_maa_inst(MaaInstanceHandle handle, std::string_view name) override; + +private: // for MaaCustomActionAPI + static MaaBool action_run(MaaSyncContextHandle sync_context, MaaStringView task_name, + MaaStringView custom_action_param, MaaRectHandle cur_box, MaaStringView cur_rec_detail, + MaaTransparentArg action_arg); + static void action_stop(MaaTransparentArg action_arg); + +private: + MaaCustomActionAPI custom_action_; +}; + +MAA_TOOLKIT_NS_END diff --git a/source/MaaToolKit/ExecAgent/ExecAgentBase.cpp b/source/MaaToolKit/ExecAgent/ExecAgentBase.cpp new file mode 100644 index 000000000..ee4f1cb04 --- /dev/null +++ b/source/MaaToolKit/ExecAgent/ExecAgentBase.cpp @@ -0,0 +1,76 @@ +#include "ExecAgentBase.h" +#include "MaaFramework/MaaAPI.h" +#include "Utils/Logger.h" + +MAA_TOOLKIT_NS_BEGIN + +bool ExecAgentBase::register_executor(MaaInstanceHandle handle, std::string_view name, std::filesystem::path exec_path, + std::vector exec_params, TextTransferMode text_mode, + ImageTransferMode image_mode) +{ + LogFunc << VAR_VOIDP(handle) << VAR(name) << VAR(exec_path) << VAR(exec_params) << VAR(text_mode) + << VAR(image_mode); + + bool registered = register_for_maa_inst(handle, name); + if (!registered) { + LogError << "register failed" << VAR(name); + return false; + } + + Executor executor { + .handle_uuid = handle_uuid(handle), + .name = std::string(name), + .exec_path = std::move(exec_path), + .exec_params = std::move(exec_params), + .text_mode = text_mode, + .image_mode = image_mode, + }; + + bool inserted = executors_.try_emplace(executor.name, std::move(executor)).second; + if (!inserted) { + LogError << "executor already registered: " << executor.name; + return false; + } + + return true; +} + +bool ExecAgentBase::unregister_executor(MaaInstanceHandle handle, std::string_view name) +{ + LogFunc << VAR_VOIDP(handle) << VAR(name); + + std::string name_str(name); + + bool ret = unregister_for_maa_inst(handle, name); + ret = executors_.erase(name_str) > 0 && ret; + + return ret; +} + +std::string ExecAgentBase::handle_uuid(MaaInstanceHandle handle) +{ + if (!handle) { + return {}; + } + + for (const auto& [uuid, h] : handles_) { + if (h == handle) { + return uuid; + } + } + + std::string uuid = std::to_string(reinterpret_cast(handle)); + handles_.emplace(uuid, handle); + return uuid; +} + +MaaInstanceHandle ExecAgentBase::uuid_handle(const std::string& uuid) const +{ + auto it = handles_.find(uuid); + if (it == handles_.end()) { + return nullptr; + } + return it->second; +} + +MAA_TOOLKIT_NS_END diff --git a/source/MaaToolKit/ExecAgent/ExecAgentBase.h b/source/MaaToolKit/ExecAgent/ExecAgentBase.h new file mode 100644 index 000000000..742e9f5bb --- /dev/null +++ b/source/MaaToolKit/ExecAgent/ExecAgentBase.h @@ -0,0 +1,36 @@ +#pragma once + +#include "Conf/Conf.h" + +#include +#include + +#include "ExecAgentType.h" +#include "MaaFramework/MaaDef.h" + +MAA_TOOLKIT_NS_BEGIN + +class ExecAgentBase +{ +public: + virtual ~ExecAgentBase() = default; + + bool register_executor(MaaInstanceHandle handle, std::string_view name, std::filesystem::path exec_path, + std::vector exec_params, TextTransferMode text_mode, + ImageTransferMode image_mode); + bool unregister_executor(MaaInstanceHandle handle, std::string_view name); + +protected: + virtual bool register_for_maa_inst(MaaInstanceHandle handle, std::string_view name) = 0; + virtual bool unregister_for_maa_inst(MaaInstanceHandle handle, std::string_view name) = 0; + +protected: + std::string handle_uuid(MaaInstanceHandle handle); + MaaInstanceHandle uuid_handle(const std::string& uuid) const; + +protected: + std::unordered_map executors_; + std::unordered_map handles_; +}; + +MAA_TOOLKIT_NS_END diff --git a/source/MaaToolKit/ExecAgent/ExecAgentType.h b/source/MaaToolKit/ExecAgent/ExecAgentType.h new file mode 100644 index 000000000..fc96fae6b --- /dev/null +++ b/source/MaaToolKit/ExecAgent/ExecAgentType.h @@ -0,0 +1,54 @@ +#pragma once + +#include "Conf/Conf.h" + +#include +#include +#include +#include + +MAA_TOOLKIT_NS_BEGIN + +enum class TextTransferMode +{ + StdIO, + FileIO, +}; +inline std::ostream& operator<<(std::ostream& os, TextTransferMode mode) +{ + switch (mode) { + case TextTransferMode::StdIO: + os << "StdIO"; + break; + case TextTransferMode::FileIO: + os << "FileIO"; + break; + } + return os; +} + +enum class ImageTransferMode +{ + FileIO, +}; +inline std::ostream& operator<<(std::ostream& os, ImageTransferMode mode) +{ + switch (mode) { + case ImageTransferMode::FileIO: + os << "FileIO"; + break; + } + return os; +} + +struct Executor +{ + std::string handle_uuid; + std::string name; + std::filesystem::path exec_path; + std::vector exec_params; + TextTransferMode text_mode; + ImageTransferMode image_mode; +}; + +MAA_TOOLKIT_NS_END diff --git a/source/MaaToolKit/ExecAgent/RecognizerExecAgent.cpp b/source/MaaToolKit/ExecAgent/RecognizerExecAgent.cpp new file mode 100644 index 000000000..a3b20f694 --- /dev/null +++ b/source/MaaToolKit/ExecAgent/RecognizerExecAgent.cpp @@ -0,0 +1,33 @@ +#include "RecognizerExecAgent.h" + +#include + +#include "MaaFramework/MaaAPI.h" +#include "Utils/Logger.h" + +MAA_TOOLKIT_NS_BEGIN + +RecognizerExecAgent::RecognizerExecAgent() +{ + custom_recognizer_.analyze = &RecognizerExecAgent::recognizer_analyze; +} + +bool RecognizerExecAgent::register_for_maa_inst(MaaInstanceHandle handle, std::string_view name) +{ + return MaaRegisterCustomRecognizer(handle, name.data(), &custom_recognizer_, this); +} + +bool RecognizerExecAgent::unregister_for_maa_inst(MaaInstanceHandle handle, std::string_view name) +{ + return MaaUnregisterCustomRecognizer(handle, name.data()); +} + +MaaBool RecognizerExecAgent::recognizer_analyze(MaaSyncContextHandle sync_context, const MaaImageBufferHandle image, + MaaStringView task_name, MaaStringView custom_recognition_param, + MaaTransparentArg recognizer_arg, MaaRectHandle out_box, + MaaStringBufferHandle out_detail) +{ + return MaaBool(); +} + +MAA_TOOLKIT_NS_END diff --git a/source/MaaToolKit/ExecAgent/RecognizerExecAgent.h b/source/MaaToolKit/ExecAgent/RecognizerExecAgent.h new file mode 100644 index 000000000..7585177d9 --- /dev/null +++ b/source/MaaToolKit/ExecAgent/RecognizerExecAgent.h @@ -0,0 +1,33 @@ +#pragma once + +#include "Conf/Conf.h" +#include "ExecAgentBase.h" + +#include "MaaFramework/Task/MaaCustomRecognizer.h" +#include "Utils/SingletonHolder.hpp" + +MAA_TOOLKIT_NS_BEGIN + +class RecognizerExecAgent final : public ExecAgentBase, public SingletonHolder +{ +public: + RecognizerExecAgent(); + virtual ~RecognizerExecAgent() = default; + +protected: // from ExecAgentBase + virtual bool register_for_maa_inst(MaaInstanceHandle handle, std::string_view name) override; + virtual bool unregister_for_maa_inst(MaaInstanceHandle handle, std::string_view name) override; + +private: + // for MaaCustomRecognizerAPI + static MaaBool recognizer_analyze( // + MaaSyncContextHandle sync_context, const MaaImageBufferHandle image, MaaStringView task_name, + MaaStringView custom_recognition_param, MaaTransparentArg recognizer_arg, + /*out*/ MaaRectHandle out_box, + /*out*/ MaaStringBufferHandle out_detail); + +private: + MaaCustomRecognizerAPI custom_recognizer_; +}; + +MAA_TOOLKIT_NS_END From cd0eff28001bec208ffe8634d5354e47843e838a Mon Sep 17 00:00:00 2001 From: MistEO Date: Sun, 3 Dec 2023 21:47:18 +0800 Subject: [PATCH 02/23] =?UTF-8?q?feat:=20exec=5Fagent=20=E4=BB=8E=20c=20ap?= =?UTF-8?q?i=20=E5=88=B0=20impl=20=E7=9A=84=E8=B0=83=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/MaaFramework/Utility/MaaBuffer.h | 2 + source/MaaFramework/API/MaaBuffer.cpp | 26 ++++++++--- .../MaaToolKit/ExecAgent/ActionExecAgent.cpp | 37 ++++++++++++--- source/MaaToolKit/ExecAgent/ActionExecAgent.h | 16 ++++--- .../ExecAgent/RecognizerExecAgent.cpp | 45 ++++++++++++++++--- .../ExecAgent/RecognizerExecAgent.h | 13 +++++- 6 files changed, 114 insertions(+), 25 deletions(-) diff --git a/include/MaaFramework/Utility/MaaBuffer.h b/include/MaaFramework/Utility/MaaBuffer.h index 5f821c132..a7073208b 100644 --- a/include/MaaFramework/Utility/MaaBuffer.h +++ b/include/MaaFramework/Utility/MaaBuffer.h @@ -42,6 +42,8 @@ extern "C" int32_t MAA_FRAMEWORK_API MaaGetRectY(MaaRectHandle handle); int32_t MAA_FRAMEWORK_API MaaGetRectW(MaaRectHandle handle); int32_t MAA_FRAMEWORK_API MaaGetRectH(MaaRectHandle handle); + + MaaBool MAA_FRAMEWORK_API MaaSetRect(MaaRectHandle handle, int32_t x, int32_t y, int32_t w, int32_t h); MaaBool MAA_FRAMEWORK_API MaaSetRectX(MaaRectHandle handle, int32_t value); MaaBool MAA_FRAMEWORK_API MaaSetRectY(MaaRectHandle handle, int32_t value); MaaBool MAA_FRAMEWORK_API MaaSetRectW(MaaRectHandle handle, int32_t value); diff --git a/source/MaaFramework/API/MaaBuffer.cpp b/source/MaaFramework/API/MaaBuffer.cpp index 2bd5b40ed..2dd8c165b 100644 --- a/source/MaaFramework/API/MaaBuffer.cpp +++ b/source/MaaFramework/API/MaaBuffer.cpp @@ -97,7 +97,7 @@ void MaaDestroyImageBuffer(MaaImageBufferHandle handle) delete handle; } -void* MaaGetImageRawData(MaaImageBufferHandle handle) +MaaImageRawData MaaGetImageRawData(MaaImageBufferHandle handle) { if (!handle) { LogError << "handle is null"; @@ -176,7 +176,7 @@ MaaBool MaaSetImageRawData(MaaImageBufferHandle handle, MaaImageRawData data, in return true; } -uint8_t* MaaGetImageEncoded(MaaImageBufferHandle handle) +MaaImageEncodedData MaaGetImageEncoded(MaaImageBufferHandle handle) { if (!handle) { LogError << "handle is null"; @@ -268,11 +268,25 @@ int32_t MaaGetRectH(MaaRectHandle handle) return handle->height; } +MaaBool MaaSetRect(MaaRectHandle handle, int32_t x, int32_t y, int32_t w, int32_t h) +{ + if (!handle) { + LogError << "handle is null"; + return false; + } + + handle->x = x; + handle->y = y; + handle->width = w; + handle->height = h; + return true; +} + MaaBool MaaSetRectX(MaaRectHandle handle, int32_t value) { if (!handle) { LogError << "handle is null"; - return 0; + return false; } handle->x = value; @@ -283,7 +297,7 @@ MaaBool MaaSetRectY(MaaRectHandle handle, int32_t value) { if (!handle) { LogError << "handle is null"; - return 0; + return false; } handle->y = value; @@ -294,7 +308,7 @@ MaaBool MaaSetRectW(MaaRectHandle handle, int32_t value) { if (!handle) { LogError << "handle is null"; - return 0; + return false; } handle->width = value; @@ -305,7 +319,7 @@ MaaBool MaaSetRectH(MaaRectHandle handle, int32_t value) { if (!handle) { LogError << "handle is null"; - return 0; + return false; } handle->height = value; diff --git a/source/MaaToolKit/ExecAgent/ActionExecAgent.cpp b/source/MaaToolKit/ExecAgent/ActionExecAgent.cpp index c9211c029..8638667b0 100644 --- a/source/MaaToolKit/ExecAgent/ActionExecAgent.cpp +++ b/source/MaaToolKit/ExecAgent/ActionExecAgent.cpp @@ -9,8 +9,8 @@ MAA_TOOLKIT_NS_BEGIN ActionExecAgent::ActionExecAgent() { - custom_action_.run = &ActionExecAgent::action_run; - custom_action_.stop = &ActionExecAgent::action_stop; + custom_action_.run = &ActionExecAgent::maa_api_run; + custom_action_.stop = &ActionExecAgent::maa_api_stop; } bool ActionExecAgent::register_for_maa_inst(MaaInstanceHandle handle, std::string_view name) @@ -23,13 +23,36 @@ bool ActionExecAgent::unregister_for_maa_inst(MaaInstanceHandle handle, std::str return MaaUnregisterCustomAction(handle, name.data()); } -MaaBool ActionExecAgent::action_run(MaaSyncContextHandle sync_context, MaaStringView task_name, - MaaStringView custom_action_param, MaaRectHandle cur_box, - MaaStringView cur_rec_detail, MaaTransparentArg action_arg) +bool ActionExecAgent::run(MaaSyncContextHandle sync_context, std::string_view task_name, + std::string_view custom_action_param, MaaRectHandle cur_box, std::string_view cur_rec_detail) { - return MaaBool(); + return false; } -void ActionExecAgent::action_stop(MaaTransparentArg action_arg) {} +void ActionExecAgent::stop() {} + +MaaBool ActionExecAgent::maa_api_run(MaaSyncContextHandle sync_context, MaaStringView task_name, + MaaStringView custom_action_param, MaaRectHandle cur_box, + MaaStringView cur_rec_detail, MaaTransparentArg action_arg) +{ + auto* self = static_cast(action_arg); + if (!self) { + LogError << "action_arg is nullptr"; + return false; + } + + return self->run(sync_context, task_name, custom_action_param, cur_box, cur_rec_detail); +} + +void ActionExecAgent::maa_api_stop(MaaTransparentArg action_arg) +{ + auto* self = static_cast(action_arg); + if (!self) { + LogError << "action_arg is nullptr"; + return; + } + + self->stop(); +} MAA_TOOLKIT_NS_END diff --git a/source/MaaToolKit/ExecAgent/ActionExecAgent.h b/source/MaaToolKit/ExecAgent/ActionExecAgent.h index 64a71a5b7..62707bb93 100644 --- a/source/MaaToolKit/ExecAgent/ActionExecAgent.h +++ b/source/MaaToolKit/ExecAgent/ActionExecAgent.h @@ -18,11 +18,17 @@ class ActionExecAgent final : public ExecAgentBase, public SingletonHolder RecognizerExecAgent::analyze( + MaaSyncContextHandle sync_context, const cv::Mat& image, std::string_view task_name, + std::string_view custom_recognition_param) { - return MaaBool(); + return std::optional(); +} + +MaaBool RecognizerExecAgent::maa_api_analyze( // + MaaSyncContextHandle sync_context, const MaaImageBufferHandle image, MaaStringView task_name, + MaaStringView custom_recognition_param, MaaTransparentArg recognizer_arg, MaaRectHandle out_box, + MaaStringBufferHandle out_detail) +{ + auto* self = static_cast(recognizer_arg); + if (!self) { + LogError << "recognizer_arg is nullptr"; + return false; + } + + void* raw_data = MaaGetImageRawData(image); + int32_t width = MaaGetImageWidth(image); + int32_t height = MaaGetImageHeight(image); + int32_t type = MaaGetImageType(image); + cv::Mat image_mat(height, width, type, raw_data); + + auto result_opt = self->analyze(sync_context, image_mat, task_name, custom_recognition_param); + + if (!result_opt) { + MaaSetRect(out_box, 0, 0, 0, 0); + MaaClearString(out_detail); + return false; + } + + auto& box = result_opt->box; + MaaSetRect(out_box, box.x, box.y, box.width, box.height); + + auto& detail = result_opt->detail; + MaaSetStringEx(out_detail, detail.c_str(), detail.size()); + + return true; } MAA_TOOLKIT_NS_END diff --git a/source/MaaToolKit/ExecAgent/RecognizerExecAgent.h b/source/MaaToolKit/ExecAgent/RecognizerExecAgent.h index 7585177d9..51d56c45e 100644 --- a/source/MaaToolKit/ExecAgent/RecognizerExecAgent.h +++ b/source/MaaToolKit/ExecAgent/RecognizerExecAgent.h @@ -4,6 +4,7 @@ #include "ExecAgentBase.h" #include "MaaFramework/Task/MaaCustomRecognizer.h" +#include "Utils/NoWarningCVMat.hpp" #include "Utils/SingletonHolder.hpp" MAA_TOOLKIT_NS_BEGIN @@ -18,9 +19,19 @@ class RecognizerExecAgent final : public ExecAgentBase, public SingletonHolder analyze( // + MaaSyncContextHandle sync_context, const cv::Mat& image, std::string_view task_name, + std::string_view custom_recognition_param); + private: // for MaaCustomRecognizerAPI - static MaaBool recognizer_analyze( // + static MaaBool maa_api_analyze( // MaaSyncContextHandle sync_context, const MaaImageBufferHandle image, MaaStringView task_name, MaaStringView custom_recognition_param, MaaTransparentArg recognizer_arg, /*out*/ MaaRectHandle out_box, From 03b74c068c2d50d710bf73d45d18397006c9c4b6 Mon Sep 17 00:00:00 2001 From: MistEO Date: Sun, 3 Dec 2023 22:11:48 +0800 Subject: [PATCH 03/23] chore: remove handle uuid for exec_agent --- source/MaaToolKit/ExecAgent/ExecAgentBase.cpp | 27 ------------------- source/MaaToolKit/ExecAgent/ExecAgentBase.h | 5 ---- source/MaaToolKit/ExecAgent/ExecAgentType.h | 1 - 3 files changed, 33 deletions(-) diff --git a/source/MaaToolKit/ExecAgent/ExecAgentBase.cpp b/source/MaaToolKit/ExecAgent/ExecAgentBase.cpp index ee4f1cb04..0354e9a93 100644 --- a/source/MaaToolKit/ExecAgent/ExecAgentBase.cpp +++ b/source/MaaToolKit/ExecAgent/ExecAgentBase.cpp @@ -18,7 +18,6 @@ bool ExecAgentBase::register_executor(MaaInstanceHandle handle, std::string_view } Executor executor { - .handle_uuid = handle_uuid(handle), .name = std::string(name), .exec_path = std::move(exec_path), .exec_params = std::move(exec_params), @@ -47,30 +46,4 @@ bool ExecAgentBase::unregister_executor(MaaInstanceHandle handle, std::string_vi return ret; } -std::string ExecAgentBase::handle_uuid(MaaInstanceHandle handle) -{ - if (!handle) { - return {}; - } - - for (const auto& [uuid, h] : handles_) { - if (h == handle) { - return uuid; - } - } - - std::string uuid = std::to_string(reinterpret_cast(handle)); - handles_.emplace(uuid, handle); - return uuid; -} - -MaaInstanceHandle ExecAgentBase::uuid_handle(const std::string& uuid) const -{ - auto it = handles_.find(uuid); - if (it == handles_.end()) { - return nullptr; - } - return it->second; -} - MAA_TOOLKIT_NS_END diff --git a/source/MaaToolKit/ExecAgent/ExecAgentBase.h b/source/MaaToolKit/ExecAgent/ExecAgentBase.h index 742e9f5bb..350b81c44 100644 --- a/source/MaaToolKit/ExecAgent/ExecAgentBase.h +++ b/source/MaaToolKit/ExecAgent/ExecAgentBase.h @@ -24,13 +24,8 @@ class ExecAgentBase virtual bool register_for_maa_inst(MaaInstanceHandle handle, std::string_view name) = 0; virtual bool unregister_for_maa_inst(MaaInstanceHandle handle, std::string_view name) = 0; -protected: - std::string handle_uuid(MaaInstanceHandle handle); - MaaInstanceHandle uuid_handle(const std::string& uuid) const; - protected: std::unordered_map executors_; - std::unordered_map handles_; }; MAA_TOOLKIT_NS_END diff --git a/source/MaaToolKit/ExecAgent/ExecAgentType.h b/source/MaaToolKit/ExecAgent/ExecAgentType.h index fc96fae6b..083bb37be 100644 --- a/source/MaaToolKit/ExecAgent/ExecAgentType.h +++ b/source/MaaToolKit/ExecAgent/ExecAgentType.h @@ -43,7 +43,6 @@ inline std::ostream& operator<<(std::ostream& os, ImageTransferMode mode) struct Executor { - std::string handle_uuid; std::string name; std::filesystem::path exec_path; std::vector exec_params; From 0e91193e8f4c1accb42d62c8d850f7631c9b3b55 Mon Sep 17 00:00:00 2001 From: MistEO Date: Mon, 4 Dec 2023 00:24:11 +0800 Subject: [PATCH 04/23] refactor: IOFactory --- .../API/AdbControlUnitAPI.cpp | 8 - source/MaaAdbControlUnit/Base/ArgvWrapper.hpp | 55 --- .../Base/ProcessArgvGenerator.cpp | 49 +++ .../Base/ProcessArgvGenerator.h | 36 ++ source/MaaAdbControlUnit/Base/UnitBase.cpp | 47 +-- source/MaaAdbControlUnit/Base/UnitBase.h | 21 +- source/MaaAdbControlUnit/CMakeLists.txt | 2 +- source/MaaAdbControlUnit/General/Activity.cpp | 15 +- source/MaaAdbControlUnit/General/Activity.h | 4 +- .../MaaAdbControlUnit/General/Connection.cpp | 20 +- source/MaaAdbControlUnit/General/Connection.h | 4 +- .../MaaAdbControlUnit/General/DeviceInfo.cpp | 30 +- source/MaaAdbControlUnit/General/DeviceInfo.h | 6 +- .../MaaAdbControlUnit/General/DeviceList.cpp | 10 +- source/MaaAdbControlUnit/General/DeviceList.h | 2 +- .../MaaAdbControlUnit/Input/MaatouchInput.h | 9 +- .../MaaAdbControlUnit/Input/MtouchHelper.cpp | 5 +- source/MaaAdbControlUnit/Input/MtouchHelper.h | 3 +- source/MaaAdbControlUnit/Input/TapInput.cpp | 28 +- source/MaaAdbControlUnit/Input/TapInput.h | 6 +- source/MaaAdbControlUnit/Invoke/InvokeApp.cpp | 99 +++--- source/MaaAdbControlUnit/Invoke/InvokeApp.h | 19 +- .../Manager/ControlUnitMgr.cpp | 20 +- .../Manager/ControlUnitMgr.h | 3 +- source/MaaAdbControlUnit/Platform/BoostIO.cpp | 333 ------------------ source/MaaAdbControlUnit/Platform/BoostIO.h | 74 ---- .../Platform/PlatformFactory.h | 17 - .../MaaAdbControlUnit/Platform/PlatformIO.h | 41 --- source/MaaAdbControlUnit/Screencap/Encode.cpp | 11 +- source/MaaAdbControlUnit/Screencap/Encode.h | 2 +- .../Screencap/EncodeToFile.cpp | 22 +- .../Screencap/EncodeToFile.h | 4 +- .../Screencap/Minicap/MinicapBase.cpp | 19 +- .../Screencap/Minicap/MinicapDirect.cpp | 5 +- .../Screencap/Minicap/MinicapStream.cpp | 80 ++--- .../Screencap/Minicap/MinicapStream.h | 14 +- .../Screencap/RawByNetcat.cpp | 61 ++-- .../MaaAdbControlUnit/Screencap/RawByNetcat.h | 9 +- .../Screencap/RawWithGzip.cpp | 11 +- .../MaaAdbControlUnit/Screencap/RawWithGzip.h | 2 +- .../Screencap/ScreencapHelper.cpp | 5 +- source/MaaRpc/implement/Utility.cpp | 12 +- source/MaaToolKit/API/MaaToolKitExecAgent.cpp | 3 +- .../ExecAgent/RecognizerExecAgent.cpp | 9 +- source/MaaUtils/CMakeLists.txt | 2 +- .../MaaUtils/IOStream/ChildPipeIOStream.cpp | 63 ++++ source/MaaUtils/IOStream/SockIOStream.cpp | 106 ++++++ source/include/Utils/Boost.hpp | 3 - .../Utils/IOStream/ChildPipeIOStream.h | 33 ++ source/include/Utils/IOStream/SockIOStream.h | 61 ++++ source/include/Utils/NonCopyable.hpp | 20 +- source/include/Utils/StringMisc.hpp | 29 +- 52 files changed, 687 insertions(+), 865 deletions(-) delete mode 100644 source/MaaAdbControlUnit/Base/ArgvWrapper.hpp create mode 100644 source/MaaAdbControlUnit/Base/ProcessArgvGenerator.cpp create mode 100644 source/MaaAdbControlUnit/Base/ProcessArgvGenerator.h delete mode 100644 source/MaaAdbControlUnit/Platform/BoostIO.cpp delete mode 100644 source/MaaAdbControlUnit/Platform/BoostIO.h delete mode 100644 source/MaaAdbControlUnit/Platform/PlatformFactory.h delete mode 100644 source/MaaAdbControlUnit/Platform/PlatformIO.h create mode 100644 source/MaaUtils/IOStream/ChildPipeIOStream.cpp create mode 100644 source/MaaUtils/IOStream/SockIOStream.cpp create mode 100644 source/include/Utils/IOStream/ChildPipeIOStream.h create mode 100644 source/include/Utils/IOStream/SockIOStream.h diff --git a/source/MaaAdbControlUnit/API/AdbControlUnitAPI.cpp b/source/MaaAdbControlUnit/API/AdbControlUnitAPI.cpp index 967367412..1e17f17be 100644 --- a/source/MaaAdbControlUnit/API/AdbControlUnitAPI.cpp +++ b/source/MaaAdbControlUnit/API/AdbControlUnitAPI.cpp @@ -6,7 +6,6 @@ #include "Input/MinitouchInput.h" #include "Input/TapInput.h" #include "Manager/ControlUnitMgr.h" -#include "Platform/PlatformFactory.h" #include "Screencap/Encode.h" #include "Screencap/EncodeToFile.h" #include "Screencap/FastestWay.h" @@ -158,13 +157,6 @@ MaaControlUnitHandle MaaAdbControlUnitCreate( // return nullptr; } - auto platform_io = PlatformFactory::create(); - if (!platform_io) { - LogError << "Create platform io failed"; - return nullptr; - } - unit_mgr->set_io(platform_io); - unit_mgr->set_replacement({ { "{ADB}", adb_path }, { "{ADB_SERIAL}", adb_serial }, diff --git a/source/MaaAdbControlUnit/Base/ArgvWrapper.hpp b/source/MaaAdbControlUnit/Base/ArgvWrapper.hpp deleted file mode 100644 index db154a61a..000000000 --- a/source/MaaAdbControlUnit/Base/ArgvWrapper.hpp +++ /dev/null @@ -1,55 +0,0 @@ -#pragma once - -#include -#include - -#include "Utils/StringMisc.hpp" - -MAA_NS_BEGIN - -template -concept CheckArgv = requires(Argv& argv) { - argv.clear(); - argv.reserve(0); - }; - -template -requires IsSomeKindOfStringArray && CheckArgv -struct ArgvWrapper -{ - using value = Argv; - using string = typename Argv::value_type; - using replacement = typename std::map; - - Argv argv; - - bool parse(const json::array& arr); - Argv gen(const std::map& replacement) const; -}; - -template -requires IsSomeKindOfStringArray && CheckArgv -bool ArgvWrapper::parse(const json::array& arr) -{ - if (!MAA_RNS::ranges::all_of(arr, [](const json::value& val) { return val.is_string(); })) { - return false; - } - - argv = arr.to_vector(); - return true; -} - -template -requires IsSomeKindOfStringArray && CheckArgv -Argv ArgvWrapper::gen(const std::map& replacement) const -{ - auto argv_dup = argv; - for (auto& s : argv_dup) { - string_replace_all_(s, replacement); - } - return argv_dup; -} - -// using _Argv = ArgvWrapper>; - -MAA_NS_END diff --git a/source/MaaAdbControlUnit/Base/ProcessArgvGenerator.cpp b/source/MaaAdbControlUnit/Base/ProcessArgvGenerator.cpp new file mode 100644 index 000000000..2c6873cae --- /dev/null +++ b/source/MaaAdbControlUnit/Base/ProcessArgvGenerator.cpp @@ -0,0 +1,49 @@ +#include "ProcessArgvGenerator.h" + +#include "Utils/Boost.hpp" +#include "Utils/Logger.h" +#include "Utils/Platform.h" + +MAA_CTRL_UNIT_NS_BEGIN + +std::optional ProcessArgvGenerator::create(const json::array& arr) +{ + if (!arr.all()) { + LogError << "array not all string" << VAR(arr); + return std::nullopt; + } + + auto raw = arr.to_vector(); + if (raw.empty()) { + LogError << "array is empty"; + return std::nullopt; + } + + return ProcessArgvGenerator(std::move(raw)); +} +std::optional ProcessArgvGenerator::gen(const Replacement& replacement) const +{ + if (raw_.empty()) { + LogError << "raw is empty"; + return std::nullopt; + } + + auto res = raw_; + for (auto& s : res) { + string_replace_all_(s, replacement); + } + + auto stdpath = MAA_NS::path(res.front()); + auto searched_path = boost::process::search_path(stdpath); + + if (!std::filesystem::exists(searched_path)) { + LogError << "exec path not exits" << VAR(searched_path); + return std::nullopt; + } + + auto args = std::vector(std::make_move_iterator(res.begin() + 1), std::make_move_iterator(res.end())); + + return ProcessArgv { .exec = std::move(searched_path), .args = std::move(args) }; +} + +MAA_CTRL_UNIT_NS_END diff --git a/source/MaaAdbControlUnit/Base/ProcessArgvGenerator.h b/source/MaaAdbControlUnit/Base/ProcessArgvGenerator.h new file mode 100644 index 000000000..aef767260 --- /dev/null +++ b/source/MaaAdbControlUnit/Base/ProcessArgvGenerator.h @@ -0,0 +1,36 @@ +#pragma once + +#include +#include +#include + +#include + +#include "Utils/StringMisc.hpp" + +MAA_CTRL_UNIT_NS_BEGIN + +class ProcessArgvGenerator +{ +public: + using Replacement = std::unordered_map; + + struct ProcessArgv + { + std::filesystem::path exec; + std::vector args; + }; + +public: + static std::optional create(const json::array& arr); + + ProcessArgvGenerator() = default; + ProcessArgvGenerator(std::vector raw) : raw_(std::move(raw)) {} + + std::optional gen(const Replacement& replacement) const; + +private: + std::vector raw_; +}; + +MAA_CTRL_UNIT_NS_END diff --git a/source/MaaAdbControlUnit/Base/UnitBase.cpp b/source/MaaAdbControlUnit/Base/UnitBase.cpp index 8cf6d5544..a7b88742e 100644 --- a/source/MaaAdbControlUnit/Base/UnitBase.cpp +++ b/source/MaaAdbControlUnit/Base/UnitBase.cpp @@ -1,18 +1,11 @@ #include "UnitBase.h" +#include "Utils/IOStream/ChildPipeIOStream.h" #include "Utils/Logger.h" MAA_CTRL_UNIT_NS_BEGIN -void UnitBase::set_io(std::shared_ptr io_ptr) -{ - for (auto child : children_) { - child->set_io(io_ptr); - } - io_ptr_ = io_ptr; -} - -void UnitBase::set_replacement(Argv::replacement argv_replace) +void UnitBase::set_replacement(Replacement argv_replace) { for (auto child : children_) { child->set_replacement(argv_replace); @@ -20,7 +13,7 @@ void UnitBase::set_replacement(Argv::replacement argv_replace) argv_replace_ = std::move(argv_replace); } -void UnitBase::merge_replacement(Argv::replacement argv_replace, bool _override) +void UnitBase::merge_replacement(Replacement argv_replace, bool _override) { for (auto child : children_) { child->merge_replacement(argv_replace, _override); @@ -35,49 +28,41 @@ void UnitBase::merge_replacement(Argv::replacement argv_replace, bool _override) } bool UnitBase::parse_argv(const std::string& key, const json::value& config, const json::array& default_argv, - Argv& argv) + /*out*/ ProcessArgvGenerator& argv) { auto jargv = config.get("command", key, default_argv); - if (!argv.parse(jargv)) { + auto opt = ProcessArgvGenerator::create(jargv); + if (!opt) { LogError << "Parse config failed:" << VAR(key); return false; } + argv = std::move(*opt); return true; } -std::optional UnitBase::command(const Argv::value& cmd, bool recv_by_socket, int64_t timeout) +std::optional UnitBase::startup_and_read_pipe(const ProcessArgv& argv, std::chrono::seconds timeout) { - if (!io_ptr_) { - LogError << "io_ptr is nullptr"; - return std::nullopt; - } - auto start_time = std::chrono::steady_clock::now(); - std::string pipe_data; - std::string sock_data; - int ret = io_ptr_->call_command(cmd, recv_by_socket, pipe_data, sock_data, timeout); + ChildPipeIOStream ios(argv.exec, argv.args); + std::string output = ios.read(timeout); + int ret = ios.release(); auto duration = duration_since(start_time); - std::string scmd = json::array(cmd).to_string(); - LogDebug << VAR(scmd) << VAR(ret) << VAR(pipe_data.size()) << VAR(sock_data.size()) << VAR(duration); - - if (!pipe_data.empty() && pipe_data.size() < 4096) { - LogDebug << MAA_LOG_NS::separator::newline << "stdout output:" << pipe_data; - } - if (recv_by_socket && !sock_data.empty() && sock_data.size() < 4096) { - LogDebug << MAA_LOG_NS::separator::newline << "socket output:" << sock_data; + LogDebug << VAR(argv.exec) << VAR(argv.args) << VAR(output.size()) << VAR(duration); + if (!output.empty() && output.size() < 4096) { + LogDebug << MAA_LOG_NS::separator::newline << "output:" << output; } if (ret != 0) { - LogError << "call_command failed" << VAR(cmd) << VAR(ret); + LogError << "child return error" << VAR(argv.exec) << VAR(argv.args) << VAR(ret); return std::nullopt; } - return recv_by_socket ? sock_data : pipe_data; + return output; } MAA_CTRL_UNIT_NS_END diff --git a/source/MaaAdbControlUnit/Base/UnitBase.h b/source/MaaAdbControlUnit/Base/UnitBase.h index 3cb60a48a..fbefc577f 100644 --- a/source/MaaAdbControlUnit/Base/UnitBase.h +++ b/source/MaaAdbControlUnit/Base/UnitBase.h @@ -1,10 +1,11 @@ #pragma once +#include + #include -#include "Base/ArgvWrapper.hpp" +#include "Base/ProcessArgvGenerator.h" #include "ControlUnit/AdbControlUnitAPI.h" -#include "Platform/PlatformIO.h" #include "Screencap/ScreencapHelper.h" MAA_CTRL_UNIT_NS_BEGIN @@ -12,27 +13,27 @@ MAA_CTRL_UNIT_NS_BEGIN class UnitBase { public: - using Argv = ArgvWrapper>; + using Replacement = ProcessArgvGenerator::Replacement; + using ProcessArgv = ProcessArgvGenerator::ProcessArgv; public: virtual ~UnitBase() = default; virtual bool parse(const json::value& config) = 0; - virtual void set_io(std::shared_ptr io_ptr); - virtual void set_replacement(Argv::replacement argv_replace); - virtual void merge_replacement(Argv::replacement argv_replace, bool _override = true); + virtual void set_replacement(Replacement argv_replace); + virtual void merge_replacement(Replacement argv_replace, bool _override = true); protected: static bool parse_argv(const std::string& key, const json::value& config, const json::array& default_argv, - /*out*/ Argv& argv); + /*out*/ ProcessArgvGenerator& argv); - std::optional command(const Argv::value& cmd, bool recv_by_socket = false, int64_t timeout = 20000); + std::optional startup_and_read_pipe(const ProcessArgv& argv, + std::chrono::seconds timeout = std::chrono::seconds(20)); protected: - std::shared_ptr io_ptr_ = nullptr; std::vector> children_; - Argv::replacement argv_replace_; + Replacement argv_replace_; }; class ScreencapBase : public UnitBase diff --git a/source/MaaAdbControlUnit/CMakeLists.txt b/source/MaaAdbControlUnit/CMakeLists.txt index d8b9105cd..117acc924 100644 --- a/source/MaaAdbControlUnit/CMakeLists.txt +++ b/source/MaaAdbControlUnit/CMakeLists.txt @@ -6,7 +6,7 @@ add_library(MaaAdbControlUnit SHARED ${maa_adb_control_unit_src} ${maa_adb_contr target_include_directories(MaaAdbControlUnit PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../include ${CMAKE_CURRENT_SOURCE_DIR}/../../include) -target_link_libraries(MaaAdbControlUnit MaaUtils HeaderOnlyLibraries ${OpenCV_LIBS} ZLIB::ZLIB Boost::system) +target_link_libraries(MaaAdbControlUnit MaaUtils HeaderOnlyLibraries ${OpenCV_LIBS} ZLIB::ZLIB) if(WIN32) target_link_libraries(MaaAdbControlUnit ws2_32) endif() diff --git a/source/MaaAdbControlUnit/General/Activity.cpp b/source/MaaAdbControlUnit/General/Activity.cpp index 8db63a8d3..a0a4361ff 100644 --- a/source/MaaAdbControlUnit/General/Activity.cpp +++ b/source/MaaAdbControlUnit/General/Activity.cpp @@ -22,9 +22,13 @@ bool Activity::start_app(const std::string& intent) LogFunc; merge_replacement({ { "{INTENT}", intent } }); - auto cmd_ret = command(start_app_argv_.gen(argv_replace_)); - return cmd_ret.has_value(); + auto argv_opt = start_app_argv_.gen(argv_replace_); + if (!argv_opt) { + return false; + } + + return startup_and_read_pipe(*argv_opt).has_value(); } bool Activity::stop_app(const std::string& intent) @@ -32,9 +36,12 @@ bool Activity::stop_app(const std::string& intent) LogFunc; merge_replacement({ { "{INTENT}", intent } }); - auto cmd_ret = command(stop_app_argv_.gen(argv_replace_)); + auto argv_opt = stop_app_argv_.gen(argv_replace_); + if (!argv_opt) { + return false; + } - return cmd_ret.has_value(); + return startup_and_read_pipe(*argv_opt).has_value(); } MAA_CTRL_UNIT_NS_END diff --git a/source/MaaAdbControlUnit/General/Activity.h b/source/MaaAdbControlUnit/General/Activity.h index 339db1c7e..1ae451790 100644 --- a/source/MaaAdbControlUnit/General/Activity.h +++ b/source/MaaAdbControlUnit/General/Activity.h @@ -17,8 +17,8 @@ class Activity : public UnitBase bool stop_app(const std::string& intent); private: - Argv start_app_argv_; - Argv stop_app_argv_; + ProcessArgvGenerator start_app_argv_; + ProcessArgvGenerator stop_app_argv_; }; MAA_CTRL_UNIT_NS_END diff --git a/source/MaaAdbControlUnit/General/Connection.cpp b/source/MaaAdbControlUnit/General/Connection.cpp index a39a38853..c7230f83e 100644 --- a/source/MaaAdbControlUnit/General/Connection.cpp +++ b/source/MaaAdbControlUnit/General/Connection.cpp @@ -24,16 +24,20 @@ bool Connection::connect() { LogFunc; - auto cmd_ret = command(connect_argv_.gen(argv_replace_), false, 60LL * 1000); + auto argv_opt = connect_argv_.gen(argv_replace_); + if (!argv_opt) { + return false; + } - if (!cmd_ret) { - LogInfo << "run command failed"; + using namespace std::chrono_literals; + auto output_opt = startup_and_read_pipe(*argv_opt, 60s); + if (!output_opt) { return false; } constexpr std::array kErrorFlag = { "error", "cannot", "refused", "unable to connect" }; for (const auto& flag : kErrorFlag) { - if (cmd_ret->find(flag) != std::string::npos) { + if (output_opt->find(flag) != std::string::npos) { LogInfo << "unable to connect"; return false; } @@ -47,7 +51,13 @@ bool Connection::kill_server() { LogFunc; - return command(kill_server_argv_.gen(argv_replace_), false, 60LL * 1000).has_value(); + auto argv_opt = kill_server_argv_.gen(argv_replace_); + if (!argv_opt) { + return false; + } + + using namespace std::chrono_literals; + return startup_and_read_pipe(*argv_opt, 60s).has_value(); } MAA_CTRL_UNIT_NS_END diff --git a/source/MaaAdbControlUnit/General/Connection.h b/source/MaaAdbControlUnit/General/Connection.h index 81aee545a..f27715175 100644 --- a/source/MaaAdbControlUnit/General/Connection.h +++ b/source/MaaAdbControlUnit/General/Connection.h @@ -17,8 +17,8 @@ class Connection : public UnitBase bool kill_server(); private: - Argv connect_argv_; - Argv kill_server_argv_; + ProcessArgvGenerator connect_argv_; + ProcessArgvGenerator kill_server_argv_; }; MAA_CTRL_UNIT_NS_END diff --git a/source/MaaAdbControlUnit/General/DeviceInfo.cpp b/source/MaaAdbControlUnit/General/DeviceInfo.cpp index 8413284a2..773dfbfb0 100644 --- a/source/MaaAdbControlUnit/General/DeviceInfo.cpp +++ b/source/MaaAdbControlUnit/General/DeviceInfo.cpp @@ -25,13 +25,17 @@ std::optional DeviceInfo::request_uuid() { LogFunc; - auto cmd_ret = command(uuid_argv_.gen(argv_replace_)); + auto argv_opt = uuid_argv_.gen(argv_replace_); + if (!argv_opt) { + return std::nullopt; + } - if (!cmd_ret) { + auto output_opt = startup_and_read_pipe(*argv_opt); + if (!output_opt) { return std::nullopt; } - auto& uuid_str = cmd_ret.value(); + auto& uuid_str = output_opt.value(); std::erase_if(uuid_str, [](char c) { return !std::isdigit(c) && !std::isalpha(c); }); return uuid_str; @@ -41,15 +45,19 @@ std::optional> DeviceInfo::request_resolution() { LogFunc; - auto cmd_ret = command(resolution_argv_.gen(argv_replace_)); + auto argv_opt = resolution_argv_.gen(argv_replace_); + if (!argv_opt) { + return std::nullopt; + } - if (!cmd_ret) { + auto output_opt = startup_and_read_pipe(*argv_opt); + if (!output_opt) { return std::nullopt; } int width = 0, height = 0; - std::istringstream iss(cmd_ret.value()); + std::istringstream iss(output_opt.value()); iss >> width >> height; return std::make_pair(width, height); } @@ -58,13 +66,17 @@ std::optional DeviceInfo::request_orientation() { LogFunc; - auto cmd_ret = command(orientation_argv_.gen(argv_replace_)); + auto argv_opt = orientation_argv_.gen(argv_replace_); + if (!argv_opt) { + return std::nullopt; + } - if (!cmd_ret) { + auto output_opt = startup_and_read_pipe(*argv_opt); + if (!output_opt) { return std::nullopt; } - const auto& s = cmd_ret.value(); + const auto& s = output_opt.value(); if (s.empty()) { return std::nullopt; diff --git a/source/MaaAdbControlUnit/General/DeviceInfo.h b/source/MaaAdbControlUnit/General/DeviceInfo.h index f205a5316..ea51d5c82 100644 --- a/source/MaaAdbControlUnit/General/DeviceInfo.h +++ b/source/MaaAdbControlUnit/General/DeviceInfo.h @@ -18,9 +18,9 @@ class DeviceInfo : public UnitBase std::optional request_orientation(); private: - Argv uuid_argv_; - Argv resolution_argv_; - Argv orientation_argv_; + ProcessArgvGenerator uuid_argv_; + ProcessArgvGenerator resolution_argv_; + ProcessArgvGenerator orientation_argv_; }; MAA_CTRL_UNIT_NS_END diff --git a/source/MaaAdbControlUnit/General/DeviceList.cpp b/source/MaaAdbControlUnit/General/DeviceList.cpp index 53c0d294f..2b050fee6 100644 --- a/source/MaaAdbControlUnit/General/DeviceList.cpp +++ b/source/MaaAdbControlUnit/General/DeviceList.cpp @@ -20,9 +20,13 @@ std::optional> DeviceList::request_devices() { LogFunc; - auto cmd_ret = command(devices_argv_.gen(argv_replace_)); + auto argv_opt = devices_argv_.gen(argv_replace_); + if (!argv_opt) { + return std::nullopt; + } - if (!cmd_ret) { + auto output_opt = startup_and_read_pipe(*argv_opt); + if (!output_opt) { return std::nullopt; } @@ -30,7 +34,7 @@ std::optional> DeviceList::request_devices() // List of devices attached // 127.0.0.1:16384 offline // 127.0.0.1:16416 device - auto devices_str = std::move(cmd_ret).value(); + auto devices_str = std::move(output_opt).value(); auto lines = string_split(devices_str, '\n'); if (lines.empty()) { return {}; diff --git a/source/MaaAdbControlUnit/General/DeviceList.h b/source/MaaAdbControlUnit/General/DeviceList.h index a9d3db4c8..772d79236 100644 --- a/source/MaaAdbControlUnit/General/DeviceList.h +++ b/source/MaaAdbControlUnit/General/DeviceList.h @@ -16,7 +16,7 @@ class DeviceList : public UnitBase std::optional> request_devices(); private: - Argv devices_argv_; + ProcessArgvGenerator devices_argv_; }; MAA_CTRL_UNIT_NS_END diff --git a/source/MaaAdbControlUnit/Input/MaatouchInput.h b/source/MaaAdbControlUnit/Input/MaatouchInput.h index 908cb62ff..47f9797ed 100644 --- a/source/MaaAdbControlUnit/Input/MaatouchInput.h +++ b/source/MaaAdbControlUnit/Input/MaatouchInput.h @@ -22,17 +22,12 @@ class MaatouchInput : public MtouchHelper, public KeyInputBase public: // from UnitBase virtual bool parse(const json::value& config) override; - virtual void set_io(std::shared_ptr io_ptr) override - { - TouchInputBase::set_io(io_ptr); - KeyInputBase::set_io(io_ptr); - } - virtual void set_replacement(Argv::replacement argv_replace) override + virtual void set_replacement(UnitBase::Replacement argv_replace) override { TouchInputBase::set_replacement(argv_replace); KeyInputBase::set_replacement(argv_replace); } - virtual void merge_replacement(Argv::replacement argv_replace, bool _override = true) override + virtual void merge_replacement(UnitBase::Replacement argv_replace, bool _override = true) override { TouchInputBase::merge_replacement(argv_replace, _override); KeyInputBase::merge_replacement(argv_replace, _override); diff --git a/source/MaaAdbControlUnit/Input/MtouchHelper.cpp b/source/MaaAdbControlUnit/Input/MtouchHelper.cpp index 77cb97b32..aeaccc0f0 100644 --- a/source/MaaAdbControlUnit/Input/MtouchHelper.cpp +++ b/source/MaaAdbControlUnit/Input/MtouchHelper.cpp @@ -22,10 +22,11 @@ bool MtouchHelper::read_info(int swidth, int sheight, int orientation) std::string info; while (check_time()) { - auto str = prev + shell_handler_->read(5); + using namespace std::chrono_literals; + auto str = prev + shell_handler_->read(5s); LogDebug << "output:" << str; if (str.empty()) { - std::this_thread::sleep_for(std::chrono::seconds(2)); + std::this_thread::sleep_for(2s); continue; } auto pos = str.find('^'); diff --git a/source/MaaAdbControlUnit/Input/MtouchHelper.h b/source/MaaAdbControlUnit/Input/MtouchHelper.h index fd86eb91b..e2f11308f 100644 --- a/source/MaaAdbControlUnit/Input/MtouchHelper.h +++ b/source/MaaAdbControlUnit/Input/MtouchHelper.h @@ -3,6 +3,7 @@ #include "Base/UnitBase.h" #include "Invoke/InvokeApp.h" +#include "Utils/IOStream/ChildPipeIOStream.h" MAA_CTRL_UNIT_NS_BEGIN @@ -29,7 +30,7 @@ class MtouchHelper : public TouchInputBase static constexpr std::string_view kMoveFormat = "m {} {} {} {}\nc\n"; static constexpr std::string_view kUpFormat = "u {}\nc\n"; - std::shared_ptr shell_handler_ = nullptr; + std::shared_ptr shell_handler_ = nullptr; int screen_width_ = 0; int screen_height_ = 0; diff --git a/source/MaaAdbControlUnit/Input/TapInput.cpp b/source/MaaAdbControlUnit/Input/TapInput.cpp index 9920e47ba..918bdf1b1 100644 --- a/source/MaaAdbControlUnit/Input/TapInput.cpp +++ b/source/MaaAdbControlUnit/Input/TapInput.cpp @@ -39,10 +39,13 @@ bool TapTouchInput::click(int x, int y) merge_replacement({ { "{X}", std::to_string(x) }, { "{Y}", std::to_string(y) } }); - LogDebug << VAR(x) << VAR(y); - auto cmd_ret = command(click_argv_.gen(argv_replace_)); + auto argv_opt = click_argv_.gen(argv_replace_); + if (!argv_opt) { + return false; + } - return cmd_ret && cmd_ret->empty(); + auto output_opt = startup_and_read_pipe(*argv_opt); + return output_opt && output_opt->empty(); } bool TapTouchInput::swipe(int x1, int y1, int x2, int y2, int duration) @@ -54,9 +57,15 @@ bool TapTouchInput::swipe(int x1, int y1, int x2, int y2, int duration) { "{X2}", std::to_string(x2) }, { "{Y2}", std::to_string(y2) }, { "{DURATION}", duration ? std::to_string(duration) : std::string() } }); - auto cmd_ret = command(swipe_argv_.gen(argv_replace_)); - return cmd_ret.has_value() && cmd_ret.value().empty(); + auto argv_opt = swipe_argv_.gen(argv_replace_); + if (!argv_opt) { + return false; + } + + using namespace std::chrono_literals; + auto output_opt = startup_and_read_pipe(*argv_opt); + return output_opt && output_opt->empty(); } bool TapTouchInput::touch_down(int contact, int x, int y, int pressure) @@ -91,9 +100,14 @@ bool TapKeyInput::press_key(int key) LogInfo << VAR(key); merge_replacement({ { "{KEY}", std::to_string(key) } }); - auto cmd_ret = command(press_key_argv_.gen(argv_replace_)); - return cmd_ret.has_value() && cmd_ret.value().empty(); + auto argv_opt = press_key_argv_.gen(argv_replace_); + if (!argv_opt) { + return false; + } + + auto output_opt = startup_and_read_pipe(*argv_opt); + return output_opt && output_opt->empty(); } MAA_CTRL_UNIT_NS_END diff --git a/source/MaaAdbControlUnit/Input/TapInput.h b/source/MaaAdbControlUnit/Input/TapInput.h index 7f38dceb2..9805ebf91 100644 --- a/source/MaaAdbControlUnit/Input/TapInput.h +++ b/source/MaaAdbControlUnit/Input/TapInput.h @@ -25,8 +25,8 @@ class TapTouchInput : public TouchInputBase virtual bool touch_up(int contact) override; private: - Argv click_argv_; - Argv swipe_argv_; + ProcessArgvGenerator click_argv_; + ProcessArgvGenerator swipe_argv_; }; class TapKeyInput : public KeyInputBase @@ -41,7 +41,7 @@ class TapKeyInput : public KeyInputBase virtual bool press_key(int key) override; private: - Argv press_key_argv_; + ProcessArgvGenerator press_key_argv_; }; MAA_CTRL_UNIT_NS_END diff --git a/source/MaaAdbControlUnit/Invoke/InvokeApp.cpp b/source/MaaAdbControlUnit/Invoke/InvokeApp.cpp index b046b62c1..55bc20538 100644 --- a/source/MaaAdbControlUnit/Invoke/InvokeApp.cpp +++ b/source/MaaAdbControlUnit/Invoke/InvokeApp.cpp @@ -45,9 +45,10 @@ bool InvokeApp::parse(const json::value& config) bool InvokeApp::init(const std::string& force_temp) { - LogFunc; - tempname_ = force_temp.empty() ? now_filestem() : force_temp; + + LogDebug << VAR(tempname_); + return true; } @@ -55,25 +56,34 @@ std::optional> InvokeApp::abilist() { LogFunc; - auto cmd_ret = command(abilist_argv_.gen(argv_replace_)); + auto argv_opt = abilist_argv_.gen(argv_replace_); + if (!argv_opt) { + return std::nullopt; + } - if (!cmd_ret) { + auto output_opt = startup_and_read_pipe(*argv_opt); + if (!output_opt) { return std::nullopt; } - return string_split(*cmd_ret, ','); + return string_split(*output_opt, ','); } std::optional InvokeApp::sdk() { LogFunc; - auto cmd_ret = command(sdk_argv_.gen(argv_replace_)); + auto argv_opt = sdk_argv_.gen(argv_replace_); + if (!argv_opt) { + return std::nullopt; + } - if (!cmd_ret) { + auto output_opt = startup_and_read_pipe(*argv_opt); + if (!output_opt) { return std::nullopt; } - std::string& ret = *cmd_ret; + + std::string& ret = *output_opt; string_trim_(ret); if (!MAA_RNS::ranges::all_of(ret, [](char c) { return std::isdigit(c); })) { @@ -84,18 +94,18 @@ std::optional InvokeApp::sdk() bool InvokeApp::push(const std::filesystem::path& path) { - LogFunc; - - if (!io_ptr_) { - LogError << "io_ptr is nullptr"; - return false; - } + LogFunc << VAR(path); std::string absolute_path = path_to_crt_string(std::filesystem::absolute(path)); merge_replacement({ { "{BIN_PATH}", absolute_path }, { "{BIN_WORKING_FILE}", tempname_ } }); - auto cmd_ret = command(push_bin_argv_.gen(argv_replace_)); - if (!cmd_ret) { + auto argv_opt = sdk_argv_.gen(argv_replace_); + if (!argv_opt) { + return false; + } + + auto output_opt = startup_and_read_pipe(*argv_opt); + if (!output_opt) { return false; } @@ -106,60 +116,61 @@ bool InvokeApp::chmod() { LogFunc; - if (!io_ptr_) { - LogError << "io_ptr is nullptr"; + merge_replacement({ { "{BIN_WORKING_FILE}", tempname_ } }); + + auto argv_opt = chmod_bin_argv_.gen(argv_replace_); + if (!argv_opt) { return false; } - merge_replacement({ { "{BIN_WORKING_FILE}", tempname_ } }); - auto cmd_ret = command(chmod_bin_argv_.gen(argv_replace_)); - - if (!cmd_ret) { + auto output_opt = startup_and_read_pipe(*argv_opt); + if (!output_opt) { return false; } return true; } -std::optional InvokeApp::invoke_bin_stdout(const std::string& extra) +std::optional InvokeApp::invoke_bin_and_read_pipe(const std::string& extra) { - LogFunc; + LogFunc << VAR(extra); merge_replacement({ { "{BIN_WORKING_FILE}", tempname_ }, { "{BIN_EXTRA_PARAMS}", extra } }); - LogInfo << invoke_bin_argv_.gen(argv_replace_); - return command(invoke_bin_argv_.gen(argv_replace_)); + + auto argv_opt = invoke_bin_argv_.gen(argv_replace_); + if (!argv_opt) { + return std::nullopt; + } + + return startup_and_read_pipe(*argv_opt); } -std::shared_ptr InvokeApp::invoke_bin(const std::string& extra, bool wants_stderr) +std::shared_ptr InvokeApp::invoke_bin(const std::string& extra) { - LogFunc; + LogFunc << VAR(extra); - if (!io_ptr_) { - LogError << "io_ptr is nullptr"; + merge_replacement({ { "{BIN_WORKING_FILE}", tempname_ }, { "{BIN_EXTRA_PARAMS}", extra } }); + + auto argv_opt = invoke_bin_argv_.gen(argv_replace_); + if (!argv_opt) { return nullptr; } - merge_replacement({ { "{BIN_WORKING_FILE}", tempname_ }, { "{BIN_EXTRA_PARAMS}", extra } }); - LogInfo << invoke_bin_argv_.gen(argv_replace_); - auto cmd_ret = io_ptr_->interactive_shell(invoke_bin_argv_.gen(argv_replace_), wants_stderr); - - return cmd_ret; + return std::make_shared(argv_opt->exec, argv_opt->args); } -std::shared_ptr InvokeApp::invoke_app(const std::string& package) +std::shared_ptr InvokeApp::invoke_app(const std::string& package) { - LogFunc; + LogFunc << VAR(package); - if (!io_ptr_) { - LogError << "io_ptr is nullptr"; + merge_replacement({ { "{APP_WORKING_FILE}", tempname_ }, { "{PACKAGE_NAME}", package } }); + + auto argv_opt = invoke_app_argv_.gen(argv_replace_); + if (!argv_opt) { return nullptr; } - merge_replacement({ { "{APP_WORKING_FILE}", tempname_ }, { "{PACKAGE_NAME}", package } }); - LogInfo << invoke_app_argv_.gen(argv_replace_); - auto cmd_ret = io_ptr_->interactive_shell(invoke_app_argv_.gen(argv_replace_), false); - - return cmd_ret; + return std::make_shared(argv_opt->exec, argv_opt->args); } MAA_CTRL_UNIT_NS_END diff --git a/source/MaaAdbControlUnit/Invoke/InvokeApp.h b/source/MaaAdbControlUnit/Invoke/InvokeApp.h index 5ccdd0b98..7329201e6 100644 --- a/source/MaaAdbControlUnit/Invoke/InvokeApp.h +++ b/source/MaaAdbControlUnit/Invoke/InvokeApp.h @@ -1,6 +1,7 @@ #pragma once #include "Base/UnitBase.h" +#include "Utils/IOStream/ChildPipeIOStream.h" #include @@ -22,17 +23,17 @@ class InvokeApp : public UnitBase bool push(const std::filesystem::path& path); bool chmod(); - std::optional invoke_bin_stdout(const std::string& extra); - std::shared_ptr invoke_bin(const std::string& extra, bool wants_stderr = false); - std::shared_ptr invoke_app(const std::string& package); + std::optional invoke_bin_and_read_pipe(const std::string& extra); + std::shared_ptr invoke_bin(const std::string& extra); + std::shared_ptr invoke_app(const std::string& package); private: - Argv abilist_argv_; - Argv sdk_argv_; - Argv push_bin_argv_; - Argv chmod_bin_argv_; - Argv invoke_bin_argv_; - Argv invoke_app_argv_; + ProcessArgvGenerator abilist_argv_; + ProcessArgvGenerator sdk_argv_; + ProcessArgvGenerator push_bin_argv_; + ProcessArgvGenerator chmod_bin_argv_; + ProcessArgvGenerator invoke_bin_argv_; + ProcessArgvGenerator invoke_app_argv_; std::string tempname_; }; diff --git a/source/MaaAdbControlUnit/Manager/ControlUnitMgr.cpp b/source/MaaAdbControlUnit/Manager/ControlUnitMgr.cpp index 042203d95..ba536e66c 100644 --- a/source/MaaAdbControlUnit/Manager/ControlUnitMgr.cpp +++ b/source/MaaAdbControlUnit/Manager/ControlUnitMgr.cpp @@ -238,25 +238,7 @@ bool ControlUnitMgr::parse(const json::value& config) return ret; } -void ControlUnitMgr::set_io(const std::shared_ptr& io_ptr) -{ - device_list_.set_io(io_ptr); - connection_.set_io(io_ptr); - device_info_.set_io(io_ptr); - activity_.set_io(io_ptr); - - if (touch_input_) { - touch_input_->set_io(io_ptr); - } - if (key_input_) { - key_input_->set_io(io_ptr); - } - if (screencap_) { - screencap_->set_io(io_ptr); - } -} - -void ControlUnitMgr::set_replacement(const std::map& replacement) +void ControlUnitMgr::set_replacement(const UnitBase::Replacement& replacement) { device_list_.set_replacement(replacement); connection_.set_replacement(replacement); diff --git a/source/MaaAdbControlUnit/Manager/ControlUnitMgr.h b/source/MaaAdbControlUnit/Manager/ControlUnitMgr.h index 0e1523710..378ea2c70 100644 --- a/source/MaaAdbControlUnit/Manager/ControlUnitMgr.h +++ b/source/MaaAdbControlUnit/Manager/ControlUnitMgr.h @@ -44,8 +44,7 @@ class ControlUnitMgr : public ControlUnitAPI public: bool parse(const json::value& config); - void set_io(const std::shared_ptr& io_ptr); - void set_replacement(const std::map& replacement); + void set_replacement(const UnitBase::Replacement& replacement); void set_touch_input_obj(std::shared_ptr obj) { touch_input_ = std::move(obj); } void set_key_input_obj(std::shared_ptr obj) { key_input_ = std::move(obj); } diff --git a/source/MaaAdbControlUnit/Platform/BoostIO.cpp b/source/MaaAdbControlUnit/Platform/BoostIO.cpp deleted file mode 100644 index a370087e9..000000000 --- a/source/MaaAdbControlUnit/Platform/BoostIO.cpp +++ /dev/null @@ -1,333 +0,0 @@ -#include "BoostIO.h" - -#include - -#include "Utils/Logger.h" -#include "Utils/Platform.h" - -#ifdef _WIN32 -#define BOOST_CREATE_NO_WINDOW , boost::process::windows::create_no_window -#else -#define BOOST_CREATE_NO_WINDOW -#endif - -MAA_CTRL_UNIT_NS_BEGIN - -BoostIO::BoostIO() : ios_(std::make_shared()), server_sock_(*ios_) -{ - support_socket_ = true; -} - -BoostIO::~BoostIO() {} - -int BoostIO::call_command(const std::vector& cmd, bool recv_by_socket, std::string& pipe_data, - std::string& sock_data, int64_t timeout) -{ - using namespace std::chrono; - - if (cmd.empty()) { - LogError << "cmd is empty"; - return -1; - } - - auto exec = boost::process::search_path(cmd.front()); - if (!std::filesystem::exists(exec)) { - LogError << "path not exists" << VAR(exec) << VAR(cmd.front()); - return -1; - } - auto args = boost::process::args(std::vector(cmd.begin() + 1, cmd.end())); - - boost::process::ipstream pout; - boost::process::child proc(exec, args, boost::process::std_in pout, - boost::process::std_err > boost::process::null BOOST_CREATE_NO_WINDOW); - - const auto start_time = std::chrono::steady_clock::now(); - auto terminate = [&]() -> bool { - return !proc.running() || (timeout && timeout < duration_since(start_time).count()); - }; - - if (recv_by_socket) { - read_sock_data(sock_data, terminate); - } - else { - read_pipe_data(pout, pipe_data, terminate); - } - - while (!terminate()) { - std::this_thread::yield(); - } - - if (proc.running()) { - LogWarn << "terminate" << VAR(exec); - proc.terminate(); - } - else { - proc.wait(); - } - - return proc.exit_code(); -} - -std::optional BoostIO::create_socket(const std::string& local_address) -{ - using namespace boost::asio::ip; - - tcp::endpoint endpoint(tcp::endpoint(address::from_string(local_address), 0)); - - server_sock_.open(endpoint.protocol()); - server_sock_.set_option(tcp::acceptor::reuse_address(true)); - server_sock_.bind(endpoint); - - server_sock_.listen(); - - tcp::endpoint ep = server_sock_.local_endpoint(); - return ep.port(); -} - -void BoostIO::close_socket() noexcept -{ - server_sock_.close(); -} - -std::shared_ptr BoostIO::tcp(const std::string& target, unsigned short port) -{ - using namespace boost::asio::ip; - - if (!ios_) { - LogError << "ios_ is nullptr"; - return nullptr; - } - - tcp::socket socket(*ios_); - - socket.connect(tcp::endpoint(address::from_string(target), port)); - - if (!socket.is_open()) { - LogError << "socket is not opened"; - return nullptr; - } - - return std::make_shared(ios_, std::move(socket)); -} - -std::shared_ptr BoostIO::interactive_shell(const std::vector& cmd, bool want_stderr) -{ - if (cmd.empty()) { - LogError << "cmd is empty"; - return nullptr; - } - - auto pin = std::make_shared(); - auto pout = std::make_shared(); - - std::shared_ptr proc = nullptr; - - auto exec = boost::process::search_path(cmd.front()); - if (!std::filesystem::exists(exec)) { - LogError << "path not exists" << VAR(exec) << VAR(cmd.front()); - return nullptr; - } - auto args = boost::process::args(std::vector(cmd.begin() + 1, cmd.end())); - - if (want_stderr) { - proc = std::make_shared( - exec, args, boost::process::std_in<*pin, boost::process::std_err> * pout BOOST_CREATE_NO_WINDOW); - } - else { - proc = std::make_shared( - exec, args, boost::process::std_in<*pin, boost::process::std_out> * pout BOOST_CREATE_NO_WINDOW); - } - - return std::make_shared(pout, pin, proc); -} - -void BoostIO::read_sock_data(std::string& data, std::function terminate) -{ - constexpr size_t kBufferSize = 128 * 1024; - auto buffer = std::make_unique(kBufferSize); - - auto socket = server_sock_.accept(); - if (!socket.is_open()) { - LogError << "socket is not opened"; - return; - } - boost::system::error_code error; - do { - memset(buffer.get(), 0, kBufferSize); - auto read_num = socket.read_some(boost::asio::mutable_buffer(buffer.get(), kBufferSize), error); - while (error != boost::asio::error::eof && read_num > 0) { - data.insert(data.end(), buffer.get(), buffer.get() + read_num); - read_num = socket.read_some(boost::asio::mutable_buffer(buffer.get(), kBufferSize), error); - } - } while (socket.is_open() && !terminate()); -} - -void BoostIO::read_pipe_data(boost::process::ipstream& pout, std::string& data, std::function terminate) -{ - constexpr size_t kBufferSize = 128 * 1024; - auto buffer = std::make_unique(kBufferSize); - - do { - if (pout.rdbuf()->in_avail() == 0) { - char ch; - pout.read(&ch, 1); - if (pout.gcount() != 1) { - break; - } - data.push_back(ch); - } - - memset(buffer.get(), 0, kBufferSize); - auto read_num = pout.readsome(buffer.get(), kBufferSize); - while (read_num > 0) { - data.insert(data.end(), buffer.get(), buffer.get() + read_num); - read_num = pout.readsome(buffer.get(), kBufferSize); - } - } while (!terminate()); -} - -IOHandlerBoostSocket::~IOHandlerBoostSocket() -{ - sock_.close(); -} - -bool IOHandlerBoostSocket::write(std::string_view data) -{ - if (!sock_.is_open()) { - LogError << "socket is not opened"; - return false; - } - sock_.write_some(boost::asio::buffer(data)); - return true; -} - -std::string IOHandlerBoostSocket::read(unsigned timeout_sec) -{ - auto start_time = std::chrono::steady_clock::now(); - auto check_timeout = [&](const auto& start_time) -> bool { - using namespace std::chrono_literals; - return std::chrono::steady_clock::now() - start_time < timeout_sec * 1s; - }; - - constexpr size_t bufferSize = 4096; - char buffer[bufferSize]; - - std::string result; - - boost::system::error_code error; - while (check_timeout(start_time) && sock_.is_open()) { - auto read_num = sock_.read_some(boost::asio::mutable_buffer(buffer, bufferSize), error); - while (error != boost::asio::error::eof && read_num > 0) { - result.insert(result.end(), buffer, buffer + read_num); - read_num = sock_.read_some(boost::asio::mutable_buffer(buffer, bufferSize), error); - } - break; - } - - return result; -} - -std::string IOHandlerBoostSocket::read(unsigned timeout_sec, size_t expect) -{ - auto start_time = std::chrono::steady_clock::now(); - auto check_timeout = [&](const auto& start_time) -> bool { - using namespace std::chrono_literals; - return std::chrono::steady_clock::now() - start_time < timeout_sec * 1s; - }; - - constexpr size_t kBufferSize = 4096; - char buffer[kBufferSize] = { 0 }; - - std::string result; - - boost::system::error_code error; - while (expect > result.size() && sock_.is_open() && check_timeout(start_time)) { - auto maxi = std::min(kBufferSize, expect - result.size()); - auto read_num = sock_.read_some(boost::asio::mutable_buffer(buffer, maxi), error); - while (error != boost::asio::error::eof && read_num > 0) { - result.insert(result.end(), buffer, buffer + read_num); - maxi = std::min(kBufferSize, expect - result.size()); - read_num = sock_.read_some(boost::asio::mutable_buffer(buffer, maxi), error); - } - } - - return result; -} - -IOHandlerBoostStream::~IOHandlerBoostStream() -{ - if (proc_->running()) { - proc_->terminate(); - } -} - -bool IOHandlerBoostStream::write(std::string_view data) -{ - if (!proc_->running()) { - return false; - } - - // std::cerr << "write " << std::string(data.data(), data.data() + data.size()) << std::endl; - in_->write(data.data(), data.size()); - in_->flush(); - return true; -} - -std::string IOHandlerBoostStream::read(unsigned timeout_sec) -{ - auto start_time = std::chrono::steady_clock::now(); - auto check_timeout = [&](const auto& start_time) -> bool { - using namespace std::chrono_literals; - return std::chrono::steady_clock::now() - start_time < timeout_sec * 1s; - }; - - constexpr size_t kBufferSize = 4096; - char buffer[kBufferSize] = { 0 }; - - std::string result; - - // dirty hack - if (out_->rdbuf()->in_avail() == 0) { - out_->read(buffer, 1); - result.push_back(buffer[0]); - } - - while (check_timeout(start_time)) { - auto read_num = out_->readsome(buffer, kBufferSize); - while (read_num > 0) { - result.insert(result.end(), buffer, buffer + read_num); - read_num = out_->readsome(buffer, kBufferSize); - } - break; - } - - return result; -} - -std::string IOHandlerBoostStream::read(unsigned timeout_sec, size_t expect) -{ - auto start_time = std::chrono::steady_clock::now(); - auto check_timeout = [&](const auto& start_time) -> bool { - using namespace std::chrono_literals; - return std::chrono::steady_clock::now() - start_time < timeout_sec * 1s; - }; - - constexpr size_t bufferSize = 4096; - char buffer[bufferSize]; - - std::string result; - - while (expect > result.size() && check_timeout(start_time)) { - auto maxi = std::min(bufferSize, expect - result.size()); - auto read_num = out_->readsome(buffer, maxi); - while (read_num > 0) { - result.insert(result.end(), buffer, buffer + read_num); - maxi = std::min(bufferSize, expect - result.size()); - read_num = out_->readsome(buffer, maxi); - } - } - - return result; -} - -MAA_CTRL_UNIT_NS_END diff --git a/source/MaaAdbControlUnit/Platform/BoostIO.h b/source/MaaAdbControlUnit/Platform/BoostIO.h deleted file mode 100644 index dc59dee27..000000000 --- a/source/MaaAdbControlUnit/Platform/BoostIO.h +++ /dev/null @@ -1,74 +0,0 @@ -#pragma once - -#include - -#include "PlatformIO.h" -#include "Utils/Boost.hpp" -#include "Utils/NonCopyable.hpp" -#include "Utils/SingletonHolder.hpp" - -MAA_CTRL_UNIT_NS_BEGIN - -class BoostIO : public PlatformIO -{ -public: - BoostIO(); - virtual ~BoostIO() override; - - virtual int call_command(const std::vector& cmd, bool recv_by_socket, std::string& pipe_data, - std::string& sock_data, int64_t timeout) override; - - virtual std::optional create_socket(const std::string& local_address) override; - virtual void close_socket() noexcept override; - - virtual std::shared_ptr tcp(const std::string& target, unsigned short port) override; - virtual std::shared_ptr interactive_shell(const std::vector& cmd, - bool want_stderr) override; - -private: - void read_sock_data(std::string& data, std::function terminate); - void read_pipe_data(boost::process::ipstream& pout, std::string& data, std::function terminate); - - std::shared_ptr ios_; - boost::asio::ip::tcp::acceptor server_sock_; -}; - -class IOHandlerBoostSocket : public IOHandler, NonCopyable -{ -public: - IOHandlerBoostSocket(std::shared_ptr ios, boost::asio::ip::tcp::socket&& socket) - : ios_(ios), sock_(std::move(socket)) - {} - - virtual ~IOHandlerBoostSocket() override; - - virtual bool write(std::string_view data) override; - virtual std::string read(unsigned timeout_sec) override; - virtual std::string read(unsigned timeout_sec, size_t expect) override; - -private: - std::shared_ptr ios_; - boost::asio::ip::tcp::socket sock_; -}; - -class IOHandlerBoostStream : public IOHandler, NonCopyable -{ -public: - IOHandlerBoostStream(std::shared_ptr out, std::shared_ptr in, - std::shared_ptr proc) - : out_(out), in_(in), proc_(proc) - {} - - virtual ~IOHandlerBoostStream() override; - - virtual bool write(std::string_view data) override; - virtual std::string read(unsigned timeout_sec) override; - virtual std::string read(unsigned timeout_sec, size_t expect) override; - -private: - std::shared_ptr out_; - std::shared_ptr in_; - std::shared_ptr proc_; -}; - -MAA_CTRL_UNIT_NS_END diff --git a/source/MaaAdbControlUnit/Platform/PlatformFactory.h b/source/MaaAdbControlUnit/Platform/PlatformFactory.h deleted file mode 100644 index c2ded3a78..000000000 --- a/source/MaaAdbControlUnit/Platform/PlatformFactory.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include "Conf/Conf.h" - -#include "BoostIO.h" - -MAA_CTRL_UNIT_NS_BEGIN - -using NativeIO = BoostIO; - -class PlatformFactory -{ -public: - static std::shared_ptr create() { return std::make_shared(); } -}; - -MAA_CTRL_UNIT_NS_END diff --git a/source/MaaAdbControlUnit/Platform/PlatformIO.h b/source/MaaAdbControlUnit/Platform/PlatformIO.h deleted file mode 100644 index 46121b002..000000000 --- a/source/MaaAdbControlUnit/Platform/PlatformIO.h +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -#include "Conf/Conf.h" - -MAA_CTRL_UNIT_NS_BEGIN - -class IOHandler; - -class PlatformIO -{ -public: - virtual ~PlatformIO() = default; - - virtual int call_command(const std::vector& cmd, bool recv_by_socket, std::string& pipe_data, - std::string& sock_data, int64_t timeout) = 0; - - virtual std::optional create_socket(const std::string& local_address) = 0; - virtual void close_socket() noexcept = 0; - - virtual std::shared_ptr tcp(const std::string& target, unsigned short port) = 0; - virtual std::shared_ptr interactive_shell(const std::vector& cmd, bool want_stderr) = 0; - - bool support_socket_ = false; -}; - -class IOHandler -{ -public: - virtual ~IOHandler() = default; - - virtual bool write(std::string_view data) = 0; - virtual std::string read(unsigned timeout_sec) = 0; - virtual std::string read(unsigned timeout_sec, size_t expect) = 0; -}; - -MAA_CTRL_UNIT_NS_END diff --git a/source/MaaAdbControlUnit/Screencap/Encode.cpp b/source/MaaAdbControlUnit/Screencap/Encode.cpp index 6b9ce7ab0..d56eee0ba 100644 --- a/source/MaaAdbControlUnit/Screencap/Encode.cpp +++ b/source/MaaAdbControlUnit/Screencap/Encode.cpp @@ -20,19 +20,18 @@ bool ScreencapEncode::init(int swidth, int sheight) std::optional ScreencapEncode::screencap() { - if (!io_ptr_) { - LogError << "io_ptr is nullptr"; + auto argv_opt = screencap_encode_argv_.gen(argv_replace_); + if (!argv_opt) { return std::nullopt; } - auto cmd_ret = command(screencap_encode_argv_.gen(argv_replace_)); - - if (!cmd_ret) { + auto output_opt = startup_and_read_pipe(*argv_opt); + if (!output_opt) { return std::nullopt; } return screencap_helper_.process_data( - cmd_ret.value(), std::bind(&ScreencapHelper::decode_png, &screencap_helper_, std::placeholders::_1)); + *output_opt, std::bind(&ScreencapHelper::decode_png, &screencap_helper_, std::placeholders::_1)); } MAA_CTRL_UNIT_NS_END diff --git a/source/MaaAdbControlUnit/Screencap/Encode.h b/source/MaaAdbControlUnit/Screencap/Encode.h index b60d6b455..0dd167c9d 100644 --- a/source/MaaAdbControlUnit/Screencap/Encode.h +++ b/source/MaaAdbControlUnit/Screencap/Encode.h @@ -21,7 +21,7 @@ class ScreencapEncode : public ScreencapBase virtual std::optional screencap() override; private: - Argv screencap_encode_argv_; + ProcessArgvGenerator screencap_encode_argv_; }; MAA_CTRL_UNIT_NS_END diff --git a/source/MaaAdbControlUnit/Screencap/EncodeToFile.cpp b/source/MaaAdbControlUnit/Screencap/EncodeToFile.cpp index 6adcbedb8..1d482d477 100644 --- a/source/MaaAdbControlUnit/Screencap/EncodeToFile.cpp +++ b/source/MaaAdbControlUnit/Screencap/EncodeToFile.cpp @@ -29,27 +29,29 @@ bool ScreencapEncodeToFileAndPull::init(int swidth, int sheight) std::optional ScreencapEncodeToFileAndPull::screencap() { - if (!io_ptr_) { - LogError << "io_ptr is nullptr"; - return std::nullopt; - } - auto dst_path = std::filesystem::temp_directory_path() / now_filestem(); merge_replacement({ { "{TEMP_FILE}", tempname_ }, { "{DST_PATH}", path_to_crt_string(dst_path) } }); - auto cmd_ret = command(screencap_encode_to_file_argv_.gen(argv_replace_)); - if (!cmd_ret) { + auto argv_opt = screencap_encode_to_file_argv_.gen(argv_replace_); + if (!argv_opt) { + return std::nullopt; + } + + auto output_opt = startup_and_read_pipe(*argv_opt); + if (!output_opt) { return std::nullopt; } - cmd_ret = command(pull_file_argv_.gen(argv_replace_)); + auto image = imread(dst_path); + std::filesystem::remove(dst_path); - if (!cmd_ret) { + if (image.empty()) { + LogError << "Failed to read image from" << dst_path; return std::nullopt; } - return imread(dst_path); + return image; } MAA_CTRL_UNIT_NS_END diff --git a/source/MaaAdbControlUnit/Screencap/EncodeToFile.h b/source/MaaAdbControlUnit/Screencap/EncodeToFile.h index 689c5a04f..f6fb4f709 100644 --- a/source/MaaAdbControlUnit/Screencap/EncodeToFile.h +++ b/source/MaaAdbControlUnit/Screencap/EncodeToFile.h @@ -21,8 +21,8 @@ class ScreencapEncodeToFileAndPull : public ScreencapBase virtual std::optional screencap() override; private: - Argv screencap_encode_to_file_argv_; - Argv pull_file_argv_; + ProcessArgvGenerator screencap_encode_to_file_argv_; + ProcessArgvGenerator pull_file_argv_; std::string tempname_; }; diff --git a/source/MaaAdbControlUnit/Screencap/Minicap/MinicapBase.cpp b/source/MaaAdbControlUnit/Screencap/Minicap/MinicapBase.cpp index e939e9341..04827e4fa 100644 --- a/source/MaaAdbControlUnit/Screencap/Minicap/MinicapBase.cpp +++ b/source/MaaAdbControlUnit/Screencap/Minicap/MinicapBase.cpp @@ -26,7 +26,7 @@ bool MinicapBase::parse(const json::value& config) static const json::array kDefaultSdk = { 31, 29, 28, 27, 26, 25, 24, 23, 22, 21, 19, 18, 17, 16, 15, 14, }; - json::array jsdk = config.get("prebuilt", "minicap", "sdk", kDefaultSdk); + json::array jsdk = config.get("prebuilt", "minicap", "sdk_opt", kDefaultSdk); sdk_list_ = jsdk.to_vector(); return binary_->parse(config) && library_->parse(config); @@ -38,29 +38,24 @@ bool MinicapBase::init(int swidth, int sheight) { LogFunc; - if (!io_ptr_) { - LogError << "io_ptr is nullptr"; - return false; - } - if (!binary_->init() || !library_->init("minicap.so")) { return false; } - auto archs = binary_->abilist(); - auto sdk = binary_->sdk(); + auto archs_opt = binary_->abilist(); + auto sdk_opt = binary_->sdk(); - if (!archs || !sdk) { + if (!archs_opt || !sdk_opt) { return false; } - auto arch_iter = MAA_RNS::ranges::find_first_of(*archs, arch_list_); - if (arch_iter == archs->end()) { + auto arch_iter = MAA_RNS::ranges::find_first_of(*archs_opt, arch_list_); + if (arch_iter == archs_opt->end()) { return false; } const std::string& target_arch = *arch_iter; - auto sdk_iter = MAA_RNS::ranges::find_if(sdk_list_, [sdk](int s) { return s <= sdk.value(); }); + auto sdk_iter = MAA_RNS::ranges::find_if(sdk_list_, [sdk_opt](int s) { return s <= sdk_opt.value(); }); if (sdk_iter == sdk_list_.end()) { return false; } diff --git a/source/MaaAdbControlUnit/Screencap/Minicap/MinicapDirect.cpp b/source/MaaAdbControlUnit/Screencap/Minicap/MinicapDirect.cpp index 8464a3cc2..58283996f 100644 --- a/source/MaaAdbControlUnit/Screencap/Minicap/MinicapDirect.cpp +++ b/source/MaaAdbControlUnit/Screencap/Minicap/MinicapDirect.cpp @@ -11,13 +11,14 @@ std::optional MinicapDirect::screencap() int width = screencap_helper_.get_w(); int height = screencap_helper_.get_h(); - auto res = binary_->invoke_bin_stdout(MAA_FMT::format("-P {}x{}@{}x{}/{} -s", width, height, width, height, 0)); + auto res = + binary_->invoke_bin_and_read_pipe(MAA_FMT::format("-P {}x{}@{}x{}/{} -s", width, height, width, height, 0)); if (!res) { return std::nullopt; } return screencap_helper_.process_data( - res.value(), std::bind(&ScreencapHelper::trunc_decode_jpg, &screencap_helper_, std::placeholders::_1)); + *res, std::bind(&ScreencapHelper::trunc_decode_jpg, &screencap_helper_, std::placeholders::_1)); } MAA_CTRL_UNIT_NS_END diff --git a/source/MaaAdbControlUnit/Screencap/Minicap/MinicapStream.cpp b/source/MaaAdbControlUnit/Screencap/Minicap/MinicapStream.cpp index 00fe443d8..3f779ca04 100644 --- a/source/MaaAdbControlUnit/Screencap/Minicap/MinicapStream.cpp +++ b/source/MaaAdbControlUnit/Screencap/Minicap/MinicapStream.cpp @@ -20,6 +20,9 @@ bool MinicapStream::parse(const json::value& config) static const json::array kDefaultForwardArgv = { "{ADB}", "-s", "{ADB_SERIAL}", "forward", "tcp:{FOWARD_PORT}", "localabstract:{LOCAL_SOCKET}", }; + static constexpr int kDefaultPort = 1313; + + port_ = config.get("prebuilt", "minicap", "stream", "port", kDefaultPort); return MinicapBase::parse(config) && parse_argv("ForwardSocket", config, kDefaultForwardArgv, forward_argv_); } @@ -32,11 +35,15 @@ bool MinicapStream::init(int swidth, int sheight) return false; } - // TODO: 也许可以允许配置? - merge_replacement({ { "{FOWARD_PORT}", "1313" }, { "{LOCAL_SOCKET}", "minicap" } }); - auto cmd_ret = command(forward_argv_.gen(argv_replace_)); + merge_replacement({ { "{FOWARD_PORT}", std::to_string(port_) }, { "{LOCAL_SOCKET}", "minicap" } }); + + auto argv_opt = forward_argv_.gen(argv_replace_); + if (!argv_opt) { + return false; + } - if (!cmd_ret) { + auto output_opt = startup_and_read_pipe(*argv_opt); + if (!output_opt) { return false; } @@ -46,7 +53,7 @@ bool MinicapStream::init(int swidth, int sheight) process_handle_ = binary_->invoke_bin(MAA_FMT::format("-P {}x{}@{}x{}/{}", width, height, width, height, 0)); if (!process_handle_) { - LogError << "invoke screencap failed"; + LogError << "invoke_bin failed"; return false; } @@ -55,7 +62,9 @@ bool MinicapStream::init(int swidth, int sheight) std::string buffer; constexpr int kMaxTry = 50; for (int i = 0; i < kMaxTry; ++i) { - auto res = process_handle_->read(5); + using namespace std::chrono_literals; + auto res = process_handle_->read(5s); + if (!res.empty()) { LogDebug << "minicap stdout:" << res; buffer.append(res); @@ -81,8 +90,8 @@ bool MinicapStream::init(int swidth, int sheight) LogInfo << "minicap try connect to:" << local; - stream_handle_ = io_ptr_->tcp(local, 1313); - + ClientSockIOFactory io_factory(local, static_cast(port_)); + stream_handle_ = io_factory.connect(); if (!stream_handle_) { return false; } @@ -92,10 +101,12 @@ bool MinicapStream::init(int swidth, int sheight) // TODO: 解决大端底的情况 MinicapHeader header; - if (!take_out(&header, sizeof(header))) { - LogError << "take_out header failed"; + auto data = read(sizeof(header)); + if (!data) { + LogError << "read header failed"; return false; } + header = *reinterpret_cast(data->data()); LogInfo << VAR(header.version) << VAR(header.size) << VAR(header.pid) << VAR(header.real_width) << VAR(header.real_height) << VAR(header.virt_width) << VAR(header.virt_height) << VAR(header.orientation) @@ -110,8 +121,8 @@ bool MinicapStream::init(int swidth, int sheight) return false; } - if (!take_out(nullptr, header.size - sizeof(header))) { - LogError << "take_out header failed"; + if (!read(header.size - sizeof(header))) { + LogError << "read header failed"; return false; } @@ -131,33 +142,15 @@ std::optional MinicapStream::screencap() return image_.empty() ? std::nullopt : std::make_optional(image_.clone()); } -bool MinicapStream::read_until(std::string& buffer, size_t size) +std::optional MinicapStream::read(size_t count) { - // LogFunc; - - using namespace std::chrono_literals; - auto start = std::chrono::steady_clock::now(); - - while (buffer.size() < size && duration_since(start) < 5s) { - auto ret = stream_handle_->read(2, size - buffer.size()); - buffer += std::move(ret); + if (!stream_handle_) { + LogError << "stream_handle_ is nullptr"; + return std::nullopt; } - return buffer.size() == size; -} - -bool MinicapStream::take_out(void* out, size_t size) -{ - // LogFunc; - - std::string buffer; - if (!read_until(buffer, size)) { - return false; - } - if (out) { - memcpy(out, buffer.data(), size); - } - return true; + using namespace std::chrono_literals; + return stream_handle_->read(5s, count); } void MinicapStream::working_thread() @@ -165,23 +158,24 @@ void MinicapStream::working_thread() LogFunc; while (!quit_) { - uint32_t size = 0; - if (!take_out(&size, 4)) { - LogError << "take_out size failed"; + auto size_opt = read(4); + if (!size_opt) { + LogError << "read size failed"; std::unique_lock locker(mutex_); image_ = cv::Mat(); continue; } + auto size = *reinterpret_cast(size_opt->data()); - std::string buffer; - if (!read_until(buffer, size)) { - LogError << "read_until size failed"; + auto data_opt = read(size); + if (!data_opt) { + LogError << "read data failed"; std::unique_lock locker(mutex_); image_ = cv::Mat(); continue; } - auto img_opt = screencap_helper_.decode_jpg(buffer); + auto img_opt = screencap_helper_.decode_jpg(*data_opt); if (!img_opt || img_opt->empty()) { LogError << "decode jpg failed"; diff --git a/source/MaaAdbControlUnit/Screencap/Minicap/MinicapStream.h b/source/MaaAdbControlUnit/Screencap/Minicap/MinicapStream.h index 324711bf3..d3690df63 100644 --- a/source/MaaAdbControlUnit/Screencap/Minicap/MinicapStream.h +++ b/source/MaaAdbControlUnit/Screencap/Minicap/MinicapStream.h @@ -5,6 +5,9 @@ #include #include +#include "Utils/IOStream/ChildPipeIOStream.h" +#include "Utils/IOStream/SockIOStream.h" + MAA_CTRL_UNIT_NS_BEGIN class MinicapStream : public MinicapBase @@ -23,11 +26,12 @@ class MinicapStream : public MinicapBase virtual std::optional screencap() override; private: - bool read_until(std::string& buffer, size_t size); - bool take_out(void* out, size_t size); + std::optional read(size_t count); + void working_thread(); - Argv forward_argv_; + ProcessArgvGenerator forward_argv_; + int port_ = 0; bool quit_ = true; std::mutex mutex_; @@ -35,8 +39,8 @@ class MinicapStream : public MinicapBase std::condition_variable cond_; std::thread pull_thread_; - std::shared_ptr process_handle_; - std::shared_ptr stream_handle_; + std::shared_ptr process_handle_; + std::shared_ptr stream_handle_; }; MAA_CTRL_UNIT_NS_END diff --git a/source/MaaAdbControlUnit/Screencap/RawByNetcat.cpp b/source/MaaAdbControlUnit/Screencap/RawByNetcat.cpp index cdf751018..c8f5f4f8c 100644 --- a/source/MaaAdbControlUnit/Screencap/RawByNetcat.cpp +++ b/source/MaaAdbControlUnit/Screencap/RawByNetcat.cpp @@ -22,16 +22,11 @@ bool ScreencapRawByNetcat::init(int swidth, int sheight) { LogFunc; - if (!io_ptr_) { - LogError << "io_ptr is nullptr"; + auto addr_opt = request_netcat_address(); + if (!addr_opt) { return false; } - - auto addr = request_netcat_address(); - if (!addr) { - return false; - } - netcat_address_ = addr.value(); + netcat_address_ = std::move(*addr_opt); auto serial_host = argv_replace_["{ADB_SERIAL}"]; auto shp = serial_host.find(':'); @@ -40,63 +35,65 @@ bool ScreencapRawByNetcat::init(int swidth, int sheight) local = serial_host.substr(0, shp); } - auto prt = io_ptr_->create_socket(local); - if (!prt) { - return false; - } - netcat_port_ = prt.value(); + io_factory_ = std::make_shared(local, 0); return set_wh(swidth, sheight); } void ScreencapRawByNetcat::deinit() { - if (netcat_port_ && io_ptr_) { - io_ptr_->close_socket(); - } - + io_factory_ = nullptr; netcat_address_.clear(); - netcat_port_ = 0; } std::optional ScreencapRawByNetcat::screencap() { - if (!io_ptr_) { - LogError << "io_ptr is nullptr"; + if (!io_factory_) { return std::nullopt; } - merge_replacement({ { "{NETCAT_ADDRESS}", netcat_address_ }, { "{NETCAT_PORT}", std::to_string(netcat_port_) } }); - constexpr int kTimeout = 2000; // netcat 能用的时候一般都很快,但连不上的时候会一直卡着,所以超时设短一点 - auto cmd_ret = command(screencap_raw_by_netcat_argv_.gen(argv_replace_), true, kTimeout); + auto port = io_factory_->port(); + merge_replacement({ { "{NETCAT_ADDRESS}", netcat_address_ }, { "{NETCAT_PORT}", std::to_string(port) } }); - if (!cmd_ret) { + auto argv_opt = screencap_raw_by_netcat_argv_.gen(argv_replace_); + if (!argv_opt) { + return std::nullopt; + } + + // netcat 能用的时候一般都很快,但连不上的时候会一直卡着,所以超时设短一点 + using namespace std::chrono_literals; + constexpr auto kTimeout = 2s; + auto output_opt = startup_and_read_pipe(*argv_opt, kTimeout); + if (!output_opt) { return std::nullopt; } return screencap_helper_.process_data( - cmd_ret.value(), std::bind(&ScreencapHelper::decode_raw, &screencap_helper_, std::placeholders::_1)); + *output_opt, std::bind(&ScreencapHelper::decode_raw, &screencap_helper_, std::placeholders::_1)); } std::optional ScreencapRawByNetcat::request_netcat_address() { LogFunc; - auto cmd_ret = command(netcat_address_argv_.gen(argv_replace_)); + auto argv_opt = netcat_address_argv_.gen(argv_replace_); + if (!argv_opt) { + return std::nullopt; + } - if (!cmd_ret) { + auto output_opt = startup_and_read_pipe(*argv_opt); + if (!output_opt) { return std::nullopt; } - auto ip = cmd_ret.value(); + auto& ip = *output_opt; auto idx = ip.find(' '); - if (idx != std::string::npos) { - return ip.substr(0, idx); - } - else { + if (idx == std::string::npos) { return std::nullopt; } + + return ip.substr(0, idx); } MAA_CTRL_UNIT_NS_END diff --git a/source/MaaAdbControlUnit/Screencap/RawByNetcat.h b/source/MaaAdbControlUnit/Screencap/RawByNetcat.h index bd3c6e9b3..d29875968 100644 --- a/source/MaaAdbControlUnit/Screencap/RawByNetcat.h +++ b/source/MaaAdbControlUnit/Screencap/RawByNetcat.h @@ -3,6 +3,7 @@ #include "Base/UnitBase.h" #include "ScreencapHelper.h" +#include "Utils/IOStream/SockIOStream.h" MAA_CTRL_UNIT_NS_BEGIN @@ -23,11 +24,13 @@ class ScreencapRawByNetcat : public ScreencapBase private: std::optional request_netcat_address(); - Argv screencap_raw_by_netcat_argv_; - Argv netcat_address_argv_; + ProcessArgvGenerator screencap_raw_by_netcat_argv_; + ProcessArgvGenerator netcat_address_argv_; std::string netcat_address_; - uint16_t netcat_port_ = 0; + + std::shared_ptr io_factory_ = nullptr; + std::shared_ptr sock_io_ = nullptr; }; MAA_CTRL_UNIT_NS_END diff --git a/source/MaaAdbControlUnit/Screencap/RawWithGzip.cpp b/source/MaaAdbControlUnit/Screencap/RawWithGzip.cpp index 29206b1f2..d1ce3f674 100644 --- a/source/MaaAdbControlUnit/Screencap/RawWithGzip.cpp +++ b/source/MaaAdbControlUnit/Screencap/RawWithGzip.cpp @@ -20,19 +20,18 @@ bool ScreencapRawWithGzip::init(int swidth, int sheight) std::optional ScreencapRawWithGzip::screencap() { - if (!io_ptr_) { - LogError << "io_ptr is nullptr"; + auto argv_opt = screencap_raw_with_gzip_argv_.gen(argv_replace_); + if (!argv_opt) { return std::nullopt; } - auto cmd_ret = command(screencap_raw_with_gzip_argv_.gen(argv_replace_)); - - if (!cmd_ret) { + auto output_opt = startup_and_read_pipe(*argv_opt); + if (!output_opt) { return std::nullopt; } return screencap_helper_.process_data( - cmd_ret.value(), std::bind(&ScreencapHelper::decode_gzip, &screencap_helper_, std::placeholders::_1)); + *output_opt, std::bind(&ScreencapHelper::decode_gzip, &screencap_helper_, std::placeholders::_1)); } MAA_CTRL_UNIT_NS_END diff --git a/source/MaaAdbControlUnit/Screencap/RawWithGzip.h b/source/MaaAdbControlUnit/Screencap/RawWithGzip.h index c228ab898..1e8920156 100644 --- a/source/MaaAdbControlUnit/Screencap/RawWithGzip.h +++ b/source/MaaAdbControlUnit/Screencap/RawWithGzip.h @@ -21,7 +21,7 @@ class ScreencapRawWithGzip : public ScreencapBase virtual std::optional screencap() override; private: - Argv screencap_raw_with_gzip_argv_; + ProcessArgvGenerator screencap_raw_with_gzip_argv_; }; MAA_CTRL_UNIT_NS_END diff --git a/source/MaaAdbControlUnit/Screencap/ScreencapHelper.cpp b/source/MaaAdbControlUnit/Screencap/ScreencapHelper.cpp index 69df69492..297a0191f 100644 --- a/source/MaaAdbControlUnit/Screencap/ScreencapHelper.cpp +++ b/source/MaaAdbControlUnit/Screencap/ScreencapHelper.cpp @@ -152,10 +152,7 @@ std::optional ScreencapHelper::trunc_decode_jpg(const std::string& buff { auto pos = buffer.find("\xFF\xD8\xFF"); auto truncbuf = buffer.substr(pos); - if (!check_head_tail(truncbuf, "\xFF\xD8\xFF", "\xFF\xD9")) { - return std::nullopt; - } - return decode(truncbuf); + return decode_jpg(truncbuf); } std::optional ScreencapHelper::decode_jpg(const std::string& buffer) diff --git a/source/MaaRpc/implement/Utility.cpp b/source/MaaRpc/implement/Utility.cpp index 3779bbf79..7396c50fe 100644 --- a/source/MaaRpc/implement/Utility.cpp +++ b/source/MaaRpc/implement/Utility.cpp @@ -2,20 +2,12 @@ #include "MaaFramework/MaaAPI.h" #include "Macro.h" #include "Utils/Logger.h" - -#include -#include +#include "Utils/Time.hpp" MAA_RPC_NS_BEGIN using namespace ::grpc; -auto uuid_generator = boost::uuids::random_generator(); -std::string make_uuid() -{ - return boost::uuids::to_string(uuid_generator()); -} - void callback_impl(MaaStringView msg, MaaStringView detail, MaaCallbackTransparentArg arg) { ::maarpc::Callback cb; @@ -121,7 +113,7 @@ Status UtilityImpl::acquire_id(ServerContext* context, const ::maarpc::EmptyRequ std::ignore = context; std::ignore = request; - response->set_id(make_uuid()); + response->set_id(format_now()); return Status::OK; } diff --git a/source/MaaToolKit/API/MaaToolKitExecAgent.cpp b/source/MaaToolKit/API/MaaToolKitExecAgent.cpp index 62eb902b8..dac8788d0 100644 --- a/source/MaaToolKit/API/MaaToolKitExecAgent.cpp +++ b/source/MaaToolKit/API/MaaToolKitExecAgent.cpp @@ -53,8 +53,7 @@ MaaBool RegisterExecutor(ExecutorType type, MaaInstanceHandle handle, MaaStringV LogError << "exec param json parse failed:" << exec_param_json; return false; } - if (!params_opt->is_array() || - !MAA_RNS::ranges::all_of(params_opt->as_array(), [](const auto& v) { return v.is_string(); })) { + if (!params_opt->is_array() || !params_opt->all()) { LogError << "exec param json is not array of string:" << exec_param_json; return false; } diff --git a/source/MaaToolKit/ExecAgent/RecognizerExecAgent.cpp b/source/MaaToolKit/ExecAgent/RecognizerExecAgent.cpp index 7270bb4bb..e53df135e 100644 --- a/source/MaaToolKit/ExecAgent/RecognizerExecAgent.cpp +++ b/source/MaaToolKit/ExecAgent/RecognizerExecAgent.cpp @@ -26,7 +26,14 @@ std::optional RecognizerExecAgent::analyze( MaaSyncContextHandle sync_context, const cv::Mat& image, std::string_view task_name, std::string_view custom_recognition_param) { - return std::optional(); + LogFunc << VAR_VOIDP(sync_context) << VAR(image.size()) << VAR(task_name) << VAR(custom_recognition_param); + + auto exec_it = executors_.find(task_name.data()); + if (exec_it == executors_.end()) { + LogError << "no executor found for task: " << task_name; + return std::nullopt; + } + auto& executor = exec_it->second; } MaaBool RecognizerExecAgent::maa_api_analyze( // diff --git a/source/MaaUtils/CMakeLists.txt b/source/MaaUtils/CMakeLists.txt index df3420e41..39099f86d 100644 --- a/source/MaaUtils/CMakeLists.txt +++ b/source/MaaUtils/CMakeLists.txt @@ -4,7 +4,7 @@ file(GLOB_RECURSE maa_utils_header ../include/Utils/*) add_library(MaaUtils SHARED ${maa_utils_src} ${maa_utils_header}) target_include_directories(MaaUtils PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../include ${CMAKE_CURRENT_SOURCE_DIR}/../../include) -target_link_libraries(MaaUtils PRIVATE HeaderOnlyLibraries) +target_link_libraries(MaaUtils PRIVATE HeaderOnlyLibraries Boost::system) target_compile_definitions(MaaUtils PRIVATE MAA_UTILS_EXPORTS) install( diff --git a/source/MaaUtils/IOStream/ChildPipeIOStream.cpp b/source/MaaUtils/IOStream/ChildPipeIOStream.cpp new file mode 100644 index 000000000..7c9af1aae --- /dev/null +++ b/source/MaaUtils/IOStream/ChildPipeIOStream.cpp @@ -0,0 +1,63 @@ +#include "Utils/IOStream/ChildPipeIOStream.h" + +MAA_NS_BEGIN + +ChildPipeIOStream::ChildPipeIOStream(const std::filesystem::path& exec, const std::vector& args) + : child_( // + exec, args, boost::process::std_out > pout_, boost::process::std_err > pout_, boost::process::std_in < pin_ +#ifdef _WIN32 + , + boost::process::windows::create_no_window +#endif + ), + buffer_(std::make_unique(kBufferSize)) +{} + +ChildPipeIOStream::~ChildPipeIOStream() +{ + release(); +} + +bool ChildPipeIOStream::write(std::string_view data) +{ + if (!child_.running()) { + return false; + } + + pin_ << data << std::endl; + return true; +} + +std::string ChildPipeIOStream::read(std::chrono::seconds timeout, size_t count) +{ + auto start_time = std::chrono::steady_clock::now(); + auto check_timeout = [&](const auto& start_time) -> bool { + return std::chrono::steady_clock::now() - start_time < timeout; + }; + + std::string result; + + while (check_timeout(start_time) && count > result.size() && child_.running()) { + auto read_size = std::min(kBufferSize, count - result.size()); + auto read_num = pout_.readsome(buffer_.get(), read_size); + if (read_num > 0) { + result.append(buffer_.get(), read_num); + } + } + + return result; +} + +int ChildPipeIOStream::release() +{ + if (child_.running()) { + child_.terminate(); + } + else { + child_.wait(); + } + + return child_.exit_code(); +} + +MAA_NS_END diff --git a/source/MaaUtils/IOStream/SockIOStream.cpp b/source/MaaUtils/IOStream/SockIOStream.cpp new file mode 100644 index 000000000..a1407d920 --- /dev/null +++ b/source/MaaUtils/IOStream/SockIOStream.cpp @@ -0,0 +1,106 @@ +#include "Utils/IOStream/SockIOStream.h" + +#include "Utils/Logger.h" + +MAA_NS_BEGIN + +ServerSockIOFactory::ServerSockIOFactory(const std::string& address, unsigned short port) : server_acceptor_(io_ctx_) +{ + LogFunc << VAR(address) << VAR(port); + + using namespace boost::asio::ip; + + tcp::endpoint endpoint(address::from_string(address), port); + + server_acceptor_.open(endpoint.protocol()); + server_acceptor_.set_option(tcp::acceptor::reuse_address(true)); + server_acceptor_.bind(endpoint); + + server_acceptor_.listen(); +} + +ServerSockIOFactory::~ServerSockIOFactory() +{ + LogFunc; + + server_acceptor_.close(); +} + +unsigned short ServerSockIOFactory::port() const +{ + return server_acceptor_.local_endpoint().port(); +} + +std::shared_ptr ServerSockIOFactory::accept() +{ + LogFunc; + + auto sock = server_acceptor_.accept(); + if (!sock.is_open()) { + LogError << "socket is not opened"; + return nullptr; + } + + return std::make_shared(std::move(sock)); +} + +ClientSockIOFactory::ClientSockIOFactory(const std::string& address, unsigned short port) + : endpoint_(boost::asio::ip::address::from_string(address), port) +{ + LogFunc << VAR(address) << VAR(port); +} + +std::shared_ptr ClientSockIOFactory::connect() +{ + LogFunc; + + boost::asio::ip::tcp::socket sock(io_ctx_); + sock.connect(endpoint_); + if (!sock.is_open()) { + LogError << "socket is not opened"; + return nullptr; + } + + return std::make_shared(std::move(sock)); +} + +SockIOStream::SockIOStream(boost::asio::ip::tcp::socket&& sock) + : sock_(std::move(sock)), buffer_(std::make_unique(kBufferSize)) +{} + +SockIOStream::~SockIOStream() +{ + sock_.close(); +} + +bool SockIOStream::write(std::string_view data) +{ + if (!sock_.is_open()) { + return false; + } + + sock_.write_some(boost::asio::buffer(data)); + return true; +} + +std::string SockIOStream::read(std::chrono::seconds timeout, size_t count) +{ + auto start_time = std::chrono::steady_clock::now(); + auto check_timeout = [&](const auto& start_time) -> bool { + return std::chrono::steady_clock::now() - start_time < timeout; + }; + + std::string result; + + while (check_timeout(start_time) && count > result.size() && sock_.is_open()) { + auto read_size = std::min(kBufferSize, count - result.size()); + auto read_num = sock_.read_some(boost::asio::mutable_buffer(buffer_.get(), read_size)); + if (read_num > 0) { + result.append(buffer_.get(), read_num); + } + } + + return result; +} + +MAA_NS_END diff --git a/source/include/Utils/Boost.hpp b/source/include/Utils/Boost.hpp index 0a3b55495..e06b07f3c 100644 --- a/source/include/Utils/Boost.hpp +++ b/source/include/Utils/Boost.hpp @@ -18,7 +18,4 @@ MAA_SUPPRESS_BOOST_WARNINGS_BEGIN #include #endif #include -#include -#include -#include MAA_SUPPRESS_BOOST_WARNINGS_END diff --git a/source/include/Utils/IOStream/ChildPipeIOStream.h b/source/include/Utils/IOStream/ChildPipeIOStream.h new file mode 100644 index 000000000..0ff7d50df --- /dev/null +++ b/source/include/Utils/IOStream/ChildPipeIOStream.h @@ -0,0 +1,33 @@ +#pragma once + +#include + +#include "MaaFramework/MaaPort.h" +#include "Utils/Boost.hpp" +#include "Utils/NonCopyable.hpp" + +MAA_NS_BEGIN + +class MAA_UTILS_API ChildPipeIOStream : public NonCopyButMovable +{ + static constexpr size_t kBufferSize = 128 * 1024; + +public: + ChildPipeIOStream(const std::filesystem::path& exec, const std::vector& args); + + virtual ~ChildPipeIOStream(); + +public: + bool write(std::string_view data); + std::string read(std::chrono::seconds timeout, size_t count = SIZE_MAX); + int release(); + +private: + boost::process::opstream pin_; + boost::process::ipstream pout_; + boost::process::child child_; + + std::unique_ptr buffer_ = nullptr; +}; + +MAA_NS_END diff --git a/source/include/Utils/IOStream/SockIOStream.h b/source/include/Utils/IOStream/SockIOStream.h new file mode 100644 index 000000000..49deda804 --- /dev/null +++ b/source/include/Utils/IOStream/SockIOStream.h @@ -0,0 +1,61 @@ +#pragma once + +#include + +#include "MaaFramework/MaaPort.h" +#include "Utils/Boost.hpp" +#include "Utils/NonCopyable.hpp" + +MAA_NS_BEGIN + +class MAA_UTILS_API SockIOStream; + +class MAA_UTILS_API ServerSockIOFactory : public NonCopyButMovable +{ +public: + ServerSockIOFactory(const std::string& address, unsigned short port); + ~ServerSockIOFactory(); + + unsigned short port() const; + +public: + std::shared_ptr accept(); + +private: + boost::asio::io_context io_ctx_; + boost::asio::ip::tcp::acceptor server_acceptor_; +}; + +class MAA_UTILS_API ClientSockIOFactory : public NonCopyButMovable +{ +public: + ClientSockIOFactory(const std::string& address, unsigned short port); + ~ClientSockIOFactory() = default; + +public: + std::shared_ptr connect(); + +private: + boost::asio::io_context io_ctx_; + boost::asio::ip::tcp::endpoint endpoint_; +}; + +class MAA_UTILS_API SockIOStream : public NonCopyButMovable +{ + static constexpr size_t kBufferSize = 128 * 1024; + +public: + SockIOStream(boost::asio::ip::tcp::socket&& sock); + ~SockIOStream(); + +public: + bool write(std::string_view data); + std::string read(std::chrono::seconds timeout, size_t count = SIZE_MAX); + +private: + boost::asio::ip::tcp::socket sock_; + + std::unique_ptr buffer_ = nullptr; +}; + +MAA_NS_END diff --git a/source/include/Utils/NonCopyable.hpp b/source/include/Utils/NonCopyable.hpp index 4066ac643..f933398ba 100644 --- a/source/include/Utils/NonCopyable.hpp +++ b/source/include/Utils/NonCopyable.hpp @@ -1,17 +1,31 @@ #pragma once #include "Conf/Conf.h" +#include "MaaFramework/MaaPort.h" MAA_NS_BEGIN -class NonCopyable +class MAA_UTILS_API NonCopyButMovable +{ +public: + NonCopyButMovable(const NonCopyButMovable&) = delete; + NonCopyButMovable(NonCopyButMovable&&) = default; + + NonCopyButMovable& operator=(const NonCopyButMovable&) = delete; + NonCopyButMovable& operator=(NonCopyButMovable&&) = default; + +protected: + NonCopyButMovable() = default; +}; + +class MAA_UTILS_API NonCopyable { public: NonCopyable(const NonCopyable&) = delete; NonCopyable(NonCopyable&&) = delete; - NonCopyable operator=(const NonCopyable&) = delete; - NonCopyable operator=(NonCopyable&&) = delete; + NonCopyable& operator=(const NonCopyable&) = delete; + NonCopyable& operator=(NonCopyable&&) = delete; protected: NonCopyable() = default; diff --git a/source/include/Utils/StringMisc.hpp b/source/include/Utils/StringMisc.hpp index 7f5b7199e..1eae8fcd6 100644 --- a/source/include/Utils/StringMisc.hpp +++ b/source/include/Utils/StringMisc.hpp @@ -43,19 +43,9 @@ inline constexpr void string_replace_all_(StringT& str, string_detail::sv_type -requires IsSomeKindOfString -inline constexpr void string_replace_all_(StringT& str, - std::initializer_list> replace_pairs) -{ - for (auto&& [from, to] : replace_pairs) { - string_replace_all_(str, from, to); - } -} - -template +template requires IsSomeKindOfString -inline constexpr void string_replace_all_(StringT& str, const std::map& replace_map) +inline constexpr void string_replace_all_(StringT& str, const MapT& replace_map) { for (const auto& [from, to] : replace_map) { string_replace_all_(str, from, to); @@ -102,20 +92,9 @@ requires IsSomeKindOfString return result; } -template -requires IsSomeKindOfString -[[nodiscard]] inline constexpr auto string_replace_all( - StringT&& str, std::initializer_list> replace_pairs) -{ - std::decay_t result = std::forward(str); - string_replace_all_(result, replace_pairs); - return result; -} - -template +template requires IsSomeKindOfString -[[nodiscard]] inline constexpr auto string_replace_all(const StringT& str, - const std::map& replace_map) +[[nodiscard]] inline constexpr auto string_replace_all(const StringT& str, const MapT& replace_map) { StringT result = str; string_replace_all_(result, replace_map); From 20b89c0a30f6ecb3134aec0f96d3b6d2d236b292 Mon Sep 17 00:00:00 2001 From: MistEO Date: Tue, 5 Dec 2023 16:44:33 +0800 Subject: [PATCH 05/23] =?UTF-8?q?chore:=20=E4=B8=BA=20iostream=20read=20?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E9=BB=98=E8=AE=A4=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/MaaUtils/IOStream/ChildPipeIOStream.cpp | 2 +- source/MaaUtils/IOStream/SockIOStream.cpp | 2 +- source/include/Utils/IOStream/ChildPipeIOStream.h | 2 +- source/include/Utils/IOStream/SockIOStream.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/source/MaaUtils/IOStream/ChildPipeIOStream.cpp b/source/MaaUtils/IOStream/ChildPipeIOStream.cpp index 7c9af1aae..5026a196a 100644 --- a/source/MaaUtils/IOStream/ChildPipeIOStream.cpp +++ b/source/MaaUtils/IOStream/ChildPipeIOStream.cpp @@ -32,7 +32,7 @@ std::string ChildPipeIOStream::read(std::chrono::seconds timeout, size_t count) { auto start_time = std::chrono::steady_clock::now(); auto check_timeout = [&](const auto& start_time) -> bool { - return std::chrono::steady_clock::now() - start_time < timeout; + return timeout > std::chrono::seconds(0) && std::chrono::steady_clock::now() - start_time < timeout; }; std::string result; diff --git a/source/MaaUtils/IOStream/SockIOStream.cpp b/source/MaaUtils/IOStream/SockIOStream.cpp index a1407d920..e7c7cdcaf 100644 --- a/source/MaaUtils/IOStream/SockIOStream.cpp +++ b/source/MaaUtils/IOStream/SockIOStream.cpp @@ -87,7 +87,7 @@ std::string SockIOStream::read(std::chrono::seconds timeout, size_t count) { auto start_time = std::chrono::steady_clock::now(); auto check_timeout = [&](const auto& start_time) -> bool { - return std::chrono::steady_clock::now() - start_time < timeout; + return timeout > std::chrono::seconds(0) && std::chrono::steady_clock::now() - start_time < timeout; }; std::string result; diff --git a/source/include/Utils/IOStream/ChildPipeIOStream.h b/source/include/Utils/IOStream/ChildPipeIOStream.h index 0ff7d50df..9f45e32d7 100644 --- a/source/include/Utils/IOStream/ChildPipeIOStream.h +++ b/source/include/Utils/IOStream/ChildPipeIOStream.h @@ -19,7 +19,7 @@ class MAA_UTILS_API ChildPipeIOStream : public NonCopyButMovable public: bool write(std::string_view data); - std::string read(std::chrono::seconds timeout, size_t count = SIZE_MAX); + std::string read(std::chrono::seconds timeout = std::chrono::seconds(-1), size_t count = SIZE_MAX); int release(); private: diff --git a/source/include/Utils/IOStream/SockIOStream.h b/source/include/Utils/IOStream/SockIOStream.h index 49deda804..ec4443efa 100644 --- a/source/include/Utils/IOStream/SockIOStream.h +++ b/source/include/Utils/IOStream/SockIOStream.h @@ -50,7 +50,7 @@ class MAA_UTILS_API SockIOStream : public NonCopyButMovable public: bool write(std::string_view data); - std::string read(std::chrono::seconds timeout, size_t count = SIZE_MAX); + std::string read(std::chrono::seconds timeout = std::chrono::seconds(-1), size_t count = SIZE_MAX); private: boost::asio::ip::tcp::socket sock_; From 86cbb3720ed1dcf8b93db16484b3e763b22a8a30 Mon Sep 17 00:00:00 2001 From: MistEO Date: Tue, 5 Dec 2023 16:51:19 +0800 Subject: [PATCH 06/23] fix: typo --- source/MaaAdbControlUnit/Screencap/Minicap/MinicapBase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/MaaAdbControlUnit/Screencap/Minicap/MinicapBase.cpp b/source/MaaAdbControlUnit/Screencap/Minicap/MinicapBase.cpp index 04827e4fa..2aa39fe3d 100644 --- a/source/MaaAdbControlUnit/Screencap/Minicap/MinicapBase.cpp +++ b/source/MaaAdbControlUnit/Screencap/Minicap/MinicapBase.cpp @@ -26,7 +26,7 @@ bool MinicapBase::parse(const json::value& config) static const json::array kDefaultSdk = { 31, 29, 28, 27, 26, 25, 24, 23, 22, 21, 19, 18, 17, 16, 15, 14, }; - json::array jsdk = config.get("prebuilt", "minicap", "sdk_opt", kDefaultSdk); + json::array jsdk = config.get("prebuilt", "minicap", "sdk", kDefaultSdk); sdk_list_ = jsdk.to_vector(); return binary_->parse(config) && library_->parse(config); From f00cf19ea518badbb344f41bfb06a4a6ce2be5d4 Mon Sep 17 00:00:00 2001 From: MistEO Date: Tue, 5 Dec 2023 17:04:25 +0800 Subject: [PATCH 07/23] fix: iostream time error --- source/MaaUtils/IOStream/ChildPipeIOStream.cpp | 2 +- source/MaaUtils/IOStream/SockIOStream.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/source/MaaUtils/IOStream/ChildPipeIOStream.cpp b/source/MaaUtils/IOStream/ChildPipeIOStream.cpp index 5026a196a..14c68ebf5 100644 --- a/source/MaaUtils/IOStream/ChildPipeIOStream.cpp +++ b/source/MaaUtils/IOStream/ChildPipeIOStream.cpp @@ -32,7 +32,7 @@ std::string ChildPipeIOStream::read(std::chrono::seconds timeout, size_t count) { auto start_time = std::chrono::steady_clock::now(); auto check_timeout = [&](const auto& start_time) -> bool { - return timeout > std::chrono::seconds(0) && std::chrono::steady_clock::now() - start_time < timeout; + return timeout < std::chrono::seconds(0) || std::chrono::steady_clock::now() - start_time < timeout; }; std::string result; diff --git a/source/MaaUtils/IOStream/SockIOStream.cpp b/source/MaaUtils/IOStream/SockIOStream.cpp index e7c7cdcaf..eeca4567b 100644 --- a/source/MaaUtils/IOStream/SockIOStream.cpp +++ b/source/MaaUtils/IOStream/SockIOStream.cpp @@ -87,7 +87,7 @@ std::string SockIOStream::read(std::chrono::seconds timeout, size_t count) { auto start_time = std::chrono::steady_clock::now(); auto check_timeout = [&](const auto& start_time) -> bool { - return timeout > std::chrono::seconds(0) && std::chrono::steady_clock::now() - start_time < timeout; + return timeout < std::chrono::seconds(0) || std::chrono::steady_clock::now() - start_time < timeout; }; std::string result; From e434ed7b2e0f0c434e9afc087fcce643dde38797 Mon Sep 17 00:00:00 2001 From: MistEO Date: Tue, 5 Dec 2023 18:28:32 +0800 Subject: [PATCH 08/23] =?UTF-8?q?refactor:=20=E6=95=B4=E7=90=86=20IOStream?= =?UTF-8?q?=20read=20=E7=9B=B8=E5=85=B3=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Screencap/Minicap/MinicapStream.cpp | 2 +- .../MaaUtils/IOStream/ChildPipeIOStream.cpp | 42 ++++++++++++++----- source/MaaUtils/IOStream/SockIOStream.cpp | 34 +++++++++++---- .../Utils/IOStream/ChildPipeIOStream.h | 12 ++++-- source/include/Utils/IOStream/SockIOStream.h | 7 +++- source/include/Utils/Time.hpp | 5 ++- 6 files changed, 76 insertions(+), 26 deletions(-) diff --git a/source/MaaAdbControlUnit/Screencap/Minicap/MinicapStream.cpp b/source/MaaAdbControlUnit/Screencap/Minicap/MinicapStream.cpp index 3f779ca04..a1411a076 100644 --- a/source/MaaAdbControlUnit/Screencap/Minicap/MinicapStream.cpp +++ b/source/MaaAdbControlUnit/Screencap/Minicap/MinicapStream.cpp @@ -150,7 +150,7 @@ std::optional MinicapStream::read(size_t count) } using namespace std::chrono_literals; - return stream_handle_->read(5s, count); + return stream_handle_->read_some(count, 5s); } void MinicapStream::working_thread() diff --git a/source/MaaUtils/IOStream/ChildPipeIOStream.cpp b/source/MaaUtils/IOStream/ChildPipeIOStream.cpp index 14c68ebf5..e3b4491bb 100644 --- a/source/MaaUtils/IOStream/ChildPipeIOStream.cpp +++ b/source/MaaUtils/IOStream/ChildPipeIOStream.cpp @@ -1,10 +1,12 @@ #include "Utils/IOStream/ChildPipeIOStream.h" +#include "Utils/Time.hpp" + MAA_NS_BEGIN ChildPipeIOStream::ChildPipeIOStream(const std::filesystem::path& exec, const std::vector& args) : child_( // - exec, args, boost::process::std_out > pout_, boost::process::std_err > pout_, boost::process::std_in < pin_ + exec, args, boost::process::std_out > pin_, boost::process::std_err > pin_, boost::process::std_in < pout_ #ifdef _WIN32 , boost::process::windows::create_no_window @@ -24,25 +26,43 @@ bool ChildPipeIOStream::write(std::string_view data) return false; } - pin_ << data << std::endl; + pout_ << data << std::endl; return true; } -std::string ChildPipeIOStream::read(std::chrono::seconds timeout, size_t count) +std::string ChildPipeIOStream::read(duration_t timeout) { - auto start_time = std::chrono::steady_clock::now(); - auto check_timeout = [&](const auto& start_time) -> bool { - return timeout < std::chrono::seconds(0) || std::chrono::steady_clock::now() - start_time < timeout; - }; + return read_some(std::numeric_limits::max(), timeout); +} +std::string ChildPipeIOStream::read_some(size_t count, duration_t timeout) +{ + auto start_time = std::chrono::steady_clock::now(); std::string result; - while (check_timeout(start_time) && count > result.size() && child_.running()) { + while (child_.running() && result.size() < count && duration_since(start_time) < timeout) { auto read_size = std::min(kBufferSize, count - result.size()); - auto read_num = pout_.readsome(buffer_.get(), read_size); - if (read_num > 0) { - result.append(buffer_.get(), read_num); + auto read_num = pin_.readsome(buffer_.get(), read_size); + result.append(buffer_.get(), read_num); + } + + return result; +} + +std::string ChildPipeIOStream::read_until(std::string_view delimiter, duration_t timeout) +{ + auto start_time = std::chrono::steady_clock::now(); + + std::string result; + + while (!result.ends_with(delimiter)) { + auto sub_timeout = timeout - duration_since(start_time); + if (sub_timeout < duration_t::zero()) { + break; } + + auto sub_str = read_some(1, sub_timeout); + result.append(std::move(sub_str)); } return result; diff --git a/source/MaaUtils/IOStream/SockIOStream.cpp b/source/MaaUtils/IOStream/SockIOStream.cpp index eeca4567b..a22dc4a13 100644 --- a/source/MaaUtils/IOStream/SockIOStream.cpp +++ b/source/MaaUtils/IOStream/SockIOStream.cpp @@ -83,21 +83,39 @@ bool SockIOStream::write(std::string_view data) return true; } -std::string SockIOStream::read(std::chrono::seconds timeout, size_t count) +std::string SockIOStream::read(duration_t timeout) { - auto start_time = std::chrono::steady_clock::now(); - auto check_timeout = [&](const auto& start_time) -> bool { - return timeout < std::chrono::seconds(0) || std::chrono::steady_clock::now() - start_time < timeout; - }; + return read_some(std::numeric_limits::max(), timeout); +} +std::string SockIOStream::read_some(size_t count, duration_t timeout) +{ + auto start_time = std::chrono::steady_clock::now(); std::string result; - while (check_timeout(start_time) && count > result.size() && sock_.is_open()) { + while (sock_.is_open() && result.size() < count && duration_since(start_time) < timeout) { auto read_size = std::min(kBufferSize, count - result.size()); auto read_num = sock_.read_some(boost::asio::mutable_buffer(buffer_.get(), read_size)); - if (read_num > 0) { - result.append(buffer_.get(), read_num); + result.append(buffer_.get(), read_num); + } + + return result; +} + +std::string SockIOStream::read_until(std::string_view delimiter, duration_t timeout) +{ + auto start_time = std::chrono::steady_clock::now(); + + std::string result; + + while (!result.ends_with(delimiter)) { + auto sub_timeout = timeout - duration_since(start_time); + if (sub_timeout < duration_t::zero()) { + break; } + + auto sub_str = read_some(1, sub_timeout); + result.append(std::move(sub_str)); } return result; diff --git a/source/include/Utils/IOStream/ChildPipeIOStream.h b/source/include/Utils/IOStream/ChildPipeIOStream.h index 9f45e32d7..b74ae11af 100644 --- a/source/include/Utils/IOStream/ChildPipeIOStream.h +++ b/source/include/Utils/IOStream/ChildPipeIOStream.h @@ -10,6 +10,8 @@ MAA_NS_BEGIN class MAA_UTILS_API ChildPipeIOStream : public NonCopyButMovable { + using duration_t = std::chrono::milliseconds; + static constexpr size_t kBufferSize = 128 * 1024; public: @@ -19,12 +21,16 @@ class MAA_UTILS_API ChildPipeIOStream : public NonCopyButMovable public: bool write(std::string_view data); - std::string read(std::chrono::seconds timeout = std::chrono::seconds(-1), size_t count = SIZE_MAX); + + std::string read(duration_t timeout = duration_t::max()); + std::string read_some(size_t count, duration_t timeout = duration_t::max()); + std::string read_until(std::string_view delimiter, duration_t timeout = duration_t::max()); + int release(); private: - boost::process::opstream pin_; - boost::process::ipstream pout_; + boost::process::ipstream pin_; + boost::process::opstream pout_; boost::process::child child_; std::unique_ptr buffer_ = nullptr; diff --git a/source/include/Utils/IOStream/SockIOStream.h b/source/include/Utils/IOStream/SockIOStream.h index ec4443efa..111acd255 100644 --- a/source/include/Utils/IOStream/SockIOStream.h +++ b/source/include/Utils/IOStream/SockIOStream.h @@ -42,6 +42,8 @@ class MAA_UTILS_API ClientSockIOFactory : public NonCopyButMovable class MAA_UTILS_API SockIOStream : public NonCopyButMovable { + using duration_t = std::chrono::milliseconds; + static constexpr size_t kBufferSize = 128 * 1024; public: @@ -50,7 +52,10 @@ class MAA_UTILS_API SockIOStream : public NonCopyButMovable public: bool write(std::string_view data); - std::string read(std::chrono::seconds timeout = std::chrono::seconds(-1), size_t count = SIZE_MAX); + + std::string read(duration_t timeout = duration_t::max()); + std::string read_some(size_t count, duration_t timeout = duration_t::max()); + std::string read_until(std::string_view delimiter, duration_t timeout = duration_t::max()); private: boost::asio::ip::tcp::socket sock_; diff --git a/source/include/Utils/Time.hpp b/source/include/Utils/Time.hpp index 3c9076b21..b458c9535 100644 --- a/source/include/Utils/Time.hpp +++ b/source/include/Utils/Time.hpp @@ -43,9 +43,10 @@ inline std::string now_filestem() #endif } -inline std::chrono::milliseconds duration_since(const std::chrono::steady_clock::time_point& start_time) +template +inline duration_t duration_since(const std::chrono::steady_clock::time_point& start_time) { - return std::chrono::duration_cast(std::chrono::steady_clock::now() - start_time); + return std::chrono::duration_cast(std::chrono::steady_clock::now() - start_time); } MAA_NS_END From deec098ead7ba54661ad43dcd9a924c092c4053f Mon Sep 17 00:00:00 2001 From: MistEO Date: Tue, 5 Dec 2023 18:29:41 +0800 Subject: [PATCH 09/23] feat: impl for ExecAgent --- source/MaaToolKit/API/MaaToolKitExecAgent.cpp | 4 -- source/MaaToolKit/CMakeLists.txt | 2 +- .../MaaToolKit/ExecAgent/ActionExecAgent.cpp | 33 +++++++++++- source/MaaToolKit/ExecAgent/ActionExecAgent.h | 2 +- source/MaaToolKit/ExecAgent/ExecAgentBase.cpp | 52 +++++++++++++++++-- source/MaaToolKit/ExecAgent/ExecAgentBase.h | 10 +++- source/MaaToolKit/ExecAgent/ExecAgentType.h | 2 +- .../MaaToolKit/ExecAgent/ExecArgConverter.cpp | 49 +++++++++++++++++ .../MaaToolKit/ExecAgent/ExecArgConverter.h | 30 +++++++++++ .../ExecAgent/RecognizerExecAgent.cpp | 25 +++++++-- .../ExecAgent/RecognizerExecAgent.h | 5 +- .../MaaUtils/IOStream/ChildPipeIOStream.cpp | 5 ++ source/MaaUtils/IOStream/SockIOStream.cpp | 5 ++ .../Utils/IOStream/ChildPipeIOStream.h | 1 + source/include/Utils/IOStream/SockIOStream.h | 2 + 15 files changed, 209 insertions(+), 18 deletions(-) create mode 100644 source/MaaToolKit/ExecAgent/ExecArgConverter.cpp create mode 100644 source/MaaToolKit/ExecAgent/ExecArgConverter.h diff --git a/source/MaaToolKit/API/MaaToolKitExecAgent.cpp b/source/MaaToolKit/API/MaaToolKitExecAgent.cpp index dac8788d0..5193920bb 100644 --- a/source/MaaToolKit/API/MaaToolKitExecAgent.cpp +++ b/source/MaaToolKit/API/MaaToolKitExecAgent.cpp @@ -43,10 +43,6 @@ MaaBool RegisterExecutor(ExecutorType type, MaaInstanceHandle handle, MaaStringV } auto path = MAA_NS::path(exec_path); - if (!std::filesystem::exists(path)) { - LogError << "exec path not exists:" << path; - return false; - } auto params_opt = json::parse(exec_param_json); if (!params_opt) { diff --git a/source/MaaToolKit/CMakeLists.txt b/source/MaaToolKit/CMakeLists.txt index 1ea6a3dc7..c8d66af9b 100644 --- a/source/MaaToolKit/CMakeLists.txt +++ b/source/MaaToolKit/CMakeLists.txt @@ -13,7 +13,7 @@ target_compile_definitions(MaaToolKit PRIVATE MAA_TOOLKIT_EXPORTS) target_link_libraries( MaaToolKit PUBLIC MaaFramework - PRIVATE MaaUtils LibraryHolder HeaderOnlyLibraries Boost::system) + PRIVATE MaaUtils LibraryHolder HeaderOnlyLibraries Boost::system ${OpenCV_LIBS}) add_dependencies(MaaToolKit MaaFramework MaaUtils LibraryHolder) diff --git a/source/MaaToolKit/ExecAgent/ActionExecAgent.cpp b/source/MaaToolKit/ExecAgent/ActionExecAgent.cpp index 8638667b0..95ddf3f30 100644 --- a/source/MaaToolKit/ExecAgent/ActionExecAgent.cpp +++ b/source/MaaToolKit/ExecAgent/ActionExecAgent.cpp @@ -26,10 +26,39 @@ bool ActionExecAgent::unregister_for_maa_inst(MaaInstanceHandle handle, std::str bool ActionExecAgent::run(MaaSyncContextHandle sync_context, std::string_view task_name, std::string_view custom_action_param, MaaRectHandle cur_box, std::string_view cur_rec_detail) { - return false; + LogFunc << VAR_VOIDP(sync_context) << VAR(task_name) << VAR(custom_action_param) << VAR_VOIDP(cur_box) + << VAR(cur_rec_detail); + + auto exec_it = executors_.find(std::string(task_name)); + if (exec_it == executors_.end()) { + LogError << "executor not found" << VAR(task_name); + return false; + } + auto& exec = exec_it->second; + + std::string handle_arg = arg_cvt_.sync_context_to_arg(sync_context); + std::string box_arg = json::array({ cur_box->x, cur_box->y, cur_box->width, cur_box->height }).to_string(); + + std::vector extra_args = { handle_arg, std::string(task_name), std::string(custom_action_param), + box_arg, std::string(cur_rec_detail) }; + std::vector args = exec.exec_args; + args.insert(args.end(), std::make_move_iterator(extra_args.begin()), std::make_move_iterator(extra_args.end())); + + auto output_opt = run_executor(exec.text_mode, exec.exec_path, args); + if (!output_opt) { + LogError << "run_executor failed" << VAR(exec.exec_path) << VAR(exec.exec_args); + return false; + } + + return true; } -void ActionExecAgent::stop() {} +void ActionExecAgent::stop() +{ + LogFunc; + + // TODO +} MaaBool ActionExecAgent::maa_api_run(MaaSyncContextHandle sync_context, MaaStringView task_name, MaaStringView custom_action_param, MaaRectHandle cur_box, diff --git a/source/MaaToolKit/ExecAgent/ActionExecAgent.h b/source/MaaToolKit/ExecAgent/ActionExecAgent.h index 62707bb93..ead360fc5 100644 --- a/source/MaaToolKit/ExecAgent/ActionExecAgent.h +++ b/source/MaaToolKit/ExecAgent/ActionExecAgent.h @@ -31,7 +31,7 @@ class ActionExecAgent final : public ExecAgentBase, public SingletonHolder exec_params, TextTransferMode text_mode, + std::vector exec_args, TextTransferMode text_mode, ImageTransferMode image_mode) { - LogFunc << VAR_VOIDP(handle) << VAR(name) << VAR(exec_path) << VAR(exec_params) << VAR(text_mode) - << VAR(image_mode); + LogFunc << VAR_VOIDP(handle) << VAR(name) << VAR(exec_path) << VAR(exec_args) << VAR(text_mode) << VAR(image_mode); bool registered = register_for_maa_inst(handle, name); if (!registered) { @@ -20,7 +22,7 @@ bool ExecAgentBase::register_executor(MaaInstanceHandle handle, std::string_view Executor executor { .name = std::string(name), .exec_path = std::move(exec_path), - .exec_params = std::move(exec_params), + .exec_args = std::move(exec_args), .text_mode = text_mode, .image_mode = image_mode, }; @@ -46,4 +48,46 @@ bool ExecAgentBase::unregister_executor(MaaInstanceHandle handle, std::string_vi return ret; } +std::optional ExecAgentBase::run_executor(TextTransferMode mode, const std::filesystem::path& exec_path, + const std::vector& exec_args) +{ + switch (mode) { + case TextTransferMode::StdIO: { + return run_executor_with_stdio(exec_path, exec_args); + } + case TextTransferMode::FileIO: + default: + LogError << "not implemented"; + return std::nullopt; + } +} + +std::optional ExecAgentBase::run_executor_with_stdio(const std::filesystem::path& exec_path, + const std::vector& exec_args) +{ + auto searched_path = boost::process::search_path(exec_path); + if (!std::filesystem::exists(searched_path)) { + LogError << "path not exists" << VAR(searched_path); + return std::nullopt; + } + + ChildPipeIOStream ios(searched_path, exec_args); + + while (ios.is_open()) { + std::string line = ios.read_until("\n"); + LogInfo << "read line:" << line; + + // TODO + } + + int exit_code = ios.release(); + if (exit_code != 0) { + LogError << "process exit with code:" << exit_code; + return std::nullopt; + } + + // TODO + return {}; +} + MAA_TOOLKIT_NS_END diff --git a/source/MaaToolKit/ExecAgent/ExecAgentBase.h b/source/MaaToolKit/ExecAgent/ExecAgentBase.h index 350b81c44..c1c535c81 100644 --- a/source/MaaToolKit/ExecAgent/ExecAgentBase.h +++ b/source/MaaToolKit/ExecAgent/ExecAgentBase.h @@ -5,6 +5,7 @@ #include #include +#include "ExecAgent/ExecArgConverter.h" #include "ExecAgentType.h" #include "MaaFramework/MaaDef.h" @@ -16,7 +17,7 @@ class ExecAgentBase virtual ~ExecAgentBase() = default; bool register_executor(MaaInstanceHandle handle, std::string_view name, std::filesystem::path exec_path, - std::vector exec_params, TextTransferMode text_mode, + std::vector exec_args, TextTransferMode text_mode, ImageTransferMode image_mode); bool unregister_executor(MaaInstanceHandle handle, std::string_view name); @@ -24,8 +25,15 @@ class ExecAgentBase virtual bool register_for_maa_inst(MaaInstanceHandle handle, std::string_view name) = 0; virtual bool unregister_for_maa_inst(MaaInstanceHandle handle, std::string_view name) = 0; + std::optional run_executor(TextTransferMode mode, const std::filesystem::path& exec_path, + const std::vector& exec_args); + std::optional run_executor_with_stdio(const std::filesystem::path& exec_path, + const std::vector& exec_args); + protected: std::unordered_map executors_; + + ExecArgConverter arg_cvt_; }; MAA_TOOLKIT_NS_END diff --git a/source/MaaToolKit/ExecAgent/ExecAgentType.h b/source/MaaToolKit/ExecAgent/ExecAgentType.h index 083bb37be..0da17ba21 100644 --- a/source/MaaToolKit/ExecAgent/ExecAgentType.h +++ b/source/MaaToolKit/ExecAgent/ExecAgentType.h @@ -45,7 +45,7 @@ struct Executor { std::string name; std::filesystem::path exec_path; - std::vector exec_params; + std::vector exec_args; TextTransferMode text_mode; ImageTransferMode image_mode; }; diff --git a/source/MaaToolKit/ExecAgent/ExecArgConverter.cpp b/source/MaaToolKit/ExecAgent/ExecArgConverter.cpp new file mode 100644 index 000000000..474f8ad9a --- /dev/null +++ b/source/MaaToolKit/ExecAgent/ExecArgConverter.cpp @@ -0,0 +1,49 @@ +#include "ExecArgConverter.h" + +#include "MaaFramework/MaaAPI.h" +#include "Utils/ImageIo.h" +#include "Utils/Logger.h" +#include "Utils/Time.hpp" + +MAA_TOOLKIT_NS_BEGIN + +ExecArgConverter::~ExecArgConverter() +{ + for (const auto& image : images_) { + std::filesystem::remove(image); + } +} + +std::string ExecArgConverter::sync_context_to_arg(MaaSyncContextHandle sync_context) +{ + std::string uuid = std::to_string(reinterpret_cast(sync_context)); + sync_contexts_.insert_or_assign(uuid, sync_context); + return uuid; +} + +std::string ExecArgConverter::image_to_arg(ImageTransferMode mode, const cv::Mat& image) +{ + switch (mode) { + case ImageTransferMode::FileIO: { + auto path = std::filesystem::temp_directory_path() / now_filestem() / ".png"; + imwrite(path, image); + images_.push_back(path); + return path_to_crt_string(path); + } + default: + LogError << "not implemented"; + return {}; + } +} + +MaaSyncContextHandle ExecArgConverter::arg_to_sync_context(const std::string& arg) const +{ + auto it = sync_contexts_.find(arg); + if (it == sync_contexts_.end()) { + LogError << "sync context not found"; + return nullptr; + } + return it->second; +} + +MAA_TOOLKIT_NS_END diff --git a/source/MaaToolKit/ExecAgent/ExecArgConverter.h b/source/MaaToolKit/ExecAgent/ExecArgConverter.h new file mode 100644 index 000000000..30fcb6df2 --- /dev/null +++ b/source/MaaToolKit/ExecAgent/ExecArgConverter.h @@ -0,0 +1,30 @@ +#pragma once + +#include "Conf/Conf.h" + +#include +#include + +#include "ExecAgentType.h" +#include "MaaFramework/MaaDef.h" +#include "Utils/NoWarningCVMat.hpp" + +MAA_TOOLKIT_NS_BEGIN + +class ExecArgConverter +{ +public: + ~ExecArgConverter(); + +public: + std::string sync_context_to_arg(MaaSyncContextHandle sync_context); + std::string image_to_arg(ImageTransferMode mode, const cv::Mat& image); + + MaaSyncContextHandle arg_to_sync_context(const std::string& arg) const; + +private: + std::map sync_contexts_; + std::vector images_; +}; + +MAA_TOOLKIT_NS_END diff --git a/source/MaaToolKit/ExecAgent/RecognizerExecAgent.cpp b/source/MaaToolKit/ExecAgent/RecognizerExecAgent.cpp index e53df135e..26b5b2a34 100644 --- a/source/MaaToolKit/ExecAgent/RecognizerExecAgent.cpp +++ b/source/MaaToolKit/ExecAgent/RecognizerExecAgent.cpp @@ -3,7 +3,9 @@ #include #include "MaaFramework/MaaAPI.h" +#include "Utils/ImageIo.h" #include "Utils/Logger.h" +#include "Utils/Time.hpp" MAA_TOOLKIT_NS_BEGIN @@ -28,12 +30,29 @@ std::optional RecognizerExecAgent::analyze( { LogFunc << VAR_VOIDP(sync_context) << VAR(image.size()) << VAR(task_name) << VAR(custom_recognition_param); - auto exec_it = executors_.find(task_name.data()); + auto exec_it = executors_.find(std::string(task_name)); if (exec_it == executors_.end()) { - LogError << "no executor found for task: " << task_name; + LogError << "executor not found" << VAR(task_name); return std::nullopt; } - auto& executor = exec_it->second; + auto& exec = exec_it->second; + + std::string handle_arg = arg_cvt_.sync_context_to_arg(sync_context); + std::string image_arg = arg_cvt_.image_to_arg(exec.image_mode, image); + + std::vector extra_args = { handle_arg, image_arg, std::string(task_name), + std::string(custom_recognition_param) }; + std::vector args = exec.exec_args; + args.insert(args.end(), std::make_move_iterator(extra_args.begin()), std::make_move_iterator(extra_args.end())); + + auto output_opt = run_executor(exec.text_mode, exec.exec_path, args); + if (!output_opt) { + LogError << "run_executor failed" << VAR(exec.exec_path) << VAR(exec.exec_args); + return std::nullopt; + } + + // TODO: parse output to get result + return {}; } MaaBool RecognizerExecAgent::maa_api_analyze( // diff --git a/source/MaaToolKit/ExecAgent/RecognizerExecAgent.h b/source/MaaToolKit/ExecAgent/RecognizerExecAgent.h index 51d56c45e..7efc1dd18 100644 --- a/source/MaaToolKit/ExecAgent/RecognizerExecAgent.h +++ b/source/MaaToolKit/ExecAgent/RecognizerExecAgent.h @@ -3,6 +3,9 @@ #include "Conf/Conf.h" #include "ExecAgentBase.h" +#include +#include + #include "MaaFramework/Task/MaaCustomRecognizer.h" #include "Utils/NoWarningCVMat.hpp" #include "Utils/SingletonHolder.hpp" @@ -38,7 +41,7 @@ class RecognizerExecAgent final : public ExecAgentBase, public SingletonHolder Date: Wed, 6 Dec 2023 00:07:18 +0800 Subject: [PATCH 10/23] fix: ChildPipeIOStream::read_some --- source/MaaUtils/IOStream/ChildPipeIOStream.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/MaaUtils/IOStream/ChildPipeIOStream.cpp b/source/MaaUtils/IOStream/ChildPipeIOStream.cpp index c49d2d18e..b7bcb1d18 100644 --- a/source/MaaUtils/IOStream/ChildPipeIOStream.cpp +++ b/source/MaaUtils/IOStream/ChildPipeIOStream.cpp @@ -40,7 +40,7 @@ std::string ChildPipeIOStream::read_some(size_t count, duration_t timeout) auto start_time = std::chrono::steady_clock::now(); std::string result; - while (child_.running() && result.size() < count && duration_since(start_time) < timeout) { + while (pin_.is_open() && result.size() < count && duration_since(start_time) < timeout) { auto read_size = std::min(kBufferSize, count - result.size()); auto read_num = pin_.readsome(buffer_.get(), read_size); result.append(buffer_.get(), read_num); From 4ec1cedbf783a39a3cf749f63199a63a358c08d4 Mon Sep 17 00:00:00 2001 From: MistEO Date: Wed, 6 Dec 2023 15:02:09 +0800 Subject: [PATCH 11/23] refactor: IOStream Base --- .../MaaUtils/IOStream/ChildPipeIOStream.cpp | 70 +++++++------------ source/MaaUtils/IOStream/IOStream.cpp | 44 ++++++++++++ source/MaaUtils/IOStream/SockIOStream.cpp | 55 +++++---------- source/include/LibraryHolder/LibraryHolder.h | 2 +- .../Utils/IOStream/ChildPipeIOStream.h | 19 ++--- source/include/Utils/IOStream/IOStream.h | 33 +++++++++ source/include/Utils/IOStream/SockIOStream.h | 19 +++-- 7 files changed, 135 insertions(+), 107 deletions(-) create mode 100644 source/MaaUtils/IOStream/IOStream.cpp create mode 100644 source/include/Utils/IOStream/IOStream.h diff --git a/source/MaaUtils/IOStream/ChildPipeIOStream.cpp b/source/MaaUtils/IOStream/ChildPipeIOStream.cpp index b7bcb1d18..76eb48a87 100644 --- a/source/MaaUtils/IOStream/ChildPipeIOStream.cpp +++ b/source/MaaUtils/IOStream/ChildPipeIOStream.cpp @@ -1,6 +1,6 @@ #include "Utils/IOStream/ChildPipeIOStream.h" -#include "Utils/Time.hpp" +#include "Utils/Logger.h" MAA_NS_BEGIN @@ -11,8 +11,7 @@ ChildPipeIOStream::ChildPipeIOStream(const std::filesystem::path& exec, const st , boost::process::windows::create_no_window #endif - ), - buffer_(std::make_unique(kBufferSize)) + ) {} ChildPipeIOStream::~ChildPipeIOStream() @@ -22,7 +21,8 @@ ChildPipeIOStream::~ChildPipeIOStream() bool ChildPipeIOStream::write(std::string_view data) { - if (!child_.running()) { + if (is_open()) { + LogError << "not opened"; return false; } @@ -30,45 +30,7 @@ bool ChildPipeIOStream::write(std::string_view data) return true; } -std::string ChildPipeIOStream::read(duration_t timeout) -{ - return read_some(std::numeric_limits::max(), timeout); -} - -std::string ChildPipeIOStream::read_some(size_t count, duration_t timeout) -{ - auto start_time = std::chrono::steady_clock::now(); - std::string result; - - while (pin_.is_open() && result.size() < count && duration_since(start_time) < timeout) { - auto read_size = std::min(kBufferSize, count - result.size()); - auto read_num = pin_.readsome(buffer_.get(), read_size); - result.append(buffer_.get(), read_num); - } - - return result; -} - -std::string ChildPipeIOStream::read_until(std::string_view delimiter, duration_t timeout) -{ - auto start_time = std::chrono::steady_clock::now(); - - std::string result; - - while (!result.ends_with(delimiter)) { - auto sub_timeout = timeout - duration_since(start_time); - if (sub_timeout < duration_t::zero()) { - break; - } - - auto sub_str = read_some(1, sub_timeout); - result.append(std::move(sub_str)); - } - - return result; -} - -int ChildPipeIOStream::release() +bool ChildPipeIOStream::release() { if (child_.running()) { child_.terminate(); @@ -77,7 +39,14 @@ int ChildPipeIOStream::release() child_.wait(); } - return child_.exit_code(); + int code = child_.exit_code(); + + if (code != 0) { + LogError << "child exit with" << code; + return false; + } + + return true; } bool ChildPipeIOStream::is_open() const @@ -85,4 +54,17 @@ bool ChildPipeIOStream::is_open() const return pin_.is_open(); } +std::string ChildPipeIOStream::read_once(size_t max_count) +{ + constexpr size_t kBufferSize = 128 * 1024; + + if (!buffer_) { + buffer_ = std::make_unique(kBufferSize); + } + + auto read_size = std::min(kBufferSize, max_count); + auto read_num = pin_.readsome(buffer_.get(), read_size); + return std::string(buffer_.get(), read_num); +} + MAA_NS_END diff --git a/source/MaaUtils/IOStream/IOStream.cpp b/source/MaaUtils/IOStream/IOStream.cpp new file mode 100644 index 000000000..ddb8143d1 --- /dev/null +++ b/source/MaaUtils/IOStream/IOStream.cpp @@ -0,0 +1,44 @@ +#include "Utils/IOStream/IOStream.h" + +#include "Utils/Time.hpp" + +MAA_NS_BEGIN + +std::string IOStream::read(duration_t timeout) +{ + return read_some(std::numeric_limits::max(), timeout); +} + +std::string IOStream::read_some(size_t count, duration_t timeout) +{ + auto start_time = std::chrono::steady_clock::now(); + std::string result; + + while (is_open() && result.size() < count && duration_since(start_time) < timeout) { + auto data = read_once(count - result.size()); + result.append(data); + } + + return result; +} + +std::string IOStream::read_until(std::string_view delimiter, duration_t timeout) +{ + auto start_time = std::chrono::steady_clock::now(); + + std::string result; + + while (!result.ends_with(delimiter)) { + auto sub_timeout = timeout - duration_since(start_time); + if (sub_timeout < duration_t::zero()) { + break; + } + + auto sub_str = read_some(1, sub_timeout); + result.append(std::move(sub_str)); + } + + return result; +} + +MAA_NS_END diff --git a/source/MaaUtils/IOStream/SockIOStream.cpp b/source/MaaUtils/IOStream/SockIOStream.cpp index bf217147a..85c536b95 100644 --- a/source/MaaUtils/IOStream/SockIOStream.cpp +++ b/source/MaaUtils/IOStream/SockIOStream.cpp @@ -64,18 +64,14 @@ std::shared_ptr ClientSockIOFactory::connect() return std::make_shared(std::move(sock)); } -SockIOStream::SockIOStream(boost::asio::ip::tcp::socket&& sock) - : sock_(std::move(sock)), buffer_(std::make_unique(kBufferSize)) -{} +SockIOStream::SockIOStream(boost::asio::ip::tcp::socket&& sock) : sock_(std::move(sock)) {} -SockIOStream::~SockIOStream() -{ - sock_.close(); -} +SockIOStream::~SockIOStream() {} bool SockIOStream::write(std::string_view data) { - if (!sock_.is_open()) { + if (!is_open()) { + LogError << "not opened"; return false; } @@ -83,47 +79,28 @@ bool SockIOStream::write(std::string_view data) return true; } -std::string SockIOStream::read(duration_t timeout) +bool SockIOStream::release() { - return read_some(std::numeric_limits::max(), timeout); + sock_.close(); + return true; } -std::string SockIOStream::read_some(size_t count, duration_t timeout) +bool SockIOStream::is_open() const { - auto start_time = std::chrono::steady_clock::now(); - std::string result; - - while (sock_.is_open() && result.size() < count && duration_since(start_time) < timeout) { - auto read_size = std::min(kBufferSize, count - result.size()); - auto read_num = sock_.read_some(boost::asio::mutable_buffer(buffer_.get(), read_size)); - result.append(buffer_.get(), read_num); - } - - return result; + return sock_.is_open(); } -std::string SockIOStream::read_until(std::string_view delimiter, duration_t timeout) +std::string SockIOStream::read_once(size_t max_count) { - auto start_time = std::chrono::steady_clock::now(); - - std::string result; + constexpr size_t kBufferSize = 128 * 1024; - while (!result.ends_with(delimiter)) { - auto sub_timeout = timeout - duration_since(start_time); - if (sub_timeout < duration_t::zero()) { - break; - } - - auto sub_str = read_some(1, sub_timeout); - result.append(std::move(sub_str)); + if (!buffer_) { + buffer_ = std::make_unique(kBufferSize); } - return result; -} - -bool SockIOStream::is_open() const -{ - return sock_.is_open(); + auto read_size = std::min(kBufferSize, max_count); + auto read_num = sock_.read_some(boost::asio::mutable_buffer(buffer_.get(), read_size)); + return std::string(buffer_.get(), read_num); } MAA_NS_END diff --git a/source/include/LibraryHolder/LibraryHolder.h b/source/include/LibraryHolder/LibraryHolder.h index 27ed70cd4..c2b0f7e9f 100644 --- a/source/include/LibraryHolder/LibraryHolder.h +++ b/source/include/LibraryHolder/LibraryHolder.h @@ -57,7 +57,7 @@ inline bool LibraryHolder::load_library(const std::filesystem::path& libname) boost::dll::fs::error_code ec; module_.load(libname, ec, boost::dll::load_mode::append_decorations | boost::dll::load_mode::search_system_folders); - if (ec.value() != boost::system::errc::success) { + if (ec) { auto message = ec.message(); LogError << "Failed to load library" << VAR(libname) << VAR(message); return false; diff --git a/source/include/Utils/IOStream/ChildPipeIOStream.h b/source/include/Utils/IOStream/ChildPipeIOStream.h index fb3a19aba..aec77965e 100644 --- a/source/include/Utils/IOStream/ChildPipeIOStream.h +++ b/source/include/Utils/IOStream/ChildPipeIOStream.h @@ -2,32 +2,27 @@ #include +#include "IOStream.h" #include "MaaFramework/MaaPort.h" #include "Utils/Boost.hpp" -#include "Utils/NonCopyable.hpp" MAA_NS_BEGIN -class MAA_UTILS_API ChildPipeIOStream : public NonCopyButMovable +class MAA_UTILS_API ChildPipeIOStream : public IOStream { - using duration_t = std::chrono::milliseconds; - - static constexpr size_t kBufferSize = 128 * 1024; - public: ChildPipeIOStream(const std::filesystem::path& exec, const std::vector& args); virtual ~ChildPipeIOStream(); public: - bool write(std::string_view data); + virtual bool write(std::string_view data) override; - std::string read(duration_t timeout = duration_t::max()); - std::string read_some(size_t count, duration_t timeout = duration_t::max()); - std::string read_until(std::string_view delimiter, duration_t timeout = duration_t::max()); + virtual bool release() override; + virtual bool is_open() const override; - int release(); - bool is_open() const; +protected: + virtual std::string read_once(size_t max_count) override; private: boost::process::ipstream pin_; diff --git a/source/include/Utils/IOStream/IOStream.h b/source/include/Utils/IOStream/IOStream.h new file mode 100644 index 000000000..8a9ff5e86 --- /dev/null +++ b/source/include/Utils/IOStream/IOStream.h @@ -0,0 +1,33 @@ +#pragma once + +#include +#include +#include + +#include "MaaFramework/MaaPort.h" +#include "Utils/NonCopyable.hpp" + +MAA_NS_BEGIN + +class MAA_UTILS_API IOStream : public NonCopyButMovable +{ + using duration_t = std::chrono::milliseconds; + +public: + virtual ~IOStream() = default; + +public: + virtual bool write(std::string_view data) = 0; + + virtual std::string read(duration_t timeout = duration_t::max()); + virtual std::string read_some(size_t count, duration_t timeout = duration_t::max()); + virtual std::string read_until(std::string_view delimiter, duration_t timeout = duration_t::max()); + + virtual bool release() = 0; + virtual bool is_open() const = 0; + +protected: + virtual std::string read_once(size_t max_count) = 0; +}; + +MAA_NS_END diff --git a/source/include/Utils/IOStream/SockIOStream.h b/source/include/Utils/IOStream/SockIOStream.h index a0e52aae5..7afdf3b9f 100644 --- a/source/include/Utils/IOStream/SockIOStream.h +++ b/source/include/Utils/IOStream/SockIOStream.h @@ -2,6 +2,7 @@ #include +#include "IOStream.h" #include "MaaFramework/MaaPort.h" #include "Utils/Boost.hpp" #include "Utils/NonCopyable.hpp" @@ -40,24 +41,20 @@ class MAA_UTILS_API ClientSockIOFactory : public NonCopyButMovable boost::asio::ip::tcp::endpoint endpoint_; }; -class MAA_UTILS_API SockIOStream : public NonCopyButMovable +class MAA_UTILS_API SockIOStream : public IOStream { - using duration_t = std::chrono::milliseconds; - - static constexpr size_t kBufferSize = 128 * 1024; - public: SockIOStream(boost::asio::ip::tcp::socket&& sock); - ~SockIOStream(); + virtual ~SockIOStream() override; public: - bool write(std::string_view data); + virtual bool write(std::string_view data) override; - std::string read(duration_t timeout = duration_t::max()); - std::string read_some(size_t count, duration_t timeout = duration_t::max()); - std::string read_until(std::string_view delimiter, duration_t timeout = duration_t::max()); + virtual bool release() override; + virtual bool is_open() const override; - bool is_open() const; +protected: + virtual std::string read_once(size_t max_count) override; private: boost::asio::ip::tcp::socket sock_; From d2d79f2c2265203eefe257ea06ffa5cddc1d0cc0 Mon Sep 17 00:00:00 2001 From: MistEO Date: Wed, 6 Dec 2023 15:17:54 +0800 Subject: [PATCH 12/23] =?UTF-8?q?refactor:=20=E9=87=8D=E6=96=B0=E6=95=B4?= =?UTF-8?q?=E7=90=86ExecAgent=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MaaToolKit/ExecAgent/ActionExecAgent.cpp | 2 +- source/MaaToolKit/ExecAgent/ExecAgentBase.cpp | 39 ++++++++++--------- source/MaaToolKit/ExecAgent/ExecAgentBase.h | 11 ++++-- .../MaaToolKit/ExecAgent/ExecArgConverter.cpp | 2 +- .../MaaToolKit/ExecAgent/ExecArgConverter.h | 2 +- .../ExecAgent/RecognizerExecAgent.cpp | 4 +- 6 files changed, 33 insertions(+), 27 deletions(-) diff --git a/source/MaaToolKit/ExecAgent/ActionExecAgent.cpp b/source/MaaToolKit/ExecAgent/ActionExecAgent.cpp index 95ddf3f30..7e4a2369e 100644 --- a/source/MaaToolKit/ExecAgent/ActionExecAgent.cpp +++ b/source/MaaToolKit/ExecAgent/ActionExecAgent.cpp @@ -44,7 +44,7 @@ bool ActionExecAgent::run(MaaSyncContextHandle sync_context, std::string_view ta std::vector args = exec.exec_args; args.insert(args.end(), std::make_move_iterator(extra_args.begin()), std::make_move_iterator(extra_args.end())); - auto output_opt = run_executor(exec.text_mode, exec.exec_path, args); + auto output_opt = run_executor(exec.exec_path, args, exec.text_mode, exec.image_mode); if (!output_opt) { LogError << "run_executor failed" << VAR(exec.exec_path) << VAR(exec.exec_args); return false; diff --git a/source/MaaToolKit/ExecAgent/ExecAgentBase.cpp b/source/MaaToolKit/ExecAgent/ExecAgentBase.cpp index 3b32d4193..3319a96d8 100644 --- a/source/MaaToolKit/ExecAgent/ExecAgentBase.cpp +++ b/source/MaaToolKit/ExecAgent/ExecAgentBase.cpp @@ -43,35 +43,40 @@ bool ExecAgentBase::unregister_executor(MaaInstanceHandle handle, std::string_vi std::string name_str(name); bool ret = unregister_for_maa_inst(handle, name); - ret = executors_.erase(name_str) > 0 && ret; + ret &= executors_.erase(name_str) > 0; return ret; } -std::optional ExecAgentBase::run_executor(TextTransferMode mode, const std::filesystem::path& exec_path, - const std::vector& exec_args) +std::optional ExecAgentBase::run_executor(const std::filesystem::path& exec_path, + const std::vector& exec_args, + TextTransferMode text_mode, ImageTransferMode image_mode) { - switch (mode) { - case TextTransferMode::StdIO: { - return run_executor_with_stdio(exec_path, exec_args); + auto searched_path = boost::process::search_path(exec_path); + if (!std::filesystem::exists(searched_path)) { + LogError << "path not exists" << VAR(searched_path); + return std::nullopt; } + + ChildPipeIOStream child(searched_path, exec_args); + + switch (text_mode) { + case TextTransferMode::StdIO: + return handle_ipc(child, image_mode); + case TextTransferMode::FileIO: + LogError << "not implemented"; + return std::nullopt; + default: LogError << "not implemented"; return std::nullopt; } } -std::optional ExecAgentBase::run_executor_with_stdio(const std::filesystem::path& exec_path, - const std::vector& exec_args) +std::optional ExecAgentBase::handle_ipc(IOStream& ios, ImageTransferMode image_mode) { - auto searched_path = boost::process::search_path(exec_path); - if (!std::filesystem::exists(searched_path)) { - LogError << "path not exists" << VAR(searched_path); - return std::nullopt; - } - - ChildPipeIOStream ios(searched_path, exec_args); + std::ignore = image_mode; while (ios.is_open()) { std::string line = ios.read_until("\n"); @@ -80,9 +85,7 @@ std::optional ExecAgentBase::run_executor_with_stdio(const std::fil // TODO } - int exit_code = ios.release(); - if (exit_code != 0) { - LogError << "process exit with code:" << exit_code; + if (!ios.release()) { return std::nullopt; } diff --git a/source/MaaToolKit/ExecAgent/ExecAgentBase.h b/source/MaaToolKit/ExecAgent/ExecAgentBase.h index c1c535c81..b2bc2d688 100644 --- a/source/MaaToolKit/ExecAgent/ExecAgentBase.h +++ b/source/MaaToolKit/ExecAgent/ExecAgentBase.h @@ -8,6 +8,7 @@ #include "ExecAgent/ExecArgConverter.h" #include "ExecAgentType.h" #include "MaaFramework/MaaDef.h" +#include "Utils/IOStream/IOStream.h" MAA_TOOLKIT_NS_BEGIN @@ -25,15 +26,17 @@ class ExecAgentBase virtual bool register_for_maa_inst(MaaInstanceHandle handle, std::string_view name) = 0; virtual bool unregister_for_maa_inst(MaaInstanceHandle handle, std::string_view name) = 0; - std::optional run_executor(TextTransferMode mode, const std::filesystem::path& exec_path, - const std::vector& exec_args); - std::optional run_executor_with_stdio(const std::filesystem::path& exec_path, - const std::vector& exec_args); + std::optional run_executor(const std::filesystem::path& exec_path, + const std::vector& exec_args, TextTransferMode text_mode, + ImageTransferMode image_mode); protected: std::unordered_map executors_; ExecArgConverter arg_cvt_; + +private: + std::optional handle_ipc(IOStream& ios, ImageTransferMode image_mode); }; MAA_TOOLKIT_NS_END diff --git a/source/MaaToolKit/ExecAgent/ExecArgConverter.cpp b/source/MaaToolKit/ExecAgent/ExecArgConverter.cpp index 474f8ad9a..09cc9d869 100644 --- a/source/MaaToolKit/ExecAgent/ExecArgConverter.cpp +++ b/source/MaaToolKit/ExecAgent/ExecArgConverter.cpp @@ -21,7 +21,7 @@ std::string ExecArgConverter::sync_context_to_arg(MaaSyncContextHandle sync_cont return uuid; } -std::string ExecArgConverter::image_to_arg(ImageTransferMode mode, const cv::Mat& image) +std::string ExecArgConverter::image_to_arg(const cv::Mat& image, ImageTransferMode mode) { switch (mode) { case ImageTransferMode::FileIO: { diff --git a/source/MaaToolKit/ExecAgent/ExecArgConverter.h b/source/MaaToolKit/ExecAgent/ExecArgConverter.h index 30fcb6df2..f5a2a51fc 100644 --- a/source/MaaToolKit/ExecAgent/ExecArgConverter.h +++ b/source/MaaToolKit/ExecAgent/ExecArgConverter.h @@ -18,7 +18,7 @@ class ExecArgConverter public: std::string sync_context_to_arg(MaaSyncContextHandle sync_context); - std::string image_to_arg(ImageTransferMode mode, const cv::Mat& image); + std::string image_to_arg(const cv::Mat& image, ImageTransferMode mode); MaaSyncContextHandle arg_to_sync_context(const std::string& arg) const; diff --git a/source/MaaToolKit/ExecAgent/RecognizerExecAgent.cpp b/source/MaaToolKit/ExecAgent/RecognizerExecAgent.cpp index 26b5b2a34..0d79fb21e 100644 --- a/source/MaaToolKit/ExecAgent/RecognizerExecAgent.cpp +++ b/source/MaaToolKit/ExecAgent/RecognizerExecAgent.cpp @@ -38,14 +38,14 @@ std::optional RecognizerExecAgent::analyze( auto& exec = exec_it->second; std::string handle_arg = arg_cvt_.sync_context_to_arg(sync_context); - std::string image_arg = arg_cvt_.image_to_arg(exec.image_mode, image); + std::string image_arg = arg_cvt_.image_to_arg(image, exec.image_mode); std::vector extra_args = { handle_arg, image_arg, std::string(task_name), std::string(custom_recognition_param) }; std::vector args = exec.exec_args; args.insert(args.end(), std::make_move_iterator(extra_args.begin()), std::make_move_iterator(extra_args.end())); - auto output_opt = run_executor(exec.text_mode, exec.exec_path, args); + auto output_opt = run_executor(exec.exec_path, args, exec.text_mode, exec.image_mode); if (!output_opt) { LogError << "run_executor failed" << VAR(exec.exec_path) << VAR(exec.exec_args); return std::nullopt; From 34bff523f7b0355c94b97b17a1ae63e8a0d22cda Mon Sep 17 00:00:00 2001 From: MistEO Date: Wed, 6 Dec 2023 15:19:19 +0800 Subject: [PATCH 13/23] =?UTF-8?q?perf:=20=E5=87=8F=E5=B0=91=E4=B8=80?= =?UTF-8?q?=E5=A4=84=E6=8B=B7=E8=B4=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/MaaUtils/IOStream/IOStream.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/MaaUtils/IOStream/IOStream.cpp b/source/MaaUtils/IOStream/IOStream.cpp index ddb8143d1..4ff283388 100644 --- a/source/MaaUtils/IOStream/IOStream.cpp +++ b/source/MaaUtils/IOStream/IOStream.cpp @@ -16,7 +16,7 @@ std::string IOStream::read_some(size_t count, duration_t timeout) while (is_open() && result.size() < count && duration_since(start_time) < timeout) { auto data = read_once(count - result.size()); - result.append(data); + result.append(std::move(data)); } return result; From e62640c6cc6c687289bdacd8e4b8100fd08eee26 Mon Sep 17 00:00:00 2001 From: MistEO Date: Wed, 6 Dec 2023 15:23:13 +0800 Subject: [PATCH 14/23] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96iostream?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/MaaUtils/IOStream/IOStream.cpp | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/source/MaaUtils/IOStream/IOStream.cpp b/source/MaaUtils/IOStream/IOStream.cpp index 4ff283388..f0211716a 100644 --- a/source/MaaUtils/IOStream/IOStream.cpp +++ b/source/MaaUtils/IOStream/IOStream.cpp @@ -25,17 +25,11 @@ std::string IOStream::read_some(size_t count, duration_t timeout) std::string IOStream::read_until(std::string_view delimiter, duration_t timeout) { auto start_time = std::chrono::steady_clock::now(); - std::string result; - while (!result.ends_with(delimiter)) { - auto sub_timeout = timeout - duration_since(start_time); - if (sub_timeout < duration_t::zero()) { - break; - } - - auto sub_str = read_some(1, sub_timeout); - result.append(std::move(sub_str)); + while (is_open() && !result.ends_with(delimiter) && duration_since(start_time) < timeout) { + auto data = read_once(1); + result.append(std::move(data)); } return result; From 6231c8b964572b2e04943eeb8e7dc96e8a04c9dc Mon Sep 17 00:00:00 2001 From: MistEO Date: Wed, 6 Dec 2023 16:08:45 +0800 Subject: [PATCH 15/23] fix(exec_agent): transfermode enum value error --- source/MaaToolKit/API/MaaToolKitExecAgent.cpp | 2 +- source/MaaToolKit/ExecAgent/ExecAgentType.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/source/MaaToolKit/API/MaaToolKitExecAgent.cpp b/source/MaaToolKit/API/MaaToolKitExecAgent.cpp index 5193920bb..e2ff5d765 100644 --- a/source/MaaToolKit/API/MaaToolKitExecAgent.cpp +++ b/source/MaaToolKit/API/MaaToolKitExecAgent.cpp @@ -58,7 +58,7 @@ MaaBool RegisterExecutor(ExecutorType type, MaaInstanceHandle handle, MaaStringV TextTransferMode text_mode = static_cast(MaaToolKitExecAgentArgvTransferMode_Text_Mask & argv_mode); ImageTransferMode image_mode = - static_cast(MaaToolKitExecAgentArgvTransferMode_Image_Mask & argv_mode); + static_cast((MaaToolKitExecAgentArgvTransferMode_Image_Mask & argv_mode) >> 8); switch (type) { case ExecutorType::Recognizer: diff --git a/source/MaaToolKit/ExecAgent/ExecAgentType.h b/source/MaaToolKit/ExecAgent/ExecAgentType.h index 0da17ba21..5e2a11346 100644 --- a/source/MaaToolKit/ExecAgent/ExecAgentType.h +++ b/source/MaaToolKit/ExecAgent/ExecAgentType.h @@ -11,7 +11,7 @@ MAA_TOOLKIT_NS_BEGIN enum class TextTransferMode { - StdIO, + StdIO = 1, FileIO, }; inline std::ostream& operator<<(std::ostream& os, TextTransferMode mode) @@ -29,7 +29,7 @@ inline std::ostream& operator<<(std::ostream& os, TextTransferMode mode) enum class ImageTransferMode { - FileIO, + FileIO = 1, }; inline std::ostream& operator<<(std::ostream& os, ImageTransferMode mode) { From 28c4cf04e11cb014b6d80c38ad1bd3f0692b40c0 Mon Sep 17 00:00:00 2001 From: MistEO Date: Wed, 6 Dec 2023 16:57:20 +0800 Subject: [PATCH 16/23] =?UTF-8?q?refactor:=20=E9=87=8D=E6=9E=84=20ExecAgen?= =?UTF-8?q?t=20=E5=AF=B9=E8=B1=A1=E6=A8=A1=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MaaToolKit/ExecAgent/ActionExecAgent.cpp | 44 ++++++++----------- source/MaaToolKit/ExecAgent/ActionExecAgent.h | 8 ++-- source/MaaToolKit/ExecAgent/ExecAgentBase.cpp | 33 +++++++------- source/MaaToolKit/ExecAgent/ExecAgentBase.h | 7 +-- source/MaaToolKit/ExecAgent/ExecAgentType.h | 2 +- .../ExecAgent/RecognizerExecAgent.cpp | 32 ++++++-------- .../ExecAgent/RecognizerExecAgent.h | 4 +- 7 files changed, 58 insertions(+), 72 deletions(-) diff --git a/source/MaaToolKit/ExecAgent/ActionExecAgent.cpp b/source/MaaToolKit/ExecAgent/ActionExecAgent.cpp index 7e4a2369e..9bddbd908 100644 --- a/source/MaaToolKit/ExecAgent/ActionExecAgent.cpp +++ b/source/MaaToolKit/ExecAgent/ActionExecAgent.cpp @@ -13,9 +13,9 @@ ActionExecAgent::ActionExecAgent() custom_action_.stop = &ActionExecAgent::maa_api_stop; } -bool ActionExecAgent::register_for_maa_inst(MaaInstanceHandle handle, std::string_view name) +bool ActionExecAgent::register_for_maa_inst(MaaInstanceHandle handle, std::string_view name, ExecData& executor) { - return MaaRegisterCustomAction(handle, name.data(), &custom_action_, this); + return MaaRegisterCustomAction(handle, name.data(), &custom_action_, reinterpret_cast(&executor)); } bool ActionExecAgent::unregister_for_maa_inst(MaaInstanceHandle handle, std::string_view name) @@ -23,39 +23,32 @@ bool ActionExecAgent::unregister_for_maa_inst(MaaInstanceHandle handle, std::str return MaaUnregisterCustomAction(handle, name.data()); } -bool ActionExecAgent::run(MaaSyncContextHandle sync_context, std::string_view task_name, +bool ActionExecAgent::run(ExecData& data, MaaSyncContextHandle sync_context, std::string_view task_name, std::string_view custom_action_param, MaaRectHandle cur_box, std::string_view cur_rec_detail) { - LogFunc << VAR_VOIDP(sync_context) << VAR(task_name) << VAR(custom_action_param) << VAR_VOIDP(cur_box) - << VAR(cur_rec_detail); - - auto exec_it = executors_.find(std::string(task_name)); - if (exec_it == executors_.end()) { - LogError << "executor not found" << VAR(task_name); - return false; - } - auto& exec = exec_it->second; + LogFunc << VAR(data.name) << VAR_VOIDP(sync_context) << VAR(task_name) << VAR(custom_action_param) + << VAR_VOIDP(cur_box) << VAR(cur_rec_detail); std::string handle_arg = arg_cvt_.sync_context_to_arg(sync_context); std::string box_arg = json::array({ cur_box->x, cur_box->y, cur_box->width, cur_box->height }).to_string(); std::vector extra_args = { handle_arg, std::string(task_name), std::string(custom_action_param), box_arg, std::string(cur_rec_detail) }; - std::vector args = exec.exec_args; + std::vector args = data.exec_args; args.insert(args.end(), std::make_move_iterator(extra_args.begin()), std::make_move_iterator(extra_args.end())); - auto output_opt = run_executor(exec.exec_path, args, exec.text_mode, exec.image_mode); + auto output_opt = run_executor(data.exec_path, args, data.text_mode, data.image_mode); if (!output_opt) { - LogError << "run_executor failed" << VAR(exec.exec_path) << VAR(exec.exec_args); + LogError << "run_executor failed" << VAR(data.exec_path) << VAR(data.exec_args); return false; } return true; } -void ActionExecAgent::stop() +void ActionExecAgent::stop(ExecData& data) { - LogFunc; + LogFunc << VAR(data.name); // TODO } @@ -64,24 +57,25 @@ MaaBool ActionExecAgent::maa_api_run(MaaSyncContextHandle sync_context, MaaStrin MaaStringView custom_action_param, MaaRectHandle cur_box, MaaStringView cur_rec_detail, MaaTransparentArg action_arg) { - auto* self = static_cast(action_arg); - if (!self) { - LogError << "action_arg is nullptr"; + auto* data = static_cast(action_arg); + if (!data) { + LogError << "data is nullptr" << VAR(action_arg); return false; } - return self->run(sync_context, task_name, custom_action_param, cur_box, cur_rec_detail); + return get_instance().run( // + *data, sync_context, task_name, custom_action_param, cur_box, cur_rec_detail); } void ActionExecAgent::maa_api_stop(MaaTransparentArg action_arg) { - auto* self = static_cast(action_arg); - if (!self) { - LogError << "action_arg is nullptr"; + auto* data = static_cast(action_arg); + if (!data) { + LogError << "data is nullptr" << VAR(action_arg); return; } - self->stop(); + get_instance().stop(*data); } MAA_TOOLKIT_NS_END diff --git a/source/MaaToolKit/ExecAgent/ActionExecAgent.h b/source/MaaToolKit/ExecAgent/ActionExecAgent.h index ead360fc5..fda3b65cb 100644 --- a/source/MaaToolKit/ExecAgent/ActionExecAgent.h +++ b/source/MaaToolKit/ExecAgent/ActionExecAgent.h @@ -15,13 +15,13 @@ class ActionExecAgent final : public ExecAgentBase, public SingletonHoldersecond); + if (!registered) { + LogError << "register failed" << VAR(name); + exec_data_.erase(iter); return false; } @@ -40,10 +39,8 @@ bool ExecAgentBase::unregister_executor(MaaInstanceHandle handle, std::string_vi { LogFunc << VAR_VOIDP(handle) << VAR(name); - std::string name_str(name); - bool ret = unregister_for_maa_inst(handle, name); - ret &= executors_.erase(name_str) > 0; + ret &= exec_data_.erase(std::string(name)) > 0; return ret; } diff --git a/source/MaaToolKit/ExecAgent/ExecAgentBase.h b/source/MaaToolKit/ExecAgent/ExecAgentBase.h index b2bc2d688..2856b1d6b 100644 --- a/source/MaaToolKit/ExecAgent/ExecAgentBase.h +++ b/source/MaaToolKit/ExecAgent/ExecAgentBase.h @@ -2,8 +2,9 @@ #include "Conf/Conf.h" +#include +#include #include -#include #include "ExecAgent/ExecArgConverter.h" #include "ExecAgentType.h" @@ -23,7 +24,7 @@ class ExecAgentBase bool unregister_executor(MaaInstanceHandle handle, std::string_view name); protected: - virtual bool register_for_maa_inst(MaaInstanceHandle handle, std::string_view name) = 0; + virtual bool register_for_maa_inst(MaaInstanceHandle handle, std::string_view name, ExecData& executor) = 0; virtual bool unregister_for_maa_inst(MaaInstanceHandle handle, std::string_view name) = 0; std::optional run_executor(const std::filesystem::path& exec_path, @@ -31,7 +32,7 @@ class ExecAgentBase ImageTransferMode image_mode); protected: - std::unordered_map executors_; + std::map exec_data_; ExecArgConverter arg_cvt_; diff --git a/source/MaaToolKit/ExecAgent/ExecAgentType.h b/source/MaaToolKit/ExecAgent/ExecAgentType.h index 5e2a11346..f9ff2904e 100644 --- a/source/MaaToolKit/ExecAgent/ExecAgentType.h +++ b/source/MaaToolKit/ExecAgent/ExecAgentType.h @@ -41,7 +41,7 @@ inline std::ostream& operator<<(std::ostream& os, ImageTransferMode mode) return os; } -struct Executor +struct ExecData { std::string name; std::filesystem::path exec_path; diff --git a/source/MaaToolKit/ExecAgent/RecognizerExecAgent.cpp b/source/MaaToolKit/ExecAgent/RecognizerExecAgent.cpp index 0d79fb21e..3c3fad1de 100644 --- a/source/MaaToolKit/ExecAgent/RecognizerExecAgent.cpp +++ b/source/MaaToolKit/ExecAgent/RecognizerExecAgent.cpp @@ -14,9 +14,9 @@ RecognizerExecAgent::RecognizerExecAgent() custom_recognizer_.analyze = &RecognizerExecAgent::maa_api_analyze; } -bool RecognizerExecAgent::register_for_maa_inst(MaaInstanceHandle handle, std::string_view name) +bool RecognizerExecAgent::register_for_maa_inst(MaaInstanceHandle handle, std::string_view name, ExecData& executor) { - return MaaRegisterCustomRecognizer(handle, name.data(), &custom_recognizer_, this); + return MaaRegisterCustomRecognizer(handle, name.data(), &custom_recognizer_, reinterpret_cast(&executor)); } bool RecognizerExecAgent::unregister_for_maa_inst(MaaInstanceHandle handle, std::string_view name) @@ -25,29 +25,23 @@ bool RecognizerExecAgent::unregister_for_maa_inst(MaaInstanceHandle handle, std: } std::optional RecognizerExecAgent::analyze( - MaaSyncContextHandle sync_context, const cv::Mat& image, std::string_view task_name, + ExecData& data, MaaSyncContextHandle sync_context, const cv::Mat& image, std::string_view task_name, std::string_view custom_recognition_param) { - LogFunc << VAR_VOIDP(sync_context) << VAR(image.size()) << VAR(task_name) << VAR(custom_recognition_param); - - auto exec_it = executors_.find(std::string(task_name)); - if (exec_it == executors_.end()) { - LogError << "executor not found" << VAR(task_name); - return std::nullopt; - } - auto& exec = exec_it->second; + LogFunc << VAR(data.name) << VAR_VOIDP(sync_context) << VAR(image.size()) << VAR(task_name) + << VAR(custom_recognition_param); std::string handle_arg = arg_cvt_.sync_context_to_arg(sync_context); - std::string image_arg = arg_cvt_.image_to_arg(image, exec.image_mode); + std::string image_arg = arg_cvt_.image_to_arg(image, data.image_mode); std::vector extra_args = { handle_arg, image_arg, std::string(task_name), std::string(custom_recognition_param) }; - std::vector args = exec.exec_args; + std::vector args = data.exec_args; args.insert(args.end(), std::make_move_iterator(extra_args.begin()), std::make_move_iterator(extra_args.end())); - auto output_opt = run_executor(exec.exec_path, args, exec.text_mode, exec.image_mode); + auto output_opt = run_executor(data.exec_path, args, data.text_mode, data.image_mode); if (!output_opt) { - LogError << "run_executor failed" << VAR(exec.exec_path) << VAR(exec.exec_args); + LogError << "run_executor failed" << VAR(data.exec_path) << VAR(data.exec_args); return std::nullopt; } @@ -60,9 +54,9 @@ MaaBool RecognizerExecAgent::maa_api_analyze( // MaaStringView custom_recognition_param, MaaTransparentArg recognizer_arg, MaaRectHandle out_box, MaaStringBufferHandle out_detail) { - auto* self = static_cast(recognizer_arg); - if (!self) { - LogError << "recognizer_arg is nullptr"; + auto* data = static_cast(recognizer_arg); + if (!data) { + LogError << "data is nullptr" << VAR(recognizer_arg); return false; } @@ -72,7 +66,7 @@ MaaBool RecognizerExecAgent::maa_api_analyze( // int32_t type = MaaGetImageType(image); cv::Mat image_mat(height, width, type, raw_data); - auto result_opt = self->analyze(sync_context, image_mat, task_name, custom_recognition_param); + auto result_opt = get_instance().analyze(*data, sync_context, image_mat, task_name, custom_recognition_param); if (!result_opt) { MaaSetRect(out_box, 0, 0, 0, 0); diff --git a/source/MaaToolKit/ExecAgent/RecognizerExecAgent.h b/source/MaaToolKit/ExecAgent/RecognizerExecAgent.h index 7efc1dd18..4d6ae5aaf 100644 --- a/source/MaaToolKit/ExecAgent/RecognizerExecAgent.h +++ b/source/MaaToolKit/ExecAgent/RecognizerExecAgent.h @@ -19,7 +19,7 @@ class RecognizerExecAgent final : public ExecAgentBase, public SingletonHolder analyze( // - MaaSyncContextHandle sync_context, const cv::Mat& image, std::string_view task_name, + ExecData& data, MaaSyncContextHandle sync_context, const cv::Mat& image, std::string_view task_name, std::string_view custom_recognition_param); private: From 7e18d838b37e509816158145f2e1d2e5ef14d7c2 Mon Sep 17 00:00:00 2001 From: MistEO Date: Wed, 6 Dec 2023 17:59:06 +0800 Subject: [PATCH 17/23] fix: iostream read --- .../MaaUtils/IOStream/ChildPipeIOStream.cpp | 11 +++---- source/MaaUtils/IOStream/SockIOStream.cpp | 29 +++++++++---------- source/include/Utils/IOStream/SockIOStream.h | 4 +-- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/source/MaaUtils/IOStream/ChildPipeIOStream.cpp b/source/MaaUtils/IOStream/ChildPipeIOStream.cpp index 76eb48a87..fb04e018c 100644 --- a/source/MaaUtils/IOStream/ChildPipeIOStream.cpp +++ b/source/MaaUtils/IOStream/ChildPipeIOStream.cpp @@ -6,7 +6,8 @@ MAA_NS_BEGIN ChildPipeIOStream::ChildPipeIOStream(const std::filesystem::path& exec, const std::vector& args) : child_( // - exec, args, boost::process::std_out > pin_, boost::process::std_err > pin_, boost::process::std_in < pout_ + exec, args, boost::process::std_out > pin_, boost::process::std_err > boost::process::null, + boost::process::std_in < pout_ #ifdef _WIN32 , boost::process::windows::create_no_window @@ -51,7 +52,7 @@ bool ChildPipeIOStream::release() bool ChildPipeIOStream::is_open() const { - return pin_.is_open(); + return !pin_.eof(); } std::string ChildPipeIOStream::read_once(size_t max_count) @@ -62,9 +63,9 @@ std::string ChildPipeIOStream::read_once(size_t max_count) buffer_ = std::make_unique(kBufferSize); } - auto read_size = std::min(kBufferSize, max_count); - auto read_num = pin_.readsome(buffer_.get(), read_size); - return std::string(buffer_.get(), read_num); + size_t count = std::min(kBufferSize, max_count); + auto read = pin_.read(buffer_.get(), count).gcount(); + return std::string(buffer_.get(), read); } MAA_NS_END diff --git a/source/MaaUtils/IOStream/SockIOStream.cpp b/source/MaaUtils/IOStream/SockIOStream.cpp index 85c536b95..d54a4c405 100644 --- a/source/MaaUtils/IOStream/SockIOStream.cpp +++ b/source/MaaUtils/IOStream/SockIOStream.cpp @@ -35,13 +35,14 @@ std::shared_ptr ServerSockIOFactory::accept() { LogFunc; - auto sock = server_acceptor_.accept(); - if (!sock.is_open()) { + boost::asio::ip::tcp::iostream ios; + server_acceptor_.accept(*ios.rdbuf()); + if (ios.eof()) { LogError << "socket is not opened"; return nullptr; } - return std::make_shared(std::move(sock)); + return std::make_shared(std::move(ios)); } ClientSockIOFactory::ClientSockIOFactory(const std::string& address, unsigned short port) @@ -54,17 +55,15 @@ std::shared_ptr ClientSockIOFactory::connect() { LogFunc; - boost::asio::ip::tcp::socket sock(io_ctx_); - sock.connect(endpoint_); - if (!sock.is_open()) { + boost::asio::ip::tcp::iostream ios(endpoint_); + if (ios.eof()) { LogError << "socket is not opened"; return nullptr; } - - return std::make_shared(std::move(sock)); + return std::make_shared(std::move(ios)); } -SockIOStream::SockIOStream(boost::asio::ip::tcp::socket&& sock) : sock_(std::move(sock)) {} +SockIOStream::SockIOStream(boost::asio::ip::tcp::iostream&& ios) : ios_(std::move(ios)) {} SockIOStream::~SockIOStream() {} @@ -75,19 +74,19 @@ bool SockIOStream::write(std::string_view data) return false; } - sock_.write_some(boost::asio::buffer(data)); + ios_ << data << std::endl; return true; } bool SockIOStream::release() { - sock_.close(); + ios_.close(); return true; } bool SockIOStream::is_open() const { - return sock_.is_open(); + return !ios_.eof(); } std::string SockIOStream::read_once(size_t max_count) @@ -98,9 +97,9 @@ std::string SockIOStream::read_once(size_t max_count) buffer_ = std::make_unique(kBufferSize); } - auto read_size = std::min(kBufferSize, max_count); - auto read_num = sock_.read_some(boost::asio::mutable_buffer(buffer_.get(), read_size)); - return std::string(buffer_.get(), read_num); + size_t count = std::min(kBufferSize, max_count); + auto read = ios_.read(buffer_.get(), count).gcount(); + return std::string(buffer_.get(), read); } MAA_NS_END diff --git a/source/include/Utils/IOStream/SockIOStream.h b/source/include/Utils/IOStream/SockIOStream.h index 7afdf3b9f..f406fb153 100644 --- a/source/include/Utils/IOStream/SockIOStream.h +++ b/source/include/Utils/IOStream/SockIOStream.h @@ -44,7 +44,7 @@ class MAA_UTILS_API ClientSockIOFactory : public NonCopyButMovable class MAA_UTILS_API SockIOStream : public IOStream { public: - SockIOStream(boost::asio::ip::tcp::socket&& sock); + SockIOStream(boost::asio::ip::tcp::iostream&& ios); virtual ~SockIOStream() override; public: @@ -57,7 +57,7 @@ class MAA_UTILS_API SockIOStream : public IOStream virtual std::string read_once(size_t max_count) override; private: - boost::asio::ip::tcp::socket sock_; + boost::asio::ip::tcp::iostream ios_; std::unique_ptr buffer_ = nullptr; }; From 211fde97c788454e44880936ef090121a58338bc Mon Sep 17 00:00:00 2001 From: MistEO Date: Wed, 6 Dec 2023 18:41:41 +0800 Subject: [PATCH 18/23] fix: resturecture boost and fix build error --- .../Base/ProcessArgvGenerator.cpp | 2 +- source/MaaRpc/implement/Utility.cpp | 2 +- source/MaaRpc/implement/Utility.h | 2 +- source/MaaToolKit/ExecAgent/ExecAgentBase.cpp | 1 - source/MaaUtils/Uuid/Uuid.cpp | 16 ++++++++++++++++ source/include/LibraryHolder/LibraryHolder.h | 5 ++++- .../Utils/{Boost.hpp => IOStream/BoostIO.hpp} | 8 +------- .../include/Utils/IOStream/ChildPipeIOStream.h | 1 - source/include/Utils/IOStream/IOStream.h | 1 + source/include/Utils/IOStream/SockIOStream.h | 1 - source/include/Utils/Uuid.h | 12 ++++++++++++ 11 files changed, 37 insertions(+), 14 deletions(-) create mode 100644 source/MaaUtils/Uuid/Uuid.cpp rename source/include/Utils/{Boost.hpp => IOStream/BoostIO.hpp} (53%) create mode 100644 source/include/Utils/Uuid.h diff --git a/source/MaaAdbControlUnit/Base/ProcessArgvGenerator.cpp b/source/MaaAdbControlUnit/Base/ProcessArgvGenerator.cpp index 2c6873cae..a0850e095 100644 --- a/source/MaaAdbControlUnit/Base/ProcessArgvGenerator.cpp +++ b/source/MaaAdbControlUnit/Base/ProcessArgvGenerator.cpp @@ -1,6 +1,6 @@ #include "ProcessArgvGenerator.h" -#include "Utils/Boost.hpp" +#include "Utils/IOStream/BoostIO.hpp" #include "Utils/Logger.h" #include "Utils/Platform.h" diff --git a/source/MaaRpc/implement/Utility.cpp b/source/MaaRpc/implement/Utility.cpp index 7396c50fe..9301ba47b 100644 --- a/source/MaaRpc/implement/Utility.cpp +++ b/source/MaaRpc/implement/Utility.cpp @@ -113,7 +113,7 @@ Status UtilityImpl::acquire_id(ServerContext* context, const ::maarpc::EmptyRequ std::ignore = context; std::ignore = request; - response->set_id(format_now()); + response->set_id(make_uuid()); return Status::OK; } diff --git a/source/MaaRpc/implement/Utility.h b/source/MaaRpc/implement/Utility.h index 6f1f5f2c8..42c239e63 100644 --- a/source/MaaRpc/implement/Utility.h +++ b/source/MaaRpc/implement/Utility.h @@ -2,6 +2,7 @@ #include "AtomicMap.h" #include "MaaFramework/MaaDef.h" +#include "Utils/Uuid.h" #include "generated/utility.grpc.pb.h" #include @@ -38,7 +39,6 @@ class UtilityImpl final : public ::maarpc::Utility::Service AtomicMap> states_; }; -extern std::string make_uuid(); extern void callback_impl(MaaStringView msg, MaaStringView detail, MaaCallbackTransparentArg arg); MAA_RPC_NS_END diff --git a/source/MaaToolKit/ExecAgent/ExecAgentBase.cpp b/source/MaaToolKit/ExecAgent/ExecAgentBase.cpp index 9cab613ba..9c8b39910 100644 --- a/source/MaaToolKit/ExecAgent/ExecAgentBase.cpp +++ b/source/MaaToolKit/ExecAgent/ExecAgentBase.cpp @@ -1,7 +1,6 @@ #include "ExecAgentBase.h" #include "MaaFramework/MaaAPI.h" -#include "Utils/Boost.hpp" #include "Utils/IOStream/ChildPipeIOStream.h" #include "Utils/Logger.h" diff --git a/source/MaaUtils/Uuid/Uuid.cpp b/source/MaaUtils/Uuid/Uuid.cpp new file mode 100644 index 000000000..2e0afbbd6 --- /dev/null +++ b/source/MaaUtils/Uuid/Uuid.cpp @@ -0,0 +1,16 @@ +#include "Utils/Uuid.h" + +MAA_SUPPRESS_BOOST_WARNINGS_BEGIN +#include +#include +MAA_SUPPRESS_BOOST_WARNINGS_END + +MAA_NS_BEGIN + +std::string make_uuid() +{ + static boost::uuids::random_generator uuid_generator; + return boost::uuids::to_string(uuid_generator()); +} + +MAA_NS_END diff --git a/source/include/LibraryHolder/LibraryHolder.h b/source/include/LibraryHolder/LibraryHolder.h index c2b0f7e9f..b2bb15b6d 100644 --- a/source/include/LibraryHolder/LibraryHolder.h +++ b/source/include/LibraryHolder/LibraryHolder.h @@ -4,8 +4,11 @@ #include #include +#define BOOST_DLL_USE_STD_FS 1 +#include +#include + #include "Conf/Conf.h" -#include "Utils/Boost.hpp" #include "Utils/Logger.h" MAA_NS_BEGIN diff --git a/source/include/Utils/Boost.hpp b/source/include/Utils/IOStream/BoostIO.hpp similarity index 53% rename from source/include/Utils/Boost.hpp rename to source/include/Utils/IOStream/BoostIO.hpp index e06b07f3c..15d621f97 100644 --- a/source/include/Utils/Boost.hpp +++ b/source/include/Utils/IOStream/BoostIO.hpp @@ -1,21 +1,15 @@ #pragma once -#include "Conf/Conf.h" - #ifdef _WIN32 #ifndef _WIN32_WINNT -#define _WIN32_WINNT 0x0601 // Win7 +#define _WIN32_WINNT 0x0A00 // Win10 #endif #endif #define BOOST_PROCESS_USE_STD_FS 1 -#define BOOST_DLL_USE_STD_FS 1 -MAA_SUPPRESS_BOOST_WARNINGS_BEGIN #include #include #ifdef _WIN32 #include #endif -#include -MAA_SUPPRESS_BOOST_WARNINGS_END diff --git a/source/include/Utils/IOStream/ChildPipeIOStream.h b/source/include/Utils/IOStream/ChildPipeIOStream.h index aec77965e..0fd125962 100644 --- a/source/include/Utils/IOStream/ChildPipeIOStream.h +++ b/source/include/Utils/IOStream/ChildPipeIOStream.h @@ -4,7 +4,6 @@ #include "IOStream.h" #include "MaaFramework/MaaPort.h" -#include "Utils/Boost.hpp" MAA_NS_BEGIN diff --git a/source/include/Utils/IOStream/IOStream.h b/source/include/Utils/IOStream/IOStream.h index 8a9ff5e86..1794f624d 100644 --- a/source/include/Utils/IOStream/IOStream.h +++ b/source/include/Utils/IOStream/IOStream.h @@ -4,6 +4,7 @@ #include #include +#include "BoostIO.hpp" #include "MaaFramework/MaaPort.h" #include "Utils/NonCopyable.hpp" diff --git a/source/include/Utils/IOStream/SockIOStream.h b/source/include/Utils/IOStream/SockIOStream.h index f406fb153..f2fbb09c9 100644 --- a/source/include/Utils/IOStream/SockIOStream.h +++ b/source/include/Utils/IOStream/SockIOStream.h @@ -4,7 +4,6 @@ #include "IOStream.h" #include "MaaFramework/MaaPort.h" -#include "Utils/Boost.hpp" #include "Utils/NonCopyable.hpp" MAA_NS_BEGIN diff --git a/source/include/Utils/Uuid.h b/source/include/Utils/Uuid.h new file mode 100644 index 000000000..6ed558e40 --- /dev/null +++ b/source/include/Utils/Uuid.h @@ -0,0 +1,12 @@ +#pragma once + +#include "Conf/Conf.h" +#include "MaaFramework/MaaPort.h" + +#include + +MAA_NS_BEGIN + +std::string MAA_UTILS_API make_uuid(); + +MAA_NS_END From 2e3c059eda1b16bd85efc40bfa5f93b17a497051 Mon Sep 17 00:00:00 2001 From: MistEO Date: Thu, 7 Dec 2023 00:22:39 +0800 Subject: [PATCH 19/23] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E4=B8=80?= =?UTF-8?q?=E7=B3=BB=E5=88=97=E7=AC=94=E8=AF=AF=E5=8F=8Abug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/MaaAdbControlUnit/Base/UnitBase.cpp | 8 ++--- source/MaaAdbControlUnit/Invoke/InvokeApp.cpp | 2 +- .../Screencap/EncodeToFile.cpp | 26 +++++++++++++---- .../Screencap/FastestWay.cpp | 4 ++- .../Screencap/RawByNetcat.cpp | 29 +++++++++++++++---- source/MaaToolKit/AdbDevice/DeviceMgr.cpp | 9 +++--- .../MaaUtils/IOStream/ChildPipeIOStream.cpp | 10 ++++++- source/MaaUtils/IOStream/SockIOStream.cpp | 5 +++- 8 files changed, 68 insertions(+), 25 deletions(-) diff --git a/source/MaaAdbControlUnit/Base/UnitBase.cpp b/source/MaaAdbControlUnit/Base/UnitBase.cpp index a7b88742e..79544588b 100644 --- a/source/MaaAdbControlUnit/Base/UnitBase.cpp +++ b/source/MaaAdbControlUnit/Base/UnitBase.cpp @@ -48,17 +48,17 @@ std::optional UnitBase::startup_and_read_pipe(const ProcessArgv& ar ChildPipeIOStream ios(argv.exec, argv.args); std::string output = ios.read(timeout); - int ret = ios.release(); + bool ret = ios.release(); auto duration = duration_since(start_time); - LogDebug << VAR(argv.exec) << VAR(argv.args) << VAR(output.size()) << VAR(duration); + LogDebug << VAR(output.size()) << VAR(duration); if (!output.empty() && output.size() < 4096) { LogDebug << MAA_LOG_NS::separator::newline << "output:" << output; } - if (ret != 0) { - LogError << "child return error" << VAR(argv.exec) << VAR(argv.args) << VAR(ret); + if (!ret) { + LogError << "child return error" << VAR(argv.exec) << VAR(argv.args); return std::nullopt; } diff --git a/source/MaaAdbControlUnit/Invoke/InvokeApp.cpp b/source/MaaAdbControlUnit/Invoke/InvokeApp.cpp index 55bc20538..b209dad60 100644 --- a/source/MaaAdbControlUnit/Invoke/InvokeApp.cpp +++ b/source/MaaAdbControlUnit/Invoke/InvokeApp.cpp @@ -99,7 +99,7 @@ bool InvokeApp::push(const std::filesystem::path& path) std::string absolute_path = path_to_crt_string(std::filesystem::absolute(path)); merge_replacement({ { "{BIN_PATH}", absolute_path }, { "{BIN_WORKING_FILE}", tempname_ } }); - auto argv_opt = sdk_argv_.gen(argv_replace_); + auto argv_opt = push_bin_argv_.gen(argv_replace_); if (!argv_opt) { return false; } diff --git a/source/MaaAdbControlUnit/Screencap/EncodeToFile.cpp b/source/MaaAdbControlUnit/Screencap/EncodeToFile.cpp index 1d482d477..49be17015 100644 --- a/source/MaaAdbControlUnit/Screencap/EncodeToFile.cpp +++ b/source/MaaAdbControlUnit/Screencap/EncodeToFile.cpp @@ -33,14 +33,28 @@ std::optional ScreencapEncodeToFileAndPull::screencap() merge_replacement({ { "{TEMP_FILE}", tempname_ }, { "{DST_PATH}", path_to_crt_string(dst_path) } }); - auto argv_opt = screencap_encode_to_file_argv_.gen(argv_replace_); - if (!argv_opt) { - return std::nullopt; + { + auto argv_opt = screencap_encode_to_file_argv_.gen(argv_replace_); + if (!argv_opt) { + return std::nullopt; + } + + auto output_opt = startup_and_read_pipe(*argv_opt); + if (!output_opt) { + return std::nullopt; + } } - auto output_opt = startup_and_read_pipe(*argv_opt); - if (!output_opt) { - return std::nullopt; + { + auto argv_opt = pull_file_argv_.gen(argv_replace_); + if (!argv_opt) { + return std::nullopt; + } + + auto output_opt = startup_and_read_pipe(*argv_opt); + if (!output_opt) { + return std::nullopt; + } } auto image = imread(dst_path); diff --git a/source/MaaAdbControlUnit/Screencap/FastestWay.cpp b/source/MaaAdbControlUnit/Screencap/FastestWay.cpp index d9a7d3b78..267a7ef21 100644 --- a/source/MaaAdbControlUnit/Screencap/FastestWay.cpp +++ b/source/MaaAdbControlUnit/Screencap/FastestWay.cpp @@ -115,13 +115,15 @@ bool ScreencapFastestWay::speed_test() // MinicapStream 是直接取数据,只取一次不准 const std::unordered_set kDropFirst = { Method::RawByNetcat, Method::MinicapStream }; - for (auto pair : units_) { + for (auto& pair : units_) { if (kDropFirst.contains(pair.first)) { + LogDebug << "Testing" << pair.first << "drop first"; if (!pair.second->screencap()) { continue; } } + LogDebug << "Testing" << pair.first; auto now = std::chrono::steady_clock::now(); if (pair.second->screencap()) { check(pair.first, now); diff --git a/source/MaaAdbControlUnit/Screencap/RawByNetcat.cpp b/source/MaaAdbControlUnit/Screencap/RawByNetcat.cpp index c8f5f4f8c..28ce6516a 100644 --- a/source/MaaAdbControlUnit/Screencap/RawByNetcat.cpp +++ b/source/MaaAdbControlUnit/Screencap/RawByNetcat.cpp @@ -1,5 +1,7 @@ #include "RawByNetcat.h" +#include "Utils/IOStream/ChildPipeIOStream.h" +#include "Utils/IOStream/SockIOStream.h" #include "Utils/Logger.h" MAA_CTRL_UNIT_NS_BEGIN @@ -59,17 +61,32 @@ std::optional ScreencapRawByNetcat::screencap() if (!argv_opt) { return std::nullopt; } + auto start_time = std::chrono::steady_clock::now(); - // netcat 能用的时候一般都很快,但连不上的时候会一直卡着,所以超时设短一点 - using namespace std::chrono_literals; - constexpr auto kTimeout = 2s; - auto output_opt = startup_and_read_pipe(*argv_opt, kTimeout); - if (!output_opt) { + auto& argv = *argv_opt; + + ChildPipeIOStream child(argv.exec, argv.args); + + auto ios = io_factory_->accept(); + if (!ios) { + LogError << "accept failed" << VAR(argv.exec) << VAR(argv.args); return std::nullopt; } + using namespace std::chrono_literals; + // netcat 能用的时候一般都很快,但连不上的时候会一直卡着,所以超时设短一点 + std::string output = ios->read(2s); + ios->release(); + + auto duration = duration_since(start_time); + LogDebug << VAR(argv.exec) << VAR(argv.args) << VAR(output.size()) << VAR(duration); + + if (!child.release()) { + LogWarn << "child return error" << VAR(argv.exec) << VAR(argv.args); + } + return screencap_helper_.process_data( - *output_opt, std::bind(&ScreencapHelper::decode_raw, &screencap_helper_, std::placeholders::_1)); + output, std::bind(&ScreencapHelper::decode_raw, &screencap_helper_, std::placeholders::_1)); } std::optional ScreencapRawByNetcat::request_netcat_address() diff --git a/source/MaaToolKit/AdbDevice/DeviceMgr.cpp b/source/MaaToolKit/AdbDevice/DeviceMgr.cpp index f93f936f2..cbc3b7721 100644 --- a/source/MaaToolKit/AdbDevice/DeviceMgr.cpp +++ b/source/MaaToolKit/AdbDevice/DeviceMgr.cpp @@ -108,15 +108,14 @@ MaaAdbControllerType DeviceMgr::check_adb_controller_type(const std::filesystem: std::ignore = adb_config; // TODO: 判断触控方式是否支持 - constexpr MaaAdbControllerType kInputType = MaaAdbControllerType_Input_Preset_Maatouch; - #ifdef MAA_DEBUG - constexpr MaaAdbControllerType kScreencapType = MaaAdbControllerType_Screencap_FastestWay; + constexpr MaaAdbControllerType kInputType = MaaAdbControllerType_Input_Preset_Adb; #else - // TODO: speed test - constexpr MaaAdbControllerType kScreencapType = MaaAdbControllerType_Screencap_FastestWay; + constexpr MaaAdbControllerType kInputType = MaaAdbControllerType_Input_Preset_Maatouch; #endif + constexpr MaaAdbControllerType kScreencapType = MaaAdbControllerType_Screencap_FastestWay; + return kInputType | kScreencapType; } diff --git a/source/MaaUtils/IOStream/ChildPipeIOStream.cpp b/source/MaaUtils/IOStream/ChildPipeIOStream.cpp index fb04e018c..fe5f9f135 100644 --- a/source/MaaUtils/IOStream/ChildPipeIOStream.cpp +++ b/source/MaaUtils/IOStream/ChildPipeIOStream.cpp @@ -13,7 +13,9 @@ ChildPipeIOStream::ChildPipeIOStream(const std::filesystem::path& exec, const st boost::process::windows::create_no_window #endif ) -{} +{ + LogDebug << VAR(exec) << VAR(args); +} ChildPipeIOStream::~ChildPipeIOStream() { @@ -33,6 +35,12 @@ bool ChildPipeIOStream::write(std::string_view data) bool ChildPipeIOStream::release() { + auto start_time = std::chrono::steady_clock::now(); + using namespace std::chrono_literals; + while (child_.running() && duration_since(start_time) < 100ms) { + std::this_thread::yield(); + } + if (child_.running()) { child_.terminate(); } diff --git a/source/MaaUtils/IOStream/SockIOStream.cpp b/source/MaaUtils/IOStream/SockIOStream.cpp index d54a4c405..b666119a8 100644 --- a/source/MaaUtils/IOStream/SockIOStream.cpp +++ b/source/MaaUtils/IOStream/SockIOStream.cpp @@ -65,7 +65,10 @@ std::shared_ptr ClientSockIOFactory::connect() SockIOStream::SockIOStream(boost::asio::ip::tcp::iostream&& ios) : ios_(std::move(ios)) {} -SockIOStream::~SockIOStream() {} +SockIOStream::~SockIOStream() +{ + release(); +} bool SockIOStream::write(std::string_view data) { From be63febad7e5ada8c9665905f41ecec25a09d96b Mon Sep 17 00:00:00 2001 From: MistEO Date: Thu, 7 Dec 2023 00:58:54 +0800 Subject: [PATCH 20/23] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8Dminitouch?= =?UTF-8?q?=E7=9B=B8=E5=85=B3=E7=9A=84=E8=AF=BB=E5=8F=96=E5=8F=8A=E5=86=99?= =?UTF-8?q?=E5=85=A5=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MaaAdbControlUnit/Input/MtouchHelper.cpp | 39 ++++++------------- source/MaaToolKit/AdbDevice/DeviceMgr.cpp | 5 --- .../MaaUtils/IOStream/ChildPipeIOStream.cpp | 4 +- source/MaaUtils/IOStream/SockIOStream.cpp | 4 +- 4 files changed, 15 insertions(+), 37 deletions(-) diff --git a/source/MaaAdbControlUnit/Input/MtouchHelper.cpp b/source/MaaAdbControlUnit/Input/MtouchHelper.cpp index aeaccc0f0..b224250eb 100644 --- a/source/MaaAdbControlUnit/Input/MtouchHelper.cpp +++ b/source/MaaAdbControlUnit/Input/MtouchHelper.cpp @@ -18,37 +18,20 @@ bool MtouchHelper::read_info(int swidth, int sheight, int orientation) return !timeout; }; - std::string prev; - std::string info; - - while (check_time()) { - using namespace std::chrono_literals; - auto str = prev + shell_handler_->read(5s); - LogDebug << "output:" << str; - if (str.empty()) { - std::this_thread::sleep_for(2s); - continue; - } - auto pos = str.find('^'); - if (pos == std::string::npos) { - continue; - } - auto rpos = str.find('\n', pos); - if (rpos == std::string::npos) { - prev = str; // 也许还得再读点? - continue; - } - - info = str.substr(pos + 1, rpos - pos - 1); - break; - } - if (timeout) { - LogError << "read info timeout"; + if (!shell_handler_) { + LogError << "shell handler not ready"; return false; } - LogInfo << "info:" << info; - string_trim_(info); + using namespace std::chrono_literals; + std::ignore = shell_handler_->read_until("^", 5s); + std::string info = shell_handler_->read_until("\n", 1s); + + if (info.empty()) { + LogError << "failed to read info"; + return false; + } + LogInfo << VAR(info); int contact = 0; int x = 0; diff --git a/source/MaaToolKit/AdbDevice/DeviceMgr.cpp b/source/MaaToolKit/AdbDevice/DeviceMgr.cpp index cbc3b7721..fe2e4f163 100644 --- a/source/MaaToolKit/AdbDevice/DeviceMgr.cpp +++ b/source/MaaToolKit/AdbDevice/DeviceMgr.cpp @@ -108,12 +108,7 @@ MaaAdbControllerType DeviceMgr::check_adb_controller_type(const std::filesystem: std::ignore = adb_config; // TODO: 判断触控方式是否支持 -#ifdef MAA_DEBUG - constexpr MaaAdbControllerType kInputType = MaaAdbControllerType_Input_Preset_Adb; -#else constexpr MaaAdbControllerType kInputType = MaaAdbControllerType_Input_Preset_Maatouch; -#endif - constexpr MaaAdbControllerType kScreencapType = MaaAdbControllerType_Screencap_FastestWay; return kInputType | kScreencapType; diff --git a/source/MaaUtils/IOStream/ChildPipeIOStream.cpp b/source/MaaUtils/IOStream/ChildPipeIOStream.cpp index fe5f9f135..d00830711 100644 --- a/source/MaaUtils/IOStream/ChildPipeIOStream.cpp +++ b/source/MaaUtils/IOStream/ChildPipeIOStream.cpp @@ -24,8 +24,8 @@ ChildPipeIOStream::~ChildPipeIOStream() bool ChildPipeIOStream::write(std::string_view data) { - if (is_open()) { - LogError << "not opened"; + if (!pout_.good()) { + LogError << "pout is not good"; return false; } diff --git a/source/MaaUtils/IOStream/SockIOStream.cpp b/source/MaaUtils/IOStream/SockIOStream.cpp index b666119a8..2c6c1dbd8 100644 --- a/source/MaaUtils/IOStream/SockIOStream.cpp +++ b/source/MaaUtils/IOStream/SockIOStream.cpp @@ -72,8 +72,8 @@ SockIOStream::~SockIOStream() bool SockIOStream::write(std::string_view data) { - if (!is_open()) { - LogError << "not opened"; + if (!ios_.good()) { + LogError << "ios is not good"; return false; } From 16d40deeaaa8f89909e31b402484331ece75ced0 Mon Sep 17 00:00:00 2001 From: MistEO Date: Thu, 7 Dec 2023 01:15:08 +0800 Subject: [PATCH 21/23] =?UTF-8?q?perf:=20minicap=E8=AF=BB=E5=8F=96?= =?UTF-8?q?=E6=96=B9=E5=BC=8F=E4=BC=98=E5=8C=96=EF=BC=8C=E9=83=A8=E5=88=86?= =?UTF-8?q?=E5=8F=98=E9=87=8F=E9=87=8D=E5=91=BD=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MaaAdbControlUnit/Input/MaatouchInput.cpp | 10 ++--- .../Input/MinitouchInput.cpp | 4 +- .../MaaAdbControlUnit/Input/MtouchHelper.cpp | 37 ++++++++-------- source/MaaAdbControlUnit/Input/MtouchHelper.h | 2 +- .../Screencap/Minicap/MinicapStream.cpp | 42 ++++++------------- .../Screencap/Minicap/MinicapStream.h | 4 +- 6 files changed, 42 insertions(+), 57 deletions(-) diff --git a/source/MaaAdbControlUnit/Input/MaatouchInput.cpp b/source/MaaAdbControlUnit/Input/MaatouchInput.cpp index 55b5432b0..7ca9ab191 100644 --- a/source/MaaAdbControlUnit/Input/MaatouchInput.cpp +++ b/source/MaaAdbControlUnit/Input/MaatouchInput.cpp @@ -41,8 +41,8 @@ bool MaatouchInput::set_wh(int swidth, int sheight, int orientation) { LogFunc << VAR(swidth) << VAR(sheight) << VAR(orientation); - shell_handler_ = invoke_app_->invoke_app(package_name_); - if (!shell_handler_) { + pipe_ios_ = invoke_app_->invoke_app(package_name_); + if (!pipe_ios_) { return false; } @@ -53,7 +53,7 @@ bool MaatouchInput::press_key(int key) { LogInfo << VAR(key); - if (!shell_handler_) { + if (!pipe_ios_) { return false; } @@ -61,8 +61,8 @@ bool MaatouchInput::press_key(int key) static constexpr std::string_view kKeyDownFormat = "k {} d\nc\n"; static constexpr std::string_view kKeyUpFormat = "k {} u\nc\n"; - bool ret = shell_handler_->write(MAA_FMT::format(kKeyDownFormat, key)) && - shell_handler_->write(MAA_FMT::format(kKeyUpFormat, key)); + bool ret = + pipe_ios_->write(MAA_FMT::format(kKeyDownFormat, key)) && pipe_ios_->write(MAA_FMT::format(kKeyUpFormat, key)); if (!ret) { LogError << "failed to write"; diff --git a/source/MaaAdbControlUnit/Input/MinitouchInput.cpp b/source/MaaAdbControlUnit/Input/MinitouchInput.cpp index b5851dbdb..2339c5ef1 100644 --- a/source/MaaAdbControlUnit/Input/MinitouchInput.cpp +++ b/source/MaaAdbControlUnit/Input/MinitouchInput.cpp @@ -63,8 +63,8 @@ bool MinitouchInput::set_wh(int swidth, int sheight, int orientation) // https://github.com/openstf/minitouch#running static const std::string kMinitouchUseStdin = "-i"; - shell_handler_ = invoke_app_->invoke_bin(kMinitouchUseStdin); - if (!shell_handler_) { + pipe_ios_ = invoke_app_->invoke_bin(kMinitouchUseStdin); + if (!pipe_ios_) { return false; } diff --git a/source/MaaAdbControlUnit/Input/MtouchHelper.cpp b/source/MaaAdbControlUnit/Input/MtouchHelper.cpp index b224250eb..7fdf4a20e 100644 --- a/source/MaaAdbControlUnit/Input/MtouchHelper.cpp +++ b/source/MaaAdbControlUnit/Input/MtouchHelper.cpp @@ -18,16 +18,17 @@ bool MtouchHelper::read_info(int swidth, int sheight, int orientation) return !timeout; }; - if (!shell_handler_) { + if (!pipe_ios_) { LogError << "shell handler not ready"; return false; } using namespace std::chrono_literals; - std::ignore = shell_handler_->read_until("^", 5s); - std::string info = shell_handler_->read_until("\n", 1s); + std::ignore = pipe_ios_->read_until("^", 5s); + constexpr std::string_view kFlag = "\n"; + std::string info = pipe_ios_->read_until(kFlag, 1s); - if (info.empty()) { + if (!info.ends_with(kFlag)) { LogError << "failed to read info"; return false; } @@ -61,7 +62,7 @@ bool MtouchHelper::read_info(int swidth, int sheight, int orientation) bool MtouchHelper::click(int x, int y) { - if (!shell_handler_) { + if (!pipe_ios_) { LogError << "shell handler not ready"; return false; } @@ -76,8 +77,8 @@ bool MtouchHelper::click(int x, int y) LogInfo << VAR(x) << VAR(y) << VAR(touch_x) << VAR(touch_y); - bool ret = shell_handler_->write(MAA_FMT::format(kDownFormat, 0, touch_x, touch_y, press_)) && - shell_handler_->write(MAA_FMT::format(kUpFormat, 0)); + bool ret = pipe_ios_->write(MAA_FMT::format(kDownFormat, 0, touch_x, touch_y, press_)) && + pipe_ios_->write(MAA_FMT::format(kUpFormat, 0)); if (!ret) { LogError << "failed to write"; @@ -89,7 +90,7 @@ bool MtouchHelper::click(int x, int y) bool MtouchHelper::swipe(int x1, int y1, int x2, int y2, int duration) { - if (!shell_handler_) { + if (!pipe_ios_) { return false; } @@ -115,7 +116,7 @@ bool MtouchHelper::swipe(int x1, int y1, int x2, int y2, int duration) auto start = std::chrono::steady_clock::now(); auto now = start; bool ret = true; - ret &= shell_handler_->write(MAA_FMT::format(kDownFormat, 0, touch_x1, touch_y1, press_)); + ret &= pipe_ios_->write(MAA_FMT::format(kDownFormat, 0, touch_x1, touch_y1, press_)); if (!ret) { LogError << "write error"; return false; @@ -132,7 +133,7 @@ bool MtouchHelper::swipe(int x1, int y1, int x2, int y2, int duration) std::this_thread::sleep_until(now + delay); now = std::chrono::steady_clock::now(); - ret &= shell_handler_->write(MAA_FMT::format(kMoveFormat, 0, tx, ty, press_)); + ret &= pipe_ios_->write(MAA_FMT::format(kMoveFormat, 0, tx, ty, press_)); if (!ret) { LogWarn << "write error"; } @@ -140,11 +141,11 @@ bool MtouchHelper::swipe(int x1, int y1, int x2, int y2, int duration) std::this_thread::sleep_until(now + delay); now = std::chrono::steady_clock::now(); - ret &= shell_handler_->write(MAA_FMT::format(kMoveFormat, 0, touch_x2, touch_y2, press_)); + ret &= pipe_ios_->write(MAA_FMT::format(kMoveFormat, 0, touch_x2, touch_y2, press_)); std::this_thread::sleep_until(now + delay); now = std::chrono::steady_clock::now(); - ret &= shell_handler_->write(MAA_FMT::format(kUpFormat, 0)); + ret &= pipe_ios_->write(MAA_FMT::format(kUpFormat, 0)); if (!ret) { LogError << "failed to write"; @@ -156,7 +157,7 @@ bool MtouchHelper::swipe(int x1, int y1, int x2, int y2, int duration) bool MtouchHelper::touch_down(int contact, int x, int y, int pressure) { - if (!shell_handler_) { + if (!pipe_ios_) { LogError << "shell handler not ready"; return false; } @@ -165,7 +166,7 @@ bool MtouchHelper::touch_down(int contact, int x, int y, int pressure) LogInfo << VAR(contact) << VAR(x) << VAR(y) << VAR(touch_x) << VAR(touch_y); - bool ret = shell_handler_->write(MAA_FMT::format(kDownFormat, contact, touch_x, touch_y, pressure)); + bool ret = pipe_ios_->write(MAA_FMT::format(kDownFormat, contact, touch_x, touch_y, pressure)); if (!ret) { LogError << "failed to write"; @@ -177,7 +178,7 @@ bool MtouchHelper::touch_down(int contact, int x, int y, int pressure) bool MtouchHelper::touch_move(int contact, int x, int y, int pressure) { - if (!shell_handler_) { + if (!pipe_ios_) { LogError << "shell handler not ready"; return false; } @@ -186,7 +187,7 @@ bool MtouchHelper::touch_move(int contact, int x, int y, int pressure) LogInfo << VAR(contact) << VAR(x) << VAR(y) << VAR(touch_x) << VAR(touch_y); - bool ret = shell_handler_->write(MAA_FMT::format(kMoveFormat, contact, touch_x, touch_y, pressure)); + bool ret = pipe_ios_->write(MAA_FMT::format(kMoveFormat, contact, touch_x, touch_y, pressure)); if (!ret) { LogError << "failed to write"; @@ -198,14 +199,14 @@ bool MtouchHelper::touch_move(int contact, int x, int y, int pressure) bool MtouchHelper::touch_up(int contact) { - if (!shell_handler_) { + if (!pipe_ios_) { LogError << "shell handler not ready"; return false; } LogInfo << VAR(contact); - bool ret = shell_handler_->write(MAA_FMT::format(kUpFormat, contact)); + bool ret = pipe_ios_->write(MAA_FMT::format(kUpFormat, contact)); if (!ret) { LogError << "failed to write"; diff --git a/source/MaaAdbControlUnit/Input/MtouchHelper.h b/source/MaaAdbControlUnit/Input/MtouchHelper.h index e2f11308f..8ef31396d 100644 --- a/source/MaaAdbControlUnit/Input/MtouchHelper.h +++ b/source/MaaAdbControlUnit/Input/MtouchHelper.h @@ -30,7 +30,7 @@ class MtouchHelper : public TouchInputBase static constexpr std::string_view kMoveFormat = "m {} {} {} {}\nc\n"; static constexpr std::string_view kUpFormat = "u {}\nc\n"; - std::shared_ptr shell_handler_ = nullptr; + std::shared_ptr pipe_ios_ = nullptr; int screen_width_ = 0; int screen_height_ = 0; diff --git a/source/MaaAdbControlUnit/Screencap/Minicap/MinicapStream.cpp b/source/MaaAdbControlUnit/Screencap/Minicap/MinicapStream.cpp index a1411a076..80ea51c3c 100644 --- a/source/MaaAdbControlUnit/Screencap/Minicap/MinicapStream.cpp +++ b/source/MaaAdbControlUnit/Screencap/Minicap/MinicapStream.cpp @@ -50,34 +50,18 @@ bool MinicapStream::init(int swidth, int sheight) uint32_t width = screencap_helper_.get_w(); uint32_t height = screencap_helper_.get_h(); - process_handle_ = binary_->invoke_bin(MAA_FMT::format("-P {}x{}@{}x{}/{}", width, height, width, height, 0)); + pipe_ios_ = binary_->invoke_bin(MAA_FMT::format("-P {}x{}@{}x{}/{}", width, height, width, height, 0)); - if (!process_handle_) { + if (!pipe_ios_) { LogError << "invoke_bin failed"; return false; } - bool ok = false; - - std::string buffer; - constexpr int kMaxTry = 50; - for (int i = 0; i < kMaxTry; ++i) { - using namespace std::chrono_literals; - auto res = process_handle_->read(5s); - - if (!res.empty()) { - LogDebug << "minicap stdout:" << res; - buffer.append(res); - } - if (buffer.find("Allocating") != std::string::npos) { - ok = true; - break; - } - using namespace std::chrono_literals; - std::this_thread::sleep_for(100ms); - } - if (!ok) { - LogError << "minicap stdout:" << buffer; + constexpr std::string_view kFlag = "Allocating"; + using namespace std::chrono_literals; + std::string output = pipe_ios_->read_until(kFlag, 10s); + if (!output.ends_with(kFlag)) { + LogError << "read_until failed" << VAR(output); return false; } @@ -88,11 +72,11 @@ bool MinicapStream::init(int swidth, int sheight) local = serial_host.substr(0, shp); } - LogInfo << "minicap try connect to:" << local; + LogInfo << "minicap try to connect" << VAR(local) << VAR(port_); ClientSockIOFactory io_factory(local, static_cast(port_)); - stream_handle_ = io_factory.connect(); - if (!stream_handle_) { + sock_ios_ = io_factory.connect(); + if (!sock_ios_) { return false; } @@ -144,13 +128,13 @@ std::optional MinicapStream::screencap() std::optional MinicapStream::read(size_t count) { - if (!stream_handle_) { - LogError << "stream_handle_ is nullptr"; + if (!sock_ios_) { + LogError << "sock_ios_ is nullptr"; return std::nullopt; } using namespace std::chrono_literals; - return stream_handle_->read_some(count, 5s); + return sock_ios_->read_some(count, 1s); } void MinicapStream::working_thread() diff --git a/source/MaaAdbControlUnit/Screencap/Minicap/MinicapStream.h b/source/MaaAdbControlUnit/Screencap/Minicap/MinicapStream.h index d3690df63..3b83b9034 100644 --- a/source/MaaAdbControlUnit/Screencap/Minicap/MinicapStream.h +++ b/source/MaaAdbControlUnit/Screencap/Minicap/MinicapStream.h @@ -39,8 +39,8 @@ class MinicapStream : public MinicapBase std::condition_variable cond_; std::thread pull_thread_; - std::shared_ptr process_handle_; - std::shared_ptr stream_handle_; + std::shared_ptr pipe_ios_; + std::shared_ptr sock_ios_; }; MAA_CTRL_UNIT_NS_END From e152616f87de0111c136f7926e7b4e3f8f1c4d9e Mon Sep 17 00:00:00 2001 From: MistEO Date: Thu, 7 Dec 2023 01:22:32 +0800 Subject: [PATCH 22/23] =?UTF-8?q?chore:=20=E5=B0=8F=E7=BB=86=E8=8A=82?= =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MaaAdbControlUnit/Input/MaatouchInput.cpp | 3 +- .../MaaAdbControlUnit/Input/MtouchHelper.cpp | 28 ++++++++----------- .../Screencap/Minicap/MinicapStream.cpp | 12 ++++---- .../Screencap/Minicap/MinicapStream.h | 4 +-- 4 files changed, 21 insertions(+), 26 deletions(-) diff --git a/source/MaaAdbControlUnit/Input/MaatouchInput.cpp b/source/MaaAdbControlUnit/Input/MaatouchInput.cpp index 7ca9ab191..0bbbee00e 100644 --- a/source/MaaAdbControlUnit/Input/MaatouchInput.cpp +++ b/source/MaaAdbControlUnit/Input/MaatouchInput.cpp @@ -54,6 +54,7 @@ bool MaatouchInput::press_key(int key) LogInfo << VAR(key); if (!pipe_ios_) { + LogError << "pipe_ios_ is nullptr"; return false; } @@ -69,7 +70,7 @@ bool MaatouchInput::press_key(int key) return false; } - return ret; + return true; } MAA_CTRL_UNIT_NS_END diff --git a/source/MaaAdbControlUnit/Input/MtouchHelper.cpp b/source/MaaAdbControlUnit/Input/MtouchHelper.cpp index 7fdf4a20e..81a2fb8de 100644 --- a/source/MaaAdbControlUnit/Input/MtouchHelper.cpp +++ b/source/MaaAdbControlUnit/Input/MtouchHelper.cpp @@ -11,15 +11,8 @@ MAA_CTRL_UNIT_NS_BEGIN bool MtouchHelper::read_info(int swidth, int sheight, int orientation) { - auto start_time = std::chrono::steady_clock::now(); - bool timeout = false; - auto check_time = [&]() { - timeout = duration_since(start_time) > std::chrono::seconds(10); - return !timeout; - }; - if (!pipe_ios_) { - LogError << "shell handler not ready"; + LogError << "pipe_ios_ is nullptr"; return false; } @@ -63,7 +56,7 @@ bool MtouchHelper::read_info(int swidth, int sheight, int orientation) bool MtouchHelper::click(int x, int y) { if (!pipe_ios_) { - LogError << "shell handler not ready"; + LogError << "pipe_ios_ is nullptr"; return false; } @@ -85,12 +78,13 @@ bool MtouchHelper::click(int x, int y) return false; } - return ret; + return true; } bool MtouchHelper::swipe(int x1, int y1, int x2, int y2, int duration) { if (!pipe_ios_) { + LogError << "pipe_ios_ is nullptr"; return false; } @@ -152,13 +146,13 @@ bool MtouchHelper::swipe(int x1, int y1, int x2, int y2, int duration) return false; } - return ret; + return true; } bool MtouchHelper::touch_down(int contact, int x, int y, int pressure) { if (!pipe_ios_) { - LogError << "shell handler not ready"; + LogError << "pipe_ios_ is nullptr"; return false; } @@ -173,13 +167,13 @@ bool MtouchHelper::touch_down(int contact, int x, int y, int pressure) return false; } - return ret; + return true; } bool MtouchHelper::touch_move(int contact, int x, int y, int pressure) { if (!pipe_ios_) { - LogError << "shell handler not ready"; + LogError << "pipe_ios_ is nullptr"; return false; } @@ -194,13 +188,13 @@ bool MtouchHelper::touch_move(int contact, int x, int y, int pressure) return false; } - return ret; + return true; } bool MtouchHelper::touch_up(int contact) { if (!pipe_ios_) { - LogError << "shell handler not ready"; + LogError << "pipe_ios_ is nullptr"; return false; } @@ -213,7 +207,7 @@ bool MtouchHelper::touch_up(int contact) return false; } - return ret; + return true; } MAA_CTRL_UNIT_NS_END diff --git a/source/MaaAdbControlUnit/Screencap/Minicap/MinicapStream.cpp b/source/MaaAdbControlUnit/Screencap/Minicap/MinicapStream.cpp index 80ea51c3c..0c3f8a14f 100644 --- a/source/MaaAdbControlUnit/Screencap/Minicap/MinicapStream.cpp +++ b/source/MaaAdbControlUnit/Screencap/Minicap/MinicapStream.cpp @@ -42,8 +42,8 @@ bool MinicapStream::init(int swidth, int sheight) return false; } - auto output_opt = startup_and_read_pipe(*argv_opt); - if (!output_opt) { + auto startup_output_opt = startup_and_read_pipe(*argv_opt); + if (!startup_output_opt) { return false; } @@ -53,15 +53,15 @@ bool MinicapStream::init(int swidth, int sheight) pipe_ios_ = binary_->invoke_bin(MAA_FMT::format("-P {}x{}@{}x{}/{}", width, height, width, height, 0)); if (!pipe_ios_) { - LogError << "invoke_bin failed"; + LogError << "pipe_ios_ is nullptr"; return false; } constexpr std::string_view kFlag = "Allocating"; using namespace std::chrono_literals; - std::string output = pipe_ios_->read_until(kFlag, 10s); - if (!output.ends_with(kFlag)) { - LogError << "read_until failed" << VAR(output); + std::string invoke_output = pipe_ios_->read_until(kFlag, 10s); + if (!invoke_output.ends_with(kFlag)) { + LogError << "read_until failed" << VAR(invoke_output); return false; } diff --git a/source/MaaAdbControlUnit/Screencap/Minicap/MinicapStream.h b/source/MaaAdbControlUnit/Screencap/Minicap/MinicapStream.h index 3b83b9034..cc44be498 100644 --- a/source/MaaAdbControlUnit/Screencap/Minicap/MinicapStream.h +++ b/source/MaaAdbControlUnit/Screencap/Minicap/MinicapStream.h @@ -39,8 +39,8 @@ class MinicapStream : public MinicapBase std::condition_variable cond_; std::thread pull_thread_; - std::shared_ptr pipe_ios_; - std::shared_ptr sock_ios_; + std::shared_ptr pipe_ios_ = nullptr; + std::shared_ptr sock_ios_ = nullptr; }; MAA_CTRL_UNIT_NS_END From bca84d83b029da862592bfb3fe4ab3dea2a885f5 Mon Sep 17 00:00:00 2001 From: MistEO Date: Thu, 7 Dec 2023 13:16:54 +0800 Subject: [PATCH 23/23] chore: update sample --- sample/cpp/main.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/sample/cpp/main.cpp b/sample/cpp/main.cpp index 1b1e7091b..2178d504f 100644 --- a/sample/cpp/main.cpp +++ b/sample/cpp/main.cpp @@ -112,12 +112,9 @@ MaaBool my_analyze(MaaSyncContextHandle sync_context, const MaaImageBufferHandle /* Output recognition result */ - // Step 1: output out_box + // Step 1: output box std::array my_box { 0 }; // your result - out_box->x = my_box[0]; - out_box->y = my_box[1]; - out_box->width = my_box[2]; - out_box->height = my_box[3]; + MaaSetRect(out_box, my_box[0], my_box[1], my_box[2], my_box[3]); // Step 2: output anything you want MaaSetString(out_detail,