summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2007-02-19 06:10:38 +0000
committerDavid Robillard <d@drobilla.net>2007-02-19 06:10:38 +0000
commit25d13653ede7fdda4f08cd1e57c73a3c186a7b50 (patch)
tree455bda6403b55b656a8b9b98bdd238ad04deaef7
parentd3d736deba06ca2ef655858ac22d8267c5cc6363 (diff)
downloadlilv-25d13653ede7fdda4f08cd1e57c73a3c186a7b50.tar.gz
lilv-25d13653ede7fdda4f08cd1e57c73a3c186a7b50.tar.bz2
lilv-25d13653ede7fdda4f08cd1e57c73a3c186a7b50.zip
Fixed doap:license typo in lv2.ttl.
Added stronger plugin validation. Plugged memory leaks. Aded list filtering by arbitrary function pointer. git-svn-id: http://svn.drobilla.net/lad/slv2@318 a436a847-0d15-0410-975c-d299462d15a1
-rw-r--r--data/lv2.ttl4
-rw-r--r--slv2/plugin.h12
-rw-r--r--slv2/pluginlist.h40
-rw-r--r--src/plugin.c88
-rw-r--r--src/pluginlist.c99
-rw-r--r--src/query.c7
-rw-r--r--src/stringlist.c4
-rw-r--r--utils/lv2_list.c2
8 files changed, 169 insertions, 87 deletions
diff --git a/data/lv2.ttl b/data/lv2.ttl
index fcea5b1..d3ed0b3 100644
--- a/data/lv2.ttl
+++ b/data/lv2.ttl
@@ -1,7 +1,7 @@
# RDF Schema for LV2 plugins
# *** PROVISIONAL ***
#
-# *** PROPOSED Revision 2007-02-07 ***
+# *** PROPOSED Revision 2007-02-19 ***
#
# This document describes the classes and properties that are defined by the
# core LV2 specification. See <http://lv2plug.in> for more information.
@@ -69,7 +69,7 @@ The class that represents an LV2 plugin.
To be used by a host a Plugin must have at least the following properties:
rdf:type (with object :Plugin)
doap:name (one without language tag)
- doap:licence
+ doap:license
:port
""" .
diff --git a/slv2/plugin.h b/slv2/plugin.h
index 559c927..3cc2f8c 100644
--- a/slv2/plugin.h
+++ b/slv2/plugin.h
@@ -61,7 +61,8 @@ slv2_plugin_verify(SLV2Plugin plugin);
/** Duplicate a plugin.
*
* Use this if you want to keep an SLV2Plugin around but free the list it came
- * from.
+ * from. Freeing the returned plugin with slv2_plugin_free is the caller's
+ * responsibility.
*
* \return a newly allocated deep copy of \a plugin.
*/
@@ -69,6 +70,15 @@ SLV2Plugin
slv2_plugin_duplicate(SLV2Plugin plugin);
+/** Free an SLV2Plugin.
+ *
+ * This should NEVER be used on a plugin contained in a Plugins. Use this
+ * only with plugins created with slv2_plugin_duplicate.
+ */
+void
+slv2_plugin_free(SLV2Plugin plugin);
+
+
/** Get the URI of \a plugin.
*
* Any serialization that refers to plugins should refer to them by this.
diff --git a/slv2/pluginlist.h b/slv2/pluginlist.h
index 3e9b9d4..f862df4 100644
--- a/slv2/pluginlist.h
+++ b/slv2/pluginlist.h
@@ -24,7 +24,7 @@ extern "C" {
#endif
-typedef struct _PluginList* SLV2Plugins;
+typedef void* SLV2Plugins;
/** \defgroup plugins Plugins - Collection of plugins, plugin discovery
@@ -67,18 +67,29 @@ void
slv2_plugins_free(SLV2Plugins list);
+/** Filter plugins from one list into another.
+ *
+ * All plugins in @a source that return true when passed to @a include
+ * (a pointer to a function that takes an SLV2Plugin and returns a bool)
+ * will be added to @a dest. Plugins are duplicated into dest, it is safe
+ * to destroy source and continue to use dest after this call.
+ */
+void
+slv2_plugins_filter(SLV2Plugins dest,
+ SLV2Plugins source,
+ bool (*include)(SLV2Plugin));
+
+
/** Add all plugins installed on the system to \a list.
*
- * This is the recommended way for hosts to access plugins. It finds all
- * plugins on the system using the recommended mechanism. At the time, this
- * is by searching the path defined in the environment variable LADSPA2_PATH,
- * though this is subject to change in the future. Future versions may, for
- * example, allow users to specify a plugin whitelist of plugins they would
- * like to be visible in apps (or conversely a blacklist of plugins they do
- * not wish to use).
+ * This is the recommended way for hosts to access plugins. It does the most
+ * reasonable thing to find all installed plugins on a system. The environment
+ * variable LV2_PATH may be set to control the locations this function will
+ * look for plugins.
*
* Use of any functions for locating plugins other than this one is \em highly
- * discouraged without a special reason to do so - use this one.
+ * discouraged without a special reason to do so (and is just more work for the
+ * host author) - use this one.
*/
void
slv2_plugins_load_all(SLV2Plugins list);
@@ -115,7 +126,7 @@ slv2_plugins_load_bundle(SLV2Plugins list,
/** Get the number of plugins in the list.
*/
unsigned
-slv2_plugins_size(const SLV2Plugins list);
+slv2_plugins_size(SLV2Plugins list);
/** Get a plugin from the list by URI.
@@ -128,8 +139,8 @@ slv2_plugins_size(const SLV2Plugins list);
* \return NULL if plugin with \a url not found in \a list.
*/
SLV2Plugin
-slv2_plugins_get_by_uri(const SLV2Plugins list,
- const char* uri);
+slv2_plugins_get_by_uri(SLV2Plugins list,
+ const char* uri);
/** Get a plugin from the list by index.
@@ -145,9 +156,8 @@ slv2_plugins_get_by_uri(const SLV2Plugins list,
* \return NULL if \a index out of range.
*/
SLV2Plugin
-slv2_plugins_get_at(const SLV2Plugins list,
- unsigned index);
-
+slv2_plugins_get_at(SLV2Plugins list,
+ unsigned index);
/** @} */
diff --git a/src/plugin.c b/src/plugin.c
index 8918fa3..64452bb 100644
--- a/src/plugin.c
+++ b/src/plugin.c
@@ -29,14 +29,20 @@
#include "private_types.h"
+// FIXME: ew
+rasqal_query_results*
+slv2_plugin_query(SLV2Plugin plugin,
+ const char* sparql_str);
+
+
SLV2Plugin
slv2_plugin_duplicate(SLV2Plugin p)
{
assert(p);
struct _Plugin* result = malloc(sizeof(struct _Plugin));
- result->plugin_uri = p->plugin_uri;
- result->bundle_url = p->bundle_url;
- result->lib_uri = p->lib_uri;
+ result->plugin_uri = strdup(p->plugin_uri);
+ result->bundle_url = strdup(p->bundle_url);
+ result->lib_uri = strdup(p->lib_uri);
result->data_uris = slv2_strings_new();
for (unsigned i=0; i < slv2_strings_size(p->data_uris); ++i)
@@ -45,6 +51,17 @@ slv2_plugin_duplicate(SLV2Plugin p)
}
+void
+slv2_plugin_free(SLV2Plugin p)
+{
+ free(p->plugin_uri);
+ free(p->bundle_url);
+ free(p->lib_uri);
+ slv2_strings_free(p->data_uris);
+ free(p);
+}
+
+
const char*
slv2_plugin_get_uri(SLV2Plugin p)
{
@@ -72,33 +89,60 @@ slv2_plugin_get_library_uri(SLV2Plugin p)
bool
slv2_plugin_verify(SLV2Plugin plugin)
{
- // FIXME: finish this (properly)
-
- size_t num_values = 0;
-
- SLV2Strings prop = slv2_plugin_get_value(plugin, "doap:name");
- if (prop) {
- num_values = slv2_strings_size(prop);
- slv2_strings_free(prop);
+ char* query_str =
+ "SELECT DISTINCT ?type ?name ?license ?port WHERE {\n"
+ "plugin: a ?type ;\n"
+ "doap:name ?name ;\n"
+ "doap:license ?license ;\n"
+ "lv2:port [ lv2:index ?port ] .\n}";
+
+ rasqal_query_results* results = slv2_plugin_query(plugin, query_str);
+
+ bool has_type = false;
+ bool has_name = false;
+ bool has_license = false;
+ bool has_port = false;
+
+ while (!rasqal_query_results_finished(results)) {
+ rasqal_literal* literal = rasqal_query_results_get_binding_value(results, 0);
+ const char* const type = (const char*)rasqal_literal_as_string(literal);
+ literal = rasqal_query_results_get_binding_value(results, 1);
+ const char* const name = (const char*)rasqal_literal_as_string(literal);
+ rasqal_literal* license = rasqal_query_results_get_binding_value(results, 2);
+ rasqal_literal* port = rasqal_query_results_get_binding_value(results, 3);
+
+ if (!strcmp(type, "http://lv2plug.in/ontology#Plugin"))
+ has_type = true;
+
+ if (name)
+ has_name = true;
+
+ if (license)
+ has_license = true;
+
+ if (port)
+ has_port = true;
+
+ rasqal_query_results_next(results);
}
- if (num_values < 1)
- return false;
-/*
- prop = slv2_plugin_get_value(plugin, "doap:license");
- num_values = prop->num_values;
- free(prop);
- if (num_values < 1)
+
+ free(query_str);
+ rasqal_free_query_results(results);
+
+ if ( ! (has_type && has_name && has_license && has_port) ) {
+ fprintf(stderr, "Invalid LV2 Plugin %s:\n", slv2_plugin_get_uri(plugin));
return false;
-*/
- return true;
+ } else {
+ return true;
+ }
}
char*
slv2_plugin_get_name(SLV2Plugin plugin)
{
- char* result = NULL;
- SLV2Strings prop = slv2_plugin_get_value(plugin, "doap:name");
+ char* result = NULL;
+ SLV2Strings prop = slv2_plugin_get_value(plugin, "doap:name");
// FIXME: guaranteed to be the untagged one?
if (prop && slv2_strings_size(prop) >= 1)
diff --git a/src/pluginlist.c b/src/pluginlist.c
index a6a2a97..9dcb33c 100644
--- a/src/pluginlist.c
+++ b/src/pluginlist.c
@@ -18,6 +18,7 @@
#define _XOPEN_SOURCE 500
#include <rasqal.h>
+#include <limits.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
@@ -47,34 +48,46 @@ slv2_plugin_new()
}
-struct _PluginList*
+SLV2Plugins
slv2_plugins_new()
{
- struct _PluginList* result = malloc(sizeof(struct _PluginList));
- result->num_plugins = 0;
- result->plugins = NULL;
- return result;
+ return raptor_new_sequence((void (*)(void*))&slv2_plugin_free, NULL);
}
void
slv2_plugins_free(SLV2Plugins list)
{
- list->num_plugins = 0;
- free(list->plugins);
- free(list);
+ raptor_free_sequence(list);
+}
+
+
+void
+slv2_plugins_filter(SLV2Plugins dest, SLV2Plugins source, bool (*include)(SLV2Plugin))
+{
+ assert(dest);
+
+ for (int i=0; i < raptor_sequence_size(source); ++i) {
+ SLV2Plugin p = raptor_sequence_get_at(source, i);
+ if (include(p))
+ raptor_sequence_push(dest, slv2_plugin_duplicate(p));
+ }
}
void
slv2_plugins_load_all(SLV2Plugins list)
{
- assert(list != NULL);
+ /* FIXME: this is much slower than it should be in many ways.. */
+
+ assert(list);
char* slv2_path = getenv("LV2_PATH");
+ SLV2Plugins load_list = slv2_plugins_new();
+
if (slv2_path) {
- slv2_plugins_load_path(list, slv2_path);
+ slv2_plugins_load_path(load_list, slv2_path);
} else {
const char* const home = getenv("HOME");
const char* const suffix = "/.lv2:/usr/local/lib/lv2:usr/lib/lv2";
@@ -83,13 +96,17 @@ slv2_plugins_load_all(SLV2Plugins list)
fprintf(stderr, "$LV2_PATH is unset. Using default path %s\n", slv2_path);
/* pass 1: find all plugins */
- slv2_plugins_load_path(list, slv2_path);
+ slv2_plugins_load_path(load_list, slv2_path);
/* pass 2: find all data files for plugins */
- slv2_plugins_load_path(list, slv2_path);
+ slv2_plugins_load_path(load_list, slv2_path);
free(slv2_path);
}
+
+ /* insert only valid plugins into list */
+ slv2_plugins_filter(list, load_list, slv2_plugin_verify);
+ slv2_plugins_free(load_list);
}
@@ -97,9 +114,11 @@ slv2_plugins_load_all(SLV2Plugins list)
* This is called twice on each bundle in the discovery process, which is (much) less
* efficient than it could be.... */
void
-slv2_plugins_load_bundle(SLV2Plugins list,
- const char* bundle_base_url)
+slv2_plugins_load_bundle(SLV2Plugins list,
+ const char* bundle_base_url)
{
+ assert(list);
+
unsigned char* manifest_url = malloc(
(strlen((char*)bundle_base_url) + strlen("manifest.ttl") + 2) * sizeof(unsigned char));
memcpy(manifest_url, bundle_base_url, strlen((char*)bundle_base_url)+1 * sizeof(unsigned char));
@@ -135,13 +154,7 @@ slv2_plugins_load_bundle(SLV2Plugins list,
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;
+ raptor_sequence_push(list, new_plugin);
}
@@ -195,7 +208,6 @@ slv2_plugins_load_bundle(SLV2Plugins list,
rasqal_free_query_results(results);
rasqal_free_query(rq);
-
raptor_free_uri(base_url);
free(manifest_url);
@@ -208,6 +220,8 @@ slv2_plugins_load_bundle(SLV2Plugins list,
void
slv2_plugins_load_dir(SLV2Plugins list, const char* dir)
{
+ assert(list);
+
DIR* pdir = opendir(dir);
if (!pdir)
return;
@@ -229,6 +243,7 @@ slv2_plugins_load_dir(SLV2Plugins list, const char* dir)
}
free(bundle_path);
+ free(bundle_url);
}
closedir(pdir);
@@ -236,12 +251,13 @@ slv2_plugins_load_dir(SLV2Plugins list, const char* dir)
void
-slv2_plugins_load_path(SLV2Plugins list,
- const char* lv2_path)
+slv2_plugins_load_path(SLV2Plugins list,
+ const char* lv2_path)
{
- char* path = slv2_strjoin(lv2_path, ":", NULL);
+ assert(list);
- char* dir = path; // Pointer into path
+ 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. i.e. strtok on crack.
@@ -262,22 +278,19 @@ slv2_plugins_load_path(SLV2Plugins list,
unsigned
-slv2_plugins_size(const SLV2Plugins list)
+slv2_plugins_size(SLV2Plugins list)
{
- assert(list != NULL);
- return list->num_plugins;
+ return raptor_sequence_size(list);
}
SLV2Plugin
-slv2_plugins_get_by_uri(const SLV2Plugins list, const char* uri)
+slv2_plugins_get_by_uri(SLV2Plugins list, const char* uri)
{
- if (list->num_plugins > 0) {
- assert(list->plugins != NULL);
-
- for (unsigned i=0; i < list->num_plugins; ++i)
- if (!strcmp((char*)list->plugins[i]->plugin_uri, (char*)uri))
- return list->plugins[i];
+ for (int i=0; i < raptor_sequence_size(list); ++i) {
+ SLV2Plugin p = raptor_sequence_get_at(list, i);
+ if (!strcmp(p->plugin_uri, uri))
+ return p;
}
return NULL;
@@ -285,13 +298,13 @@ slv2_plugins_get_by_uri(const SLV2Plugins list, const char* uri)
SLV2Plugin
-slv2_plugins_get_at(const SLV2Plugins list, unsigned index)
-{
- if (list->num_plugins == 0)
+slv2_plugins_get_at(SLV2Plugins list, unsigned index)
+{
+ assert(list);
+
+ if (index > INT_MAX)
return NULL;
-
- assert(list->plugins != NULL);
-
- return (index < list->num_plugins) ? list->plugins[index] : NULL;
+ else
+ return (SLV2Plugin)raptor_sequence_get_at(list, (int)index);
}
diff --git a/src/query.c b/src/query.c
index b671ac8..4d259f2 100644
--- a/src/query.c
+++ b/src/query.c
@@ -134,15 +134,18 @@ slv2_plugin_query(SLV2Plugin plugin,
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);
+ raptor_free_uri(file_uri);
}
rasqal_query_results* results = rasqal_query_execute(rq);
- assert(results);
rasqal_free_query(rq);
raptor_free_uri(base_uri);
- // FIXME: results leaked?
+ free(header);
+ free(query_str);
+
+ // FIXME: results leaked internally in places?
return results;
/*
diff --git a/src/stringlist.c b/src/stringlist.c
index 930454f..2233e7e 100644
--- a/src/stringlist.c
+++ b/src/stringlist.c
@@ -55,10 +55,10 @@ slv2_strings_get_at(SLV2Strings list, unsigned index)
bool
-slv2_strings_contains(SLV2Strings list, const char* uri)
+slv2_strings_contains(SLV2Strings list, const char* str)
{
for (unsigned i=0; i < slv2_strings_size(list); ++i)
- if (!strcmp(slv2_strings_get_at(list, i), uri))
+ if (!strcmp(slv2_strings_get_at(list, i), str))
return true;
return false;
diff --git a/utils/lv2_list.c b/utils/lv2_list.c
index c8e430d..0112bc7 100644
--- a/utils/lv2_list.c
+++ b/utils/lv2_list.c
@@ -40,6 +40,8 @@ main()//int argc, char** argv)
list_plugins(plugins);
+ slv2_plugins_free(plugins);
+
slv2_finish();
return 0;