13
0

Delegated plugin configuration is now always successful.. except

..in case of outright errors (e.g. data format mismatch)
or non-implemented edge-cases e.g. midi generators
(no audio in, no midi in, no audio-out) or control-data filters (only
control ports).
This commit is contained in:
Robin Gareus 2016-03-30 02:06:59 +02:00
parent 81a9446533
commit d73df3d990
6 changed files with 124 additions and 66 deletions

View File

@ -103,7 +103,7 @@ class LIBARDOUR_API AUPlugin : public ARDOUR::Plugin
bool has_editor () const;
bool can_support_io_configuration (const ChanCount& in, ChanCount& out);
bool can_support_io_configuration (const ChanCount& in, ChanCount& out, ChanCount* imprecise);
ChanCount output_streams() const;
ChanCount input_streams() const;
bool configure_io (ChanCount in, ChanCount out);

View File

@ -93,7 +93,7 @@ public:
bool load_preset (PresetRecord) { return false; }
bool has_editor() const { return false; }
bool can_support_io_configuration (const ChanCount& in, ChanCount& out);
bool can_support_io_configuration (const ChanCount& in, ChanCount& out, ChanCount* imprecise);
bool configure_io (ChanCount in, ChanCount out);
ChanCount output_streams() const { return _configured_out; }

View File

@ -210,7 +210,7 @@ class LIBARDOUR_API Plugin : public PBD::StatefulDestructible, public Latent
/* specific types of plugins can overload this. As of September 2008, only
AUPlugin does this.
*/
virtual bool can_support_io_configuration (const ChanCount& /*in*/, ChanCount& /*out*/) { return false; }
virtual bool can_support_io_configuration (const ChanCount& /*in*/, ChanCount& /*out*/, ChanCount* imprecise = 0) { return false; }
virtual ChanCount output_streams() const;
virtual ChanCount input_streams() const;

View File

@ -1129,21 +1129,18 @@ AUPlugin::output_streams() const
}
bool
AUPlugin::can_support_io_configuration (const ChanCount& in, ChanCount& out)
AUPlugin::can_support_io_configuration (const ChanCount& in, ChanCount& out, ChanCount* imprecise)
{
// Note: We never attempt to multiply-instantiate plugins to meet io configurations.
int32_t audio_in = in.n_audio();
const int32_t audio_in = in.n_audio();
int32_t audio_out;
bool found = false;
AUPluginInfoPtr pinfo = boost::dynamic_pointer_cast<AUPluginInfo>(get_info());
/* lets check MIDI first */
if (in.n_midi() > 0) {
if (!_has_midi_input) {
return false;
}
if (in.n_midi() > 0 && !_has_midi_input && !imprecise) {
return false;
}
vector<pair<int,int> >& io_configs = pinfo->cache.io_configs;
@ -1201,13 +1198,13 @@ AUPlugin::can_support_io_configuration (const ChanCount& in, ChanCount& out)
out.set (DataType::MIDI, 0);
out.set (DataType::AUDIO, audio_out);
return 1;
return true;
}
}
/* now allow potentially "imprecise" matches */
audio_out = -1;
bool found = false;
for (vector<pair<int,int> >::iterator i = io_configs.begin(); i != io_configs.end(); ++i) {
@ -1223,26 +1220,17 @@ AUPlugin::can_support_io_configuration (const ChanCount& in, ChanCount& out)
}
if (possible_in == 0) {
/* instrument plugin, always legal but throws away inputs ...
*/
/* no inputs, generators & instruments */
if (possible_out == -1) {
/* any configuration possible, provide stereo output */
audio_out = 2;
found = true;
} else if (possible_out == -2) {
/* plugins shouldn't really use (0,-2) but might.
any configuration possible, provide stereo output
*/
/* invalid, should be (0, -1) */
audio_out = 2;
found = true;
} else if (possible_out < -2) {
/* explicitly variable number of outputs.
*
* We really need to ask the user in this case.
* stereo will be correct in 99.9% of all cases.
*/
/* explicitly variable number of outputs. */
audio_out = 2;
found = true;
} else {
@ -1253,11 +1241,9 @@ AUPlugin::can_support_io_configuration (const ChanCount& in, ChanCount& out)
}
if (possible_in == -1) {
/* wildcard for input */
if (possible_out == -1) {
/* out much match in */
/* out must match in */
audio_out = audio_in;
found = true;
} else if (possible_out == -2) {
@ -1276,15 +1262,12 @@ AUPlugin::can_support_io_configuration (const ChanCount& in, ChanCount& out)
}
if (possible_in == -2) {
if (possible_out == -1) {
/* any configuration possible, pick matching */
audio_out = audio_in;
found = true;
} else if (possible_out == -2) {
/* plugins shouldn't really use (-2,-2) but might.
interpret as (-1,-1).
*/
/* invalid. interpret as (-1, -1) */
audio_out = audio_in;
found = true;
} else if (possible_out < -2) {
@ -1299,30 +1282,24 @@ AUPlugin::can_support_io_configuration (const ChanCount& in, ChanCount& out)
}
if (possible_in < -2) {
/* explicit variable number of inputs */
if (audio_in > -possible_in) {
/* request is too large */
if (audio_in > -possible_in && imprecise != NULL) {
// hide inputs ports
imprecise->set (DataType::AUDIO, -possible_in);
}
if (possible_out == -1) {
if (audio_in > -possible_in && imprecise == NULL) {
/* request is too large */
} else if (possible_out == -1) {
/* any output configuration possible, provide stereo out */
audio_out = 2;
found = true;
} else if (possible_out == -2) {
/* plugins shouldn't really use (<-2,-2) but might.
interpret as (<-2,-1): any configuration possible, provide stereo output
*/
/* invalid. interpret as (<-2, -1) */
audio_out = 2;
found = true;
} else if (possible_out < -2) {
/* explicitly variable number of outputs.
*
* We really need to ask the user in this case.
* stereo will be correct in 99.9% of all cases.
*/
/* explicitly variable number of outputs, pick stereo */
audio_out = 2;
found = true;
} else {
@ -1333,9 +1310,7 @@ AUPlugin::can_support_io_configuration (const ChanCount& in, ChanCount& out)
}
if (possible_in && (possible_in == audio_in)) {
/* exact number of inputs ... must match obviously */
if (possible_out == -1) {
/* any output configuration possible, provide stereo output */
audio_out = 2;
@ -1368,6 +1343,38 @@ AUPlugin::can_support_io_configuration (const ChanCount& in, ChanCount& out)
}
}
if (!found && imprecise) {
/* try harder */
for (vector<pair<int,int> >::iterator i = io_configs.begin(); i != io_configs.end(); ++i) {
int possible_in = io["audio_in"];
int possible_out = io["audio_out"];
assert (possible_in > 0); // all other cases will have been matched above
assert (possible_out !=0 || possible_in !=0); // already handled above
imprecise->set (DataType::AUDIO, possible_in);
if (possible_out == -1 || possible_out == -2) {
audio_out = 2;
found = true;
} else if (possible_out < -2) {
/* explicitly variable number of outputs, pick maximum */
audio_out = -possible_out;
found = true;
} else {
/* exact number of outputs */
audio_out = possible_out;
found = true;
}
if (found) {
// ideally we'll keep iterating and take the "best match"
// whatever "best" means:
// least unconnected inputs, least silenced inputs,
// closest match of inputs == outputs
break;
}
}
}
if (found) {
out.set (DataType::MIDI, 0); /// XXX

View File

@ -305,9 +305,11 @@ LuaProc::load_script ()
}
bool
LuaProc::can_support_io_configuration (const ChanCount& in, ChanCount& out)
LuaProc::can_support_io_configuration (const ChanCount& in, ChanCount& out, ChanCount* imprecise)
{
if (in.n_midi() > 0 && !_has_midi_input) {
// caller must hold process lock (no concurrent calls to interpreter
if (in.n_midi() > 0 && !_has_midi_input && !imprecise) {
return false;
}
@ -344,8 +346,9 @@ LuaProc::can_support_io_configuration (const ChanCount& in, ChanCount& out)
return false;
}
int32_t audio_in = in.n_audio ();
const int32_t audio_in = in.n_audio ();
int32_t audio_out;
int32_t midi_out = 0; // TODO handle _has_midi_output
if (in.n_midi() > 0 && audio_in == 0) {
audio_out = 2; // prefer stereo version if available.
@ -353,6 +356,7 @@ LuaProc::can_support_io_configuration (const ChanCount& in, ChanCount& out)
audio_out = audio_in;
}
for (luabridge::Iterator i (iotable); !i.isNil (); ++i) {
assert (i.value ().type () == LUA_TTABLE);
luabridge::LuaRef io (i.value ());
@ -406,7 +410,7 @@ LuaProc::can_support_io_configuration (const ChanCount& in, ChanCount& out)
if (possible_in == -1) {
/* wildcard for input */
if (possible_out == -1) {
/* out much match in */
/* out must match in */
audio_out = audio_in;
found = true;
} else if (possible_out == -2) {
@ -447,10 +451,14 @@ LuaProc::can_support_io_configuration (const ChanCount& in, ChanCount& out)
if (possible_in < -2) {
/* explicit variable number of inputs */
if (audio_in > -possible_in) {
/* request is too large */
if (audio_in > -possible_in && imprecise != NULL) {
// hide inputs ports
imprecise->set (DataType::AUDIO, -possible_in);
}
if (possible_out == -1) {
if (audio_in > -possible_in && imprecise == NULL) {
/* request is too large */
} else if (possible_out == -1) {
/* any output configuration possible, provide stereo out */
audio_out = 2;
found = true;
@ -495,11 +503,48 @@ LuaProc::can_support_io_configuration (const ChanCount& in, ChanCount& out)
}
}
if (!found && imprecise) {
/* try harder */
for (luabridge::Iterator i (iotable); !i.isNil (); ++i) {
assert (i.value ().type () == LUA_TTABLE);
luabridge::LuaRef io (i.value ());
int possible_in = io["audio_in"];
int possible_out = io["audio_out"];
assert (possible_in > 0); // all other cases will have been matched above
assert (possible_out !=0 || possible_in !=0); // already handled above
imprecise->set (DataType::AUDIO, possible_in);
if (possible_out == -1 || possible_out == -2) {
audio_out = 2;
found = true;
} else if (possible_out < -2) {
/* explicitly variable number of outputs, pick maximum */
audio_out = -possible_out;
found = true;
} else {
/* exact number of outputs */
audio_out = possible_out;
found = true;
}
if (found) {
// ideally we'll keep iterating and take the "best match"
// whatever "best" means:
// least unconnected inputs, least silenced inputs,
// closest match of inputs == outputs
break;
}
}
}
if (!found) {
return false;
}
out.set (DataType::MIDI, 0);
out.set (DataType::MIDI, midi_out); // currently always zero
out.set (DataType::AUDIO, audio_out);
return true;
}

View File

@ -915,18 +915,22 @@ PluginInsert::configure_io (ChanCount in, ChanCount out)
}
break;
case Delegate:
if (_match.strict_io) {
{
ChanCount dout;
bool const r = _plugins.front()->can_support_io_configuration (in, dout);
ChanCount useins;
bool const r = _plugins.front()->can_support_io_configuration (in, dout, &useins);
assert (r);
if (_plugins.front()->configure_io (in, dout) == false) {
assert (_match.strict_io || dout.n_audio() == out.n_audio()); // sans midi bypass
if (useins.n_audio() == 0) {
useins = in;
}
if (_plugins.front()->configure_io (useins, dout) == false) {
PluginIoReConfigure (); /* EMIT SIGNAL */
_configured = false;
return false;
}
break;
}
// no break -- fall through
break;
default:
if (_plugins.front()->configure_io (in, out) == false) {
PluginIoReConfigure (); /* EMIT SIGNAL */
@ -1003,7 +1007,7 @@ PluginInsert::configure_io (ChanCount in, ChanCount out)
if (mapping_changed) {
PluginMapChanged (); /* EMIT SIGNAL */
#if 1
#ifndef NDEBUG
uint32_t pc = 0;
cout << "----<<----\n";
for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i, ++pc) {
@ -1126,10 +1130,13 @@ PluginInsert::private_can_support_io_configuration (ChanCount const & inx, ChanC
}
if (info->reconfigurable_io()) {
// houston, we have a problem.
// TODO: match closest closes available config.
// also handle strict_io
return Match (Impossible, 0);
ChanCount useins;
bool const r = _plugins.front()->can_support_io_configuration (inx, out, &useins);
if (!r) {
// houston, we have a problem.
return Match (Impossible, 0);
}
return Match (Delegate, 1);
}
// add at least as many plugins so that output count matches input count
@ -1175,7 +1182,6 @@ PluginInsert::automatic_can_support_io_configuration (ChanCount const & inx, Cha
if (!r) {
return Match (Impossible, 0);
}
return Match (Delegate, 1);
}