diff --git a/plugins/lv2/sfizz.cpp b/plugins/lv2/sfizz.cpp index 3998c0646..65474bd9d 100644 --- a/plugins/lv2/sfizz.cpp +++ b/plugins/lv2/sfizz.cpp @@ -117,6 +117,7 @@ sfizz_lv2_map_required_uris(sfizz_plugin_t *self) self->state_changed_uri = map->map(map->handle, LV2_STATE__StateChanged); self->sfizz_sfz_file_uri = map->map(map->handle, SFIZZ__sfzFile); self->sfizz_scala_file_uri = map->map(map->handle, SFIZZ__tuningfile); + self->sfizz_description_uri = map->map(map->handle, SFIZZ__description); self->sfizz_num_voices_uri = map->map(map->handle, SFIZZ__numVoices); self->sfizz_preload_size_uri = map->map(map->handle, SFIZZ__preloadSize); self->sfizz_oversampling_uri = map->map(map->handle, SFIZZ__oversampling); @@ -658,6 +659,9 @@ instantiate(const LV2_Descriptor *descriptor, sfizz_lv2_update_timeinfo(self, 0, ~0); + self->text_description[0] = 0; + self->resend_description = false; + #if defined(SFIZZ_LV2_UI) if (self->multi_out) self->rms_follower.setNumOutputs(MULTI_OUTPUT_COUNT); @@ -719,6 +723,25 @@ sfizz_lv2_send_file_path(sfizz_plugin_t *self, LV2_URID verb_uri, LV2_URID urid, lv2_atom_forge_pop(forge, &frame); } +static void +sfizz_lv2_send_instrument_description(sfizz_plugin_t *self) +{ + LV2_Atom_Forge_Frame frame; + LV2_Atom_Forge* forge = &self->forge_automate; + + bool write_ok = + lv2_atom_forge_frame_time(forge, 0) && + lv2_atom_forge_object(forge, &frame, 0, self->patch_set_uri) && + lv2_atom_forge_key(forge, self->patch_property_uri) && + lv2_atom_forge_urid(forge, self->sfizz_description_uri) && + lv2_atom_forge_key(forge, self->patch_value_uri) && + lv2_atom_forge_string(forge, self->text_description, + (uint32_t)strnlen(self->text_description, sizeof(self->text_description))); + + if (write_ok) + lv2_atom_forge_pop(forge, &frame); +} + static void sfizz_lv2_send_controller(sfizz_plugin_t *self, LV2_URID verb_uri, unsigned cc, float value) { @@ -839,12 +862,6 @@ sfizz_lv2_handle_atom_object(sfizz_plugin_t *self, int delay, const LV2_Atom_Obj } } -static bool -sfizz_is_sustain_or_sostenuto(sfizz_plugin_t* self, unsigned cc) -{ - return (self->sustain_or_sostenuto[cc / 8] & (1 << (cc % 8))); -} - static void sfizz_lv2_process_midi_event(sfizz_plugin_t *self, const LV2_Atom_Event *ev) { @@ -1072,6 +1089,8 @@ run(LV2_Handle instance, uint32_t sample_count) for (unsigned cc = 0; cc < sfz::config::numCCs; ++cc) sfizz_lv2_send_controller(self, self->sfizz_notify_uri, cc, self->cc_current[cc]); + + sfizz_lv2_send_instrument_description(self); } else if (property->body == self->sfizz_sfz_file_uri) { @@ -1081,6 +1100,10 @@ run(LV2_Handle instance, uint32_t sample_count) { sfizz_lv2_send_file_path(self, self->sfizz_notify_uri, self->sfizz_scala_file_uri, self->scala_file_path); } + else if (property->body == self->sfizz_description_uri) + { + sfizz_lv2_send_instrument_description(self); + } else { int cc = sfizz_lv2_ccmap_unmap(self->ccmap, property->body); @@ -1193,6 +1216,10 @@ run(LV2_Handle instance, uint32_t sample_count) *(self->num_groups_port) = sfizz_get_num_groups(self->synth); *(self->num_regions_port) = sfizz_get_num_regions(self->synth); *(self->num_samples_port) = sfizz_get_num_preloaded_samples(self->synth); + if (self->resend_description) { + sfizz_lv2_send_instrument_description(self); + self->resend_description = false; + } // Log the buffer usage self->sample_counter += (int)sample_count; @@ -1379,15 +1406,20 @@ sfizz_lv2_update_sfz_info(sfizz_plugin_t *self) // const InstrumentDescription desc = parseDescriptionBlob(blob); + char *cursor = self->text_description; + char *end = self->text_description + sizeof(self->text_description); + cursor += snprintf(cursor, end - cursor, "CC used:\n"); for (unsigned cc = 0; cc < sfz::config::numCCs; ++cc) { if (desc.ccUsed.test(cc) && !desc.sustainOrSostenuto.test(cc)) { // Update the current CCs self->cc_current[cc] = desc.ccValue[cc]; + if (desc.ccLabel[cc].empty()) + cursor += snprintf(cursor, end - cursor, "- %d\n", cc); + else + cursor += snprintf(cursor, end - cursor, "- %d: %s\n", + cc, desc.ccLabel[cc].c_str()); } } - - memcpy(self->sustain_or_sostenuto, desc.sustainOrSostenuto.data(), - sizeof(self->sustain_or_sostenuto)); } static bool @@ -1653,15 +1685,15 @@ save(LV2_Handle instance, } static void -sfizz_lv2_activate_file_checking( - sfizz_plugin_t *self, +sfizz_lv2_respond_with_simple_atom( LV2_Worker_Respond_Function respond, - LV2_Worker_Respond_Handle handle) + LV2_Worker_Respond_Handle handle, + uint32_t type_uri) { - LV2_Atom check_modification_atom; - check_modification_atom.size = 0; - check_modification_atom.type = self->sfizz_check_modification_uri; - respond(handle, lv2_atom_total_size(&check_modification_atom), &check_modification_atom); + LV2_Atom atom; + atom.size = 0; + atom.type = type_uri; + respond(handle, lv2_atom_total_size(&atom), &atom); } // This runs in a lower priority thread @@ -1694,7 +1726,8 @@ work(LV2_Handle instance, } // Reactivate checking for file changes - sfizz_lv2_activate_file_checking(self, respond, handle); + sfizz_lv2_respond_with_simple_atom(respond, handle, self->sfizz_check_modification_uri); + sfizz_lv2_respond_with_simple_atom(respond, handle, self->sfizz_description_uri); } else if (atom->type == self->sfizz_scala_file_uri) { @@ -1712,7 +1745,7 @@ work(LV2_Handle instance, } // Reactivate checking for file changes - sfizz_lv2_activate_file_checking(self, respond, handle); + sfizz_lv2_respond_with_simple_atom(respond, handle, self->sfizz_check_modification_uri); } else if (atom->type == self->sfizz_num_voices_uri) { @@ -1777,6 +1810,8 @@ work(LV2_Handle instance, lv2_log_error(&self->logger, "[sfizz] Error with %s; no file should be loaded\n", self->sfz_file_path); } + + sfizz_lv2_respond_with_simple_atom(respond, handle, self->sfizz_description_uri); } if (sfizz_should_reload_scala(self->synth)) @@ -1798,7 +1833,7 @@ work(LV2_Handle instance, } // Reactivate checking for file changes - sfizz_lv2_activate_file_checking(self, respond, handle); + sfizz_lv2_respond_with_simple_atom(respond, handle, self->sfizz_check_modification_uri); } else { @@ -1827,6 +1862,8 @@ work_response(LV2_Handle instance, const LV2_Atom *atom = (const LV2_Atom *)data; if (atom->type == self->sfizz_check_modification_uri) { self->check_modification = true; // check changes + } else if (atom->type == self->sfizz_description_uri) { + self->resend_description = true; } else { lv2_log_error(&self->logger, "[sfizz] Got an unexpected atom in work response\n"); if (self->unmap) diff --git a/plugins/lv2/sfizz.ttl.in b/plugins/lv2/sfizz.ttl.in index 5d7a8f66d..a72340aa4 100644 --- a/plugins/lv2/sfizz.ttl.in +++ b/plugins/lv2/sfizz.ttl.in @@ -65,6 +65,11 @@ midnam:update a lv2:Feature . "File Scala"@it ; rdfs:range atom:Path . +<@LV2PLUGIN_URI@:description> + a lv2:Parameter ; + rdfs:label "Instrument description" ; + rdfs:range atom:String . + <@LV2PLUGIN_URI@> a doap:Project, lv2:Plugin, lv2:InstrumentPlugin ; @@ -96,6 +101,7 @@ midnam:update a lv2:Feature . patch:writable <@LV2PLUGIN_URI@:sfzfile> , <@LV2PLUGIN_URI@:tuningfile> ; + patch:readable <@LV2PLUGIN_URI@:description> ; pg:mainOutput <@LV2PLUGIN_URI@#stereo_output> ; @@ -471,6 +477,7 @@ midnam:update a lv2:Feature . patch:writable <@LV2PLUGIN_URI@:sfzfile> , <@LV2PLUGIN_URI@:tuningfile> ; + patch:readable <@LV2PLUGIN_URI@:description> ; pg:mainOutput <@LV2PLUGIN_URI@#stereo_output> ; diff --git a/plugins/lv2/sfizz_lv2.h b/plugins/lv2/sfizz_lv2.h index 69867119f..ab3dc946f 100644 --- a/plugins/lv2/sfizz_lv2.h +++ b/plugins/lv2/sfizz_lv2.h @@ -42,6 +42,7 @@ #define SFIZZ__preloadSize SFIZZ_URI ":" "preload_size" #define SFIZZ__oversampling SFIZZ_URI ":" "oversampling" #define SFIZZ__lastKeyswitch SFIZZ_URI ":" "last_keyswitch" +#define SFIZZ__description SFIZZ_URI ":" "description" // These ones are just for the worker #define SFIZZ__logStatus SFIZZ_URI ":" "log_status" #define SFIZZ__checkModification SFIZZ_URI ":" "check_modification" diff --git a/plugins/lv2/sfizz_lv2_plugin.h b/plugins/lv2/sfizz_lv2_plugin.h index 4e987e68e..911698ec1 100644 --- a/plugins/lv2/sfizz_lv2_plugin.h +++ b/plugins/lv2/sfizz_lv2_plugin.h @@ -7,6 +7,7 @@ #pragma once #include "sfizz_lv2.h" +#include "sfizz/utility/bit_array/BitArray.h" #if defined(SFIZZ_LV2_UI) #include "plugin/RMSFollower.h" #endif @@ -87,6 +88,7 @@ struct sfizz_plugin_t LV2_URID state_changed_uri {}; LV2_URID sfizz_sfz_file_uri {}; LV2_URID sfizz_scala_file_uri {}; + LV2_URID sfizz_description_uri {}; LV2_URID sfizz_num_voices_uri {}; LV2_URID sfizz_preload_size_uri {}; LV2_URID sfizz_oversampling_uri {}; @@ -132,9 +134,8 @@ struct sfizz_plugin_t volatile int sfz_blob_serial {}; const uint8_t *volatile sfz_blob_data {}; volatile uint32_t sfz_blob_size {}; - - // Sostenuto or sustain - char sustain_or_sostenuto[16] {}; + char text_description[1024]; + volatile bool resend_description {}; // Current CC values in the synth (synchronized by `synth_mutex`) // updated by hdcc or file load