|
|
@@ -405,7 +405,7 @@ lilv_plugin_get_value_internal(const LilvPlugin* p, |
|
|
|
const SordNode* predicate) |
|
|
|
{ |
|
|
|
lilv_plugin_load_if_necessary(p); |
|
|
|
return lilv_world_query_values_internal( |
|
|
|
return lilv_world_find_nodes_internal( |
|
|
|
p->world, p->plugin_uri->node, predicate, NULL); |
|
|
|
} |
|
|
|
|
|
|
@@ -528,37 +528,57 @@ lilv_plugin_get_port_ranges_float(const LilvPlugin* p, |
|
|
|
|
|
|
|
LILV_API |
|
|
|
uint32_t |
|
|
|
lilv_plugin_get_num_ports_of_class(const LilvPlugin* p, |
|
|
|
const LilvNode* class_1, ...) |
|
|
|
lilv_plugin_get_num_ports_of_class_va(const LilvPlugin* p, |
|
|
|
const LilvNode* class_1, |
|
|
|
va_list args) |
|
|
|
{ |
|
|
|
lilv_plugin_load_ports_if_necessary(p); |
|
|
|
|
|
|
|
uint32_t ret = 0; |
|
|
|
va_list args; |
|
|
|
uint32_t count = 0; |
|
|
|
|
|
|
|
// Build array of classes from args so we can walk it several times |
|
|
|
size_t n_classes = 0; |
|
|
|
const LilvNode** classes = NULL; |
|
|
|
for (LilvNode* class_i = NULL; (class_i = va_arg(args, LilvNode*)); ) { |
|
|
|
classes = (const LilvNode**)realloc( |
|
|
|
classes, ++n_classes * sizeof(LilvNode*)); |
|
|
|
classes[n_classes - 1] = class_i; |
|
|
|
} |
|
|
|
|
|
|
|
// Check each port against every type |
|
|
|
for (unsigned i = 0; i < p->num_ports; ++i) { |
|
|
|
LilvPort* port = p->ports[i]; |
|
|
|
if (!port || !lilv_port_is_a(p, port, class_1)) |
|
|
|
continue; |
|
|
|
|
|
|
|
va_start(args, class_1); |
|
|
|
if (port && lilv_port_is_a(p, port, class_1)) { |
|
|
|
bool matches = true; |
|
|
|
for (size_t j = 0; j < n_classes; ++j) { |
|
|
|
if (!lilv_port_is_a(p, port, classes[j])) { |
|
|
|
matches = false; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
bool matches = true; |
|
|
|
for (LilvNode* class_i = NULL; (class_i = va_arg(args, LilvNode*)); ) { |
|
|
|
if (!lilv_port_is_a(p, port, class_i)) { |
|
|
|
va_end(args); |
|
|
|
matches = false; |
|
|
|
break; |
|
|
|
if (matches) { |
|
|
|
++count; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (matches) |
|
|
|
++ret; |
|
|
|
free(classes); |
|
|
|
return count; |
|
|
|
} |
|
|
|
|
|
|
|
va_end(args); |
|
|
|
} |
|
|
|
LILV_API |
|
|
|
uint32_t |
|
|
|
lilv_plugin_get_num_ports_of_class(const LilvPlugin* p, |
|
|
|
const LilvNode* class_1, ...) |
|
|
|
{ |
|
|
|
va_list args; |
|
|
|
va_start(args, class_1); |
|
|
|
|
|
|
|
return ret; |
|
|
|
uint32_t count = lilv_plugin_get_num_ports_of_class_va(p, class_1, args); |
|
|
|
|
|
|
|
va_end(args); |
|
|
|
return count; |
|
|
|
} |
|
|
|
|
|
|
|
LILV_API |
|
|
@@ -592,7 +612,7 @@ lilv_plugin_has_latency(const LilvPlugin* p) |
|
|
|
return ret; |
|
|
|
} |
|
|
|
|
|
|
|
static LilvPort* |
|
|
|
static const LilvPort* |
|
|
|
lilv_plugin_get_port_by_property(const LilvPlugin* plugin, |
|
|
|
const LilvNode* port_property) |
|
|
|
{ |
|
|
@@ -617,7 +637,7 @@ lilv_plugin_get_port_by_property(const LilvPlugin* plugin, |
|
|
|
} |
|
|
|
|
|
|
|
LILV_API |
|
|
|
LilvPort* |
|
|
|
const LilvPort* |
|
|
|
lilv_plugin_get_port_by_designation(const LilvPlugin* plugin, |
|
|
|
const LilvNode* port_class, |
|
|
|
const LilvNode* designation) |
|
|
@@ -648,10 +668,10 @@ LILV_API |
|
|
|
uint32_t |
|
|
|
lilv_plugin_get_latency_port_index(const LilvPlugin* p) |
|
|
|
{ |
|
|
|
LilvNode* property = lilv_node_new_from_node( |
|
|
|
LilvNode* prop = lilv_node_new_from_node( |
|
|
|
p->world, p->world->uris.lv2_reportsLatency); |
|
|
|
LilvPort* latency_port = lilv_plugin_get_port_by_property(p, property); |
|
|
|
lilv_node_free(property); |
|
|
|
const LilvPort* latency_port = lilv_plugin_get_port_by_property(p, prop); |
|
|
|
lilv_node_free(prop); |
|
|
|
return latency_port ? latency_port->index : UINT32_MAX; |
|
|
|
} |
|
|
|
|
|
|
@@ -660,13 +680,18 @@ bool |
|
|
|
lilv_plugin_has_feature(const LilvPlugin* p, |
|
|
|
const LilvNode* feature) |
|
|
|
{ |
|
|
|
LilvNodes* features = lilv_plugin_get_supported_features(p); |
|
|
|
|
|
|
|
const bool ret = (features && feature |
|
|
|
&& lilv_nodes_contains(features, feature)); |
|
|
|
|
|
|
|
lilv_nodes_free(features); |
|
|
|
return ret; |
|
|
|
lilv_plugin_load_if_necessary(p); |
|
|
|
const SordNode* predicates[] = { p->world->uris.lv2_requiredFeature, |
|
|
|
p->world->uris.lv2_optionalFeature, |
|
|
|
NULL }; |
|
|
|
|
|
|
|
for (const SordNode** pred = predicates; *pred; ++pred) { |
|
|
|
if (lilv_world_ask_internal( |
|
|
|
p->world, p->plugin_uri->node, *pred, feature->node)) { |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
LILV_API |
|
|
@@ -675,20 +700,9 @@ lilv_plugin_get_supported_features(const LilvPlugin* p) |
|
|
|
{ |
|
|
|
LilvNodes* optional = lilv_plugin_get_optional_features(p); |
|
|
|
LilvNodes* required = lilv_plugin_get_required_features(p); |
|
|
|
LilvNodes* result = lilv_nodes_new(); |
|
|
|
|
|
|
|
LILV_FOREACH(nodes, i, optional) |
|
|
|
zix_tree_insert((ZixTree*)result, |
|
|
|
lilv_node_duplicate(lilv_nodes_get(optional, i)), |
|
|
|
NULL); |
|
|
|
LILV_FOREACH(nodes, i, required) |
|
|
|
zix_tree_insert((ZixTree*)result, |
|
|
|
lilv_node_duplicate(lilv_nodes_get(required, i)), |
|
|
|
NULL); |
|
|
|
|
|
|
|
LilvNodes* result = lilv_nodes_merge(optional, required); |
|
|
|
lilv_nodes_free(optional); |
|
|
|
lilv_nodes_free(required); |
|
|
|
|
|
|
|
return result; |
|
|
|
} |
|
|
|
|
|
|
@@ -696,16 +710,22 @@ LILV_API |
|
|
|
LilvNodes* |
|
|
|
lilv_plugin_get_optional_features(const LilvPlugin* p) |
|
|
|
{ |
|
|
|
return lilv_plugin_get_value_internal( |
|
|
|
p, p->world->uris.lv2_optionalFeature); |
|
|
|
lilv_plugin_load_if_necessary(p); |
|
|
|
return lilv_world_find_nodes_internal(p->world, |
|
|
|
p->plugin_uri->node, |
|
|
|
p->world->uris.lv2_optionalFeature, |
|
|
|
NULL); |
|
|
|
} |
|
|
|
|
|
|
|
LILV_API |
|
|
|
LilvNodes* |
|
|
|
lilv_plugin_get_required_features(const LilvPlugin* p) |
|
|
|
{ |
|
|
|
return lilv_plugin_get_value_internal( |
|
|
|
p, p->world->uris.lv2_requiredFeature); |
|
|
|
lilv_plugin_load_if_necessary(p); |
|
|
|
return lilv_world_find_nodes_internal(p->world, |
|
|
|
p->plugin_uri->node, |
|
|
|
p->world->uris.lv2_requiredFeature, |
|
|
|
NULL); |
|
|
|
} |
|
|
|
|
|
|
|
LILV_API |
|
|
@@ -719,18 +739,12 @@ lilv_plugin_has_extension_data(const LilvPlugin* p, |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
SordIter* iter = lilv_world_query_internal( |
|
|
|
lilv_plugin_load_if_necessary(p); |
|
|
|
return lilv_world_ask_internal( |
|
|
|
p->world, |
|
|
|
p->plugin_uri->node, |
|
|
|
p->world->uris.lv2_extensionData, |
|
|
|
uri->node); |
|
|
|
|
|
|
|
if (iter) { |
|
|
|
sord_iter_free(iter); |
|
|
|
return true; |
|
|
|
} else { |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
LILV_API |
|
|
@@ -937,8 +951,10 @@ LILV_API |
|
|
|
LilvNodes* |
|
|
|
lilv_plugin_get_related(const LilvPlugin* plugin, const LilvNode* type) |
|
|
|
{ |
|
|
|
lilv_plugin_load_if_necessary(plugin); |
|
|
|
|
|
|
|
LilvWorld* const world = plugin->world; |
|
|
|
LilvNodes* const related = lilv_world_query_values_internal( |
|
|
|
LilvNodes* const related = lilv_world_find_nodes_internal( |
|
|
|
world, |
|
|
|
NULL, |
|
|
|
world->uris.lv2_appliesTo, |
|
|
@@ -951,14 +967,12 @@ lilv_plugin_get_related(const LilvPlugin* plugin, const LilvNode* type) |
|
|
|
LilvNodes* matches = lilv_nodes_new(); |
|
|
|
LILV_FOREACH(nodes, i, related) { |
|
|
|
LilvNode* node = (LilvNode*)lilv_collection_get((ZixTree*)related, i); |
|
|
|
SordIter* titer = lilv_world_query_internal( |
|
|
|
world, node->node, world->uris.rdf_a, type->node); |
|
|
|
if (!sord_iter_end(titer)) { |
|
|
|
if (lilv_world_ask_internal( |
|
|
|
world, node->node, world->uris.rdf_a, type->node)) { |
|
|
|
zix_tree_insert((ZixTree*)matches, |
|
|
|
lilv_node_new_from_node(world, node->node), |
|
|
|
NULL); |
|
|
|
} |
|
|
|
sord_iter_free(titer); |
|
|
|
} |
|
|
|
|
|
|
|
lilv_nodes_free(related); |