diff options
Diffstat (limited to 'src/world.c')
-rw-r--r-- | src/world.c | 1877 |
1 files changed, 917 insertions, 960 deletions
diff --git a/src/world.c b/src/world.c index a04ba26..a6f103e 100644 --- a/src/world.c +++ b/src/world.c @@ -28,8 +28,8 @@ #include "lv2/presets/presets.h" #ifdef LILV_DYN_MANIFEST -# include "lv2/dynmanifest/dynmanifest.h" -# include <dlfcn.h> +# include "lv2/dynmanifest/dynmanifest.h" +# include <dlfcn.h> #endif #include <assert.h> @@ -45,166 +45,164 @@ lilv_world_drop_graph(LilvWorld* world, const SordNode* graph); LilvWorld* lilv_world_new(void) { - LilvWorld* world = (LilvWorld*)calloc(1, sizeof(LilvWorld)); + LilvWorld* world = (LilvWorld*)calloc(1, sizeof(LilvWorld)); - world->world = sord_world_new(); - if (!world->world) { - goto fail; - } + world->world = sord_world_new(); + if (!world->world) { + goto fail; + } - world->model = sord_new(world->world, SORD_SPO|SORD_OPS, true); - if (!world->model) { - goto fail; - } + world->model = sord_new(world->world, SORD_SPO | SORD_OPS, true); + if (!world->model) { + goto fail; + } - world->specs = NULL; - world->plugin_classes = lilv_plugin_classes_new(); - world->plugins = lilv_plugins_new(); - world->zombies = lilv_plugins_new(); - world->loaded_files = zix_tree_new( - false, lilv_resource_node_cmp, NULL, (ZixDestroyFunc)lilv_node_free); + world->specs = NULL; + world->plugin_classes = lilv_plugin_classes_new(); + world->plugins = lilv_plugins_new(); + world->zombies = lilv_plugins_new(); + world->loaded_files = zix_tree_new( + false, lilv_resource_node_cmp, NULL, (ZixDestroyFunc)lilv_node_free); - world->libs = zix_tree_new(false, lilv_lib_compare, NULL, NULL); + world->libs = zix_tree_new(false, lilv_lib_compare, NULL, NULL); #define NS_DCTERMS "http://purl.org/dc/terms/" -#define NS_DYNMAN "http://lv2plug.in/ns/ext/dynmanifest#" -#define NS_OWL "http://www.w3.org/2002/07/owl#" +#define NS_DYNMAN "http://lv2plug.in/ns/ext/dynmanifest#" +#define NS_OWL "http://www.w3.org/2002/07/owl#" #define NEW_URI(uri) sord_new_uri(world->world, (const uint8_t*)(uri)) - world->uris.dc_replaces = NEW_URI(NS_DCTERMS "replaces"); - world->uris.dman_DynManifest = NEW_URI(NS_DYNMAN "DynManifest"); - world->uris.doap_name = NEW_URI(LILV_NS_DOAP "name"); - world->uris.lv2_Plugin = NEW_URI(LV2_CORE__Plugin); - world->uris.lv2_Specification = NEW_URI(LV2_CORE__Specification); - world->uris.lv2_appliesTo = NEW_URI(LV2_CORE__appliesTo); - world->uris.lv2_binary = NEW_URI(LV2_CORE__binary); - world->uris.lv2_default = NEW_URI(LV2_CORE__default); - world->uris.lv2_designation = NEW_URI(LV2_CORE__designation); - world->uris.lv2_extensionData = NEW_URI(LV2_CORE__extensionData); - world->uris.lv2_index = NEW_URI(LV2_CORE__index); - world->uris.lv2_latency = NEW_URI(LV2_CORE__latency); - world->uris.lv2_maximum = NEW_URI(LV2_CORE__maximum); - world->uris.lv2_microVersion = NEW_URI(LV2_CORE__microVersion); - world->uris.lv2_minimum = NEW_URI(LV2_CORE__minimum); - world->uris.lv2_minorVersion = NEW_URI(LV2_CORE__minorVersion); - world->uris.lv2_name = NEW_URI(LV2_CORE__name); - world->uris.lv2_optionalFeature = NEW_URI(LV2_CORE__optionalFeature); - world->uris.lv2_port = NEW_URI(LV2_CORE__port); - world->uris.lv2_portProperty = NEW_URI(LV2_CORE__portProperty); - world->uris.lv2_reportsLatency = NEW_URI(LV2_CORE__reportsLatency); - world->uris.lv2_requiredFeature = NEW_URI(LV2_CORE__requiredFeature); - world->uris.lv2_symbol = NEW_URI(LV2_CORE__symbol); - world->uris.lv2_prototype = NEW_URI(LV2_CORE__prototype); - world->uris.owl_Ontology = NEW_URI(NS_OWL "Ontology"); - world->uris.pset_value = NEW_URI(LV2_PRESETS__value); - world->uris.rdf_a = NEW_URI(LILV_NS_RDF "type"); - world->uris.rdf_value = NEW_URI(LILV_NS_RDF "value"); - world->uris.rdfs_Class = NEW_URI(LILV_NS_RDFS "Class"); - world->uris.rdfs_label = NEW_URI(LILV_NS_RDFS "label"); - world->uris.rdfs_seeAlso = NEW_URI(LILV_NS_RDFS "seeAlso"); - world->uris.rdfs_subClassOf = NEW_URI(LILV_NS_RDFS "subClassOf"); - world->uris.xsd_base64Binary = NEW_URI(LILV_NS_XSD "base64Binary"); - world->uris.xsd_boolean = NEW_URI(LILV_NS_XSD "boolean"); - world->uris.xsd_decimal = NEW_URI(LILV_NS_XSD "decimal"); - world->uris.xsd_double = NEW_URI(LILV_NS_XSD "double"); - world->uris.xsd_integer = NEW_URI(LILV_NS_XSD "integer"); - world->uris.null_uri = NULL; - - world->lv2_plugin_class = lilv_plugin_class_new( - world, NULL, world->uris.lv2_Plugin, "Plugin"); - assert(world->lv2_plugin_class); - - world->n_read_files = 0; - world->opt.filter_language = true; - world->opt.dyn_manifest = true; - - return world; + world->uris.dc_replaces = NEW_URI(NS_DCTERMS "replaces"); + world->uris.dman_DynManifest = NEW_URI(NS_DYNMAN "DynManifest"); + world->uris.doap_name = NEW_URI(LILV_NS_DOAP "name"); + world->uris.lv2_Plugin = NEW_URI(LV2_CORE__Plugin); + world->uris.lv2_Specification = NEW_URI(LV2_CORE__Specification); + world->uris.lv2_appliesTo = NEW_URI(LV2_CORE__appliesTo); + world->uris.lv2_binary = NEW_URI(LV2_CORE__binary); + world->uris.lv2_default = NEW_URI(LV2_CORE__default); + world->uris.lv2_designation = NEW_URI(LV2_CORE__designation); + world->uris.lv2_extensionData = NEW_URI(LV2_CORE__extensionData); + world->uris.lv2_index = NEW_URI(LV2_CORE__index); + world->uris.lv2_latency = NEW_URI(LV2_CORE__latency); + world->uris.lv2_maximum = NEW_URI(LV2_CORE__maximum); + world->uris.lv2_microVersion = NEW_URI(LV2_CORE__microVersion); + world->uris.lv2_minimum = NEW_URI(LV2_CORE__minimum); + world->uris.lv2_minorVersion = NEW_URI(LV2_CORE__minorVersion); + world->uris.lv2_name = NEW_URI(LV2_CORE__name); + world->uris.lv2_optionalFeature = NEW_URI(LV2_CORE__optionalFeature); + world->uris.lv2_port = NEW_URI(LV2_CORE__port); + world->uris.lv2_portProperty = NEW_URI(LV2_CORE__portProperty); + world->uris.lv2_reportsLatency = NEW_URI(LV2_CORE__reportsLatency); + world->uris.lv2_requiredFeature = NEW_URI(LV2_CORE__requiredFeature); + world->uris.lv2_symbol = NEW_URI(LV2_CORE__symbol); + world->uris.lv2_prototype = NEW_URI(LV2_CORE__prototype); + world->uris.owl_Ontology = NEW_URI(NS_OWL "Ontology"); + world->uris.pset_value = NEW_URI(LV2_PRESETS__value); + world->uris.rdf_a = NEW_URI(LILV_NS_RDF "type"); + world->uris.rdf_value = NEW_URI(LILV_NS_RDF "value"); + world->uris.rdfs_Class = NEW_URI(LILV_NS_RDFS "Class"); + world->uris.rdfs_label = NEW_URI(LILV_NS_RDFS "label"); + world->uris.rdfs_seeAlso = NEW_URI(LILV_NS_RDFS "seeAlso"); + world->uris.rdfs_subClassOf = NEW_URI(LILV_NS_RDFS "subClassOf"); + world->uris.xsd_base64Binary = NEW_URI(LILV_NS_XSD "base64Binary"); + world->uris.xsd_boolean = NEW_URI(LILV_NS_XSD "boolean"); + world->uris.xsd_decimal = NEW_URI(LILV_NS_XSD "decimal"); + world->uris.xsd_double = NEW_URI(LILV_NS_XSD "double"); + world->uris.xsd_integer = NEW_URI(LILV_NS_XSD "integer"); + world->uris.null_uri = NULL; + + world->lv2_plugin_class = + lilv_plugin_class_new(world, NULL, world->uris.lv2_Plugin, "Plugin"); + assert(world->lv2_plugin_class); + + world->n_read_files = 0; + world->opt.filter_language = true; + world->opt.dyn_manifest = true; + + return world; fail: - /* keep on rockin' in the */ free(world); - return NULL; + /* keep on rockin' in the */ free(world); + return NULL; } void lilv_world_free(LilvWorld* world) { - if (!world) { - return; - } - - lilv_plugin_class_free(world->lv2_plugin_class); - world->lv2_plugin_class = NULL; - - for (SordNode** n = (SordNode**)&world->uris; *n; ++n) { - sord_node_free(world->world, *n); - } - - for (LilvSpec* spec = world->specs; spec;) { - LilvSpec* next = spec->next; - sord_node_free(world->world, spec->spec); - sord_node_free(world->world, spec->bundle); - lilv_nodes_free(spec->data_uris); - free(spec); - spec = next; - } - world->specs = NULL; - - LILV_FOREACH(plugins, i, world->plugins) { - const LilvPlugin* p = lilv_plugins_get(world->plugins, i); - lilv_plugin_free((LilvPlugin*)p); - } - zix_tree_free((ZixTree*)world->plugins); - world->plugins = NULL; - - LILV_FOREACH(plugins, i, world->zombies) { - const LilvPlugin* p = lilv_plugins_get(world->zombies, i); - lilv_plugin_free((LilvPlugin*)p); - } - zix_tree_free((ZixTree*)world->zombies); - world->zombies = NULL; - - zix_tree_free((ZixTree*)world->loaded_files); - world->loaded_files = NULL; - - zix_tree_free(world->libs); - world->libs = NULL; - - zix_tree_free((ZixTree*)world->plugin_classes); - world->plugin_classes = NULL; - - sord_free(world->model); - world->model = NULL; - - sord_world_free(world->world); - world->world = NULL; - - free(world->opt.lv2_path); - free(world); + if (!world) { + return; + } + + lilv_plugin_class_free(world->lv2_plugin_class); + world->lv2_plugin_class = NULL; + + for (SordNode** n = (SordNode**)&world->uris; *n; ++n) { + sord_node_free(world->world, *n); + } + + for (LilvSpec* spec = world->specs; spec;) { + LilvSpec* next = spec->next; + sord_node_free(world->world, spec->spec); + sord_node_free(world->world, spec->bundle); + lilv_nodes_free(spec->data_uris); + free(spec); + spec = next; + } + world->specs = NULL; + + LILV_FOREACH (plugins, i, world->plugins) { + const LilvPlugin* p = lilv_plugins_get(world->plugins, i); + lilv_plugin_free((LilvPlugin*)p); + } + zix_tree_free((ZixTree*)world->plugins); + world->plugins = NULL; + + LILV_FOREACH (plugins, i, world->zombies) { + const LilvPlugin* p = lilv_plugins_get(world->zombies, i); + lilv_plugin_free((LilvPlugin*)p); + } + zix_tree_free((ZixTree*)world->zombies); + world->zombies = NULL; + + zix_tree_free((ZixTree*)world->loaded_files); + world->loaded_files = NULL; + + zix_tree_free(world->libs); + world->libs = NULL; + + zix_tree_free((ZixTree*)world->plugin_classes); + world->plugin_classes = NULL; + + sord_free(world->model); + world->model = NULL; + + sord_world_free(world->world); + world->world = NULL; + + free(world->opt.lv2_path); + free(world); } void -lilv_world_set_option(LilvWorld* world, - const char* uri, - const LilvNode* value) +lilv_world_set_option(LilvWorld* world, const char* uri, const LilvNode* value) { - if (!strcmp(uri, LILV_OPTION_DYN_MANIFEST)) { - if (lilv_node_is_bool(value)) { - world->opt.dyn_manifest = lilv_node_as_bool(value); - return; - } - } else if (!strcmp(uri, LILV_OPTION_FILTER_LANG)) { - if (lilv_node_is_bool(value)) { - world->opt.filter_language = lilv_node_as_bool(value); - return; - } - } else if (!strcmp(uri, LILV_OPTION_LV2_PATH)) { - if (lilv_node_is_string(value)) { - world->opt.lv2_path = lilv_strdup(lilv_node_as_string(value)); - return; - } - } - LILV_WARNF("Unrecognized or invalid option `%s'\n", uri); + if (!strcmp(uri, LILV_OPTION_DYN_MANIFEST)) { + if (lilv_node_is_bool(value)) { + world->opt.dyn_manifest = lilv_node_as_bool(value); + return; + } + } else if (!strcmp(uri, LILV_OPTION_FILTER_LANG)) { + if (lilv_node_is_bool(value)) { + world->opt.filter_language = lilv_node_as_bool(value); + return; + } + } else if (!strcmp(uri, LILV_OPTION_LV2_PATH)) { + if (lilv_node_is_string(value)) { + world->opt.lv2_path = lilv_strdup(lilv_node_as_string(value)); + return; + } + } + LILV_WARNF("Unrecognized or invalid option `%s'\n", uri); } LilvNodes* @@ -213,32 +211,32 @@ lilv_world_find_nodes(LilvWorld* world, const LilvNode* predicate, const LilvNode* object) { - if (subject && !lilv_node_is_uri(subject) && !lilv_node_is_blank(subject)) { - LILV_ERRORF("Subject `%s' is not a resource\n", - sord_node_get_string(subject->node)); - return NULL; - } - - if (!predicate) { - LILV_ERROR("Missing required predicate\n"); - return NULL; - } - - if (!lilv_node_is_uri(predicate)) { - LILV_ERRORF("Predicate `%s' is not a URI\n", - sord_node_get_string(predicate->node)); - return NULL; - } - - if (!subject && !object) { - LILV_ERROR("Both subject and object are NULL\n"); - return NULL; - } - - return lilv_world_find_nodes_internal(world, - subject ? subject->node : NULL, - predicate->node, - object ? object->node : NULL); + if (subject && !lilv_node_is_uri(subject) && !lilv_node_is_blank(subject)) { + LILV_ERRORF("Subject `%s' is not a resource\n", + sord_node_get_string(subject->node)); + return NULL; + } + + if (!predicate) { + LILV_ERROR("Missing required predicate\n"); + return NULL; + } + + if (!lilv_node_is_uri(predicate)) { + LILV_ERRORF("Predicate `%s' is not a URI\n", + sord_node_get_string(predicate->node)); + return NULL; + } + + if (!subject && !object) { + LILV_ERROR("Both subject and object are NULL\n"); + return NULL; + } + + return lilv_world_find_nodes_internal(world, + subject ? subject->node : NULL, + predicate->node, + object ? object->node : NULL); } LilvNode* @@ -247,34 +245,34 @@ lilv_world_get(LilvWorld* world, const LilvNode* predicate, const LilvNode* object) { - if (!object) { - // TODO: Improve performance (see lilv_plugin_get_one) - SordIter* stream = sord_search(world->model, - subject ? subject->node : NULL, - predicate ? predicate->node : NULL, - NULL, - NULL); - - LilvNodes* nodes = - lilv_nodes_from_stream_objects(world, stream, SORD_OBJECT); - - if (nodes) { - LilvNode* value = lilv_node_duplicate(lilv_nodes_get_first(nodes)); - lilv_nodes_free(nodes); - return value; - } - - return NULL; - } - - SordNode* snode = sord_get(world->model, - subject ? subject->node : NULL, - predicate ? predicate->node : NULL, - object ? object->node : NULL, - NULL); - LilvNode* lnode = lilv_node_new_from_node(world, snode); - sord_node_free(world->world, snode); - return lnode; + if (!object) { + // TODO: Improve performance (see lilv_plugin_get_one) + SordIter* stream = sord_search(world->model, + subject ? subject->node : NULL, + predicate ? predicate->node : NULL, + NULL, + NULL); + + LilvNodes* nodes = + lilv_nodes_from_stream_objects(world, stream, SORD_OBJECT); + + if (nodes) { + LilvNode* value = lilv_node_duplicate(lilv_nodes_get_first(nodes)); + lilv_nodes_free(nodes); + return value; + } + + return NULL; + } + + SordNode* snode = sord_get(world->model, + subject ? subject->node : NULL, + predicate ? predicate->node : NULL, + object ? object->node : NULL, + NULL); + LilvNode* lnode = lilv_node_new_from_node(world, snode); + sord_node_free(world->world, snode); + return lnode; } SordIter* @@ -283,7 +281,7 @@ lilv_world_query_internal(LilvWorld* world, const SordNode* predicate, const SordNode* object) { - return sord_search(world->model, subject, predicate, object, NULL); + return sord_search(world->model, subject, predicate, object, NULL); } bool @@ -292,7 +290,7 @@ lilv_world_ask_internal(LilvWorld* world, const SordNode* predicate, const SordNode* object) { - return sord_ask(world->model, subject, predicate, object, NULL); + return sord_ask(world->model, subject, predicate, object, NULL); } bool @@ -301,11 +299,11 @@ lilv_world_ask(LilvWorld* world, const LilvNode* predicate, const LilvNode* object) { - return sord_ask(world->model, - subject ? subject->node : NULL, - predicate ? predicate->node : NULL, - object ? object->node : NULL, - NULL); + return sord_ask(world->model, + subject ? subject->node : NULL, + predicate ? predicate->node : NULL, + object ? object->node : NULL, + NULL); } SordModel* @@ -316,15 +314,15 @@ lilv_world_filter_model(LilvWorld* world, const SordNode* object, const SordNode* graph) { - SordModel* results = sord_new(world->world, SORD_SPO, false); - SordIter* i = sord_search(model, subject, predicate, object, graph); - for (; !sord_iter_end(i); sord_iter_next(i)) { - SordQuad quad; - sord_iter_get(i, quad); - sord_add(results, quad); - } - sord_iter_free(i); - return results; + SordModel* results = sord_new(world->world, SORD_SPO, false); + SordIter* i = sord_search(model, subject, predicate, object, graph); + for (; !sord_iter_end(i); sord_iter_next(i)) { + SordQuad quad; + sord_iter_get(i, quad); + sord_add(results, quad); + } + sord_iter_free(i); + return results; } LilvNodes* @@ -333,37 +331,37 @@ lilv_world_find_nodes_internal(LilvWorld* world, const SordNode* predicate, const SordNode* object) { - return lilv_nodes_from_stream_objects( - world, - lilv_world_query_internal(world, subject, predicate, object), - (object == NULL) ? SORD_OBJECT : SORD_SUBJECT); + return lilv_nodes_from_stream_objects( + world, + lilv_world_query_internal(world, subject, predicate, object), + (object == NULL) ? SORD_OBJECT : SORD_SUBJECT); } static SerdNode lilv_new_uri_relative_to_base(const uint8_t* uri_str, const uint8_t* base_uri_str) { - SerdURI base_uri; - serd_uri_parse(base_uri_str, &base_uri); - return serd_node_new_uri_from_string(uri_str, &base_uri, NULL); + SerdURI base_uri; + serd_uri_parse(base_uri_str, &base_uri); + return serd_node_new_uri_from_string(uri_str, &base_uri, NULL); } const uint8_t* lilv_world_blank_node_prefix(LilvWorld* world) { - static char str[32]; - snprintf(str, sizeof(str), "%u", world->n_read_files++); - return (const uint8_t*)str; + static char str[32]; + snprintf(str, sizeof(str), "%u", world->n_read_files++); + return (const uint8_t*)str; } /** Comparator for sequences (e.g. world->plugins). */ int lilv_header_compare_by_uri(const void* a, const void* b, void* user_data) { - const struct LilvHeader* const header_a = (const struct LilvHeader*)a; - const struct LilvHeader* const header_b = (const struct LilvHeader*)b; - return strcmp(lilv_node_as_uri(header_a->uri), - lilv_node_as_uri(header_b->uri)); + const struct LilvHeader* const header_a = (const struct LilvHeader*)a; + const struct LilvHeader* const header_b = (const struct LilvHeader*)b; + return strcmp(lilv_node_as_uri(header_a->uri), + lilv_node_as_uri(header_b->uri)); } /** @@ -376,32 +374,31 @@ lilv_header_compare_by_uri(const void* a, const void* b, void* user_data) int lilv_lib_compare(const void* a, const void* b, void* user_data) { - const LilvLib* const lib_a = (const LilvLib*)a; - const LilvLib* const lib_b = (const LilvLib*)b; - int cmp = strcmp(lilv_node_as_uri(lib_a->uri), - lilv_node_as_uri(lib_b->uri)); - return cmp ? cmp : strcmp(lib_a->bundle_path, lib_b->bundle_path); + const LilvLib* const lib_a = (const LilvLib*)a; + const LilvLib* const lib_b = (const LilvLib*)b; + int cmp = strcmp(lilv_node_as_uri(lib_a->uri), lilv_node_as_uri(lib_b->uri)); + return cmp ? cmp : strcmp(lib_a->bundle_path, lib_b->bundle_path); } /** Get an element of a collection of any object with an LilvHeader by URI. */ static ZixTreeIter* lilv_collection_find_by_uri(const ZixTree* seq, const LilvNode* uri) { - ZixTreeIter* i = NULL; - if (lilv_node_is_uri(uri)) { - struct LilvHeader key = { NULL, (LilvNode*)uri }; - zix_tree_find(seq, &key, &i); - } - return i; + ZixTreeIter* i = NULL; + if (lilv_node_is_uri(uri)) { + struct LilvHeader key = {NULL, (LilvNode*)uri}; + zix_tree_find(seq, &key, &i); + } + return i; } /** Get an element of a collection of any object with an LilvHeader by URI. */ struct LilvHeader* lilv_collection_get_by_uri(const ZixTree* seq, const LilvNode* uri) { - ZixTreeIter* const i = lilv_collection_find_by_uri(seq, uri); + ZixTreeIter* const i = lilv_collection_find_by_uri(seq, uri); - return i ? (struct LilvHeader*)zix_tree_get(i) : NULL; + return i ? (struct LilvHeader*)zix_tree_get(i) : NULL; } static void @@ -409,28 +406,25 @@ lilv_world_add_spec(LilvWorld* world, const SordNode* specification_node, const SordNode* bundle_node) { - LilvSpec* spec = (LilvSpec*)malloc(sizeof(LilvSpec)); - spec->spec = sord_node_copy(specification_node); - spec->bundle = sord_node_copy(bundle_node); - spec->data_uris = lilv_nodes_new(); - - // Add all data files (rdfs:seeAlso) - SordIter* files = sord_search(world->model, - specification_node, - world->uris.rdfs_seeAlso, - NULL, - NULL); - FOREACH_MATCH(files) { - const SordNode* file_node = sord_iter_get_node(files, SORD_OBJECT); - zix_tree_insert((ZixTree*)spec->data_uris, - lilv_node_new_from_node(world, file_node), - NULL); - } - sord_iter_free(files); - - // Add specification to world specification list - spec->next = world->specs; - world->specs = spec; + LilvSpec* spec = (LilvSpec*)malloc(sizeof(LilvSpec)); + spec->spec = sord_node_copy(specification_node); + spec->bundle = sord_node_copy(bundle_node); + spec->data_uris = lilv_nodes_new(); + + // Add all data files (rdfs:seeAlso) + SordIter* files = sord_search( + world->model, specification_node, world->uris.rdfs_seeAlso, NULL, NULL); + FOREACH_MATCH (files) { + const SordNode* file_node = sord_iter_get_node(files, SORD_OBJECT); + zix_tree_insert((ZixTree*)spec->data_uris, + lilv_node_new_from_node(world, file_node), + NULL); + } + sord_iter_free(files); + + // Add specification to world specification list + spec->next = world->specs; + world->specs = spec; } static void @@ -440,86 +434,80 @@ lilv_world_add_plugin(LilvWorld* world, void* dynmanifest, const SordNode* bundle) { - LilvNode* plugin_uri = lilv_node_new_from_node(world, plugin_node); - ZixTreeIter* z = NULL; - LilvPlugin* plugin = (LilvPlugin*)lilv_plugins_get_by_uri( - world->plugins, plugin_uri); - - if (plugin) { - // Existing plugin, if this is different bundle, ignore it - // (use the first plugin found in LV2_PATH) - const LilvNode* last_bundle = lilv_plugin_get_bundle_uri(plugin); - const char* plugin_uri_str = lilv_node_as_uri(plugin_uri); - if (sord_node_equals(bundle, last_bundle->node)) { - LILV_WARNF("Reloading plugin <%s>\n", plugin_uri_str); - plugin->loaded = false; - lilv_node_free(plugin_uri); - } else { - LILV_WARNF("Duplicate plugin <%s>\n", plugin_uri_str); - LILV_WARNF("... found in %s\n", lilv_node_as_string(last_bundle)); - LILV_WARNF("... and %s (ignored)\n", sord_node_get_string(bundle)); - lilv_node_free(plugin_uri); - return; - } - } else if ((z = lilv_collection_find_by_uri((const ZixTree*)world->zombies, - plugin_uri))) { - // Plugin bundle has been re-loaded, move from zombies to plugins - plugin = (LilvPlugin*)zix_tree_get(z); - zix_tree_remove((ZixTree*)world->zombies, z); - zix_tree_insert((ZixTree*)world->plugins, plugin, NULL); - lilv_node_free(plugin_uri); - lilv_plugin_clear(plugin, lilv_node_new_from_node(world, bundle)); - } else { - // Add new plugin to the world - plugin = lilv_plugin_new( - world, plugin_uri, lilv_node_new_from_node(world, bundle)); - - // Add manifest as plugin data file (as if it were rdfs:seeAlso) - zix_tree_insert((ZixTree*)plugin->data_uris, - lilv_node_duplicate(manifest_uri), - NULL); - - // Add plugin to world plugin sequence - zix_tree_insert((ZixTree*)world->plugins, plugin, NULL); - } - + LilvNode* plugin_uri = lilv_node_new_from_node(world, plugin_node); + ZixTreeIter* z = NULL; + LilvPlugin* plugin = + (LilvPlugin*)lilv_plugins_get_by_uri(world->plugins, plugin_uri); + + if (plugin) { + // Existing plugin, if this is different bundle, ignore it + // (use the first plugin found in LV2_PATH) + const LilvNode* last_bundle = lilv_plugin_get_bundle_uri(plugin); + const char* plugin_uri_str = lilv_node_as_uri(plugin_uri); + if (sord_node_equals(bundle, last_bundle->node)) { + LILV_WARNF("Reloading plugin <%s>\n", plugin_uri_str); + plugin->loaded = false; + lilv_node_free(plugin_uri); + } else { + LILV_WARNF("Duplicate plugin <%s>\n", plugin_uri_str); + LILV_WARNF("... found in %s\n", lilv_node_as_string(last_bundle)); + LILV_WARNF("... and %s (ignored)\n", sord_node_get_string(bundle)); + lilv_node_free(plugin_uri); + return; + } + } else if ((z = lilv_collection_find_by_uri((const ZixTree*)world->zombies, + plugin_uri))) { + // Plugin bundle has been re-loaded, move from zombies to plugins + plugin = (LilvPlugin*)zix_tree_get(z); + zix_tree_remove((ZixTree*)world->zombies, z); + zix_tree_insert((ZixTree*)world->plugins, plugin, NULL); + lilv_node_free(plugin_uri); + lilv_plugin_clear(plugin, lilv_node_new_from_node(world, bundle)); + } else { + // Add new plugin to the world + plugin = lilv_plugin_new( + world, plugin_uri, lilv_node_new_from_node(world, bundle)); + + // Add manifest as plugin data file (as if it were rdfs:seeAlso) + zix_tree_insert( + (ZixTree*)plugin->data_uris, lilv_node_duplicate(manifest_uri), NULL); + + // Add plugin to world plugin sequence + zix_tree_insert((ZixTree*)world->plugins, plugin, NULL); + } #ifdef LILV_DYN_MANIFEST - // Set dynamic manifest library URI, if applicable - if (dynmanifest) { - plugin->dynmanifest = (LilvDynManifest*)dynmanifest; - ++((LilvDynManifest*)dynmanifest)->refs; - } + // Set dynamic manifest library URI, if applicable + if (dynmanifest) { + plugin->dynmanifest = (LilvDynManifest*)dynmanifest; + ++((LilvDynManifest*)dynmanifest)->refs; + } #endif - // Add all plugin data files (rdfs:seeAlso) - SordIter* files = sord_search(world->model, - plugin_node, - world->uris.rdfs_seeAlso, - NULL, - NULL); - FOREACH_MATCH(files) { - const SordNode* file_node = sord_iter_get_node(files, SORD_OBJECT); - zix_tree_insert((ZixTree*)plugin->data_uris, - lilv_node_new_from_node(world, file_node), - NULL); - } - sord_iter_free(files); + // Add all plugin data files (rdfs:seeAlso) + SordIter* files = sord_search( + world->model, plugin_node, world->uris.rdfs_seeAlso, NULL, NULL); + FOREACH_MATCH (files) { + const SordNode* file_node = sord_iter_get_node(files, SORD_OBJECT); + zix_tree_insert((ZixTree*)plugin->data_uris, + lilv_node_new_from_node(world, file_node), + NULL); + } + sord_iter_free(files); } SerdStatus lilv_world_load_graph(LilvWorld* world, SordNode* graph, const LilvNode* uri) { - const SerdNode* base = sord_node_to_serd_node(uri->node); - SerdEnv* env = serd_env_new(base); - SerdReader* reader = sord_new_reader( - world->model, env, SERD_TURTLE, graph); + const SerdNode* base = sord_node_to_serd_node(uri->node); + SerdEnv* env = serd_env_new(base); + SerdReader* reader = sord_new_reader(world->model, env, SERD_TURTLE, graph); - const SerdStatus st = lilv_world_load_file(world, reader, uri); + const SerdStatus st = lilv_world_load_file(world, reader, uri); - serd_env_free(env); - serd_reader_free(reader); - return st; + serd_env_free(env); + serd_reader_free(reader); + return st; } static void @@ -528,161 +516,154 @@ lilv_world_load_dyn_manifest(LilvWorld* world, const LilvNode* manifest) { #ifdef LILV_DYN_MANIFEST - if (!world->opt.dyn_manifest) { - return; - } - - LV2_Dyn_Manifest_Handle handle = NULL; - - // ?dman a dynman:DynManifest bundle_node - SordModel* model = lilv_world_filter_model(world, - world->model, - NULL, - world->uris.rdf_a, - world->uris.dman_DynManifest, - bundle_node); - SordIter* iter = sord_begin(model); - for (; !sord_iter_end(iter); sord_iter_next(iter)) { - const SordNode* dmanifest = sord_iter_get_node(iter, SORD_SUBJECT); - - // ?dman lv2:binary ?binary - SordIter* binaries = sord_search(world->model, - dmanifest, - world->uris.lv2_binary, - NULL, - bundle_node); - if (sord_iter_end(binaries)) { - sord_iter_free(binaries); - LILV_ERRORF("Dynamic manifest in <%s> has no binaries, ignored\n", - sord_node_get_string(bundle_node)); - continue; - } - - // Get binary path - const SordNode* binary = sord_iter_get_node(binaries, SORD_OBJECT); - const uint8_t* lib_uri = sord_node_get_string(binary); - char* lib_path = lilv_file_uri_parse((const char*)lib_uri, 0); - if (!lib_path) { - LILV_ERROR("No dynamic manifest library path\n"); - sord_iter_free(binaries); - continue; - } - - // Open library - dlerror(); - void* lib = dlopen(lib_path, RTLD_LAZY); - if (!lib) { - LILV_ERRORF("Failed to open dynmanifest library `%s' (%s)\n", - lib_path, dlerror()); - sord_iter_free(binaries); - lilv_free(lib_path); - continue; - } - - // Open dynamic manifest - typedef int (*OpenFunc)(LV2_Dyn_Manifest_Handle*, - const LV2_Feature *const *); - OpenFunc dmopen = (OpenFunc)lilv_dlfunc(lib, "lv2_dyn_manifest_open"); - if (!dmopen || dmopen(&handle, &dman_features)) { - LILV_ERRORF("No `lv2_dyn_manifest_open' in `%s'\n", lib_path); - sord_iter_free(binaries); - dlclose(lib); - lilv_free(lib_path); - continue; - } - - // Get subjects (the data that would be in manifest.ttl) - typedef int (*GetSubjectsFunc)(LV2_Dyn_Manifest_Handle, FILE*); - GetSubjectsFunc get_subjects_func = (GetSubjectsFunc)lilv_dlfunc( - lib, "lv2_dyn_manifest_get_subjects"); - if (!get_subjects_func) { - LILV_ERRORF("No `lv2_dyn_manifest_get_subjects' in `%s'\n", - lib_path); - sord_iter_free(binaries); - dlclose(lib); - lilv_free(lib_path); - continue; - } - - LilvDynManifest* desc = (LilvDynManifest*)malloc(sizeof(LilvDynManifest)); - desc->bundle = lilv_node_new_from_node(world, bundle_node); - desc->lib = lib; - desc->handle = handle; - desc->refs = 0; - - sord_iter_free(binaries); - - // Generate data file - FILE* fd = tmpfile(); - get_subjects_func(handle, fd); - rewind(fd); - - // Parse generated data file into temporary model - // FIXME - const SerdNode* base = sord_node_to_serd_node(dmanifest); - SerdEnv* env = serd_env_new(base); - SerdReader* reader = sord_new_reader( - world->model, env, SERD_TURTLE, sord_node_copy(dmanifest)); - serd_reader_add_blank_prefix(reader, - lilv_world_blank_node_prefix(world)); - serd_reader_read_file_handle(reader, fd, - (const uint8_t*)"(dyn-manifest)"); - serd_reader_free(reader); - serd_env_free(env); - - // Close (and automatically delete) temporary data file - fclose(fd); - - // ?plugin a lv2:Plugin - SordModel* plugins = lilv_world_filter_model(world, - world->model, - NULL, - world->uris.rdf_a, - world->uris.lv2_Plugin, - dmanifest); - SordIter* p = sord_begin(plugins); - FOREACH_MATCH(p) { - const SordNode* plug = sord_iter_get_node(p, SORD_SUBJECT); - lilv_world_add_plugin(world, plug, manifest, desc, bundle_node); - } - if (desc->refs == 0) { - lilv_dynmanifest_free(desc); - } - sord_iter_free(p); - sord_free(plugins); - lilv_free(lib_path); - } - sord_iter_free(iter); - sord_free(model); -#endif // LILV_DYN_MANIFEST + if (!world->opt.dyn_manifest) { + return; + } + + LV2_Dyn_Manifest_Handle handle = NULL; + + // ?dman a dynman:DynManifest bundle_node + SordModel* model = lilv_world_filter_model(world, + world->model, + NULL, + world->uris.rdf_a, + world->uris.dman_DynManifest, + bundle_node); + SordIter* iter = sord_begin(model); + for (; !sord_iter_end(iter); sord_iter_next(iter)) { + const SordNode* dmanifest = sord_iter_get_node(iter, SORD_SUBJECT); + + // ?dman lv2:binary ?binary + SordIter* binaries = sord_search( + world->model, dmanifest, world->uris.lv2_binary, NULL, bundle_node); + if (sord_iter_end(binaries)) { + sord_iter_free(binaries); + LILV_ERRORF("Dynamic manifest in <%s> has no binaries, ignored\n", + sord_node_get_string(bundle_node)); + continue; + } + + // Get binary path + const SordNode* binary = sord_iter_get_node(binaries, SORD_OBJECT); + const uint8_t* lib_uri = sord_node_get_string(binary); + char* lib_path = lilv_file_uri_parse((const char*)lib_uri, 0); + if (!lib_path) { + LILV_ERROR("No dynamic manifest library path\n"); + sord_iter_free(binaries); + continue; + } + + // Open library + dlerror(); + void* lib = dlopen(lib_path, RTLD_LAZY); + if (!lib) { + LILV_ERRORF( + "Failed to open dynmanifest library `%s' (%s)\n", lib_path, dlerror()); + sord_iter_free(binaries); + lilv_free(lib_path); + continue; + } + + // Open dynamic manifest + typedef int (*OpenFunc)(LV2_Dyn_Manifest_Handle*, + const LV2_Feature* const*); + OpenFunc dmopen = (OpenFunc)lilv_dlfunc(lib, "lv2_dyn_manifest_open"); + if (!dmopen || dmopen(&handle, &dman_features)) { + LILV_ERRORF("No `lv2_dyn_manifest_open' in `%s'\n", lib_path); + sord_iter_free(binaries); + dlclose(lib); + lilv_free(lib_path); + continue; + } + + // Get subjects (the data that would be in manifest.ttl) + typedef int (*GetSubjectsFunc)(LV2_Dyn_Manifest_Handle, FILE*); + GetSubjectsFunc get_subjects_func = + (GetSubjectsFunc)lilv_dlfunc(lib, "lv2_dyn_manifest_get_subjects"); + if (!get_subjects_func) { + LILV_ERRORF("No `lv2_dyn_manifest_get_subjects' in `%s'\n", lib_path); + sord_iter_free(binaries); + dlclose(lib); + lilv_free(lib_path); + continue; + } + + LilvDynManifest* desc = (LilvDynManifest*)malloc(sizeof(LilvDynManifest)); + desc->bundle = lilv_node_new_from_node(world, bundle_node); + desc->lib = lib; + desc->handle = handle; + desc->refs = 0; + + sord_iter_free(binaries); + + // Generate data file + FILE* fd = tmpfile(); + get_subjects_func(handle, fd); + rewind(fd); + + // Parse generated data file into temporary model + // FIXME + const SerdNode* base = sord_node_to_serd_node(dmanifest); + SerdEnv* env = serd_env_new(base); + SerdReader* reader = sord_new_reader( + world->model, env, SERD_TURTLE, sord_node_copy(dmanifest)); + serd_reader_add_blank_prefix(reader, lilv_world_blank_node_prefix(world)); + serd_reader_read_file_handle(reader, fd, (const uint8_t*)"(dyn-manifest)"); + serd_reader_free(reader); + serd_env_free(env); + + // Close (and automatically delete) temporary data file + fclose(fd); + + // ?plugin a lv2:Plugin + SordModel* plugins = lilv_world_filter_model(world, + world->model, + NULL, + world->uris.rdf_a, + world->uris.lv2_Plugin, + dmanifest); + SordIter* p = sord_begin(plugins); + FOREACH_MATCH (p) { + const SordNode* plug = sord_iter_get_node(p, SORD_SUBJECT); + lilv_world_add_plugin(world, plug, manifest, desc, bundle_node); + } + if (desc->refs == 0) { + lilv_dynmanifest_free(desc); + } + sord_iter_free(p); + sord_free(plugins); + lilv_free(lib_path); + } + sord_iter_free(iter); + sord_free(model); +#endif // LILV_DYN_MANIFEST } #ifdef LILV_DYN_MANIFEST void lilv_dynmanifest_free(LilvDynManifest* dynmanifest) { - typedef int (*CloseFunc)(LV2_Dyn_Manifest_Handle); - CloseFunc close_func = (CloseFunc)lilv_dlfunc(dynmanifest->lib, - "lv2_dyn_manifest_close"); - if (close_func) { - close_func(dynmanifest->handle); - } - - dlclose(dynmanifest->lib); - lilv_node_free(dynmanifest->bundle); - free(dynmanifest); + typedef int (*CloseFunc)(LV2_Dyn_Manifest_Handle); + CloseFunc close_func = + (CloseFunc)lilv_dlfunc(dynmanifest->lib, "lv2_dyn_manifest_close"); + if (close_func) { + close_func(dynmanifest->handle); + } + + dlclose(dynmanifest->lib); + lilv_node_free(dynmanifest->bundle); + free(dynmanifest); } -#endif // LILV_DYN_MANIFEST +#endif // LILV_DYN_MANIFEST LilvNode* lilv_world_get_manifest_uri(LilvWorld* world, const LilvNode* bundle_uri) { - SerdNode manifest_uri = lilv_new_uri_relative_to_base( - (const uint8_t*)"manifest.ttl", - sord_node_get_string(bundle_uri->node)); - LilvNode* manifest = lilv_new_uri(world, (const char*)manifest_uri.buf); - serd_node_free(&manifest_uri); - return manifest; + SerdNode manifest_uri = lilv_new_uri_relative_to_base( + (const uint8_t*)"manifest.ttl", sord_node_get_string(bundle_uri->node)); + LilvNode* manifest = lilv_new_uri(world, (const char*)manifest_uri.buf); + serd_node_free(&manifest_uri); + return manifest; } static SordModel* @@ -690,308 +671,298 @@ load_plugin_model(LilvWorld* world, const LilvNode* bundle_uri, const LilvNode* plugin_uri) { - // Create model and reader for loading into it - SordNode* bundle_node = bundle_uri->node; - SordModel* model = sord_new(world->world, SORD_SPO|SORD_OPS, false); - SerdEnv* env = serd_env_new(sord_node_to_serd_node(bundle_node)); - SerdReader* reader = sord_new_reader(model, env, SERD_TURTLE, NULL); - - // Load manifest - LilvNode* manifest_uri = lilv_world_get_manifest_uri(world, bundle_uri); - serd_reader_add_blank_prefix(reader, lilv_world_blank_node_prefix(world)); - serd_reader_read_file( - reader, (const uint8_t*)lilv_node_as_string(manifest_uri)); - - // Load any seeAlso files - SordModel* files = lilv_world_filter_model( - world, model, plugin_uri->node, world->uris.rdfs_seeAlso, NULL, NULL); - - SordIter* f = sord_begin(files); - FOREACH_MATCH(f) { - const SordNode* file = sord_iter_get_node(f, SORD_OBJECT); - const uint8_t* file_str = sord_node_get_string(file); - if (sord_node_get_type(file) == SORD_URI) { - serd_reader_add_blank_prefix( - reader, lilv_world_blank_node_prefix(world)); - serd_reader_read_file(reader, file_str); - } - } - - sord_iter_free(f); - sord_free(files); - serd_reader_free(reader); - serd_env_free(env); - lilv_node_free(manifest_uri); - - return model; + // Create model and reader for loading into it + SordNode* bundle_node = bundle_uri->node; + SordModel* model = sord_new(world->world, SORD_SPO | SORD_OPS, false); + SerdEnv* env = serd_env_new(sord_node_to_serd_node(bundle_node)); + SerdReader* reader = sord_new_reader(model, env, SERD_TURTLE, NULL); + + // Load manifest + LilvNode* manifest_uri = lilv_world_get_manifest_uri(world, bundle_uri); + serd_reader_add_blank_prefix(reader, lilv_world_blank_node_prefix(world)); + serd_reader_read_file(reader, + (const uint8_t*)lilv_node_as_string(manifest_uri)); + + // Load any seeAlso files + SordModel* files = lilv_world_filter_model( + world, model, plugin_uri->node, world->uris.rdfs_seeAlso, NULL, NULL); + + SordIter* f = sord_begin(files); + FOREACH_MATCH (f) { + const SordNode* file = sord_iter_get_node(f, SORD_OBJECT); + const uint8_t* file_str = sord_node_get_string(file); + if (sord_node_get_type(file) == SORD_URI) { + serd_reader_add_blank_prefix(reader, lilv_world_blank_node_prefix(world)); + serd_reader_read_file(reader, file_str); + } + } + + sord_iter_free(f); + sord_free(files); + serd_reader_free(reader); + serd_env_free(env); + lilv_node_free(manifest_uri); + + return model; } static LilvVersion get_version(LilvWorld* world, SordModel* model, const LilvNode* subject) { - const SordNode* minor_node = sord_get( - model, subject->node, world->uris.lv2_minorVersion, NULL, NULL); - const SordNode* micro_node = sord_get( - model, subject->node, world->uris.lv2_microVersion, NULL, NULL); - - - LilvVersion version = { 0, 0 }; - if (minor_node && micro_node) { - version.minor = atoi((const char*)sord_node_get_string(minor_node)); - version.micro = atoi((const char*)sord_node_get_string(micro_node)); - } - - return version; + const SordNode* minor_node = + sord_get(model, subject->node, world->uris.lv2_minorVersion, NULL, NULL); + const SordNode* micro_node = + sord_get(model, subject->node, world->uris.lv2_microVersion, NULL, NULL); + + LilvVersion version = {0, 0}; + if (minor_node && micro_node) { + version.minor = atoi((const char*)sord_node_get_string(minor_node)); + version.micro = atoi((const char*)sord_node_get_string(micro_node)); + } + + return version; } void lilv_world_load_bundle(LilvWorld* world, const LilvNode* bundle_uri) { - if (!lilv_node_is_uri(bundle_uri)) { - LILV_ERRORF("Bundle URI `%s' is not a URI\n", - sord_node_get_string(bundle_uri->node)); - return; - } - - SordNode* bundle_node = bundle_uri->node; - LilvNode* manifest = lilv_world_get_manifest_uri(world, bundle_uri); - - // Read manifest into model with graph = bundle_node - SerdStatus st = lilv_world_load_graph(world, bundle_node, manifest); - if (st > SERD_FAILURE) { - LILV_ERRORF("Error reading %s\n", lilv_node_as_string(manifest)); - lilv_node_free(manifest); - return; - } - - // ?plugin a lv2:Plugin - SordIter* plug_results = sord_search(world->model, - NULL, - world->uris.rdf_a, - world->uris.lv2_Plugin, - bundle_node); - - // Find any loaded plugins that will be replaced with a newer version - LilvNodes* unload_uris = lilv_nodes_new(); - FOREACH_MATCH(plug_results) { - const SordNode* plug = sord_iter_get_node(plug_results, SORD_SUBJECT); - - LilvNode* plugin_uri = lilv_node_new_from_node(world, plug); - const LilvPlugin* plugin = lilv_plugins_get_by_uri(world->plugins, plugin_uri); - const LilvNode* last_bundle = plugin ? lilv_plugin_get_bundle_uri(plugin) : NULL; - if (!plugin || sord_node_equals(bundle_node, last_bundle->node)) { - // No previously loaded version, or it's from the same bundle - lilv_node_free(plugin_uri); - continue; - } - - // Compare versions - SordModel* this_model = load_plugin_model(world, bundle_uri, plugin_uri); - LilvVersion this_version = get_version(world, this_model, plugin_uri); - SordModel* last_model = load_plugin_model(world, last_bundle, plugin_uri); - LilvVersion last_version = get_version(world, last_model, plugin_uri); - sord_free(this_model); - sord_free(last_model); - const int cmp = lilv_version_cmp(&this_version, &last_version); - if (cmp > 0) { - zix_tree_insert((ZixTree*)unload_uris, - lilv_node_duplicate(plugin_uri), - NULL); - LILV_WARNF("Replacing version %d.%d of <%s> from <%s>\n", - last_version.minor, last_version.micro, - sord_node_get_string(plug), - sord_node_get_string(last_bundle->node)); - LILV_NOTEF("New version %d.%d found in <%s>\n", - this_version.minor, this_version.micro, - sord_node_get_string(bundle_node)); - } else if (cmp < 0) { - LILV_WARNF("Ignoring bundle <%s>\n", - sord_node_get_string(bundle_node)); - LILV_NOTEF("Newer version of <%s> loaded from <%s>\n", - sord_node_get_string(plug), - sord_node_get_string(last_bundle->node)); - lilv_node_free(plugin_uri); - sord_iter_free(plug_results); - lilv_world_drop_graph(world, bundle_node); - lilv_node_free(manifest); - lilv_nodes_free(unload_uris); - return; - } - lilv_node_free(plugin_uri); - } - - sord_iter_free(plug_results); - - // Unload any old conflicting plugins - LilvNodes* unload_bundles = lilv_nodes_new(); - LILV_FOREACH(nodes, i, unload_uris) { - const LilvNode* uri = lilv_nodes_get(unload_uris, i); - const LilvPlugin* plugin = lilv_plugins_get_by_uri(world->plugins, uri); - const LilvNode* bundle = lilv_plugin_get_bundle_uri(plugin); - - // Unload plugin and record bundle for later unloading - lilv_world_unload_resource(world, uri); - zix_tree_insert((ZixTree*)unload_bundles, - lilv_node_duplicate(bundle), - NULL); - - } - lilv_nodes_free(unload_uris); - - // Now unload the associated bundles - // This must be done last since several plugins could be in the same bundle - LILV_FOREACH(nodes, i, unload_bundles) { - lilv_world_unload_bundle(world, lilv_nodes_get(unload_bundles, i)); - } - lilv_nodes_free(unload_bundles); - - // Re-search for plugin results now that old plugins are gone - plug_results = sord_search(world->model, - NULL, - world->uris.rdf_a, - world->uris.lv2_Plugin, - bundle_node); - - FOREACH_MATCH(plug_results) { - const SordNode* plug = sord_iter_get_node(plug_results, SORD_SUBJECT); - lilv_world_add_plugin(world, plug, manifest, NULL, bundle_node); - } - sord_iter_free(plug_results); - - lilv_world_load_dyn_manifest(world, bundle_node, manifest); - - // ?spec a lv2:Specification - // ?spec a owl:Ontology - const SordNode* spec_preds[] = { world->uris.lv2_Specification, - world->uris.owl_Ontology, - NULL }; - for (const SordNode** p = spec_preds; *p; ++p) { - SordIter* i = sord_search( - world->model, NULL, world->uris.rdf_a, *p, bundle_node); - FOREACH_MATCH(i) { - const SordNode* spec = sord_iter_get_node(i, SORD_SUBJECT); - lilv_world_add_spec(world, spec, bundle_node); - } - sord_iter_free(i); - } - - lilv_node_free(manifest); + if (!lilv_node_is_uri(bundle_uri)) { + LILV_ERRORF("Bundle URI `%s' is not a URI\n", + sord_node_get_string(bundle_uri->node)); + return; + } + + SordNode* bundle_node = bundle_uri->node; + LilvNode* manifest = lilv_world_get_manifest_uri(world, bundle_uri); + + // Read manifest into model with graph = bundle_node + SerdStatus st = lilv_world_load_graph(world, bundle_node, manifest); + if (st > SERD_FAILURE) { + LILV_ERRORF("Error reading %s\n", lilv_node_as_string(manifest)); + lilv_node_free(manifest); + return; + } + + // ?plugin a lv2:Plugin + SordIter* plug_results = sord_search( + world->model, NULL, world->uris.rdf_a, world->uris.lv2_Plugin, bundle_node); + + // Find any loaded plugins that will be replaced with a newer version + LilvNodes* unload_uris = lilv_nodes_new(); + FOREACH_MATCH (plug_results) { + const SordNode* plug = sord_iter_get_node(plug_results, SORD_SUBJECT); + + LilvNode* plugin_uri = lilv_node_new_from_node(world, plug); + const LilvPlugin* plugin = + lilv_plugins_get_by_uri(world->plugins, plugin_uri); + const LilvNode* last_bundle = + plugin ? lilv_plugin_get_bundle_uri(plugin) : NULL; + if (!plugin || sord_node_equals(bundle_node, last_bundle->node)) { + // No previously loaded version, or it's from the same bundle + lilv_node_free(plugin_uri); + continue; + } + + // Compare versions + SordModel* this_model = load_plugin_model(world, bundle_uri, plugin_uri); + LilvVersion this_version = get_version(world, this_model, plugin_uri); + SordModel* last_model = load_plugin_model(world, last_bundle, plugin_uri); + LilvVersion last_version = get_version(world, last_model, plugin_uri); + sord_free(this_model); + sord_free(last_model); + const int cmp = lilv_version_cmp(&this_version, &last_version); + if (cmp > 0) { + zix_tree_insert( + (ZixTree*)unload_uris, lilv_node_duplicate(plugin_uri), NULL); + LILV_WARNF("Replacing version %d.%d of <%s> from <%s>\n", + last_version.minor, + last_version.micro, + sord_node_get_string(plug), + sord_node_get_string(last_bundle->node)); + LILV_NOTEF("New version %d.%d found in <%s>\n", + this_version.minor, + this_version.micro, + sord_node_get_string(bundle_node)); + } else if (cmp < 0) { + LILV_WARNF("Ignoring bundle <%s>\n", sord_node_get_string(bundle_node)); + LILV_NOTEF("Newer version of <%s> loaded from <%s>\n", + sord_node_get_string(plug), + sord_node_get_string(last_bundle->node)); + lilv_node_free(plugin_uri); + sord_iter_free(plug_results); + lilv_world_drop_graph(world, bundle_node); + lilv_node_free(manifest); + lilv_nodes_free(unload_uris); + return; + } + lilv_node_free(plugin_uri); + } + + sord_iter_free(plug_results); + + // Unload any old conflicting plugins + LilvNodes* unload_bundles = lilv_nodes_new(); + LILV_FOREACH (nodes, i, unload_uris) { + const LilvNode* uri = lilv_nodes_get(unload_uris, i); + const LilvPlugin* plugin = lilv_plugins_get_by_uri(world->plugins, uri); + const LilvNode* bundle = lilv_plugin_get_bundle_uri(plugin); + + // Unload plugin and record bundle for later unloading + lilv_world_unload_resource(world, uri); + zix_tree_insert( + (ZixTree*)unload_bundles, lilv_node_duplicate(bundle), NULL); + } + lilv_nodes_free(unload_uris); + + // Now unload the associated bundles + // This must be done last since several plugins could be in the same bundle + LILV_FOREACH (nodes, i, unload_bundles) { + lilv_world_unload_bundle(world, lilv_nodes_get(unload_bundles, i)); + } + lilv_nodes_free(unload_bundles); + + // Re-search for plugin results now that old plugins are gone + plug_results = sord_search( + world->model, NULL, world->uris.rdf_a, world->uris.lv2_Plugin, bundle_node); + + FOREACH_MATCH (plug_results) { + const SordNode* plug = sord_iter_get_node(plug_results, SORD_SUBJECT); + lilv_world_add_plugin(world, plug, manifest, NULL, bundle_node); + } + sord_iter_free(plug_results); + + lilv_world_load_dyn_manifest(world, bundle_node, manifest); + + // ?spec a lv2:Specification + // ?spec a owl:Ontology + const SordNode* spec_preds[] = { + world->uris.lv2_Specification, world->uris.owl_Ontology, NULL}; + for (const SordNode** p = spec_preds; *p; ++p) { + SordIter* i = + sord_search(world->model, NULL, world->uris.rdf_a, *p, bundle_node); + FOREACH_MATCH (i) { + const SordNode* spec = sord_iter_get_node(i, SORD_SUBJECT); + lilv_world_add_spec(world, spec, bundle_node); + } + sord_iter_free(i); + } + + lilv_node_free(manifest); } static int lilv_world_drop_graph(LilvWorld* world, const SordNode* graph) { - SordIter* i = sord_search(world->model, NULL, NULL, NULL, graph); - while (!sord_iter_end(i)) { - const SerdStatus st = sord_erase(world->model, i); - if (st) { - LILV_ERRORF("Error removing statement from <%s> (%s)\n", - sord_node_get_string(graph), serd_strerror(st)); - return st; - } - } - sord_iter_free(i); - - return 0; + SordIter* i = sord_search(world->model, NULL, NULL, NULL, graph); + while (!sord_iter_end(i)) { + const SerdStatus st = sord_erase(world->model, i); + if (st) { + LILV_ERRORF("Error removing statement from <%s> (%s)\n", + sord_node_get_string(graph), + serd_strerror(st)); + return st; + } + } + sord_iter_free(i); + + return 0; } /** Remove loaded_files entry so file will be reloaded if requested. */ static int lilv_world_unload_file(LilvWorld* world, const LilvNode* file) { - ZixTreeIter* iter = NULL; - if (!zix_tree_find((ZixTree*)world->loaded_files, file, &iter)) { - zix_tree_remove((ZixTree*)world->loaded_files, iter); - return 0; - } - return 1; + ZixTreeIter* iter = NULL; + if (!zix_tree_find((ZixTree*)world->loaded_files, file, &iter)) { + zix_tree_remove((ZixTree*)world->loaded_files, iter); + return 0; + } + return 1; } int lilv_world_unload_bundle(LilvWorld* world, const LilvNode* bundle_uri) { - if (!bundle_uri) { - return 0; - } - - // Find all loaded files that are inside the bundle - LilvNodes* files = lilv_nodes_new(); - LILV_FOREACH(nodes, i, world->loaded_files) { - const LilvNode* file = lilv_nodes_get(world->loaded_files, i); - if (!strncmp(lilv_node_as_string(file), - lilv_node_as_string(bundle_uri), - strlen(lilv_node_as_string(bundle_uri)))) { - zix_tree_insert((ZixTree*)files, - lilv_node_duplicate(file), - NULL); - } - } - - // Unload all loaded files in the bundle - LILV_FOREACH(nodes, i, files) { - const LilvNode* file = lilv_nodes_get(world->plugins, i); - lilv_world_unload_file(world, file); - } - - lilv_nodes_free(files); - - /* Remove any plugins in the bundle from the plugin list. Since the - application may still have a pointer to the LilvPlugin, it can not be - destroyed here. Instead, we move it to the zombie plugin list, so it - will not be in the list returned by lilv_world_get_all_plugins() but can - still be used. - */ - ZixTreeIter* i = zix_tree_begin((ZixTree*)world->plugins); - while (i != zix_tree_end((ZixTree*)world->plugins)) { - LilvPlugin* p = (LilvPlugin*)zix_tree_get(i); - ZixTreeIter* next = zix_tree_iter_next(i); - - if (lilv_node_equals(lilv_plugin_get_bundle_uri(p), bundle_uri)) { - zix_tree_remove((ZixTree*)world->plugins, i); - zix_tree_insert((ZixTree*)world->zombies, p, NULL); - } - - i = next; - } - - // Drop everything in bundle graph - return lilv_world_drop_graph(world, bundle_uri->node); + if (!bundle_uri) { + return 0; + } + + // Find all loaded files that are inside the bundle + LilvNodes* files = lilv_nodes_new(); + LILV_FOREACH (nodes, i, world->loaded_files) { + const LilvNode* file = lilv_nodes_get(world->loaded_files, i); + if (!strncmp(lilv_node_as_string(file), + lilv_node_as_string(bundle_uri), + strlen(lilv_node_as_string(bundle_uri)))) { + zix_tree_insert((ZixTree*)files, lilv_node_duplicate(file), NULL); + } + } + + // Unload all loaded files in the bundle + LILV_FOREACH (nodes, i, files) { + const LilvNode* file = lilv_nodes_get(world->plugins, i); + lilv_world_unload_file(world, file); + } + + lilv_nodes_free(files); + + /* Remove any plugins in the bundle from the plugin list. Since the + application may still have a pointer to the LilvPlugin, it can not be + destroyed here. Instead, we move it to the zombie plugin list, so it + will not be in the list returned by lilv_world_get_all_plugins() but can + still be used. + */ + ZixTreeIter* i = zix_tree_begin((ZixTree*)world->plugins); + while (i != zix_tree_end((ZixTree*)world->plugins)) { + LilvPlugin* p = (LilvPlugin*)zix_tree_get(i); + ZixTreeIter* next = zix_tree_iter_next(i); + + if (lilv_node_equals(lilv_plugin_get_bundle_uri(p), bundle_uri)) { + zix_tree_remove((ZixTree*)world->plugins, i); + zix_tree_insert((ZixTree*)world->zombies, p, NULL); + } + + i = next; + } + + // Drop everything in bundle graph + return lilv_world_drop_graph(world, bundle_uri->node); } static void load_dir_entry(const char* dir, const char* name, void* data) { - LilvWorld* world = (LilvWorld*)data; - char* path = lilv_strjoin(dir, "/", name, "/", NULL); - SerdNode suri = serd_node_new_file_uri((const uint8_t*)path, 0, 0, true); - LilvNode* node = lilv_new_uri(world, (const char*)suri.buf); - - lilv_world_load_bundle(world, node); - lilv_node_free(node); - serd_node_free(&suri); - free(path); + LilvWorld* world = (LilvWorld*)data; + char* path = lilv_strjoin(dir, "/", name, "/", NULL); + SerdNode suri = serd_node_new_file_uri((const uint8_t*)path, 0, 0, true); + LilvNode* node = lilv_new_uri(world, (const char*)suri.buf); + + lilv_world_load_bundle(world, node); + lilv_node_free(node); + serd_node_free(&suri); + free(path); } /** Load all bundles in the directory at `dir_path`. */ static void lilv_world_load_directory(LilvWorld* world, const char* dir_path) { - char* path = lilv_expand(dir_path); - if (path) { - lilv_dir_for_each(path, world, load_dir_entry); - free(path); - } + char* path = lilv_expand(dir_path); + if (path) { + lilv_dir_for_each(path, world, load_dir_entry); + free(path); + } } static const char* first_path_sep(const char* path) { - for (const char* p = path; *p != '\0'; ++p) { - if (*p == LILV_PATH_SEP[0]) { - return p; - } - } - return NULL; + for (const char* p = path; *p != '\0'; ++p) { + if (*p == LILV_PATH_SEP[0]) { + return p; + } + } + return NULL; } /** Load all bundles found in `lv2_path`. @@ -1000,279 +971,265 @@ first_path_sep(const char* path) * parent directories of bundles, not a list of bundle directories). */ static void -lilv_world_load_path(LilvWorld* world, - const char* lv2_path) +lilv_world_load_path(LilvWorld* world, const char* lv2_path) { - while (lv2_path[0] != '\0') { - const char* const sep = first_path_sep(lv2_path); - if (sep) { - const size_t dir_len = sep - lv2_path; - char* const dir = (char*)malloc(dir_len + 1); - memcpy(dir, lv2_path, dir_len); - dir[dir_len] = '\0'; - lilv_world_load_directory(world, dir); - free(dir); - lv2_path += dir_len + 1; - } else { - lilv_world_load_directory(world, lv2_path); - lv2_path = "\0"; - } - } + while (lv2_path[0] != '\0') { + const char* const sep = first_path_sep(lv2_path); + if (sep) { + const size_t dir_len = sep - lv2_path; + char* const dir = (char*)malloc(dir_len + 1); + memcpy(dir, lv2_path, dir_len); + dir[dir_len] = '\0'; + lilv_world_load_directory(world, dir); + free(dir); + lv2_path += dir_len + 1; + } else { + lilv_world_load_directory(world, lv2_path); + lv2_path = "\0"; + } + } } void lilv_world_load_specifications(LilvWorld* world) { - for (LilvSpec* spec = world->specs; spec; spec = spec->next) { - LILV_FOREACH(nodes, f, spec->data_uris) { - LilvNode* file = (LilvNode*)lilv_collection_get(spec->data_uris, f); - lilv_world_load_graph(world, NULL, file); - } - } + for (LilvSpec* spec = world->specs; spec; spec = spec->next) { + LILV_FOREACH (nodes, f, spec->data_uris) { + LilvNode* file = (LilvNode*)lilv_collection_get(spec->data_uris, f); + lilv_world_load_graph(world, NULL, file); + } + } } void lilv_world_load_plugin_classes(LilvWorld* world) { - /* FIXME: This loads all classes, not just lv2:Plugin subclasses. - However, if the host gets all the classes via lilv_plugin_class_get_children - starting with lv2:Plugin as the root (which is e.g. how a host would build - a menu), they won't be seen anyway... - */ - - SordIter* classes = sord_search(world->model, - NULL, - world->uris.rdf_a, - world->uris.rdfs_Class, - NULL); - FOREACH_MATCH(classes) { - const SordNode* class_node = sord_iter_get_node(classes, SORD_SUBJECT); - - SordNode* parent = sord_get( - world->model, class_node, world->uris.rdfs_subClassOf, NULL, NULL); - if (!parent || sord_node_get_type(parent) != SORD_URI) { - continue; - } - - SordNode* label = sord_get( - world->model, class_node, world->uris.rdfs_label, NULL, NULL); - if (!label) { - sord_node_free(world->world, parent); - continue; - } - - LilvPluginClass* pclass = lilv_plugin_class_new( - world, parent, class_node, - (const char*)sord_node_get_string(label)); - if (pclass) { - zix_tree_insert((ZixTree*)world->plugin_classes, pclass, NULL); - } - - sord_node_free(world->world, label); - sord_node_free(world->world, parent); - } - sord_iter_free(classes); + /* FIXME: This loads all classes, not just lv2:Plugin subclasses. + However, if the host gets all the classes via + lilv_plugin_class_get_children starting with lv2:Plugin as the root (which + is e.g. how a host would build a menu), they won't be seen anyway... + */ + + SordIter* classes = sord_search( + world->model, NULL, world->uris.rdf_a, world->uris.rdfs_Class, NULL); + FOREACH_MATCH (classes) { + const SordNode* class_node = sord_iter_get_node(classes, SORD_SUBJECT); + + SordNode* parent = sord_get( + world->model, class_node, world->uris.rdfs_subClassOf, NULL, NULL); + if (!parent || sord_node_get_type(parent) != SORD_URI) { + continue; + } + + SordNode* label = + sord_get(world->model, class_node, world->uris.rdfs_label, NULL, NULL); + if (!label) { + sord_node_free(world->world, parent); + continue; + } + + LilvPluginClass* pclass = lilv_plugin_class_new( + world, parent, class_node, (const char*)sord_node_get_string(label)); + if (pclass) { + zix_tree_insert((ZixTree*)world->plugin_classes, pclass, NULL); + } + + sord_node_free(world->world, label); + sord_node_free(world->world, parent); + } + sord_iter_free(classes); } void lilv_world_load_all(LilvWorld* world) { - const char* lv2_path = world->opt.lv2_path; - if (!lv2_path) { - lv2_path = getenv("LV2_PATH"); - } - if (!lv2_path) { - lv2_path = LILV_DEFAULT_LV2_PATH; - } - - // Discover bundles and read all manifest files into model - lilv_world_load_path(world, lv2_path); - - LILV_FOREACH(plugins, p, world->plugins) { - const LilvPlugin* plugin = (const LilvPlugin*)lilv_collection_get( - (ZixTree*)world->plugins, p); - - // ?new dc:replaces plugin - if (sord_ask(world->model, - NULL, - world->uris.dc_replaces, - lilv_plugin_get_uri(plugin)->node, - NULL)) { - // TODO: Check if replacement is a known plugin? (expensive) - ((LilvPlugin*)plugin)->replaced = true; - } - } - - // Query out things to cache - lilv_world_load_specifications(world); - lilv_world_load_plugin_classes(world); + const char* lv2_path = world->opt.lv2_path; + if (!lv2_path) { + lv2_path = getenv("LV2_PATH"); + } + if (!lv2_path) { + lv2_path = LILV_DEFAULT_LV2_PATH; + } + + // Discover bundles and read all manifest files into model + lilv_world_load_path(world, lv2_path); + + LILV_FOREACH (plugins, p, world->plugins) { + const LilvPlugin* plugin = + (const LilvPlugin*)lilv_collection_get((ZixTree*)world->plugins, p); + + // ?new dc:replaces plugin + if (sord_ask(world->model, + NULL, + world->uris.dc_replaces, + lilv_plugin_get_uri(plugin)->node, + NULL)) { + // TODO: Check if replacement is a known plugin? (expensive) + ((LilvPlugin*)plugin)->replaced = true; + } + } + + // Query out things to cache + lilv_world_load_specifications(world); + lilv_world_load_plugin_classes(world); } SerdStatus lilv_world_load_file(LilvWorld* world, SerdReader* reader, const LilvNode* uri) { - ZixTreeIter* iter = NULL; - if (!zix_tree_find((ZixTree*)world->loaded_files, uri, &iter)) { - return SERD_FAILURE; // File has already been loaded - } - - size_t uri_len = 0; - const uint8_t* const uri_str = sord_node_get_string_counted( - uri->node, &uri_len); - if (strncmp((const char*)uri_str, "file:", 5)) { - return SERD_FAILURE; // Not a local file - } - - if (strcmp((const char*)uri_str + uri_len - 4, ".ttl")) { - return SERD_FAILURE; // Not a Turtle file - } - - serd_reader_add_blank_prefix(reader, lilv_world_blank_node_prefix(world)); - const SerdStatus st = serd_reader_read_file(reader, uri_str); - if (st) { - LILV_ERRORF("Error loading file `%s'\n", lilv_node_as_string(uri)); - return st; - } - - zix_tree_insert((ZixTree*)world->loaded_files, - lilv_node_duplicate(uri), - NULL); - return SERD_SUCCESS; + ZixTreeIter* iter = NULL; + if (!zix_tree_find((ZixTree*)world->loaded_files, uri, &iter)) { + return SERD_FAILURE; // File has already been loaded + } + + size_t uri_len = 0; + const uint8_t* const uri_str = + sord_node_get_string_counted(uri->node, &uri_len); + if (strncmp((const char*)uri_str, "file:", 5)) { + return SERD_FAILURE; // Not a local file + } + + if (strcmp((const char*)uri_str + uri_len - 4, ".ttl")) { + return SERD_FAILURE; // Not a Turtle file + } + + serd_reader_add_blank_prefix(reader, lilv_world_blank_node_prefix(world)); + const SerdStatus st = serd_reader_read_file(reader, uri_str); + if (st) { + LILV_ERRORF("Error loading file `%s'\n", lilv_node_as_string(uri)); + return st; + } + + zix_tree_insert( + (ZixTree*)world->loaded_files, lilv_node_duplicate(uri), NULL); + return SERD_SUCCESS; } int -lilv_world_load_resource(LilvWorld* world, - const LilvNode* resource) +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", - sord_node_get_string(resource->node)); - return -1; - } - - SordModel* files = lilv_world_filter_model(world, - world->model, - resource->node, - world->uris.rdfs_seeAlso, - NULL, NULL); - - SordIter* f = sord_begin(files); - int n_read = 0; - FOREACH_MATCH(f) { - const SordNode* file = sord_iter_get_node(f, SORD_OBJECT); - const uint8_t* file_str = sord_node_get_string(file); - LilvNode* file_node = lilv_node_new_from_node(world, file); - if (sord_node_get_type(file) != SORD_URI) { - LILV_ERRORF("rdfs:seeAlso node `%s' is not a URI\n", file_str); - } else if (!lilv_world_load_graph(world, (SordNode*)file, file_node)) { - ++n_read; - } - lilv_node_free(file_node); - } - sord_iter_free(f); - - sord_free(files); - return n_read; + if (!lilv_node_is_uri(resource) && !lilv_node_is_blank(resource)) { + LILV_ERRORF("Node `%s' is not a resource\n", + sord_node_get_string(resource->node)); + return -1; + } + + SordModel* files = lilv_world_filter_model( + world, world->model, resource->node, world->uris.rdfs_seeAlso, NULL, NULL); + + SordIter* f = sord_begin(files); + int n_read = 0; + FOREACH_MATCH (f) { + const SordNode* file = sord_iter_get_node(f, SORD_OBJECT); + const uint8_t* file_str = sord_node_get_string(file); + LilvNode* file_node = lilv_node_new_from_node(world, file); + if (sord_node_get_type(file) != SORD_URI) { + LILV_ERRORF("rdfs:seeAlso node `%s' is not a URI\n", file_str); + } else if (!lilv_world_load_graph(world, (SordNode*)file, file_node)) { + ++n_read; + } + lilv_node_free(file_node); + } + sord_iter_free(f); + + sord_free(files); + return n_read; } int -lilv_world_unload_resource(LilvWorld* world, - const LilvNode* resource) +lilv_world_unload_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", - sord_node_get_string(resource->node)); - return -1; - } - - SordModel* files = lilv_world_filter_model(world, - world->model, - resource->node, - world->uris.rdfs_seeAlso, - NULL, NULL); - - SordIter* f = sord_begin(files); - int n_dropped = 0; - FOREACH_MATCH(f) { - const SordNode* file = sord_iter_get_node(f, SORD_OBJECT); - LilvNode* file_node = lilv_node_new_from_node(world, file); - if (sord_node_get_type(file) != SORD_URI) { - LILV_ERRORF("rdfs:seeAlso node `%s' is not a URI\n", - sord_node_get_string(file)); - } else if (!lilv_world_drop_graph(world, file_node->node)) { - lilv_world_unload_file(world, file_node); - ++n_dropped; - } - lilv_node_free(file_node); - } - sord_iter_free(f); - - sord_free(files); - return n_dropped; + if (!lilv_node_is_uri(resource) && !lilv_node_is_blank(resource)) { + LILV_ERRORF("Node `%s' is not a resource\n", + sord_node_get_string(resource->node)); + return -1; + } + + SordModel* files = lilv_world_filter_model( + world, world->model, resource->node, world->uris.rdfs_seeAlso, NULL, NULL); + + SordIter* f = sord_begin(files); + int n_dropped = 0; + FOREACH_MATCH (f) { + const SordNode* file = sord_iter_get_node(f, SORD_OBJECT); + LilvNode* file_node = lilv_node_new_from_node(world, file); + if (sord_node_get_type(file) != SORD_URI) { + LILV_ERRORF("rdfs:seeAlso node `%s' is not a URI\n", + sord_node_get_string(file)); + } else if (!lilv_world_drop_graph(world, file_node->node)) { + lilv_world_unload_file(world, file_node); + ++n_dropped; + } + lilv_node_free(file_node); + } + sord_iter_free(f); + + sord_free(files); + return n_dropped; } const LilvPluginClass* lilv_world_get_plugin_class(const LilvWorld* world) { - return world->lv2_plugin_class; + return world->lv2_plugin_class; } const LilvPluginClasses* lilv_world_get_plugin_classes(const LilvWorld* world) { - return world->plugin_classes; + return world->plugin_classes; } const LilvPlugins* lilv_world_get_all_plugins(const LilvWorld* world) { - return world->plugins; + return world->plugins; } LilvNode* lilv_world_get_symbol(LilvWorld* world, const LilvNode* subject) { - // Check for explicitly given symbol - SordNode* snode = sord_get( - world->model, subject->node, world->uris.lv2_symbol, NULL, NULL); - - if (snode) { - LilvNode* ret = lilv_node_new_from_node(world, snode); - sord_node_free(world->world, snode); - return ret; - } - - if (!lilv_node_is_uri(subject)) { - return NULL; - } - - // Find rightmost segment of URI - SerdURI uri; - serd_uri_parse((const uint8_t*)lilv_node_as_uri(subject), &uri); - const char* str = "_"; - if (uri.fragment.buf) { - str = (const char*)uri.fragment.buf + 1; - } else if (uri.query.buf) { - str = (const char*)uri.query.buf; - } else if (uri.path.buf) { - const char* last_slash = strrchr((const char*)uri.path.buf, '/'); - str = last_slash ? (last_slash + 1) : (const char*)uri.path.buf; - } - - // Replace invalid characters - const size_t len = strlen(str); - char* const sym = (char*)calloc(1, len + 1); - for (size_t i = 0; i < len; ++i) { - const char c = str[i]; - if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || - (c == '_') || (i > 0 && c >= '0' && c <= '9'))) { - sym[i] = '_'; - } else { - sym[i] = str[i]; - } - } - - LilvNode* ret = lilv_new_string(world, sym); - free(sym); - return ret; + // Check for explicitly given symbol + SordNode* snode = + sord_get(world->model, subject->node, world->uris.lv2_symbol, NULL, NULL); + + if (snode) { + LilvNode* ret = lilv_node_new_from_node(world, snode); + sord_node_free(world->world, snode); + return ret; + } + + if (!lilv_node_is_uri(subject)) { + return NULL; + } + + // Find rightmost segment of URI + SerdURI uri; + serd_uri_parse((const uint8_t*)lilv_node_as_uri(subject), &uri); + const char* str = "_"; + if (uri.fragment.buf) { + str = (const char*)uri.fragment.buf + 1; + } else if (uri.query.buf) { + str = (const char*)uri.query.buf; + } else if (uri.path.buf) { + const char* last_slash = strrchr((const char*)uri.path.buf, '/'); + str = last_slash ? (last_slash + 1) : (const char*)uri.path.buf; + } + + // Replace invalid characters + const size_t len = strlen(str); + char* const sym = (char*)calloc(1, len + 1); + for (size_t i = 0; i < len; ++i) { + const char c = str[i]; + if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c == '_') || + (i > 0 && c >= '0' && c <= '9'))) { + sym[i] = '_'; + } else { + sym[i] = str[i]; + } + } + + LilvNode* ret = lilv_new_string(world, sym); + free(sym); + return ret; } |