todo rpc框架

This commit is contained in:
daiqingshuang
2025-08-19 19:13:40 +08:00
parent 16235e0936
commit b96404e317
28 changed files with 663 additions and 169 deletions

View File

@@ -50,7 +50,7 @@ find_package(gRPC CONFIG REQUIRED)
find_package(Protobuf CONFIG REQUIRED)
find_package(ZeroMQ CONFIG REQUIRED)
find_package(spdlog CONFIG REQUIRED)
find_package(Boost CONFIG REQUIRED COMPONENTS system thread interprocess lockfree asio)
find_package(Boost CONFIG REQUIRED COMPONENTS system interprocess lockfree asio process)
# --- Protocol Buffers 编译 (Protocol Buffers Compilation) ---
# 使用自定义函数编译 .proto 文件,自动生成 C++ 源代码和 gRPC 服务代码。
@@ -60,7 +60,7 @@ find_package(Boost CONFIG REQUIRED COMPONENTS system thread interprocess lockfre
# @param OUTPUT_PATH: 生成的 .pb.h, .pb.cc, .grpc.pb.h, .grpc.pb.cc 文件的输出目录。
# @param GRPC_ENABLED: 设置为 TRUE表示同时生成 gRPC 服务相关的代码。
compile_proto_files(
TARGET_NAME alicho_proto
TARGET_NAME AlichoProto
PROTO_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../proto
OUTPUT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/proto
GRPC_ENABLED TRUE

View File

@@ -23,6 +23,11 @@ function(add_os_definitions target)
set(alicho_def_arch_64bit 0)
set(alicho_def_arch_32bit 0)
set(alicho_def_apple 0) # 用于 iOS 和 macOS 的通用定义
set(alicho_def_debug 0) # 当前是否处于调试模式
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
set(alicho_def_debug 1)
endif ()
# -- 操作系统检测与赋值 --
# 注意检测顺序:优先检测更具体的平台
@@ -113,6 +118,8 @@ function(add_os_definitions target)
list(APPEND definitions_list "ALICHO_PLATFORM_POSIX=${alicho_def_posix}")
list(APPEND definitions_list "ALICHO_PLATFORM_IS_MOBILE=${alicho_def_mobile}")
list(APPEND definitions_list "ALICHO_DEBUG=${alicho_def_debug}") # 当前是否处于调试模式
# --- 阶段 3: 应用所有定义 ---
# **关键:使用一次调用将所有定义添加到目标**
if(definitions_list) # 确保列表非空

View File

@@ -30,5 +30,14 @@ target_link_libraries(${PROJECT_NAME} PRIVATE
gRPC::grpc++
protobuf::libprotobuf
libzmq
alicho_proto
Boost::process
Boost::interprocess
Boost::system
Boost::lockfree
Boost::asio
AlichoProto
AlichoMisc
ws2_32
)
target_compile_definitions(${PROJECT_NAME} PRIVATE _WIN32_WINNT=0x0A00 WIN32_LEAN_AND_MEAN)
target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)

View File

@@ -0,0 +1 @@
#include "engine_grpc.h"

View File

@@ -0,0 +1,96 @@
#pragma once
#include "ctrl/frontend_to_engine.grpc.pb.h"
class daw_api_project_service : public daw::api::ProjectService::Service {
public:
grpc::Status NewProject(grpc::ServerContext* context,
const google::protobuf::Empty* request,
daw::api::ProjectState* response) override {
return grpc::Status::OK;
}
grpc::Status LoadProject(grpc::ServerContext* context,
const daw::api::LoadProjectRequest* request,
daw::api::ProjectState* response) override {
return grpc::Status::OK;
}
grpc::Status SaveProject(grpc::ServerContext* context,
const daw::api::SaveProjectRequest* request,
daw::api::StatusResponse* response) override {
return grpc::Status::OK;
}
};
class daw_api_transport_service : public daw::api::TransportService::Service {
public:
virtual ~daw_api_transport_service() override;
virtual grpc::Status Play(grpc::ServerContext* context,
const google::protobuf::Empty* request,
daw::api::StatusResponse* response) override;
virtual grpc::Status Pause(grpc::ServerContext* context,
const google::protobuf::Empty* request,
daw::api::StatusResponse* response) override;
virtual grpc::Status Stop(grpc::ServerContext* context,
const google::protobuf::Empty* request,
daw::api::StatusResponse* response) override;
virtual grpc::Status SetTempo(grpc::ServerContext* context,
const daw::api::SetTempoRequest* request,
daw::api::StatusResponse* response) override;
};
class daw_api_track_service : public daw::api::TrackService::Service {
public:
grpc::Status AddTrack(grpc::ServerContext* context,
const daw::api::AddTrackRequest* request,
daw::api::TrackInfo* response) override {
return grpc::Status::OK;
}
grpc::Status RemoveTrack(grpc::ServerContext* context,
const daw::api::TrackIdRequest* request,
daw::api::StatusResponse* response) override {
return grpc::Status::OK;
}
grpc::Status SetTrackVolume(grpc::ServerContext* context,
const daw::api::SetTrackVolumeRequest* request,
daw::api::StatusResponse* response) override {
return grpc::Status::OK;
}
grpc::Status SetTrackPan(grpc::ServerContext* context,
const daw::api::SetTrackPanRequest* request,
daw::api::StatusResponse* response) override {
return grpc::Status::OK;
}
};
class daw_api_plugin_service : public daw::api::PluginService::Service {
public:
grpc::Status LoadPlugin(grpc::ServerContext* context,
const daw::api::LoadPluginRequest* request,
daw::api::PluginInfo* response) override {
return grpc::Status::OK;
}
grpc::Status SetPluginParameter(grpc::ServerContext* context,
const daw::api::SetPluginParameterRequest* request,
daw::api::StatusResponse* response) override {
return grpc::Status::OK;
}
};

View File

@@ -1,104 +1,22 @@
//
// Created by A on 2025/8/12.
//
#include "zmq.h"
#include "ctrl/frontend_to_engine.grpc.pb.h"
class daw_api_project_service : public daw::api::ProjectService::Service {
public:
grpc::Status NewProject(grpc::ServerContext* context,
const google::protobuf::Empty* request,
daw::api::ProjectState* response) override {
return grpc::Status::OK;
}
grpc::Status LoadProject(grpc::ServerContext* context,
const daw::api::LoadProjectRequest* request,
daw::api::ProjectState* response) override {
return grpc::Status::OK;
}
grpc::Status SaveProject(grpc::ServerContext* context,
const daw::api::SaveProjectRequest* request,
daw::api::StatusResponse* response) override {
return grpc::Status::OK;
}
};
class daw_api_transport_service : public daw::api::TransportService::Service {
public:
virtual ~daw_api_transport_service() override;
virtual grpc::Status Play(grpc::ServerContext* context,
const google::protobuf::Empty* request,
daw::api::StatusResponse* response) override;
virtual grpc::Status Pause(grpc::ServerContext* context,
const google::protobuf::Empty* request,
daw::api::StatusResponse* response) override;
virtual grpc::Status Stop(grpc::ServerContext* context,
const google::protobuf::Empty* request,
daw::api::StatusResponse* response) override;
virtual grpc::Status SetTempo(grpc::ServerContext* context,
const daw::api::SetTempoRequest* request,
daw::api::StatusResponse* response) override;
};
class daw_api_track_service : public daw::api::TrackService::Service {
public:
grpc::Status AddTrack(grpc::ServerContext* context,
const daw::api::AddTrackRequest* request,
daw::api::TrackInfo* response) override {
return grpc::Status::OK;
}
grpc::Status RemoveTrack(grpc::ServerContext* context,
const daw::api::TrackIdRequest* request,
daw::api::StatusResponse* response) override {
return grpc::Status::OK;
}
grpc::Status SetTrackVolume(grpc::ServerContext* context,
const daw::api::SetTrackVolumeRequest* request,
daw::api::StatusResponse* response) override {
return grpc::Status::OK;
}
grpc::Status SetTrackPan(grpc::ServerContext* context,
const daw::api::SetTrackPanRequest* request,
daw::api::StatusResponse* response) override {
return grpc::Status::OK;
}
};
class daw_api_plugin_service : public daw::api::PluginService::Service {
public:
grpc::Status LoadPlugin(grpc::ServerContext* context,
const daw::api::LoadPluginRequest* request,
daw::api::PluginInfo* response) override {
return grpc::Status::OK;
}
grpc::Status SetPluginParameter(grpc::ServerContext* context,
const daw::api::SetPluginParameterRequest* request,
daw::api::StatusResponse* response) override {
return grpc::Status::OK;
}
};
#include "plugin_manage/plugin_host_manager.h"
#include "rpc/rpc_session.h"
#include <filesystem>
int main(int argc, char *argv[])
{
std::filesystem::path path(R"(D:\Projects\Alicho\src\backend\src\vst2_host\test\4Front Piano x64.dll)");
plugin_host_manager::get_instance().load_plugin(path);
uint32_t times = 0;
while (true) {
// 模拟主循环
std::this_thread::sleep_for(std::chrono::milliseconds(100));
if (++times > 10) {
break; // 运行10次后退出
}
}
return 0;
}

View File

@@ -0,0 +1,53 @@
#include "plugin_host_manager.h"
#include "plugin_instance.h"
plugin_host_manager::~plugin_host_manager() {
std::vector<uint32_t> ids_to_unload;
{
std::lock_guard lock(mutex_);
for (const auto& id: plugin_instances_ | std::views::keys) {
ids_to_unload.push_back(id);
}
}
for (const auto& id: ids_to_unload) {
unload_plugin(id);
}
}
plugin_instance* plugin_host_manager::load_plugin(const std::filesystem::path& plugin_binary_path) {
auto plugin_id = get_next_plugin_id();
plugin_instance* ptr = nullptr;
try {
auto instance = std::make_unique<plugin_instance>(io_context_, plugin_id, plugin_binary_path);
ptr = instance.get();
std::lock_guard lock(mutex_);
plugin_instances_.emplace(plugin_id, std::move(instance));
}
catch (const std::exception& e) {
// TODO: 如果创建失败,清理已分配的资源
spdlog::error("Failed to load plugin {}: {}", plugin_binary_path.string(), e.what());
}
return ptr;
}
void plugin_host_manager::unload_plugin(uint32_t plugin_id) {
}
void plugin_host_manager::register_session(uint32_t plugin_id, std::shared_ptr<rpc_session> session) {
}
plugin_instance* plugin_host_manager::get_plugin_instance(uint32_t plugin_id) {
std::lock_guard lock(mutex_);
const auto& it = plugin_instances_.find(plugin_id);
if (it != plugin_instances_.end()) {
return it->second.get();
}
return nullptr;
}

View File

@@ -0,0 +1,37 @@
#pragma once
#include <memory>
#include <ranges>
#include "lazy_singleton.h"
#include "plugin_instance.h"
#include "rpc/rpc_session.h"
class plugin_host_manager : public lazy_singleton<plugin_host_manager> {
public:
~plugin_host_manager();
plugin_instance* load_plugin(const std::filesystem::path& plugin_binary_path);
void unload_plugin(uint32_t plugin_id);
void register_session(uint32_t plugin_id, std::shared_ptr<rpc_session> session);
plugin_instance* get_plugin_instance(uint32_t plugin_id);
template<typename Func>
void for_each_plugin_instance(Func&& func) {
std::lock_guard lock(mutex_);
for (const auto& instance: plugin_instances_ | std::views::values) {
func(instance.get());
}
}
private:
auto get_next_plugin_id() {
return plugin_id_.fetch_add(1);
}
std::mutex mutex_;
std::unordered_map<uint32_t, std::unique_ptr<plugin_instance>> plugin_instances_;
std::atomic_uint32_t plugin_id_ = 1;
boost::asio::io_context io_context_;
rpc_server rpc_server_{ io_context_ };
};

View File

@@ -0,0 +1,64 @@
#include "plugin_instance.h"
#include <filesystem>
namespace bi = boost::interprocess;
namespace bp = boost::process;
auto execute_plugin_process(uint32_t id, boost::asio::io_context& ctx, const std::filesystem::path& plugin_path) {
if (!std::filesystem::exists(plugin_path)) {
throw std::runtime_error("Plugin path does not exist: " + plugin_path.string());
}
if (!plugin_path.has_extension()) {
throw std::runtime_error("Plugin path must have an extension: " + plugin_path.string());
}
// 启动沙箱进程
const auto& ext = plugin_path.extension();
const static std::unordered_map<std::string, std::string> supported_exts = {
{".so", "AlichoPluginHostVst2.exe"},
{".dll", "AlichoPluginHostVst2.exe"},
{".dylib", "AlichoPluginHostVst2.exe"},
{".vst2", "AlichoPluginHostVst2.exe"},
{".vst3", "AlichoPluginHostVst3.exe"},
{".clap", "AlichoPluginHostClap.exe"},
};
if (!supported_exts.contains(ext.string())) {
throw std::runtime_error("Unsupported plugin file type: " + ext.string());
}
const auto& host_executable = supported_exts.at(ext.string());
const auto& host_path = std::filesystem::current_path() / host_executable;
if (!std::filesystem::exists(host_path)) {
throw std::runtime_error("Host executable not found: " + host_path.string());
}
return new bp::process(ctx, host_path.string(), { get_shm_in_name(id), get_shm_out_name(id) });
}
plugin_instance::plugin_instance(boost::asio::io_context& ctx,
uint32_t in_id,
const std::filesystem::path& in_plugin_path) {
id = in_id;
// 创建共享内存段
input_segment = std::make_unique<bi::managed_shared_memory>(bi::open_or_create, get_shm_in_name(id).c_str(), SHM_SIZE);
output_segment = std::make_unique<bi::managed_shared_memory>(bi::open_or_create, get_shm_out_name(id).c_str(), SHM_SIZE);
// 获取锁无阻塞队列
input_queue = input_segment->find_or_construct<lock_free_queue>("input_queue")();
output_queue = output_segment->find_or_construct<lock_free_queue>("output_queue")();
process = std::shared_ptr<boost::process::process>(execute_plugin_process(id, ctx, in_plugin_path), [](boost::process::process* p) {
delete p;
});
}
plugin_instance::~plugin_instance() {
output_queue->push({});
if (input_segment) {
bi::shared_memory_object::remove(get_shm_in_name(id).c_str());
}
if (output_segment) {
bi::shared_memory_object::remove(get_shm_out_name(id).c_str());
}
}

View File

@@ -0,0 +1,32 @@
#pragma once
#include <memory>
#include <boost/process.hpp>
#include <boost/interprocess/managed_shared_memory.hpp>
#include "rpc/common.h"
class rpc_session;
struct plugin_instance {
plugin_instance(boost::asio::io_context& ctx, uint32_t in_id, const std::filesystem::path& in_plugin_path);
~plugin_instance();
uint32_t id = 0;
std::shared_ptr<boost::process::process> process; // 沙箱进程句柄
// 共享内存资源
std::unique_ptr<boost::interprocess::managed_shared_memory> input_segment;
std::unique_ptr<boost::interprocess::managed_shared_memory> output_segment;
lock_free_queue* input_queue = nullptr; // AudioEngine -> Host
lock_free_queue* output_queue = nullptr; // Host -> AudioEngine
// 控制连接
// std::shared_ptr<rpc_session> session;
// 状态标识
std::atomic_bool is_processing_done{ true }; // 插件是否处理完毕
std::atomic_bool is_registered{ false }; // RPC会话是否注册
auto is_process_running() const {
return process && process->running();
}
};

View File

@@ -0,0 +1,10 @@
#include "engine_rpc.h"
void __rpc_handler_func_PROCESS_DONE(uint64_t seq_id, const rpc::process_done& body) {
}
void __rpc_handler_func_REGISTER_HOST(uint64_t seq_id, const rpc::register_host& body) {
}

View File

@@ -0,0 +1,8 @@
#pragma once
#include "rpc/common.h"
#include "rpc/rpc_type.h"
#include "rpc/rpc_manager.h"
REGISTER_RPC_HANDLER(LOG, rpc::log)
REGISTER_RPC_HANDLER(REGISTER_HOST, rpc::register_host)
REGISTER_RPC_HANDLER(PROCESS_DONE, rpc::process_done)

View File

@@ -1,40 +0,0 @@
#pragma once
#include <array>
#include <cstddef>
#include <cstdint>
constexpr size_t AUDIO_BLOCK_SIZE = 4096; // 最大音频块大小
constexpr size_t QUEUE_CAPACITY = 4; // 音频队列容量
constexpr size_t MAX_PAYLOAD_SIZE = 246; // 最大有效载荷大小
struct audio_block {
float data[AUDIO_BLOCK_SIZE]; // 音频数据
size_t size; // 有效数据大小
};
enum class message_type : uint32_t {
// Host -> AudioEngine
REGISTER = 1, // 注册插件
PROCESS_DONE, // 处理完成
PARAMETER_VALUE_CHANGED, // 参数值改变
// AudioEngine -> Host
PROCESS_AUDIO_BLOCK = 10001, // 处理音频块
SET_PARAMETER, // 设置参数
SHUTDOWN // 关闭插件
};
// RPC 消息帧结构
struct rpc_message {
message_type type;
uint64_t seq_id; // 消息序列号, 用于跟踪请求和响应
uint32_t payload_size; // 有效载荷大小
std::array<std::byte, MAX_PAYLOAD_SIZE> payload;
};
// 根据 plugin_id 生成 IPC 资源名称
inline std::string get_uds_path() {
#if ALICHO_PLATFORM_WINDOWS
return
}

View File

@@ -0,0 +1,12 @@
#pragma once
template<typename T>
class lazy_singleton {
public:
static auto get_instance() -> T& {
static T instance;
return instance;
}
protected:
lazy_singleton() = default;
};

View File

@@ -1,4 +1,4 @@
#include "library_handle.h"
#include "library_handle/library_handle.h"
#include <windows.h>
library_handle* library_handle::create(const std::filesystem::path& in_path) {

View File

@@ -0,0 +1,34 @@
#pragma once
#include <string>
#include <boost/lockfree/spsc_queue.hpp>
constexpr size_t AUDIO_BLOCK_SIZE = 4096; // 最大音频块大小
constexpr size_t QUEUE_CAPACITY = 4; // 音频队列容量
constexpr size_t MAX_PAYLOAD_SIZE = 1024; // 最大有效载荷大小
constexpr size_t SHM_SIZE = 1024 * 1024; // 共享内存段大小
struct audio_block {
float data[AUDIO_BLOCK_SIZE * 2]; // 音频数据, 双声道
size_t size; // 有效数据大小
};
// 单生产者单消费者无锁队列
using lock_free_queue = boost::lockfree::spsc_queue<audio_block, boost::lockfree::capacity<QUEUE_CAPACITY>>;
// 根据 plugin_id 生成 IPC 资源名称
inline std::string get_uds_path() {
#if ALICHO_PLATFORM_WINDOWS
return "alicho_host.sock";
#else
return "/tmp/alicho_host"; // Linux 使用 Unix 域套接字
#endif
}
inline std::string get_shm_in_name(const uint32_t plugin_id) {
return "alicho_host_in_" + std::to_string(plugin_id);
}
inline std::string get_shm_out_name(const uint32_t plugin_id) {
return "alicho_host_out_" + std::to_string(plugin_id);
}

View File

@@ -0,0 +1,47 @@
#pragma once
#include <spdlog/spdlog.h>
#include "lazy_singleton.h"
#include "rpc_type.h"
#include "common.h"
using rpc_callback = std::function<void(uint64_t, const std::vector<std::byte>&)>;
class rpc_message_handler : public lazy_singleton<rpc_message_handler> {
public:
void register_rpc_handler(rpc::message_type type, rpc_callback handler) {
if (handlers_.contains(type))
spdlog::warn("RPC消息类型 {} 已经注册,覆盖旧处理器", static_cast<uint32_t>(type));
handlers_[type] = std::move(handler);
}
void handle_message(const rpc::rpc_header& in_header, const std::vector<std::byte>& in_payload) {
const auto& it = handlers_.find(in_header.type);
if (it != handlers_.end()) {
it->second(in_header.seq_id, in_payload);
} else {
spdlog::warn("未处理的RPC消息类型: {}", static_cast<uint32_t>(in_header.type));
}
}
private:
std::unordered_map<rpc::message_type, rpc_callback> handlers_;
};
template<typename T>
struct rpc_handler_register {
explicit rpc_handler_register(rpc::message_type in_type, const std::function<void(uint64_t, const T&)>& in_func) {
auto cast_func = [in_func](uint64_t in_seq_id, const std::vector<std::byte>& msg) {
#if ALICHO_DEBUG
assert(msg.size() == sizeof(T));
#endif
auto payload = reinterpret_cast<const T*>(msg.data());
in_func(in_seq_id, *payload);
};
rpc_message_handler::get_instance().register_rpc_handler(in_type, cast_func);
}
};
#define REGISTER_RPC_HANDLER(type, body_type) \
void __rpc_handler_func_##type(uint64_t seq_id, const body_type& body); \
static rpc_handler_register<body_type> __rpc_handler_register_##type(rpc::message_type::type, __rpc_handler_func_##type);

View File

@@ -0,0 +1,53 @@
// RPC调用消息体结构, 由AudioEngine和PluginHost之间传输
#pragma once
#include <cstdint>
#include <spdlog/spdlog.h>
namespace rpc {
enum class message_type : uint32_t {
WTF = 0, // 未知消息类型, 用于调试
// Host -> AudioEngine
LOG = 1, // 日志消息
REGISTER_HOST, // 注册插件
PROCESS_DONE, // 处理完成
PARAMETER_VALUE_CHANGED, // 参数值改变
// AudioEngine -> Host
PROCESS_AUDIO_BLOCK = 10001, // 处理音频块
SET_PARAMETER, // 设置参数
SHUTDOWN // 关闭插件
};
struct rpc_header {
message_type type; // 消息类型
uint64_t seq_id; // 消息序列号
uint32_t payload_size; // 有效载荷大小
};
}
namespace rpc {
struct log {
uint32_t id; // 插件ID
spdlog::level::level_enum level;
std::array<char, MAX_PAYLOAD_SIZE> str;
};
struct register_host {
uint32_t id;
};
struct process_done {
uint32_t id; // 插件ID
};
struct parameter_value_changed {
uint32_t id; // 插件ID
uint32_t parameter_id; // 参数ID
float value; // 新值
};
}
namespace rpc {
}

View File

@@ -0,0 +1,41 @@
#include "session.h"
#include "rpc_manager.h"
void rpc::session::start() {
do_read_header();
}
void rpc::session::stop() {
}
void rpc::session::do_read_header() {
auto self = shared_from_this();
// 读取消息到 read_queue_ 中
auto func = [self](boost::system::error_code ec, std::size_t in_size) {
if (ec)
return;
self->do_read_body();
};
boost::asio::async_read(socket_, boost::asio::buffer{read_header_, 4}, func);
}
void rpc::session::do_read_body() {
auto self = shared_from_this();
auto func = [self](boost::system::error_code ec, std::size_t in_size) {
if (ec)
return;
// 处理读取到的消息
rpc_message_handler::get_instance().handle_message(self->read_header_, self->read_body_);
};
read_body_.resize(read_header_.payload_size);
boost::asio::async_read(socket_, boost::asio::buffer(read_body_, read_header_.payload_size), func);
}
void rpc::session::do_write() {
}
void rpc::server::do_accept() {
}

View File

@@ -0,0 +1,72 @@
#pragma once
#include <deque>
#include <memory>
#include <boost/asio.hpp>
#include "common.h"
#include "rpc_type.h"
namespace rpc {
class session : public std::enable_shared_from_this<session> {
public:
explicit session(boost::asio::local::stream_protocol::socket&& in_socket)
: socket_(std::move(in_socket)) {
}
void start();
void stop();
template<typename Msg>
auto async_call(Msg&& msg) {
// 这里可以实现异步调用逻辑
// 比如将消息放入写队列,触发写操作等
return boost::asio::post(socket_.get_executor(), [this, msg = std::forward<Msg>(msg)]() mutable {
write_queue_.emplace_back(std::move(msg));
if (write_queue_.size() == 1) {
do_write();
}
});
}
private:
void do_read_header();
void do_read_body();
void do_write();
boost::asio::local::stream_protocol::socket socket_;
rpc_header read_header_;
std::vector<std::byte> read_body_;
std::deque<std::vector<std::byte>> write_queue_; // 写队列, 用于发送消息
std::atomic_uint32_t next_id_{ 1 };
};
class server : public std::enable_shared_from_this<server> {
public:
explicit server(boost::asio::io_context& io_context) : acceptor_(io_context,
boost::asio::local::stream_protocol::endpoint(get_uds_path()), false) {
}
private:
void do_accept();
boost::asio::local::stream_protocol::acceptor acceptor_;;
};
class client {
public:
explicit client(boost::asio::io_context& io_context) {
boost::asio::local::stream_protocol::socket socket_(io_context);
socket_.connect(get_uds_path());
session_ = std::make_shared<session>(std::move(socket_));
session_->start();
}
template<typename Msg>
auto async_call(Msg&& msg) {
}
private:
std::shared_ptr<session> session_;
};
}

View File

@@ -15,9 +15,12 @@ retrieve_files(${CMAKE_CURRENT_SOURCE_DIR}/src SRC_FILES)
add_executable(${PROJECT_NAME} ${SRC_FILES})
target_link_libraries(${PROJECT_NAME} PRIVATE
config_target
alicho_proto
glfw
AlichoMisc
Boost::interprocess
Boost::lockfree
Boost::asio
Boost::system
)
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src)
register_plugin_host(${PROJECT_NAME})

View File

@@ -1,37 +1,69 @@
#include "GLFW/glfw3.h"
#include <thread>
#include <boost/asio.hpp>
#include "rpc/common.h"
#include "vst2host.h"
#include "spdlog/spdlog.h"
#include "boost/asio.hpp"
#include <boost/interprocess/managed_shared_memory.hpp>
namespace bi = boost::interprocess;
int main(int argc, char *argv[])
{
if (argc != 3) {
if (argc != 3)
return 1;
std::string shm_input_path = argv[1];
std::string shm_output_path = argv[2];
boost::system::error_code ec;
boost::asio::io_context io_context;
boost::asio::local::stream_protocol::socket socket(io_context);
socket.connect(get_uds_path(), ec);
if (ec) {
spdlog::error("无法连接到插件主机: {}", ec.message());
return 1;
}
// 连接共享内存
bi::managed_shared_memory input_segment(bi::open_only, shm_input_path.c_str());
bi::managed_shared_memory output_segment(bi::open_only, shm_output_path.c_str());
// 获取锁无阻塞队列
auto input_queue = input_segment.find<lock_free_queue>("input_queue").first;
auto output_queue = output_segment.find<lock_free_queue>("output_queue").first;
if (!input_queue || !output_queue) {
spdlog::error("无法找到共享内存队列");
return 1;
}
glfwSetErrorCallback([](int error, const char* description) {
spdlog::error("GLFW Error {}: {}", error, description);
spdlog::error("GLFW 错误 {}: {}", error, description);
});
glfwInit(); // 初始化 GLFW
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); // 仅使用 GLFW 的窗口功能,不使用 OpenGL
open_editor();
while (true) {
if (is_editor_open()) {
glfwPollEvents();
idle_editor();
constexpr std::chrono::nanoseconds delta_time(std::nano::den / 320); // 240fps刷新率但是留有额外的抖动余量(防止CPU时间片分配不均)
std::this_thread::sleep_for(delta_time);
}
else {
break;
// if (is_editor_open()) {
// glfwPollEvents();
// idle_editor();
// }
// else {
// break;
// }
// 处理音频块
audio_block block;
if (input_queue->pop(block)) {
break; // 这里临时测试, 直接退出
}
constexpr std::chrono::nanoseconds delta_time(std::nano::den / 320); // 240fps刷新率但是留有额外的抖动余量(防止CPU时间片分配不均)
std::this_thread::sleep_for(delta_time);
}
unload_plugin();
glfwTerminate();
bi::shared_memory_object::remove(shm_input_path.c_str());
bi::shared_memory_object::remove(shm_output_path.c_str());
return 0;
}

View File

@@ -2,10 +2,10 @@
#include "pluginterfaces/vst2.x/aeffectx.h" // Steinberg 官方头
#include <span>
#include "library_handle.h"
#include "library_handle/library_handle.h"
#include <GLFW/glfw3.h>
#include "size_type.h"
#include "vec.h"
inline library_handle* lib_ = nullptr;

View File

@@ -13,7 +13,7 @@ retrieve_files(${CMAKE_CURRENT_SOURCE_DIR}/src SRC_FILES)
add_executable(${PROJECT_NAME} ${SRC_FILES})
target_link_libraries(${PROJECT_NAME} PRIVATE
config_target
alicho_proto
AlichoProto
gRPC::grpc++
protobuf::libprotobuf
libzmq

View File

@@ -1,13 +1,18 @@
{
"dependencies": [
"grpc",
"protobuf",
"cppzmq",
"glfw3",
"spdlog",
"boost",
"gtest"
],
"version": "0.0.1",
"name": "ninaengine"
"name" : "alicho",
"version" : "0.0.1",
"builtin-baseline" : "f33cc491c85a7d643c5ab6da1667c1458e6d7abf",
"dependencies" : [ "grpc", "protobuf", "cppzmq", "glfw3", "spdlog", "gtest", {
"name" : "boost-asio",
"version>=" : "1.88.0"
}, {
"name" : "boost-process",
"version>=" : "1.88.0"
}, {
"name" : "boost-interprocess",
"version>=" : "1.88.0"
}, {
"name" : "boost-lockfree",
"version>=" : "1.88.0"
} ]
}