return pip->n_inputs.n_midi() != 0 && pip->n_outputs.n_audio() != 0;
}
+bool
+PluginInsert::has_output_presets (ChanCount in, ChanCount out)
+{
+ if (!_configured && _plugins[0]->get_info ()->reconfigurable_io ()) {
+ // collect possible configurations, prefer given in/out
+ _plugins[0]->can_support_io_configuration (in, out);
+ }
+
+ PluginOutputConfiguration ppc (_plugins[0]->possible_output ());
+
+ if (ppc.size () == 0) {
+ return false;
+ }
+ if (!strict_io () && ppc.size () == 1) {
+ return false;
+ }
+
+ if (strict_io () && ppc.size () == 1) {
+ // "stereo" is currently preferred default for instruments
+ if (ppc.find (2) != ppc.end ()) {
+ return false;
+ }
+ }
+ if (!needs_midi_input ()) {
+ return false;
+ }
+ return true;
+}
+
void
PluginInsert::create_automatable_parameters ()
{
assert (!_plugins.empty());
+ boost::shared_ptr<Plugin> plugin = _plugins.front();
set<Evoral::Parameter> a = _plugins.front()->automatable ();
- for (set<Evoral::Parameter>::iterator i = a.begin(); i != a.end(); ++i) {
- if (i->type() == PluginAutomation) {
+ for (uint32_t i = 0; i < plugin->parameter_count(); ++i) {
+ if (!plugin->parameter_is_control (i) || !plugin->parameter_is_input (i)) {
+ continue;
+ }
+ Evoral::Parameter param (PluginAutomation, 0, i);
- Evoral::Parameter param(*i);
+ ParameterDescriptor desc;
+ plugin->get_parameter_descriptor(i, desc);
- ParameterDescriptor desc;
- _plugins.front()->get_parameter_descriptor(i->id(), desc);
+ const bool automatable = a.find(param) != a.end();
+ if (automatable) {
can_automate (param);
- boost::shared_ptr<AutomationList> list(new AutomationList(param, desc));
- boost::shared_ptr<AutomationControl> c (new PluginControl(this, param, desc, list));
- add_control (c);
- _plugins.front()->set_automation_control (i->id(), c);
- } 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<AutomationList> list;
- 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<AutomationList> list(new AutomationList(param, desc));
+ boost::shared_ptr<AutomationControl> c (new PluginControl(this, param, desc, list));
+ if (!automatable) {
+ c->set_flags (Controllable::Flag ((int)c->flags() | Controllable::NotAutomatable));
+ }
+ add_control (c);
+ plugin->set_automation_control (i, c);
+ }
+
+ const Plugin::PropertyDescriptors& pdl (plugin->get_supported_properties ());
+ for (Plugin::PropertyDescriptors::const_iterator p = pdl.begin(); p != pdl.end(); ++p) {
+ Evoral::Parameter param (PluginPropertyAutomation, 0, p->first);
+ const ParameterDescriptor& desc = plugin->get_property_descriptor(param.id());
+ if (desc.datatype != Variant::NOTHING) {
+ boost::shared_ptr<AutomationList> list;
+ 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)));
}
}
}
//std::cerr << " streams " << internal_input_streams().n_audio() << std::endl;
//std::cerr << "filling buffer with " << collect_signal_nframes << " frames at " << _signal_analysis_collected_nframes << std::endl;
- _signal_analysis_inputs.set_count(internal_input_streams());
+ _signal_analysis_inputs.set_count(input_streams());
- for (uint32_t i = 0; i < internal_input_streams().n_audio(); ++i) {
- _signal_analysis_inputs.get_audio(i).read_from(
+ for (uint32_t i = 0; i < input_streams().n_audio(); ++i) {
+ _signal_analysis_inputs.get_audio(i).read_from (
bufs.get_audio(i),
collect_signal_nframes,
_signal_analysis_collected_nframes); // offset is for target buffer
//std::cerr << " output, bufs " << bufs.count().n_audio() << " count, " << bufs.available().n_audio() << " available" << std::endl;
//std::cerr << " streams " << internal_output_streams().n_audio() << std::endl;
- _signal_analysis_outputs.set_count(internal_output_streams());
+ _signal_analysis_outputs.set_count(output_streams());
- for (uint32_t i = 0; i < internal_output_streams().n_audio(); ++i) {
+ for (uint32_t i = 0; i < output_streams().n_audio(); ++i) {
_signal_analysis_outputs.get_audio(i).read_from(
bufs.get_audio(i),
collect_signal_nframes,
}
}
+bool
+PluginInsert::pre_seed (const ChanCount& in, const ChanCount& out,
+ const ChanMapping& im, const ChanMapping& om, const ChanMapping& tm)
+{
+ if (_configured) { return false; }
+ _configured_in = in;
+ _configured_out = out;
+ _in_map[0] = im;
+ _out_map[0] = om;
+ _thru_map = tm;
+ _maps_from_state = in.n_total () > 0 && out.n_total () > 0;
+ return true;
+}
+
ChanMapping
PluginInsert::input_map () const
{
inplace_ok = false;
}
}
+
+ if (inplace_ok) {
+ /* check if every output is fed by the corresponding input
+ *
+ * this prevents in-port 1 -> sink-pin 2 || source-pin 1 -> out port 1, source-pin 2 -> out port 2
+ * (with in-place, source-pin 1 -> out port 1 overwrites in-port 1)
+ *
+ * but allows in-port 1 -> sink-pin 2 || source-pin 2 -> out port 1
+ */
+ ChanMapping in_map (input_map ());
+ const ChanMapping::Mappings out_m (output_map ().mappings ());
+ for (ChanMapping::Mappings::const_iterator t = out_m.begin (); t != out_m.end () && inplace_ok; ++t) {
+ for (ChanMapping::TypeMapping::const_iterator c = (*t).second.begin (); c != (*t).second.end () ; ++c) {
+ /* src-pin: c->first, out-port: c->second */
+ bool valid;
+ uint32_t in_port = in_map.get (t->first, c->first, &valid);
+ if (valid && in_port != c->second) {
+ inplace_ok = false;
+ break;
+ }
+ }
+ }
+ }
+
DEBUG_TRACE (DEBUG::ChanMapping, string_compose ("%1: %2\n", name(), inplace_ok ? "In-Place" : "No Inplace Processing"));
return !inplace_ok; // no-inplace
}
// buffers and the analyser makes sure it gets enough data for the
// analysis window
session().ensure_buffer_set (_signal_analysis_inputs, in);
- //_signal_analysis_inputs.set_count (in);
+ _signal_analysis_inputs.set_count (in);
session().ensure_buffer_set (_signal_analysis_outputs, out);
- //_signal_analysis_outputs.set_count (out);
+ _signal_analysis_outputs.set_count (out);
// std::cerr << "set counts to i" << in.n_audio() << "/o" << out.n_audio() << std::endl;
// houston, we have a problem.
return Match (Impossible, 0);
}
+ // midi bypass
+ if (inx.n_midi () > 0 && out.n_midi () == 0) { out.set (DataType::MIDI, 1); }
return Match (Delegate, 1, _strict_io);
}
if (!r) {
return Match (Impossible, 0);
}
+ // midi bypass
+ if (in.n_midi () > 0 && out.n_midi () == 0) { out.set (DataType::MIDI, 1); }
return Match (Delegate, 1);
}
list->set_interpolation(Evoral::ControlList::Discrete);
}
}
-
- if (desc.toggled) {
- set_flags(Controllable::Toggle);
- }
}
/** @param val `user' value */
-void
-PluginInsert::PluginControl::set_value (double user_val, PBD::Controllable::GroupControlDisposition group_override)
-{
- if (writable()) {
- _set_value (user_val, group_override);
- }
-}
-void
-PluginInsert::PluginControl::set_value_unchecked (double user_val)
-{
- /* used only by automation playback */
- _set_value (user_val, Controllable::NoGroup);
-}
void
-PluginInsert::PluginControl::_set_value (double user_val, PBD::Controllable::GroupControlDisposition group_override)
+PluginInsert::PluginControl::actually_set_value (double user_val, PBD::Controllable::GroupControlDisposition group_override)
{
/* FIXME: probably should be taking out some lock here.. */
iasp->set_parameter (_list->parameter().id(), user_val);
}
- AutomationControl::set_value (user_val, group_override);
+ AutomationControl::actually_set_value (user_val, group_override);
}
void
PluginInsert::PluginControl::catch_up_with_external_value (double user_val)
{
- AutomationControl::set_value (user_val, Controllable::NoGroup);
+ AutomationControl::actually_set_value (user_val, Controllable::NoGroup);
}
XMLNode&
alist()->set_yrange (desc.lower, desc.upper);
alist()->reset_default (desc.normal);
}
-
- if (desc.toggled) {
- set_flags(Controllable::Toggle);
- }
}
void
-PluginInsert::PluginPropertyControl::set_value (double user_val, PBD::Controllable::GroupControlDisposition /* group_override*/)
-{
- if (writable()) {
- set_value_unchecked (user_val);
- }
-}
-
-void
-PluginInsert::PluginPropertyControl::set_value_unchecked (double user_val)
+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
}
_value = value;
- AutomationControl::set_value (user_val, Controllable::NoGroup);
+
+ AutomationControl::actually_set_value (user_val, gcd);
}
XMLNode&
{
// called from outside the audio thread, so this should be safe
// only do audio as analysis is (currently) only for audio plugins
- _signal_analysis_inputs.ensure_buffers( DataType::AUDIO, internal_input_streams().n_audio(), nframes);
- _signal_analysis_outputs.ensure_buffers( DataType::AUDIO, internal_output_streams().n_audio(), nframes);
+ _signal_analysis_inputs.ensure_buffers (DataType::AUDIO, input_streams().n_audio(), nframes);
+ _signal_analysis_outputs.ensure_buffers (DataType::AUDIO, output_streams().n_audio(), nframes);
_signal_analysis_collected_nframes = 0;
_signal_analysis_collect_nframes_max = nframes;