From 3f739738062eb5fd646a1a88a61019b453bbda7f Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Sat, 29 Oct 2016 19:21:48 +0200 Subject: Prototype LV2 extension for plugins to provide Midnams --- libs/ardour/ardour/lv2_extensions.h | 38 ++++++++++++++++++ libs/ardour/ardour/lv2_plugin.h | 6 +++ libs/ardour/ardour/plugin.h | 5 +++ libs/ardour/lv2_plugin.cc | 78 ++++++++++++++++++++++++++++++++++++- 4 files changed, 126 insertions(+), 1 deletion(-) (limited to 'libs/ardour') diff --git a/libs/ardour/ardour/lv2_extensions.h b/libs/ardour/ardour/lv2_extensions.h index 64fc3bc615..f38ac8122a 100644 --- a/libs/ardour/ardour/lv2_extensions.h +++ b/libs/ardour/ardour/lv2_extensions.h @@ -171,4 +171,42 @@ typedef struct _LV2_License_Interface { @} */ +/** + @defgroup midnam MIDI Naming + + @{ +*/ + + +#define LV2_MIDNAM_URI "http://ardour.org/lv2/midnam" +#define LV2_MIDNAM_PREFIX LV2_MIDNAM_URI "#" +#define LV2_MIDNAM__interface LV2_MIDNAM_PREFIX "interface" +#define LV2_MIDNAM__update LV2_MIDNAM_PREFIX "update" + +typedef void* LV2_Midnam_Handle; + +/** a LV2 Feature provided by the Host to the plugin */ +typedef struct { + /** Opaque host data */ + LV2_Midnam_Handle handle; + /** Request from run() that the host should re-read the midnam */ + void (*update)(LV2_Midnam_Handle handle); +} LV2_Midnam; + +typedef struct { + /** query midnam document. The plugin + * is expected to return an allocated + * null-terminated XML text, which is + * safe for the host to pass to free(). + * + * The midnam must be unique and + * specific for the given plugin-instance. + */ + char* (*midnam)(LV2_Handle instance); + char* (*model)(LV2_Handle instance); +} LV2_Midnam_Interface; + +/** + @} +*/ #endif diff --git a/libs/ardour/ardour/lv2_plugin.h b/libs/ardour/ardour/lv2_plugin.h index a1e38fda32..202ddbb240 100644 --- a/libs/ardour/ardour/lv2_plugin.h +++ b/libs/ardour/ardour/lv2_plugin.h @@ -278,6 +278,7 @@ class LIBARDOUR_API LV2Plugin : public ARDOUR::Plugin, public ARDOUR::Workee #ifdef LV2_EXTENDED const LV2_Inline_Display_Interface* _display_interface; + const LV2_Midnam_Interface* _midname_interface; #endif typedef struct { @@ -294,6 +295,7 @@ class LIBARDOUR_API LV2Plugin : public ARDOUR::Plugin, public ARDOUR::Workee LV2_Feature _def_state_feature; #ifdef LV2_EXTENDED LV2_Feature _queue_draw_feature; + LV2_Feature _midnam_feature; #endif // Options passed to plugin @@ -321,6 +323,10 @@ class LIBARDOUR_API LV2Plugin : public ARDOUR::Plugin, public ARDOUR::Workee #ifdef LV2_EXTENDED bool has_inline_display (); Plugin::Display_Image_Surface* render_inline_display (uint32_t, uint32_t); + + bool has_midnam (); + bool read_midnam (); + std::string midnam_model (); #endif void latency_compute_run (); diff --git a/libs/ardour/ardour/plugin.h b/libs/ardour/ardour/plugin.h index 612091191e..7d35ac7c2e 100644 --- a/libs/ardour/ardour/plugin.h +++ b/libs/ardour/ardour/plugin.h @@ -166,6 +166,11 @@ class LIBARDOUR_API Plugin : public PBD::StatefulDestructible, public Latent virtual Display_Image_Surface* render_inline_display (uint32_t, uint32_t) { return NULL; } PBD::Signal0 QueueDraw; + virtual bool has_midnam () { return false; } + virtual bool read_midnam () { return false; } + virtual std::string midnam_model () { return ""; } + PBD::Signal0 UpdateMidnam; + struct PresetRecord { PresetRecord () : valid (false) {} PresetRecord (const std::string& u, const std::string& l, bool s = true) : uri (u), label (l), user (s), valid (true) {} diff --git a/libs/ardour/lv2_plugin.cc b/libs/ardour/lv2_plugin.cc index 91ab6b43a4..7248dfeaa1 100644 --- a/libs/ardour/lv2_plugin.cc +++ b/libs/ardour/lv2_plugin.cc @@ -45,6 +45,7 @@ #include "ardour/audioengine.h" #include "ardour/debug.h" #include "ardour/lv2_plugin.h" +#include "ardour/midi_patch_manager.h" #include "ardour/session.h" #include "ardour/tempo.h" #include "ardour/types.h" @@ -223,6 +224,13 @@ queue_draw (LV2_Inline_Display_Handle handle) LV2Plugin* plugin = (LV2Plugin*)handle; plugin->QueueDraw(); /* EMIT SIGNAL */ } + +static void +midnam_update (LV2_Midnam_Handle handle) +{ + LV2Plugin* plugin = (LV2Plugin*)handle; + plugin->UpdateMidnam (); /* EMIT SIGNAL */ +} #endif /* log extension */ @@ -280,6 +288,7 @@ struct LV2Plugin::Impl { #endif #ifdef LV2_EXTENDED , queue_draw(0) + , midnam(0) #endif {} @@ -307,6 +316,7 @@ struct LV2Plugin::Impl { #endif #ifdef LV2_EXTENDED LV2_Inline_Display* queue_draw; + LV2_Midnam* midnam; #endif }; @@ -399,7 +409,7 @@ LV2Plugin::init(const void* c_plugin, framecnt_t rate) lilv_node_free(state_uri); lilv_node_free(state_iface_uri); - _features = (LV2_Feature**)calloc(12, sizeof(LV2_Feature*)); + _features = (LV2_Feature**)calloc(13, sizeof(LV2_Feature*)); _features[0] = &_instance_access_feature; _features[1] = &_data_access_feature; _features[2] = &_make_path_feature; @@ -425,6 +435,15 @@ LV2Plugin::init(const void* c_plugin, framecnt_t rate) _queue_draw_feature.URI = LV2_INLINEDISPLAY__queue_draw; _queue_draw_feature.data = _impl->queue_draw; _features[n_features++] = &_queue_draw_feature; + + _impl->midnam = (LV2_Midnam*) + malloc (sizeof(LV2_Midnam)); + _impl->midnam->handle = this; + _impl->midnam->update = midnam_update; + + _midnam_feature.URI = LV2_MIDNAM__update; + _midnam_feature.data = _impl->midnam; + _features[n_features++] = &_midnam_feature; #endif #ifdef HAVE_LV2_1_2_0 @@ -521,6 +540,16 @@ LV2Plugin::init(const void* c_plugin, framecnt_t rate) #ifdef LV2_EXTENDED _display_interface = (const LV2_Inline_Display_Interface*) extension_data (LV2_INLINEDISPLAY__interface); + + _midname_interface = (const LV2_Midnam_Interface*) + extension_data (LV2_MIDNAM__interface); + if (_midname_interface) { + if (read_midnam ()) { + printf ("READ MIDNAM FROM PLUGIN\n"); + } else { + printf ("**FAILED TO ** READ MIDNAM FROM PLUGIN\n"); + } + } #endif if (lilv_plugin_has_feature(plugin, _world.lv2_inPlaceBroken)) { @@ -840,6 +869,15 @@ LV2Plugin::~LV2Plugin () deactivate(); cleanup(); +#ifdef LV2_EXTENDED + if (has_midnam ()) { + std::stringstream ss; + ss << (void*)this; + ss << unique_id(); + MIDI::Name::MidiPatchManager::instance().remove_custom_midnam (ss.str()); + } +#endif + lilv_instance_free(_impl->instance); lilv_state_free(_impl->state); lilv_node_free(_impl->name); @@ -849,6 +887,7 @@ LV2Plugin::~LV2Plugin () #endif #ifdef LV2_EXTENDED free(_impl->queue_draw); + free(_impl->midnam); #endif free(_features); @@ -930,6 +969,43 @@ LV2Plugin::render_inline_display (uint32_t w, uint32_t h) { } return NULL; } + +bool +LV2Plugin::has_midnam () { + return _midname_interface ? true : false; +} + +bool +LV2Plugin::read_midnam () { + bool rv = false; + if (!_midname_interface) { + return rv; + } + char* midnam = _midname_interface->midnam ((void*)_impl->instance->lv2_handle); + if (midnam) { + std::stringstream ss; + ss << (void*)this; + ss << unique_id(); + MIDI::Name::MidiPatchManager::instance().remove_custom_midnam (ss.str()); + rv = MIDI::Name::MidiPatchManager::instance().add_custom_midnam (ss.str(), midnam); + } + free (midnam); + return rv; +} + +std::string +LV2Plugin::midnam_model () { + std::string rv; + if (!_midname_interface) { + return rv; + } + char* model = _midname_interface->model ((void*)_impl->instance->lv2_handle); + if (model) { + rv = model; + } + free (model); + return rv; +} #endif string -- cgit v1.2.3