diff options
-rw-r--r-- | data/lv2.ttl | 4 | ||||
-rw-r--r-- | slv2/plugin.h | 12 | ||||
-rw-r--r-- | slv2/pluginlist.h | 40 | ||||
-rw-r--r-- | src/plugin.c | 88 | ||||
-rw-r--r-- | src/pluginlist.c | 99 | ||||
-rw-r--r-- | src/query.c | 7 | ||||
-rw-r--r-- | src/stringlist.c | 4 | ||||
-rw-r--r-- | utils/lv2_list.c | 2 |
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; |