From 005954c907e140698aefa04d57c701e0327602f5 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Fri, 9 Dec 2011 23:40:21 +0000 Subject: Only load dynmanifests once per bundle, not once per plugin (fix #669). git-svn-id: http://svn.drobilla.net/lad/trunk/lilv@3845 a436a847-0d15-0410-975c-d299462d15a1 --- ChangeLog | 1 + src/lilv_internal.h | 15 +++++++++++++-- src/plugin.c | 50 +++++++++++++++++++++----------------------------- src/world.c | 26 +++++++++++++++++--------- 4 files changed, 52 insertions(+), 40 deletions(-) diff --git a/ChangeLog b/ChangeLog index 911d74c..ff4eabd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -8,6 +8,7 @@ lilv (UNRELEASED) unstable; urgency=low "http://purl.org/dc/terms/replaces" * Fix compilation on BSD * Fix crash in wordexp when LV2_PATH is corrupt + * Only load dynmanifest libraries once per bundle, not once per plugin -- David Robillard (UNRELEASED) diff --git a/src/lilv_internal.h b/src/lilv_internal.h index 155cec8..c53eacb 100644 --- a/src/lilv_internal.h +++ b/src/lilv_internal.h @@ -83,12 +83,23 @@ struct LilvHeader { LilvNode* uri; }; +#ifdef LILV_DYN_MANIFEST +typedef struct { + LilvNode* uri; + void* lib; + LV2_Dyn_Manifest_Handle handle; + uint32_t refs; +} LilvDynManifest; +#endif + struct LilvPluginImpl { LilvWorld* world; LilvNode* plugin_uri; LilvNode* bundle_uri; ///< Bundle plugin was loaded from LilvNode* binary_uri; ///< lv2:binary - LilvNode* dynman_uri; ///< dynamic manifest binary +#ifdef LILV_DYN_MANIFEST + LilvDynManifest* dynmanifest; +#endif const LilvPluginClass* plugin_class; LilvNodes* data_uris; ///< rdfs::seeAlso LilvPort** ports; @@ -176,7 +187,7 @@ struct LilvScalePointImpl { }; struct LilvUIImpl { - LilvWorld* world; + LilvWorld* world; LilvNode* uri; LilvNode* bundle_uri; LilvNode* binary_uri; diff --git a/src/plugin.c b/src/plugin.c index 88732d1..f4f1315 100644 --- a/src/plugin.c +++ b/src/plugin.c @@ -39,7 +39,7 @@ lilv_plugin_new(LilvWorld* world, LilvNode* uri, LilvNode* bundle_uri) plugin->bundle_uri = bundle_uri; plugin->binary_uri = NULL; #ifdef LILV_DYN_MANIFEST - plugin->dynman_uri = NULL; + plugin->dynmanifest = NULL; #endif plugin->plugin_class = NULL; plugin->data_uris = lilv_nodes_new(); @@ -54,6 +54,21 @@ lilv_plugin_new(LilvWorld* world, LilvNode* uri, LilvNode* bundle_uri) void lilv_plugin_free(LilvPlugin* p) { +#ifdef LILV_DYN_MANIFEST + if (p->dynmanifest && --p->dynmanifest->refs == 0) { + typedef int (*CloseFunc)(LV2_Dyn_Manifest_Handle); + CloseFunc close_func = (CloseFunc)lilv_dlfunc(p->dynmanifest->lib, + "lv2_dyn_manifest_close"); + if (close_func) { + close_func(p->dynmanifest->handle); + } + + dlclose(p->dynmanifest->lib); + lilv_node_free(p->dynmanifest->uri); + free(p->dynmanifest); + } +#endif + lilv_node_free(p->plugin_uri); p->plugin_uri = NULL; @@ -63,11 +78,6 @@ lilv_plugin_free(LilvPlugin* p) lilv_node_free(p->binary_uri); p->binary_uri = NULL; -#ifdef LILV_DYN_MANIFEST - lilv_node_free(p->dynman_uri); - p->dynman_uri = NULL; -#endif - if (p->ports) { for (uint32_t i = 0; i < p->num_ports; ++i) { lilv_port_free(p, p->ports[i]); @@ -136,41 +146,23 @@ lilv_plugin_load(LilvPlugin* p) #ifdef LILV_DYN_MANIFEST typedef void* LV2_Dyn_Manifest_Handle; // Load and parse dynamic manifest data, if this is a library - if (p->dynman_uri) { - const char* lib_path = lilv_uri_to_path(lilv_node_as_string(p->dynman_uri)); - void* lib = dlopen(lib_path, RTLD_LAZY); - if (!lib) { - LILV_WARNF("Failed to open dynamic manifest %s\n", - lilv_node_as_string(p->dynman_uri)); - return; - } - - typedef int (*OpenFunc)(LV2_Dyn_Manifest_Handle*, const LV2_Feature *const *); - OpenFunc open_func = (OpenFunc)lilv_dlfunc(lib, "lv2_dyn_manifest_open"); - LV2_Dyn_Manifest_Handle handle = NULL; - if (open_func) - open_func(&handle, &dman_features); - + if (p->dynmanifest) { typedef int (*GetDataFunc)(LV2_Dyn_Manifest_Handle handle, FILE* fp, const char* uri); GetDataFunc get_data_func = (GetDataFunc)lilv_dlfunc( - lib, "lv2_dyn_manifest_get_data"); + p->dynmanifest->lib, "lv2_dyn_manifest_get_data"); if (get_data_func) { serd_env_set_base_uri( - env, sord_node_to_serd_node(p->dynman_uri->val.uri_val)); + env, sord_node_to_serd_node(p->dynmanifest->uri->val.uri_val)); FILE* fd = tmpfile(); - get_data_func(handle, fd, lilv_node_as_string(p->plugin_uri)); + get_data_func(p->dynmanifest->handle, fd, + lilv_node_as_string(p->plugin_uri)); rewind(fd); serd_reader_read_file_handle(reader, fd, (const uint8_t*)"(dyn-manifest)"); fclose(fd); } - - typedef int (*CloseFunc)(LV2_Dyn_Manifest_Handle); - CloseFunc close_func = (CloseFunc)lilv_dlfunc(lib, "lv2_dyn_manifest_close"); - if (close_func) - close_func(handle); } #endif serd_reader_free(reader); diff --git a/src/world.c b/src/world.c index e291c55..ba75ec8 100644 --- a/src/world.c +++ b/src/world.c @@ -328,11 +328,11 @@ lilv_world_add_spec(LilvWorld* world, } static void -lilv_world_add_plugin(LilvWorld* world, - const SordNode* plugin_node, - SerdNode* manifest_uri, - const SordNode* dyn_manifest_lib, - const SordNode* bundle_node) +lilv_world_add_plugin(LilvWorld* world, + const SordNode* plugin_node, + SerdNode* manifest_uri, + void* dynmanifest, + const SordNode* bundle_node) { LilvNode* plugin_uri = lilv_node_new_from_node(world, plugin_node); @@ -355,10 +355,13 @@ lilv_world_add_plugin(LilvWorld* world, lilv_new_uri(world, (const char*)manifest_uri->buf), NULL); +#ifdef LILV_DYN_MANIFEST // Set dynamic manifest library URI, if applicable - if (dyn_manifest_lib) { - plugin->dynman_uri = lilv_node_new_from_node(world, dyn_manifest_lib); + if (dynmanifest) { + plugin->dynmanifest = (LilvDynManifest*)dynmanifest; + ++((LilvDynManifest*)dynmanifest)->refs; } +#endif // Add all plugin data files (rdfs:seeAlso) SordIter* files = lilv_world_find_statements( @@ -456,6 +459,12 @@ lilv_world_load_dyn_manifest(LilvWorld* world, continue; } + LilvDynManifest* desc = malloc(sizeof(LilvDynManifest)); + desc->uri = lilv_node_new_from_node(world, dmanifest); + desc->lib = lib; + desc->handle = handle; + desc->refs = 0; + // Generate data file FILE* fd = tmpfile(); get_subjects_func(handle, fd); @@ -483,12 +492,11 @@ lilv_world_load_dyn_manifest(LilvWorld* world, FOREACH_MATCH(plug_results) { const SordNode* plugin_node = lilv_match_subject(plug_results); lilv_world_add_plugin(world, plugin_node, - &manifest_uri, binary, bundle_node); + &manifest_uri, desc, bundle_node); } lilv_match_end(plug_results); lilv_match_end(binaries); - dlclose(lib); } lilv_match_end(dmanifests); #endif // LILV_DYN_MANIFEST -- cgit v1.2.1