fix typo
[ardour.git] / libs / ardour / plugin_insert.cc
index 267dd23dbff7037e9a5a616ab8ab09dd41db40f7..9e55979a244dd9bc2ab0720afe8d09c53dad2ebc 100644 (file)
@@ -418,7 +418,7 @@ PluginInsert::connect_and_run (BufferSet& bufs, pframes_t nframes, framecnt_t of
        // Currently this never triggers because the in_map for "Split" triggeres no_inplace.
        if (_match.method == Split && !_no_inplace) {
                assert (in_map.size () == 1);
-               in_map[0] = ChanMapping (max (natural_input_streams (), _configured_in));
+               in_map[0] = ChanMapping (ChanCount::max (natural_input_streams (), _configured_in));
                ChanCount const in_streams = internal_input_streams ();
                /* copy the first stream's audio buffer contents to the others */
                bool valid;
@@ -494,12 +494,12 @@ PluginInsert::connect_and_run (BufferSet& bufs, pframes_t nframes, framecnt_t of
 #ifdef MIXBUS
        if (_plugins.front()->is_channelstrip() ) {
                if (_configured_in.n_audio() > 0) {
-                       ChanMapping mb_in_map (min (_configured_in, ChanCount (DataType::AUDIO, 2)));
-                       ChanMapping mb_out_map (min (_configured_out, ChanCount (DataType::AUDIO, 2)));
+                       ChanMapping mb_in_map (ChanCount::min (_configured_in, ChanCount (DataType::AUDIO, 2)));
+                       ChanMapping mb_out_map (ChanCount::min (_configured_out, ChanCount (DataType::AUDIO, 2)));
 
                        _plugins.front()->connect_and_run (bufs, mb_in_map, mb_out_map, nframes, offset);
 
-                       for (uint32_t out = _configured_in.n_audio; out < bufs.count().get (DataType::AUDIO); ++out) {
+                       for (uint32_t out = _configured_in.n_audio (); out < bufs.count().get (DataType::AUDIO); ++out) {
                                bufs.get (DataType::AUDIO, out).silence (nframes, offset);
                        }
                }
@@ -567,7 +567,7 @@ PluginInsert::connect_and_run (BufferSet& bufs, pframes_t nframes, framecnt_t of
                /* all instances have completed, now clear outputs that have not been written to.
                 * (except midi bypass)
                 */
-               if (bufs.count().n_midi() == 1 && natural_output_streams().get(DataType::MIDI) == 0) {
+               if (has_midi_bypass ()) {
                        used_outputs.set (DataType::MIDI, 0, 1); // Midi bypass.
                }
                for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
@@ -592,6 +592,9 @@ PluginInsert::connect_and_run (BufferSet& bufs, pframes_t nframes, framecnt_t of
                for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
                        for (uint32_t out = 0; out < bufs.count().get (*t); ++out) {
                                bool mapped = false;
+                               if (*t == DataType::MIDI && out == 0 && has_midi_bypass ()) {
+                                       mapped = true; // in-place Midi bypass
+                               }
                                for (uint32_t pc = 0; pc < get_count() && !mapped; ++pc) {
                                        for (uint32_t o = 0; o < natural_output_streams().get (*t); ++o) {
                                                bool valid;
@@ -892,6 +895,53 @@ PluginInsert::set_output_map (uint32_t num, ChanMapping m) {
        }
 }
 
+ChanMapping
+PluginInsert::input_map () const
+{
+       ChanMapping rv;
+       uint32_t pc = 0;
+       for (PinMappings::const_iterator i = _in_map.begin (); i != _in_map.end (); ++i, ++pc) {
+               ChanMapping m (i->second);
+               const ChanMapping::Mappings& mp ((*i).second.mappings());
+               for (ChanMapping::Mappings::const_iterator tm = mp.begin(); tm != mp.end(); ++tm) {
+                       for (ChanMapping::TypeMapping::const_iterator i = tm->second.begin(); i != tm->second.end(); ++i) {
+                               rv.set (tm->first, i->first + pc * natural_input_streams().get(tm->first), i->second);
+                       }
+               }
+       }
+       return rv;
+}
+
+ChanMapping
+PluginInsert::output_map () const
+{
+       ChanMapping rv;
+       uint32_t pc = 0;
+       for (PinMappings::const_iterator i = _out_map.begin (); i != _out_map.end (); ++i, ++pc) {
+               ChanMapping m (i->second);
+               const ChanMapping::Mappings& mp ((*i).second.mappings());
+               for (ChanMapping::Mappings::const_iterator tm = mp.begin(); tm != mp.end(); ++tm) {
+                       for (ChanMapping::TypeMapping::const_iterator i = tm->second.begin(); i != tm->second.end(); ++i) {
+                               rv.set (tm->first, i->first + pc * natural_output_streams().get(tm->first), i->second);
+                       }
+               }
+       }
+       if (has_midi_bypass ()) {
+               rv.set (DataType::MIDI, 0, 0);
+       }
+
+       return rv;
+}
+
+bool
+PluginInsert::has_midi_bypass () const
+{
+       if (_configured_in.n_midi () == 1 && _configured_out.n_midi () == 1 && natural_output_streams ().n_midi () == 0) {
+               return true;
+       }
+       return false;
+}
+
 bool
 PluginInsert::configure_io (ChanCount in, ChanCount out)
 {
@@ -909,6 +959,9 @@ PluginInsert::configure_io (ChanCount in, ChanCount out)
 
        /* get plugin configuration */
        _match = private_can_support_io_configuration (in, out);
+#ifndef NDEBUG // XXX
+       cout << "Match '" << name() << "': " << _match;
+#endif
 
        /* set the matching method and number of plugins that we will use to meet this configuration */
        if (set_count (_match.plugins) == false) {
@@ -1006,9 +1059,9 @@ PluginInsert::configure_io (ChanCount in, ChanCount out)
                                        }
                                }
                        } else {
-                               _in_map[pc] = ChanMapping (min (natural_input_streams (), in));
+                               _in_map[pc] = ChanMapping (ChanCount::min (natural_input_streams (), in));
                        }
-                       _out_map[pc] = ChanMapping (min (natural_output_streams(), out));
+                       _out_map[pc] = ChanMapping (ChanCount::min (natural_output_streams(), out));
 
                        for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
                                _in_map[pc].offset_to(*t, pc * natural_input_streams().get(*t));
@@ -1020,7 +1073,7 @@ PluginInsert::configure_io (ChanCount in, ChanCount out)
 
        if (mapping_changed) {
                PluginMapChanged (); /* EMIT SIGNAL */
-#ifndef NDEBUG
+#ifndef NDEBUG // XXX
                uint32_t pc = 0;
                cout << "----<<----\n";
                for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i, ++pc) {
@@ -1085,14 +1138,16 @@ PluginInsert::private_can_support_io_configuration (ChanCount const & inx, ChanC
                return Match (ExactMatch, get_count(), false, true); // XXX
        }
 
-       /* try automatic configuration next */
+       /* try automatic configuration */
        Match m = PluginInsert::automatic_can_support_io_configuration (inx, out);
 
-
        PluginInfoPtr info = _plugins.front()->get_info();
        ChanCount inputs  = info->n_inputs;
        ChanCount outputs = info->n_outputs;
        ChanCount midi_bypass;
+       if (inx.get(DataType::MIDI) == 1 && outputs.get(DataType::MIDI) == 0) {
+               midi_bypass.set (DataType::MIDI, 1);
+       }
 
        /* handle case strict-i/o */
        if (_strict_io && m.method != Impossible) {
@@ -1103,13 +1158,13 @@ PluginInsert::private_can_support_io_configuration (ChanCount const & inx, ChanC
                        // output = midi-bypass + at most master-out channels.
                        ChanCount max_out (DataType::AUDIO, 2); // TODO use master-out
                        max_out.set (DataType::MIDI, out.get(DataType::MIDI));
-                       out = min (out, max_out);
+                       out = ChanCount::min (out, max_out);
                        return m;
                }
 
                switch (m.method) {
                        case NoInputs:
-                               if (inx != out) {
+                               if (inx.n_audio () != out.n_audio ()) { // ignore midi bypass
                                        /* replicate processor to match output count (generators and such)
                                         * at least enough to feed every output port. */
                                        uint32_t f = 1; // at least one. e.g. control data filters, no in, no out.
@@ -1118,7 +1173,7 @@ PluginInsert::private_can_support_io_configuration (ChanCount const & inx, ChanC
                                                if (nin == 0 || inx.get(*t) == 0) { continue; }
                                                f = max (f, (uint32_t) ceil (inx.get(*t) / (float)nin));
                                        }
-                                       out = inx;
+                                       out = inx + midi_bypass;
                                        return Match (Replicate, f);
                                }
                                break;
@@ -1127,9 +1182,8 @@ PluginInsert::private_can_support_io_configuration (ChanCount const & inx, ChanC
                        default:
                                break;
                }
-               if (inx == out) { return m; }
 
-               out = inx;
+               out = inx + midi_bypass;
                if (inx.get(DataType::MIDI) == 1
                                && out.get (DataType::MIDI) == 0
                                && outputs.get(DataType::MIDI) == 0) {
@@ -1162,7 +1216,7 @@ PluginInsert::private_can_support_io_configuration (ChanCount const & inx, ChanC
                f = max (f, (uint32_t) floor (inx.get(*t) / (float)nout));
        }
        if (f > 0 && outputs * f >= _configured_out) {
-               out = outputs * f;
+               out = outputs * f + midi_bypass;
                return Match (Replicate, f);
        }
 
@@ -1173,7 +1227,7 @@ PluginInsert::private_can_support_io_configuration (ChanCount const & inx, ChanC
                if (nin == 0 || inx.get(*t) == 0) { continue; }
                f = max (f, (uint32_t) ceil (inx.get(*t) / (float)nin));
        }
-       out = outputs * f;
+       out = outputs * f + midi_bypass;
        return Match (Replicate, f);
 }
 
@@ -1203,7 +1257,7 @@ PluginInsert::automatic_can_support_io_configuration (ChanCount const & inx, Cha
 
        if (in.get(DataType::MIDI) == 1 && outputs.get(DataType::MIDI) == 0) {
                DEBUG_TRACE ( DEBUG::Processors, string_compose ("bypassing midi-data around %1\n", name()));
-               midi_bypass.set(DataType::MIDI, 1);
+               midi_bypass.set (DataType::MIDI, 1);
        }
        if (in.get(DataType::MIDI) == 1 && inputs.get(DataType::MIDI) == 0) {
                DEBUG_TRACE ( DEBUG::Processors, string_compose ("hiding midi-port from plugin %1\n", name()));
@@ -1264,7 +1318,7 @@ PluginInsert::automatic_can_support_io_configuration (ChanCount const & inx, Cha
                }
        }
 
-       if (can_replicate) {
+       if (can_replicate && f > 0) {
                for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
                        out.set (*t, outputs.get(*t) * f);
                }
@@ -1320,7 +1374,6 @@ PluginInsert::automatic_can_support_io_configuration (ChanCount const & inx, Cha
                return Match (Hide, 1, false, false, hide_channels);
        }
 
-       midi_bypass.reset();
        return Match (Impossible, 0);
 }
 
@@ -1993,3 +2046,24 @@ PluginInsert::end_touch (uint32_t param_id)
                 ac->stop_touch (true, session().audible_frame());
         }
 }
+
+std::ostream& operator<<(std::ostream& o, const ARDOUR::PluginInsert::Match& m)
+{
+       switch (m.method) {
+               case PluginInsert::Impossible: o << "Impossible"; break;
+               case PluginInsert::Delegate:   o << "Delegate"; break;
+               case PluginInsert::NoInputs:   o << "NoInputs"; break;
+               case PluginInsert::ExactMatch: o << "ExactMatch"; break;
+               case PluginInsert::Replicate:  o << "Replicate"; break;
+               case PluginInsert::Split:      o << "Split"; break;
+               case PluginInsert::Hide:       o << "Hide"; break;
+       }
+       o << " cnt: " << m.plugins
+               << (m.strict_io ? " strict-io" : "")
+               << (m.custom_cfg ? " custom-cfg" : "");
+       if (m.method == PluginInsert::Hide) {
+               o << " hide: " << m.hide;
+       }
+       o << "\n";
+       return o;
+}