13
0

VST3: Use a proxy for connecting and passing messages #8481

This separates channels in each direction component <> controller,
preventing recursions.
This commit is contained in:
Robin Gareus 2020-12-03 02:48:20 +01:00
parent 0cfee47867
commit b79520d316
Signed by: rgareus
GPG Key ID: A090BCE02CF57F04
4 changed files with 122 additions and 61 deletions

View File

@ -198,6 +198,28 @@ protected:
boost::shared_ptr<HostAttributeList> _attribute_list; boost::shared_ptr<HostAttributeList> _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 class LIBARDOUR_API PlugInterfaceSupport : public Vst::IPlugInterfaceSupport
{ {
public: public:

View File

@ -54,7 +54,6 @@ namespace Steinberg {
class LIBARDOUR_API VST3PI class LIBARDOUR_API VST3PI
: public Vst::IComponentHandler : public Vst::IComponentHandler
, public Vst::IComponentHandler2 , public Vst::IComponentHandler2
, public Vst::IConnectionPoint
, public Vst::IUnitHandler , public Vst::IUnitHandler
, public IPlugFrame , public IPlugFrame
, public Presonus::IContextInfoProvider3 , public Presonus::IContextInfoProvider3
@ -75,11 +74,6 @@ public:
tresult PLUGIN_API startGroupEdit () SMTG_OVERRIDE; tresult PLUGIN_API startGroupEdit () SMTG_OVERRIDE;
tresult PLUGIN_API finishGroupEdit () 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 */ /* IPlugFrame */
tresult PLUGIN_API resizeView (IPlugView* view, ViewRect* newSize) SMTG_OVERRIDE; tresult PLUGIN_API resizeView (IPlugView* view, ViewRect* newSize) SMTG_OVERRIDE;
@ -217,7 +211,8 @@ private:
boost::shared_ptr<ARDOUR::VST3PluginModule> _module; boost::shared_ptr<ARDOUR::VST3PluginModule> _module;
std::vector <Vst::IConnectionPoint*> _connections; boost::shared_ptr<ConnectionProxy> _component_cproxy;
boost::shared_ptr<ConnectionProxy> _controller_cproxy;
FUID _fuid; FUID _fuid;
Vst::IComponent* _component; Vst::IComponent* _component;

View File

@ -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 () PlugInterfaceSupport::PlugInterfaceSupport ()
{ {
using namespace Vst; using namespace Vst;

View File

@ -1232,14 +1232,18 @@ VST3PI::connect_components ()
return true; return true;
} }
tresult res = componentCP->connect (this); _component_cproxy = boost::shared_ptr<ConnectionProxy> (new ConnectionProxy (componentCP));
_controller_cproxy = boost::shared_ptr<ConnectionProxy> (new ConnectionProxy (controllerCP));
tresult res = _component_cproxy->connect (controllerCP);
if (!(res == kResultOk || res == kNotImplemented)) { 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)) { 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; return true;
@ -1248,60 +1252,17 @@ VST3PI::connect_components ()
bool bool
VST3PI::disconnect_components () VST3PI::disconnect_components ()
{ {
FUnknownPtr<Vst::IConnectionPoint> componentCP (_component); if (!_component_cproxy || !_controller_cproxy) {
FUnknownPtr<Vst::IConnectionPoint> controllerCP (_controller);
if (!componentCP || !controllerCP) {
return false; return false;
} }
bool res = kResultTrue == componentCP->disconnect (this); bool rv = _component_cproxy->disconnect ();
res &= kResultTrue == controllerCP->disconnect (this); rv &= _controller_cproxy->disconnect ();
return res;
}
tresult _component_cproxy.reset ();
VST3PI::connect (Vst::IConnectionPoint* other) _controller_cproxy.reset ();
{
if (!other) {
return kInvalidArgument;
}
_connections.push_back (other);
return kResultTrue;
}
tresult return rv;
VST3PI::disconnect (Vst::IConnectionPoint* other)
{
std::vector <Vst::IConnectionPoint*>::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 <Vst::IConnectionPoint*>::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<Vst::IConnectionPoint> componentCP (_component);
FUnknownPtr<Vst::IConnectionPoint> controllerCP (_controller);
if (componentCP) {
componentCP->notify (msg);
}
if (controllerCP) {
controllerCP->notify (msg);
}
return kResultTrue;
} }
tresult 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::IComponentHandler::iid, Vst::IComponentHandler)
QUERY_INTERFACE (_iid, obj, Vst::IComponentHandler2::iid, Vst::IComponentHandler2) 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, Vst::IUnitHandler::iid, Vst::IUnitHandler)
QUERY_INTERFACE (_iid, obj, Presonus::IContextInfoProvider::iid, Presonus::IContextInfoProvider) QUERY_INTERFACE (_iid, obj, Presonus::IContextInfoProvider::iid, Presonus::IContextInfoProvider)