diff options
Diffstat (limited to 'src/pluginlist.c')
-rw-r--r-- | src/pluginlist.c | 243 |
1 files changed, 243 insertions, 0 deletions
diff --git a/src/pluginlist.c b/src/pluginlist.c new file mode 100644 index 0000000..61e4c4b --- /dev/null +++ b/src/pluginlist.c @@ -0,0 +1,243 @@ +/* LibSLV2 + * Copyright (C) 2006 Dave Robillard <drobilla@connect.carleton.ca> + * + * 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. + */ + +#define _XOPEN_SOURCE 500 +#include <rasqal.h> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include <assert.h> +#include <dirent.h> +#include <slv2/private_types.h> +#include <slv2/types.h> +#include <slv2/plugin.h> +#include <slv2/pluginlist.h> +#include "util.h" + + +struct _PluginList* +slv2_list_new() +{ + struct _PluginList* result = malloc(sizeof(struct _PluginList)); + result->num_plugins = 0; + result->plugins = NULL; + return result; +} + + +void +slv2_list_free(SLV2List list) +{ + list->num_plugins = 0; + free(list->plugins); + free(list); +} + + +void +slv2_list_load_all(SLV2List list) +{ + assert(list != NULL); + + char* slv2_path = getenv("LV2_PATH"); + + if (!slv2_path) { + slv2_path = "~/.lv2:/usr/local/lib/lv2:usr/lib/lv2"; + + printf("$LV2_PATH is unset. Using default path %s\n", + slv2_path); + } + + slv2_list_load_path(list, slv2_path); +} + + +/* This is the parser for manifest.ttl */ +void +slv2_list_load_bundle(SLV2List list, + const unsigned char* bundle_base_uri) +{ + // FIXME: ew + unsigned char* manifest_uri = malloc( + (strlen((char*)bundle_base_uri) + strlen("manifest.ttl") + 2) * sizeof(unsigned char)); + memcpy(manifest_uri, bundle_base_uri, strlen((char*)bundle_base_uri)+1 * sizeof(unsigned char)); + if (bundle_base_uri[strlen((char*)bundle_base_uri)-1] == '/') + strcat((char*)manifest_uri, (char*)"manifest.ttl"); + else + strcat((char*)manifest_uri, (char*)"/manifest.ttl"); + + rasqal_init(); + rasqal_query_results *results; + raptor_uri *base_uri = raptor_new_uri(manifest_uri); + rasqal_query *rq = rasqal_new_query((const char*)"sparql", (const uchar*)base_uri); + + unsigned char* query_string = + U("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" + " rdfs:seeAlso $data_url . \n" + "} \n"); + + //printf("%s\n\n", query_string); + + rasqal_query_prepare(rq, (const uchar*)query_string, base_uri); + 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 = ustrdup(bundle_base_uri); + + rasqal_literal* literal = NULL; + + literal = rasqal_query_results_get_binding_value_by_name(results, + U("plugin_uri")); + if (literal) + new_plugin->plugin_uri = ustrdup(rasqal_literal_as_string(literal)); + + literal = rasqal_query_results_get_binding_value_by_name(results, + U("data_url")); + if (literal) + new_plugin->data_url = ustrdup(rasqal_literal_as_string(literal)); + + literal = rasqal_query_results_get_binding_value_by_name(results, + U("lib_url")); + if (literal) + new_plugin->lib_url = ustrdup(rasqal_literal_as_string(literal)); + + /* 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 */ + 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); + } + + rasqal_free_query_results(results); + rasqal_free_query(rq); + raptor_free_uri(base_uri); + rasqal_finish(); + + free(manifest_uri); +} + + +/* Add all the plugins found in dir to list. + * (Private helper function, not exposed in public API) + */ +void +add_plugins_from_dir(SLV2List list, const char* dir) +{ + DIR* pdir = opendir(dir); + if (!pdir) + return; + + struct dirent* pfile; + while ((pfile = readdir(pdir))) { + if (!strcmp(pfile->d_name, ".") || !strcmp(pfile->d_name, "..")) + continue; + + char* bundle_path = (char*)ustrjoin(U(dir), U("/"), U(pfile->d_name), 0); + char* bundle_url = (char*)ustrjoin(U("file://"), U(dir), U("/"), U(pfile->d_name), 0); + DIR* bundle_dir = opendir(bundle_path); + + if (bundle_dir != NULL) { + closedir(bundle_dir); + + slv2_list_load_bundle(list, U(bundle_url)); + //printf("Loaded bundle %s\n", bundle_url); + } + + free(bundle_path); + } + + closedir(pdir); +} + + +void +slv2_list_load_path(SLV2List list, + const char* slv2_path) +{ + + char* path = (char*)ustrjoin(U(slv2_path), U(":"), 0); + + 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. + while (strchr(path, ':') != NULL) { + char* delim = strchr(path, ':'); + *delim = '\0'; + + add_plugins_from_dir(list, dir); + + *delim = 'X'; + dir = delim + 1; + } + + //char* slv2_path = strdup(slv2 + + free(path); +} + + +unsigned long +slv2_list_get_length(const SLV2List list) +{ + assert(list != NULL); + return list->num_plugins; +} + + +SLV2Plugin* +slv2_list_get_plugin_by_uri(const SLV2List list, const unsigned char* uri) +{ + if (list->num_plugins > 0) { + assert(list->plugins != NULL); + + for (unsigned long i=0; i < list->num_plugins; ++i) + if (!strcmp((char*)list->plugins[i]->plugin_uri, (char*)uri)) + return list->plugins[i]; + } + + return NULL; +} + + +SLV2Plugin* +slv2_list_get_plugin_by_index(const SLV2List list, unsigned long index) +{ + if (list->num_plugins == 0) + return NULL; + + assert(list->plugins != NULL); + + return (index < list->num_plugins) ? list->plugins[index] : NULL; +} + |