From 96dcffcb222bc920cef9bfbaffb0548138352d65 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Fri, 21 Oct 2011 04:51:04 +0000 Subject: [PATCH] More robust plugin I/O mapping. 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 | 2 +- libs/ardour/chan_mapping.cc | 13 ++++++-- libs/ardour/ladspa_plugin.cc | 16 +++++++--- libs/ardour/lv2_plugin_lilv.cc | 49 +++++++++++++++++++++++-------- libs/ardour/plugin_insert.cc | 6 ++-- 5 files changed, 63 insertions(+), 23 deletions(-) diff --git a/libs/ardour/ardour/chan_mapping.h b/libs/ardour/ardour/chan_mapping.h index 90b1d6fdf3..5b63844f66 100644 --- a/libs/ardour/ardour/chan_mapping.h +++ b/libs/ardour/ardour/chan_mapping.h @@ -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); diff --git a/libs/ardour/chan_mapping.cc b/libs/ardour/chan_mapping.cc index 3f7ccad8f9..5c5bb17de6 100644 --- a/libs/ardour/chan_mapping.cc +++ b/libs/ardour/chan_mapping.cc @@ -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; } diff --git a/libs/ardour/ladspa_plugin.cc b/libs/ardour/ladspa_plugin.cc index ef1a6b6682..b9400dd8d8 100644 --- a/libs/ardour/ladspa_plugin.cc +++ b/libs/ardour/ladspa_plugin.cc @@ -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)); } } } diff --git a/libs/ardour/lv2_plugin_lilv.cc b/libs/ardour/lv2_plugin_lilv.cc index a1f42e6407..25020e541a 100644 --- a/libs/ardour/lv2_plugin_lilv.cc +++ b/libs/ardour/lv2_plugin_lilv.cc @@ -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); + } } } diff --git a/libs/ardour/plugin_insert.cc b/libs/ardour/plugin_insert.cc index 1bdf7e32d0..aa5eeaea3b 100644 --- a/libs/ardour/plugin_insert.cc +++ b/libs/ardour/plugin_insert.cc @@ -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); } } -- 2.30.2