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;