diff options
author | David Robillard <d@drobilla.net> | 2007-06-20 03:05:16 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2007-06-20 03:05:16 +0000 |
commit | 8ae580427987b4eefc102f3e801c1b76fdc74d48 (patch) | |
tree | 52d9ffe3e964bc96d60dae929c5c3c834bccf107 | |
parent | 996d59663f83200c0716f1ba7bccc486d52bee7e (diff) |
Made plugin input/output counts multi-typed (towards MIDI plugins, instruments, etc).
Cleaning up/genericification of Insert interface.
Fixed meter count for pre-fader metering (was # inputs, not # channels at end of pre-fader redirect list).
Work on redirect list stream handling, better error reporting (towards automatically adding 'adaptors' in the future?).
git-svn-id: svn://localhost/ardour2/trunk@2025 d708f5d6-7413-0410-9779-e7cbd77b26cf
-rw-r--r-- | gtk2_ardour/gain_meter.cc | 4 | ||||
-rw-r--r-- | gtk2_ardour/plugin_selector.cc | 4 | ||||
-rw-r--r-- | gtk2_ardour/redirect_box.cc | 26 | ||||
-rw-r--r-- | gtk2_ardour/redirect_box.h | 2 | ||||
-rw-r--r-- | libs/ardour/ardour/chan_count.h | 2 | ||||
-rw-r--r-- | libs/ardour/ardour/insert.h | 26 | ||||
-rw-r--r-- | libs/ardour/ardour/plugin.h | 5 | ||||
-rw-r--r-- | libs/ardour/ardour/route.h | 39 | ||||
-rw-r--r-- | libs/ardour/insert.cc | 192 | ||||
-rw-r--r-- | libs/ardour/plugin_manager.cc | 8 | ||||
-rw-r--r-- | libs/ardour/route.cc | 168 |
11 files changed, 275 insertions, 201 deletions
diff --git a/gtk2_ardour/gain_meter.cc b/gtk2_ardour/gain_meter.cc index c9e26d1b5f..bb925d8f8e 100644 --- a/gtk2_ardour/gain_meter.cc +++ b/gtk2_ardour/gain_meter.cc @@ -425,10 +425,12 @@ GainMeter::setup_meters () if ((r = dynamic_cast<Route*> (_io.get())) != 0) { switch (r->meter_point()) { - case MeterPreFader: case MeterInput: nmeters = r->n_inputs().n_total(); break; + case MeterPreFader: + nmeters = r->pre_fader_streams().n_total(); + break; case MeterPostFader: nmeters = r->n_outputs().n_total(); break; diff --git a/gtk2_ardour/plugin_selector.cc b/gtk2_ardour/plugin_selector.cc index 1283837e0c..7333e45242 100644 --- a/gtk2_ardour/plugin_selector.cc +++ b/gtk2_ardour/plugin_selector.cc @@ -270,8 +270,8 @@ PluginSelector::input_refiller () // Insert into GTK list for (row = 0, i=plugs.begin(); i != plugs.end(); ++i, ++row) { - snprintf (ibuf, sizeof(ibuf)-1, "%d", (*i)->n_inputs); - snprintf (obuf, sizeof(obuf)-1, "%d", (*i)->n_outputs); + snprintf (ibuf, sizeof(ibuf)-1, "%zu", (*i)->n_inputs.n_total()); + snprintf (obuf, sizeof(obuf)-1, "%zu", (*i)->n_outputs.n_total()); Gtk::TreeModel::Row newrow = *(lmodel->append()); newrow[lcols.name] = (*i)->name.c_str(); diff --git a/gtk2_ardour/redirect_box.cc b/gtk2_ardour/redirect_box.cc index 9533cbf782..30bec50a19 100644 --- a/gtk2_ardour/redirect_box.cc +++ b/gtk2_ardour/redirect_box.cc @@ -396,24 +396,24 @@ RedirectBox::insert_plugin_chosen (boost::shared_ptr<Plugin> plugin) redirect->active_changed.connect (bind (mem_fun (*this, &RedirectBox::show_redirect_active_r), boost::weak_ptr<Redirect>(redirect))); - uint32_t err_streams; + Route::InsertStreams err; - if (_route->add_redirect (redirect, this, &err_streams)) { - weird_plugin_dialog (*plugin, err_streams, _route); + if (_route->add_redirect (redirect, this, &err)) { + weird_plugin_dialog (*plugin, err, _route); // XXX SHAREDPTR delete plugin here .. do we even need to care? } } } void -RedirectBox::weird_plugin_dialog (Plugin& p, uint32_t streams, boost::shared_ptr<IO> io) +RedirectBox::weird_plugin_dialog (Plugin& p, Route::InsertStreams streams, boost::shared_ptr<IO> io) { ArdourDialog dialog (_("ardour: weird plugin dialog")); Label label; /* i hate this kind of code */ - if (streams > p.get_info()->n_inputs) { + if (streams.count > p.get_info()->n_inputs) { label.set_text (string_compose (_( "You attempted to add a plugin (%1).\n" "The plugin has %2 inputs\n" @@ -423,9 +423,9 @@ RedirectBox::weird_plugin_dialog (Plugin& p, uint32_t streams, boost::shared_ptr "This makes no sense - you are throwing away\n" "part of the signal."), p.name(), - p.get_info()->n_inputs, - streams)); - } else if (streams < p.get_info()->n_inputs) { + p.get_info()->n_inputs.n_total(), + streams.count.n_total())); + } else if (streams.count < p.get_info()->n_inputs) { label.set_text (string_compose (_( "You attempted to add a plugin (%1).\n" "The plugin has %2 inputs\n" @@ -436,8 +436,8 @@ RedirectBox::weird_plugin_dialog (Plugin& p, uint32_t streams, boost::shared_ptr "side-chain inputs. A future version of Ardour will\n" "support this type of configuration."), p.name(), - p.get_info()->n_inputs, - streams)); + p.get_info()->n_inputs.n_total(), + streams.count.n_total())); } else { label.set_text (string_compose (_( "You attempted to add a plugin (%1).\n" @@ -450,11 +450,11 @@ RedirectBox::weird_plugin_dialog (Plugin& p, uint32_t streams, boost::shared_ptr "\n" "Ardour does not understand what to do in such situations.\n"), p.name(), - p.get_info()->n_inputs, - p.get_info()->n_outputs, + p.get_info()->n_inputs.n_total(), + p.get_info()->n_outputs.n_total(), io->n_inputs().n_total(), io->n_outputs().n_total(), - streams)); + streams.count.n_total())); } dialog.get_vbox()->pack_start (label); diff --git a/gtk2_ardour/redirect_box.h b/gtk2_ardour/redirect_box.h index 089542b041..baf0746723 100644 --- a/gtk2_ardour/redirect_box.h +++ b/gtk2_ardour/redirect_box.h @@ -198,7 +198,7 @@ class RedirectBox : public Gtk::HBox gint idle_delete_redirect (boost::weak_ptr<ARDOUR::Redirect>); - void weird_plugin_dialog (ARDOUR::Plugin& p, uint32_t streams, boost::shared_ptr<ARDOUR::IO> io); + void weird_plugin_dialog (ARDOUR::Plugin& p, ARDOUR::Route::InsertStreams streams, boost::shared_ptr<ARDOUR::IO> io); static RedirectBox* _current_redirect_box; static bool enter_box (GdkEventCrossing*, RedirectBox*); diff --git a/libs/ardour/ardour/chan_count.h b/libs/ardour/ardour/chan_count.h index a859c37b5a..1ed50f7abb 100644 --- a/libs/ardour/ardour/chan_count.h +++ b/libs/ardour/ardour/chan_count.h @@ -47,6 +47,8 @@ public: // -1 is what to_index does. inlined for speed. this should maybe be changed.. inline size_t n_audio() const { return _counts[DataType::AUDIO-1]; } inline size_t n_midi() const { return _counts[DataType::MIDI-1]; } + inline void set_audio(size_t a) { _counts[DataType::AUDIO-1] = a; } + inline void set_midi(size_t m) { _counts[DataType::MIDI-1] = m; } size_t n_total() const { diff --git a/libs/ardour/ardour/insert.h b/libs/ardour/ardour/insert.h index e58cb71754..10902a76b0 100644 --- a/libs/ardour/ardour/insert.h +++ b/libs/ardour/ardour/insert.h @@ -55,9 +55,13 @@ class Insert : public Redirect virtual void activate () {} virtual void deactivate () {} - virtual int32_t can_support_input_configuration (int32_t in) const = 0; - virtual int32_t configure_io (int32_t magic, int32_t in, int32_t out) = 0; - virtual int32_t compute_output_streams (int32_t cnt) const = 0; + virtual bool can_support_input_configuration (ChanCount in) const = 0; + virtual ChanCount output_for_input_configuration (ChanCount in) const = 0; + virtual bool configure_io (ChanCount in, ChanCount out) = 0; + +protected: + bool _configured; + ChanCount _configured_input; }; class PortInsert : public Insert @@ -81,9 +85,9 @@ class PortInsert : public Insert ChanCount output_streams() const; ChanCount input_streams() const; - int32_t can_support_input_configuration (int32_t) const; - int32_t configure_io (int32_t magic, int32_t in, int32_t out); - int32_t compute_output_streams (int32_t cnt) const; + virtual bool can_support_input_configuration (ChanCount in) const; + virtual ChanCount output_for_input_configuration (ChanCount in) const; + virtual bool configure_io (ChanCount in, ChanCount out); uint32_t bit_slot() const { return bitslot; } @@ -118,12 +122,12 @@ class PluginInsert : public Insert ChanCount natural_output_streams() const; ChanCount natural_input_streams() const; - int set_count (uint32_t num); + bool set_count (uint32_t num); uint32_t get_count () const { return _plugins.size(); } - int32_t can_support_input_configuration (int32_t) const; - int32_t configure_io (int32_t magic, int32_t in, int32_t out); - int32_t compute_output_streams (int32_t cnt) const; + virtual bool can_support_input_configuration (ChanCount in) const; + virtual ChanCount output_for_input_configuration (ChanCount in) const; + virtual bool configure_io (ChanCount in, ChanCount out); bool is_generator() const; @@ -166,6 +170,8 @@ class PluginInsert : public Insert void auto_state_changed (uint32_t which); void automation_list_creation_callback (uint32_t, AutomationList&); + int32_t count_for_configuration (ChanCount in, ChanCount out) const; + boost::shared_ptr<Plugin> plugin_factory (boost::shared_ptr<Plugin>); }; diff --git a/libs/ardour/ardour/plugin.h b/libs/ardour/ardour/plugin.h index feb86f1b7b..b1a2823b33 100644 --- a/libs/ardour/ardour/plugin.h +++ b/libs/ardour/ardour/plugin.h @@ -28,6 +28,7 @@ #include <jack/types.h> #include <ardour/types.h> +#include <ardour/chan_count.h> #include <ardour/plugin_state.h> #include <ardour/cycles.h> @@ -60,8 +61,8 @@ class PluginInfo { string name; string category; - uint32_t n_inputs; - uint32_t n_outputs; + ChanCount n_inputs; + ChanCount n_outputs; ARDOUR::PluginType type; long unique_id; diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h index ed839f091b..b5d1fa03d6 100644 --- a/libs/ardour/ardour/route.h +++ b/libs/ardour/ardour/route.h @@ -159,15 +159,23 @@ class Route : public IO } ChanCount max_redirect_outs () const { return redirect_max_outs; } + ChanCount pre_fader_streams() const; - // FIXME: remove/replace err_streams parameters with something appropriate - // they are used by 'wierd_plugin_dialog'(sic) to display the number of input streams - // at the insertion point if the insert fails - int add_redirect (boost::shared_ptr<Redirect>, void *src, uint32_t* err_streams = 0); - int add_redirects (const RedirectList&, void *src, uint32_t* err_streams = 0); - int remove_redirect (boost::shared_ptr<Redirect>, void *src, uint32_t* err_streams = 0); - int copy_redirects (const Route&, Placement, uint32_t* err_streams = 0); - int sort_redirects (uint32_t* err_streams = 0); + /** A record of the stream configuration at some point in the redirect list. + * Used to return where and why a redirect list configuration request failed. + */ + struct InsertStreams { + InsertStreams(size_t i=0, ChanCount c=ChanCount()) : index(i), count(c) {} + + size_t index; ///< Index of redirect where configuration failed + ChanCount count; ///< Input requested of redirect + }; + + int add_redirect (boost::shared_ptr<Redirect>, void *src, InsertStreams* err = 0); + int add_redirects (const RedirectList&, void *src, InsertStreams* err = 0); + int remove_redirect (boost::shared_ptr<Redirect>, void *src, InsertStreams* err = 0); + int copy_redirects (const Route&, Placement, InsertStreams* err = 0); + int sort_redirects (InsertStreams* err = 0); void disable_redirects (Placement); void disable_redirects (); void disable_plugins (Placement); @@ -347,22 +355,21 @@ class Route : public IO void output_change_handler (IOChange, void *src); bool legal_redirect (Redirect&); - int reset_plugin_counts (uint32_t*); /* locked */ - int _reset_plugin_counts (uint32_t*); /* unlocked */ + int reset_plugin_counts (InsertStreams*); /* locked */ + int _reset_plugin_counts (InsertStreams*); /* unlocked */ - /* plugin count handling */ + /* insert I/O channels and plugin count handling */ struct InsertCount { boost::shared_ptr<ARDOUR::Insert> insert; - int32_t cnt; - int32_t in; - int32_t out; + ChanCount in; + ChanCount out; - InsertCount (boost::shared_ptr<ARDOUR::Insert> ins) : insert (ins), cnt (-1) {} + InsertCount (boost::shared_ptr<ARDOUR::Insert> ins) : insert(ins) {} }; int32_t apply_some_plugin_counts (std::list<InsertCount>& iclist); - int32_t check_some_plugin_counts (std::list<InsertCount>& iclist, int32_t required_inputs, uint32_t* err_streams); + bool check_some_plugin_counts (std::list<InsertCount>& iclist, ChanCount required_inputs, InsertStreams* err_streams); void set_deferred_state (); void add_redirect_from_xml (const XMLNode&); diff --git a/libs/ardour/insert.cc b/libs/ardour/insert.cc index f08661b06a..88a5c1a14d 100644 --- a/libs/ardour/insert.cc +++ b/libs/ardour/insert.cc @@ -53,11 +53,13 @@ using namespace PBD; * Inserts are still definitely audio only */ Insert::Insert(Session& s, string name, Placement p) : Redirect (s, name, p) + , _configured(false) { } Insert::Insert(Session& s, string name, Placement p, int imin, int imax, int omin, int omax) : Redirect (s, name, p, imin, imax, omin, omax) + , _configured(false) { } @@ -121,7 +123,7 @@ PluginInsert::PluginInsert (const PluginInsert& other) RedirectCreated (this); /* EMIT SIGNAL */ } -int +bool PluginInsert::set_count (uint32_t num) { bool require_state = !_plugins.empty(); @@ -131,7 +133,7 @@ PluginInsert::set_count (uint32_t num) */ if (num == 0) { - return -1; + return false; } else if (num > _plugins.size()) { uint32_t diff = num - _plugins.size(); @@ -150,7 +152,7 @@ PluginInsert::set_count (uint32_t num) } } - return 0; + return true; } void @@ -185,29 +187,31 @@ PluginInsert::auto_state_changed (uint32_t which) ChanCount PluginInsert::output_streams() const { - // FIXME: TYPE - return ChanCount(DataType::AUDIO, _plugins[0]->get_info()->n_outputs * _plugins.size()); + if (_configured) + return output_for_input_configuration(_configured_input); + else + return natural_output_streams(); } ChanCount PluginInsert::input_streams() const { - // FIXME: TYPE - return ChanCount(DataType::AUDIO, _plugins[0]->get_info()->n_inputs * _plugins.size()); + if (_configured) + return _configured_input; + else + return natural_input_streams(); } ChanCount PluginInsert::natural_output_streams() const { - // FIXME: TYPE - return ChanCount(DataType::AUDIO, _plugins[0]->get_info()->n_outputs); + return _plugins[0]->get_info()->n_outputs; } ChanCount PluginInsert::natural_input_streams() const { - // FIXME: TYPE - return ChanCount(DataType::AUDIO, _plugins[0]->get_info()->n_inputs); + return _plugins[0]->get_info()->n_inputs; } bool @@ -217,7 +221,7 @@ PluginInsert::is_generator() const a specific "instrument" flag, for example. */ - return _plugins[0]->get_info()->n_inputs == 0; + return _plugins[0]->get_info()->n_inputs.n_audio() == 0; } void @@ -349,12 +353,9 @@ PluginInsert::silence (nframes_t nframes, nframes_t offset) uint32_t in_index = 0; uint32_t out_index = 0; - uint32_t n; - if (active()) { for (vector<boost::shared_ptr<Plugin> >::iterator i = _plugins.begin(); i != _plugins.end(); ++i) { - n = (*i) -> get_info()->n_inputs; - (*i)->connect_and_run (_session.get_silent_buffers (ChanCount(DataType::AUDIO, n)), in_index, out_index, nframes, offset); + (*i)->connect_and_run (_session.get_silent_buffers ((*i)->get_info()->n_inputs), in_index, out_index, nframes, offset); } } } @@ -370,8 +371,8 @@ PluginInsert::run (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, connect_and_run (bufs, nframes, offset, false); } } else { - uint32_t in = _plugins[0]->get_info()->n_inputs; - uint32_t out = _plugins[0]->get_info()->n_outputs; + uint32_t in = _plugins[0]->get_info()->n_inputs.n_audio(); + uint32_t out = _plugins[0]->get_info()->n_outputs.n_audio(); if (out > in) { @@ -382,7 +383,7 @@ PluginInsert::run (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, } } - bufs.count().set(DataType::AUDIO, out); + bufs.count().set(_default_type, out); } } @@ -534,36 +535,98 @@ PluginInsert::plugin_factory (boost::shared_ptr<Plugin> other) return boost::shared_ptr<Plugin> ((Plugin*) 0); } -int32_t -PluginInsert::compute_output_streams (int32_t cnt) const +bool +PluginInsert::configure_io (ChanCount in, ChanCount out) { - return _plugins[0]->get_info()->n_outputs * cnt; + ChanCount matching_out = output_for_input_configuration(out); + if (matching_out != out) { + _configured = false; + return false; + } else { + bool success = set_count (count_for_configuration(in, out)); + if (success) { + _configured = true; + _configured_input = in; + } + return success; + } } -int32_t -PluginInsert::configure_io (int32_t magic, int32_t in, int32_t out) +bool +PluginInsert::can_support_input_configuration (ChanCount in_count) const { - return set_count (magic); + int32_t outputs = _plugins[0]->get_info()->n_outputs.get(_default_type); + int32_t inputs = _plugins[0]->get_info()->n_inputs.get(_default_type); + int32_t in = in_count.get(_default_type); + + /* see output_for_input_configuration below */ + if ((inputs == 0) + || (outputs == 1 && inputs == 1) + || (inputs == in) + || ((inputs < in) && (inputs % in == 0))) { + return true; + } else { + return false; + } } -int32_t -PluginInsert::can_support_input_configuration (int32_t in) const +ChanCount +PluginInsert::output_for_input_configuration (ChanCount in) const { - int32_t outputs = _plugins[0]->get_info()->n_outputs; - int32_t inputs = _plugins[0]->get_info()->n_inputs; + ChanCount outputs = _plugins[0]->get_info()->n_outputs; + ChanCount inputs = _plugins[0]->get_info()->n_inputs; + + if (inputs.n_total() == 0) { + /* instrument plugin, always legal, but throws away any existing streams */ + return outputs; + } + + if (inputs.n_total() == 1 && outputs == inputs) { + /* mono plugin, replicate as needed to match in */ + return in; + } + + if (inputs == in) { + /* exact match */ + return outputs; + } - if (inputs == 0) { + // FIXME: single type plugins only. can we do this for instruments? + if ((inputs.n_total() == inputs.get(_default_type)) + && ((in.n_total() == in.get(_default_type)) + && (inputs.n_total() < in.n_total()) + && (inputs.n_total() % in.n_total() == 0))) { - /* instrument plugin, always legal, but it throws - away any existing active streams. + /* number of inputs is a factor of the requested input + configuration, so we can replicate. */ + return ChanCount(_default_type, in.n_total() / inputs.n_total()); + } + + /* sorry */ + return ChanCount(); +} + +/* Number of plugin instances required to support a given channel configuration. + * (private helper) + */ +int32_t +PluginInsert::count_for_configuration (ChanCount in, ChanCount out) const +{ + // FIXME: take 'out' into consideration + + ChanCount outputs = _plugins[0]->get_info()->n_outputs; + ChanCount inputs = _plugins[0]->get_info()->n_inputs; + + if (inputs.n_total() == 0) { + /* instrument plugin, always legal, but throws away any existing streams */ return 1; } - if (outputs == 1 && inputs == 1) { - /* mono plugin, replicate as needed */ - return in; + if (inputs.n_total() == 1 && outputs == inputs) { + /* mono plugin, replicate as needed to match in */ + return in.n_total(); } if (inputs == in) { @@ -571,18 +634,21 @@ PluginInsert::can_support_input_configuration (int32_t in) const return 1; } - if ((inputs < in) && (inputs % in == 0)) { + // FIXME: single type plugins only. can we do this for instruments? + if ((inputs.n_total() == inputs.get(_default_type)) + && ((in.n_total() == in.get(_default_type)) + && (inputs.n_total() < in.n_total()) + && (inputs.n_total() % in.n_total() == 0))) { /* number of inputs is a factor of the requested input configuration, so we can replicate. */ - return in/inputs; + return in.n_total() / inputs.n_total(); } /* sorry */ - - return -1; + return 0; } XMLNode& @@ -970,14 +1036,14 @@ PortInsert::latency() return _session.engine().frames_per_cycle() + input_latency(); } -int32_t -PortInsert::can_support_input_configuration (int32_t in) const +bool +PortInsert::can_support_input_configuration (ChanCount in) const { if (input_maximum() == ChanCount::INFINITE && output_maximum() == ChanCount::INFINITE) { /* not configured yet */ - return 1; /* we can support anything the first time we're asked */ + return true; /* we can support anything the first time we're asked */ } else { @@ -985,16 +1051,23 @@ PortInsert::can_support_input_configuration (int32_t in) const many output ports it will have. */ - if (output_maximum().get(_default_type) == static_cast<uint32_t>(in)) { - return 1; + if (output_maximum() == in) { + + return true; } } - return -1; + return false; } -int32_t -PortInsert::configure_io (int32_t ignored_magic, int32_t in, int32_t out) +ChanCount +PortInsert::output_for_input_configuration (ChanCount in) const +{ + return in; +} + +bool +PortInsert::configure_io (ChanCount in, ChanCount out) { /* do not allow configuration to be changed outside the range of the last request config. or something like that. @@ -1010,27 +1083,12 @@ PortInsert::configure_io (int32_t ignored_magic, int32_t in, int32_t out) to the number of input ports we need. */ - set_output_maximum (ChanCount(_default_type, in)); - set_output_minimum (ChanCount(_default_type, in)); - set_input_maximum (ChanCount(_default_type, out)); - set_input_minimum (ChanCount(_default_type, out)); - - if (in < 0) { - in = n_outputs ().get(_default_type); - } + set_output_maximum (in); + set_output_minimum (in); + set_input_maximum (out); + set_input_minimum (out); - if (out < 0) { - out = n_inputs ().get(_default_type); - } - - return ensure_io (ChanCount(_default_type, out), ChanCount(_default_type, in), false, this); -} - -int32_t -PortInsert::compute_output_streams (int32_t cnt) const -{ - /* puzzling, eh? think about it ... */ - return n_inputs ().get(_default_type); + return (ensure_io (out, in, false, this) == 0); } ChanCount diff --git a/libs/ardour/plugin_manager.cc b/libs/ardour/plugin_manager.cc index 9af7ad0451..02cba7dd94 100644 --- a/libs/ardour/plugin_manager.cc +++ b/libs/ardour/plugin_manager.cc @@ -253,18 +253,18 @@ PluginManager::ladspa_discover (string path) info->category = get_ladspa_category(descriptor->UniqueID); info->path = path; info->index = i; - info->n_inputs = 0; - info->n_outputs = 0; + info->n_inputs = ChanCount(); + info->n_outputs = ChanCount(); info->type = ARDOUR::LADSPA; info->unique_id = descriptor->UniqueID; for (uint32_t n=0; n < descriptor->PortCount; ++n) { if ( LADSPA_IS_PORT_AUDIO (descriptor->PortDescriptors[n]) ) { if ( LADSPA_IS_PORT_INPUT (descriptor->PortDescriptors[n]) ) { - info->n_inputs++; + info->n_inputs.set_audio(info->n_inputs.n_audio() + 1); } else if ( LADSPA_IS_PORT_OUTPUT (descriptor->PortDescriptors[n]) ) { - info->n_outputs++; + info->n_outputs.set_audio(info->n_outputs.n_audio() + 1); } } } diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index 49870abf37..d77dc46b0c 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -773,7 +773,7 @@ Route::set_mute (bool yn, void *src) } int -Route::add_redirect (boost::shared_ptr<Redirect> redirect, void *src, uint32_t* err_streams) +Route::add_redirect (boost::shared_ptr<Redirect> redirect, void *src, InsertStreams* err) { ChanCount old_rmo = redirect_max_outs; @@ -792,7 +792,7 @@ Route::add_redirect (boost::shared_ptr<Redirect> redirect, void *src, uint32_t* if ((pi = boost::dynamic_pointer_cast<PluginInsert>(redirect)) != 0) { pi->set_count (1); - if (pi->input_streams() == ChanCount::ZERO) { + if (pi->natural_input_streams() == ChanCount::ZERO) { /* generator plugin */ _have_internal_generator = true; } @@ -814,18 +814,19 @@ Route::add_redirect (boost::shared_ptr<Redirect> redirect, void *src, uint32_t* porti->ensure_io (n_outputs (), n_inputs(), false, this); } - // Ensure peak vector sizes before the plugin is activated - ChanCount potential_max_streams = max(redirect->input_streams(), redirect->output_streams()); - _meter->setup(potential_max_streams); - _redirects.push_back (redirect); - if (_reset_plugin_counts (err_streams)) { + // Set up redirect list channels. This will set redirect->[input|output]_streams() + if (_reset_plugin_counts (err)) { _redirects.pop_back (); _reset_plugin_counts (0); // it worked before we tried to add it ... return -1; } + // Ensure peak vector sizes before the plugin is activated + ChanCount potential_max_streams = max(redirect->input_streams(), redirect->output_streams()); + _meter->setup(potential_max_streams); + redirect->activate (); redirect->active_changed.connect (mem_fun (*this, &Route::redirect_active_proxy)); } @@ -840,7 +841,7 @@ Route::add_redirect (boost::shared_ptr<Redirect> redirect, void *src, uint32_t* } int -Route::add_redirects (const RedirectList& others, void *src, uint32_t* err_streams) +Route::add_redirects (const RedirectList& others, void *src, InsertStreams* err) { ChanCount old_rmo = redirect_max_outs; @@ -873,7 +874,7 @@ Route::add_redirects (const RedirectList& others, void *src, uint32_t* err_strea _redirects.push_back (*i); - if (_reset_plugin_counts (err_streams)) { + if (_reset_plugin_counts (err)) { ++existing_end; _redirects.erase (existing_end, _redirects.end()); _reset_plugin_counts (0); // it worked before we tried to add it ... @@ -996,6 +997,28 @@ Route::ab_plugins (bool forward) } } } + + +/* Figure out the streams that will feed into PreFader */ +ChanCount +Route::pre_fader_streams() const +{ + boost::shared_ptr<Redirect> redirect; + + // Find the last pre-fader redirect + for (RedirectList::const_iterator r = _redirects.begin(); r != _redirects.end(); ++r) { + if ((*r)->placement() == PreFader) { + redirect = *r; + } + } + + if (redirect) { + return redirect->output_streams(); + } else { + return n_inputs (); + } +} + /** Remove redirects with a given placement. * @param p Placement of redirects to remove. @@ -1037,7 +1060,7 @@ Route::clear_redirects (Placement p, void *src) } int -Route::remove_redirect (boost::shared_ptr<Redirect> redirect, void *src, uint32_t* err_streams) +Route::remove_redirect (boost::shared_ptr<Redirect> redirect, void *src, InsertStreams* err) { ChanCount old_rmo = redirect_max_outs; @@ -1093,7 +1116,7 @@ Route::remove_redirect (boost::shared_ptr<Redirect> redirect, void *src, uint32_ return 1; } - if (_reset_plugin_counts (err_streams)) { + if (_reset_plugin_counts (err)) { /* get back to where we where */ _redirects.insert (i, redirect); /* we know this will work, because it worked before :) */ @@ -1127,92 +1150,52 @@ Route::remove_redirect (boost::shared_ptr<Redirect> redirect, void *src, uint32_ } int -Route::reset_plugin_counts (uint32_t* lpc) +Route::reset_plugin_counts (InsertStreams* err) { Glib::RWLock::WriterLock lm (redirect_lock); - return _reset_plugin_counts (lpc); + return _reset_plugin_counts (err); } int -Route::_reset_plugin_counts (uint32_t* err_streams) +Route::_reset_plugin_counts (InsertStreams* err) { RedirectList::iterator r; - uint32_t i_cnt; - uint32_t s_cnt; map<Placement,list<InsertCount> > insert_map; - nframes_t initial_streams; - - redirect_max_outs.reset(); - i_cnt = 0; - s_cnt = 0; + ChanCount initial_streams; + /* Process each placement in order, checking to see if we + can really do what has been requested. + */ + /* divide inserts up by placement so we get the signal flow properly modelled. we need to do this because the _redirects - list is not sorted by placement, and because other reasons may - exist now or in the future for this separate treatment. + list is not sorted by placement */ + + /* ... but it should/will be... */ for (r = _redirects.begin(); r != _redirects.end(); ++r) { boost::shared_ptr<Insert> insert; - /* do this here in case we bomb out before we get to the end of - this function. - */ - - redirect_max_outs = max ((*r)->output_streams (), redirect_max_outs); - if ((insert = boost::dynamic_pointer_cast<Insert>(*r)) != 0) { - ++i_cnt; insert_map[insert->placement()].push_back (InsertCount (insert)); - - /* reset plugin counts back to one for now so - that we have a predictable, controlled - state to try to configure. - */ - - boost::shared_ptr<PluginInsert> pi; - - if ((pi = boost::dynamic_pointer_cast<PluginInsert>(insert)) != 0) { - pi->set_count (1); - } - - } else if (boost::dynamic_pointer_cast<Send> (*r) != 0) { - ++s_cnt; } } - if (i_cnt == 0) { - if (s_cnt) { - goto recompute; - } else { - return 0; - } - } - - /* Now process each placement in order, checking to see if we - can really do what has been requested. - */ /* A: PreFader */ - if (check_some_plugin_counts (insert_map[PreFader], n_inputs ().get(_default_type), err_streams)) { + if ( ! check_some_plugin_counts (insert_map[PreFader], n_inputs (), err)) { return -1; } - /* figure out the streams that will feed into PreFader */ - - if (!insert_map[PreFader].empty()) { - InsertCount& ic (insert_map[PreFader].back()); - initial_streams = ic.insert->compute_output_streams (ic.cnt); - } else { - initial_streams = n_inputs ().get(_default_type); - } + ChanCount post_fader_input = (err ? err->count : n_inputs()); /* B: PostFader */ - if (check_some_plugin_counts (insert_map[PostFader], initial_streams, err_streams)) { + if ( ! check_some_plugin_counts (insert_map[PostFader], post_fader_input, err)) { return -1; } @@ -1223,8 +1206,6 @@ Route::_reset_plugin_counts (uint32_t* err_streams) /* recompute max outs of any redirect */ - recompute: - redirect_max_outs.reset(); RedirectList::iterator prev = _redirects.end(); @@ -1261,7 +1242,7 @@ Route::apply_some_plugin_counts (list<InsertCount>& iclist) for (i = iclist.begin(); i != iclist.end(); ++i) { - if ((*i).insert->configure_io ((*i).cnt, (*i).in, (*i).out)) { + if ((*i).insert->configure_io ((*i).in, (*i).out)) { return -1; } /* make sure that however many we have, they are all active */ @@ -1271,38 +1252,55 @@ Route::apply_some_plugin_counts (list<InsertCount>& iclist) return 0; } -int32_t -Route::check_some_plugin_counts (list<InsertCount>& iclist, int32_t required_inputs, uint32_t* err_streams) +/** Returns whether \a iclist can be configured and run starting with + * \a required_inputs at the first insert's inputs. + * If false is returned, \a iclist can not be run with \a required_inputs, and \a err is set. + * Otherwise, \a err is set to the output of the list. + */ +bool +Route::check_some_plugin_counts (list<InsertCount>& iclist, ChanCount required_inputs, InsertStreams* err) { list<InsertCount>::iterator i; - + size_t index = 0; + + if (err) { + err->index = 0; + err->count = required_inputs; + } + for (i = iclist.begin(); i != iclist.end(); ++i) { - if (((*i).cnt = (*i).insert->can_support_input_configuration (required_inputs)) < 0) { - if (err_streams) { - *err_streams = required_inputs; + if ((*i).insert->can_support_input_configuration (required_inputs) < 0) { + if (err) { + err->index = index; + err->count = required_inputs; } - return -1; + return false; } (*i).in = required_inputs; - (*i).out = (*i).insert->compute_output_streams ((*i).cnt); + (*i).out = (*i).insert->output_for_input_configuration (required_inputs); required_inputs = (*i).out; + + ++index; + } + + if (err) { + if (!iclist.empty()) { + err->index = index; + err->count = iclist.back().insert->output_for_input_configuration(required_inputs); + } } - return 0; + return true; } int -Route::copy_redirects (const Route& other, Placement placement, uint32_t* err_streams) +Route::copy_redirects (const Route& other, Placement placement, InsertStreams* err) { ChanCount old_rmo = redirect_max_outs; - if (err_streams) { - *err_streams = 0; - } - RedirectList to_be_deleted; { @@ -1336,7 +1334,7 @@ Route::copy_redirects (const Route& other, Placement placement, uint32_t* err_st /* reset plugin stream handling */ - if (_reset_plugin_counts (err_streams)) { + if (_reset_plugin_counts (err)) { /* FAILED COPY ATTEMPT: we have to restore order */ @@ -1421,7 +1419,7 @@ struct RedirectSorter { }; int -Route::sort_redirects (uint32_t* err_streams) +Route::sort_redirects (InsertStreams* err) { { RedirectSorter comparator; @@ -1434,7 +1432,7 @@ Route::sort_redirects (uint32_t* err_streams) _redirects.sort (comparator); - if (_reset_plugin_counts (err_streams)) { + if (_reset_plugin_counts (err)) { _redirects = as_it_was_before; redirect_max_outs = old_rmo; return -1; |