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 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 output_streams() const;
ChanCount input_streams() const; ChanCount input_streams() const;
bool configure_io (ChanCount in, ChanCount out); bool configure_io (ChanCount in, ChanCount out);

View file

@ -93,7 +93,7 @@ public:
bool load_preset (PresetRecord) { return false; } bool load_preset (PresetRecord) { return false; }
bool has_editor() const { 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); bool configure_io (ChanCount in, ChanCount out);
ChanCount output_streams() const { return _configured_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 /* specific types of plugins can overload this. As of September 2008, only
AUPlugin does this. 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 output_streams() const;
virtual ChanCount input_streams() const; virtual ChanCount input_streams() const;

View file

@ -1129,22 +1129,19 @@ AUPlugin::output_streams() const
} }
bool 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. // 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; int32_t audio_out;
bool found = false;
AUPluginInfoPtr pinfo = boost::dynamic_pointer_cast<AUPluginInfo>(get_info()); AUPluginInfoPtr pinfo = boost::dynamic_pointer_cast<AUPluginInfo>(get_info());
/* lets check MIDI first */ /* lets check MIDI first */
if (in.n_midi() > 0) { if (in.n_midi() > 0 && !_has_midi_input && !imprecise) {
if (!_has_midi_input) {
return false; return false;
} }
}
vector<pair<int,int> >& io_configs = pinfo->cache.io_configs; 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::MIDI, 0);
out.set (DataType::AUDIO, audio_out); out.set (DataType::AUDIO, audio_out);
return 1; return true;
} }
} }
/* now allow potentially "imprecise" matches */ /* now allow potentially "imprecise" matches */
audio_out = -1; audio_out = -1;
bool found = false;
for (vector<pair<int,int> >::iterator i = io_configs.begin(); i != io_configs.end(); ++i) { 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) { if (possible_in == 0) {
/* no inputs, generators & instruments */
/* instrument plugin, always legal but throws away inputs ...
*/
if (possible_out == -1) { if (possible_out == -1) {
/* any configuration possible, provide stereo output */ /* any configuration possible, provide stereo output */
audio_out = 2; audio_out = 2;
found = true; found = true;
} else if (possible_out == -2) { } else if (possible_out == -2) {
/* plugins shouldn't really use (0,-2) but might. /* invalid, should be (0, -1) */
any configuration possible, provide stereo output
*/
audio_out = 2; audio_out = 2;
found = true; found = true;
} else if (possible_out < -2) { } else if (possible_out < -2) {
/* explicitly variable number of outputs. /* 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.
*/
audio_out = 2; audio_out = 2;
found = true; found = true;
} else { } else {
@ -1253,11 +1241,9 @@ AUPlugin::can_support_io_configuration (const ChanCount& in, ChanCount& out)
} }
if (possible_in == -1) { if (possible_in == -1) {
/* wildcard for input */ /* wildcard for input */
if (possible_out == -1) { if (possible_out == -1) {
/* out much match in */ /* out must match in */
audio_out = audio_in; audio_out = audio_in;
found = true; found = true;
} else if (possible_out == -2) { } 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_in == -2) {
if (possible_out == -1) { if (possible_out == -1) {
/* any configuration possible, pick matching */ /* any configuration possible, pick matching */
audio_out = audio_in; audio_out = audio_in;
found = true; found = true;
} else if (possible_out == -2) { } else if (possible_out == -2) {
/* plugins shouldn't really use (-2,-2) but might. /* invalid. interpret as (-1, -1) */
interpret as (-1,-1).
*/
audio_out = audio_in; audio_out = audio_in;
found = true; found = true;
} else if (possible_out < -2) { } else if (possible_out < -2) {
@ -1299,30 +1282,24 @@ AUPlugin::can_support_io_configuration (const ChanCount& in, ChanCount& out)
} }
if (possible_in < -2) { if (possible_in < -2) {
/* explicit variable number of inputs */ /* explicit variable number of inputs */
if (audio_in > -possible_in && imprecise != NULL) {
if (audio_in > -possible_in) { // hide inputs ports
/* request is too large */ imprecise->set (DataType::AUDIO, -possible_in);
} }
if (audio_in > -possible_in && imprecise == NULL) {
if (possible_out == -1) { /* request is too large */
} else if (possible_out == -1) {
/* any output configuration possible, provide stereo out */ /* any output configuration possible, provide stereo out */
audio_out = 2; audio_out = 2;
found = true; found = true;
} else if (possible_out == -2) { } else if (possible_out == -2) {
/* plugins shouldn't really use (<-2,-2) but might. /* invalid. interpret as (<-2, -1) */
interpret as (<-2,-1): any configuration possible, provide stereo output
*/
audio_out = 2; audio_out = 2;
found = true; found = true;
} else if (possible_out < -2) { } else if (possible_out < -2) {
/* explicitly variable number of outputs. /* explicitly variable number of outputs, pick stereo */
*
* We really need to ask the user in this case.
* stereo will be correct in 99.9% of all cases.
*/
audio_out = 2; audio_out = 2;
found = true; found = true;
} else { } else {
@ -1333,9 +1310,7 @@ AUPlugin::can_support_io_configuration (const ChanCount& in, ChanCount& out)
} }
if (possible_in && (possible_in == audio_in)) { if (possible_in && (possible_in == audio_in)) {
/* exact number of inputs ... must match obviously */ /* exact number of inputs ... must match obviously */
if (possible_out == -1) { if (possible_out == -1) {
/* any output configuration possible, provide stereo output */ /* any output configuration possible, provide stereo output */
audio_out = 2; 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) { if (found) {
out.set (DataType::MIDI, 0); /// XXX out.set (DataType::MIDI, 0); /// XXX

View file

@ -305,9 +305,11 @@ LuaProc::load_script ()
} }
bool 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; return false;
} }
@ -344,8 +346,9 @@ LuaProc::can_support_io_configuration (const ChanCount& in, ChanCount& out)
return false; return false;
} }
int32_t audio_in = in.n_audio (); const int32_t audio_in = in.n_audio ();
int32_t audio_out; int32_t audio_out;
int32_t midi_out = 0; // TODO handle _has_midi_output
if (in.n_midi() > 0 && audio_in == 0) { if (in.n_midi() > 0 && audio_in == 0) {
audio_out = 2; // prefer stereo version if available. 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; audio_out = audio_in;
} }
for (luabridge::Iterator i (iotable); !i.isNil (); ++i) { for (luabridge::Iterator i (iotable); !i.isNil (); ++i) {
assert (i.value ().type () == LUA_TTABLE); assert (i.value ().type () == LUA_TTABLE);
luabridge::LuaRef io (i.value ()); luabridge::LuaRef io (i.value ());
@ -406,7 +410,7 @@ LuaProc::can_support_io_configuration (const ChanCount& in, ChanCount& out)
if (possible_in == -1) { if (possible_in == -1) {
/* wildcard for input */ /* wildcard for input */
if (possible_out == -1) { if (possible_out == -1) {
/* out much match in */ /* out must match in */
audio_out = audio_in; audio_out = audio_in;
found = true; found = true;
} else if (possible_out == -2) { } else if (possible_out == -2) {
@ -447,10 +451,14 @@ LuaProc::can_support_io_configuration (const ChanCount& in, ChanCount& out)
if (possible_in < -2) { if (possible_in < -2) {
/* explicit variable number of inputs */ /* explicit variable number of inputs */
if (audio_in > -possible_in) { if (audio_in > -possible_in && imprecise != NULL) {
/* request is too large */ // 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 */ /* any output configuration possible, provide stereo out */
audio_out = 2; audio_out = 2;
found = true; 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) { if (!found) {
return false; return false;
} }
out.set (DataType::MIDI, 0); out.set (DataType::MIDI, midi_out); // currently always zero
out.set (DataType::AUDIO, audio_out); out.set (DataType::AUDIO, audio_out);
return true; return true;
} }

View file

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