Consolidate PluginControl Code

This code was (for the most part) duplicated, and with
preparation for Region FX, a third copy motivated this
consolidation.
This commit is contained in:
Robin Gareus 2024-03-19 00:02:53 +01:00
parent 6191f89d55
commit d2bdf440c8
Signed by: rgareus
GPG Key ID: A090BCE02CF57F04
9 changed files with 190 additions and 294 deletions

View File

@ -108,37 +108,6 @@ public:
protected:
std::string describe_parameter (Evoral::Parameter);
/** A control that manipulates a plugin parameter (control port). */
struct PluginControl : public AutomationControl
{
PluginControl (IOPlug* p,
Evoral::Parameter const& param,
ParameterDescriptor const& desc);
double get_value () const;
void catch_up_with_external_value (double val);
XMLNode& get_state() const;
std::string get_user_string() const;
private:
void actually_set_value (double val, PBD::Controllable::GroupControlDisposition group_override);
IOPlug* _iop;
};
/** A control that manipulates a plugin property (message). */
struct PluginPropertyControl : public AutomationControl
{
PluginPropertyControl (IOPlug* p,
Evoral::Parameter const& param,
ParameterDescriptor const& desc);
double get_value () const;
XMLNode& get_state() const;
private:
void actually_set_value (double value, PBD::Controllable::GroupControlDisposition);
IOPlug* _iop;
Variant _value;
};
private:
/* disallow copy construction */
IOPlug (IOPlug const&);

View File

@ -24,15 +24,16 @@
#include "evoral/ControlSet.h"
#include "ardour/ardour.h"
#include "ardour/automation_control.h"
#include "ardour/plugin.h"
#include "ardour/plugin_types.h"
namespace ARDOUR {
class Session;
class Plugin;
class ReadOnlyControl;
class Route;
class Plugin;
class Session;
class LIBARDOUR_API PlugInsertBase : virtual public Evoral::ControlSet, virtual public PBD::Destructible
{
@ -61,10 +62,47 @@ public:
virtual bool can_reset_all_parameters () = 0;
virtual bool reset_parameters_to_default () = 0;
virtual std::string describe_parameter (Evoral::Parameter param) = 0;
virtual bool provides_stats () const = 0;
virtual bool get_stats (PBD::microseconds_t&, PBD::microseconds_t&, double&, double&) const = 0;
virtual void clear_stats () = 0;
/** A control that manipulates a plugin parameter (control port). */
struct PluginControl : public AutomationControl {
PluginControl (Session& s,
PlugInsertBase* p,
const Evoral::Parameter& param,
const ParameterDescriptor& desc,
std::shared_ptr<AutomationList> list = std::shared_ptr<AutomationList> ());
double get_value (void) const;
void catch_up_with_external_value (double val);
XMLNode& get_state () const;
std::string get_user_string () const;
protected:
virtual void actually_set_value (double val, PBD::Controllable::GroupControlDisposition group_override);
PlugInsertBase* _pib;
};
/** A control that manipulates a plugin property (message). */
struct PluginPropertyControl : public AutomationControl {
PluginPropertyControl (Session& s,
PlugInsertBase* p,
const Evoral::Parameter& param,
const ParameterDescriptor& desc,
std::shared_ptr<AutomationList> list = std::shared_ptr<AutomationList> ());
double get_value (void) const;
XMLNode& get_state () const;
protected:
virtual void actually_set_value (double value, PBD::Controllable::GroupControlDisposition);
PlugInsertBase* _pib;
Variant _value;
};
protected:
bool parse_plugin_type (XMLNode const&, PluginType&, std::string&) const;
std::shared_ptr<Plugin> find_and_load_plugin (Session&, XMLNode const&, PluginType&, std::string const&, bool& any_vst);

View File

@ -53,6 +53,7 @@ class AudioEngine;
class Session;
class BufferSet;
class IOPlug;
class PlugInsertBase;
class PluginInsert;
class Plugin;
class PluginInfo;
@ -373,8 +374,8 @@ public:
PBD::Signal1<void, uint32_t> EndTouch;
protected:
friend class IOPlug;
friend class PluginInsert;
friend class PlugInsertBase;
friend class Session;
/* Called when a parameter of the plugin is changed outside of this

View File

@ -44,7 +44,6 @@
#include "ardour/processor.h"
#include "ardour/readonly_control.h"
#include "ardour/sidechain.h"
#include "ardour/automation_control.h"
class XMLNode;
@ -209,42 +208,18 @@ public:
bool get_stats (PBD::microseconds_t& min, PBD::microseconds_t& max, double& avg, double& dev) const;
void clear_stats ();
/** A control that manipulates a plugin parameter (control port). */
struct PluginControl : public AutomationControl
struct PIControl : public PluginControl
{
PluginControl (PluginInsert* p,
const Evoral::Parameter& param,
const ParameterDescriptor& desc,
std::shared_ptr<AutomationList> list=std::shared_ptr<AutomationList>());
double get_value (void) const;
void catch_up_with_external_value (double val);
XMLNode& get_state() const;
std::string get_user_string() const;
PIControl (Session& s,
PlugInsertBase* p,
const Evoral::Parameter& param,
const ParameterDescriptor& desc,
std::shared_ptr<AutomationList> list = std::shared_ptr<AutomationList>())
: PluginControl (s, p, param, desc, list) {}
private:
PluginInsert* _plugin;
void actually_set_value (double val, PBD::Controllable::GroupControlDisposition group_override);
};
/** A control that manipulates a plugin property (message). */
struct PluginPropertyControl : public AutomationControl
{
PluginPropertyControl (PluginInsert* p,
const Evoral::Parameter& param,
const ParameterDescriptor& desc,
std::shared_ptr<AutomationList> list=std::shared_ptr<AutomationList>());
double get_value (void) const;
XMLNode& get_state() const;
protected:
void actually_set_value (double value, PBD::Controllable::GroupControlDisposition);
private:
PluginInsert* _plugin;
Variant _value;
};
std::shared_ptr<Plugin> plugin(uint32_t num=0) const {
if (num < _plugins.size()) {
return _plugins[num];

View File

@ -569,7 +569,7 @@ Automatable::control_factory(const Evoral::Parameter& param)
PluginInsert* pi = dynamic_cast<PluginInsert*>(this);
if (pi) {
pi->plugin(0)->get_parameter_descriptor(param.id(), desc);
control = new PluginInsert::PluginControl(pi, param, desc);
control = new PluginInsert::PIControl (_a_session, pi, param, desc);
} else {
warning << "PluginAutomation for non-Plugin" << endl;
}
@ -583,7 +583,7 @@ Automatable::control_factory(const Evoral::Parameter& param)
} else {
list = std::shared_ptr<AutomationList>(new AutomationList(param, desc, Temporal::TimeDomainProvider (Temporal::AudioTime)));
}
control = new PluginInsert::PluginPropertyControl(pi, param, desc, list);
control = new PluginInsert::PluginPropertyControl (_a_session, pi, param, desc, list);
}
} else {
warning << "PluginPropertyAutomation for non-Plugin" << endl;

View File

@ -336,7 +336,7 @@ IOPlug::create_parameters ()
Evoral::Parameter param (PluginAutomation, 0, i);
std::shared_ptr<AutomationControl> c (new PluginControl(this, param, desc));
std::shared_ptr<AutomationControl> c (new PluginControl (_session, this, param, desc));
c->set_flag (Controllable::NotAutomatable);
add_control (c);
@ -351,7 +351,7 @@ IOPlug::create_parameters ()
if (desc.datatype == Variant::NOTHING) {
continue;
}
std::shared_ptr<AutomationControl> c (new PluginPropertyControl (this, param, desc));
std::shared_ptr<AutomationControl> c (new PluginPropertyControl (_session, this, param, desc));
c->set_flag (Controllable::NotAutomatable);
add_control (c);
}
@ -655,104 +655,3 @@ IOPlug::reset_parameters_to_default ()
}
return all;
}
/* ****************************************************************************/
IOPlug::PluginControl::PluginControl (IOPlug* p,
Evoral::Parameter const& param,
ParameterDescriptor const& desc)
: AutomationControl (p->session (), param, desc, std::shared_ptr<AutomationList> (), p->describe_parameter (param))
, _iop (p)
{
}
void
IOPlug::PluginControl::actually_set_value (double user_val, PBD::Controllable::GroupControlDisposition group_override)
{
_iop->plugin ()->set_parameter (parameter().id(), user_val, 0);
AutomationControl::actually_set_value (user_val, group_override);
}
void
IOPlug::PluginControl::catch_up_with_external_value (double user_val)
{
AutomationControl::actually_set_value (user_val, Controllable::NoGroup);
}
XMLNode&
IOPlug::PluginControl::get_state () const
{
XMLNode& node (AutomationControl::get_state());
node.set_property ("parameter", parameter().id());
std::shared_ptr<LV2Plugin> lv2plugin = std::dynamic_pointer_cast<LV2Plugin> (_iop->plugin ());
if (lv2plugin) {
node.set_property ("symbol", lv2plugin->port_symbol (parameter().id()));
}
return node;
}
double
IOPlug::PluginControl::get_value () const
{
std::shared_ptr<Plugin> plugin = _iop->plugin ();
if (!plugin) {
return 0.0;
}
return plugin->get_parameter (parameter().id());
}
std::string
IOPlug::PluginControl::get_user_string () const
{
std::shared_ptr<Plugin> plugin = _iop->plugin (0);
if (plugin) {
std::string pp;
if (plugin->print_parameter (parameter().id(), pp) && pp.size () > 0) {
return pp;
}
}
return AutomationControl::get_user_string ();
}
IOPlug::PluginPropertyControl::PluginPropertyControl (IOPlug* p,
Evoral::Parameter const& param,
ParameterDescriptor const& desc)
: AutomationControl (p->session(), param, desc )
, _iop (p)
{
}
void
IOPlug::PluginPropertyControl::actually_set_value (double user_val, Controllable::GroupControlDisposition gcd)
{
const Variant value(_desc.datatype, user_val);
if (value.type() == Variant::NOTHING) {
return;
}
_iop->plugin ()->set_property (parameter().id(), value);
_value = value;
AutomationControl::actually_set_value (user_val, gcd);
}
XMLNode&
IOPlug::PluginPropertyControl::get_state () const
{
XMLNode& node (AutomationControl::get_state());
node.set_property ("property", parameter ().id ());
node.remove_property ("value");
return node;
}
double
IOPlug::PluginPropertyControl::get_value () const
{
return _value.to_double();
}

View File

@ -2168,7 +2168,13 @@ LuaBindings::common (lua_State* L)
.addFunction ("delay", &DelayLine::delay)
.endClass ()
.deriveWSPtrClass <PluginInsert::PluginControl, AutomationControl> ("PluginControl")
.deriveWSPtrClass <PlugInsertBase::PluginControl, AutomationControl> ("PluginControl")
.endClass ()
.deriveWSPtrClass <PlugInsertBase::PluginPropertyControl, AutomationControl> ("PluginPropertyControl")
.endClass ()
.deriveWSPtrClass <PluginInsert::PIControl, PlugInsertBase::PluginControl> ("PIControl")
.endClass ()
.beginClass <RawMidiParser> ("RawMidiParser")

View File

@ -16,11 +16,11 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "ardour/plug_insert_base.h"
#include "ardour/ardour.h"
#include "ardour/automation_control.h"
#include "ardour/lv2_plugin.h"
#include "ardour/luaproc.h"
#include "ardour/plug_insert_base.h"
#include "ardour/lv2_plugin.h"
#include "pbd/i18n.h"
@ -198,3 +198,125 @@ PlugInsertBase::preset_load_set_value (uint32_t p, float v)
ac->set_value (v, Controllable::NoGroup);
ac->stop_touch (timepos_t (ac->session ().audible_sample()));
}
/* ****************************************************************************/
PlugInsertBase::PluginControl::PluginControl (Session& s,
PlugInsertBase* p,
const Evoral::Parameter& param,
const ParameterDescriptor& desc,
std::shared_ptr<AutomationList> list)
: AutomationControl (s, param, desc, list, p->describe_parameter (param))
, _pib (p)
{
if (alist ()) {
if (desc.toggled) {
list->set_interpolation (Evoral::ControlList::Discrete);
}
}
}
/** @param val `user' value */
void
PlugInsertBase::PluginControl::actually_set_value (double user_val, PBD::Controllable::GroupControlDisposition group_override)
{
for (uint32_t i = 0; i < _pib->get_count (); ++i) {
_pib->plugin (i)->set_parameter (parameter ().id (), user_val, 0);
}
AutomationControl::actually_set_value (user_val, group_override);
}
void
PlugInsertBase::PluginControl::catch_up_with_external_value (double user_val)
{
AutomationControl::actually_set_value (user_val, Controllable::NoGroup);
}
XMLNode&
PlugInsertBase::PluginControl::get_state () const
{
XMLNode& node (AutomationControl::get_state ());
node.set_property (X_("parameter"), parameter ().id ());
std::shared_ptr<LV2Plugin> lv2plugin = std::dynamic_pointer_cast<LV2Plugin> (_pib->plugin (0));
if (lv2plugin) {
node.set_property (X_("symbol"), lv2plugin->port_symbol (parameter ().id ()));
}
return node;
}
/** @return `user' val */
double
PlugInsertBase::PluginControl::get_value () const
{
std::shared_ptr<Plugin> plugin = _pib->plugin ();
if (!plugin) {
return 0.0;
}
return plugin->get_parameter (parameter ().id ());
}
std::string
PlugInsertBase::PluginControl::get_user_string () const
{
std::shared_ptr<Plugin> plugin = _pib->plugin ();
if (plugin) {
std::string pp;
if (plugin->print_parameter (parameter ().id (), pp) && pp.size () > 0) {
return pp;
}
}
return AutomationControl::get_user_string ();
}
PlugInsertBase::PluginPropertyControl::PluginPropertyControl (Session& s,
PlugInsertBase* p,
const Evoral::Parameter& param,
const ParameterDescriptor& desc,
std::shared_ptr<AutomationList> list)
: AutomationControl (s, param, desc, list)
, _pib (p)
{
}
void
PlugInsertBase::PluginPropertyControl::actually_set_value (double user_val, Controllable::GroupControlDisposition gcd)
{
/* Old numeric set_value(), coerce to appropriate datatype if possible.
* This is lossy, but better than nothing until Ardour's automation system
* can handle various datatypes all the way down.
*/
const Variant value (_desc.datatype, user_val);
if (value.type () == Variant::NOTHING) {
error << "set_value(double) called for non-numeric property" << endmsg;
return;
}
for (uint32_t i = 0; i < _pib->get_count (); ++i) {
_pib->plugin (i)->set_property (parameter ().id (), value);
}
_value = value;
AutomationControl::actually_set_value (user_val, gcd);
}
XMLNode&
PlugInsertBase::PluginPropertyControl::get_state () const
{
XMLNode& node (AutomationControl::get_state ());
node.set_property (X_("property"), parameter ().id ());
node.remove_property (X_("value"));
return node;
}
double
PlugInsertBase::PluginPropertyControl::get_value () const
{
return _value.to_double ();
}

View File

@ -569,7 +569,7 @@ PluginInsert::create_automatable_parameters ()
const bool automatable = a.find(param) != a.end();
std::shared_ptr<AutomationList> list(new AutomationList(param, desc, *this));
std::shared_ptr<AutomationControl> c (new PluginControl(this, param, desc, list));
std::shared_ptr<AutomationControl> c (new PIControl(_session, this, param, desc, list));
if (!automatable || (limit_automatables > 0 && what_can_be_automated ().size() > limit_automatables)) {
c->set_flag (Controllable::NotAutomatable);
}
@ -590,7 +590,7 @@ PluginInsert::create_automatable_parameters ()
if (Variant::type_is_numeric(desc.datatype)) {
list = std::shared_ptr<AutomationList>(new AutomationList(param, desc, *this));
}
std::shared_ptr<AutomationControl> c (new PluginPropertyControl(this, param, desc, list));
std::shared_ptr<AutomationControl> c (new PluginPropertyControl(_session, this, param, desc, list));
if (!Variant::type_is_numeric(desc.datatype)) {
c->set_flag (Controllable::NotAutomatable);
}
@ -612,7 +612,7 @@ PluginInsert::create_automatable_parameters ()
desc.upper = 1;
std::shared_ptr<AutomationList> list(new AutomationList(param, desc, *this));
std::shared_ptr<AutomationControl> c (new PluginControl(this, param, desc, list));
std::shared_ptr<AutomationControl> c (new PluginControl(_session, this, param, desc, list));
add_control (c);
}
@ -3069,129 +3069,15 @@ PluginInsert::type () const
return plugin()->get_info()->type;
}
PluginInsert::PluginControl::PluginControl (PluginInsert* p,
const Evoral::Parameter& param,
const ParameterDescriptor& desc,
std::shared_ptr<AutomationList> list)
: AutomationControl (p->session(), param, desc, list, p->describe_parameter(param))
, _plugin (p)
{
if (alist()) {
if (desc.toggled) {
list->set_interpolation(Evoral::ControlList::Discrete);
}
}
}
/** @param val `user' value */
void
PluginInsert::PluginControl::actually_set_value (double user_val, PBD::Controllable::GroupControlDisposition group_override)
PluginInsert::PIControl::actually_set_value (double user_val, PBD::Controllable::GroupControlDisposition group_override)
{
/* FIXME: probably should be taking out some lock here.. */
for (Plugins::iterator i = _plugin->_plugins.begin(); i != _plugin->_plugins.end(); ++i) {
(*i)->set_parameter (_list->parameter().id(), user_val, 0);
}
std::shared_ptr<Plugin> iasp = _plugin->_impulseAnalysisPlugin.lock();
std::shared_ptr<Plugin> iasp = dynamic_cast<PluginInsert*>(_pib)->_impulseAnalysisPlugin.lock();
if (iasp) {
iasp->set_parameter (_list->parameter().id(), user_val, 0);
}
AutomationControl::actually_set_value (user_val, group_override);
}
void
PluginInsert::PluginControl::catch_up_with_external_value (double user_val)
{
AutomationControl::actually_set_value (user_val, Controllable::NoGroup);
}
XMLNode&
PluginInsert::PluginControl::get_state () const
{
XMLNode& node (AutomationControl::get_state());
node.set_property (X_("parameter"), parameter().id());
std::shared_ptr<LV2Plugin> lv2plugin = std::dynamic_pointer_cast<LV2Plugin> (_plugin->_plugins[0]);
if (lv2plugin) {
node.set_property (X_("symbol"), lv2plugin->port_symbol (parameter().id()));
}
return node;
}
/** @return `user' val */
double
PluginInsert::PluginControl::get_value () const
{
std::shared_ptr<Plugin> plugin = _plugin->plugin (0);
if (!plugin) {
return 0.0;
}
return plugin->get_parameter (_list->parameter().id());
}
std::string
PluginInsert::PluginControl::get_user_string () const
{
std::shared_ptr<Plugin> plugin = _plugin->plugin (0);
if (plugin) {
std::string pp;
if (plugin->print_parameter (parameter().id(), pp) && pp.size () > 0) {
return pp;
}
}
return AutomationControl::get_user_string ();
}
PluginInsert::PluginPropertyControl::PluginPropertyControl (PluginInsert* p,
const Evoral::Parameter& param,
const ParameterDescriptor& desc,
std::shared_ptr<AutomationList> list)
: AutomationControl (p->session(), param, desc, list)
, _plugin (p)
{
}
void
PluginInsert::PluginPropertyControl::actually_set_value (double user_val, Controllable::GroupControlDisposition gcd)
{
/* Old numeric set_value(), coerce to appropriate datatype if possible.
This is lossy, but better than nothing until Ardour's automation system
can handle various datatypes all the way down. */
const Variant value(_desc.datatype, user_val);
if (value.type() == Variant::NOTHING) {
error << "set_value(double) called for non-numeric property" << endmsg;
return;
}
for (Plugins::iterator i = _plugin->_plugins.begin(); i != _plugin->_plugins.end(); ++i) {
(*i)->set_property(_list->parameter().id(), value);
}
_value = value;
AutomationControl::actually_set_value (user_val, gcd);
}
XMLNode&
PluginInsert::PluginPropertyControl::get_state () const
{
XMLNode& node (AutomationControl::get_state());
node.set_property (X_("property"), parameter().id());
node.remove_property (X_("value"));
return node;
}
double
PluginInsert::PluginPropertyControl::get_value () const
{
return _value.to_double();
PluginControl::actually_set_value (user_val, group_override);
}
std::shared_ptr<Plugin>