X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fplugin_insert.cc;h=8da0abb00fac440f58630e57eb383c7d96342449;hb=ca25a664d31aa4d16121aa4b41dad8ac04eafb16;hp=ae018fb2a3c53544c5e20034e4b13455b87d16ef;hpb=af0c42ec4f9d46907299f704d0c70e25e0af6b96;p=ardour.git diff --git a/libs/ardour/plugin_insert.cc b/libs/ardour/plugin_insert.cc index ae018fb2a3..8da0abb00f 100644 --- a/libs/ardour/plugin_insert.cc +++ b/libs/ardour/plugin_insert.cc @@ -240,23 +240,27 @@ PluginInsert::create_automatable_parameters () set a = _plugins.front()->automatable (); - Plugin::ParameterDescriptor desc; - for (set::iterator i = a.begin(); i != a.end(); ++i) { if (i->type() == PluginAutomation) { Evoral::Parameter param(*i); + ParameterDescriptor desc; _plugins.front()->get_parameter_descriptor(i->id(), desc); - /* the Parameter belonging to the actual plugin doesn't have its range set - but we want the Controllable related to this Parameter to have those limits. - */ - - param.set_range (desc.lower, desc.upper, _plugins.front()->default_value(i->id()), desc.toggled); can_automate (param); - boost::shared_ptr list(new AutomationList(param)); - add_control (boost::shared_ptr (new PluginControl(this, param, list))); + boost::shared_ptr list(new AutomationList(param, desc)); + add_control (boost::shared_ptr (new PluginControl(this, param, desc, list))); + } else if (i->type() == PluginPropertyAutomation) { + Evoral::Parameter param(*i); + const ParameterDescriptor& desc = _plugins.front()->get_property_descriptor(param.id()); + if (desc.datatype != Variant::NOTHING) { + boost::shared_ptr list; + if (Variant::type_is_numeric(desc.datatype)) { + list = boost::shared_ptr(new AutomationList(param, desc)); + } + add_control (boost::shared_ptr (new PluginPropertyControl(this, param, desc, list))); + } } } } @@ -352,6 +356,9 @@ PluginInsert::connect_and_run (BufferSet& bufs, pframes_t nframes, framecnt_t of } } + bufs.set_count(ChanCount::max(bufs.count(), in_streams)); + bufs.set_count(ChanCount::max(bufs.count(), out_streams)); + /* Note that we've already required that plugins be able to handle in-place processing. */ @@ -365,7 +372,7 @@ PluginInsert::connect_and_run (BufferSet& bufs, pframes_t nframes, framecnt_t of boost::shared_ptr c = boost::dynamic_pointer_cast(li->second); - if (c->parameter().type() == PluginAutomation && c->automation_playback()) { + if (c->list() && c->automation_playback()) { bool valid; const float val = c->list()->rt_safe_eval (now, valid); @@ -452,13 +459,13 @@ PluginInsert::silence (framecnt_t nframes) } void -PluginInsert::run (BufferSet& bufs, framepos_t /*start_frame*/, framepos_t /*end_frame*/, pframes_t nframes, bool) +PluginInsert::run (BufferSet& bufs, framepos_t start_frame, framepos_t /*end_frame*/, pframes_t nframes, bool) { if (_pending_active) { /* run as normal if we are active or moving from inactive to active */ - if (_session.transport_rolling()) { - automation_run (bufs, nframes); + if (_session.transport_rolling() || _session.bounce_processing()) { + automation_run (bufs, start_frame, nframes); } else { connect_and_run (bufs, nframes, 0, false); } @@ -535,10 +542,10 @@ PluginInsert::get_parameter (Evoral::Parameter param) } void -PluginInsert::automation_run (BufferSet& bufs, pframes_t nframes) +PluginInsert::automation_run (BufferSet& bufs, framepos_t start, pframes_t nframes) { Evoral::ControlEvent next_event (0, 0.0f); - framepos_t now = _session.transport_frame (); + framepos_t now = start; framepos_t end = now + nframes; framecnt_t offset = 0; @@ -588,12 +595,75 @@ PluginInsert::default_parameter_value (const Evoral::Parameter& param) if (_plugins.empty()) { fatal << _("programming error: ") << X_("PluginInsert::default_parameter_value() called with no plugin") << endmsg; - /*NOTREACHED*/ + abort(); /*NOTREACHED*/ } return _plugins[0]->default_value (param.id()); } + +bool +PluginInsert::can_reset_all_parameters () +{ + bool all = true; + uint32_t params = 0; + for (uint32_t par = 0; par < _plugins[0]->parameter_count(); ++par) { + bool ok=false; + const uint32_t cid = _plugins[0]->nth_parameter (par, ok); + + if (!ok || !_plugins[0]->parameter_is_input(cid)) { + continue; + } + + boost::shared_ptr ac = automation_control (Evoral::Parameter(PluginAutomation, 0, cid)); + if (!ac) { + continue; + } + + ++params; + if (ac->automation_state() & Play) { + all = false; + break; + } + } + return all && (params > 0); +} + +bool +PluginInsert::reset_parameters_to_default () +{ + bool all = true; + + for (uint32_t par = 0; par < _plugins[0]->parameter_count(); ++par) { + bool ok=false; + const uint32_t cid = _plugins[0]->nth_parameter (par, ok); + + if (!ok || !_plugins[0]->parameter_is_input(cid)) { + continue; + } + + const float dflt = _plugins[0]->default_value (cid); + const float curr = _plugins[0]->get_parameter (cid); + + if (dflt == curr) { + continue; + } + + boost::shared_ptr ac = automation_control (Evoral::Parameter(PluginAutomation, 0, cid)); + if (!ac) { + continue; + } + + if (ac->automation_state() & Play) { + all = false; + continue; + } + + ac->set_value (dflt); + } + return all; +} + boost::shared_ptr PluginInsert::plugin_factory (boost::shared_ptr other) { @@ -634,7 +704,7 @@ PluginInsert::plugin_factory (boost::shared_ptr other) fatal << string_compose (_("programming error: %1"), X_("unknown plugin type in PluginInsert::plugin_factory")) << endmsg; - /*NOTREACHED*/ + abort(); /*NOTREACHED*/ return boost::shared_ptr ((Plugin*) 0); } @@ -973,6 +1043,22 @@ PluginInsert::set_state(const XMLNode& node, int version) boost::shared_ptr plugin = find_plugin (_session, prop->value(), type); + /* treat linux and windows VST plugins equivalent if they have the same uniqueID + * allow to move sessions windows <> linux */ +#ifdef LXVST_SUPPORT + if (plugin == 0 && type == ARDOUR::Windows_VST) { + type = ARDOUR::LXVST; + plugin = find_plugin (_session, prop->value(), type); + } +#endif + +#ifdef WINDOWS_VST_SUPPORT + if (plugin == 0 && type == ARDOUR::LXVST) { + type = ARDOUR::Windows_VST; + plugin = find_plugin (_session, prop->value(), type); + } +#endif + if (plugin == 0) { error << string_compose( _("Found a reference to a plugin (\"%1\") that is unknown.\n" @@ -1023,8 +1109,6 @@ PluginInsert::set_state(const XMLNode& node, int version) if ((*niter)->name() == plugin->state_node_name()) { - plugin->set_state (**niter, version); - for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) { (*i)->set_state (**niter, version); } @@ -1105,7 +1189,7 @@ PluginInsert::set_parameter_state_2X (const XMLNode& node, int version) boost::shared_ptr c = boost::dynamic_pointer_cast( control(Evoral::Parameter(PluginAutomation, 0, port_id), true)); - if (c) { + if (c && c->alist()) { if (!child->children().empty()) { c->alist()->set_state (*child->children().front(), version); @@ -1120,7 +1204,7 @@ PluginInsert::set_parameter_state_2X (const XMLNode& node, int version) float min_y = c->alist()->get_min_y (); float max_y = c->alist()->get_max_y (); - Plugin::ParameterDescriptor desc; + ParameterDescriptor desc; _plugins.front()->get_parameter_descriptor (port_id, desc); if (min_y == FLT_MIN) { @@ -1148,11 +1232,15 @@ PluginInsert::set_parameter_state_2X (const XMLNode& node, int version) string PluginInsert::describe_parameter (Evoral::Parameter param) { - if (param.type() != PluginAutomation) { - return Automatable::describe_parameter(param); + if (param.type() == PluginAutomation) { + return _plugins[0]->describe_parameter (param); + } else if (param.type() == PluginPropertyAutomation) { + boost::shared_ptr c(automation_control(param)); + if (c && !c->desc().label.empty()) { + return c->desc().label; + } } - - return _plugins[0]->describe_parameter (param); + return Automatable::describe_parameter(param); } ARDOUR::framecnt_t @@ -1171,19 +1259,19 @@ PluginInsert::type () return plugin()->get_info()->type; } -PluginInsert::PluginControl::PluginControl (PluginInsert* p, const Evoral::Parameter ¶m, boost::shared_ptr list) - : AutomationControl (p->session(), param, list, p->describe_parameter(param)) +PluginInsert::PluginControl::PluginControl (PluginInsert* p, + const Evoral::Parameter& param, + const ParameterDescriptor& desc, + boost::shared_ptr list) + : AutomationControl (p->session(), param, desc, list, p->describe_parameter(param)) , _plugin (p) { - Plugin::ParameterDescriptor desc; - boost::shared_ptr plugin = p->plugin (0); - - alist()->reset_default (plugin->default_value (param.id())); - - plugin->get_parameter_descriptor (param.id(), desc); - _logarithmic = desc.logarithmic; - _sr_dependent = desc.sr_dependent; - _toggled = desc.toggled; + if (alist()) { + alist()->reset_default (desc.normal); + if (desc.toggled) { + list->set_interpolation(Evoral::ControlList::Discrete); + } + } if (desc.toggled) { set_flags(Controllable::Toggle); @@ -1208,66 +1296,80 @@ PluginInsert::PluginControl::set_value (double user_val) AutomationControl::set_value (user_val); } +XMLNode& +PluginInsert::PluginControl::get_state () +{ + stringstream ss; + + XMLNode& node (AutomationControl::get_state()); + ss << parameter().id(); + node.add_property (X_("parameter"), ss.str()); + + return node; +} + +/** @return `user' val */ double -PluginInsert::PluginControl::internal_to_interface (double val) const +PluginInsert::PluginControl::get_value () const { - if (_logarithmic) { - /* some plugins have a log-scale range "0.." - * ideally we'd map the range down to infinity somehow :) - * - * one solution could be to use - * val = exp(lower + log(range) * value); - * (log(val) - lower) / range) - * This approach would require access to the actual range (ie - * Plugin::ParameterDescriptor) and also require handling - * of unbound ranges.. - * - * currently an arbitrarly low number is assumed to represnt - * log(0) as hot-fix solution. - */ - if (val > 0) { - val = log (val); - } else { - val = -8; // ~ -70dB = 20 * log10(exp(-8)) - } + /* FIXME: probably should be taking out some lock here.. */ + return _plugin->get_parameter (_list->parameter()); +} + +PluginInsert::PluginPropertyControl::PluginPropertyControl (PluginInsert* p, + const Evoral::Parameter& param, + const ParameterDescriptor& desc, + boost::shared_ptr list) + : AutomationControl (p->session(), param, desc, list) + , _plugin (p) +{ + if (alist()) { + alist()->set_yrange (desc.lower, desc.upper); + alist()->reset_default (desc.normal); } - return val; + if (desc.toggled) { + set_flags(Controllable::Toggle); + } } -double -PluginInsert::PluginControl::interface_to_internal (double val) const +void +PluginInsert::PluginPropertyControl::set_value (double user_val) { - if (_logarithmic) { - if (val <= -8) { - /* see note in PluginInsert::PluginControl::internal_to_interface() */ - val= 0; - } else { - val = exp (val); - } + /* 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); } - return val; + _value = value; + AutomationControl::set_value(user_val); } XMLNode& -PluginInsert::PluginControl::get_state () +PluginInsert::PluginPropertyControl::get_state () { stringstream ss; XMLNode& node (AutomationControl::get_state()); ss << parameter().id(); - node.add_property (X_("parameter"), ss.str()); + node.add_property (X_("property"), ss.str()); + node.remove_property (X_("value")); return node; } -/** @return `user' val */ double -PluginInsert::PluginControl::get_value () const +PluginInsert::PluginPropertyControl::get_value () const { - /* FIXME: probably should be taking out some lock here.. */ - return _plugin->get_parameter (_list->parameter()); + return _value.to_double(); } boost::shared_ptr @@ -1300,7 +1402,7 @@ PluginInsert::collect_signal_for_analysis (framecnt_t nframes) void PluginInsert::add_plugin (boost::shared_ptr plugin) { - plugin->set_insert_info (this); + plugin->set_insert_id (this->id()); if (_plugins.empty()) { /* first (and probably only) plugin instance - connect to relevant signals