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
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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*);
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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>);
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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&);
|
||||
|
||||
@@ -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 == 0) {
|
||||
if (inputs.n_total() == 0) {
|
||||
/* instrument plugin, always legal, but throws away any existing streams */
|
||||
return outputs;
|
||||
}
|
||||
|
||||
/* instrument plugin, always legal, but it throws
|
||||
away any existing active streams.
|
||||
if (inputs.n_total() == 1 && outputs == inputs) {
|
||||
/* mono plugin, replicate as needed to match in */
|
||||
return in;
|
||||
}
|
||||
|
||||
if (inputs == in) {
|
||||
/* exact match */
|
||||
return outputs;
|
||||
}
|
||||
|
||||
// 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 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));
|
||||
set_output_maximum (in);
|
||||
set_output_minimum (in);
|
||||
set_input_maximum (out);
|
||||
set_input_minimum (out);
|
||||
|
||||
if (in < 0) {
|
||||
in = n_outputs ().get(_default_type);
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user