diff --git a/libs/ardour/ardour/vst3_plugin.h b/libs/ardour/ardour/vst3_plugin.h index 364950076b..7467752f8a 100644 --- a/libs/ardour/ardour/vst3_plugin.h +++ b/libs/ardour/ardour/vst3_plugin.h @@ -29,6 +29,7 @@ namespace ARDOUR { class VST3PluginModule; +class AutomationList; } #if defined(__clang__) @@ -113,6 +114,9 @@ public: std::string print_parameter (Vst::ParamID, Vst::ParamValue) const; bool set_program (int p, int32 sample_off); + bool subscribe_to_automation_changes () const; + void automation_state_changed (uint32_t, ARDOUR::AutoState, boost::weak_ptr); + ARDOUR::Plugin::IOPortDescription describe_io_port (ARDOUR::DataType dt, bool input, uint32_t id) const; uint32_t n_audio_inputs () const; @@ -154,6 +158,11 @@ public: void process (float** ins, float** outs, uint32_t n_samples); + /* PSL Extension */ + Vst::IEditController* conroller () const { return _controller; } + bool add_slave (Vst::IEditController*, bool); + bool remove_slave (Vst::IEditController*); + private: /* prevent copy construction */ VST3PI (const VST3PI&); @@ -287,6 +296,8 @@ public: IOPortDescription describe_io_port (DataType dt, bool input, uint32_t id) const; PluginOutputConfiguration possible_output () const; + void set_automation_control (uint32_t, boost::shared_ptr); + std::string state_node_name () const { return "vst3"; } void add_state (XMLNode*) const; @@ -303,6 +314,9 @@ public: void set_owner (ARDOUR::SessionObject* o); + void add_slave (boost::shared_ptr, bool); + void remove_slave (boost::shared_ptr); + int connect_and_run (BufferSet& bufs, samplepos_t start, samplepos_t end, double speed, ChanMapping const& in, ChanMapping const& out, diff --git a/libs/ardour/vst3_host.cc b/libs/ardour/vst3_host.cc index 31f93cbe46..d4c2eea283 100644 --- a/libs/ardour/vst3_host.cc +++ b/libs/ardour/vst3_host.cc @@ -60,6 +60,16 @@ DEF_CLASS_IID (Vst::IUnitData) DEF_CLASS_IID (Vst::IUnitInfo) DEF_CLASS_IID (Vst::ChannelContext::IInfoListener) +DEF_CLASS_IID (Presonus::IContextInfoProvider) +DEF_CLASS_IID (Presonus::IContextInfoProvider2) +DEF_CLASS_IID (Presonus::IContextInfoProvider3) +DEF_CLASS_IID (Presonus::IContextInfoHandler) +DEF_CLASS_IID (Presonus::IContextInfoHandler2) +DEF_CLASS_IID (Presonus::IEditControllerExtra) +DEF_CLASS_IID (Presonus::ISlaveControllerHandler) +DEF_CLASS_IID (Presonus::IPlugInViewEmbedding) +DEF_CLASS_IID (Presonus::IPlugInViewScaling) + #if SMTG_OS_LINUX DEF_CLASS_IID (Linux::IRunLoop); #endif diff --git a/libs/ardour/vst3_plugin.cc b/libs/ardour/vst3_plugin.cc index 8f27340ff1..19a8bf0ca8 100644 --- a/libs/ardour/vst3_plugin.cc +++ b/libs/ardour/vst3_plugin.cc @@ -183,6 +183,15 @@ VST3Plugin::designated_bypass_port () return _plug->designated_bypass_port (); } +void +VST3Plugin::set_automation_control (uint32_t port, boost::shared_ptr ac) +{ + if (!ac->alist () || !_plug->subscribe_to_automation_changes ()) { + return; + } + ac->alist()->automation_state_changed.connect_same_thread (_connections, boost::bind (&VST3PI::automation_state_changed, _plug, port, _1, boost::weak_ptr (ac->alist ()))); +} + std::set VST3Plugin::automatable () const { @@ -543,6 +552,24 @@ VST3Plugin::configure_io (ChanCount in, ChanCount out) return Plugin::configure_io (in, out); } +void +VST3Plugin::add_slave (boost::shared_ptr p, bool rt) +{ + boost::shared_ptr vst = boost::dynamic_pointer_cast (p); + if (vst) { + _plug->add_slave (vst->_plug->conroller (), rt); + } +} + +void +VST3Plugin::remove_slave (boost::shared_ptr p) +{ + boost::shared_ptr vst = boost::dynamic_pointer_cast (p); + if (vst) { + _plug->remove_slave (vst->_plug->conroller ()); + } +} + int VST3Plugin::connect_and_run (BufferSet& bufs, samplepos_t start, samplepos_t end, double speed, @@ -1564,6 +1591,12 @@ VST3PI::get_parameter_descriptor (uint32_t port, ParameterDescriptor& desc) cons } else if (p.unit == "Hz") { desc.unit = ARDOUR::ParameterDescriptor::HZ; } + + FUnknownPtr extra_ctrl (_controller); + if (extra_ctrl) { + int32 flags = extra_ctrl->getParamExtraFlags (id); + desc.inline_ctrl = (flags & Presonus::kParamFlagMicroEdit) ? true : false; + } } std::string @@ -2325,6 +2358,72 @@ VST3PI::setup_info_listener () stripable_property_changed (PropertyChange ()); } +/* **************************************************************************** + * PSL Extensions + */ + +bool +VST3PI::add_slave (Vst::IEditController* c, bool rt) +{ + FUnknownPtr slave_ctrl (_controller); + if (slave_ctrl) { + return slave_ctrl->addSlave (c, rt ? Presonus::kSlaveModeLowLatencyClone : Presonus::kSlaveModeNormal) == kResultOk; + } + return false; +} + +bool +VST3PI::remove_slave (Vst::IEditController* c) +{ + FUnknownPtr slave_ctrl (_controller); + if (slave_ctrl) { + return slave_ctrl->removeSlave (c) == kResultOk; + } + return false; +} + +bool +VST3PI::subscribe_to_automation_changes () const +{ + FUnknownPtr extra_ctrl (_controller); + return 0 != extra_ctrl ? true : false; +} + +void +VST3PI::automation_state_changed (uint32_t port, AutoState s, boost::weak_ptr wal) +{ + Vst::ParamID id (index_to_id (port)); + boost::shared_ptr al = wal.lock (); + FUnknownPtr extra_ctrl (_controller); + assert (extra_ctrl); + + Presonus::AutomationMode am; + switch (s) { + case ARDOUR::Off: + if (!al || al->empty ()) { + am = Presonus::kAutomationNone; + } else { + am = Presonus::kAutomationOff; + } + break; + case Write: + am = Presonus::kAutomationWrite; + break; + case Touch: + am = Presonus::kAutomationTouch; + break; + case Play: + am = Presonus::kAutomationRead; + break; + case Latch: + am = Presonus::kAutomationLatch; + break; + default: + assert (0); + } + extra_ctrl->setParamAutomationMode (id, am); +} + /* **************************************************************************** * GUI */