diff options
author | David Robillard <d@drobilla.net> | 2007-02-18 04:16:24 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2007-02-18 04:16:24 +0000 |
commit | a80e895b0b23d478807377360b85b4bb1d7073b7 (patch) | |
tree | e2ea19db66cd44bce0d84176c4c87a90d9b5d9e0 | |
parent | 07c3b4ce3ed385368147bd4f2e058f83d9064b0d (diff) | |
download | lilv-a80e895b0b23d478807377360b85b4bb1d7073b7.tar.gz lilv-a80e895b0b23d478807377360b85b4bb1d7073b7.tar.bz2 lilv-a80e895b0b23d478807377360b85b4bb1d7073b7.zip |
Implemented discovery of plugin extension bundles.
git-svn-id: http://svn.drobilla.net/lad/slv2@309 a436a847-0d15-0410-975c-d299462d15a1
-rw-r--r-- | slv2/Makefile.am | 3 | ||||
-rw-r--r-- | slv2/plugin.h | 37 | ||||
-rw-r--r-- | slv2/private_types.h | 23 | ||||
-rw-r--r-- | slv2/types.h | 21 | ||||
-rw-r--r-- | slv2/util.h (renamed from src/util.h) | 35 | ||||
-rw-r--r-- | src/Makefile.am | 3 | ||||
-rw-r--r-- | src/plugin.c | 66 | ||||
-rw-r--r-- | src/plugininstance.c | 16 | ||||
-rw-r--r-- | src/pluginlist.c | 148 | ||||
-rw-r--r-- | src/port.c | 10 | ||||
-rw-r--r-- | src/query.c | 33 | ||||
-rw-r--r-- | src/types.c | 54 | ||||
-rw-r--r-- | src/util.c | 23 | ||||
-rw-r--r-- | utils/lv2_inspect.c | 8 |
14 files changed, 308 insertions, 172 deletions
diff --git a/slv2/Makefile.am b/slv2/Makefile.am index 5fba079..d2153ef 100644 --- a/slv2/Makefile.am +++ b/slv2/Makefile.am @@ -10,4 +10,5 @@ slv2include_HEADERS = \ query.h \ port.h \ pluginlist.h \ - plugininstance.h + plugininstance.h \ + util.h diff --git a/slv2/plugin.h b/slv2/plugin.h index d646504..5555437 100644 --- a/slv2/plugin.h +++ b/slv2/plugin.h @@ -48,11 +48,11 @@ typedef const struct _Plugin SLV2Plugin; * and will not work with libslv2 (eg plugins missing required fields, or * having multiple values for mandatory single-valued fields, etc. * - * Note that normal hosts do not need to worry about this - libslv2 does not + * Note that normal hosts do NOT need to use this - slv2 does not * load invalid plugins into plugin lists. This is included for plugin * testing utilities, etc. * - * \return True if \a plugin is valid. + * \return true if \a plugin is valid. */ bool slv2_plugin_verify(const SLV2Plugin* plugin); @@ -87,44 +87,29 @@ const char* slv2_plugin_get_uri(const SLV2Plugin* plugin); -/** Get the URL of the RDF data file plugin information is located in. +/** Get the (resolvable) URIs of the RDF data files that define a plugin. * - * Only file: URL's are supported at this time. + * Note this always returns fully qualified URIs. If you want local + * filesystem paths, use slv2_uri_to_path. * * \return a complete URL eg. "file:///usr/foo/SomeBundle.lv2/someplug.ttl", * which is shared and must not be modified or free()'d. */ -const char* -slv2_plugin_get_data_url(const SLV2Plugin* plugin); +SLV2URIList +slv2_plugin_get_data_uris(const SLV2Plugin* plugin); -/** Get the local filesystem path of the RDF data file for \a plugin. +/** Get the (resolvable) URI of the shared library for \a plugin. * - * \return a valid path on the local filesystem - * eg. "/usr/foo/SomeBundle.lv2/someplug.ttl" which is shared and must not - * be free()'d; or NULL if URL is not a local filesystem path. - */ -const char* -slv2_plugin_get_data_path(const SLV2Plugin* plugin); - - -/** Get the URL of the shared library for \a plugin. + * Note this always returns a fully qualified URI. If you want a local + * filesystem path, use slv2_uri_to_path. * * \return a shared string which must not be modified or free()'d. */ const char* -slv2_plugin_get_library_url(const SLV2Plugin* plugin); +slv2_plugin_get_library_uri(const SLV2Plugin* plugin); -/** Get the local filesystem path of the shared library for \a plugin. - * - * \return a valid path on the local filesystem - * eg. "/usr/foo/SomeBundle.lv2/someplug.so" which is shared and must not - * be free()'d; or NULL if URL is not a local filesystem path. - */ -const char* -slv2_plugin_get_library_path(const SLV2Plugin* plugin); - /** Get the name of \a plugin. * diff --git a/slv2/private_types.h b/slv2/private_types.h index 590ecae..cfdcb9c 100644 --- a/slv2/private_types.h +++ b/slv2/private_types.h @@ -25,13 +25,17 @@ extern "C" { #include <stdbool.h> #include <stddef.h> +#include <raptor.h> #include <slv2/lv2.h> -/* If you're a user of SLV2, stop reading this file RIGHT NOW. +/* @file private_types.h + * + * If you're a user of SLV2, stop reading this RIGHT NOW :) * Unfortunately it needs to be exposed to allow inlining of some things that - * really need to be inlined, but these are opaque types. Don't even think - * about writing code that depends on any information here :) + * really need to be inlined, but these are opaque types. + * + * DO NOT WRITE CODE THAT DEPENDS ON DEFINITIONS IN THIS FILE */ @@ -41,10 +45,10 @@ extern "C" { * paths of relevant files, the actual data therein isn't loaded into memory. */ struct _Plugin { - char* plugin_uri; - char* bundle_url; // Bundle directory plugin was loaded from - char* data_url; // rdfs::seeAlso - char* lib_url; // lv2:binary + char* plugin_uri; + char* bundle_url; // Bundle directory plugin was loaded from + raptor_sequence* data_uris; // rdfs::seeAlso + char* lib_uri; // lv2:binary }; @@ -65,6 +69,11 @@ struct _PluginList { }; +typedef raptor_sequence* SLV2URIList; + +SLV2URIList slv2_uri_list_new(); + + #ifdef __cplusplus } #endif diff --git a/slv2/types.h b/slv2/types.h index 7e366ba..4fb8cf4 100644 --- a/slv2/types.h +++ b/slv2/types.h @@ -22,6 +22,7 @@ #include <stddef.h> #include <stdbool.h> #include <stdint.h> +#include <slv2/private_types.h> #ifdef __cplusplus extern "C" { @@ -72,9 +73,29 @@ typedef enum _PortClass { } SLV2PortClass; +/** Get the number of elements in a URI list. + */ +int +slv2_uri_list_size(const SLV2URIList list); + + +/** Get a URI from a URI list at the given index. + * + * @return the element at @index, or NULL if index is out of range. + */ +char* +slv2_uri_list_get_at(const SLV2URIList list, int index); + + +/** Return whether @list contains @uri. + */ +bool +slv2_uri_list_contains(const SLV2URIList list, const char* uri); + #ifdef __cplusplus } #endif + #endif /* __SLV2_TYPES_H__ */ @@ -16,15 +16,29 @@ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef __UTIL_H -#define __UTIL_H +#ifndef __SLV2_UTIL_H__ +#define __SLV2_UTIL_H__ #define _XOPEN_SOURCE 500 #include <string.h> - #include <stdarg.h> +#include <stddef.h> +#include <stdbool.h> +#include <stdint.h> #include <slv2/types.h> +#ifdef __cplusplus +extern "C" { +#endif + + +/** Convert a full URI (eg file://foo/bar/baz.ttl) to a local path (e.g. /foo/bar/baz.ttl). + * + * Return value is shared and must not be deleted by caller. + * @return @uri converted to a path, or NULL on failure (URI is not local). + */ +const char* slv2_uri_to_path(const char* uri); + /** Append \a suffix to \a *dst, reallocating \a dst as necessary. * @@ -32,7 +46,7 @@ * or NULL. */ void -strappend(char** dst, const char* suffix); +slv2_strappend(char** dst, const char* suffix); /** Join all arguments into one string. @@ -40,13 +54,20 @@ strappend(char** dst, const char* suffix); * Arguments are not modified, return value must be free()'d. */ char* -strjoin(const char* first, ...); +slv2_strjoin(const char* first, ...); + char* -vstrjoin(const char** first, va_list args_list); +slv2_vstrjoin(const char** first, va_list args_list); + const char* -url2path(const char* const url); +slv2_url2path(const char* const url); +#ifdef __cplusplus +} #endif + +#endif /* __SLV2_UTIL_H__ */ + diff --git a/src/Makefile.am b/src/Makefile.am index 4f81d9a..5ad71df 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -12,4 +12,5 @@ libslv2_la_SOURCES = \ pluginlist.c \ util.c \ plugininstance.c \ - library.c + library.c \ + types.c diff --git a/src/plugin.c b/src/plugin.c index 970b82f..30e737a 100644 --- a/src/plugin.c +++ b/src/plugin.c @@ -16,6 +16,8 @@ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ +#define _XOPEN_SOURCE 500 + #include <string.h> #include <stdlib.h> #include <assert.h> @@ -24,7 +26,7 @@ #include <slv2/plugin.h> #include <slv2/types.h> #include <slv2/query.h> -#include "util.h" +#include <slv2/util.h> SLV2Plugin* @@ -34,8 +36,11 @@ slv2_plugin_duplicate(const SLV2Plugin* p) struct _Plugin* result = malloc(sizeof(struct _Plugin)); result->plugin_uri = p->plugin_uri; result->bundle_url = p->bundle_url; - result->data_url = p->data_url; - result->lib_url = p->lib_url; + result->lib_uri = p->lib_uri; + + result->data_uris = slv2_uri_list_new(); + for (int i=0; i < slv2_uri_list_size(p->data_uris); ++i) + raptor_sequence_push(result->data_uris, strdup(slv2_uri_list_get_at(p->data_uris, i))); return result; } @@ -48,41 +53,19 @@ slv2_plugin_get_uri(const SLV2Plugin* p) } -const char* -slv2_plugin_get_data_url(const SLV2Plugin* p) -{ - assert(p); - return p->data_url; -} - - -const char* -slv2_plugin_get_data_path(const SLV2Plugin* p) -{ - assert(p); - if (!strncmp((char*)p->data_url, "file://", (size_t)7)) - return (p->data_url) + 7; - else - return NULL; -} - - -const char* -slv2_plugin_get_library_url(const SLV2Plugin* p) +SLV2URIList +slv2_plugin_get_data_uris(const SLV2Plugin* p) { assert(p); - return p->lib_url; + return p->data_uris; } const char* -slv2_plugin_get_library_path(const SLV2Plugin* p) +slv2_plugin_get_library_uri(const SLV2Plugin* p) { assert(p); - if (!strncmp((char*)p->lib_url, "file://", (size_t)7)) - return (p->lib_url) + 7; - else - return NULL; + return p->lib_uri; } @@ -136,9 +119,9 @@ slv2_plugin_get_value(const SLV2Plugin* p, char* header = slv2_query_header(p); char* lang_filter = slv2_query_lang_filter("?value"); - char* query_string = strjoin( + char* query_string = slv2_strjoin( header, - "SELECT DISTINCT ?value FROM data: WHERE { \n", + "SELECT DISTINCT ?value WHERE { \n", "plugin: ", property, " ?value . \n", ((lang_filter != NULL) ? lang_filter : ""), "}", 0); @@ -146,8 +129,8 @@ slv2_plugin_get_value(const SLV2Plugin* p, free(header); free(lang_filter);*/ - char* query = strjoin( - "SELECT DISTINCT ?value FROM data: WHERE {\n" + char* query = slv2_strjoin( + "SELECT DISTINCT ?value WHERE {\n" "plugin: ", predicate, " ?value .\n" "}\n", NULL); @@ -177,9 +160,8 @@ uint32_t slv2_plugin_get_num_ports(const SLV2Plugin* p) { const char* const query = - "SELECT DISTINCT ?value FROM data: WHERE {\n" - "plugin: lv2:port ?value .\n" - "}\n"; + "SELECT DISTINCT ?value\n" + "WHERE { plugin: lv2:port ?value }\n"; SLV2Value results = slv2_plugin_simple_query(p, query, "value"); @@ -195,7 +177,7 @@ bool slv2_plugin_has_latency(const SLV2Plugin* p) { const char* const query = - "SELECT DISTINCT ?port FROM data: WHERE {\n" + "SELECT DISTINCT ?port WHERE {\n" " plugin: lv2:port ?port .\n" " ?port lv2:portHint lv2:reportsLatency .\n" "}\n"; @@ -214,7 +196,7 @@ uint32_t slv2_plugin_get_latency_port(const SLV2Plugin* p) { const char* const query = - "SELECT DISTINCT ?value FROM data: WHERE {\n" + "SELECT DISTINCT ?value WHERE {\n" " plugin: lv2:port ?port .\n" " ?port lv2:portHint lv2:reportsLatency ;\n" " lv2:index ?index .\n" @@ -236,7 +218,7 @@ SLV2Value slv2_plugin_get_supported_features(const SLV2Plugin* p) { const char* const query = - "SELECT DISTINCT ?feature FROM data: WHERE {\n" + "SELECT DISTINCT ?feature WHERE {\n" " { plugin: lv2:optionalHostFeature ?feature }\n" " UNION\n" " { plugin: lv2:requiredHostFeature ?feature }\n" @@ -252,7 +234,7 @@ SLV2Value slv2_plugin_get_optional_features(const SLV2Plugin* p) { const char* const query = - "SELECT DISTINCT ?feature FROM data: WHERE {\n" + "SELECT DISTINCT ?feature WHERE {\n" " plugin: lv2:optionalHostFeature ?feature .\n" "}\n"; @@ -266,7 +248,7 @@ SLV2Value slv2_plugin_get_required_features(const SLV2Plugin* p) { const char* const query = - "SELECT DISTINCT ?feature FROM data: WHERE {\n" + "SELECT DISTINCT ?feature WHERE {\n" " plugin: lv2:requiredHostFeature ?feature .\n" "}\n"; diff --git a/src/plugininstance.c b/src/plugininstance.c index 2c178a8..ed8abc7 100644 --- a/src/plugininstance.c +++ b/src/plugininstance.c @@ -25,7 +25,7 @@ #include <slv2/types.h> #include <slv2/plugin.h> #include <slv2/plugininstance.h> -#include "util.h" +#include <slv2/util.h> SLV2Instance* @@ -41,14 +41,14 @@ slv2_plugin_instantiate(const SLV2Plugin* plugin, host_features[0] = NULL; } - const char* const lib_path = slv2_plugin_get_library_path(plugin); - if (!lib_path) + const char* const lib_uri = slv2_plugin_get_library_uri(plugin); + if (!lib_uri || slv2_uri_to_path(lib_uri) == NULL) return NULL; dlerror(); - void* lib = dlopen((char*)lib_path, RTLD_NOW); + void* lib = dlopen(slv2_uri_to_path(lib_uri), RTLD_NOW); if (!lib) { - fprintf(stderr, "Unable to open library %s (%s)\n", lib_path, dlerror()); + fprintf(stderr, "Unable to open library %s (%s)\n", lib_uri, dlerror()); return NULL; } @@ -56,20 +56,20 @@ slv2_plugin_instantiate(const SLV2Plugin* plugin, if (!df) { fprintf(stderr, "Could not find symbol 'lv2_descriptor', " - "%s is not a LV2 plugin.\n", lib_path); + "%s is not a LV2 plugin.\n", lib_uri); dlclose(lib); return NULL; } else { // Search for plugin by URI - const char* const bundle_path = url2path(plugin->bundle_url); + const char* const bundle_path = slv2_uri_to_path(plugin->bundle_url); for (uint32_t i=0; 1; ++i) { const LV2_Descriptor* ld = df(i); if (!ld) { fprintf(stderr, "Did not find plugin %s in %s\n", - plugin->plugin_uri, plugin->lib_url); + plugin->plugin_uri, plugin->lib_uri); dlclose(lib); break; // return NULL } else if (!strcmp(ld->URI, (char*)plugin->plugin_uri)) { diff --git a/src/pluginlist.c b/src/pluginlist.c index 3c8e409..d9bbe7b 100644 --- a/src/pluginlist.c +++ b/src/pluginlist.c @@ -28,9 +28,24 @@ #include <slv2/types.h> #include <slv2/plugin.h> #include <slv2/pluginlist.h> -#include "util.h" +#include <slv2/util.h> +/* not exposed */ +struct _Plugin* +slv2_plugin_new() +{ + struct _Plugin* result = malloc(sizeof(struct _Plugin)); + result->plugin_uri = NULL; + result->bundle_url = NULL; + result->lib_uri = NULL; + + result->data_uris = slv2_uri_list_new(); + + return result; +} + + struct _PluginList* slv2_list_new() { @@ -62,17 +77,24 @@ slv2_list_load_all(SLV2List list) } else { const char* const home = getenv("HOME"); const char* const suffix = "/.lv2:/usr/local/lib/lv2:usr/lib/lv2"; - slv2_path = strjoin(home, suffix, NULL); + slv2_path = slv2_strjoin(home, suffix, NULL); fprintf(stderr, "$LV2_PATH is unset. Using default path %s\n", slv2_path); - slv2_list_load_path(list, slv2_path); + + /* pass 1: find all plugins */ + slv2_list_load_path(list, slv2_path); + + /* pass 2: find all data files for plugins */ + slv2_list_load_path(list, slv2_path); free(slv2_path); } } -/* This is the parser for manifest.ttl */ +/* This is the parser for manifest.ttl + * This is called twice on each bundle in the discovery process, which is (much) less + * efficient than it could be.... */ void slv2_list_load_bundle(SLV2List list, const char* bundle_base_url) @@ -89,14 +111,11 @@ slv2_list_load_bundle(SLV2List list, raptor_uri *base_url = raptor_new_uri(manifest_url); rasqal_query *rq = rasqal_new_query("sparql", NULL); + /* Get all plugins explicitly mentioned in the manifest (discovery pass 1) */ char* query_string = - "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n" - "PREFIX : <http://lv2plug.in/ontology#> \n\n" - - "SELECT DISTINCT $plugin_uri $data_url $lib_url FROM <> WHERE { \n" - "$plugin_uri :binary $lib_url . \n" - "OPTIONAL { $plugin_uri rdfs:seeAlso $data_url } \n" - "} \n"; + "PREFIX : <http://lv2plug.in/ontology#>\n\n" + "SELECT DISTINCT ?plugin_uri FROM <>\n" + "WHERE { ?plugin_uri a :Plugin }\n"; //printf("%s\n\n", query_string); @@ -104,48 +123,80 @@ slv2_list_load_bundle(SLV2List list, results = rasqal_query_execute(rq); while (!rasqal_query_results_finished(results)) { - - // Create a new plugin - struct _Plugin* new_plugin = malloc(sizeof(struct _Plugin)); - new_plugin->bundle_url = strdup(bundle_base_url); - rasqal_literal* literal = NULL; - - literal = rasqal_query_results_get_binding_value_by_name(results, (const unsigned char*)"plugin_uri"); + rasqal_literal* literal = rasqal_query_results_get_binding_value(results, 0); assert(literal); - new_plugin->plugin_uri = strdup((const char*)rasqal_literal_as_string(literal)); - - literal = rasqal_query_results_get_binding_value_by_name(results, (const unsigned char*)"lib_url"); - assert(literal); - new_plugin->lib_url = strdup((const char*)rasqal_literal_as_string(literal)); - - literal = rasqal_query_results_get_binding_value_by_name(results, (const unsigned char*)"data_url"); - if (literal) - new_plugin->data_url = strdup((const char*)rasqal_literal_as_string(literal)); - else - new_plugin->data_url = strdup((const char*)manifest_url); - - /* Add the plugin if it's valid */ - if (new_plugin->lib_url && new_plugin->data_url && new_plugin->plugin_uri - && slv2_plugin_verify(new_plugin)) { - /* Yes, this is disgusting, but it doesn't seem there's a way to know - * how many matches there are before iterating over them */ + + if (!slv2_list_get_plugin_by_uri(list, (const char*)rasqal_literal_as_string(literal))) { + /* Create a new plugin */ + struct _Plugin* new_plugin = slv2_plugin_new(); + new_plugin->plugin_uri = strdup((const char*)rasqal_literal_as_string(literal)); + new_plugin->bundle_url = strdup(bundle_base_url); + raptor_sequence_push(new_plugin->data_uris, strdup((const char*)manifest_url)); + + /* And add it to the list + * Yes, this is disgusting, but it doesn't seem there's a way to know + * how many matches there are before iterating over them.. */ list->num_plugins++; list->plugins = realloc(list->plugins, list->num_plugins * sizeof(struct _Plugin*)); list->plugins[list->num_plugins-1] = new_plugin; + } + + rasqal_query_results_next(results); + } + + if (results) + rasqal_free_query_results(results); + + rasqal_free_query(rq); + + rq = rasqal_new_query("sparql", NULL); + + /* Get all data files linked to plugins (discovery pass 2) */ + query_string = + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>\n" + "PREFIX : <http://lv2plug.in/ontology#>\n\n" + "SELECT DISTINCT ?subject ?data_uri ?binary FROM <>\n" + "WHERE { ?subject rdfs:seeAlso ?data_uri\n" + "OPTIONAL { ?subject :binary ?binary } }\n"; + + //printf("%s\n\n", query_string); + + rasqal_query_prepare(rq, (unsigned char*)query_string, base_url); + results = rasqal_query_execute(rq); + + while (!rasqal_query_results_finished(results)) { + const char* subject = (const char*)rasqal_literal_as_string( + rasqal_query_results_get_binding_value(results, 0)); + + const char* data_uri = (const char*)rasqal_literal_as_string( + rasqal_query_results_get_binding_value(results, 1)); + + const char* binary = (const char*)rasqal_literal_as_string( + rasqal_query_results_get_binding_value(results, 2)); + + struct _Plugin* plugin = slv2_list_get_plugin_by_uri(list, subject); + + if (plugin && data_uri && !slv2_uri_list_contains(plugin->data_uris, data_uri)) + raptor_sequence_push(plugin->data_uris, strdup(data_uri)); + + if (plugin && binary && !plugin->lib_uri) + plugin->lib_uri = strdup(binary); + rasqal_query_results_next(results); + } - // FIXME: leaks? rasqal really doesn't handle missing files well.. - if (results) { + if (results) rasqal_free_query_results(results); - //rasqal_free_query(rq); // FIXME: crashes? leak? - raptor_free_uri(base_url); - } + + rasqal_free_query(rq); + + raptor_free_uri(base_url); free(manifest_url); } @@ -154,7 +205,7 @@ slv2_list_load_bundle(SLV2List list, * (Private helper function, not exposed in public API) */ void -add_plugins_from_dir(SLV2List list, const char* dir) +slv2_list_load_dir(SLV2List list, const char* dir) { DIR* pdir = opendir(dir); if (!pdir) @@ -165,8 +216,8 @@ add_plugins_from_dir(SLV2List list, const char* dir) if (!strcmp(pfile->d_name, ".") || !strcmp(pfile->d_name, "..")) continue; - char* bundle_path = (char*)strjoin(dir, "/", pfile->d_name, NULL); - char* bundle_url = (char*)strjoin("file://", dir, "/", pfile->d_name, NULL); + char* bundle_path = slv2_strjoin(dir, "/", pfile->d_name, NULL); + char* bundle_url = slv2_strjoin("file://", dir, "/", pfile->d_name, NULL); DIR* bundle_dir = opendir(bundle_path); if (bundle_dir != NULL) { @@ -184,21 +235,20 @@ add_plugins_from_dir(SLV2List list, const char* dir) void -slv2_list_load_path(SLV2List list, - const char* slv2_path) +slv2_list_load_path(SLV2List list, + const char* lv2_path) { - - char* path = (char*)strjoin(slv2_path, ":", NULL); + char* path = slv2_strjoin(lv2_path, ":", NULL); char* dir = path; // Pointer into path // Go through string replacing ':' with '\0', using the substring, - // then replacing it with 'X' and moving on. eg strtok on crack. + // then replacing it with 'X' and moving on. i.e. strtok on crack. while (strchr(path, ':') != NULL) { char* delim = strchr(path, ':'); *delim = '\0'; - add_plugins_from_dir(list, dir); + slv2_list_load_dir(list, dir); *delim = 'X'; dir = delim + 1; @@ -24,7 +24,7 @@ #include <slv2/port.h> #include <slv2/types.h> #include <slv2/query.h> -#include "util.h" +#include <slv2/util.h> SLV2PortID @@ -111,8 +111,8 @@ slv2_port_get_value(SLV2Plugin* p, char index_str[16]; snprintf(index_str, (size_t)16, "%u", id.index); - char* query = strjoin( - "SELECT DISTINCT ?value FROM data: WHERE { \n" + char* query = slv2_strjoin( + "SELECT DISTINCT ?value WHERE { \n" "plugin: lv2:port ?port . \n" "?port lv2:index ", index_str, " ;\n\t", property, " ?value . \n}\n", NULL); @@ -122,8 +122,8 @@ slv2_port_get_value(SLV2Plugin* p, free(query); } else { - char* query = strjoin( - "SELECT DISTINCT ?value FROM data: WHERE { \n" + char* query = slv2_strjoin( + "SELECT DISTINCT ?value WHERE { \n" "plugin: lv2:port ?port . \n" "?port lv2:symbol ", id.symbol, " ;\n\t", property, " ?value . \n}\n", NULL); diff --git a/src/query.c b/src/query.c index 6149531..0d44533 100644 --- a/src/query.c +++ b/src/query.c @@ -16,27 +16,36 @@ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include <util.h> +#define _XOPEN_SOURCE 500 #include <stdlib.h> #include <assert.h> #include <slv2/plugin.h> #include <slv2/query.h> #include <slv2/library.h> +#include <slv2/util.h> char* slv2_query_header(const SLV2Plugin* p) { const char* const plugin_uri = slv2_plugin_get_uri(p); - const char* const data_file_url = slv2_plugin_get_data_url(p); + //SLV2URIList files = slv2_plugin_get_data_uris(p); - char* query_string = strjoin( + char* query_string = slv2_strjoin( "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>\n" "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>\n" "PREFIX doap: <http://usefulinc.com/ns/doap#>\n" "PREFIX lv2: <http://lv2plug.in/ontology#>\n" - "PREFIX plugin: <", plugin_uri, ">\n", - "PREFIX data: <", data_file_url, ">\n\n", NULL); + "PREFIX plugin: <", plugin_uri, ">\n", NULL); + + /*for (int i=0; i < slv2_uri_list_size(files); ++i) { + const char* file_uri = slv2_uri_list_get_at(files, i); + slv2_strappend(&query_string, "PREFIX data: <"); + slv2_strappend(&query_string, file_uri); + slv2_strappend(&query_string, ">\n"); + }*/ + + slv2_strappend(&query_string, "\n"); return query_string; } @@ -49,7 +58,7 @@ slv2_query_lang_filter(const char* variable) char* const lang = (char*)getenv("LANG"); if (lang) { // FILTER( LANG(?value) = "en" || LANG(?value) = "" ) - result = strjoin( + result = slv2_strjoin( //"FILTER (lang(?value) = \"", lang, "\"\n"), 0); "FILTER( lang(?", variable, ") = \"", lang, "\" || lang(?", variable, ") = \"\" )\n", NULL); @@ -114,7 +123,7 @@ slv2_plugin_query(SLV2Plugin* plugin, rasqal_query *rq = rasqal_new_query("sparql", NULL); char* header = slv2_query_header(plugin); - char* query_str = strjoin(header, sparql_str, NULL); + char* query_str = slv2_strjoin(header, sparql_str, NULL); //printf("Query: \n%s\n\n", query_str); @@ -123,6 +132,14 @@ slv2_plugin_query(SLV2Plugin* plugin, // Add LV2 ontology to query sources rasqal_query_add_data_graph(rq, slv2_ontology_uri, NULL, RASQAL_DATA_GRAPH_BACKGROUND); + + // Add all plugin data files to query sources + for (int i=0; i < slv2_uri_list_size(plugin->data_uris); ++i) { + const char* file_uri_str = slv2_uri_list_get_at(plugin->data_uris, i); + raptor_uri* file_uri = raptor_new_uri((const unsigned char*)file_uri_str); + rasqal_query_add_data_graph(rq, file_uri, + NULL, RASQAL_DATA_GRAPH_BACKGROUND); + } rasqal_query_results* results = rasqal_query_execute(rq); assert(results); @@ -163,7 +180,7 @@ slv2_query_count_results(const SLV2Plugin* p, const char* query) { char* header = slv2_query_header(p); - char* query_str = strjoin(header, query, NULL); + char* query_str = slv2_strjoin(header, query, NULL); assert(p); assert(query_str); diff --git a/src/types.c b/src/types.c new file mode 100644 index 0000000..76521c0 --- /dev/null +++ b/src/types.c @@ -0,0 +1,54 @@ +/* SLV2 + * Copyright (C) 2007 Dave Robillard <http://drobilla.net> + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include <string.h> +#include <stdlib.h> +#include <raptor.h> +#include <slv2/types.h> + + +SLV2URIList +slv2_uri_list_new() +{ + return raptor_new_sequence(&free, NULL); +} + + +int +slv2_uri_list_size(const SLV2URIList list) +{ + return raptor_sequence_size(list); +} + + +char* +slv2_uri_list_get_at(const SLV2URIList list, int index) +{ + return (char*)raptor_sequence_get_at(list, index); +} + + +bool +slv2_uri_list_contains(const SLV2URIList list, const char* uri) +{ + for (int i=0; i < slv2_uri_list_size(list); ++i) + if (!strcmp(slv2_uri_list_get_at(list, i), uri)) + return true; + + return false; +} @@ -18,15 +18,15 @@ #define _XOPEN_SOURCE 500 -#include <util.h> #include <stdlib.h> #include <string.h> #include <assert.h> #include <stdarg.h> +#include <slv2/util.h> void -strappend(char** dst, const char* suffix) +slv2_strappend(char** dst, const char* suffix) { assert(dst); assert(*dst); @@ -40,7 +40,7 @@ strappend(char** dst, const char* suffix) char* -strjoin(const char* first, ...) +slv2_strjoin(const char* first, ...) { size_t len = strlen(first); char* result = NULL; @@ -73,23 +73,14 @@ strjoin(const char* first, ...) } -/** Convert a URL to a local filesystem path (ie by chopping off the - * leading "file://". - * - * Returns NULL if URL is not a valid URL on the local filesystem. - * Result is simply a pointer in to \a url and must not be free()'d. - */ const char* -url2path(const char* const url) +slv2_uri_to_path(const char* uri) { - /*assert(strlen((char*)url) > 8); - char* result = calloc(strlen((char*)url)-7+1, sizeof(char)); - strcpy(result, (char*)url+7); - return result;*/ - if (!strncmp((char*)url, "file://", (size_t)7)) - return (char*)url + 7; + if (!strncmp(uri, "file://", (size_t)7)) + return (char*)(uri + 7); else return NULL; } + diff --git a/utils/lv2_inspect.c b/utils/lv2_inspect.c index a7aaf1a..8dbc6e6 100644 --- a/utils/lv2_inspect.c +++ b/utils/lv2_inspect.c @@ -82,8 +82,12 @@ print_plugin(SLV2Plugin* p) printf("<%s>\n", slv2_plugin_get_uri(p)); - printf("\tData URL: %s\n", slv2_plugin_get_data_url(p)); - printf("\tLibrary URL: %s\n\n", slv2_plugin_get_library_url(p)); + printf("\tData URIs:\n"); + SLV2URIList data_uris = slv2_plugin_get_data_uris(p); + for (int i=0; i < slv2_uri_list_size(data_uris); ++i) + printf("\t\t%s\n", slv2_uri_list_get_at(data_uris, i)); + + printf("\n\tLibrary URI: %s\n\n", slv2_plugin_get_library_uri(p)); str = slv2_plugin_get_name(p); printf("\tName: %s\n", str); |