Delegated plugin configuration is now always successful.. except
authorRobin Gareus <robin@gareus.org>
Wed, 30 Mar 2016 00:06:59 +0000 (02:06 +0200)
committerRobin Gareus <robin@gareus.org>
Wed, 30 Mar 2016 00:06:59 +0000 (02:06 +0200)
..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
libs/ardour/ardour/luaproc.h
libs/ardour/ardour/plugin.h
libs/ardour/audio_unit.cc
libs/ardour/luaproc.cc
libs/ardour/plugin_insert.cc

index e9a5622ea97a4a1689d2e6243b598798fa6001ab..42e74b37da8d9760ec516ea5a0324abf864fb036 100644 (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);
index 1908ab8c339e4fa61ae41572a4a82ebc56b7afbe..0956bdf21306213c93fb5cf76dfdde4490423a9f 100644 (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; }
index 28bc7169da4712eca17ca8c891d99a1b68a005c2..65cb1f6c367ff1b16bfa265f4e8b309e694e0c52 100644 (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;
 
index bcc8c2c31044e70db8a2a16dc794303ad7855139..b08d122e7efd387dec93f5f87270c8ec608065c3 100644 (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
index 5c6df719998b8e7c1e6d7baed9c34928bca22661..71278a06580310f1f80de1c948b763ce52c28227 100644 (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;
 }
index fb6434e38805081fbe577946cf5ed1579a7c7502..21debe1d80bc47a44976e929ef5f670c24fe9fdc 100644 (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);
        }