summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2007-02-18 04:16:24 +0000
committerDavid Robillard <d@drobilla.net>2007-02-18 04:16:24 +0000
commita80e895b0b23d478807377360b85b4bb1d7073b7 (patch)
treee2ea19db66cd44bce0d84176c4c87a90d9b5d9e0
parent07c3b4ce3ed385368147bd4f2e058f83d9064b0d (diff)
downloadlilv-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.am3
-rw-r--r--slv2/plugin.h37
-rw-r--r--slv2/private_types.h23
-rw-r--r--slv2/types.h21
-rw-r--r--slv2/util.h (renamed from src/util.h)35
-rw-r--r--src/Makefile.am3
-rw-r--r--src/plugin.c66
-rw-r--r--src/plugininstance.c16
-rw-r--r--src/pluginlist.c148
-rw-r--r--src/port.c10
-rw-r--r--src/query.c33
-rw-r--r--src/types.c54
-rw-r--r--src/util.c23
-rw-r--r--utils/lv2_inspect.c8
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__ */
diff --git a/src/util.h b/slv2/util.h
index caa025e..f6c90d4 100644
--- a/src/util.h
+++ b/slv2/util.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;
diff --git a/src/port.c b/src/port.c
index a7691ea..b92e12b 100644
--- a/src/port.c
+++ b/src/port.c
@@ -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;
+}
diff --git a/src/util.c b/src/util.c
index 135c256..35624c1 100644
--- a/src/util.c
+++ b/src/util.c
@@ -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);