247 lines
6.3 KiB
C
247 lines
6.3 KiB
C
/* 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);
|
|
}
|
|
|
|
// FIXME: leaks? rasqal really doesn't handle missing files well..
|
|
if (results) {
|
|
rasqal_free_query_results(results);
|
|
rasqal_free_query(rq);
|
|
raptor_free_uri(base_uri); // FIXME: leak?
|
|
}
|
|
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), NULL);
|
|
char* bundle_url = (char*)ustrjoin(U("file://"), U(dir), U("/"), U(pfile->d_name), NULL);
|
|
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(":"), 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.
|
|
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;
|
|
}
|
|
|