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;
};
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:

View File

@ -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<ARDOUR::VST3PluginModule> _module;
std::vector <Vst::IConnectionPoint*> _connections;
boost::shared_ptr<ConnectionProxy> _component_cproxy;
boost::shared_ptr<ConnectionProxy> _controller_cproxy;
FUID _fuid;
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 ()
{
using namespace Vst;

View File

@ -1232,14 +1232,18 @@ VST3PI::connect_components ()
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)) {
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<Vst::IConnectionPoint> componentCP (_component);
FUnknownPtr<Vst::IConnectionPoint> 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 <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;
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)