diff --git a/meson.build b/meson.build index 86ea1751..b4c42e78 100644 --- a/meson.build +++ b/meson.build @@ -158,6 +158,7 @@ if with_vst3 'src/common/serialization/vst3/plugin-factory.cpp', 'src/common/serialization/vst3/process-data.cpp', 'src/wine-host/bridges/vst3-impls/component-handler-proxy.cpp', + 'src/wine-host/bridges/vst3-impls/connection-point-proxy.cpp', 'src/wine-host/bridges/vst3-impls/host-context-proxy.cpp', 'src/wine-host/bridges/vst3-impls/plug-frame-proxy.cpp', 'src/wine-host/bridges/vst3.cpp', diff --git a/src/common/serialization/vst3.h b/src/common/serialization/vst3.h index 08853061..61d93ab3 100644 --- a/src/common/serialization/vst3.h +++ b/src/common/serialization/vst3.h @@ -24,6 +24,7 @@ #include "../utils.h" #include "common.h" #include "vst3/component-handler-proxy.h" +#include "vst3/connection-point-proxy.h" #include "vst3/host-context-proxy.h" #include "vst3/plug-frame-proxy.h" #include "vst3/plug-view-proxy.h" @@ -143,6 +144,11 @@ using CallbackRequest = std::variant; diff --git a/src/plugin/bridges/vst3-impls/plugin-proxy.h b/src/plugin/bridges/vst3-impls/plugin-proxy.h index 621c0d70..d767cd2b 100644 --- a/src/plugin/bridges/vst3-impls/plugin-proxy.h +++ b/src/plugin/bridges/vst3-impls/plugin-proxy.h @@ -124,6 +124,22 @@ class Vst3PluginProxyImpl : public Vst3PluginProxy { tresult PLUGIN_API initialize(FUnknown* context) override; tresult PLUGIN_API terminate() override; + /** + * The component handler the host passed to us during + * `IEditController::setComponentHandler()`. When the plugin makes a + * callback on a component handler proxy object, we'll pass the call through + * to this object. + */ + Steinberg::IPtr component_handler; + + /** + * If the host doesn't connect two objects directly in + * `IConnectionPoint::connect` but instead connects them through a proxy, + * we'll store that proxy here. This way we can then route messages sent by + * the plugin through this proxy. So far this is only needed for Ardour. + */ + Steinberg::IPtr connection_point_proxy; + /** * An unmanaged, raw pointer to the `IPlugView` instance returned in our * implementation of `IEditController::createView()`. We need this to handle @@ -136,14 +152,6 @@ class Vst3PluginProxyImpl : public Vst3PluginProxy { */ Vst3PlugViewProxyImpl* last_created_plug_view = nullptr; - /** - * The component handler the host passed to us during - * `IEditController::setComponentHandler()`. When the plugin makes a - * callback on a component handler proxy object, we'll pass the call through - * to this object. - */ - Steinberg::IPtr component_handler; - // The following pointers are cast from `host_context` if `setHostContext()` // has been called diff --git a/src/plugin/bridges/vst3.cpp b/src/plugin/bridges/vst3.cpp index 6712019f..61a4e43e 100644 --- a/src/plugin/bridges/vst3.cpp +++ b/src/plugin/bridges/vst3.cpp @@ -106,6 +106,12 @@ Vst3PluginBridge::Vst3PluginBridge() .get() .component_handler->restartComponent(request.flags); }, + [&](YaConnectionPoint::Notify& request) + -> YaConnectionPoint::Notify::Response { + return plugin_proxies.at(request.instance_id) + .get() + .connection_point_proxy->notify(&request.message); + }, [&](const YaHostApplication::GetName& request) -> YaHostApplication::GetName::Response { tresult result; diff --git a/src/wine-host/bridges/vst3-impls/connection-point-proxy.cpp b/src/wine-host/bridges/vst3-impls/connection-point-proxy.cpp new file mode 100644 index 00000000..24dfe718 --- /dev/null +++ b/src/wine-host/bridges/vst3-impls/connection-point-proxy.cpp @@ -0,0 +1,69 @@ +// yabridge: a Wine VST bridge +// Copyright (C) 2020 Robbert van der Helm +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#include "connection-point-proxy.h" + +#include + +Vst3ConnectionPointProxyImpl::Vst3ConnectionPointProxyImpl( + Vst3Bridge& bridge, + Vst3ConnectionPointProxy::ConstructArgs&& args) + : Vst3ConnectionPointProxy(std::move(args)), bridge(bridge) {} + +tresult PLUGIN_API +Vst3ConnectionPointProxyImpl::queryInterface(const Steinberg::TUID _iid, + void** obj) { + // TODO: Successful queries should also be logged + const tresult result = Vst3ConnectionPointProxy::queryInterface(_iid, obj); + if (result != Steinberg::kResultOk) { + std::cerr << "TODO: Implement unknown interface logging on Wine side " + "for Vst3ConnectionPointProxyImpl::queryInterface" + << std::endl; + } + + return result; +} + +tresult PLUGIN_API +Vst3ConnectionPointProxyImpl::connect(IConnectionPoint* /*other*/) { + std::cerr << "WARNING: The plugin called IConnectionPoint::connect(), this " + "should not happen" + << std::endl; + return Steinberg::kNotImplemented; +} + +tresult PLUGIN_API +Vst3ConnectionPointProxyImpl::disconnect(IConnectionPoint* /*other*/) { + std::cerr << "WARNING: The plugin called IConnectionPoint::disconnect(), " + "this should not happen" + << std::endl; + return Steinberg::kNotImplemented; +} + +tresult PLUGIN_API +Vst3ConnectionPointProxyImpl::notify(Steinberg::Vst::IMessage* message) { + // As explained in `YaMessage` and `Vst3PluginProxyImpl::notify`, we can + // only support our own `IMessage implementation here` + if (auto message_impl = dynamic_cast(message)) { + return bridge.send_message(YaConnectionPoint::Notify{ + .instance_id = owner_instance_id(), .message = *message_impl}); + } else { + std::cerr << "WARNING: Unknown message type passed to " + "'IConnectionPoint::notify()', ignoring" + << std::endl; + return Steinberg::kNotImplemented; + } +} diff --git a/src/wine-host/bridges/vst3-impls/connection-point-proxy.h b/src/wine-host/bridges/vst3-impls/connection-point-proxy.h new file mode 100644 index 00000000..9cff5c9e --- /dev/null +++ b/src/wine-host/bridges/vst3-impls/connection-point-proxy.h @@ -0,0 +1,41 @@ +// yabridge: a Wine VST bridge +// Copyright (C) 2020 Robbert van der Helm +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#pragma once + +#include "../vst3.h" + +class Vst3ConnectionPointProxyImpl : public Vst3ConnectionPointProxy { + public: + Vst3ConnectionPointProxyImpl( + Vst3Bridge& bridge, + Vst3ConnectionPointProxy::ConstructArgs&& args); + + /** + * We'll override the query interface to log queries for interfaces we do + * not (yet) support. + */ + tresult PLUGIN_API queryInterface(const Steinberg::TUID _iid, + void** obj) override; + + // From `IConnectionPoint` + tresult PLUGIN_API connect(IConnectionPoint* other) override; + tresult PLUGIN_API disconnect(IConnectionPoint* other) override; + tresult PLUGIN_API notify(Steinberg::Vst::IMessage* message) override; + + private: + Vst3Bridge& bridge; +};