SDK v2.3 was just tagged (api-v2.3.0), and with it come some new safety features as well as helpers for USB and USB-MIDI:
Exceptions (out of memory)
tl:dr: Use try/catch around all large memory allocations.
Plugins can throw and catch exceptions across the plugin/host boundary now.
If your plugin is allocating memory, and the allocation fails because we’re out of memory, your plugin will get a std::bad_alloc exception which you can (and should) catch and respond to gracefully.
Example:
std::vector<float> sample_data;
try {
sample_data.resize(sample_size);
sample_loaded = true;
} catch (std::bad_alloc &) {
Gui::notify_user("Could not allocate memory for the sample. Choose a smaller file.", 2000);
sample_loaded = false;
}
If you do it like above, then if the MetaModule runs out of memory, your module will just pop up a notification to the user, and the patch will continue being played. No memory is leaked, nothing crashes.
On the other hand, if you don’t catch failed allocations, like this:
std::vector<float> sample_data;
sample_data.resize(sample_size);
sample_loaded = true; // BUG: need to check if allocation succeeded
In the above example, if there’s not enough memory to resize sample_data, then the patch will be stopped, the user will get a generic “The module crashed” notification, and then different things happen depending on the context:
- If the module is already in a playing patch, the module will be in a possibly corrupted state (future firmware may try to remove the module or the plugin)
- If the failed allocation happened in the module’s constructor when the user attempted to add the module to the patch or open a patch with that module in it, then the module will not be added. Any dynamic memory already allocated by the module will be leaked.
- If the failed allocation happened in plugin
init(), then the plugin will be removed.
Clearly, the first example with try/catch is much better because memory will not be leaked, and your module can take alternative actions or at least inform the user what’s going on. In the second example case, there’s a chance that memory was leaked, and a chance the module is in a corrupted state and will crash if the user tries again.
USB and USB-MIDI Queries
Added USB query functions (see System API):
- System::get_usb_connection_status()
- System::get_usb_device_name()
- System::get_usb_midi_rx_cable() and System::get_usb_midi_tx_cable(): look
up a MIDI port of the attached device by cable number, so a module can
list the ports by name, filter incoming messages based on cable number, and/or
transmit messages over a particular cable. - System::get_usb_midi_in_jack_info() and System::get_usb_midi_out_jack_info():
low-level information from the device’s descriptors.
Example for filtering MIDI RX by a cable name:
auto status = System::get_usb_connection_status();
for (unsigned c = 0; c < status.num_midi_rx_cables; c++) {
auto cable = System::get_usb_midi_rx_cable(c);
if (cable.name.contains("Kontrol DAW")) {
my_port = c;
}
}
if (auto msg = midi.pop_message()) {
if (msg->usb_hdr.cable_num == my_port)
process(*msg);
}
Fixed a non-working MIDI classes:
- Fixed MidiInput and MidiOutput API: some headers were missing, making them
unusable in v2.2.0 and v2.2.1 - Added docs for MIDI classes: docs/midi.md
Test Plugins
In the SDK, in the test/ folder are some example plugins that are meant to test and demonstrate usage. Feel free to poke around or run them on hardware.
- Implemented test plugins:
tests/exceptions-testtests OOM/bad_alloc and more- tests/usb-info-test` dumps everything the USB query API reports to the console.
tests/midi-testconverts incoming MIDI to gate/pitch CV and gate/CV
back to outgoing Note On/Off, with an LED to verify MIDI rx unpatched. Also
demonstrates filtering based on cable number.