summaryrefslogtreecommitdiff
path: root/libs/ardour/lv2_plugin.cc
diff options
context:
space:
mode:
authorRobin Gareus <robin@gareus.org>2019-04-10 00:19:39 +0200
committerRobin Gareus <robin@gareus.org>2019-04-10 00:22:20 +0200
commit7fc7c18a0786f07ea17f00b3bc031974c5ac701e (patch)
tree257c65403d0b3d1613b352f0dbc43a42df48bd80 /libs/ardour/lv2_plugin.cc
parent59b1193b56a89e1c3e761aa5a09b41d16e8e6a1e (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.cc78
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;