diff --git a/src/common/logging/vst3.cpp b/src/common/logging/vst3.cpp index bd3dcd6d..43ee3330 100644 --- a/src/common/logging/vst3.cpp +++ b/src/common/logging/vst3.cpp @@ -52,6 +52,19 @@ void Vst3Logger::log_request(bool is_host_vst, }); } +void Vst3Logger::log_request(bool is_host_vst, + const YaComponent::Initialize& request) { + log_request_base(is_host_vst, [&](auto& message) { + message << "::initialize("; + if (request.host_application_context_args) { + message << "IHostApplication*"; + } else { + message << "nullptr"; + } + message << ")"; + }); +} + void Vst3Logger::log_request(bool is_host_vst, const YaComponent::Terminate& request) { log_request_base(is_host_vst, [&](auto& message) { diff --git a/src/common/logging/vst3.h b/src/common/logging/vst3.h index 326704ff..324186bf 100644 --- a/src/common/logging/vst3.h +++ b/src/common/logging/vst3.h @@ -58,6 +58,7 @@ class Vst3Logger { void log_request(bool is_host_vst, const YaComponent::Construct&); void log_request(bool is_host_vst, const YaComponent::Destruct&); + void log_request(bool is_host_vst, const YaComponent::Initialize&); void log_request(bool is_host_vst, const YaComponent::Terminate&); void log_request(bool is_host_vst, const YaPluginFactory::Construct&); void log_request(bool is_host_vst, const WantsConfiguration&); diff --git a/src/common/serialization/vst3.h b/src/common/serialization/vst3.h index 06c43977..449547b8 100644 --- a/src/common/serialization/vst3.h +++ b/src/common/serialization/vst3.h @@ -59,6 +59,7 @@ struct WantsConfiguration { */ using ControlRequest = std::variant; diff --git a/src/common/serialization/vst3/component.h b/src/common/serialization/vst3/component.h index 6068aaca..b370be25 100644 --- a/src/common/serialization/vst3/component.h +++ b/src/common/serialization/vst3/component.h @@ -27,6 +27,7 @@ #include "../common.h" #include "base.h" +#include "host-application.h" #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wnon-virtual-dtor" @@ -125,6 +126,29 @@ class YaComponent : public Steinberg::Vst::IComponent { DECLARE_FUNKNOWN_METHODS // From `IPluginBase` + + /** + * Message to pass through a call to `IPluginBase::initialize()` to the Wine + * plugin host. if we pass an `IHostApplication` instance, then a proxy + * `YaHostApplication` should be created and passed as an argument to + * `IPluginBase::initialize()`. If this is absent a null pointer should be + * passed. The lifetime of this `YaHostApplication` object should be bound + * to the `IComponent` we are proxying. + */ + struct Initialize { + using Response = UniversalTResult; + + native_size_t instance_id; + std::optional + host_application_context_args; + + template + void serialize(S& s) { + s.value8b(instance_id); + s.ext(host_application_context_args, bitsery::ext::StdOptional{}); + } + }; + virtual tresult PLUGIN_API initialize(FUnknown* context) override = 0; /** diff --git a/src/common/serialization/vst3/host-application.h b/src/common/serialization/vst3/host-application.h index 0589feee..9f2e989a 100644 --- a/src/common/serialization/vst3/host-application.h +++ b/src/common/serialization/vst3/host-application.h @@ -68,7 +68,7 @@ class YaHostApplication : public Steinberg::Vst::IHostApplication { void serialize(S& s) { s.value8b(component_instance_id); s.ext(name, bitsery::ext::StdOptional{}, - [](S& s, std::string& name) { + [](S& s, std::u16string& name) { s.text2b(name, std::extent_v); }); } @@ -78,9 +78,9 @@ class YaHostApplication : public Steinberg::Vst::IHostApplication { * Instantiate this instance with arguments read from an actual host * context. * - * @note Since this is passed as part of ``IPluginBase::intialize()` and - * `IPluginFactory3::setHostContext()``, there are no direct `Construct` - * or `Destruct` messages. This object's lifetime is bound to that of the + * @note Since this is passed as part of `IPluginBase::intialize()` and + * `IPluginFactory3::setHostContext()`, there are no direct `Construct` or + * `Destruct` messages. This object's lifetime is bound to that of the * objects they are passed to. If those objects get dropped, then the host * contexts should also be dropped. * diff --git a/src/plugin/bridges/vst3-impls/component.cpp b/src/plugin/bridges/vst3-impls/component.cpp index e3bbe257..ba6dfee3 100644 --- a/src/plugin/bridges/vst3-impls/component.cpp +++ b/src/plugin/bridges/vst3-impls/component.cpp @@ -45,18 +45,24 @@ tresult PLUGIN_API YaComponentPluginImpl::initialize(FUnknown* context) { // side. Otherwise we'll still call `IPluginBase::initialize()` but with a // null pointer instead. host_application_context = context; + + std::optional + host_application_context_args = std::nullopt; if (host_application_context) { - // TODO: Init with `YaHostApplication` + host_application_context_args = YaHostApplication::ConstructArgs( + host_application_context, arguments.instance_id); } else { bridge.logger.log_unknown_interface( "In IPluginBase::initialize()", context ? std::optional(context->iid) : std::nullopt); - - // TODO: Init with null pointer } - // TODO: Implement - return Steinberg::kNotImplemented; + return bridge + .send_message(YaComponent::Initialize{ + .instance_id = arguments.instance_id, + .host_application_context_args = + std::move(host_application_context_args)}) + .native(); } tresult PLUGIN_API YaComponentPluginImpl::terminate() { diff --git a/src/wine-host/bridges/vst3.cpp b/src/wine-host/bridges/vst3.cpp index 02ed53fd..ffd0e29d 100644 --- a/src/wine-host/bridges/vst3.cpp +++ b/src/wine-host/bridges/vst3.cpp @@ -72,6 +72,14 @@ void Vst3Bridge::run() { return Ack{}; }, + [&](const YaComponent::Initialize& request) + -> YaComponent::Initialize::Response { + // TODO: If `request.host_context_args` has a value, we should + // initialize a proxy object and pass a pointer to that + // instead + return component_instances[request.instance_id]->initialize( + nullptr); + }, [&](const YaComponent::Terminate& request) -> YaComponent::Terminate::Response { return component_instances[request.instance_id]->terminate();