if (!plugin->parameter_is_control (i)) {
continue;
}
+
+ ParameterDescriptor desc;
+ plugin->get_parameter_descriptor(i, desc);
+
if (!plugin->parameter_is_input (i)) {
- _control_outputs[i] = boost::shared_ptr<ReadOnlyControl> (new ReadOnlyControl (plugin, i));
+ _control_outputs[i] = boost::shared_ptr<ReadOnlyControl> (new ReadOnlyControl (plugin, desc, i));
continue;
}
Evoral::Parameter param (PluginAutomation, 0, i);
- ParameterDescriptor desc;
- plugin->get_parameter_descriptor(i, desc);
-
const bool automatable = a.find(param) != a.end();
if (automatable) {
if (Variant::type_is_numeric(desc.datatype)) {
list = boost::shared_ptr<AutomationList>(new AutomationList(param, desc));
}
- add_control (boost::shared_ptr<AutomationControl> (new PluginPropertyControl(this, param, desc, list)));
+ boost::shared_ptr<AutomationControl> c (new PluginPropertyControl(this, param, desc, list));
+ if (!Variant::type_is_numeric(desc.datatype)) {
+ c->set_flags (Controllable::Flag ((int)c->flags() | Controllable::NotAutomatable));
+ }
+ add_control (c);
}
}
BypassableChanged ();
}
+bool
+PluginInsert::write_immediate_event (size_t size, const uint8_t* buf)
+{
+ bool rv = true;
+ for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
+ if (!(*i)->write_immediate_event (size, buf)) {
+ rv = false;
+ }
+ }
+ return rv;
+}
+
void
PluginInsert::preset_load_set_value (uint32_t p, float v)
{
void
PluginInsert::silence (framecnt_t nframes, framepos_t start_frame)
{
+ automation_run (start_frame, nframes); // evaluate automation only
+
if (!active ()) {
+ // XXX delaybuffers need to be offset by nframes
return;
}
/* run as normal if we are active or moving from inactive to active */
if (_session.transport_rolling() || _session.bounce_processing()) {
- automation_run (bufs, start_frame, end_frame, speed, nframes);
+ automate_and_run (bufs, start_frame, end_frame, speed, nframes);
} else {
Glib::Threads::Mutex::Lock lm (control_lock(), Glib::Threads::TRY_LOCK);
connect_and_run (bufs, start_frame, end_frame, speed, nframes, 0, lm.locked());
}
} else {
+ // XXX should call ::silence() to run plugin(s) for consistent load.
+ // We'll need to change this anyway when bypass can be automated
bypass (bufs, nframes);
+ automation_run (start_frame, nframes); // evaluate automation only
_delaybuffers.flush ();
}
}
void
-PluginInsert::automation_run (BufferSet& bufs, framepos_t start, framepos_t end, double speed, pframes_t nframes)
+PluginInsert::automate_and_run (BufferSet& bufs, framepos_t start, framepos_t end, double speed, pframes_t nframes)
{
Evoral::ControlEvent next_event (0, 0.0f);
framecnt_t offset = 0;
}
}
#endif
- if (p == (uint32_t)-1 && (*iter)->get_property (X_("parameter"), p)) {
+ if (p == (uint32_t)-1) {
+ (*iter)->get_property (X_("parameter"), p);
+ }
+
+ if (p != (uint32_t)-1) {
/* this may create the new controllable */
}
boost::shared_ptr<Plugin> plugin = find_plugin (_session, prop->value(), type);
+ bool any_vst = false;
/* treat VST plugins equivalent if they have the same uniqueID
* allow to move sessions windows <> linux */
if (plugin == 0 && (type == ARDOUR::Windows_VST || type == ARDOUR::MacVST)) {
type = ARDOUR::LXVST;
plugin = find_plugin (_session, prop->value(), type);
+ if (plugin) { any_vst = true; }
}
#endif
if (plugin == 0 && (type == ARDOUR::LXVST || type == ARDOUR::MacVST)) {
type = ARDOUR::Windows_VST;
plugin = find_plugin (_session, prop->value(), type);
+ if (plugin) { any_vst = true; }
}
#endif
if (plugin == 0 && (type == ARDOUR::Windows_VST || type == ARDOUR::LXVST)) {
type = ARDOUR::MacVST;
plugin = find_plugin (_session, prop->value(), type);
+ if (plugin) { any_vst = true; }
}
#endif
and set all plugins to the same state.
*/
- if ((*niter)->name() == plugin->state_node_name()) {
+ if ( ((*niter)->name() == plugin->state_node_name())
+ || (any_vst && ((*niter)->name() == "lxvst" || (*niter)->name() == "windows-vst" || (*niter)->name() == "mac-vst"))
+ ) {
for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
/* Plugin state can include external files which are named after the ID.
if (c && c->alist()) {
if (!child->children().empty()) {
c->alist()->set_state (*child->children().front(), version);
-
- /* In some cases 2.X saves lists with min_yval and max_yval
- being FLT_MIN and FLT_MAX respectively. This causes problems
- in A3 because these min/max values are used to compute
- where GUI control points should be drawn. If we see such
- values, `correct' them to the min/max of the appropriate
- parameter.
- */
-
- float min_y = c->alist()->get_min_y ();
- float max_y = c->alist()->get_max_y ();
-
- ParameterDescriptor desc;
- _plugins.front()->get_parameter_descriptor (port_id, desc);
-
- if (min_y == FLT_MIN) {
- min_y = desc.lower;
- }
-
- if (max_y == FLT_MAX) {
- max_y = desc.upper;
- }
-
- c->alist()->set_yrange (min_y, max_y);
}
} else {
error << string_compose (_("PluginInsert: automatable control %1 not found - ignored"), port_id) << endmsg;
, _plugin (p)
{
if (alist()) {
- alist()->reset_default (desc.normal);
if (desc.toggled) {
list->set_interpolation(Evoral::ControlList::Discrete);
}
: AutomationControl (p->session(), param, desc, list)
, _plugin (p)
{
- if (alist()) {
- alist()->set_yrange (desc.lower, desc.upper);
- alist()->reset_default (desc.normal);
- }
}
void
boost::shared_ptr<AutomationControl> ac = automation_control (Evoral::Parameter (PluginAutomation, 0, param_id));
if (ac) {
// ToDo subtract _plugin_signal_latency from audible_frame() when rolling, assert > 0
- ac->stop_touch (true, session().audible_frame());
+ ac->stop_touch (session().audible_frame());
}
}