From 03aa15ef37abb29d9d88d8b4912616247ceffa5d Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sun, 14 Jun 2009 22:28:29 +0000 Subject: Updated LV2 dynamic manifest extension. git-svn-id: http://svn.drobilla.net/lad/trunk/slv2@2105 a436a847-0d15-0410-975c-d299462d15a1 --- src/plugin.c | 52 ++++++++++++++++++++ src/slv2_internal.h | 16 +++++++ src/world.c | 136 ++++++++++++++++++++++++++++++++++------------------ 3 files changed, 158 insertions(+), 46 deletions(-) diff --git a/src/plugin.c b/src/plugin.c index 9564336..2aa9417 100644 --- a/src/plugin.c +++ b/src/plugin.c @@ -30,6 +30,9 @@ #include "slv2/query.h" #include "slv2/util.h" #include "slv2_internal.h" +#ifdef SLV2_DYN_MANIFEST +#include +#endif /* private @@ -43,6 +46,9 @@ slv2_plugin_new(SLV2World world, SLV2Value uri, librdf_uri* bundle_uri) plugin->plugin_uri = uri; plugin->bundle_uri = slv2_value_new_librdf_uri(world, bundle_uri); plugin->binary_uri = NULL; +#ifdef SLV2_DYN_MANIFEST + plugin->dynman_uri = NULL; +#endif plugin->plugin_class = NULL; plugin->data_uris = slv2_values_new(); plugin->ports = NULL; @@ -50,6 +56,10 @@ slv2_plugin_new(SLV2World world, SLV2Value uri, librdf_uri* bundle_uri) plugin->rdf = NULL; plugin->num_ports = 0; + /*printf("PLUGIN %s DATA URIs: %p\n", + slv2_value_as_string(plugin->plugin_uri), + (void*)plugin->data_uris);*/ + return plugin; } @@ -67,6 +77,11 @@ slv2_plugin_free(SLV2Plugin p) slv2_value_free(p->binary_uri); p->binary_uri = NULL; +#ifdef SLV2_DYN_MANIFEST + slv2_value_free(p->dynman_uri); + p->dynman_uri = NULL; +#endif + if (p->ports) { for (uint32_t i = 0; i < p->num_ports; ++i) slv2_port_free(p->ports[i]); @@ -205,6 +220,43 @@ slv2_plugin_load(SLV2Plugin p) librdf_uri* data_uri = slv2_value_as_librdf_uri(data_uri_val); librdf_parser_parse_into_model(p->world->parser, data_uri, NULL, p->rdf); } + +#ifdef SLV2_DYN_MANIFEST + // Load and parse dynamic manifest data, if this is a library + if (p->dynman_uri) { + const char* lib_path = slv2_uri_to_path(slv2_value_as_string(p->dynman_uri)); + void* lib = dlopen(lib_path, RTLD_LAZY); + if (!lib) { + SLV2_WARNF("Unable to open dynamic manifest %s\n", slv2_value_as_string(p->dynman_uri)); + return; + } + + typedef int (*OpenFunc)(LV2_Dyn_Manifest_Handle*, const LV2_Dyn_Manifest_Feature *const *); + OpenFunc open_func = (OpenFunc)dlsym(lib, "lv2_dyn_manifest_open"); + LV2_Dyn_Manifest_Handle handle = NULL; + if (open_func) + open_func(&handle, &dman_features); + + typedef int (*GetDataFunc)(LV2_Dyn_Manifest_Handle handle, + FILE* fp, + const char* uri); + GetDataFunc get_data_func = (GetDataFunc)dlsym(lib, "lv2_dyn_manifest_get_data"); + if (get_data_func) { + FILE* fd = tmpfile(); + get_data_func(handle, fd, slv2_value_as_string(p->plugin_uri)); + rewind(fd); + librdf_parser_parse_file_handle_into_model(p->world->parser, + fd, 0, slv2_value_as_librdf_uri(p->plugin_uri), p->rdf); + fclose(fd); + } + + typedef int (*CloseFunc)(LV2_Dyn_Manifest_Handle); + CloseFunc close_func = (CloseFunc)dlsym(lib, "lv2_dyn_manifest_close"); + if (close_func) + close_func(handle); + } +#endif + assert(p->rdf); } diff --git a/src/slv2_internal.h b/src/slv2_internal.h index 20fe619..1b2c785 100644 --- a/src/slv2_internal.h +++ b/src/slv2_internal.h @@ -16,6 +16,8 @@ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include "slv2-config.h" + #ifndef __SLV2_INTERNAL_H__ #define __SLV2_INTERNAL_H__ @@ -30,7 +32,12 @@ extern "C" { #include #include "slv2/types.h" #include "slv2/lv2_ui.h" +#ifdef SLV2_DYN_MANIFEST +#include "lv2_dyn_manifest.h" +#endif +#define SLV2_NS_RDFS (const unsigned char*)"http://www.w3.org/2000/01/rdf-schema#" +#define SLV2_NS_SLV2 (const unsigned char*)"http://drobilla.net/ns/slv2#" /* ********* PORT ********* */ @@ -59,6 +66,9 @@ struct _SLV2Plugin { SLV2Value plugin_uri; SLV2Value bundle_uri; ///< Bundle directory plugin was loaded from SLV2Value binary_uri; ///< lv2:binary +//#ifdef SLV2_DYN_MANIFEST + SLV2Value dynman_uri; ///< dynamic manifest binary +//#endif SLV2PluginClass plugin_class; raptor_sequence* data_uris; ///< rdfs::seeAlso SLV2Port* ports; @@ -244,6 +254,12 @@ struct _SLV2Results { char* slv2_strjoin(const char* first, ...); char* slv2_get_lang(); + +/* ********* Dynamic Manifest ********* */ +#ifdef SLV2_DYN_MANIFEST +static const LV2_Dyn_Manifest_Feature* const dman_features = { NULL }; +#endif + #define SLV2_ERROR(str) fprintf(stderr, "ERROR: %s: " str, __func__) #define SLV2_ERRORF(fmt, ...) fprintf(stderr, "ERROR: %s: " fmt, __func__, __VA_ARGS__) diff --git a/src/world.c b/src/world.c index 2c0bc8d..b99ee35 100644 --- a/src/world.c +++ b/src/world.c @@ -24,14 +24,13 @@ #include #include #include -#include #include "slv2/types.h" #include "slv2/world.h" #include "slv2/slv2.h" #include "slv2/util.h" #include "slv2_internal.h" #ifdef SLV2_DYN_MANIFEST -#include "lv2_dyn_manifest.h" +#include #endif @@ -221,44 +220,76 @@ slv2_world_load_bundle(SLV2World world, SLV2Value bundle_uri) librdf_query* query = librdf_new_query(world->world, "sparql", NULL, query_str, NULL); librdf_query_results* query_results = librdf_query_execute(query, manifest_model); - while (!librdf_query_results_finished(query_results)) { - librdf_node* dynman_node = librdf_query_results_get_binding_value(query_results, 0); + for (; !librdf_query_results_finished(query_results); librdf_query_results_next(query_results)) { librdf_node* binary_node = librdf_query_results_get_binding_value(query_results, 1); - if (librdf_node_get_type(binary_node) == LIBRDF_NODE_TYPE_RESOURCE) { - const char* lib_path = slv2_uri_to_path( - (const char*)librdf_uri_as_string(librdf_node_get_uri(binary_node))); - - if (lib_path) { - void* lib = dlopen(lib_path, RTLD_NOW); - - // Open dynamic manifest - typedef int (*OpenFunc)(LV2_Dyn_Manifest_Handle*, - const LV2_Dyn_Manifest_Feature *const *); - OpenFunc open_func = (OpenFunc)dlsym(lib, "lv2_dyn_manifest_open"); - open_func(&handle, &features); - - // Get subjects (what would be in the manifest) - typedef int (*GetSubjectsFunc)(LV2_Dyn_Manifest_Handle, FILE*); - GetSubjectsFunc get_subjects_func = (GetSubjectsFunc)dlsym(lib, - "lv2_dyn_manifest_get_subjects"); - if (get_subjects_func) { - printf("DYNAMIC MANIFEST <%s> @ <%s> {\n", - librdf_uri_as_string(librdf_node_get_uri(dynman_node)), - librdf_uri_as_string(librdf_node_get_uri(binary_node))); - //FILE* dyn_manifest = tmpfile(); - FILE* dyn_manifest = fopen("/tmp/naspro.ttl", "w+"); - get_subjects_func(handle, dyn_manifest); - rewind(dyn_manifest); - librdf_parser_parse_file_handle_into_model(world->parser, - dyn_manifest, 0, manifest_uri, manifest_model); - fclose(dyn_manifest); - } - } + if (librdf_node_get_type(binary_node) != LIBRDF_NODE_TYPE_RESOURCE) + continue; - } + const unsigned char* lib_uri = librdf_uri_as_string(librdf_node_get_uri(binary_node)); + const char* lib_path = slv2_uri_to_path((const char*)lib_uri); + if (!lib_path) + continue; + + void* lib = dlopen(lib_path, RTLD_LAZY); + if (!lib) + continue; - librdf_query_results_next(query_results); + // Open dynamic manifest + typedef int (*OpenFunc)(LV2_Dyn_Manifest_Handle*, const LV2_Dyn_Manifest_Feature *const *); + OpenFunc open_func = (OpenFunc)dlsym(lib, "lv2_dyn_manifest_open"); + if (open_func) + open_func(&handle, &features); + + // Get subjects (the data that would be in manifest.ttl) + typedef int (*GetSubjectsFunc)(LV2_Dyn_Manifest_Handle, FILE*); + GetSubjectsFunc get_subjects_func = (GetSubjectsFunc)dlsym(lib, + "lv2_dyn_manifest_get_subjects"); + if (!get_subjects_func) + continue; + + librdf_storage* dyn_manifest_storage = slv2_world_new_storage(world); + librdf_model* dyn_manifest_model = librdf_new_model(world->world, + dyn_manifest_storage, NULL); + + FILE* fd = tmpfile(); + get_subjects_func(handle, fd); + rewind(fd); + librdf_parser_parse_file_handle_into_model(world->parser, + fd, 0, librdf_node_get_uri(binary_node), dyn_manifest_model); + fclose(fd); + + // Query plugins from dynamic manifest + librdf_query* dyn_query = librdf_new_query(world->world, "sparql", NULL, + (const unsigned char*) + "PREFIX : \n" + "PREFIX dynman: \n" + "SELECT DISTINCT ?plugin WHERE {\n" + " ?plugin a :Plugin .\n" + "}", NULL); + + // Add ?plugin rdfs:seeAlso ?binary to dynamic model + librdf_query_results* r = librdf_query_execute(dyn_query, dyn_manifest_model); + for (; !librdf_query_results_finished(r); librdf_query_results_next(r)) { + librdf_node* plugin = librdf_query_results_get_binding_value(r, 0); + librdf_node* predicate = librdf_new_node_from_uri_string(world->world, + (const unsigned char*)(SLV2_NS_RDFS "seeAlso")); + librdf_node* object = librdf_new_node_from_node(binary_node); + librdf_model_add(dyn_manifest_model, plugin, predicate, object); + } + librdf_free_query_results(r); + librdf_free_query(dyn_query); + + /*printf("*************************************************\n"); + librdf_model_print(dyn_manifest_model, stdout); + printf("*************************************************\n");*/ + + // Merge dynamic model into main manifest model + librdf_stream* dyn_manifest_stream = librdf_model_as_stream(dyn_manifest_model); + librdf_model_add_statements(manifest_model, dyn_manifest_stream); + librdf_free_stream(dyn_manifest_stream); + librdf_free_model(dyn_manifest_model); + librdf_free_storage(dyn_manifest_storage); } librdf_free_query_results(query_results); librdf_free_query(query); @@ -278,16 +309,15 @@ slv2_world_load_bundle(SLV2World world, SLV2Value bundle_uri) /* Add ?plugin rdfs:seeAlso */ librdf_node* subject = plugin_node; librdf_node* predicate = librdf_new_node_from_uri_string(world->world, - (unsigned char*)"http://www.w3.org/2000/01/rdf-schema#seeAlso"); + (const unsigned char*)(SLV2_NS_RDFS "seeAlso")); librdf_node* object = librdf_new_node_from_uri(world->world, manifest_uri); - librdf_model_add(world->model, subject, predicate, object); /* Add ?plugin slv2:bundleURI */ subject = librdf_new_node_from_node(plugin_node); predicate = librdf_new_node_from_uri_string(world->world, - (unsigned char*)"http://drobilla.net/ns/slv2#bundleURI"); + (const unsigned char*)(SLV2_NS_SLV2 "bundleURI")); object = librdf_new_node_from_uri(world->world, bundle_uri->val.uri_val); librdf_model_add(world->model, subject, predicate, object); @@ -312,7 +342,7 @@ slv2_world_load_bundle(SLV2World world, SLV2Value bundle_uri) /* Add ?specification rdfs:seeAlso */ librdf_node* subject = spec_node; librdf_node* predicate = librdf_new_node_from_uri_string(world->world, - (unsigned char*)"http://www.w3.org/2000/01/rdf-schema#seeAlso"); + (const unsigned char*)(SLV2_NS_RDFS "seeAlso")); librdf_node* object = librdf_new_node_from_uri(world->world, manifest_uri); @@ -321,7 +351,7 @@ slv2_world_load_bundle(SLV2World world, SLV2Value bundle_uri) /* Add ?specification slv2:bundleURI */ subject = librdf_new_node_from_node(spec_node); predicate = librdf_new_node_from_uri_string(world->world, - (unsigned char*)"http://drobilla.net/ns/slv2#bundleURI"); + (const unsigned char*)(SLV2_NS_SLV2 "bundleURI")); object = librdf_new_node_from_uri(world->world, bundle_uri->val.uri_val); librdf_model_add(world->model, subject, predicate, object); @@ -591,8 +621,11 @@ slv2_world_load_all(SLV2World world) "PREFIX : \n" "PREFIX rdfs: \n" "PREFIX slv2: \n" - "SELECT DISTINCT ?plugin ?data ?bundle\n" - "WHERE { ?plugin a :Plugin; slv2:bundleURI ?bundle; rdfs:seeAlso ?data }\n"; + "SELECT DISTINCT ?plugin ?data ?bundle WHERE {\n" + " ?plugin a :Plugin ;\n" + " slv2:bundleURI ?bundle ;\n" + " rdfs:seeAlso ?data .\n" + "}\n"; librdf_query* q = librdf_new_query(world->world, "sparql", NULL, query_string, NULL); @@ -658,9 +691,20 @@ slv2_world_load_all(SLV2World world) plugin->world = world; - // FIXME: check for duplicates - raptor_sequence_push(plugin->data_uris, - slv2_value_new_librdf_uri(plugin->world, data_uri)); +#ifdef SLV2_DYN_MANIFEST + const char* const data_uri_str = (const char*)librdf_uri_as_string(data_uri); + void* lib = dlopen(slv2_uri_to_path(data_uri_str), RTLD_LAZY); + if (lib) { + plugin->dynman_uri = slv2_value_new_librdf_uri(world, data_uri); + librdf_query_results_next(results); + } else +#endif + if (data_uri) { + assert(plugin->data_uris); + // FIXME: check for duplicates + raptor_sequence_push(plugin->data_uris, + slv2_value_new_librdf_uri(plugin->world, data_uri)); + } } librdf_free_node(plugin_node); -- cgit v1.2.1