summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2011-12-16 04:59:14 +0000
committerDavid Robillard <d@drobilla.net>2011-12-16 04:59:14 +0000
commitb8eb516e97042ca9559aaa506becf504180df0a8 (patch)
tree26fdb669e20b70b9927c1bd62723c48b6947dddc /src
parent3af74220b27e5b5b2bfa7061eb773d0a563d2600 (diff)
downloadlilv-b8eb516e97042ca9559aaa506becf504180df0a8.tar.gz
lilv-b8eb516e97042ca9559aaa506becf504180df0a8.tar.bz2
lilv-b8eb516e97042ca9559aaa506becf504180df0a8.zip
Fix lilv_world_find_nodes to work with wildcard subjects.
Add lilv_plugin_get_related to get resources related to plugins that are not directly rdfs:seeAlso linked (e.g. presets). Add lilv_world_load_resource for related resources (e.g. presets). Print presets in lv2info. git-svn-id: http://svn.drobilla.net/lad/trunk/lilv@3877 a436a847-0d15-0410-975c-d299462d15a1
Diffstat (limited to 'src')
-rw-r--r--src/collections.c8
-rw-r--r--src/lilv_internal.h8
-rw-r--r--src/plugin.c29
-rw-r--r--src/port.c2
-rw-r--r--src/query.c22
-rw-r--r--src/world.c79
6 files changed, 129 insertions, 19 deletions
diff --git a/src/collections.c b/src/collections.c
index e057c6f..77917f6 100644
--- a/src/collections.c
+++ b/src/collections.c
@@ -22,6 +22,14 @@ lilv_ptr_cmp(const void* a, const void* b, void* user_data)
return (intptr_t)a - (intptr_t)b;
}
+int
+lilv_resource_node_cmp(const void* a, const void* b, void* user_data)
+{
+ const SordNode* an = ((LilvNode*)a)->val.uri_val;
+ const SordNode* bn = ((LilvNode*)a)->val.uri_val;
+ return (intptr_t)an - (intptr_t)bn;
+}
+
/* Generic collection functions */
static inline LilvCollection*
diff --git a/src/lilv_internal.h b/src/lilv_internal.h
index 710d00f..a700d6f 100644
--- a/src/lilv_internal.h
+++ b/src/lilv_internal.h
@@ -129,6 +129,7 @@ struct LilvWorldImpl {
LilvPluginClasses* plugin_classes;
LilvSpec* specs;
LilvPlugins* plugins;
+ LilvNodes* loaded_files;
SordNode* dc_replaces_node;
SordNode* dyn_manifest_node;
SordNode* lv2_binary_node;
@@ -153,6 +154,7 @@ struct LilvWorldImpl {
SordNode* xsd_double_node;
SordNode* xsd_integer_node;
LilvNode* doap_name_val;
+ LilvNode* lv2_applies_to_val;
LilvNode* lv2_extensionData_val;
LilvNode* lv2_name_val;
LilvNode* lv2_optionalFeature_val;
@@ -256,6 +258,9 @@ int lilv_header_compare_by_uri(const void* a, const void* b, void* user_data);
int
lilv_ptr_cmp(const void* a, const void* b, void* user_data);
+int
+lilv_resource_node_cmp(const void* a, const void* b, void* user_data);
+
struct LilvHeader*
lilv_collection_get_by_uri(const ZixTree* seq, const LilvNode* uri);
@@ -306,7 +311,8 @@ static inline bool lilv_matches_end(SordIter* matches) {
}
LilvNodes* lilv_nodes_from_stream_objects(LilvWorld* w,
- SordIter* stream);
+ SordIter* stream,
+ bool object);
char* lilv_strjoin(const char* first, ...);
char* lilv_strdup(const char* str);
diff --git a/src/plugin.c b/src/plugin.c
index f8cf054..b305291 100644
--- a/src/plugin.c
+++ b/src/plugin.c
@@ -828,6 +828,35 @@ lilv_plugin_get_uis(const LilvPlugin* p)
}
}
+LILV_API
+LilvNodes*
+lilv_plugin_get_related(const LilvPlugin* plugin, const LilvNode* type)
+{
+ LilvWorld* const world = plugin->world;
+ LilvNodes* const related = lilv_world_find_nodes(
+ world, NULL, world->lv2_applies_to_val, lilv_plugin_get_uri(plugin));
+
+ if (!type) {
+ return related;
+ }
+
+ LilvNodes* matches = lilv_nodes_new();
+ LILV_FOREACH(nodes, i, related) {
+ LilvNode* node = lilv_collection_get(related, i);
+ SordIter* titer = lilv_world_query_internal(
+ world, node->val.uri_val, world->rdf_a_node, type->val.uri_val);
+ if (!sord_iter_end(titer)) {
+ zix_tree_insert(matches,
+ lilv_node_new_from_node(world, node->val.uri_val),
+ NULL);
+ }
+ sord_iter_free(titer);
+ }
+
+ lilv_nodes_free(related);
+ return matches;
+}
+
static size_t
file_sink(const void* buf, size_t len, void* stream)
{
diff --git a/src/port.c b/src/port.c
index 1a8ffaf..2c1b5c7 100644
--- a/src/port.c
+++ b/src/port.c
@@ -109,7 +109,7 @@ lilv_port_get_value_by_node(const LilvPlugin* p,
predicate,
NULL);
- return lilv_nodes_from_stream_objects(p->world, results);
+ return lilv_nodes_from_stream_objects(p->world, results, true);
}
LILV_API
diff --git a/src/query.c b/src/query.c
index e465a67..40387ef 100644
--- a/src/query.c
+++ b/src/query.c
@@ -53,14 +53,17 @@ lilv_lang_matches(const char* a, const char* b)
LilvNodes*
lilv_nodes_from_stream_objects_i18n(LilvWorld* world,
- SordIter* stream)
+ SordIter* stream,
+ bool object)
{
LilvNodes* values = lilv_nodes_new();
const SordNode* nolang = NULL; // Untranslated value
const SordNode* partial = NULL; // Partial language match
char* syslang = lilv_get_lang();
FOREACH_MATCH(stream) {
- const SordNode* value = lilv_match_object(stream);
+ const SordNode* value = object
+ ? lilv_match_object(stream)
+ : lilv_match_subject(stream);
if (sord_node_get_type(value) == SORD_LITERAL) {
const char* lang = sord_node_get_language(value);
LilvLangMatch lm = LILV_LANG_MATCH_NONE;
@@ -117,20 +120,23 @@ lilv_nodes_from_stream_objects_i18n(LilvWorld* world,
LilvNodes*
lilv_nodes_from_stream_objects(LilvWorld* world,
- SordIter* stream)
+ SordIter* stream,
+ bool object)
{
if (lilv_matches_end(stream)) {
lilv_match_end(stream);
return NULL;
} else if (world->opt.filter_language) {
- return lilv_nodes_from_stream_objects_i18n(world, stream);
+ return lilv_nodes_from_stream_objects_i18n(world, stream, object);
} else {
LilvNodes* values = lilv_nodes_new();
FOREACH_MATCH(stream) {
- LilvNode* value = lilv_node_new_from_node(
- world, lilv_match_object(stream));
- if (value) {
- zix_tree_insert(values, value, NULL);
+ const SordNode* value = object
+ ? lilv_match_object(stream)
+ : lilv_match_subject(stream);
+ LilvNode* node = lilv_node_new_from_node(world, value);
+ if (node) {
+ zix_tree_insert(values, node, NULL);
}
}
lilv_match_end(stream);
diff --git a/src/world.c b/src/world.c
index 7a51a3b..d5af0fe 100644
--- a/src/world.c
+++ b/src/world.c
@@ -45,6 +45,9 @@ lilv_world_new(void)
world->specs = NULL;
world->plugin_classes = lilv_plugin_classes_new();
world->plugins = lilv_plugins_new();
+ world->loaded_files = zix_tree_new(
+ false, lilv_resource_node_cmp, NULL, (ZixDestroyFunc)lilv_node_free);
+
#define NS_DYNMAN "http://lv2plug.in/ns/ext/dynmanifest#"
#define NS_DCTERMS "http://purl.org/dc/terms/"
@@ -77,6 +80,7 @@ lilv_world_new(void)
world->xsd_integer_node = NEW_URI(LILV_NS_XSD "integer");
world->doap_name_val = NEW_URI_VAL(LILV_NS_DOAP "name");
+ world->lv2_applies_to_val = NEW_URI_VAL(LILV_NS_LV2 "appliesTo");
world->lv2_extensionData_val = NEW_URI_VAL(LILV_NS_LV2 "extensionData");
world->lv2_name_val = NEW_URI_VAL(LILV_NS_LV2 "name");
world->lv2_optionalFeature_val = NEW_URI_VAL(LILV_NS_LV2 "optionalFeature");
@@ -132,6 +136,7 @@ lilv_world_free(LilvWorld* world)
sord_node_free(world->world, world->xsd_double_node);
sord_node_free(world->world, world->xsd_integer_node);
lilv_node_free(world->doap_name_val);
+ lilv_node_free(world->lv2_applies_to_val);
lilv_node_free(world->lv2_extensionData_val);
lilv_node_free(world->lv2_name_val);
lilv_node_free(world->lv2_optionalFeature_val);
@@ -154,6 +159,9 @@ lilv_world_free(LilvWorld* world)
zix_tree_free(world->plugins);
world->plugins = NULL;
+ zix_tree_free(world->loaded_files);
+ world->loaded_files = NULL;
+
zix_tree_free(world->plugin_classes);
world->plugin_classes = NULL;
@@ -205,7 +213,7 @@ lilv_world_find_nodes(LilvWorld* world,
const LilvNode* predicate,
const LilvNode* object)
{
- if (!lilv_node_is_uri(subject) && !lilv_node_is_blank(subject)) {
+ if (subject && !lilv_node_is_uri(subject) && !lilv_node_is_blank(subject)) {
LILV_ERRORF("Subject `%s' is not a resource\n", subject->str_val);
return NULL;
}
@@ -213,18 +221,24 @@ lilv_world_find_nodes(LilvWorld* world,
LILV_ERRORF("Predicate `%s' is not a URI\n", predicate->str_val);
return NULL;
}
+ if (!subject && !object) {
+ LILV_ERROR("Both subject and object are NULL\n");
+ return NULL;
+ }
- SordNode* subject_node = (lilv_node_is_uri(subject))
+ SordNode* const subject_node = subject
? sord_node_copy(subject->val.uri_val)
- : sord_new_blank(world->world,
- (const uint8_t*)lilv_node_as_blank(subject));
+ : NULL;
+
+ SordNode* const object_node = object
+ ? sord_node_copy(object->val.uri_val)
+ : NULL;
- LilvNodes* ret = lilv_world_query_values_internal(world,
- subject_node,
- predicate->val.uri_val,
- NULL);
+ LilvNodes* ret = lilv_world_query_values_internal(
+ world, subject_node, predicate->val.uri_val, object_node);
sord_node_free(world->world, subject_node);
+ sord_node_free(world->world, object_node);
return ret;
}
@@ -246,7 +260,8 @@ lilv_world_query_values_internal(LilvWorld* world,
{
return lilv_nodes_from_stream_objects(
world,
- lilv_world_query_internal(world, subject, predicate, object));
+ lilv_world_query_internal(world, subject, predicate, object),
+ (object == NULL));
}
static SerdNode
@@ -805,6 +820,52 @@ lilv_world_load_all(LilvWorld* world)
}
LILV_API
+int
+lilv_world_load_resource(LilvWorld* world,
+ const LilvNode* resource)
+{
+ if (!lilv_node_is_uri(resource) && !lilv_node_is_blank(resource)) {
+ LILV_ERRORF("Node `%s' is not a resource\n", resource->str_val);
+ return -1;
+ }
+
+ int n_read = 0;
+ SordIter* files = lilv_world_find_statements(world, world->model,
+ resource->val.uri_val,
+ world->rdfs_seealso_node,
+ NULL, NULL);
+ FOREACH_MATCH(files) {
+ const SordNode* file = lilv_match_object(files);
+ const uint8_t* str = sord_node_get_string(file);
+ LilvNode* file_node = lilv_node_new_from_node(world, file);
+ ZixTreeIter* iter;
+ if (zix_tree_find(world->loaded_files, file, &iter)) {
+ if (sord_node_get_type(file) == SORD_URI) {
+ const SerdNode* base = sord_node_to_serd_node(file);
+ SerdEnv* env = serd_env_new(base);
+ SerdReader* reader = sord_new_reader(
+ world->model, env, SERD_TURTLE, (SordNode*)file);
+ if (!serd_reader_read_file(reader, str)) {
+ ++n_read;
+ zix_tree_insert(world->loaded_files, file_node, NULL);
+ file_node = NULL; // prevent deletion...
+ } else {
+ LILV_ERRORF("Error loading resource `%s'\n", str);
+ }
+ serd_reader_free(reader);
+ serd_env_free(env);
+ } else {
+ LILV_ERRORF("rdfs:seeAlso node `%s' is not a URI\n", str);
+ }
+ }
+ lilv_node_free(file_node); // ...here
+ }
+ lilv_match_end(files);
+
+ return n_read;
+}
+
+LILV_API
const LilvPluginClass*
lilv_world_get_plugin_class(const LilvWorld* world)
{