From 699ddfd2ea7b4ec7896481e6df15218c6166e31b Mon Sep 17 00:00:00 2001 From: Robbert van der Helm Date: Fri, 11 Dec 2020 22:59:32 +0100 Subject: [PATCH] Implement YaComponentPluginImpl destructor When the object gets dropped through the reference counting system, the object should also be dropped in the Wine plugin host. --- src/common/logging/vst3.cpp | 12 ++++++++++++ src/common/logging/vst3.h | 2 ++ src/common/serialization/vst3.h | 3 ++- src/common/serialization/vst3/base.h | 9 +++++++++ src/common/serialization/vst3/component.h | 21 +++++++++++++++++---- src/plugin/bridges/vst3-impls/component.cpp | 3 ++- src/wine-host/bridges/vst3.cpp | 7 +++++++ 7 files changed, 51 insertions(+), 6 deletions(-) diff --git a/src/common/logging/vst3.cpp b/src/common/logging/vst3.cpp index 61c67816..7807a23c 100644 --- a/src/common/logging/vst3.cpp +++ b/src/common/logging/vst3.cpp @@ -30,6 +30,14 @@ void Vst3Logger::log_request(bool is_host_vst, const YaComponent::Create&) { }); } +void Vst3Logger::log_request(bool is_host_vst, + const YaComponent::Destroy& request) { + log_request_base(is_host_vst, [&](auto& message) { + message << "::~IPluginFactory()"; + }); +} + void Vst3Logger::log_request(bool is_host_vst, const WantsConfiguration&) { log_request_base(is_host_vst, [](auto& message) { message << "Requesting "; @@ -42,6 +50,10 @@ void Vst3Logger::log_request(bool is_host_vst, const WantsPluginFactory&) { }); } +void Vst3Logger::log_response(bool is_host_vst, const Ack&) { + log_response_base(is_host_vst, [&](auto& message) { message << "ACK"; }); +} + void Vst3Logger::log_response( bool is_host_vst, const std::optional& args) { diff --git a/src/common/logging/vst3.h b/src/common/logging/vst3.h index 78b69176..66a0a14f 100644 --- a/src/common/logging/vst3.h +++ b/src/common/logging/vst3.h @@ -48,9 +48,11 @@ class Vst3Logger { // (what we'll call a control message). void log_request(bool is_host_vst, const YaComponent::Create&); + void log_request(bool is_host_vst, const YaComponent::Destroy&); void log_request(bool is_host_vst, const WantsConfiguration&); void log_request(bool is_host_vst, const WantsPluginFactory&); + void log_response(bool is_host_vst, const Ack&); void log_response(bool is_host_vst, const std::optional&); void log_response(bool is_host_vst, const Configuration&); diff --git a/src/common/serialization/vst3.h b/src/common/serialization/vst3.h index 74157ec9..f037a44c 100644 --- a/src/common/serialization/vst3.h +++ b/src/common/serialization/vst3.h @@ -68,7 +68,8 @@ struct WantsPluginFactory { * encodes the information we request or the operation we want to perform. A * request of type `ControlRequest(T)` should send back a `T::Response`. */ -using ControlRequest = std::variant; +using ControlRequest = + std::variant; template void serialize(S& s, ControlRequest& payload) { diff --git a/src/common/serialization/vst3/base.h b/src/common/serialization/vst3/base.h index e4836118..c9d8a591 100644 --- a/src/common/serialization/vst3/base.h +++ b/src/common/serialization/vst3/base.h @@ -34,3 +34,12 @@ using Steinberg::TBool, Steinberg::int8, Steinberg::int32, Steinberg::tresult; using ArrayUID = std::array< std::remove_reference_t()[0])>, std::extent_v>; + +/** + * Empty struct for when we have send a response to some operation without any + * result values. + */ +struct Ack { + template + void serialize(S&) {} +}; diff --git a/src/common/serialization/vst3/component.h b/src/common/serialization/vst3/component.h index f1fb4802..c31932de 100644 --- a/src/common/serialization/vst3/component.h +++ b/src/common/serialization/vst3/component.h @@ -93,6 +93,22 @@ class YaComponent : public Steinberg::Vst::IComponent { } }; + /** + * Message to request the Wine plugin host to destroy the IComponent + * instance with the given instance ID. Sent from the destructor of + * `YaComponentPluginImpl`. + */ + struct Destroy { + using Response = Ack; + + native_size_t instance_id; + + template + void serialize(S& s) { + s.value8b(instance_id); + } + }; + /** * Instantiate this instance with arguments read from another interface * implementation. @@ -136,11 +152,8 @@ class YaComponent : public Steinberg::Vst::IComponent { virtual tresult PLUGIN_API getState(Steinberg::IBStream* state) override = 0; - private: + protected: CreateArgs arguments; - - // TODO: As explained in a few other places, `YaComponent` objects should be - // assigned a unique ID for identification }; template diff --git a/src/plugin/bridges/vst3-impls/component.cpp b/src/plugin/bridges/vst3-impls/component.cpp index 52ff91ad..3b4062fb 100644 --- a/src/plugin/bridges/vst3-impls/component.cpp +++ b/src/plugin/bridges/vst3-impls/component.cpp @@ -21,7 +21,8 @@ YaComponentPluginImpl::YaComponentPluginImpl(Vst3PluginBridge& bridge, : YaComponent(std::move(args)), bridge(bridge) {} YaComponentPluginImpl::~YaComponentPluginImpl() { - // TODO: Send a control message to destroy the instance on the Wine side + bridge.send_message( + YaComponent::Destroy{.instance_id = arguments.instance_id}); } tresult PLUGIN_API diff --git a/src/wine-host/bridges/vst3.cpp b/src/wine-host/bridges/vst3.cpp index 1fc887e4..dd34e711 100644 --- a/src/wine-host/bridges/vst3.cpp +++ b/src/wine-host/bridges/vst3.cpp @@ -70,6 +70,13 @@ void Vst3Bridge::run() { return std::nullopt; } }, + [&](const YaComponent::Destroy& request) + -> YaComponent::Destroy::Response { + std::lock_guard lock(component_instances_mutex); + component_instances.erase(request.instance_id); + + return Ack{}; + }, [&](const WantsPluginFactory&) -> WantsPluginFactory::Response { return *plugin_factory; }});