From fe2de8de8de71440a08b96152b9c28555c06ad87 Mon Sep 17 00:00:00 2001 From: Robbert van der Helm Date: Thu, 17 Dec 2020 17:52:51 +0100 Subject: [PATCH] Unify handling for *::{get,set}State Since these functions are exactly the same, and for whatever reason they didn't just add them to the `IPluginBase` both `IComponent` and `IEditController`. inherit from --- src/common/logging/vst3.cpp | 57 ++++++++++--------- src/common/logging/vst3.h | 7 ++- src/common/serialization/vst3.h | 4 +- src/common/serialization/vst3/plugin-proxy.h | 52 +++++++++++++++++ .../serialization/vst3/plugin/component.h | 53 ++--------------- .../vst3/plugin/edit-controller.h | 6 ++ .../bridges/vst3-impls/plugin-proxy.cpp | 11 ++-- src/plugin/bridges/vst3-impls/plugin-proxy.h | 9 +-- src/wine-host/bridges/vst3.cpp | 45 ++++++++++----- 9 files changed, 136 insertions(+), 108 deletions(-) diff --git a/src/common/logging/vst3.cpp b/src/common/logging/vst3.cpp index a84fbd4f..3abd4cec 100644 --- a/src/common/logging/vst3.cpp +++ b/src/common/logging/vst3.cpp @@ -60,6 +60,23 @@ void Vst3Logger::log_request(bool is_host_vst, }); } +void Vst3Logger::log_request(bool is_host_vst, + const Vst3PluginProxy::SetState& request) { + log_request_base(is_host_vst, [&](auto& message) { + message << "<{IComponent,IEditController}* #" << request.instance_id + << ">::setState(state = )"; + }); +} + +void Vst3Logger::log_request(bool is_host_vst, + const Vst3PluginProxy::GetState& request) { + log_request_base(is_host_vst, [&](auto& message) { + message << "<{IComponent,IEditController}* #" << request.instance_id + << ">::getState(state = )"; + }); +} + void Vst3Logger::log_request( bool is_host_vst, const YaAudioProcessor::SetBusArrangements& request) { @@ -247,23 +264,6 @@ void Vst3Logger::log_request(bool is_host_vst, }); } -void Vst3Logger::log_request(bool is_host_vst, - const YaComponent::SetState& request) { - log_request_base(is_host_vst, [&](auto& message) { - message << "::setState(state = )"; - }); -} - -void Vst3Logger::log_request(bool is_host_vst, - const YaComponent::GetState& request) { - log_request_base(is_host_vst, [&](auto& message) { - message << "::getState(state = )"; - }); -} - void Vst3Logger::log_request(bool is_host_vst, const YaPluginBase::Initialize& request) { log_request_base(is_host_vst, [&](auto& message) { @@ -323,6 +323,18 @@ void Vst3Logger::log_response(bool is_host_vst, }); } +void Vst3Logger::log_response( + bool is_host_vst, + const Vst3PluginProxy::GetStateResponse& response) { + log_response_base(is_host_vst, [&](auto& message) { + message << response.result.string(); + if (response.result == Steinberg::kResultOk) { + message << ", "; + } + }); +} + void Vst3Logger::log_response( bool is_host_vst, const YaAudioProcessor::GetBusArrangementResponse& response) { @@ -403,17 +415,6 @@ void Vst3Logger::log_response( }); } -void Vst3Logger::log_response(bool is_host_vst, - const YaComponent::GetStateResponse& response) { - log_response_base(is_host_vst, [&](auto& message) { - message << response.result.string(); - if (response.result == Steinberg::kResultOk) { - message << ", "; - } - }); -} - void Vst3Logger::log_response(bool is_host_vst, const YaPluginFactory::ConstructArgs& args) { log_response_base(is_host_vst, [&](auto& message) { diff --git a/src/common/logging/vst3.h b/src/common/logging/vst3.h index 2e23c85b..65c3ff4a 100644 --- a/src/common/logging/vst3.h +++ b/src/common/logging/vst3.h @@ -58,6 +58,8 @@ class Vst3Logger { void log_request(bool is_host_vst, const Vst3PluginProxy::Construct&); void log_request(bool is_host_vst, const Vst3PluginProxy::Destruct&); + void log_request(bool is_host_vst, const Vst3PluginProxy::SetState&); + void log_request(bool is_host_vst, const Vst3PluginProxy::GetState&); void log_request(bool is_host_vst, const YaAudioProcessor::SetBusArrangements&); void log_request(bool is_host_vst, @@ -77,8 +79,6 @@ class Vst3Logger { void log_request(bool is_host_vst, const YaComponent::GetRoutingInfo&); void log_request(bool is_host_vst, const YaComponent::ActivateBus&); void log_request(bool is_host_vst, const YaComponent::SetActive&); - void log_request(bool is_host_vst, const YaComponent::SetState&); - void log_request(bool is_host_vst, const YaComponent::GetState&); void log_request(bool is_host_vst, const YaPluginBase::Initialize&); void log_request(bool is_host_vst, const YaPluginBase::Terminate&); void log_request(bool is_host_vst, const YaPluginFactory::Construct&); @@ -89,6 +89,8 @@ class Vst3Logger { void log_response( bool is_host_vst, const std::variant&); + void log_response(bool is_host_vst, + const Vst3PluginProxy::GetStateResponse&); void log_response(bool is_host_vst, const YaAudioProcessor::GetBusArrangementResponse&); void log_response(bool is_host_vst, @@ -96,7 +98,6 @@ class Vst3Logger { void log_response(bool is_host_vst, const YaComponent::GetBusInfoResponse&); void log_response(bool is_host_vst, const YaComponent::GetRoutingInfoResponse&); - void log_response(bool is_host_vst, const YaComponent::GetStateResponse&); void log_response(bool is_host_vst, const YaPluginFactory::ConstructArgs&); void log_response(bool is_host_vst, const Configuration&); diff --git a/src/common/serialization/vst3.h b/src/common/serialization/vst3.h index df052f14..5cb7549f 100644 --- a/src/common/serialization/vst3.h +++ b/src/common/serialization/vst3.h @@ -59,6 +59,8 @@ struct WantsConfiguration { */ using ControlRequest = std::variant + void serialize(S& s) { + s.value8b(instance_id); + s.object(state); + } + }; + + /** + * The response code and written state for a call to + * `{IComponent,IEditController}::getState(state)`. + */ + struct GetStateResponse { + UniversalTResult result; + VectorStream updated_state; + + template + void serialize(S& s) { + s.object(result); + s.object(updated_state); + } + }; + + /** + * Message to pass through a call to + * `{IComponent,IEditController}::getState(state)` to the Wine plugin host. + */ + struct GetState { + using Response = GetStateResponse; + + native_size_t instance_id; + + template + void serialize(S& s) { + s.value8b(instance_id); + } + }; + protected: ConstructArgs arguments; }; diff --git a/src/common/serialization/vst3/plugin/component.h b/src/common/serialization/vst3/plugin/component.h index 6fb190bd..60b73b7a 100644 --- a/src/common/serialization/vst3/plugin/component.h +++ b/src/common/serialization/vst3/plugin/component.h @@ -255,57 +255,12 @@ class YaComponent : public Steinberg::Vst::IComponent { virtual tresult PLUGIN_API setActive(TBool state) override = 0; - /** - * Message to pass through a call to `IComponent::setState(state)` to the - * Wine plugin host. - */ - struct SetState { - using Response = UniversalTResult; - - native_size_t instance_id; - - VectorStream state; - - template - void serialize(S& s) { - s.value8b(instance_id); - s.object(state); - } - }; - + // `setState()` and `getState()` are defiend in both `IComponent` and + // `IEditController`. Since an object can only ever implement one or the + // other, the messages for calling either are defined directly on + // `Vst3PluginProxy`. virtual tresult PLUGIN_API setState(Steinberg::IBStream* state) override = 0; - - /** - * The response code and written state for a call to - * `IComponent::getState(state)`. - */ - struct GetStateResponse { - UniversalTResult result; - VectorStream updated_state; - - template - void serialize(S& s) { - s.object(result); - s.object(updated_state); - } - }; - - /** - * Message to pass through a call to `IComponent::getState(state)` to the - * Wine plugin host. - */ - struct GetState { - using Response = GetStateResponse; - - native_size_t instance_id; - - template - void serialize(S& s) { - s.value8b(instance_id); - } - }; - virtual tresult PLUGIN_API getState(Steinberg::IBStream* state) override = 0; diff --git a/src/common/serialization/vst3/plugin/edit-controller.h b/src/common/serialization/vst3/plugin/edit-controller.h index 2a9e42d9..df549cf7 100644 --- a/src/common/serialization/vst3/plugin/edit-controller.h +++ b/src/common/serialization/vst3/plugin/edit-controller.h @@ -80,10 +80,16 @@ class YaEditController2 : public Steinberg::Vst::IEditController, virtual tresult PLUGIN_API setComponentState(Steinberg::IBStream* state) override = 0; + + // `setState()` and `getState()` are defiend in both `IComponent` and + // `IEditController`. Since an object can only ever implement one or the + // other, the messages for calling either are defined directly on + // `Vst3PluginProxy`. virtual tresult PLUGIN_API setState(Steinberg::IBStream* state) override = 0; virtual tresult PLUGIN_API getState(Steinberg::IBStream* state) override = 0; + virtual int32 PLUGIN_API getParameterCount() override = 0; virtual tresult PLUGIN_API getParameterInfo(int32 paramIndex, diff --git a/src/plugin/bridges/vst3-impls/plugin-proxy.cpp b/src/plugin/bridges/vst3-impls/plugin-proxy.cpp index 7a36cee6..00c7944d 100644 --- a/src/plugin/bridges/vst3-impls/plugin-proxy.cpp +++ b/src/plugin/bridges/vst3-impls/plugin-proxy.cpp @@ -171,22 +171,23 @@ tresult PLUGIN_API Vst3PluginProxyImpl::setActive(TBool state) { } tresult PLUGIN_API Vst3PluginProxyImpl::setState(Steinberg::IBStream* state) { - return bridge.send_message(YaComponent::SetState{ + // Since both interfaces contain this function, this is used for both + // `IComponent::setState()` as well as `IEditController::setState()` + return bridge.send_message(Vst3PluginProxy::SetState{ .instance_id = arguments.instance_id, .state = state}); } tresult PLUGIN_API Vst3PluginProxyImpl::getState(Steinberg::IBStream* state) { + // Since both interfaces contain this function, this is used for both + // `IComponent::getState()` as well as `IEditController::getState()` const GetStateResponse response = bridge.send_message( - YaComponent::GetState{.instance_id = arguments.instance_id}); + Vst3PluginProxy::GetState{.instance_id = arguments.instance_id}); assert(response.updated_state.write_back(state) == Steinberg::kResultOk); return response.result; } -// FIXME: Fix `{set,get}State()` for `IEditController` as mentioned in the -// header - tresult PLUGIN_API Vst3PluginProxyImpl::setComponentState(Steinberg::IBStream* state) { // TODO: Implement diff --git a/src/plugin/bridges/vst3-impls/plugin-proxy.h b/src/plugin/bridges/vst3-impls/plugin-proxy.h index a8df71c6..964460c8 100644 --- a/src/plugin/bridges/vst3-impls/plugin-proxy.h +++ b/src/plugin/bridges/vst3-impls/plugin-proxy.h @@ -81,12 +81,9 @@ class Vst3PluginProxyImpl : public Vst3PluginProxy { // From `IEditController` tresult PLUGIN_API setComponentState(Steinberg::IBStream* state) override; - // FIXME: These are duplicate, we need to change the implementation to call - // this on either `object_instances[instance_id].component` or - // `object_instances[instance_id].edit_controller` depending on which - // one exists. - // tresult PLUGIN_API setState(Steinberg::IBStream* state) override; - // tresult PLUGIN_API getState(Steinberg::IBStream* state) override; + // `IEditController` also contains `getState()` and `setState()` functions. + // These are identical to those defiend in `IComponent` and they're thus + // handled in in the same function. int32 PLUGIN_API getParameterCount() override; tresult PLUGIN_API getParameterInfo(int32 paramIndex, diff --git a/src/wine-host/bridges/vst3.cpp b/src/wine-host/bridges/vst3.cpp index ec3967c2..a65784f7 100644 --- a/src/wine-host/bridges/vst3.cpp +++ b/src/wine-host/bridges/vst3.cpp @@ -106,6 +106,36 @@ void Vst3Bridge::run() { return Ack{}; }, + [&](Vst3PluginProxy::SetState& request) + -> Vst3PluginProxy::SetState::Response { + // This same function is defined in both `IComponent` and + // `IEditController`, so the host is calling one or the other + if (object_instances[request.instance_id].component) { + return object_instances[request.instance_id] + .component->setState(&request.state); + } else { + return object_instances[request.instance_id] + .edit_controller->setState(&request.state); + } + }, + [&](Vst3PluginProxy::GetState& request) + -> Vst3PluginProxy::GetState::Response { + VectorStream stream; + tresult result; + + // This same function is defined in both `IComponent` and + // `IEditController`, so the host is calling one or the other + if (object_instances[request.instance_id].component) { + result = object_instances[request.instance_id] + .component->getState(&stream); + } else { + result = object_instances[request.instance_id] + .edit_controller->getState(&stream); + } + + return Vst3PluginProxy::GetStateResponse{ + .result = result, .updated_state = std::move(stream)}; + }, [&](YaAudioProcessor::SetBusArrangements& request) -> YaAudioProcessor::SetBusArrangements::Response { return object_instances[request.instance_id] @@ -201,21 +231,6 @@ void Vst3Bridge::run() { return object_instances[request.instance_id] .component->setActive(request.state); }, - [&](YaComponent::SetState& request) - -> YaComponent::SetState::Response { - return object_instances[request.instance_id] - .component->setState(&request.state); - }, - [&](YaComponent::GetState& request) - -> YaComponent::GetState::Response { - VectorStream stream; - const tresult result = - object_instances[request.instance_id].component->getState( - &stream); - - return YaComponent::GetStateResponse{ - .result = result, .updated_state = std::move(stream)}; - }, [&](YaPluginBase::Initialize& request) -> YaPluginBase::Initialize::Response { // If we got passed a host context, we'll create a proxy object