Update Plugin API to allow timestamped parameter changes

This is in preparation for VST3 automation.
This commit is contained in:
Robin Gareus 2020-08-07 22:02:56 +02:00
parent 04e5ea0f86
commit 1a50b6b8ea
Signed by: rgareus
GPG Key ID: A090BCE02CF57F04
15 changed files with 73 additions and 38 deletions

View File

@ -71,7 +71,7 @@ class LIBARDOUR_API AUPlugin : public ARDOUR::Plugin
const char * maker () const { return _info->creator.c_str(); }
uint32_t parameter_count () const;
float default_value (uint32_t port);
void set_parameter (uint32_t which, float val);
void set_parameter (uint32_t which, float val, sampleoffset_t);
float get_parameter (uint32_t which) const;
PluginOutputConfiguration possible_output () const { return _output_configs; }

View File

@ -127,10 +127,11 @@ protected:
SlavableControlList slavables () const { return SlavableControlList(); }
private:
inline void find_next_ac_event (boost::shared_ptr<AutomationControl>, double start, double end, Evoral::ControlEvent& ev) const;
inline void find_prev_ac_event (boost::shared_ptr<AutomationControl>, double start, double end, Evoral::ControlEvent& ev) const;
protected:
void find_next_ac_event (boost::shared_ptr<AutomationControl>, double start, double end, Evoral::ControlEvent& ev) const;
void find_prev_ac_event (boost::shared_ptr<AutomationControl>, double start, double end, Evoral::ControlEvent& ev) const;
private:
PBD::ScopedConnectionList _control_connections; ///< connections to our controls' signals
};

View File

@ -53,7 +53,7 @@ class LIBARDOUR_API LadspaPlugin : public ARDOUR::Plugin
const char* maker() const { return _descriptor->Maker; }
uint32_t parameter_count() const { return _descriptor->PortCount; }
float default_value (uint32_t port) { return _default_value (port); }
void set_parameter (uint32_t port, float val);
void set_parameter (uint32_t port, float val, sampleoffset_t);
float get_parameter (uint32_t port) const;
int get_parameter_descriptor (uint32_t which, ParameterDescriptor&) const;
uint32_t nth_parameter (uint32_t port, bool& ok) const;

View File

@ -68,7 +68,7 @@ public:
uint32_t parameter_count() const;
float default_value (uint32_t port);
void set_parameter (uint32_t port, float val);
void set_parameter (uint32_t port, float val, sampleoffset_t);
float get_parameter (uint32_t port) const;
int get_parameter_descriptor (uint32_t which, ParameterDescriptor&) const;
uint32_t nth_parameter (uint32_t port, bool& ok) const;

View File

@ -79,7 +79,7 @@ class LIBARDOUR_API LV2Plugin : public ARDOUR::Plugin, public ARDOUR::Workee
uint32_t parameter_count () const;
float default_value (uint32_t port);
samplecnt_t max_latency () const;
void set_parameter (uint32_t port, float val);
void set_parameter (uint32_t port, float val, sampleoffset_t);
float get_parameter (uint32_t port) const;
std::string get_docs() const;
std::string get_parameter_docs(uint32_t which) const;

View File

@ -368,8 +368,13 @@ protected:
/* should be overridden by plugin API specific derived types to
* actually implement changing the parameter. The derived type should
* call this after the change is made.
*
* @param which parameter-id
* @param val the raw value (plugin internal)
* @param when time offset of samples in current cycle (0 .. n_samples)
* when the event is effective.
*/
virtual void set_parameter (uint32_t which, float val);
virtual void set_parameter (uint32_t which, float val, sampleoffset_t when);
/** Do the actual saving of the current plugin settings to a preset of the provided name.
* Should return a URI on success, or an empty string on failure.

View File

@ -323,7 +323,7 @@ private:
void parameter_changed_externally (uint32_t, float);
void set_parameter (Evoral::Parameter param, float val);
void set_parameter (Evoral::Parameter param, float val, sampleoffset_t);
float default_parameter_value (const Evoral::Parameter& param);

View File

@ -58,7 +58,7 @@ public:
float default_value (uint32_t port);
float get_parameter (uint32_t port) const;
uint32_t nth_parameter (uint32_t port, bool& ok) const;
void set_parameter (uint32_t port, float val);
void set_parameter (uint32_t port, float val, sampleoffset_t);
void set_parameter_automated (uint32_t port, float val);
bool load_preset (PresetRecord);
int get_parameter_descriptor (uint32_t which, ParameterDescriptor&) const;

View File

@ -508,7 +508,7 @@ AUPlugin::AUPlugin (const AUPlugin& other)
set_state (root, Stateful::loading_state_version);
for (size_t i = 0; i < descriptors.size(); ++i) {
set_parameter (i, other.get_parameter (i));
set_parameter (i, other.get_parameter (i), 0);
}
}
@ -961,7 +961,7 @@ AUPlugin::plugin_latency () const
}
void
AUPlugin::set_parameter (uint32_t which, float val)
AUPlugin::set_parameter (uint32_t which, float val, sampleoffset_t when)
{
if (which >= descriptors.size()) {
return;
@ -989,7 +989,7 @@ AUPlugin::set_parameter (uint32_t which, float val)
/* Note the 1st argument, which means "Don't notify us about a change we made ourselves" */
AUEventListenerNotify (_parameter_listener, NULL, &theEvent);
Plugin::set_parameter (which, val);
Plugin::set_parameter (which, val, when);
}
float

View File

@ -295,7 +295,7 @@ LadspaPlugin::_default_value (uint32_t port) const
}
void
LadspaPlugin::set_parameter (uint32_t which, float val)
LadspaPlugin::set_parameter (uint32_t which, float val, sampleoffset_t when)
{
if (which < _descriptor->PortCount) {
@ -318,7 +318,7 @@ LadspaPlugin::set_parameter (uint32_t which, float val)
<< endmsg;
}
Plugin::set_parameter (which, val);
Plugin::set_parameter (which, val, when);
}
/** @return `plugin' value */
@ -403,7 +403,7 @@ LadspaPlugin::set_state (const XMLNode& node, int version)
continue;
}
set_parameter (port_id, value);
set_parameter (port_id, value, 0);
}
latency_compute_run ();
@ -448,7 +448,7 @@ LadspaPlugin::set_state_2X (const XMLNode& node, int /* version */)
}
sscanf (port, "%" PRIu32, &port_id);
set_parameter (port_id, atof(data));
set_parameter (port_id, atof(data), 0);
}
latency_compute_run ();
@ -774,7 +774,7 @@ LadspaPlugin::load_preset (PresetRecord r)
if (defs) {
for (uint32_t i = 0; i < (uint32_t) defs->count; ++i) {
if (parameter_is_input (defs->items[i].pid)) {
set_parameter(defs->items[i].pid, defs->items[i].value);
set_parameter(defs->items[i].pid, defs->items[i].value, 0);
PresetPortSetValue (defs->items[i].pid, defs->items[i].value); /* EMIT SIGNAL */
}
}

View File

@ -916,7 +916,7 @@ LuaProc::set_state (const XMLNode& node, int version)
continue;
}
set_parameter (port_id, value);
set_parameter (port_id, value, 0);
}
return Plugin::set_state (node, version);
@ -940,14 +940,14 @@ LuaProc::default_value (uint32_t port)
}
void
LuaProc::set_parameter (uint32_t port, float val)
LuaProc::set_parameter (uint32_t port, float val, sampleoffset_t when)
{
assert (port < parameter_count ());
if (get_parameter (port) == val) {
return;
}
_shadow_data[port] = val;
Plugin::set_parameter (port, val);
Plugin::set_parameter (port, val, when);
}
float
@ -1176,7 +1176,7 @@ LuaProc::load_preset (PresetRecord r)
assert (false);
continue;
}
set_parameter (index, value);
set_parameter (index, value, 0);
PresetPortSetValue (index, value); /* EMIT SIGNAL */
}
}

View File

@ -263,7 +263,7 @@ set_port_value(const char* port_symbol,
const uint32_t port_index = self->port_index(port_symbol);
if (port_index != (uint32_t)-1) {
self->set_parameter(port_index, *(const float*)value);
self->set_parameter(port_index, *(const float*)value, 0);
self->PresetPortSetValue (port_index, *(const float*)value); /* EMIT SIGNAL */
}
}
@ -1222,7 +1222,7 @@ LV2Plugin::port_index (const char* symbol) const
}
void
LV2Plugin::set_parameter(uint32_t which, float val)
LV2Plugin::set_parameter(uint32_t which, float val, sampleoffset_t when)
{
DEBUG_TRACE(DEBUG::LV2, string_compose(
"%1 set parameter %2 to %3\n", name(), which, val));
@ -1240,7 +1240,7 @@ LV2Plugin::set_parameter(uint32_t which, float val)
name(), PROGRAM_NAME, unique_id()) << endmsg;
}
Plugin::set_parameter(which, val);
Plugin::set_parameter(which, val, when);
}
float
@ -2212,7 +2212,7 @@ LV2Plugin::set_state(const XMLNode& node, int version)
continue;
}
set_parameter(port_id, val);
set_parameter(port_id, val, 0);
}
std::string template_dir;

View File

@ -489,7 +489,7 @@ Plugin::clear_preset ()
}
void
Plugin::set_parameter (uint32_t /* which */, float /* value */)
Plugin::set_parameter (uint32_t /* which */, float /* value */, sampleoffset_t /* when */)
{
_parameter_changed_since_last_preset = true;
PresetDirty (); /* EMIT SIGNAL */

View File

@ -289,7 +289,7 @@ PluginInsert::control_list_automation_state_changed (Evoral::Parameter which, Au
= boost::dynamic_pointer_cast<AutomationControl>(control (which));
if (c && s != Off) {
_plugins[0]->set_parameter (which.id(), c->list()->eval (_session.transport_sample()));
_plugins[0]->set_parameter (which.id(), c->list()->eval (_session.transport_sample()), 0);
}
}
@ -595,12 +595,12 @@ PluginInsert::parameter_changed_externally (uint32_t which, float val)
if (i != _plugins.end()) {
++i;
for (; i != _plugins.end(); ++i) {
(*i)->set_parameter (which, val);
(*i)->set_parameter (which, val, 0);
}
}
boost::shared_ptr<Plugin> iasp = _impulseAnalysisPlugin.lock();
if (iasp) {
iasp->set_parameter (which, val);
iasp->set_parameter (which, val, 0);
}
}
@ -909,11 +909,40 @@ PluginInsert::connect_and_run (BufferSet& bufs, samplepos_t start, samplepos_t e
boost::shared_ptr<const Evoral::ControlList> clist (c.list());
/* we still need to check for Touch and Latch */
if (clist && (static_cast<AutomationList const&> (*clist)).automation_playback ()) {
/* 1. Set value at [sub]cycle start */
bool valid;
const float val = c.list()->rt_safe_eval (start, valid);
float val = clist->rt_safe_eval (start, valid);
if (valid) {
c.set_value_unchecked(val);
}
#if 0
/* 2. VST3: events between now and end. */
assert (_plugins.front()->requires_fixed_sized_buffers());
samplepos_t now = start;
while (true) {
Evoral::ControlEvent next_event (end, 0.0f);
find_next_ac_event (*ci, now, end, next_event);
if (next_event.when >= end) {
break;
}
now = next_event.when;
const float val = c.list()->rt_safe_eval (now, valid);
if (valid) {
for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
(*i)->set_parameter (clist->parameter().id(), val, now - start);
}
}
}
#endif
#if 0
/* 3. set value at cycle-end */
val = c.list()->rt_safe_eval (end, valid);
if (valid) {
for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
(*i)->set_parameter (clist->parameter().id(), val, end - start);
}
}
#endif
}
}
}
@ -2990,12 +3019,12 @@ PluginInsert::PluginControl::actually_set_value (double user_val, PBD::Controlla
/* 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);
(*i)->set_parameter (_list->parameter().id(), user_val, 0);
}
boost::shared_ptr<Plugin> iasp = _plugin->_impulseAnalysisPlugin.lock();
if (iasp) {
iasp->set_parameter (_list->parameter().id(), user_val);
iasp->set_parameter (_list->parameter().id(), user_val, 0);
}
AutomationControl::actually_set_value (user_val, group_override);

View File

@ -187,7 +187,7 @@ VSTPlugin::get_parameter (uint32_t which) const
}
void
VSTPlugin::set_parameter (uint32_t which, float newval)
VSTPlugin::set_parameter (uint32_t which, float newval, sampleoffset_t when)
{
if (which == UINT32_MAX - 1) {
// ardour uses enable-semantics: 1: enabled, 0: bypassed
@ -217,15 +217,15 @@ VSTPlugin::set_parameter (uint32_t which, float newval)
if (!PBD::floateq (curval, oldval, 1)) {
/* value has changed, follow rest of the notification path */
Plugin::set_parameter (which, newval);
Plugin::set_parameter (which, newval, when);
}
}
void
VSTPlugin::parameter_changed_externally (uint32_t which, float value )
VSTPlugin::parameter_changed_externally (uint32_t which, float value)
{
ParameterChangedExternally (which, value); /* EMIT SIGNAL */
Plugin::set_parameter (which, value);
Plugin::set_parameter (which, value, 0);
}
@ -531,7 +531,7 @@ VSTPlugin::load_user_preset (PresetRecord r)
assert (false);
}
set_parameter (index, value);
set_parameter (index, value, 0);
PresetPortSetValue (index, value); /* EMIT SIGNAL */
}
}