variable plugin port config.
authorRobin Gareus <robin@gareus.org>
Fri, 15 Apr 2016 15:57:40 +0000 (17:57 +0200)
committerRobin Gareus <robin@gareus.org>
Fri, 15 Apr 2016 15:57:40 +0000 (17:57 +0200)
* extend plugin API (query IO ports)
* collect possible variable plugin configurations (AU, Lua)
* prepare semi-automatic configuration (presets: mono, stereo, N)

12 files changed:
libs/ardour/ardour/audio_unit.h
libs/ardour/ardour/luaproc.h
libs/ardour/ardour/lv2_plugin.h
libs/ardour/ardour/plugin.h
libs/ardour/ardour/plugin_insert.h
libs/ardour/ardour/route.h
libs/ardour/audio_unit.cc
libs/ardour/luaproc.cc
libs/ardour/lv2_plugin.cc
libs/ardour/plugin.cc
libs/ardour/plugin_insert.cc
libs/ardour/route.cc

index b83798fd3e302386932b5b9940d2ac22c8d2455f..63bd05b50de0fa7999c446d5ccc06d707d05911b 100644 (file)
@@ -74,6 +74,8 @@ class LIBARDOUR_API AUPlugin : public ARDOUR::Plugin
        void set_parameter (uint32_t which, float val);
        float get_parameter (uint32_t which) const;
 
        void set_parameter (uint32_t which, float val);
        float get_parameter (uint32_t which) const;
 
+       PluginOutputConfiguration possible_output () const { return _output_configs; }
+
        int get_parameter_descriptor (uint32_t which, ParameterDescriptor&) const;
        uint32_t nth_parameter (uint32_t which, bool& ok) const;
        void activate ();
        int get_parameter_descriptor (uint32_t which, ParameterDescriptor&) const;
        uint32_t nth_parameter (uint32_t which, bool& ok) const;
        void activate ();
@@ -172,6 +174,7 @@ class LIBARDOUR_API AUPlugin : public ARDOUR::Plugin
        AudioBufferList* buffers;
        bool _has_midi_input;
        bool _has_midi_output;
        AudioBufferList* buffers;
        bool _has_midi_input;
        bool _has_midi_output;
+       PluginOutputConfiguration _output_configs;
 
        /* despite all the cool work that apple did on their AU preset
           system, they left factory presets and user presets as two
 
        /* despite all the cool work that apple did on their AU preset
           system, they left factory presets and user presets as two
index 0f4f8d7d6d8fb5716265ff89e9d3c3286a1dbdb7..a0f49d61bbe4e04e16cfc1b20256ff81a007b880 100644 (file)
@@ -63,6 +63,8 @@ public:
        std::string get_docs () const { return _docs; }
        std::string get_parameter_docs (uint32_t) const;
 
        std::string get_docs () const { return _docs; }
        std::string get_parameter_docs (uint32_t) const;
 
+       PluginOutputConfiguration possible_output () const { return _output_configs; }
+
        std::set<Evoral::Parameter> automatable() const;
 
        void activate () { }
        std::set<Evoral::Parameter> automatable() const;
 
        void activate () { }
@@ -140,6 +142,7 @@ private:
 
        ChanCount _configured_in;
        ChanCount _configured_out;
 
        ChanCount _configured_in;
        ChanCount _configured_out;
+       PluginOutputConfiguration _output_configs;
 
        bool _has_midi_input;
        bool _has_midi_output;
 
        bool _has_midi_input;
        bool _has_midi_output;
index f1907e80ae53dadf0d9adf9e3669de4d4ba51a56..34e68fdc7f22419a3da03ab7d04eb318a261bc19 100644 (file)
@@ -80,7 +80,7 @@ class LIBARDOUR_API LV2Plugin : public ARDOUR::Plugin, public ARDOUR::Workee
        int         get_parameter_descriptor (uint32_t which, ParameterDescriptor&) const;
        uint32_t    nth_parameter (uint32_t port, bool& ok) const;
 
        int         get_parameter_descriptor (uint32_t which, ParameterDescriptor&) const;
        uint32_t    nth_parameter (uint32_t port, bool& ok) const;
 
-       IOPortDescription describe_io_port (DataType dt, bool input, uint32_t id);
+       IOPortDescription describe_io_port (DataType dt, bool input, uint32_t id) const;
 
        const void* extension_data (const char* uri) const;
 
 
        const void* extension_data (const char* uri) const;
 
index ec749281af2ace14ff6af725e58c9da16e667632..d284c2620d75f3580388cac74d102a71b31b7a3e 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <boost/shared_ptr.hpp>
 #include <string>
 
 #include <boost/shared_ptr.hpp>
 #include <string>
+#include <set>
 
 #include "pbd/statefuldestructible.h"
 #include "pbd/controllable.h"
 
 #include "pbd/statefuldestructible.h"
 #include "pbd/controllable.h"
@@ -54,6 +55,7 @@ class AutomationControl;
 typedef boost::shared_ptr<Plugin> PluginPtr;
 typedef boost::shared_ptr<PluginInfo> PluginInfoPtr;
 typedef std::list<PluginInfoPtr> PluginInfoList;
 typedef boost::shared_ptr<Plugin> PluginPtr;
 typedef boost::shared_ptr<PluginInfo> PluginInfoPtr;
 typedef std::list<PluginInfoPtr> PluginInfoList;
+typedef std::set<uint32_t> PluginOutputConfiguration;
 
 /** A plugin is an external module (usually 3rd party provided) loaded into Ardour
  * for the purpose of digital signal processing.
 
 /** A plugin is an external module (usually 3rd party provided) loaded into Ardour
  * for the purpose of digital signal processing.
@@ -124,7 +126,8 @@ class LIBARDOUR_API Plugin : public PBD::StatefulDestructible, public Latent
                bool is_sidechain;
        };
 
                bool is_sidechain;
        };
 
-       virtual IOPortDescription describe_io_port (DataType dt, bool input, uint32_t id);
+       virtual IOPortDescription describe_io_port (DataType dt, bool input, uint32_t id) const;
+       virtual PluginOutputConfiguration possible_output () const;
 
        virtual void set_automation_control (uint32_t /*port_index*/, boost::shared_ptr<ARDOUR::AutomationControl>) { }
 
 
        virtual void set_automation_control (uint32_t /*port_index*/, boost::shared_ptr<ARDOUR::AutomationControl>) { }
 
index aa1164187d4dfed7c7fbc264099b93adcd011f79..c8f0a84222e391f5f2536a4a4dc1db5c798490c1 100644 (file)
@@ -134,7 +134,8 @@ class LIBARDOUR_API PluginInsert : public Processor
                }
        }
 
                }
        }
 
-       ChanCount required_buffers () const { return _required_buffers; }
+       const ChanCount& required_buffers () const { return _required_buffers; }
+       const ChanCount& preset_out () const { return _preset_out; }
 
        // allow to override output_streams(), implies "Custom Mode"
 
 
        // allow to override output_streams(), implies "Custom Mode"
 
@@ -144,6 +145,7 @@ class LIBARDOUR_API PluginInsert : public Processor
        void set_outputs    (const ChanCount&);
        void set_strict_io  (bool b);
        void set_custom_cfg (bool b);
        void set_outputs    (const ChanCount&);
        void set_strict_io  (bool b);
        void set_custom_cfg (bool b);
+       bool set_preset_out (const ChanCount&);
        bool add_sidechain  (uint32_t n_audio = 1);
        bool del_sidechain ();
        boost::shared_ptr<SideChain> sidechain () const { return _sidechain; }
        bool add_sidechain  (uint32_t n_audio = 1);
        bool del_sidechain ();
        boost::shared_ptr<SideChain> sidechain () const { return _sidechain; }
@@ -306,6 +308,7 @@ class LIBARDOUR_API PluginInsert : public Processor
        ChanCount _configured_internal; // with side-chain
        ChanCount _configured_out;
        ChanCount _custom_out;
        ChanCount _configured_internal; // with side-chain
        ChanCount _configured_out;
        ChanCount _custom_out;
+       ChanCount _preset_out;
        ChanCount _cached_sidechain_pins;
        ChanCount _required_buffers;
 
        ChanCount _cached_sidechain_pins;
        ChanCount _required_buffers;
 
@@ -317,6 +320,7 @@ class LIBARDOUR_API PluginInsert : public Processor
        bool _mapping_changed;
 
        Match private_can_support_io_configuration (ChanCount const &, ChanCount &) const;
        bool _mapping_changed;
 
        Match private_can_support_io_configuration (ChanCount const &, ChanCount &) const;
+       Match internal_can_support_io_configuration (ChanCount const &, ChanCount &) const;
        Match automatic_can_support_io_configuration (ChanCount const &, ChanCount &) const;
 
        /** details of the match currently being used */
        Match automatic_can_support_io_configuration (ChanCount const &, ChanCount &) const;
 
        /** details of the match currently being used */
index 7e7d5d55d4b072fa090c8f0854375824d74a9c6c..c8f60058725c9cca521ba430c4d662bdced31b1c 100644 (file)
@@ -313,6 +313,7 @@ class LIBARDOUR_API Route : public SessionObject, public Automatable, public Rou
         */
        bool customize_plugin_insert (boost::shared_ptr<Processor> proc, uint32_t count, ChanCount outs);
        bool add_remove_sidechain (boost::shared_ptr<Processor> proc, bool);
         */
        bool customize_plugin_insert (boost::shared_ptr<Processor> proc, uint32_t count, ChanCount outs);
        bool add_remove_sidechain (boost::shared_ptr<Processor> proc, bool);
+       bool plugin_preset_output (boost::shared_ptr<Processor> proc, ChanCount outs);
 
        /* enable sidechain input for a given processor
         *
 
        /* enable sidechain input for a given processor
         *
index 2ded196f52a2d35a973606f08e147699a7ae7215..2746f763300820250fb52303bf858273228c3fa0 100644 (file)
@@ -1133,8 +1133,7 @@ AUPlugin::output_streams() const
 bool
 AUPlugin::can_support_io_configuration (const ChanCount& in, ChanCount& out, ChanCount* imprecise)
 {
 bool
 AUPlugin::can_support_io_configuration (const ChanCount& in, ChanCount& out, ChanCount* imprecise)
 {
-       // Note: We never attempt to multiply-instantiate plugins to meet io configurations.
-
+       _output_configs.clear ();
        const int32_t audio_in = in.n_audio();
        int32_t audio_out;
        AUPluginInfoPtr pinfo = boost::dynamic_pointer_cast<AUPluginInfo>(get_info());
        const int32_t audio_in = in.n_audio();
        int32_t audio_out;
        AUPluginInfoPtr pinfo = boost::dynamic_pointer_cast<AUPluginInfo>(get_info());
@@ -1151,7 +1150,10 @@ AUPlugin::can_support_io_configuration (const ChanCount& in, ChanCount& out, Cha
                                                        name(), io_configs.size(), in, out));
 
        // preferred setting (provided by plugin_insert)
                                                        name(), io_configs.size(), in, out));
 
        // preferred setting (provided by plugin_insert)
+       const int preferred_out = out.n_audio ();
        audio_out = out.n_audio ();
        audio_out = out.n_audio ();
+       bool found = false;
+       bool exact_match = false;
 
        /* kAudioUnitProperty_SupportedNumChannels
         * https://developer.apple.com/library/mac/documentation/MusicAudio/Conceptual/AudioUnitProgrammingGuide/TheAudioUnit/TheAudioUnit.html#//apple_ref/doc/uid/TP40003278-CH12-SW20
 
        /* kAudioUnitProperty_SupportedNumChannels
         * https://developer.apple.com/library/mac/documentation/MusicAudio/Conceptual/AudioUnitProgrammingGuide/TheAudioUnit/TheAudioUnit.html#//apple_ref/doc/uid/TP40003278-CH12-SW20
@@ -1184,35 +1186,43 @@ AUPlugin::can_support_io_configuration (const ChanCount& in, ChanCount& out, Cha
                int32_t possible_in = i->first;
                int32_t possible_out = i->second;
 
                int32_t possible_in = i->first;
                int32_t possible_out = i->second;
 
-               if ((possible_in == audio_in) && (possible_out == audio_out)) {
+               if ((possible_in == audio_in) && (possible_out == preferred_out)) {
                        DEBUG_TRACE (DEBUG::AudioUnits, string_compose ("\tCHOSEN: %1 in %2 out to match in %3 out %4\n",
                        DEBUG_TRACE (DEBUG::AudioUnits, string_compose ("\tCHOSEN: %1 in %2 out to match in %3 out %4\n",
-                                                                       possible_in, possible_out,
-                                                                       in, out));
+                                               possible_in, possible_out,
+                                               in, out));
 
 
-                       out.set (DataType::MIDI, 0);
-                       out.set (DataType::AUDIO, audio_out);
-
-                       return true;
+                       // exact match
+                       _output_configs.insert (preferred_out);
+                       exact_match = true;
+                       found = true;
+                       break;
                }
        }
 
        /* now allow potentially "imprecise" matches */
                }
        }
 
        /* now allow potentially "imprecise" matches */
-       audio_out = -1;
-       bool found = false;
-
+       int32_t audio_out = -1;
        float penalty = 9999;
        float penalty = 9999;
-       const int preferred_out = out.n_audio ();
        int used_possible_in = 0;
 
        int used_possible_in = 0;
 
-#define FOUNDCFG(nch) {                                  \
-       float p = fabsf ((float)(nch) - preferred_out);  \
-       if ((nch) > preferred_out) { p *= 1.1; }         \
-       if (p < penalty) {                               \
-               used_possible_in = possible_in;          \
-               audio_out = (nch);                       \
-               penalty = p;                             \
-               found = true;                            \
-       }                                                \
+#define FOUNDCFG(nch) {                            \
+  float p = fabsf ((float)(nch) - preferred_out);  \
+  _output_configs.insert (nch);                    \
+  if ((nch) > preferred_out) { p *= 1.1; }         \
+  if (p < penalty) {                               \
+    used_possible_in = possible_in;                \
+    audio_out = (nch);                             \
+    penalty = p;                                   \
+    found = true;                                  \
+  }                                                \
+}
+
+#define ANYTHINGGOES                               \
+  _output_configs.insert (0);
+
+#define UPTO(nch) {                                \
+  for (int n = 1; n < nch; ++n) {                  \
+    _output_configs.insert (n);                    \
+  }                                                \
 }
 
        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) {
@@ -1233,12 +1243,15 @@ AUPlugin::can_support_io_configuration (const ChanCount& in, ChanCount& out, Cha
                        if (possible_out == -1) {
                                /* any configuration possible, provide stereo output */
                                FOUNDCFG (preferred_out);
                        if (possible_out == -1) {
                                /* any configuration possible, provide stereo output */
                                FOUNDCFG (preferred_out);
+                               ANYTHINGGOES;
                        } else if (possible_out == -2) {
                                /* invalid, should be (0, -1) */
                                FOUNDCFG (preferred_out);
                        } else if (possible_out == -2) {
                                /* invalid, should be (0, -1) */
                                FOUNDCFG (preferred_out);
+                               ANYTHINGGOES;
                        } else if (possible_out < -2) {
                                /* variable number of outputs up to -N, */
                                FOUNDCFG (min (-possible_out, preferred_out));
                        } else if (possible_out < -2) {
                                /* variable number of outputs up to -N, */
                                FOUNDCFG (min (-possible_out, preferred_out));
+                               UPTO (-possible_out);
                        } else {
                                /* exact number of outputs */
                                FOUNDCFG (possible_out);
                        } else {
                                /* exact number of outputs */
                                FOUNDCFG (possible_out);
@@ -1253,11 +1266,13 @@ AUPlugin::can_support_io_configuration (const ChanCount& in, ChanCount& out, Cha
                        } else if (possible_out == -2) {
                                /* any configuration possible, pick matching */
                                FOUNDCFG (preferred_out);
                        } else if (possible_out == -2) {
                                /* any configuration possible, pick matching */
                                FOUNDCFG (preferred_out);
+                               ANYTHINGGOES;
                        } else if (possible_out < -2) {
                                /* explicitly variable number of outputs, pick maximum */
                                FOUNDCFG (max (-possible_out, preferred_out));
                                /* and try min, too, in case the penalty is lower */
                                FOUNDCFG (min (-possible_out, preferred_out));
                        } else if (possible_out < -2) {
                                /* explicitly variable number of outputs, pick maximum */
                                FOUNDCFG (max (-possible_out, preferred_out));
                                /* and try min, too, in case the penalty is lower */
                                FOUNDCFG (min (-possible_out, preferred_out));
+                               UPTO (-possible_out)
                        } else {
                                /* exact number of outputs */
                                FOUNDCFG (possible_out);
                        } else {
                                /* exact number of outputs */
                                FOUNDCFG (possible_out);
@@ -1268,13 +1283,16 @@ AUPlugin::can_support_io_configuration (const ChanCount& in, ChanCount& out, Cha
                        if (possible_out == -1) {
                                /* any configuration possible, pick matching */
                                FOUNDCFG (preferred_out);
                        if (possible_out == -1) {
                                /* any configuration possible, pick matching */
                                FOUNDCFG (preferred_out);
+                               ANYTHINGGOES;
                        } else if (possible_out == -2) {
                                /* invalid. interpret as (-1, -1) */
                                FOUNDCFG (preferred_out);
                        } else if (possible_out == -2) {
                                /* invalid. interpret as (-1, -1) */
                                FOUNDCFG (preferred_out);
+                               ANYTHINGGOES;
                        } else if (possible_out < -2) {
                                /* invalid,  interpret as (<-2, <-2)
                                 * variable number of outputs up to -N, */
                                FOUNDCFG (min (-possible_out, preferred_out));
                        } else if (possible_out < -2) {
                                /* invalid,  interpret as (<-2, <-2)
                                 * variable number of outputs up to -N, */
                                FOUNDCFG (min (-possible_out, preferred_out));
+                               UPTO (-possible_out)
                        } else {
                                /* exact number of outputs */
                                FOUNDCFG (possible_out);
                        } else {
                                /* exact number of outputs */
                                FOUNDCFG (possible_out);
@@ -1291,14 +1309,17 @@ AUPlugin::can_support_io_configuration (const ChanCount& in, ChanCount& out, Cha
                        if (audio_in > -possible_in && imprecise == NULL) {
                                /* request is too large */
                        } else 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 */
                                FOUNDCFG (preferred_out);
                                FOUNDCFG (preferred_out);
+                               ANYTHINGGOES;
                        } else if (possible_out == -2) {
                                /* invalid. interpret as (<-2, -1) */
                                FOUNDCFG (preferred_out);
                        } else if (possible_out == -2) {
                                /* invalid. interpret as (<-2, -1) */
                                FOUNDCFG (preferred_out);
+                               ANYTHINGGOES;
                        } else if (possible_out < -2) {
                                /* variable number of outputs up to -N, */
                                FOUNDCFG (min (-possible_out, preferred_out));
                        } else if (possible_out < -2) {
                                /* variable number of outputs up to -N, */
                                FOUNDCFG (min (-possible_out, preferred_out));
+                               UPTO (-possible_out)
                        } else {
                                /* exact number of outputs */
                                FOUNDCFG (possible_out);
                        } else {
                                /* exact number of outputs */
                                FOUNDCFG (possible_out);
@@ -1310,15 +1331,16 @@ AUPlugin::can_support_io_configuration (const ChanCount& in, ChanCount& out, Cha
                        if (possible_out == -1) {
                                /* any output configuration possible */
                                FOUNDCFG (preferred_out);
                        if (possible_out == -1) {
                                /* any output configuration possible */
                                FOUNDCFG (preferred_out);
+                               ANYTHINGGOES;
                        } else if (possible_out == -2) {
                        } else if (possible_out == -2) {
-                               /* plugins shouldn't really use (>0,-2) but might.
-                                * interpret as (>0,-1):
-                                */
+                               /* plugins shouldn't really use (>0,-2), interpret as (>0,-1) */
                                FOUNDCFG (preferred_out);
                                FOUNDCFG (preferred_out);
+                               ANYTHINGGOES;
                        } else if (possible_out < -2) {
                                /* > 0, < -2 is not specified
                                 * interpret as up to -N */
                                FOUNDCFG (min (-possible_out, preferred_out));
                        } else if (possible_out < -2) {
                                /* > 0, < -2 is not specified
                                 * interpret as up to -N */
                                FOUNDCFG (min (-possible_out, preferred_out));
+                               UPTO (-possible_out)
                        } else {
                                /* exact number of outputs */
                                FOUNDCFG (possible_out);
                        } else {
                                /* exact number of outputs */
                                FOUNDCFG (possible_out);
@@ -1350,20 +1372,24 @@ AUPlugin::can_support_io_configuration (const ChanCount& in, ChanCount& out, Cha
                }
        }
 
                }
        }
 
-       if (found) {
+       if (!found) {
+               DEBUG_TRACE (DEBUG::AudioUnits, string_compose ("\tFAIL: no io configs match %1\n", in));
+               return false;
+       }
+
+       if (exact_match) {
+               out.set (DataType::MIDI, 0); // currently always zero
+               out.set (DataType::AUDIO, preferred_out);
+       } else {
                if (used_possible_in < -2 && audio_in == 0) {
                        // input-port count cannot be zero, use as many ports
                        // as outputs, but at most abs(possible_in)
                        audio_input_cnt = max (1, min (audio_out, -used_possible_in));
                }
                if (used_possible_in < -2 && audio_in == 0) {
                        // input-port count cannot be zero, use as many ports
                        // as outputs, but at most abs(possible_in)
                        audio_input_cnt = max (1, min (audio_out, -used_possible_in));
                }
-
                out.set (DataType::MIDI, 0); /// XXX
                out.set (DataType::AUDIO, audio_out);
                out.set (DataType::MIDI, 0); /// XXX
                out.set (DataType::AUDIO, audio_out);
-               DEBUG_TRACE (DEBUG::AudioUnits, string_compose ("\tCHOSEN: in %1 out %2\n", in, out));
-       } else {
-               DEBUG_TRACE (DEBUG::AudioUnits, string_compose ("\tFAIL: no io configs match %1\n", in));
-               return false;
        }
        }
+       DEBUG_TRACE (DEBUG::AudioUnits, string_compose ("\tCHOSEN: in %1 out %2\n", in, out));
 
        return true;
 }
 
        return true;
 }
index 31a5dd8785ea9ded314e97ad6d725e9dcc62a666..baeb9409f402efb8468145c93b9c7f6d561b0fcf 100644 (file)
@@ -311,6 +311,7 @@ bool
 LuaProc::can_support_io_configuration (const ChanCount& in, ChanCount& out, ChanCount* imprecise)
 {
        // caller must hold process lock (no concurrent calls to interpreter
 LuaProc::can_support_io_configuration (const ChanCount& in, ChanCount& out, ChanCount* imprecise)
 {
        // caller must hold process lock (no concurrent calls to interpreter
+       _output_configs.clear ();
 
        if (in.n_midi() > 0 && !_has_midi_input && !imprecise) {
                return false;
 
        if (in.n_midi() > 0 && !_has_midi_input && !imprecise) {
                return false;
@@ -322,14 +323,9 @@ LuaProc::can_support_io_configuration (const ChanCount& in, ChanCount& out, Chan
                return false;
        }
 
                return false;
        }
 
-       luabridge::LuaRef table = luabridge::getGlobal (L, "table"); //lua std lib
-       luabridge::LuaRef tablesort = table["sort"];
-       assert (tablesort.isFunction ());
-
        luabridge::LuaRef *_iotable = NULL; // can't use reference :(
        try {
                luabridge::LuaRef iotable = ioconfig ();
        luabridge::LuaRef *_iotable = NULL; // can't use reference :(
        try {
                luabridge::LuaRef iotable = ioconfig ();
-               tablesort (iotable);
                if (iotable.isTable ()) {
                        _iotable = new luabridge::LuaRef (iotable);
                }
                if (iotable.isTable ()) {
                        _iotable = new luabridge::LuaRef (iotable);
                }
@@ -349,13 +345,14 @@ LuaProc::can_support_io_configuration (const ChanCount& in, ChanCount& out, Chan
                return false;
        }
 
                return false;
        }
 
+       bool found = false;
+       bool exact_match = false;
        const 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
 
        // preferred setting (provided by plugin_insert)
        assert (out.n_audio () > 0);
        int32_t midi_out = 0; // TODO handle  _has_midi_output
 
        // preferred setting (provided by plugin_insert)
        assert (out.n_audio () > 0);
-       audio_out = out.n_audio ();
+       const int preferred_out = out.n_audio ();
 
        for (luabridge::Iterator i (iotable); !i.isNil (); ++i) {
                assert (i.value ().type () == LUA_TTABLE);
 
        for (luabridge::Iterator i (iotable); !i.isNil (); ++i) {
                assert (i.value ().type () == LUA_TTABLE);
@@ -365,28 +362,36 @@ LuaProc::can_support_io_configuration (const ChanCount& in, ChanCount& out, Chan
                int possible_out = io["audio_out"];
 
                // exact match
                int possible_out = io["audio_out"];
 
                // exact match
-               if ((possible_in == audio_in) && (possible_out == audio_out)) {
-                       out.set (DataType::MIDI, 0);
-                       out.set (DataType::AUDIO, audio_out);
-                       return true;
+               if ((possible_in == audio_in) && (possible_out == preferred_out)) {
+                       _output_configs.insert (preferred_out);
+                       exact_match = true;
+                       found = true;
+                       break;
                }
        }
 
        /* now allow potentially "imprecise" matches */
                }
        }
 
        /* now allow potentially "imprecise" matches */
-       audio_out = -1;
-       bool found = false;
-
+       int32_t audio_out = -1;
        float penalty = 9999;
        float penalty = 9999;
-       const int preferred_out = out.n_audio ();
 
 
-#define FOUNDCFG(nch) {                                  \
-       float p = fabsf ((float)(nch) - preferred_out);  \
-       if ((nch) > preferred_out) { p *= 1.1; }         \
-       if (p < penalty) {                               \
-               audio_out = (nch);                       \
-               penalty = p;                             \
-               found = true;                            \
-       }                                                \
+#define FOUNDCFG(nch) {                            \
+  float p = fabsf ((float)(nch) - preferred_out);  \
+  _output_configs.insert (nch);                    \
+  if ((nch) > preferred_out) { p *= 1.1; }         \
+  if (p < penalty) {                               \
+    audio_out = (nch);                             \
+    penalty = p;                                   \
+    found = true;                                  \
+  }                                                \
+}
+
+#define ANYTHINGGOES                               \
+  _output_configs.insert (0);
+
+#define UPTO(nch) {                                \
+  for (int n = 1; n < nch; ++n) {                  \
+    _output_configs.insert (n);                    \
+  }                                                \
 }
 
        for (luabridge::Iterator i (iotable); !i.isNil (); ++i) {
 }
 
        for (luabridge::Iterator i (iotable); !i.isNil (); ++i) {
@@ -404,12 +409,15 @@ LuaProc::can_support_io_configuration (const ChanCount& in, ChanCount& out, Chan
                        if (possible_out == -1) {
                                /* any configuration possible, stereo output */
                                FOUNDCFG (preferred_out);
                        if (possible_out == -1) {
                                /* any configuration possible, stereo output */
                                FOUNDCFG (preferred_out);
+                               ANYTHINGGOES;
                        } else if (possible_out == -2) {
                                /* invalid, should be (0, -1) */
                                FOUNDCFG (preferred_out);
                        } else if (possible_out == -2) {
                                /* invalid, should be (0, -1) */
                                FOUNDCFG (preferred_out);
+                               ANYTHINGGOES;
                        } else if (possible_out < -2) {
                                /* variable number of outputs up to -N, */
                                FOUNDCFG (min (-possible_out, preferred_out));
                        } else if (possible_out < -2) {
                                /* variable number of outputs up to -N, */
                                FOUNDCFG (min (-possible_out, preferred_out));
+                               UPTO (-possible_out);
                        } else {
                                /* exact number of outputs */
                                FOUNDCFG (possible_out);
                        } else {
                                /* exact number of outputs */
                                FOUNDCFG (possible_out);
@@ -424,11 +432,13 @@ LuaProc::can_support_io_configuration (const ChanCount& in, ChanCount& out, Chan
                        } else if (possible_out == -2) {
                                /* any configuration possible, pick matching */
                                FOUNDCFG (preferred_out);
                        } else if (possible_out == -2) {
                                /* any configuration possible, pick matching */
                                FOUNDCFG (preferred_out);
+                               ANYTHINGGOES;
                        } else if (possible_out < -2) {
                                /* explicitly variable number of outputs, pick maximum */
                                FOUNDCFG (max (-possible_out, preferred_out));
                                /* and try min, too, in case the penalty is lower */
                                FOUNDCFG (min (-possible_out, preferred_out));
                        } else if (possible_out < -2) {
                                /* explicitly variable number of outputs, pick maximum */
                                FOUNDCFG (max (-possible_out, preferred_out));
                                /* and try min, too, in case the penalty is lower */
                                FOUNDCFG (min (-possible_out, preferred_out));
+                               UPTO (-possible_out)
                        } else {
                                /* exact number of outputs */
                                FOUNDCFG (possible_out);
                        } else {
                                /* exact number of outputs */
                                FOUNDCFG (possible_out);
@@ -436,17 +446,19 @@ LuaProc::can_support_io_configuration (const ChanCount& in, ChanCount& out, Chan
                }
 
                if (possible_in == -2) {
                }
 
                if (possible_in == -2) {
-
                        if (possible_out == -1) {
                                /* any configuration possible, pick matching */
                                FOUNDCFG (preferred_out);
                        if (possible_out == -1) {
                                /* any configuration possible, pick matching */
                                FOUNDCFG (preferred_out);
+                               ANYTHINGGOES;
                        } else if (possible_out == -2) {
                                /* invalid. interpret as (-1, -1) */
                                FOUNDCFG (preferred_out);
                        } else if (possible_out == -2) {
                                /* invalid. interpret as (-1, -1) */
                                FOUNDCFG (preferred_out);
+                               ANYTHINGGOES;
                        } else if (possible_out < -2) {
                                /* invalid,  interpret as (<-2, <-2)
                                 * variable number of outputs up to -N, */
                                FOUNDCFG (min (-possible_out, preferred_out));
                        } else if (possible_out < -2) {
                                /* invalid,  interpret as (<-2, <-2)
                                 * variable number of outputs up to -N, */
                                FOUNDCFG (min (-possible_out, preferred_out));
+                               UPTO (-possible_out)
                        } else {
                                /* exact number of outputs */
                                FOUNDCFG (possible_out);
                        } else {
                                /* exact number of outputs */
                                FOUNDCFG (possible_out);
@@ -465,12 +477,15 @@ LuaProc::can_support_io_configuration (const ChanCount& in, ChanCount& out, Chan
                        } else if (possible_out == -1) {
                                /* any output configuration possible */
                                FOUNDCFG (preferred_out);
                        } else if (possible_out == -1) {
                                /* any output configuration possible */
                                FOUNDCFG (preferred_out);
+                               ANYTHINGGOES;
                        } else if (possible_out == -2) {
                                /* invalid. interpret as (<-2, -1) */
                                FOUNDCFG (preferred_out);
                        } else if (possible_out == -2) {
                                /* invalid. interpret as (<-2, -1) */
                                FOUNDCFG (preferred_out);
+                               ANYTHINGGOES;
                        } else if (possible_out < -2) {
                                /* variable number of outputs up to -N, */
                                FOUNDCFG (min (-possible_out, preferred_out));
                        } else if (possible_out < -2) {
                                /* variable number of outputs up to -N, */
                                FOUNDCFG (min (-possible_out, preferred_out));
+                               UPTO (-possible_out)
                        } else {
                                /* exact number of outputs */
                                FOUNDCFG (possible_out);
                        } else {
                                /* exact number of outputs */
                                FOUNDCFG (possible_out);
@@ -482,13 +497,16 @@ LuaProc::can_support_io_configuration (const ChanCount& in, ChanCount& out, Chan
                        if (possible_out == -1) {
                                /* any output configuration possible */
                                FOUNDCFG (preferred_out);
                        if (possible_out == -1) {
                                /* any output configuration possible */
                                FOUNDCFG (preferred_out);
+                               ANYTHINGGOES;
                        } else if (possible_out == -2) {
                                /* invalid. interpret as (>0, -1) */
                                FOUNDCFG (preferred_out);
                        } else if (possible_out == -2) {
                                /* invalid. interpret as (>0, -1) */
                                FOUNDCFG (preferred_out);
+                               ANYTHINGGOES;
                        } else if (possible_out < -2) {
                                /* > 0, < -2 is not specified
                                 * interpret as up to -N */
                                FOUNDCFG (min (-possible_out, preferred_out));
                        } else if (possible_out < -2) {
                                /* > 0, < -2 is not specified
                                 * interpret as up to -N */
                                FOUNDCFG (min (-possible_out, preferred_out));
+                               UPTO (-possible_out)
                        } else {
                                /* exact number of outputs */
                                FOUNDCFG (possible_out);
                        } else {
                                /* exact number of outputs */
                                FOUNDCFG (possible_out);
@@ -523,13 +541,17 @@ LuaProc::can_support_io_configuration (const ChanCount& in, ChanCount& out, Chan
                }
        }
 
                }
        }
 
-
        if (!found) {
                return false;
        }
 
        if (!found) {
                return false;
        }
 
-       out.set (DataType::MIDI, midi_out); // currently always zero
-       out.set (DataType::AUDIO, audio_out);
+       if (exact_match) {
+               out.set (DataType::MIDI, midi_out); // currently always zero
+               out.set (DataType::AUDIO, preferred_out);
+       } else {
+               out.set (DataType::MIDI, midi_out); // currently always zero
+               out.set (DataType::AUDIO, audio_out);
+       }
        return true;
 }
 
        return true;
 }
 
index e13328b97b89c33e667b20b7dc07203021bb43ed..43a4901ca7d5639a1619f54cda0270bad2f79577 100644 (file)
@@ -1934,7 +1934,7 @@ LV2Plugin::get_parameter_descriptor(uint32_t which, ParameterDescriptor& desc) c
 }
 
 Plugin::IOPortDescription
 }
 
 Plugin::IOPortDescription
-LV2Plugin::describe_io_port (ARDOUR::DataType dt, bool input, uint32_t id)
+LV2Plugin::describe_io_port (ARDOUR::DataType dt, bool input, uint32_t id) const
 {
        PortFlags match = 0;
        switch (dt) {
 {
        PortFlags match = 0;
        switch (dt) {
index 61141301cb13f31ad13de0c1a20e639a1c37e753..babc3e441f2344274660d5c59c27d6293dbbd4a6 100644 (file)
@@ -258,7 +258,7 @@ Plugin::input_streams () const
 }
 
 Plugin::IOPortDescription
 }
 
 Plugin::IOPortDescription
-Plugin::describe_io_port (ARDOUR::DataType dt, bool input, uint32_t id)
+Plugin::describe_io_port (ARDOUR::DataType dt, bool input, uint32_t id) const
 {
        std::stringstream ss;
        switch (dt) {
 {
        std::stringstream ss;
        switch (dt) {
@@ -278,12 +278,22 @@ Plugin::describe_io_port (ARDOUR::DataType dt, bool input, uint32_t id)
                ss << _("Out") << " ";
        }
 
                ss << _("Out") << " ";
        }
 
-       ss << id;
+       ss << (id + 1);
 
        Plugin::IOPortDescription iod (ss.str());
        return iod;
 }
 
 
        Plugin::IOPortDescription iod (ss.str());
        return iod;
 }
 
+PluginOutputConfiguration
+Plugin::possible_output () const
+{
+       PluginOutputConfiguration oc;
+       if (_info) {
+               oc.insert (_info->n_outputs.n_audio ());
+       }
+       return oc;
+}
+
 const Plugin::PresetRecord *
 Plugin::preset_by_label (const string& label)
 {
 const Plugin::PresetRecord *
 Plugin::preset_by_label (const string& label)
 {
index 2005d5b2e20f8c86b260de7c874479c211b9616c..646bf5e63a5519cd580ded16b3fe47153b2330a6 100644 (file)
@@ -159,6 +159,17 @@ PluginInsert::set_custom_cfg (bool b)
        }
 }
 
        }
 }
 
+bool
+PluginInsert::set_preset_out (const ChanCount& c)
+{
+       bool changed = _preset_out != c;
+       _preset_out = c;
+       if (changed && !_custom_cfg) {
+               PluginConfigChanged (); /* EMIT SIGNAL */
+       }
+       return changed;
+}
+
 bool
 PluginInsert::add_sidechain (uint32_t n_audio)
 {
 bool
 PluginInsert::add_sidechain (uint32_t n_audio)
 {
@@ -1383,6 +1394,8 @@ PluginInsert::configure_io (ChanCount in, ChanCount out)
                        ChanCount dout (in); // hint
                        if (_custom_cfg) { 
                                dout = _custom_out;
                        ChanCount dout (in); // hint
                        if (_custom_cfg) { 
                                dout = _custom_out;
+                       } else if (_preset_out.n_audio () > 0) {
+                               dout.set (DataType::AUDIO, _preset_out.n_audio ());
                        } else if (dout.n_midi () > 0 && dout.n_audio () == 0) {
                                dout.set (DataType::AUDIO, 2);
                        }
                        } else if (dout.n_midi () > 0 && dout.n_audio () == 0) {
                                dout.set (DataType::AUDIO, 2);
                        }
@@ -1390,7 +1403,6 @@ PluginInsert::configure_io (ChanCount in, ChanCount out)
                        ChanCount useins;
                        bool const r = _plugins.front()->can_support_io_configuration (in, dout, &useins);
                        assert (r);
                        ChanCount useins;
                        bool const r = _plugins.front()->can_support_io_configuration (in, dout, &useins);
                        assert (r);
-                       assert (dout.n_audio() <= out.n_audio()); // sans midi bypass
                        if (useins.n_audio() == 0) {
                                useins = in;
                        }
                        if (useins.n_audio() == 0) {
                                useins = in;
                        }
@@ -1529,12 +1541,29 @@ PluginInsert::can_support_io_configuration (const ChanCount& in, ChanCount& out)
        return private_can_support_io_configuration (in, out).method != Impossible;
 }
 
        return private_can_support_io_configuration (in, out).method != Impossible;
 }
 
+PluginInsert::Match
+PluginInsert::private_can_support_io_configuration (ChanCount const& in, ChanCount& out) const
+{
+       if (!_custom_cfg && _preset_out.n_audio () > 0) {
+               // preseed hint (for variable i/o)
+               out.set (DataType::AUDIO, _preset_out.n_audio ());
+       }
+
+       Match rv = internal_can_support_io_configuration (in, out);
+
+       if (!_custom_cfg && _preset_out.n_audio () > 0) {
+               DEBUG_TRACE (DEBUG::ChanMapping, string_compose ("using output preset: %1 %2\n", name(), _preset_out));
+               out.set (DataType::AUDIO, _preset_out.n_audio ());
+       }
+       return rv;
+}
+
 /** 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.
  */
 PluginInsert::Match
 /** 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.
  */
 PluginInsert::Match
-PluginInsert::private_can_support_io_configuration (ChanCount const & inx, ChanCount& out) const
+PluginInsert::internal_can_support_io_configuration (ChanCount const & inx, ChanCount& out) const
 {
        if (_plugins.empty()) {
                return Match();
 {
        if (_plugins.empty()) {
                return Match();
@@ -1848,6 +1877,7 @@ PluginInsert::state (bool full)
         * in case the plugin goes missing) */
        node.add_child_nocopy (* _configured_in.state (X_("ConfiguredInput")));
        node.add_child_nocopy (* _configured_out.state (X_("ConfiguredOutput")));
         * in case the plugin goes missing) */
        node.add_child_nocopy (* _configured_in.state (X_("ConfiguredInput")));
        node.add_child_nocopy (* _configured_out.state (X_("ConfiguredOutput")));
+       node.add_child_nocopy (* _preset_out.state (X_("PresetOutput")));
 
        /* save custom i/o config */
        node.add_property("custom", _custom_cfg ? "yes" : "no");
 
        /* save custom i/o config */
        node.add_property("custom", _custom_cfg ? "yes" : "no");
@@ -2121,6 +2151,9 @@ PluginInsert::set_state(const XMLNode& node, int version)
                if ((*i)->name() == X_("ConfiguredOutput")) {
                        _custom_out = ChanCount(**i);
                }
                if ((*i)->name() == X_("ConfiguredOutput")) {
                        _custom_out = ChanCount(**i);
                }
+               if ((*i)->name() == X_("PresetOutput")) {
+                       _preset_out = ChanCount(**i);
+               }
                if (strncmp ((*i)->name ().c_str(), X_("InputMap-"), 9) == 0) {
                        long pc = atol (&((*i)->name().c_str()[9]));
                        if (pc >=0 && pc <= get_count()) {
                if (strncmp ((*i)->name ().c_str(), X_("InputMap-"), 9) == 0) {
                        long pc = atol (&((*i)->name().c_str()[9]));
                        if (pc >=0 && pc <= get_count()) {
index 51fc33a39509cb97bb83c0295d8163876bc637fc..7ef2a62a24b4e00dcbba86a92f3bfb818ebd04f6 100644 (file)
@@ -2505,6 +2505,45 @@ Route::add_remove_sidechain (boost::shared_ptr<Processor> proc, bool add)
        return true;
 }
 
        return true;
 }
 
+bool
+Route::plugin_preset_output (boost::shared_ptr<Processor> proc, ChanCount outs)
+{
+       boost::shared_ptr<PluginInsert> pi;
+       if ((pi = boost::dynamic_pointer_cast<PluginInsert>(proc)) == 0) {
+               return false;
+       }
+
+       {
+               Glib::Threads::RWLock::ReaderLock lm (_processor_lock);
+               ProcessorList::iterator i = find (_processors.begin(), _processors.end(), proc);
+               if (i == _processors.end ()) {
+                       return false;
+               }
+       }
+
+       {
+               Glib::Threads::Mutex::Lock lx (AudioEngine::instance()->process_lock ());
+               Glib::Threads::RWLock::WriterLock lm (_processor_lock);
+
+               const ChanCount& old (pi->preset_out ());
+               if (!pi->set_preset_out (outs)) {
+                       return true; // no change, OK
+               }
+
+               list<pair<ChanCount, ChanCount> > c = try_configure_processors_unlocked (n_inputs (), 0);
+               if (c.empty()) {
+                       /* not possible */
+                       pi->set_preset_out (old);
+                       return false;
+               }
+               configure_processors_unlocked (0);
+       }
+
+       processors_changed (RouteProcessorChange ()); /* EMIT SIGNAL */
+       _session.set_dirty ();
+       return true;
+}
+
 bool
 Route::reset_plugin_insert (boost::shared_ptr<Processor> proc)
 {
 bool
 Route::reset_plugin_insert (boost::shared_ptr<Processor> proc)
 {