From c625507d8a3101742c083dd030cbd1e1e295a9a0 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Thu, 19 Apr 2007 18:29:16 +0000 Subject: Renamed SLV2Model SLV2World. Updated Ingen for SLV2 API changes. git-svn-id: http://svn.drobilla.net/lad/slv2@459 a436a847-0d15-0410-975c-d299462d15a1 --- hosts/lv2_jack_host.c | 8 +- hosts/lv2_simple_jack_host.c | 6 +- slv2/Makefile.am | 2 +- slv2/model.h | 166 ---------------------- slv2/plugin.h | 8 +- slv2/pluginlist.h | 2 +- slv2/slv2.h | 2 +- slv2/types.h | 2 +- slv2/world.h | 166 ++++++++++++++++++++++ src/Makefile.am | 2 +- src/model.c | 321 ------------------------------------------- src/plugin.c | 17 +-- src/private_types.h | 7 +- src/query.c | 6 +- src/world.c | 321 +++++++++++++++++++++++++++++++++++++++++++ utils/lv2_inspect.c | 8 +- utils/lv2_list.c | 8 +- 17 files changed, 524 insertions(+), 528 deletions(-) delete mode 100644 slv2/model.h create mode 100644 slv2/world.h delete mode 100644 src/model.c create mode 100644 src/world.c diff --git a/hosts/lv2_jack_host.c b/hosts/lv2_jack_host.c index 2e7a23f..a0bca74 100644 --- a/hosts/lv2_jack_host.c +++ b/hosts/lv2_jack_host.c @@ -63,9 +63,9 @@ main(int argc, char** argv) host.ports = NULL; /* Find all installed plugins */ - SLV2Model model = slv2_model_new(); - slv2_model_load_all(model); - SLV2Plugins plugins = slv2_model_get_all_plugins(model); + SLV2World world = slv2_world_new(); + slv2_world_load_all(world); + SLV2Plugins plugins = slv2_world_get_all_plugins(world); /* Find the plugin to run */ const char* plugin_uri = (argc == 2) ? argv[1] : NULL; @@ -140,7 +140,7 @@ main(int argc, char** argv) } jack_client_close(host.jack_client); - slv2_model_free(model); + slv2_world_free(world); return 0; } diff --git a/hosts/lv2_simple_jack_host.c b/hosts/lv2_simple_jack_host.c index 260605c..0b938e3 100644 --- a/hosts/lv2_simple_jack_host.c +++ b/hosts/lv2_simple_jack_host.c @@ -24,8 +24,8 @@ int main(/*int argc, char** argv*/) { - SLV2Model model = slv2_model_new(); - slv2_model_load_all(model); + SLV2World world = slv2_world_new(); + slv2_world_load_all(world); /*printf("********** All plugins **********\n"); @@ -62,7 +62,7 @@ main(/*int argc, char** argv*/) slv2_plugins_free(plugins); */ - slv2_model_free(model); + slv2_world_free(world); return 0; } diff --git a/slv2/Makefile.am b/slv2/Makefile.am index 2c69aef..e20cde8 100644 --- a/slv2/Makefile.am +++ b/slv2/Makefile.am @@ -4,7 +4,7 @@ slv2include_HEADERS = \ lv2.h \ types.h \ slv2.h \ - model.h \ + world.h \ plugin.h \ port.h \ pluginlist.h \ diff --git a/slv2/model.h b/slv2/model.h deleted file mode 100644 index 4db1b2f..0000000 --- a/slv2/model.h +++ /dev/null @@ -1,166 +0,0 @@ -/* SLV2 - * Copyright (C) 2007 Dave Robillard - * - * 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. - */ - -#ifndef __SLV2_MODEL_H__ -#define __SLV2_MODEL_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - - -/** \defgroup model Data model loading - * - * These functions deal with the data model which other SLV2 methods - * operate with. The data model is LV2 data loaded from bundles, from - * which you can query plugins, etc. - * - * Normal hosts which just want to easily load plugins by URI are strongly - * recommended to simply find all installed data in the recommended way with - * \ref slv2_model_load_all rather than find and load bundles manually. - * - * Functions are provided for hosts that wish to access bundles explicitly and - * individually for some reason, this is intended for hosts which are tied to - * a specific bundle (shipped with the application). - * - * @{ - */ - - -/** Create a new, empty model. - */ -SLV2Model -slv2_model_new(); - - -/** Destroy a model. - * - * NB: Destroying a model will leave dangling references in any plugin lists, - * plugins, etc. Do not destroy a model until you are finished with all - * objects that came from it. - */ -void -slv2_model_free(SLV2Model model); - - -/** Load all installed LV2 bundles on the system - * - * This is the recommended way for hosts to load LV2 data. It does the most - * reasonable thing to find all installed plugins, extensions, etc. on the - * system. The environment variable LV2_PATH may be used to set the - * directories inside which this function will look for bundles. Otherwise - * a sensible, standard default will be used. - * - * Use of other functions for loading bundles is \em highly discouraged - * without a special reason to do so - use this one. - */ -void -slv2_model_load_all(SLV2Model model); - - -/** Load all bundles found in \a search_path. - * - * \param search_path A colon-delimited list of directories. These directories - * should contain LV2 bundle directories (ie the search path is a list of - * parent directories of bundles, not a list of bundle directories). - * - * If \a search_path is NULL, \a model will be unmodified. - * Use of this function is \b not recommended. Use \ref slv2_model_load_all. - */ -void -slv2_model_load_path(SLV2Model model, - const char* search_path); - - -/** Load a specific bundle into \a model. - * - * \arg bundle_base_uri is a fully qualified URI to the bundle directory, - * with the trailing slash, eg. file:///usr/lib/lv2/someBundle/ - * - * Normal hosts should not use this function. - * - * Hosts should not attach \em any long-term significance to bundle paths - * as there are no guarantees they will remain consistent whatsoever. - * This function should only be used by apps which ship with a special - * bundle (which it knows exists at some path because they are part of - * the same package). - */ -void -slv2_model_load_bundle(SLV2Model model, - const char* bundle_base_uri); - - -/** Add all plugins present in \a model to \a list. - * - * Returned plugins contain a reference to this model, model must not be - * destroyed until plugins are finished with. - */ -SLV2Plugins -slv2_model_get_all_plugins(SLV2Model model); - - -/** Get plugins filtered by a user-defined filter function. - * - * All plugins in \a model 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 list. - * - * Returned plugins contain a reference to this model, model must not be - * destroyed until plugins are finished with. - */ -SLV2Plugins -slv2_model_get_plugins_by_filter(SLV2Model model, - bool (*include)(SLV2Plugin)); - - -#if 0 -/** Get plugins filtered by a user-defined SPARQL query. - * - * This is much faster than using slv2_model_get_plugins_by_filter with a - * filter function which calls the various slv2_plugin_* functions. - * - * \param query A valid SPARQL query which SELECTs a single variable, which - * should match the URI of plugins to be loaded. - * - * \b Example: Get all plugins with at least 1 audio input and output: - \verbatim -PREFIX : -SELECT DISTINCT ?plugin WHERE { - ?plugin :port [ a :AudioPort; a :InputPort ] ; - :port [ a :AudioPort; a :OutputPort ] . -} -\endverbatim - * - * Returned plugins contain a reference to this model, model must not be - * destroyed until plugins are finished with. - */ -SLV2Plugins -slv2_model_get_plugins_by_query(SLV2Model model, - const char* query); -#endif - -/** @} */ - -#ifdef __cplusplus -} -#endif - -#endif /* __SLV2_MODEL_H__ */ - diff --git a/slv2/plugin.h b/slv2/plugin.h index 7b8d62b..47cb9ee 100644 --- a/slv2/plugin.h +++ b/slv2/plugin.h @@ -31,12 +31,12 @@ extern "C" { /** \defgroup data Plugin data access * - * These functions work exclusively with the plugin's RDF data file. + * These functions work exclusively with the plugin's RDF data. * They do not load or access the plugin dynamic library in any way. * - * An SLV2Plugin is a weak reference (ie URIs) to an LV2 plugin in the - * Model. Most functions which operate on an SLV2Plugin actually query - * the data in the model. + * An SLV2Plugin contains an in-memory cache of the plugin data, loaded + * on demand. Duplicating plugins should be avoided when possible for + * performance reasons. * * @{ */ diff --git a/slv2/pluginlist.h b/slv2/pluginlist.h index c0c1b4d..cd1bbf8 100644 --- a/slv2/pluginlist.h +++ b/slv2/pluginlist.h @@ -32,7 +32,7 @@ typedef void* SLV2Plugins; /** \defgroup plugins Plugin lists * * These functions work with lists of plugins which come from an - * SLV2Model. These lists contain only a weak reference to an LV2 plugin + * SLV2World. These lists contain only a weak reference to an LV2 plugin * in the Model. * * @{ diff --git a/slv2/slv2.h b/slv2/slv2.h index 8691e28..431bd17 100644 --- a/slv2/slv2.h +++ b/slv2/slv2.h @@ -24,7 +24,7 @@ extern "C" { #endif #include -#include +#include #include #include #include diff --git a/slv2/types.h b/slv2/types.h index da53069..f0f9b7f 100644 --- a/slv2/types.h +++ b/slv2/types.h @@ -47,7 +47,7 @@ typedef struct _Port* SLV2Port; typedef struct _Plugin* SLV2Plugin; -typedef struct _Model* SLV2Model; +typedef struct _World* SLV2World; #ifdef __cplusplus } diff --git a/slv2/world.h b/slv2/world.h new file mode 100644 index 0000000..4f5b252 --- /dev/null +++ b/slv2/world.h @@ -0,0 +1,166 @@ +/* SLV2 + * Copyright (C) 2007 Dave Robillard + * + * 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. + */ + +#ifndef __SLV2_WORLD_H__ +#define __SLV2_WORLD_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +/** \defgroup world Library context, data loading, etc. + * + * These functions deal with the data model which other SLV2 methods + * operate with. The world contains an in-memory cache of all bundles + * manifest.ttl files, from which you can quickly query plugins, etc. + * + * Normal hosts which just want to easily load plugins by URI are strongly + * recommended to simply find all installed data in the recommended way with + * \ref slv2_world_load_all rather than find and load bundles manually. + * + * Functions are provided for hosts that wish to access bundles explicitly and + * individually for some reason, this is intended for hosts which are tied to + * a specific bundle (shipped with the application). + * + * @{ + */ + + +/** Initialize a new, empty world. + */ +SLV2World +slv2_world_new(); + + +/** Destroy the world, mwahaha. + * + * NB: Destroying the world will leave dangling references in any plugin lists, + * plugins, etc. Do not destroy the world until you are finished with all + * objects that came from it. + */ +void +slv2_world_free(SLV2World world); + + +/** Load all installed LV2 bundles on the system + * + * This is the recommended way for hosts to load LV2 data. It does the most + * reasonable thing to find all installed plugins, extensions, etc. on the + * system. The environment variable LV2_PATH may be used to set the + * directories inside which this function will look for bundles. Otherwise + * a sensible, standard default will be used. + * + * Use of other functions for loading bundles is \em highly discouraged + * without a special reason to do so - use this one. + */ +void +slv2_world_load_all(SLV2World world); + + +/** Load all bundles found in \a search_path. + * + * \param search_path A colon-delimited list of directories. These directories + * should contain LV2 bundle directories (ie the search path is a list of + * parent directories of bundles, not a list of bundle directories). + * + * If \a search_path is NULL, \a world will be unmodified. + * Use of this function is \b not recommended. Use \ref slv2_world_load_all. + */ +void +slv2_world_load_path(SLV2World world, + const char* search_path); + + +/** Load a specific bundle into \a world. + * + * \arg bundle_base_uri is a fully qualified URI to the bundle directory, + * with the trailing slash, eg. file:///usr/lib/lv2/someBundle/ + * + * Normal hosts should not use this function. + * + * Hosts should not attach \em any long-term significance to bundle paths + * as there are no guarantees they will remain consistent whatsoever. + * This function should only be used by apps which ship with a special + * bundle (which it knows exists at some path because they are part of + * the same package). + */ +void +slv2_world_load_bundle(SLV2World world, + const char* bundle_base_uri); + + +/** Add all plugins present in \a world to \a list. + * + * Returned plugins contain a reference to this world, world must not be + * destroyed until plugins are finished with. + */ +SLV2Plugins +slv2_world_get_all_plugins(SLV2World world); + + +/** Get plugins filtered by a user-defined filter function. + * + * All plugins in \a world 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 list. + * + * Returned plugins contain a reference to this world, world must not be + * destroyed until plugins are finished with. + */ +SLV2Plugins +slv2_world_get_plugins_by_filter(SLV2World world, + bool (*include)(SLV2Plugin)); + + +#if 0 +/** Get plugins filtered by a user-defined SPARQL query. + * + * This is much faster than using slv2_world_get_plugins_by_filter with a + * filter function which calls the various slv2_plugin_* functions. + * + * \param query A valid SPARQL query which SELECTs a single variable, which + * should match the URI of plugins to be loaded. + * + * \b Example: Get all plugins with at least 1 audio input and output: + \verbatim +PREFIX : +SELECT DISTINCT ?plugin WHERE { + ?plugin :port [ a :AudioPort; a :InputPort ] ; + :port [ a :AudioPort; a :OutputPort ] . +} +\endverbatim + * + * Returned plugins contain a reference to this world, world must not be + * destroyed until plugins are finished with. + */ +SLV2Plugins +slv2_world_get_plugins_by_query(SLV2World world, + const char* query); +#endif + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* __SLV2_WORLD_H__ */ + diff --git a/src/Makefile.am b/src/Makefile.am index eb25597..8009ff8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -6,7 +6,7 @@ libslv2_la_LIBADD = @REDLAND_LIBS@ libslv2_la_SOURCES = \ private_types.h \ - model.c \ + world.c \ plugin.c \ query.c \ port.c \ diff --git a/src/model.c b/src/model.c deleted file mode 100644 index 16a1962..0000000 --- a/src/model.c +++ /dev/null @@ -1,321 +0,0 @@ -/* SLV2 - * Copyright (C) 2007 Dave Robillard - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include "config.h" -#include "private_types.h" - - -SLV2Model -slv2_model_new() -{ - struct _Model* model = (struct _Model*)malloc(sizeof(struct _Model)); - - model->world = librdf_new_world(); - librdf_world_open(model->world); - - model->storage = librdf_new_storage(model->world, "hashes", NULL, - "hash-type='memory'"); - - model->model = librdf_new_model(model->world, model->storage, NULL); - - model->parser = librdf_new_parser(model->world, "turtle", NULL, NULL); - - model->plugins = slv2_plugins_new(); - - /*slv2_ontology_uri = raptor_new_uri((const unsigned char*) - "file://" LV2_TTL_PATH);*/ - - return model; -} - - -void -slv2_model_free(SLV2Model model) -{ - /*raptor_free_uri(slv2_ontology_uri); - slv2_ontology_uri = NULL;*/ - - slv2_plugins_free(model->plugins); - model->plugins = NULL; - - librdf_free_parser(model->parser); - model->parser = NULL; - - librdf_free_model(model->model); - model->model = NULL; - - librdf_free_storage(model->storage); - model->storage = NULL; - - librdf_free_world(model->world); - model->world = NULL; - - free(model); -} - - -/* private */ -void -slv2_model_load_directory(SLV2Model model, 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_uri_str = slv2_strjoin("file://", dir, "/", pfile->d_name, "/", NULL); - librdf_uri* bundle_uri = librdf_new_uri(model->world, (unsigned char*)bundle_uri_str); - - DIR* bundle_dir = opendir(bundle_uri_str + 7); - - if (bundle_dir != NULL) { - closedir(bundle_dir); - - librdf_uri* manifest_uri = librdf_new_uri_relative_to_base( - bundle_uri, (const unsigned char*)"manifest.ttl"); - - librdf_parser_parse_into_model(model->parser, manifest_uri, NULL, model->model); - - librdf_free_uri(manifest_uri); - } - - free(bundle_uri_str); - librdf_free_uri(bundle_uri); - } - - closedir(pdir); -} - - -void -slv2_model_load_path(SLV2Model model, - const char* lv2_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. - while (strchr(path, ':') != NULL) { - char* delim = strchr(path, ':'); - *delim = '\0'; - - slv2_model_load_directory(model, dir); - - *delim = 'X'; - dir = delim + 1; - } - - free(path); -} - - -/** comparator for sorting */ -/*int -slv2_plugin_compare_by_uri(const void* a, const void* b) -{ - SLV2Plugin plugin_a = *(SLV2Plugin*)a; - SLV2Plugin plugin_b = *(SLV2Plugin*)b; - - return strcmp((const char*)librdf_uri_as_string(plugin_a->plugin_uri), - (const char*)librdf_uri_as_string(plugin_b->plugin_uri)); -} -*/ - -void -slv2_model_load_all(SLV2Model model) -{ - char* lv2_path = getenv("LV2_PATH"); - - // Read all manifest files - if (lv2_path) { - slv2_model_load_path(model, lv2_path); - } else { - const char* const home = getenv("HOME"); - const char* const suffix = "/.lv2:/usr/local/lib/lv2:usr/lib/lv2"; - lv2_path = slv2_strjoin(home, suffix, NULL); - - //fprintf(stderr, "$LV2_PATH is unset. Using default path %s\n", lv2_path); - - slv2_model_load_path(model, lv2_path); - - free(lv2_path); - } - - - // Find all plugins and associated data files - unsigned char* query_string = (unsigned char*) - "PREFIX : \n" - "PREFIX rdfs: \n" - "SELECT DISTINCT ?plugin ?data ?binary\n" - "WHERE { ?plugin a :Plugin; rdfs:seeAlso ?data\n" - "OPTIONAL { ?plugin :binary ?binary } }\n" - "ORDER BY ?plugin\n"; - - librdf_query* q = librdf_new_query(model->world, "sparql", - NULL, query_string, NULL); - - librdf_query_results* results = librdf_query_execute(q, model->model); - - while (!librdf_query_results_finished(results)) { - - librdf_node* plugin_node = librdf_query_results_get_binding_value(results, 0); - librdf_uri* plugin_uri = librdf_node_get_uri(plugin_node); - librdf_node* data_node = librdf_query_results_get_binding_value(results, 1); - librdf_uri* data_uri = librdf_node_get_uri(data_node); - librdf_node* binary_node = librdf_query_results_get_binding_value(results, 2); - librdf_uri* binary_uri = librdf_node_get_uri(binary_node); - - SLV2Plugin plugin = slv2_plugins_get_by_uri(model->plugins, - (const char*)librdf_uri_as_string(plugin_uri)); - - // Create a new SLV2Plugin - if (!plugin) - plugin = slv2_plugin_new(model, plugin_uri, - (const char*)librdf_uri_as_string(binary_uri)); - - plugin->model = model; - - // FIXME: check for duplicates - raptor_sequence_push(plugin->data_uris, librdf_new_uri_from_uri(data_uri)); - - raptor_sequence_push(model->plugins, plugin); - - librdf_free_node(plugin_node); - librdf_free_node(data_node); - - librdf_query_results_next(results); - } - - // ORDER BY should (and appears to actually) guarantee this - //raptor_sequence_sort(model->plugins, slv2_plugin_compare_by_uri); - - if (results) - librdf_free_query_results(results); - - librdf_free_query(q); -} - - -#if 0 -void -slv2_model_serialize(const char* filename) -{ - librdf_uri* lv2_uri = librdf_new_uri(slv2_rdf_world, - (unsigned char*)"http://lv2plug.in/ontology#"); - - librdf_uri* rdfs_uri = librdf_new_uri(slv2_rdf_world, - (unsigned char*)"http://www.w3.org/2000/01/rdf-schema#"); - - // Write out test file - librdf_serializer* serializer = librdf_new_serializer(slv2_rdf_world, - "turtle", NULL, NULL); - librdf_serializer_set_namespace(serializer, lv2_uri, ""); - librdf_serializer_set_namespace(serializer, rdfs_uri, "rdfs"); - librdf_serializer_serialize_model_to_file(serializer, filename, NULL, slv2_model); - librdf_free_serializer(serializer); -} -#endif - - -SLV2Plugins -slv2_model_get_all_plugins(SLV2Model model) -{ - // FIXME: Slow.. - - // NULL deleter so user can free returned sequence without nuking - // our locally stored plugins - raptor_sequence* result = raptor_new_sequence(NULL, NULL); - - for (int i=0; i < raptor_sequence_size(model->plugins); ++i) - raptor_sequence_push(result, raptor_sequence_get_at(model->plugins, i)); - - // sorted? - - return result; -} - - -SLV2Plugins -slv2_model_get_plugins_by_filter(SLV2Model model, bool (*include)(SLV2Plugin)) -{ - SLV2Plugins all = slv2_model_get_all_plugins(model); - SLV2Plugins result = slv2_plugins_new(); - - for (int i=0; i < raptor_sequence_size(all); ++i) { - SLV2Plugin p = raptor_sequence_get_at(all, i); - if (include(p)) - raptor_sequence_push(result, slv2_plugin_duplicate(p)); - } - - slv2_plugins_free(all); - return result; -} - - -#if 0 -SLV2Plugins -slv2_model_get_plugins_by_query(SLV2Model model, const char* query) -{ - SLV2Plugins list = slv2_plugins_new(); - - librdf_query* rq = librdf_new_query(model->world, "sparql", - NULL, (const unsigned char*)query, NULL); - - librdf_query_results* results = librdf_query_execute(rq, model->model); - - while (!librdf_query_results_finished(results)) { - librdf_node* plugin_node = librdf_query_results_get_binding_value(results, 0); - librdf_uri* plugin_uri = librdf_node_get_uri(plugin_node); - - SLV2Plugin plugin = slv2_plugins_get_by_uri(list, - (const char*)librdf_uri_as_string(plugin_uri)); - - /* Create a new SLV2Plugin */ - if (!plugin) { - SLV2Plugin new_plugin = slv2_plugin_new(model, plugin_uri); - raptor_sequence_push(list, new_plugin); - } - - librdf_free_node(plugin_node); - - librdf_query_results_next(results); - } - - if (results) - librdf_free_query_results(results); - - librdf_free_query(rq); - - return list; -} -#endif - diff --git a/src/plugin.c b/src/plugin.c index ab36caf..b3577f2 100644 --- a/src/plugin.c +++ b/src/plugin.c @@ -31,10 +31,10 @@ /* private */ SLV2Plugin -slv2_plugin_new(SLV2Model model, librdf_uri* uri, const char* binary_uri) +slv2_plugin_new(SLV2World world, librdf_uri* uri, const char* binary_uri) { struct _Plugin* plugin = malloc(sizeof(struct _Plugin)); - plugin->model = model; + plugin->world = world; plugin->plugin_uri = librdf_new_uri_from_uri(uri); plugin->binary_uri = strdup(binary_uri); plugin->data_uris = raptor_new_sequence((void (*)(void*))&raptor_free_uri, NULL); @@ -84,11 +84,9 @@ slv2_plugin_query(SLV2Plugin plugin, SLV2Plugin slv2_plugin_duplicate(SLV2Plugin p) { - fprintf(stderr, "FIXME: duplicate\n"); - assert(p); struct _Plugin* result = malloc(sizeof(struct _Plugin)); - result->model = p->model; + result->world = p->world; result->plugin_uri = librdf_new_uri_from_uri(p->plugin_uri); //result->bundle_url = strdup(p->bundle_url); @@ -102,7 +100,6 @@ slv2_plugin_duplicate(SLV2Plugin p) for (int i=0; i < raptor_sequence_size(p->ports); ++i) raptor_sequence_push(result->ports, slv2_port_duplicate(raptor_sequence_get_at(p->ports, i))); - result->ports = NULL; result->storage = NULL; result->rdf = NULL; @@ -133,15 +130,15 @@ slv2_plugin_load(SLV2Plugin p) if (!p->storage) { assert(!p->rdf); - p->storage = librdf_new_storage(p->model->world, "hashes", NULL, + p->storage = librdf_new_storage(p->world->world, "hashes", NULL, "hash-type='memory'"); - p->rdf = librdf_new_model(p->model->world, p->storage, NULL); + p->rdf = librdf_new_model(p->world->world, p->storage, NULL); } // Parse all the plugin's data files into RDF model for (int i=0; i < raptor_sequence_size(p->data_uris); ++i) { librdf_uri* data_uri = raptor_sequence_get_at(p->data_uris, i); - librdf_parser_parse_into_model(p->model->parser, data_uri, NULL, p->rdf); + librdf_parser_parse_into_model(p->world->parser, data_uri, NULL, p->rdf); } // Load ports @@ -153,7 +150,7 @@ slv2_plugin_load(SLV2Plugin p) " :index ?index .\n" "}"; - librdf_query* q = librdf_new_query(p->model->world, "sparql", + librdf_query* q = librdf_new_query(p->world->world, "sparql", NULL, query, p->plugin_uri); librdf_query_results* results = librdf_query_execute(q, p->rdf); diff --git a/src/private_types.h b/src/private_types.h index 12f74cb..8f2f89d 100644 --- a/src/private_types.h +++ b/src/private_types.h @@ -48,8 +48,7 @@ void slv2_port_free(SLV2Port port); * paths of relevant files, the actual data therein isn't loaded into memory. */ struct _Plugin { - int deletable; - struct _Model* model; + struct _World* world; librdf_uri* plugin_uri; // char* bundle_url; // Bundle directory plugin was loaded from char* binary_uri; // lv2:binary @@ -59,7 +58,7 @@ struct _Plugin { librdf_model* rdf; }; -SLV2Plugin slv2_plugin_new(SLV2Model model, librdf_uri* uri, const char* binary_uri); +SLV2Plugin slv2_plugin_new(SLV2World world, librdf_uri* uri, const char* binary_uri); void slv2_plugin_load(SLV2Plugin p); @@ -77,7 +76,7 @@ struct _InstanceImpl { /** Model of LV2 (RDF) data loaded from bundles. */ -struct _Model { +struct _World { librdf_world* world; librdf_storage* storage; librdf_model* model; diff --git a/src/query.c b/src/query.c index 7127a8d..968834c 100644 --- a/src/query.c +++ b/src/query.c @@ -124,7 +124,7 @@ slv2_plugin_query(SLV2Plugin plugin, //printf("******** Query \n%s********\n", query_str); - librdf_query *rq = librdf_new_query(plugin->model->world, "sparql", NULL, + librdf_query *rq = librdf_new_query(plugin->world->world, "sparql", NULL, (const unsigned char*)query_str, base_uri); if (!rq) { @@ -200,7 +200,7 @@ slv2_query_count_results(SLV2Plugin p, assert(p); assert(query_str); - librdf_query *rq = librdf_new_query(p->model->world, "sparql", NULL, + librdf_query *rq = librdf_new_query(p->world->world, "sparql", NULL, (unsigned char*)query_str, NULL); //printf("Query: \n%s\n\n", query_str); @@ -209,7 +209,7 @@ slv2_query_count_results(SLV2Plugin p, //librdf_query_add_data_graph(rq, slv2_ontology_uri, // NULL, RASQAL_DATA_GRAPH_BACKGROUND); - librdf_query_results* results = librdf_query_execute(rq, p->model->model); + librdf_query_results* results = librdf_query_execute(rq, p->world->model); assert(results); size_t count = slv2_query_count_bindings(results); diff --git a/src/world.c b/src/world.c new file mode 100644 index 0000000..afb71ad --- /dev/null +++ b/src/world.c @@ -0,0 +1,321 @@ +/* SLV2 + * Copyright (C) 2007 Dave Robillard + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include "config.h" +#include "private_types.h" + + +SLV2World +slv2_world_new() +{ + struct _World* world = (struct _World*)malloc(sizeof(struct _World)); + + world->world = librdf_new_world(); + librdf_world_open(world->world); + + world->storage = librdf_new_storage(world->world, "hashes", NULL, + "hash-type='memory'"); + + world->model = librdf_new_model(world->world, world->storage, NULL); + + world->parser = librdf_new_parser(world->world, "turtle", NULL, NULL); + + world->plugins = slv2_plugins_new(); + + /*slv2_ontology_uri = raptor_new_uri((const unsigned char*) + "file://" LV2_TTL_PATH);*/ + + return world; +} + + +void +slv2_world_free(SLV2World world) +{ + /*raptor_free_uri(slv2_ontology_uri); + slv2_ontology_uri = NULL;*/ + + slv2_plugins_free(world->plugins); + world->plugins = NULL; + + librdf_free_parser(world->parser); + world->parser = NULL; + + librdf_free_model(world->model); + world->model = NULL; + + librdf_free_storage(world->storage); + world->storage = NULL; + + librdf_free_world(world->world); + world->world = NULL; + + free(world); +} + + +/* private */ +void +slv2_world_load_directory(SLV2World world, 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_uri_str = slv2_strjoin("file://", dir, "/", pfile->d_name, "/", NULL); + librdf_uri* bundle_uri = librdf_new_uri(world->world, (unsigned char*)bundle_uri_str); + + DIR* bundle_dir = opendir(bundle_uri_str + 7); + + if (bundle_dir != NULL) { + closedir(bundle_dir); + + librdf_uri* manifest_uri = librdf_new_uri_relative_to_base( + bundle_uri, (const unsigned char*)"manifest.ttl"); + + librdf_parser_parse_into_model(world->parser, manifest_uri, NULL, world->model); + + librdf_free_uri(manifest_uri); + } + + free(bundle_uri_str); + librdf_free_uri(bundle_uri); + } + + closedir(pdir); +} + + +void +slv2_world_load_path(SLV2World world, + const char* lv2_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. + while (strchr(path, ':') != NULL) { + char* delim = strchr(path, ':'); + *delim = '\0'; + + slv2_world_load_directory(world, dir); + + *delim = 'X'; + dir = delim + 1; + } + + free(path); +} + + +/** comparator for sorting */ +/*int +slv2_plugin_compare_by_uri(const void* a, const void* b) +{ + SLV2Plugin plugin_a = *(SLV2Plugin*)a; + SLV2Plugin plugin_b = *(SLV2Plugin*)b; + + return strcmp((const char*)librdf_uri_as_string(plugin_a->plugin_uri), + (const char*)librdf_uri_as_string(plugin_b->plugin_uri)); +} +*/ + +void +slv2_world_load_all(SLV2World world) +{ + char* lv2_path = getenv("LV2_PATH"); + + // Read all manifest files + if (lv2_path) { + slv2_world_load_path(world, lv2_path); + } else { + const char* const home = getenv("HOME"); + const char* const suffix = "/.lv2:/usr/local/lib/lv2:usr/lib/lv2"; + lv2_path = slv2_strjoin(home, suffix, NULL); + + //fprintf(stderr, "$LV2_PATH is unset. Using default path %s\n", lv2_path); + + slv2_world_load_path(world, lv2_path); + + free(lv2_path); + } + + + // Find all plugins and associated data files + unsigned char* query_string = (unsigned char*) + "PREFIX : \n" + "PREFIX rdfs: \n" + "SELECT DISTINCT ?plugin ?data ?binary\n" + "WHERE { ?plugin a :Plugin; rdfs:seeAlso ?data\n" + "OPTIONAL { ?plugin :binary ?binary } }\n" + "ORDER BY ?plugin\n"; + + librdf_query* q = librdf_new_query(world->world, "sparql", + NULL, query_string, NULL); + + librdf_query_results* results = librdf_query_execute(q, world->model); + + while (!librdf_query_results_finished(results)) { + + librdf_node* plugin_node = librdf_query_results_get_binding_value(results, 0); + librdf_uri* plugin_uri = librdf_node_get_uri(plugin_node); + librdf_node* data_node = librdf_query_results_get_binding_value(results, 1); + librdf_uri* data_uri = librdf_node_get_uri(data_node); + librdf_node* binary_node = librdf_query_results_get_binding_value(results, 2); + librdf_uri* binary_uri = librdf_node_get_uri(binary_node); + + SLV2Plugin plugin = slv2_plugins_get_by_uri(world->plugins, + (const char*)librdf_uri_as_string(plugin_uri)); + + // Create a new SLV2Plugin + if (!plugin) + plugin = slv2_plugin_new(world, plugin_uri, + (const char*)librdf_uri_as_string(binary_uri)); + + plugin->world = world; + + // FIXME: check for duplicates + raptor_sequence_push(plugin->data_uris, librdf_new_uri_from_uri(data_uri)); + + raptor_sequence_push(world->plugins, plugin); + + librdf_free_node(plugin_node); + librdf_free_node(data_node); + + librdf_query_results_next(results); + } + + // ORDER BY should (and appears to actually) guarantee this + //raptor_sequence_sort(world->plugins, slv2_plugin_compare_by_uri); + + if (results) + librdf_free_query_results(results); + + librdf_free_query(q); +} + + +#if 0 +void +slv2_world_serialize(const char* filename) +{ + librdf_uri* lv2_uri = librdf_new_uri(slv2_rdf_world, + (unsigned char*)"http://lv2plug.in/ontology#"); + + librdf_uri* rdfs_uri = librdf_new_uri(slv2_rdf_world, + (unsigned char*)"http://www.w3.org/2000/01/rdf-schema#"); + + // Write out test file + librdf_serializer* serializer = librdf_new_serializer(slv2_rdf_world, + "turtle", NULL, NULL); + librdf_serializer_set_namespace(serializer, lv2_uri, ""); + librdf_serializer_set_namespace(serializer, rdfs_uri, "rdfs"); + librdf_serializer_serialize_world_to_file(serializer, filename, NULL, slv2_model); + librdf_free_serializer(serializer); +} +#endif + + +SLV2Plugins +slv2_world_get_all_plugins(SLV2World world) +{ + // FIXME: Slow.. + + // NULL deleter so user can free returned sequence without nuking + // our locally stored plugins + raptor_sequence* result = raptor_new_sequence(NULL, NULL); + + for (int i=0; i < raptor_sequence_size(world->plugins); ++i) + raptor_sequence_push(result, raptor_sequence_get_at(world->plugins, i)); + + // sorted? + + return result; +} + + +SLV2Plugins +slv2_world_get_plugins_by_filter(SLV2World world, bool (*include)(SLV2Plugin)) +{ + SLV2Plugins all = slv2_world_get_all_plugins(world); + SLV2Plugins result = slv2_plugins_new(); + + for (int i=0; i < raptor_sequence_size(all); ++i) { + SLV2Plugin p = raptor_sequence_get_at(all, i); + if (include(p)) + raptor_sequence_push(result, slv2_plugin_duplicate(p)); + } + + slv2_plugins_free(all); + return result; +} + + +#if 0 +SLV2Plugins +slv2_world_get_plugins_by_query(SLV2World world, const char* query) +{ + SLV2Plugins list = slv2_plugins_new(); + + librdf_query* rq = librdf_new_query(world->world, "sparql", + NULL, (const unsigned char*)query, NULL); + + librdf_query_results* results = librdf_query_execute(rq, world->model); + + while (!librdf_query_results_finished(results)) { + librdf_node* plugin_node = librdf_query_results_get_binding_value(results, 0); + librdf_uri* plugin_uri = librdf_node_get_uri(plugin_node); + + SLV2Plugin plugin = slv2_plugins_get_by_uri(list, + (const char*)librdf_uri_as_string(plugin_uri)); + + /* Create a new SLV2Plugin */ + if (!plugin) { + SLV2Plugin new_plugin = slv2_plugin_new(world, plugin_uri); + raptor_sequence_push(list, new_plugin); + } + + librdf_free_node(plugin_node); + + librdf_query_results_next(results); + } + + if (results) + librdf_free_query_results(results); + + librdf_free_query(rq); + + return list; +} +#endif + diff --git a/utils/lv2_inspect.c b/utils/lv2_inspect.c index 593cc00..a6a949d 100644 --- a/utils/lv2_inspect.c +++ b/utils/lv2_inspect.c @@ -138,15 +138,15 @@ print_plugin(SLV2Plugin p) int main(int argc, char** argv) { - SLV2Model model = slv2_model_new(); - slv2_model_load_all(model); + SLV2World world = slv2_world_new(); + slv2_world_load_all(world); if (argc != 2) { fprintf(stderr, "Usage: %s PLUGIN_URI\n", argv[0]); return -1; } - SLV2Plugins plugins = slv2_model_get_all_plugins(model); + SLV2Plugins plugins = slv2_world_get_all_plugins(world); SLV2Plugin p = slv2_plugins_get_by_uri(plugins, argv[1]); @@ -158,7 +158,7 @@ main(int argc, char** argv) } slv2_plugins_free(plugins); - slv2_model_free(model); + slv2_world_free(world); return (p != NULL ? 0 : -1); } diff --git a/utils/lv2_list.c b/utils/lv2_list.c index 5c2a1dd..56afe4a 100644 --- a/utils/lv2_list.c +++ b/utils/lv2_list.c @@ -33,15 +33,15 @@ list_plugins(SLV2Plugins list) int main()//int argc, char** argv) { - SLV2Model model = slv2_model_new(); - slv2_model_load_all(model); + SLV2World world = slv2_world_new(); + slv2_world_load_all(world); - SLV2Plugins plugins = slv2_model_get_all_plugins(model); + SLV2Plugins plugins = slv2_world_get_all_plugins(world); list_plugins(plugins); slv2_plugins_free(plugins); - slv2_model_free(model); + slv2_world_free(world); return 0; } -- cgit v1.2.1