From 63ae5f330c51f8760ff9bea44a6ebc5fd23d64ee Mon Sep 17 00:00:00 2001 From: Robbert van der Helm Date: Sat, 19 Dec 2020 18:28:16 +0100 Subject: [PATCH] Don't cache IHostApplication::getName() As it turns out there are only two or three functions where we can do this. It also breaks logging, and this function will probably only be called once anyways. More consistency is always better. --- src/common/logging/vst3.cpp | 25 ++++++++++ src/common/logging/vst3.h | 4 ++ src/common/serialization/vst3.h | 3 +- .../vst3/host-context/host-application.cpp | 30 +---------- .../vst3/host-context/host-application.h | 50 +++++++++++++++---- .../bridges/vst3-impls/plugin-factory.cpp | 4 ++ .../bridges/vst3-impls/plugin-factory.h | 5 ++ .../bridges/vst3-impls/plugin-proxy.cpp | 4 ++ src/plugin/bridges/vst3-impls/plugin-proxy.h | 5 ++ src/plugin/bridges/vst3.cpp | 18 +++++++ src/plugin/bridges/vst3.h | 5 +- .../bridges/vst3-impls/host-context-proxy.cpp | 11 ++++ .../bridges/vst3-impls/host-context-proxy.h | 1 + 13 files changed, 124 insertions(+), 41 deletions(-) diff --git a/src/common/logging/vst3.cpp b/src/common/logging/vst3.cpp index 9de2ee99..50f3da77 100644 --- a/src/common/logging/vst3.cpp +++ b/src/common/logging/vst3.cpp @@ -487,6 +487,19 @@ bool Vst3Logger::log_request( }); } +bool Vst3Logger::log_request(bool is_host_vst, + const YaHostApplication::GetName& request) { + return log_request_base(is_host_vst, [&](auto& message) { + // This can be called either from a plugin object or from the plugin's + // plugin factory + if (request.owner_instance_id) { + message << *request.owner_instance_id << ": "; + } + + message << "IHostApplication::getName(&name)"; + }); +} + void Vst3Logger::log_response(bool is_host_vst, const Ack&) { log_response_base(is_host_vst, [&](auto& message) { message << "ACK"; }); } @@ -644,3 +657,15 @@ void Vst3Logger::log_response(bool is_host_vst, const Configuration&) { log_response_base(is_host_vst, [&](auto& message) { message << ""; }); } + +void Vst3Logger::log_response( + bool is_host_vst, + const YaHostApplication::GetNameResponse& response) { + log_response_base(is_host_vst, [&](auto& message) { + message << response.result.string(); + if (response.result == Steinberg::kResultOk) { + std::string value = VST3::StringConvert::convert(response.name); + message << ", \"" << value << "\""; + } + }); +} diff --git a/src/common/logging/vst3.h b/src/common/logging/vst3.h index 42639df4..ee7e2544 100644 --- a/src/common/logging/vst3.h +++ b/src/common/logging/vst3.h @@ -115,6 +115,7 @@ class Vst3Logger { bool log_request(bool is_host_vst, const YaComponentHandler::EndEdit&); bool log_request(bool is_host_vst, const YaComponentHandler::RestartComponent&); + bool log_request(bool is_host_vst, const YaHostApplication::GetName&); void log_response(bool is_host_vst, const Ack&); void log_response( @@ -138,6 +139,9 @@ class Vst3Logger { void log_response(bool is_host_vst, const YaPluginFactory::ConstructArgs&); void log_response(bool is_host_vst, const Configuration&); + void log_response(bool is_host_vst, + const YaHostApplication::GetNameResponse&); + template void log_response(bool is_host_vst, const PrimitiveWrapper& value) { // For logging all primitive return values other than `tresult` diff --git a/src/common/serialization/vst3.h b/src/common/serialization/vst3.h index f8e33ae6..955b2c6e 100644 --- a/src/common/serialization/vst3.h +++ b/src/common/serialization/vst3.h @@ -110,7 +110,8 @@ using CallbackRequest = std::variant; + YaComponentHandler::RestartComponent, + YaHostApplication::GetName>; template void serialize(S& s, CallbackRequest& payload) { diff --git a/src/common/serialization/vst3/host-context/host-application.cpp b/src/common/serialization/vst3/host-context/host-application.cpp index 9072a9ab..46c12993 100644 --- a/src/common/serialization/vst3/host-context/host-application.cpp +++ b/src/common/serialization/vst3/host-context/host-application.cpp @@ -20,34 +20,8 @@ YaHostApplication::ConstructArgs::ConstructArgs() {} YaHostApplication::ConstructArgs::ConstructArgs( Steinberg::IPtr object) - : supported(false) { - if (auto host_application = - Steinberg::FUnknownPtr(object)) { - supported = true; - - // `IHostApplication::getName` - Steinberg::Vst::String128 name_array; - if (host_application->getName(name_array) == Steinberg::kResultOk) { - name = tchar_pointer_to_u16string(name_array); - } - } -} + : supported( + Steinberg::FUnknownPtr(object)) {} YaHostApplication::YaHostApplication(const ConstructArgs&& args) : arguments(std::move(args)) {} - -tresult PLUGIN_API YaHostApplication::getName(Steinberg::Vst::String128 name) { - // TODO: This is now not being logged at all. It's probably better if we - // just drop these two functions that output cached data directly. - // They'll only be used once or twice anyways. - if (arguments.name) { - // Terminate with a null byte. There are no nice functions for copying - // UTF-16 strings (because who would use those?). - std::copy(arguments.name->begin(), arguments.name->end(), name); - name[arguments.name->size()] = 0; - - return Steinberg::kResultOk; - } else { - return Steinberg::kNotImplemented; - } -} diff --git a/src/common/serialization/vst3/host-context/host-application.h b/src/common/serialization/vst3/host-context/host-application.h index 7dc449a5..5b63dea4 100644 --- a/src/common/serialization/vst3/host-context/host-application.h +++ b/src/common/serialization/vst3/host-context/host-application.h @@ -51,18 +51,9 @@ class YaHostApplication : public Steinberg::Vst::IHostApplication { */ bool supported; - /** - * For `IHostApplication::getName`. - */ - std::optional name; - template void serialize(S& s) { s.value1b(supported); - s.ext(name, bitsery::ext::StdOptional{}, - [](S& s, std::u16string& name) { - s.text2b(name, std::extent_v); - }); } }; @@ -74,7 +65,46 @@ class YaHostApplication : public Steinberg::Vst::IHostApplication { inline bool supported() const { return arguments.supported; } - tresult PLUGIN_API getName(Steinberg::Vst::String128 name) override; + /** + * The response code and resulting value for a call to + * `IHostApplication::getName()`. + */ + struct GetNameResponse { + UniversalTResult result; + std::u16string name; + + template + void serialize(S& s) { + s.object(result); + s.text2b(name, std::extent_v); + } + }; + + /** + * Message to pass through a call to `IHostApplication::getName()` to the + * host context provided by the host. + */ + struct GetName { + using Response = GetNameResponse; + + /** + * The object instance whose host context to call this function to. Of + * empty, then the function will be called on the factory's host context + * instead. + */ + std::optional owner_instance_id; + + template + void serialize(S& s) { + s.ext(owner_instance_id, bitsery::ext::StdOptional{}, + [](S& s, native_size_t& instance_id) { + s.value8b(instance_id); + }); + } + }; + + virtual tresult PLUGIN_API + getName(Steinberg::Vst::String128 name) override = 0; virtual tresult PLUGIN_API createInstance(Steinberg::TUID cid, Steinberg::TUID _iid, void** obj) override = 0; diff --git a/src/plugin/bridges/vst3-impls/plugin-factory.cpp b/src/plugin/bridges/vst3-impls/plugin-factory.cpp index 64fa6c13..988bf06a 100644 --- a/src/plugin/bridges/vst3-impls/plugin-factory.cpp +++ b/src/plugin/bridges/vst3-impls/plugin-factory.cpp @@ -106,6 +106,10 @@ YaPluginFactoryImpl::setHostContext(Steinberg::FUnknown* context) { // context. host_context = context; + // Automatically converted smart pointers for when the plugin performs a + // callback later + host_application = host_context; + std::optional host_context_args{}; if (host_context) { host_context_args = diff --git a/src/plugin/bridges/vst3-impls/plugin-factory.h b/src/plugin/bridges/vst3-impls/plugin-factory.h index 2e6ecc19..3e2d93a6 100644 --- a/src/plugin/bridges/vst3-impls/plugin-factory.h +++ b/src/plugin/bridges/vst3-impls/plugin-factory.h @@ -28,6 +28,11 @@ class YaPluginFactoryImpl : public YaPluginFactory { void** obj) override; tresult PLUGIN_API setHostContext(Steinberg::FUnknown* context) override; + // The following pointers are cast from `host_context` if `setHostContext()` + // has been called + + Steinberg::FUnknownPtr host_application; + private: Vst3PluginBridge& bridge; diff --git a/src/plugin/bridges/vst3-impls/plugin-proxy.cpp b/src/plugin/bridges/vst3-impls/plugin-proxy.cpp index 3ab12494..cabe7b61 100644 --- a/src/plugin/bridges/vst3-impls/plugin-proxy.cpp +++ b/src/plugin/bridges/vst3-impls/plugin-proxy.cpp @@ -323,6 +323,10 @@ tresult PLUGIN_API Vst3PluginProxyImpl::setComponentHandler( // this component handler component_handler = handler; + // Automatically converted smart pointers for when the plugin performs a + // callback later + host_application = host_context; + std::optional component_handler_proxy_args = std::nullopt; if (handler) { diff --git a/src/plugin/bridges/vst3-impls/plugin-proxy.h b/src/plugin/bridges/vst3-impls/plugin-proxy.h index 15e1ee37..e406f968 100644 --- a/src/plugin/bridges/vst3-impls/plugin-proxy.h +++ b/src/plugin/bridges/vst3-impls/plugin-proxy.h @@ -130,6 +130,11 @@ class Vst3PluginProxyImpl : public Vst3PluginProxy { */ Steinberg::IPtr component_handler; + // The following pointers are cast from `host_context` if `setHostContext()` + // has been called + + Steinberg::FUnknownPtr host_application; + private: Vst3PluginBridge& bridge; diff --git a/src/plugin/bridges/vst3.cpp b/src/plugin/bridges/vst3.cpp index 35811bfc..681d6bd3 100644 --- a/src/plugin/bridges/vst3.cpp +++ b/src/plugin/bridges/vst3.cpp @@ -83,6 +83,24 @@ Vst3PluginBridge::Vst3PluginBridge() [&](const WantsConfiguration&) -> WantsConfiguration::Response { return config; }, + [&](const YaHostApplication::GetName& request) + -> YaHostApplication::GetName::Response { + tresult result; + Steinberg::Vst::String128 name{0}; + if (request.owner_instance_id) { + result = plugin_proxies.at(*request.owner_instance_id) + .get() + .host_application->getName(name); + } else { + result = + plugin_factory->host_application->getName(name); + } + + return YaHostApplication::GetNameResponse{ + .result = result, + .name = tchar_pointer_to_u16string(name), + }; + }, [&](const YaComponentHandler::BeginEdit& request) -> YaComponentHandler::BeginEdit::Response { return plugin_proxies.at(request.owner_instance_id) diff --git a/src/plugin/bridges/vst3.h b/src/plugin/bridges/vst3.h index c0ad49e7..613b89f1 100644 --- a/src/plugin/bridges/vst3.h +++ b/src/plugin/bridges/vst3.h @@ -23,8 +23,9 @@ #include "../../common/logging/vst3.h" #include "common.h" -// Forward declaration +// Forward declarations class Vst3PluginProxyImpl; +class YaPluginFactoryImpl; /** * This handles the communication between the native host and a VST3 plugin @@ -134,7 +135,7 @@ class Vst3PluginBridge : PluginBridge> { * * @related get_plugin_factory */ - YaPluginFactory* plugin_factory = nullptr; + YaPluginFactoryImpl* plugin_factory = nullptr; private: /** diff --git a/src/wine-host/bridges/vst3-impls/host-context-proxy.cpp b/src/wine-host/bridges/vst3-impls/host-context-proxy.cpp index 937b0546..c3661e16 100644 --- a/src/wine-host/bridges/vst3-impls/host-context-proxy.cpp +++ b/src/wine-host/bridges/vst3-impls/host-context-proxy.cpp @@ -42,6 +42,17 @@ Vst3HostContextProxyImpl::queryInterface(const Steinberg::TUID _iid, return result; } +tresult PLUGIN_API +Vst3HostContextProxyImpl::getName(Steinberg::Vst::String128 name) { + const GetNameResponse response = bridge.send_message( + YaHostApplication::GetName{.owner_instance_id = owner_instance_id()}); + + std::copy(response.name.begin(), response.name.end(), name); + name[response.name.size()] = 0; + + return response.result; +} + tresult PLUGIN_API Vst3HostContextProxyImpl::createInstance(Steinberg::TUID cid, Steinberg::TUID _iid, diff --git a/src/wine-host/bridges/vst3-impls/host-context-proxy.h b/src/wine-host/bridges/vst3-impls/host-context-proxy.h index fe6d59a4..85ca3476 100644 --- a/src/wine-host/bridges/vst3-impls/host-context-proxy.h +++ b/src/wine-host/bridges/vst3-impls/host-context-proxy.h @@ -31,6 +31,7 @@ class Vst3HostContextProxyImpl : public Vst3HostContextProxy { void** obj) override; // From `IHostApplication` + tresult PLUGIN_API getName(Steinberg::Vst::String128 name) override; tresult PLUGIN_API createInstance(Steinberg::TUID cid, Steinberg::TUID _iid, void** obj) override;