summaryrefslogtreecommitdiff
path: root/libs/ardour
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2007-06-20 03:05:16 +0000
committerDavid Robillard <d@drobilla.net>2007-06-20 03:05:16 +0000
commit8ae580427987b4eefc102f3e801c1b76fdc74d48 (patch)
tree52d9ffe3e964bc96d60dae929c5c3c834bccf107 /libs/ardour
parent996d59663f83200c0716f1ba7bccc486d52bee7e (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
Diffstat (limited to 'libs/ardour')
-rw-r--r--libs/ardour/ardour/chan_count.h2
-rw-r--r--libs/ardour/ardour/insert.h26
-rw-r--r--libs/ardour/ardour/plugin.h5
-rw-r--r--libs/ardour/ardour/route.h39
-rw-r--r--libs/ardour/insert.cc192
-rw-r--r--libs/ardour/plugin_manager.cc8
-rw-r--r--libs/ardour/route.cc168
7 files changed, 256 insertions, 184 deletions
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;