diff options
author | David Robillard <d@drobilla.net> | 2014-07-15 19:48:59 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2014-07-15 19:48:59 +0000 |
commit | 45f02a1390bbea3f7acbef5fdb4807a9f9331f3d (patch) | |
tree | c0a04698cdc1d392b5671ebe3c20d302acae61bf | |
parent | c067725cf5c187bca3c7b9a41c8b90a8ce50d95d (diff) | |
download | lilv-45f02a1390bbea3f7acbef5fdb4807a9f9331f3d.tar.gz lilv-45f02a1390bbea3f7acbef5fdb4807a9f9331f3d.tar.bz2 lilv-45f02a1390bbea3f7acbef5fdb4807a9f9331f3d.zip |
Add lilv_world_unload_bundle() and lilv_world_unload_resource().
git-svn-id: http://svn.drobilla.net/lad/trunk/lilv@5413 a436a847-0d15-0410-975c-d299462d15a1
-rw-r--r-- | NEWS | 5 | ||||
-rw-r--r-- | lilv/lilv.h | 26 | ||||
-rw-r--r-- | src/state.c | 8 | ||||
-rw-r--r-- | src/world.c | 126 | ||||
-rw-r--r-- | test/lilv_test.c | 16 | ||||
-rw-r--r-- | wscript | 2 |
6 files changed, 155 insertions, 28 deletions
@@ -1,4 +1,4 @@ -lilv (0.19.0) unstable; +lilv (0.19.2) unstable; * Don't load files multiple times if they are listed as rdfs:seeAlso for several plugins @@ -12,10 +12,11 @@ lilv (0.19.0) unstable; (thanks Filipe Coelho) * Improved/working lv2_apply.py to apply plugin to a .wav (thanks Joe Button) + * Add lilv_world_unload_bundle() and lilv_world_unload_resource() * Fix several minor memory leaks * Improve test coverage - -- David Robillard <d@drobilla.net> Sat, 12 Jul 2014 22:42:56 -0400 + -- David Robillard <d@drobilla.net> Tue, 15 Jul 2014 15:14:36 -0400 lilv (0.18.0) stable; diff --git a/lilv/lilv.h b/lilv/lilv.h index 8c60132..7de90d4 100644 --- a/lilv/lilv.h +++ b/lilv/lilv.h @@ -608,6 +608,18 @@ lilv_world_load_bundle(LilvWorld* world, LilvNode* bundle_uri); /** + Unload a specific bundle. + + This unloads statements loaded by lilv_world_load_bundle(). Note that this + is not necessarily all information loaded from the bundle. If any resources + have been separately loaded with liv_world_load_resource(), they must be + separately unloaded with lilv_world_unload_resource(). +*/ +LILV_API +int +lilv_world_unload_bundle(LilvWorld* world, LilvNode* bundle_uri); + +/** Load all the data associated with the given @c resource. @param resource Must be a subject (i.e. a URI or a blank node). @return The number of files parsed, or -1 on error @@ -621,6 +633,18 @@ lilv_world_load_resource(LilvWorld* world, const LilvNode* resource); /** + Unload all the data associated with the given @c resource. + @param resource Must be a subject (i.e. a URI or a blank node). + + This unloads all data loaded by a previous call to + lilv_world_load_resource() with the given @c resource. +*/ +LILV_API +int +lilv_world_unload_resource(LilvWorld* world, + const LilvNode* resource); + +/** Get the parent of all other plugin classes, lv2:Plugin. */ LILV_API @@ -1236,7 +1260,7 @@ lilv_port_get_scale_points(const LilvPlugin* plugin, This function can be used to load the default state of a plugin by passing the plugin URI as the @p subject parameter. @param subject The subject of the state description (e.g. a preset URI). - @return A new LilvState which must be freed with lilv_state_free(). + @return A new LilvState which must be freed with lilv_state_free(), or NULL. */ LILV_API LilvState* diff --git a/src/state.c b/src/state.c index 79b55ec..0a775c9 100644 --- a/src/state.c +++ b/src/state.c @@ -1,5 +1,5 @@ /* - Copyright 2007-2012 David Robillard <http://drobilla.net> + Copyright 2007-2014 David Robillard <http://drobilla.net> Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above @@ -439,6 +439,12 @@ new_state_from_model(LilvWorld* world, const SordNode* node, const char* dir) { + // Check that we know at least something about this state subject + if (!sord_ask(model, node, 0, 0, 0)) { + return NULL; + } + + // Allocate state LilvState* const state = (LilvState*)malloc(sizeof(LilvState)); memset(state, '\0', sizeof(LilvState)); state->dir = lilv_strdup(dir); diff --git a/src/world.c b/src/world.c index 228db8a..48bf401 100644 --- a/src/world.c +++ b/src/world.c @@ -1,5 +1,5 @@ /* - Copyright 2007-2011 David Robillard <http://drobilla.net> + Copyright 2007-2014 David Robillard <http://drobilla.net> Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above @@ -362,7 +362,7 @@ lilv_world_add_spec(LilvWorld* world, static void lilv_world_add_plugin(LilvWorld* world, const SordNode* plugin_node, - SerdNode* manifest_uri, + const LilvNode* manifest_uri, void* dynmanifest, const SordNode* bundle_node) { @@ -385,7 +385,7 @@ lilv_world_add_plugin(LilvWorld* world, // Add manifest as plugin data file (as if it were rdfs:seeAlso) zix_tree_insert((ZixTree*)plugin->data_uris, - lilv_new_uri(world, (const char*)manifest_uri->buf), + lilv_node_duplicate(manifest_uri), NULL); #ifdef LILV_DYN_MANIFEST @@ -431,9 +431,9 @@ lilv_world_load_graph(LilvWorld* world, SordNode* graph, const LilvNode* uri) } static void -lilv_world_load_dyn_manifest(LilvWorld* world, - SordNode* bundle_node, - SerdNode manifest_uri) +lilv_world_load_dyn_manifest(LilvWorld* world, + SordNode* bundle_node, + const LilvNode* manifest) { #ifdef LILV_DYN_MANIFEST if (!world->opt.dyn_manifest) { @@ -542,9 +542,8 @@ lilv_world_load_dyn_manifest(LilvWorld* world, world->uris.lv2_Plugin, dmanifest); FOREACH_MATCH(plug_results) { - const SordNode* plugin_node = sord_iter_get_node(plug_results, SORD_SUBJECT); - lilv_world_add_plugin(world, plugin_node, - &manifest_uri, desc, bundle_node); + const SordNode* plug = sord_iter_get_node(plug_results, SORD_SUBJECT); + lilv_world_add_plugin(world, plug, manifest, desc, bundle_node); } sord_iter_free(plug_results); @@ -554,6 +553,18 @@ lilv_world_load_dyn_manifest(LilvWorld* world, #endif // LILV_DYN_MANIFEST } +static +LilvNode* +lilv_world_get_manifest_uri(LilvWorld* world, LilvNode* bundle_uri) +{ + SerdNode manifest_uri = lilv_new_uri_relative_to_base( + (const uint8_t*)"manifest.ttl", + (const uint8_t*)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; +} + LILV_API void lilv_world_load_bundle(LilvWorld* world, LilvNode* bundle_uri) @@ -564,17 +575,14 @@ lilv_world_load_bundle(LilvWorld* world, LilvNode* bundle_uri) return; } - SordNode* bundle_node = bundle_uri->node; - SerdNode manifest_uri = lilv_new_uri_relative_to_base( - (const uint8_t*)"manifest.ttl", - (const uint8_t*)sord_node_get_string(bundle_node)); - LilvNode* manifest = lilv_new_uri(world, (const char*)manifest_uri.buf); + 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); - lilv_node_free(manifest); if (st > SERD_FAILURE) { - LILV_ERRORF("Error reading %s\n", manifest_uri.buf); + LILV_ERRORF("Error reading %s\n", lilv_node_as_string(manifest)); + lilv_node_free(manifest); return; } @@ -586,13 +594,12 @@ lilv_world_load_bundle(LilvWorld* world, LilvNode* bundle_uri) world->uris.lv2_Plugin, bundle_node); FOREACH_MATCH(plug_results) { - const SordNode* plugin_node = sord_iter_get_node(plug_results, SORD_SUBJECT); - lilv_world_add_plugin(world, plugin_node, - &manifest_uri, NULL, bundle_node); + 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_uri); + lilv_world_load_dyn_manifest(world, bundle_node, manifest); // ?specification a lv2:Specification SordIter* spec_results = sord_search( @@ -607,7 +614,51 @@ lilv_world_load_bundle(LilvWorld* world, LilvNode* bundle_uri) } sord_iter_free(spec_results); - serd_node_free(&manifest_uri); + lilv_node_free(manifest); +} + +static int +lilv_world_drop_graph(LilvWorld* world, LilvNode* graph) +{ + SordIter* i = sord_search(world->model, NULL, NULL, NULL, graph->node); + + while (!sord_iter_end(i)) { + // Get quad and increment iter so sord_remove doesn't invalidate it + SordQuad quad; + sord_iter_get(i, quad); + sord_iter_next(i); + + // Remove quad (nodes may now be deleted, quad is invalid) + sord_remove(world->model, quad); + } + 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, LilvNode* file) +{ + ZixTreeIter* iter; + if (!zix_tree_find((ZixTree*)world->loaded_files, file, &iter)) { + zix_tree_remove(world->loaded_files, iter); + return 0; + } + return 1; +} + +LILV_API +int +lilv_world_unload_bundle(LilvWorld* world, LilvNode* bundle_uri) +{ + // Remove loaded_files entry for manifest.ttl + LilvNode* manifest = lilv_world_get_manifest_uri(world, bundle_uri); + lilv_world_unload_file(world, manifest); + lilv_node_free(manifest); + + // Drop everything in bundle graph + return lilv_world_drop_graph(world, bundle_uri); } static void @@ -824,6 +875,39 @@ lilv_world_load_resource(LilvWorld* world, } LILV_API +int +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; + } + + int n_dropped = 0; + SordIter* files = sord_search(world->model, + resource->node, + world->uris.rdfs_seeAlso, + NULL, NULL); + FOREACH_MATCH(files) { + const SordNode* file = sord_iter_get_node(files, 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_drop_graph(world, file_node)) { + lilv_world_unload_file(world, file_node); + ++n_dropped; + } + lilv_node_free(file_node); + } + sord_iter_free(files); + + return n_dropped; +} + +LILV_API const LilvPluginClass* lilv_world_get_plugin_class(const LilvWorld* world) { diff --git a/test/lilv_test.c b/test/lilv_test.c index ea12013..52d4113 100644 --- a/test/lilv_test.c +++ b/test/lilv_test.c @@ -969,10 +969,9 @@ test_prototype(void) { if (!start_bundle(MANIFEST_PREFIXES ":prot a lv2:PluginBase ; rdfs:seeAlso <plugin.ttl> .\n" - ":plug a lv2:Plugin ; lv2:binary <foo" SHLIB_EXT "> ; lv2:prototype :prot .\n", + ":plug a lv2:Plugin ; lv2:binary <inst" SHLIB_EXT "> ; lv2:prototype :prot .\n", BUNDLE_PREFIXES ":prot a lv2:Plugin ; a lv2:CompressorPlugin ; " - PLUGIN_NAME("Test plugin with project") " ; " LICENSE_GPL " ; " "lv2:project [ " " doap:name \"Fake project\" ;" @@ -999,10 +998,15 @@ test_prototype(void) const LilvPlugin* plug = lilv_plugins_get_by_uri(plugins, plugin_uri_value); TEST_ASSERT(plug); + // Test non-inherited property LilvNode* name = lilv_plugin_get_name(plug); TEST_ASSERT(!strcmp(lilv_node_as_string(name), "Instance")); lilv_node_free(name); + // Test inherited property + const LilvNode* binary = lilv_plugin_get_library_uri(plug); + TEST_ASSERT(strstr(lilv_node_as_string(binary), "inst" SHLIB_EXT)); + cleanup_uris(); return 1; } @@ -1608,6 +1612,14 @@ test_state(void) LilvState* state6 = lilv_state_new_from_world(world, &map, test_state_node); TEST_ASSERT(lilv_state_equals(state, state6)); // Round trip accuracy + + lilv_world_unload_resource(world, test_state_node); + lilv_world_unload_bundle(world, test_state_bundle); + + LilvState* state6_2 = lilv_state_new_from_world(world, &map, test_state_node); + TEST_ASSERT(!state6_2); // No longer present + lilv_state_free(state6_2); + lilv_node_free(test_state_bundle); lilv_node_free(test_state_node); @@ -12,7 +12,7 @@ import waflib.Logs as Logs # major increment <=> incompatible changes # minor increment <=> compatible changes (additions) # micro increment <=> no interface changes -LILV_VERSION = '0.19.0' +LILV_VERSION = '0.19.2' LILV_MAJOR_VERSION = '0' # Mandatory waf variables |