13
0

Tidy up PluginInsert's handling of how it chooses to map plugin IO to that of the insert.

git-svn-id: svn://localhost/ardour2/branches/3.0@10125 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Carl Hetherington 2011-09-26 18:04:02 +00:00
parent fa9e3b3165
commit 8f46b0dc4b
2 changed files with 83 additions and 94 deletions

View File

@ -120,13 +120,25 @@ class PluginInsert : public Processor
void collect_signal_for_analysis (framecnt_t nframes);
bool splitting () const {
return _splitting;
return _matching_method == Split;
}
PBD::Signal2<void,BufferSet*, BufferSet*> AnalysisDataGathered;
/** Emitted when the return value of splitting () has changed */
PBD::Signal0<void> SplittingChanged;
/** Enumeration of the ways in which we can match our insert's
* IO to that of the plugin(s).
*/
enum MatchingMethod {
Impossible, ///< we can't
Delegate, ///< we are delegating to the plugin, and it can handle it
NoInputs, ///< plugin has no inputs, so anything goes
ExactMatch, ///< the insert's inputs are the same as the plugin's
Replicate, ///< we have multiple instances of the plugin
Split, ///< we copy one of the insert's inputs to multiple plugin inputs
};
private:
/* disallow copy construction */
PluginInsert (const PluginInsert&);
@ -149,10 +161,10 @@ class PluginInsert : public Processor
BufferSet _signal_analysis_inputs;
BufferSet _signal_analysis_outputs;
/** true if we are splitting one processor input to >1 plugin inputs */
bool _splitting;
std::pair<MatchingMethod, int32_t> private_can_support_io_configuration (ChanCount const &, ChanCount &) const;
void set_splitting (bool);
/** matching method currently being used */
MatchingMethod _matching_method;
void automation_run (BufferSet& bufs, pframes_t nframes);
void connect_and_run (BufferSet& bufs, pframes_t nframes, framecnt_t offset, bool with_auto, framepos_t now = 0);
@ -162,8 +174,6 @@ class PluginInsert : public Processor
void set_parameter_state_2X (const XMLNode& node, int version);
void set_control_ids (const XMLNode&, int version);
int32_t count_for_configuration (ChanCount in, ChanCount out) const;
boost::shared_ptr<Plugin> plugin_factory (boost::shared_ptr<Plugin>);
void add_plugin_with_activation (boost::shared_ptr<Plugin>);
void add_plugin (boost::shared_ptr<Plugin>);

View File

@ -69,7 +69,7 @@ PluginInsert::PluginInsert (Session& s, boost::shared_ptr<Plugin> plug)
: Processor (s, (plug ? plug->name() : string ("toBeRenamed")))
, _signal_analysis_collected_nframes(0)
, _signal_analysis_collect_nframes_max(0)
, _splitting (false)
, _matching_method (Impossible)
{
/* the first is the master */
@ -151,7 +151,7 @@ PluginInsert::input_streams() const
{
ChanCount in = _plugins[0]->get_info()->n_inputs;
if (_splitting) {
if (_matching_method == Split) {
/* we are splitting 1 processor input to multiple plugin inputs,
so we have a maximum of 1 stream of each type.
@ -164,11 +164,15 @@ PluginInsert::input_streams() const
return in;
} else if (in == ChanCount::INFINITE) {
return _plugins[0]->input_streams ();
} else {
in.set_audio (in.n_audio() * _plugins.size());
in.set_midi (in.n_midi() * _plugins.size());
return in;
}
}
@ -307,7 +311,7 @@ PluginInsert::connect_and_run (BufferSet& bufs, pframes_t nframes, framecnt_t of
ChanMapping in_map(input_streams());
ChanMapping out_map(output_streams());
if (_splitting) {
if (_matching_method == Split) {
/* fix the input mapping so that we have maps for each of the plugin's inputs */
in_map = ChanMapping (natural_input_streams ());
@ -408,7 +412,7 @@ PluginInsert::silence (framecnt_t nframes)
ChanMapping in_map(input_streams());
ChanMapping out_map(output_streams());
if (_splitting) {
if (_matching_method == Split) {
/* fix the input mapping so that we have maps for each of the plugin's inputs */
in_map = ChanMapping (natural_input_streams ());
}
@ -611,22 +615,33 @@ PluginInsert::plugin_factory (boost::shared_ptr<Plugin> other)
bool
PluginInsert::configure_io (ChanCount in, ChanCount out)
{
if (set_count (count_for_configuration (in, out)) == false) {
set_splitting (false);
MatchingMethod old_matching_method = _matching_method;
/* set the matching method and number of plugins that we will use to meet this configuration */
pair<MatchingMethod, int32_t> const r = private_can_support_io_configuration (in, out);
_matching_method = r.first;
if (set_count (r.second) == false) {
return false;
}
if (_plugins.front()->get_info()->n_inputs <= in) {
set_splitting (false);
/* a signal needs emitting if we start or stop splitting */
if (old_matching_method != _matching_method && (old_matching_method == Split || _matching_method == Split)) {
SplittingChanged (); /* EMIT SIGNAL */
}
/* configure plugins */
switch (_matching_method) {
case Split:
if (_plugins.front()->configure_io (_plugins.front()->get_info()->n_inputs, out)) {
return false;
}
break;
default:
if (_plugins.front()->configure_io (in, out) == false) {
return false;
}
} else {
/* we must be splitting a single processor input to
multiple plugin inputs
*/
set_splitting (true);
_plugins.front()->configure_io (_plugins.front()->get_info()->n_inputs, out);
break;
}
// we don't know the analysis window size, so we must work with the
@ -644,12 +659,35 @@ PluginInsert::configure_io (ChanCount in, ChanCount out)
return Processor::configure_io (in, out);
}
/** Decide whether this PluginInsert can support a given IO configuration.
* To do this, we run through a set of possible solutions in rough order of
* preference.
*
* @param in Required input channel count.
* @param out Filled in with the output channel count if we return true.
* @return true if the given IO configuration can be supported.
*/
bool
PluginInsert::can_support_io_configuration (const ChanCount& in, ChanCount& out) const
{
// Plugin has flexible I/O, so delegate to it
return private_can_support_io_configuration (in, out).first != Impossible;
}
/** A private version of can_support_io_configuration which returns the method
* by which the configuration can be matched, rather than just whether or not
* it can be.
*/
pair<PluginInsert::MatchingMethod, int32_t>
PluginInsert::private_can_support_io_configuration (ChanCount const & in, ChanCount& out) const
{
if (_plugins.front()->reconfigurable_io()) {
return _plugins.front()->can_support_io_configuration (in, out);
/* Plugin has flexible I/O, so delegate to it */
bool const r = _plugins.front()->can_support_io_configuration (in, out);
if (!r) {
return make_pair (Impossible, 0);
}
return make_pair (Delegate, 1);
}
ChanCount inputs = _plugins[0]->get_info()->n_inputs;
@ -666,18 +704,21 @@ PluginInsert::can_support_io_configuration (const ChanCount& in, ChanCount& out)
if (no_inputs) {
/* no inputs so we can take any input configuration since we throw it away */
out = outputs;
return true;
return make_pair (NoInputs, 1);
}
// Plugin inputs match requested inputs exactly
/* Plugin inputs match requested inputs exactly */
if (inputs == in) {
out = outputs;
return true;
return make_pair (ExactMatch, 1);
}
// See if replication is possible
// We allow replication only for plugins with either zero or 1 inputs and outputs
// for every valid data type.
/* We may be able to run more than one copy of the plugin within this insert
to cope with the insert having more inputs than the plugin.
We allow replication only for plugins with either zero or 1 inputs and outputs
for every valid data type.
*/
uint32_t f = 0;
bool can_replicate = true;
for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
@ -695,7 +736,6 @@ PluginInsert::can_support_io_configuration (const ChanCount& in, ChanCount& out)
}
// Potential factor not set yet
if (f == 0) {
f = in.get(*t) / nin;
}
@ -711,7 +751,7 @@ PluginInsert::can_support_io_configuration (const ChanCount& in, ChanCount& out)
for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
out.set (*t, outputs.get(*t) * f);
}
return true;
return make_pair (Replicate, f);
}
/* If the processor has exactly one input of a given type, and
@ -735,64 +775,14 @@ PluginInsert::can_support_io_configuration (const ChanCount& in, ChanCount& out)
if (can_split) {
out = outputs;
return true;
return make_pair (Split, 1);
}
return false;
}
/* Number of plugin instances required to support a given channel configuration.
* (private helper)
*/
int32_t
PluginInsert::count_for_configuration (ChanCount in, ChanCount /*out*/) const
{
if (_plugins.front()->reconfigurable_io()) {
/* plugin has flexible I/O, so the answer is always 1 */
/* this could change if we ever decide to replicate AU's */
return 1;
}
// 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 (inputs.n_total() == 1 && outputs == inputs
&& ((inputs.n_audio() == 0 && in.n_audio() == 0)
|| (inputs.n_midi() == 0 && in.n_midi() == 0))) {
/* mono plugin, replicate as needed to match in */
return in.n_total();
}
if (inputs == in) {
/* exact match */
return 1;
}
if (inputs > in) {
/* more plugin inputs than processor inputs, so we are splitting */
return 1;
}
// assumes in is valid, so we must be replicating
if (inputs.n_total() < in.n_total()
&& (in.n_total() % inputs.n_total() == 0)) {
return in.n_total() / inputs.n_total();
}
/* err... */
return 0;
return make_pair (Impossible, 0);
}
XMLNode&
PluginInsert::get_state(void)
PluginInsert::get_state ()
{
return state (true);
}
@ -1259,14 +1249,3 @@ PluginInsert::realtime_handle_transport_stopped ()
(*i)->realtime_handle_transport_stopped ();
}
}
void
PluginInsert::set_splitting (bool s)
{
if (_splitting == s) {
return;
}
_splitting = s;
SplittingChanged (); /* EMIT SIGNAL */
}