X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;ds=inline;f=libs%2Fardour%2Fplugin_insert.cc;h=b174ceb2fe57ce67d32b669765ae38ab5d03a177;hb=1503db4a28fe01650bb8619f5f38fccb312474ab;hp=b001895e0e7ba86d337d54913472875dedd56261;hpb=9e5b7db89f381c70232fab35dc21fd885863f998;p=ardour.git diff --git a/libs/ardour/plugin_insert.cc b/libs/ardour/plugin_insert.cc index b001895e0e..b174ceb2fe 100644 --- a/libs/ardour/plugin_insert.cc +++ b/libs/ardour/plugin_insert.cc @@ -33,6 +33,7 @@ #include "ardour/debug.h" #include "ardour/event_type_map.h" #include "ardour/ladspa_plugin.h" +#include "ardour/luaproc.h" #include "ardour/plugin.h" #include "ardour/plugin_insert.h" @@ -67,6 +68,10 @@ PluginInsert::PluginInsert (Session& s, boost::shared_ptr plug) : Processor (s, (plug ? plug->name() : string ("toBeRenamed"))) , _signal_analysis_collected_nframes(0) , _signal_analysis_collect_nframes_max(0) + , _no_inplace (false) + , _pending_no_inplace (false) + , _strict_io (false) + , _strict_io_configured (false) { /* the first is the master */ @@ -137,7 +142,10 @@ PluginInsert::output_streams() const PluginInfoPtr info = _plugins.front()->get_info(); - if (info->reconfigurable_io()) { + if (_strict_io_configured) { + return _configured_in; // XXX, check initial configuration + } + else if (info->reconfigurable_io()) { ChanCount out = _plugins.front()->output_streams (); // DEBUG_TRACE (DEBUG::Processors, string_compose ("Plugin insert, reconfigur(able) output streams = %1\n", out)); return out; @@ -250,7 +258,9 @@ PluginInsert::create_automatable_parameters () can_automate (param); boost::shared_ptr list(new AutomationList(param, desc)); - add_control (boost::shared_ptr (new PluginControl(this, param, desc, list))); + boost::shared_ptr 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()); @@ -356,6 +366,7 @@ PluginInsert::flush () void PluginInsert::connect_and_run (BufferSet& bufs, pframes_t nframes, framecnt_t offset, bool with_auto, framepos_t now) { + _no_inplace = _pending_no_inplace; // Calculate if, and how many frames we need to collect for analysis framecnt_t collect_signal_nframes = (_signal_analysis_collect_nframes_max - _signal_analysis_collected_nframes); @@ -366,19 +377,17 @@ PluginInsert::connect_and_run (BufferSet& bufs, pframes_t nframes, framecnt_t of ChanCount const in_streams = input_streams (); ChanCount const out_streams = output_streams (); - ChanMapping in_map (in_streams); - ChanMapping out_map (out_streams); - bool valid; if (_match.method == Split) { + assert (_in_map.size () == 1); /* fix the input mapping so that we have maps for each of the plugin's inputs */ - in_map = ChanMapping (natural_input_streams ()); /* copy the first stream's buffer contents to the others */ /* XXX: audio only */ - uint32_t first_idx = in_map.get (DataType::AUDIO, 0, &valid); + bool valid; + uint32_t first_idx = _in_map[0].get (DataType::AUDIO, 0, &valid); if (valid) { for (uint32_t i = in_streams.n_audio(); i < natural_input_streams().n_audio(); ++i) { - bufs.get_audio(in_map.get (DataType::AUDIO, i, &valid)).read_from(bufs.get_audio(first_idx), nframes, offset, offset); + bufs.get_audio(_in_map[0].get (DataType::AUDIO, i, &valid)).read_from(bufs.get_audio(first_idx), nframes, offset, offset); } } } @@ -438,11 +447,71 @@ PluginInsert::connect_and_run (BufferSet& bufs, pframes_t nframes, framecnt_t of } - for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) { - (*i)->connect_and_run(bufs, in_map, out_map, nframes, offset); - for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) { - in_map.offset_to(*t, natural_input_streams().get(*t)); - out_map.offset_to(*t, natural_output_streams().get(*t)); + if (_no_inplace) { + BufferSet& inplace_bufs = _session.get_noinplace_buffers(); + + uint32_t pc = 0; + for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i, ++pc) { + + ARDOUR::ChanMapping in_map (natural_input_streams()); + ARDOUR::ChanMapping out_map; + ARDOUR::ChanCount mapped; + ARDOUR::ChanCount backmap; + + // map inputs sequentially + for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) { + for (uint32_t in = 0; in < natural_input_streams().get (*t); ++in) { + bool valid; + uint32_t in_idx = _in_map[pc].get (*t, in, &valid); + uint32_t m = mapped.get (*t); + if (valid) { + inplace_bufs.get (*t, m).read_from (bufs.get (*t, in_idx), nframes, offset, offset); + } else { + inplace_bufs.get (*t, m).silence (nframes, offset); + } + mapped.set (*t, m + 1); + } + } + + backmap = mapped; + + // map outputs + for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) { + for (uint32_t out = 0; out < natural_output_streams().get (*t); ++out) { + uint32_t m = mapped.get (*t); + inplace_bufs.get (*t, m).silence (nframes, offset); + out_map.set (*t, out, m); + mapped.set (*t, m + 1); + } + } + + if ((*i)->connect_and_run(inplace_bufs, in_map, out_map, nframes, offset)) { + deactivate (); + } + + // clear output buffers + bufs.silence (nframes, offset); + + // copy back outputs + for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) { + for (uint32_t out = 0; out < natural_output_streams().get (*t); ++out) { + uint32_t m = backmap.get (*t); + bool valid; + uint32_t out_idx = _out_map[pc].get (*t, out, &valid); + if (valid) { + bufs.get (*t, out_idx).read_from (inplace_bufs.get (*t, m), nframes, offset, offset); + } + backmap.set (*t, m + 1); + } + } + } + + } else { + uint32_t pc = 0; + for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i, ++pc) { + if ((*i)->connect_and_run(bufs, _in_map[pc], _out_map[pc], nframes, offset)) { + deactivate (); + } } } @@ -481,13 +550,8 @@ PluginInsert::silence (framecnt_t nframes) return; } - ChanMapping in_map(input_streams()); - ChanMapping out_map(output_streams()); - - if (_match.method == Split) { - /* fix the input mapping so that we have maps for each of the plugin's inputs */ - in_map = ChanMapping (natural_input_streams ()); - } + ChanMapping in_map (natural_input_streams ()); + ChanMapping out_map (natural_output_streams ()); for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) { (*i)->connect_and_run (_session.get_scratch_buffers ((*i)->get_info()->n_inputs, true), in_map, out_map, nframes, 0); @@ -557,7 +621,7 @@ PluginInsert::automation_run (BufferSet& bufs, framepos_t start, pframes_t nfram return; } - if (!find_next_event (now, end, next_event) || requires_fixed_sized_buffers()) { + if (!find_next_event (now, end, next_event) || _plugins.front()->requires_fixed_sized_buffers()) { /* no events have a time within the relevant range */ @@ -669,6 +733,7 @@ boost::shared_ptr PluginInsert::plugin_factory (boost::shared_ptr other) { boost::shared_ptr lp; + boost::shared_ptr lua; #ifdef LV2_SUPPORT boost::shared_ptr lv2p; #endif @@ -684,6 +749,8 @@ PluginInsert::plugin_factory (boost::shared_ptr other) if ((lp = boost::dynamic_pointer_cast (other)) != 0) { return boost::shared_ptr (new LadspaPlugin (*lp)); + } else if ((lua = boost::dynamic_pointer_cast (other)) != 0) { + return boost::shared_ptr (new LuaProc (*lua)); #ifdef LV2_SUPPORT } else if ((lv2p = boost::dynamic_pointer_cast (other)) != 0) { return boost::shared_ptr (new LV2Plugin (*lv2p)); @@ -744,6 +811,24 @@ PluginInsert::configure_io (ChanCount in, ChanCount out) break; } + // TODO make configurable + uint32_t pc = 0; + for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i, ++pc) { + if (_match.method == Split) { + /* TODO see PluginInsert::connect_and_run, channel replication */ + _in_map[pc] = ChanMapping (natural_input_streams ()); + } else { + _in_map[pc] = ChanMapping (input_streams ()); + } + _out_map[pc] = ChanMapping (output_streams()); + + for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) { + _in_map[pc].offset_to(*t, pc * natural_input_streams().get(*t)); + _out_map[pc].offset_to(*t, pc * natural_output_streams().get(*t)); + } + } + + if ( (old_match.method != _match.method && (old_match.method == Split || _match.method == Split)) || old_in != in || old_out != out @@ -788,6 +873,7 @@ PluginInsert::can_support_io_configuration (const ChanCount& in, ChanCount& out) PluginInsert::Match PluginInsert::private_can_support_io_configuration (ChanCount const & inx, ChanCount& out) { + _strict_io_configured = false; if (_plugins.empty()) { return Match(); } @@ -803,6 +889,11 @@ PluginInsert::private_can_support_io_configuration (ChanCount const & inx, ChanC return Match (Impossible, 0); } + if (_strict_io && in.n_audio() < out.n_audio()) { + DEBUG_TRACE (DEBUG::Processors, string_compose ("hiding output ports of reconfigurable %1\n", name())); + out.set (DataType::AUDIO, in.get (DataType::AUDIO)); + } + return Match (Delegate, 1); } @@ -833,7 +924,7 @@ PluginInsert::private_can_support_io_configuration (ChanCount const & inx, ChanC } /* Plugin inputs match requested inputs exactly */ - if (inputs == in) { + if (inputs == in && (!_strict_io || outputs.n_audio() == inputs.n_audio())) { out = outputs + midi_bypass; return Match (ExactMatch, 1); } @@ -888,7 +979,7 @@ PluginInsert::private_can_support_io_configuration (ChanCount const & inx, ChanC plugin inputs? Let me count the ways ... */ - bool can_split = true; + bool can_split = !_strict_io; for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) { bool const can_split_type = (in.get (*t) == 1 && inputs.get (*t) > 1); @@ -924,7 +1015,12 @@ PluginInsert::private_can_support_io_configuration (ChanCount const & inx, ChanC } if (could_hide && !cannot_hide) { - out = outputs + midi_bypass; + if (_strict_io && inputs.get (DataType::AUDIO) == outputs.get (DataType::AUDIO)) { + _strict_io_configured = true; + outputs = inputs; + } else { + out = outputs + midi_bypass; + } return Match (Hide, 1, hide_channels); } @@ -1033,6 +1129,8 @@ PluginInsert::set_state(const XMLNode& node, int version) type = ARDOUR::LXVST; } else if (prop->value() == X_("audiounit")) { type = ARDOUR::AudioUnit; + } else if (prop->value() == X_("luaproc")) { + type = ARDOUR::Lua; } else { error << string_compose (_("unknown plugin type %1 in plugin insert state"), prop->value()) @@ -1094,6 +1192,15 @@ PluginInsert::set_state(const XMLNode& node, int version) return -1; } + if (type == ARDOUR::Lua) { + XMLNode *ls = node.child (plugin->state_node_name().c_str()); + // we need to load the script to set the name and parameters. + boost::shared_ptr lp = boost::dynamic_pointer_cast(plugin); + if (ls && lp) { + lp->set_script_from_state (*ls); + } + } + // The name of the PluginInsert comes from the plugin, nothing else _name = plugin->get_info()->name;