From d73df3d99007854152fe2e7ff9539dcadf31e15a Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Wed, 30 Mar 2016 02:06:59 +0200 Subject: [PATCH] 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). --- libs/ardour/ardour/audio_unit.h | 2 +- libs/ardour/ardour/luaproc.h | 2 +- libs/ardour/ardour/plugin.h | 2 +- libs/ardour/audio_unit.cc | 95 ++++++++++++++++++--------------- libs/ardour/luaproc.cc | 61 ++++++++++++++++++--- libs/ardour/plugin_insert.cc | 28 ++++++---- 6 files changed, 124 insertions(+), 66 deletions(-) diff --git a/libs/ardour/ardour/audio_unit.h b/libs/ardour/ardour/audio_unit.h index e9a5622ea9..42e74b37da 100644 --- a/libs/ardour/ardour/audio_unit.h +++ b/libs/ardour/ardour/audio_unit.h @@ -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); diff --git a/libs/ardour/ardour/luaproc.h b/libs/ardour/ardour/luaproc.h index 1908ab8c33..0956bdf213 100644 --- a/libs/ardour/ardour/luaproc.h +++ b/libs/ardour/ardour/luaproc.h @@ -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; } diff --git a/libs/ardour/ardour/plugin.h b/libs/ardour/ardour/plugin.h index 28bc7169da..65cb1f6c36 100644 --- a/libs/ardour/ardour/plugin.h +++ b/libs/ardour/ardour/plugin.h @@ -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; diff --git a/libs/ardour/audio_unit.cc b/libs/ardour/audio_unit.cc index bcc8c2c310..b08d122e7e 100644 --- a/libs/ardour/audio_unit.cc +++ b/libs/ardour/audio_unit.cc @@ -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(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 >& 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 >::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 >::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 diff --git a/libs/ardour/luaproc.cc b/libs/ardour/luaproc.cc index 5c6df71999..71278a0658 100644 --- a/libs/ardour/luaproc.cc +++ b/libs/ardour/luaproc.cc @@ -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; } diff --git a/libs/ardour/plugin_insert.cc b/libs/ardour/plugin_insert.cc index fb6434e388..21debe1d80 100644 --- a/libs/ardour/plugin_insert.cc +++ b/libs/ardour/plugin_insert.cc @@ -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); }