summaryrefslogtreecommitdiffstats
path: root/src/pluginlist.c
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 /src/pluginlist.c
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
Diffstat (limited to 'src/pluginlist.c')
-rw-r--r--src/pluginlist.c148
1 files changed, 99 insertions, 49 deletions
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;