More robust plugin I/O mapping.
authorDavid Robillard <d@drobilla.net>
Fri, 21 Oct 2011 04:51:04 +0000 (04:51 +0000)
committerDavid Robillard <d@drobilla.net>
Fri, 21 Oct 2011 04:51:04 +0000 (04:51 +0000)
This does not change the actual mapping logic, but makes the application of
the mapping much more robust.  If there is no valid mapping for a given port,
that port is connected to silence (instead of crashing messily and/or via a
failed assertion).

Also tolerate mappings that nonsensically map to a buffer that is not present
(this particularly happens for MIDI ports in some cases) as a temporary fix.
The mapping logic needs work and/or our concept of just how much MIDI we support
in a route needs simplification...

git-svn-id: svn://localhost/ardour2/branches/3.0@10262 d708f5d6-7413-0410-9779-e7cbd77b26cf

libs/ardour/ardour/chan_mapping.h
libs/ardour/chan_mapping.cc
libs/ardour/ladspa_plugin.cc
libs/ardour/lv2_plugin_lilv.cc
libs/ardour/plugin_insert.cc

index 90b1d6fdf31fc71674313a02125058bc4d1e1cef..5b63844f66903efdef578ae1703cb7a9e25ed510 100644 (file)
@@ -39,7 +39,7 @@ public:
        ChanMapping() {}
        ChanMapping(ARDOUR::ChanCount identity);
 
-       uint32_t get(DataType t, uint32_t from);
+       uint32_t get(DataType t, uint32_t from, bool* valid);
        void     set(DataType t, uint32_t from, uint32_t to);
        void     offset_from(DataType t, int32_t delta);
        void     offset_to(DataType t, int32_t delta);
index 3f7ccad8f9722dc7b3f03818927ed45786a93e6b..5c5bb17de67a292c3094eb4584dbf25e84779603 100644 (file)
@@ -41,12 +41,19 @@ ChanMapping::ChanMapping(ChanCount identity)
 }
 
 uint32_t
-ChanMapping::get(DataType t, uint32_t from)
+ChanMapping::get(DataType t, uint32_t from, bool* valid)
 {
        Mappings::iterator tm = _mappings.find(t);
-       assert(tm != _mappings.end());
+       if (tm == _mappings.end()) {
+               *valid = false;
+               return -1;
+       }
        TypeMapping::iterator m = tm->second.find(from);
-       assert(m != tm->second.end());
+       if (m == tm->second.end()) {
+               *valid = false;
+               return -1;
+       }
+       *valid = true;
        return m->second;
 }
 
index ef1a6b66823a8413cb540446425171351a0d2c94..b9400dd8d8d63431982f83a2d5d6f0b75b9a5de2 100644 (file)
@@ -548,16 +548,24 @@ LadspaPlugin::connect_and_run (BufferSet& bufs,
        cycles_t now;
        cycles_t then = get_cycles ();
 
+       BufferSet& silent_bufs  = _session.get_silent_buffers(ChanCount(DataType::AUDIO, 1));
+       BufferSet& scratch_bufs = _session.get_silent_buffers(ChanCount(DataType::AUDIO, 1));
+
        uint32_t audio_in_index  = 0;
        uint32_t audio_out_index = 0;
+       bool valid;
        for (uint32_t port_index = 0; port_index < parameter_count(); ++port_index) {
                if (LADSPA_IS_PORT_AUDIO(port_descriptor(port_index))) {
                        if (LADSPA_IS_PORT_INPUT(port_descriptor(port_index))) {
-                               const uint32_t buf_index = in_map.get(DataType::AUDIO, audio_in_index++);
-                               connect_port(port_index, bufs.get_audio(buf_index).data(offset));
+                               const uint32_t buf_index = in_map.get(DataType::AUDIO, audio_in_index++, &valid);
+                               connect_port(port_index,
+                                            valid ? bufs.get_audio(buf_index).data(offset)
+                                                  : silent_bufs.get_audio(0).data(offset));
                        } else if (LADSPA_IS_PORT_OUTPUT(port_descriptor(port_index))) {
-                               const uint32_t buf_index = out_map.get(DataType::AUDIO, audio_out_index++);
-                               connect_port(port_index, bufs.get_audio(buf_index).data(offset));
+                               const uint32_t buf_index = out_map.get(DataType::AUDIO, audio_out_index++, &valid);
+                               connect_port(port_index,
+                                            valid ? bufs.get_audio(buf_index).data(offset)
+                                                  : scratch_bufs.get_audio(0).data(offset));
                        }
                }
        }
index a1f42e640769a892171bd4672a02655ff530bcb5..25020e541a530e56127d5b26283b156032124118 100644 (file)
@@ -908,31 +908,54 @@ LV2Plugin::connect_and_run(BufferSet& bufs,
 
        cycles_t then = get_cycles();
 
+       ChanCount bufs_count;
+       bufs_count.set(DataType::AUDIO, 1);
+       bufs_count.set(DataType::MIDI, 1);
+       BufferSet& silent_bufs  = _session.get_silent_buffers(bufs_count);
+       BufferSet& scratch_bufs = _session.get_silent_buffers(bufs_count);
+
        uint32_t audio_in_index  = 0;
        uint32_t audio_out_index = 0;
        uint32_t midi_in_index   = 0;
        uint32_t midi_out_index  = 0;
+       bool valid;
        for (uint32_t port_index = 0; port_index < parameter_count(); ++port_index) {
                if (parameter_is_audio(port_index)) {
                        if (parameter_is_input(port_index)) {
-                               const uint32_t buf_index = in_map.get(DataType::AUDIO, audio_in_index++);
+                               const uint32_t buf_index = in_map.get(DataType::AUDIO, audio_in_index++, &valid);
                                lilv_instance_connect_port(_impl->instance, port_index,
-                                                          bufs.get_audio(buf_index).data(offset));
+                                                          valid ? bufs.get_audio(buf_index).data(offset)
+                                                                : silent_bufs.get_audio(0).data(offset));
                        } else if (parameter_is_output(port_index)) {
-                               const uint32_t buf_index = out_map.get(DataType::AUDIO, audio_out_index++);
+                               const uint32_t buf_index = out_map.get(DataType::AUDIO, audio_out_index++, &valid);
                                //cerr << port_index << " : " << " AUDIO OUT " << buf_index << endl;
                                lilv_instance_connect_port(_impl->instance, port_index,
-                                                          bufs.get_audio(buf_index).data(offset));
+                                                          valid ? bufs.get_audio(buf_index).data(offset)
+                                                                : scratch_bufs.get_audio(0).data(offset));
                        }
                } else if (parameter_is_midi(port_index)) {
+                       /* FIXME: The checks here for bufs.count().n_midi() > buf_index shouldn't
+                          be necessary, but the mapping is illegal in some cases.  Ideally
+                          that should be fixed, but this is easier...
+                       */
                        if (parameter_is_input(port_index)) {
-                               const uint32_t buf_index = in_map.get(DataType::MIDI, midi_in_index++);
-                               lilv_instance_connect_port(_impl->instance, port_index,
-                                                          bufs.get_lv2_midi(true, buf_index).data());
+                               const uint32_t buf_index = in_map.get(DataType::MIDI, midi_in_index++, &valid);
+                               if (valid && bufs.count().n_midi() > buf_index) {
+                                       lilv_instance_connect_port(_impl->instance, port_index,
+                                                                  bufs.get_lv2_midi(true, buf_index).data());
+                               } else {
+                                       lilv_instance_connect_port(_impl->instance, port_index,
+                                                                  silent_bufs.get_lv2_midi(true, 0).data());
+                               }
                        } else if (parameter_is_output(port_index)) {
-                               const uint32_t buf_index = out_map.get(DataType::MIDI, midi_out_index++);
-                               lilv_instance_connect_port(_impl->instance, port_index,
-                                                          bufs.get_lv2_midi(false, buf_index).data());
+                               const uint32_t buf_index = out_map.get(DataType::MIDI, midi_out_index++, &valid);
+                               if (valid && bufs.count().n_midi() > buf_index) {
+                                       lilv_instance_connect_port(_impl->instance, port_index,
+                                                                  bufs.get_lv2_midi(false, buf_index).data());
+                               } else {
+                                       lilv_instance_connect_port(_impl->instance, port_index,
+                                                                  scratch_bufs.get_lv2_midi(true, 0).data());
+                               }
                        }
                } else if (!parameter_is_control(port_index)) {
                        // Optional port (it'd better be if we've made it this far...)
@@ -945,8 +968,10 @@ LV2Plugin::connect_and_run(BufferSet& bufs,
        midi_out_index = 0;
        for (uint32_t port_index = 0; port_index < parameter_count(); ++port_index) {
                if (parameter_is_midi(port_index) && parameter_is_output(port_index)) {
-                       const uint32_t buf_index = out_map.get(DataType::MIDI, midi_out_index++);
-                       bufs.flush_lv2_midi(true, buf_index);
+                       const uint32_t buf_index = out_map.get(DataType::MIDI, midi_out_index++, &valid);
+                       if (valid) {
+                               bufs.flush_lv2_midi(true, buf_index);
+                       }
                }
        }
 
index 1bdf7e32d08cf34002e806586d831f4530ee8bce..aa5eeaea3b95e7a14101782d40c3eb2c6055e386 100644 (file)
@@ -322,16 +322,16 @@ PluginInsert::connect_and_run (BufferSet& bufs, pframes_t nframes, framecnt_t of
 
        ChanMapping in_map (in_streams);
        ChanMapping out_map (out_streams);
-
+       bool valid;
        if (_match.method == Split) {
                /* fix the input mapping so that we have maps for each of the plugin's inputs */
                in_map = ChanMapping (natural_input_streams ());
 
                /* copy the first stream's buffer contents to the others */
                /* XXX: audio only */
-               Sample const * mono = bufs.get_audio (in_map.get (DataType::AUDIO, 0)).data (offset);
+               Sample const * mono = bufs.get_audio (in_map.get (DataType::AUDIO, 0, &valid)).data (offset);
                for (uint32_t i = in_streams.n_audio(); i < natural_input_streams().n_audio(); ++i) {
-                       memcpy (bufs.get_audio (in_map.get (DataType::AUDIO, i)).data (offset), mono, sizeof (Sample) * nframes);
+                       memcpy (bufs.get_audio (in_map.get (DataType::AUDIO, i, &valid)).data (offset), mono, sizeof (Sample) * nframes);
                }
        }