diff options
author | Robin Gareus <robin@gareus.org> | 2019-04-10 00:19:39 +0200 |
---|---|---|
committer | Robin Gareus <robin@gareus.org> | 2019-04-10 00:22:20 +0200 |
commit | 7fc7c18a0786f07ea17f00b3bc031974c5ac701e (patch) | |
tree | 257c65403d0b3d1613b352f0dbc43a42df48bd80 /libs/ardour/lv2_plugin.cc | |
parent | 59b1193b56a89e1c3e761aa5a09b41d16e8e6a1e (diff) |
LV2: check required feature and options
When discovering LV2 plugins, verify if a plugin's required features
and required options can be be satisfied.
This replaces a previous blacklist with a whitelist of supported
features/options.
Diffstat (limited to 'libs/ardour/lv2_plugin.cc')
-rw-r--r-- | libs/ardour/lv2_plugin.cc | 78 |
1 files changed, 52 insertions, 26 deletions
diff --git a/libs/ardour/lv2_plugin.cc b/libs/ardour/lv2_plugin.cc index 042bc92200..fe2bde8d1d 100644 --- a/libs/ardour/lv2_plugin.cc +++ b/libs/ardour/lv2_plugin.cc @@ -82,6 +82,7 @@ #include "lv2/lv2plug.in/ns/extensions/units/units.h" #include "lv2/lv2plug.in/ns/ext/patch/patch.h" #include "lv2/lv2plug.in/ns/ext/port-groups/port-groups.h" +#include "lv2/lv2plug.in/ns/ext/parameters/parameters.h" #ifdef HAVE_LV2_1_2_0 #include "lv2/lv2plug.in/ns/ext/buf-size/buf-size.h" #include "lv2/lv2plug.in/ns/ext/options/options.h" @@ -180,6 +181,7 @@ public: LilvNode* units_midiNote; LilvNode* patch_writable; LilvNode* patch_Message; + LilvNode* opts_requiredOptions; #ifdef HAVE_LV2_1_2_0 LilvNode* bufz_powerOf2BlockLength; LilvNode* bufz_fixedBlockLength; @@ -624,22 +626,6 @@ LV2Plugin::init(const void* c_plugin, samplecnt_t rate) throw failed_constructor(); } -#ifdef HAVE_LV2_1_2_0 - LilvNodes *required_features = lilv_plugin_get_required_features (plugin); - if (lilv_nodes_contains (required_features, _world.bufz_powerOf2BlockLength) || - lilv_nodes_contains (required_features, _world.bufz_fixedBlockLength) - ) { - error << string_compose( - _("LV2: \"%1\" buffer-size requirements cannot be satisfied."), - lilv_node_as_string(_impl->name)) << endmsg; - lilv_node_free(_impl->name); - lilv_node_free(_impl->author); - lilv_nodes_free(required_features); - throw failed_constructor(); - } - lilv_nodes_free(required_features); -#endif - LilvNodes* optional_features = lilv_plugin_get_optional_features (plugin); #ifdef HAVE_LV2_1_2_0 if (lilv_nodes_contains (optional_features, _world.bufz_coarseBlockLength)) { @@ -3258,6 +3244,7 @@ LV2World::LV2World() units_db = lilv_new_uri(world, LV2_UNITS__db); patch_writable = lilv_new_uri(world, LV2_PATCH__writable); patch_Message = lilv_new_uri(world, LV2_PATCH__Message); + opts_requiredOptions = lilv_new_uri(world, LV2_OPTIONS__requiredOption); #ifdef LV2_EXTENDED lv2_noSampleAccurateCtrl = lilv_new_uri(world, "http://ardour.org/lv2/ext#noSampleAccurateControls"); // deprecated 2016-09-18 auto_can_write_automatation = lilv_new_uri(world, LV2_AUTOMATE_URI__can_write); @@ -3294,6 +3281,7 @@ LV2World::~LV2World() lilv_node_free(auto_automation_controller); #endif lilv_node_free(patch_Message); + lilv_node_free(opts_requiredOptions); lilv_node_free(patch_writable); lilv_node_free(units_hz); lilv_node_free(units_midiNote); @@ -3485,18 +3473,56 @@ LV2PluginInfo::discover() } #ifdef HAVE_LV2_1_2_0 - LilvNodes *required_features = lilv_plugin_get_required_features (p); - if (lilv_nodes_contains (required_features, world.bufz_powerOf2BlockLength) || - lilv_nodes_contains (required_features, world.bufz_fixedBlockLength) - ) { - warning << string_compose( - _("Ignoring LV2 plugin \"%1\" because its buffer-size requirements cannot be satisfied."), - lilv_node_as_string(name)) << endmsg; - lilv_nodes_free(required_features); - lilv_node_free(name); + int err = 0; + LilvNodes* required_features = lilv_plugin_get_required_features (p); + LILV_FOREACH(nodes, i, required_features) { + const char* rf = lilv_node_as_uri (lilv_nodes_get (required_features, i)); + bool ok = false; + if (!strcmp (rf, "http://lv2plug.in/ns/ext/instance-access")) { ok = true; } + if (!strcmp (rf, "http://lv2plug.in/ns/ext/data-access")) { ok = true; } + if (!strcmp (rf, LV2_STATE__makePath)) { ok = true; } + if (!strcmp (rf, LV2_LOG__log)) { ok = true; } + if (!strcmp (rf, LV2_WORKER__schedule)) { ok = true; } + if (!strcmp (rf, LV2_STATE_PREFIX "loadDefaultState")) { ok = true; } + if (!strcmp (rf, LV2_URID_MAP_URI)) { ok = true; } + if (!strcmp (rf, LV2_URID_UNMAP_URI)) { ok = true; } + if (!strcmp (rf, "http://lv2plug.in/ns/lv2core#isLive")) { ok = true; } + if (!ok) { + warning << string_compose ( + _("Unsupported required LV2 feature: '%1' in '%2'."), + rf, lilv_node_as_string(name)) << endmsg; + err = 1; + } + } + + if (err) { + continue; + } + + lilv_nodes_free (required_features); + + LilvNodes* required_options = lilv_world_find_nodes (world.world, lilv_plugin_get_uri (p), world.opts_requiredOptions, NULL); + if (required_options) { + LILV_FOREACH(nodes, i, required_options) { + const char* ro = lilv_node_as_uri (lilv_nodes_get (required_options, i)); + bool ok = false; + if (!strcmp (ro, LV2_PARAMETERS__sampleRate)) { ok = true; } + if (!strcmp (ro, LV2_BUF_SIZE__minBlockLength)) { ok = true; } + if (!strcmp (ro, LV2_BUF_SIZE__maxBlockLength)) { ok = true; } + if (!strcmp (ro, LV2_BUF_SIZE__sequenceSize)) { ok = true; } + if (!ok) { + warning << string_compose ( + _("Unsupported required LV2 option: '%1' in '%2'."), + ro, lilv_node_as_string(name)) << endmsg; + err = 1; + } + } + } + lilv_nodes_free(required_options); + + if (err) { continue; } - lilv_nodes_free(required_features); #endif info->type = LV2; |