From b79520d316f5dbebb4f5aa99f74efebf6434611e Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Thu, 3 Dec 2020 02:48:20 +0100 Subject: [PATCH] VST3: Use a proxy for connecting and passing messages #8481 This separates channels in each direction component <> controller, preventing recursions. --- libs/ardour/ardour/vst3_host.h | 22 +++++++++ libs/ardour/ardour/vst3_plugin.h | 9 +--- libs/ardour/vst3_host.cc | 84 ++++++++++++++++++++++++++++++++ libs/ardour/vst3_plugin.cc | 68 ++++++-------------------- 4 files changed, 122 insertions(+), 61 deletions(-) diff --git a/libs/ardour/ardour/vst3_host.h b/libs/ardour/ardour/vst3_host.h index 6560ffc398..1125be973d 100644 --- a/libs/ardour/ardour/vst3_host.h +++ b/libs/ardour/ardour/vst3_host.h @@ -198,6 +198,28 @@ protected: boost::shared_ptr _attribute_list; }; +class LIBARDOUR_API ConnectionProxy : public Vst::IConnectionPoint, public RefObject +{ +public: + ConnectionProxy (IConnectionPoint* src); + ~ConnectionProxy () SMTG_OVERRIDE; + + QUERY_INTERFACE_IMPL (Vst::IConnectionPoint); + uint32 PLUGIN_API addRef () SMTG_OVERRIDE { return RefObject::addRef (); } + uint32 PLUGIN_API release () SMTG_OVERRIDE { return RefObject::release (); } + + /* IConnectionPoint API */ + tresult PLUGIN_API connect (Vst::IConnectionPoint*) SMTG_OVERRIDE; + tresult PLUGIN_API disconnect (Vst::IConnectionPoint*) SMTG_OVERRIDE; + tresult PLUGIN_API notify (Vst::IMessage*) SMTG_OVERRIDE; + + bool disconnect (); + +protected: + IConnectionPoint* _src; + IConnectionPoint* _dst; +}; + class LIBARDOUR_API PlugInterfaceSupport : public Vst::IPlugInterfaceSupport { public: diff --git a/libs/ardour/ardour/vst3_plugin.h b/libs/ardour/ardour/vst3_plugin.h index b5096be7c3..afaaecc5ca 100644 --- a/libs/ardour/ardour/vst3_plugin.h +++ b/libs/ardour/ardour/vst3_plugin.h @@ -54,7 +54,6 @@ namespace Steinberg { class LIBARDOUR_API VST3PI : public Vst::IComponentHandler , public Vst::IComponentHandler2 - , public Vst::IConnectionPoint , public Vst::IUnitHandler , public IPlugFrame , public Presonus::IContextInfoProvider3 @@ -75,11 +74,6 @@ public: tresult PLUGIN_API startGroupEdit () SMTG_OVERRIDE; tresult PLUGIN_API finishGroupEdit () SMTG_OVERRIDE; - /* IConnectionPoint API */ - tresult PLUGIN_API connect (Vst::IConnectionPoint* other) SMTG_OVERRIDE; - tresult PLUGIN_API disconnect (Vst::IConnectionPoint* other) SMTG_OVERRIDE; - tresult PLUGIN_API notify (Vst::IMessage* message) SMTG_OVERRIDE; - /* IPlugFrame */ tresult PLUGIN_API resizeView (IPlugView* view, ViewRect* newSize) SMTG_OVERRIDE; @@ -217,7 +211,8 @@ private: boost::shared_ptr _module; - std::vector _connections; + boost::shared_ptr _component_cproxy; + boost::shared_ptr _controller_cproxy; FUID _fuid; Vst::IComponent* _component; diff --git a/libs/ardour/vst3_host.cc b/libs/ardour/vst3_host.cc index 9d1249b7d4..dfd0bc7f34 100644 --- a/libs/ardour/vst3_host.cc +++ b/libs/ardour/vst3_host.cc @@ -299,6 +299,90 @@ HostMessage::getAttributes () /* ****************************************************************************/ +ConnectionProxy::ConnectionProxy (Vst::IConnectionPoint* src) + : _src (src) + , _dst (0) +{ + if (_src) { + _src->addRef (); + } +} + +ConnectionProxy::~ConnectionProxy () +{ + if (_src) { + _src->release (); + } + if (_dst) { + _dst->release (); + } +} + +tresult +ConnectionProxy::connect (Vst::IConnectionPoint* dst) +{ + if (!dst) { + return kInvalidArgument; + } + if (_dst) { + return kResultFalse; + } + + _dst = dst; + _dst->addRef (); + + tresult res = _src->connect (this); + + if (res != kResultTrue) { + _dst->release (); + _dst = 0; + } + return res; +} + +tresult + ConnectionProxy::disconnect (Vst::IConnectionPoint* dst) +{ + if (!dst) { + return kInvalidArgument; + } + + if (dst != _dst) { + return kInvalidArgument; + } + + if (_src) { + _src->disconnect (this); + } + + _dst->release (); + _dst = 0; + return kResultTrue; +} + + +tresult +ConnectionProxy::notify (Vst::IMessage* message) +{ + if (!_dst) { + return kResultFalse; + } +#if 0 + if (strcmp ("ArdourGUI", pthread_name ())) { + return kResultFalse; + } +#endif + return _dst->notify (message); +} + +bool +ConnectionProxy::disconnect () +{ + return kResultTrue == disconnect (_dst); +} + +/* ****************************************************************************/ + PlugInterfaceSupport::PlugInterfaceSupport () { using namespace Vst; diff --git a/libs/ardour/vst3_plugin.cc b/libs/ardour/vst3_plugin.cc index 994518db80..9b9db16361 100644 --- a/libs/ardour/vst3_plugin.cc +++ b/libs/ardour/vst3_plugin.cc @@ -1232,14 +1232,18 @@ VST3PI::connect_components () return true; } - tresult res = componentCP->connect (this); + _component_cproxy = boost::shared_ptr (new ConnectionProxy (componentCP)); + _controller_cproxy = boost::shared_ptr (new ConnectionProxy (controllerCP)); + + tresult res = _component_cproxy->connect (controllerCP); if (!(res == kResultOk || res == kNotImplemented)) { - return false; + DEBUG_TRACE (DEBUG::VST3Config, "VST3PI::connect_components Cannot connect controller to component\n"); + //return false; } - res = controllerCP->connect (this); + res = _controller_cproxy->connect (componentCP); if (!(res == kResultOk || res == kNotImplemented)) { - DEBUG_TRACE (DEBUG::VST3Config, "VST3PI::connect_components Cannot connect controller, ignored.\n"); + DEBUG_TRACE (DEBUG::VST3Config, "VST3PI::connect_components Cannot connect component to controller\n"); } return true; @@ -1248,60 +1252,17 @@ VST3PI::connect_components () bool VST3PI::disconnect_components () { - FUnknownPtr componentCP (_component); - FUnknownPtr controllerCP (_controller); - if (!componentCP || !controllerCP) { + if (!_component_cproxy || !_controller_cproxy) { return false; } - bool res = kResultTrue == componentCP->disconnect (this); - res &= kResultTrue == controllerCP->disconnect (this); - return res; -} + bool rv = _component_cproxy->disconnect (); + rv &= _controller_cproxy->disconnect (); -tresult -VST3PI::connect (Vst::IConnectionPoint* other) -{ - if (!other) { - return kInvalidArgument; - } - _connections.push_back (other); - return kResultTrue; -} + _component_cproxy.reset (); + _controller_cproxy.reset (); -tresult -VST3PI::disconnect (Vst::IConnectionPoint* other) -{ - std::vector ::iterator i = std::find (_connections.begin(), _connections.end(), other); - if (i != _connections.end()) { - _connections.erase (i); - return kResultTrue; - } - return kInvalidArgument; -} - -tresult -VST3PI::notify (Vst::IMessage* msg) -{ - DEBUG_TRACE (DEBUG::VST3Callbacks, "VST3PI::notify.\n"); - for (std::vector ::const_iterator i = _connections.begin(); i != _connections.end(); ++i) { - /* TODO delegate to GUI thread if available - * see ./libs/pbd/pbd/event_loop.h ir->call_slot () - * and HostMessage() - */ - (*i)->notify (msg); - } - - FUnknownPtr componentCP (_component); - FUnknownPtr controllerCP (_controller); - if (componentCP) { - componentCP->notify (msg); - } - if (controllerCP) { - controllerCP->notify (msg); - } - - return kResultTrue; + return rv; } tresult @@ -1311,7 +1272,6 @@ VST3PI::queryInterface (const TUID _iid, void** obj) QUERY_INTERFACE (_iid, obj, Vst::IComponentHandler::iid, Vst::IComponentHandler) QUERY_INTERFACE (_iid, obj, Vst::IComponentHandler2::iid, Vst::IComponentHandler2) - QUERY_INTERFACE (_iid, obj, Vst::IConnectionPoint::iid, Vst::IConnectionPoint) QUERY_INTERFACE (_iid, obj, Vst::IUnitHandler::iid, Vst::IUnitHandler) QUERY_INTERFACE (_iid, obj, Presonus::IContextInfoProvider::iid, Presonus::IContextInfoProvider)