[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Traverso-commit] traverso/src/3rdparty/slv2 slv2/lv2.h slv2/plug...
From: |
Remon Sijrier |
Subject: |
[Traverso-commit] traverso/src/3rdparty/slv2 slv2/lv2.h slv2/plug... |
Date: |
Mon, 23 Apr 2007 11:59:22 +0000 |
CVSROOT: /sources/traverso
Module name: traverso
Changes by: Remon Sijrier <r_sijrier> 07/04/23 11:59:22
Added files:
src/3rdparty/slv2/slv2: lv2.h plugin.h plugininstance.h
pluginlist.h port.h slv2.h stringlist.h
types.h util.h world.h
src/3rdparty/slv2/src: plugin.c plugininstance.c pluginlist.c
port.c private_types.h query.c
stringlist.c util.c world.c
Log message:
* imported slv2 source
CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/traverso/src/3rdparty/slv2/slv2/lv2.h?cvsroot=traverso&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/traverso/src/3rdparty/slv2/slv2/plugin.h?cvsroot=traverso&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/traverso/src/3rdparty/slv2/slv2/plugininstance.h?cvsroot=traverso&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/traverso/src/3rdparty/slv2/slv2/pluginlist.h?cvsroot=traverso&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/traverso/src/3rdparty/slv2/slv2/port.h?cvsroot=traverso&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/traverso/src/3rdparty/slv2/slv2/slv2.h?cvsroot=traverso&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/traverso/src/3rdparty/slv2/slv2/stringlist.h?cvsroot=traverso&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/traverso/src/3rdparty/slv2/slv2/types.h?cvsroot=traverso&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/traverso/src/3rdparty/slv2/slv2/util.h?cvsroot=traverso&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/traverso/src/3rdparty/slv2/slv2/world.h?cvsroot=traverso&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/traverso/src/3rdparty/slv2/src/plugin.c?cvsroot=traverso&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/traverso/src/3rdparty/slv2/src/plugininstance.c?cvsroot=traverso&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/traverso/src/3rdparty/slv2/src/pluginlist.c?cvsroot=traverso&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/traverso/src/3rdparty/slv2/src/port.c?cvsroot=traverso&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/traverso/src/3rdparty/slv2/src/private_types.h?cvsroot=traverso&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/traverso/src/3rdparty/slv2/src/query.c?cvsroot=traverso&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/traverso/src/3rdparty/slv2/src/stringlist.c?cvsroot=traverso&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/traverso/src/3rdparty/slv2/src/util.c?cvsroot=traverso&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/traverso/src/3rdparty/slv2/src/world.c?cvsroot=traverso&rev=1.1
Patches:
Index: slv2/lv2.h
===================================================================
RCS file: slv2/lv2.h
diff -N slv2/lv2.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ slv2/lv2.h 23 Apr 2007 11:59:21 -0000 1.1
@@ -0,0 +1,389 @@
+/* LV2 - LADSPA (Linux Audio Developer's Simple Plugin API) Version 2.0
+ * *** PROVISIONAL ***
+ *
+ * Copyright (C) 2000-2002 Richard W.E. Furse, Paul Barton-Davis,
+ * Stefan Westerfeld
+ * Copyright (C) 2006-2007 Steve Harris, Dave Robillard.
+ *
+ * This header is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License,
+ * or (at your option) any later version.
+ *
+ * This header 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+ * USA.
+ */
+
+#ifndef LV2_H_INCLUDED
+#define LV2_H_INCLUDED
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* ************************************************************************* */
+
+
+/** @file lv2.h
+ *
+ * Revision: 1.0beta1
+ *
+ * == Overview ==
+ *
+ * There are a large number of open source and free software synthesis
+ * packages in use or development at this time. This API ('LV2')
+ * attempts to give programmers the ability to write simple 'plugin'
+ * audio processors in C/C++ and link them dynamically ('plug') into
+ * a range of these packages ('hosts'). It should be possible for any
+ * host and any plugin to communicate completely through this interface.
+ *
+ * This API is deliberately as short and simple as possible.
+ * The information required to use a plugin is in a companion data
+ * (RDF) file. The shared library portion of the API (defined in this
+ * header) does not contain enough information to make use of the plugin
+ * possible - the data file is mandatory.
+ *
+ * Plugins are expected to distinguish between control rate and audio
+ * rate data. Plugins have 'ports' that are inputs or outputs for audio
+ * or control data and each plugin is 'run' for a 'block' corresponding
+ * to a short time interval measured in samples. Audio rate data is
+ * communicated using arrays with one element per sample processed,
+ * allowing a block of audio to be processed by the plugin in a single
+ * pass. Control rate data is communicated using single values. Control
+ * rate data has a single value at the start of a call to the 'run()'
+ * function, and may be considered to remain this value for its duration.
+ * Thus the 'control rate' is determined by the block size, controlled
+ * by the host. The plugin may assume that all its input and output
+ * ports have been connected to the relevant data location (see the
+ * 'connect_port()' function below) before it is asked to run.
+ *
+ * Plugins will reside in shared object files suitable for dynamic linking
+ * by dlopen() and family. The file will provide a number of 'plugin
+ * types' that can be used to instantiate actual plugins (sometimes known
+ * as 'plugin instances') that can be connected together to perform tasks.
+ * The host can access these plugin types using the lv2_descriptor()
+ * function.
+ *
+ * This API contains very limited error-handling.
+ *
+ * == Threading rules ==
+ *
+ * Certain hosts may need to call the functions provided by a plugin from
+ * multiple threads. For this to be safe, the plugin must be written so that
+ * those functions can be executed simultaneously without problems.
+ * To facilitate this, the functions provided by a plugin are divided into
+ * classes:
+ *
+ * - Audio class: run(), connect_port()
+ * - Instantiation class: instantiate(), cleanup(),
+ * activate(), deactivate()
+ *
+ * Extensions to this specification which add new functions MUST declare in
+ * which of these classes the functions belong, or define new classes for them.
+ * The rules that hosts must follow are these:
+ *
+ * - When a function from the Instantiation class is running for a plugin
+ * instance, no other functions for that instance may run.
+ * - When a function is running for a plugin instance, no other
+ * function in the same class may run for that instance.
+ *
+ * Any simultaneous calls that are not explicitly forbidden by these rules
+ * are allowed. For example, a host may call run() for two different plugin
+ * instances simultaneously.
+ *
+ * The extension_data() function and the lv2_descriptor() function are never
+ * associated with any plugin instances and may be called at any time.
+ */
+
+
+/* ************************************************************************* */
+
+
+/** Plugin Handle.
+ *
+ * This plugin handle indicates a particular instance of the plugin
+ * concerned. It is valid to compare this to NULL (0 for C++) but
+ * otherwise the host MUST NOT attempt to interpret it. The plugin
+ * may use it to reference internal instance data. */
+typedef void * LV2_Handle;
+
+
+/* ************************************************************************* */
+
+
+/** Host feature.
+ *
+ * These are passed to a plugin's instantiate method to represent a special
+ * feature the host has which the plugin may depend on. This is to allow
+ * extensions to the LV2 specification without causing any breakage. The base
+ * LV2 specification does not define any host features; hosts are not required
+ * to use this facility.
+ */
+typedef struct _LV2_Host_Feature {
+ /** A globally unique, case-sensitive identifier for this feature.
+ *
+ * This MUST be defined in the specification of any LV2 extension which
+ * defines a host feature.
+ */
+ const char * URI;
+
+ /** Pointer to arbitrary data.
+ *
+ * This is to allow hosts to pass data to a plugin (simple values, data
+ * structures, function pointers, etc) as part of a 'feature'. The LV2
+ * specification makes no restrictions on the contents of this data.
+ * The data here MUST be cleary defined by the LV2 extension which
defines
+ * this feature.
+ * If no data is required, this may be set to NULL.
+ */
+ void * data;
+} LV2_Host_Feature;
+
+
+/* ************************************************************************* */
+
+
+/** Descriptor for a Type of Plugin.
+ *
+ * This structure is used to describe a plugin type. It provides a number
+ * of functions to instantiate it, link it to buffers and run it. */
+typedef struct _LV2_Descriptor {
+
+ /** A globally unique, case-sensitive identifier for this plugin type.
+ *
+ * All plugins with the same URI MUST be compatible in terms of 'port
+ * signature', meaning they have the same number of ports, same port
+ * shortnames, and roughly the same functionality. URIs should
+ * probably contain a version number (or similar) for this reason.
+ *
+ * Rationale: When serializing session/patch/etc files, hosts MUST
+ * refer to a loaded plugin by the plugin URI only. In the future
+ * loading a plugin with this URI MUST yield a plugin with the
+ * same ports (etc) which is 100% compatible. */
+ const char * URI;
+
+ /** Function pointer that instantiates a plugin.
+ *
+ * A handle is returned indicating the new plugin instance. The
+ * instantiation function accepts a sample rate as a parameter as well
+ * as the plugin descriptor from which this instantiate function was
+ * found. This function must return NULL if instantiation fails.
+ *
+ * BundlePath is a string of the path to the LV2 bundle which contains
+ * this plugin binary. It MUST include the trailing directory separator
+ * (e.g. '/') so that BundlePath + filename gives the path to a file
+ * in the bundle.
+ *
+ * HostFeatures is a NULL terminated array of the URIs of the LV2
+ * features that the host supports. Plugins may refuse to instantiate
+ * if required features are not found here (however hosts SHOULD NOT use
+ * this as a discovery mechanism, instead reading the data file before
+ * attempting to instantiate the plugin). This array must always exist;
+ * if a host has no features, it MUST pass a single element array
+ * containing NULL (to simplify plugins).
+ *
+ * Note that instance initialisation should generally occur in
+ * activate() rather than here. If a host calls instantiate, it MUST
+ * call cleanup() at some point in the future. */
+ LV2_Handle (*instantiate)(const struct _LV2_Descriptor * Descriptor,
+ uint32_t SampleRate,
+ const char * BundlePath,
+ const LV2_Host_Feature *const * HostFeatures);
+
+ /** Function pointer that connects a port on a plugin instance to a memory
+ * location where the block of data for the port will be read/written.
+ *
+ * The data location is expected to be of the type defined in the
+ * plugin's data file (e.g. an array of float for an lv2:AudioPort).
+ * Memory issues are managed by the host. The plugin must read/write
+ * the data at these locations every time run() is called, data
+ * present at the time of this connection call MUST NOT be
+ * considered meaningful.
+ *
+ * connect_port() may be called more than once for a plugin instance
+ * to allow the host to change the buffers that the plugin is reading
+ * or writing. These calls may be made before or after activate()
+ * or deactivate() calls. Note that there may be realtime constraints
+ * on connect_port (see lv2:hardRTCapable in lv2.ttl).
+ *
+ * connect_port() MUST be called at least once for each port before
+ * run() is called. The plugin must pay careful attention to the block
+ * size passed to the run function as the block allocated may only just
+ * be large enough to contain the block of data (typically samples), and
+ * is not guaranteed to be constant.
+ *
+ * Plugin writers should be aware that the host may elect to use the
+ * same buffer for more than one port and even use the same buffer for
+ * both input and output (see lv2:inPlaceBroken in lv2.ttl).
+ * However, overlapped buffers or use of a single buffer for both
+ * audio and control data may result in unexpected behaviour.
+ *
+ * If the plugin has the property lv2:hardRTCapable then there are
+ * various things that the plugin MUST NOT do within the connect_port()
+ * function (see lv2.ttl). */
+ void (*connect_port)(LV2_Handle Instance,
+ uint32_t Port,
+ void * DataLocation);
+
+ /** Function pointer that initialises a plugin instance and activates
+ * it for use.
+ *
+ * This is separated from instantiate() to aid real-time support and so
+ * that hosts can reinitialise a plugin instance by calling deactivate()
+ * and then activate(). In this case the plugin instance must reset all
+ * state information dependent on the history of the plugin instance
+ * except for any data locations provided by connect_port(). If there
+ * is nothing for activate() to do then the plugin writer may provide
+ * a NULL rather than an empty function.
+ *
+ * When present, hosts MUST call this function once before run()
+ * is called for the first time. This call SHOULD be made as close
+ * to the run() call as possible and indicates to real-time plugins
+ * that they are now live, however plugins MUST NOT rely on a prompt
+ * call to run() after activate(). activate() may not be called again
+ * unless deactivate() is called first (after which activate() may be
+ * called again, followed by deactivate, etc. etc.). If a host calls
+ * activate, it MUST call deactivate at some point in the future.
+ *
+ * Note that connect_port() may be called before or after a call to
+ * activate(). */
+ void (*activate)(LV2_Handle Instance);
+
+ /** Function pointer that runs a plugin instance for a block.
+ *
+ * Two parameters are required: the first is a handle to the particular
+ * instance to be run and the second indicates the block size (in
+ * samples) for which the plugin instance may run.
+ *
+ * Note that if an activate() function exists then it must be called
+ * before run(). If deactivate() is called for a plugin instance then
+ * the plugin instance may not be reused until activate() has been
+ * called again.
+ *
+ * If the plugin has the property lv2:hardRTCapable then there are
+ * various things that the plugin MUST NOT do within the run()
+ * function (see lv2.ttl). */
+ void (*run)(LV2_Handle Instance,
+ uint32_t SampleCount);
+
+ /** This is the counterpart to activate() (see above). If there is
+ * nothing for deactivate() to do then the plugin writer may provide
+ * a NULL rather than an empty function.
+ *
+ * Hosts must deactivate all activated units after they have been run()
+ * for the last time. This call SHOULD be made as close to the last
+ * run() call as possible and indicates to real-time plugins that
+ * they are no longer live, however plugins MUST NOT rely on prompt
+ * deactivation. Note that connect_port() may be called before or
+ * after a call to deactivate().
+ *
+ * Note that deactivation is not similar to pausing as the plugin
+ * instance will be reinitialised when activate() is called to reuse it.
+ * Hosts MUST NOT call deactivate() unless activate() was previously
+ * called. */
+ void (*deactivate)(LV2_Handle Instance);
+
+ /** This is the counterpart to instantiate() (see above). Once an instance
+ * of a plugin has been finished with it can be deleted using this
+ * function. The instance handle passed ceases to be valid after
+ * this call.
+ *
+ * If activate() was called for a plugin instance then a corresponding
+ * call to deactivate() MUST be made before cleanup() is called.
+ * Hosts MUST NOT call cleanup() unless instantiate() was previously
+ * called. */
+ void (*cleanup)(LV2_Handle Instance);
+
+ /** Function pointer that can be used to return additional instance data for
+ * a plugin defined by some extenion (e.g. a struct containing additional
+ * function pointers).
+ *
+ * The actual type and meaning of the returned object MUST be specified
+ * precisely by the extension if it defines any extra data. If a particular
+ * extension does not define extra instance data, this function MUST return
+ * NULL for that extension's URI. If a plugin does not support any
+ * extensions that define extra instance data, this function pointer may be
+ * set to NULL rather than providing an empty function.
+ *
+ * The only parameter is the URI of the extension. The plugin MUST return
+ * NULL if it does not support the extension, but hosts SHOULD NOT use this
+ * as a discovery method (e.g. hosts should only call this function for
+ * extensions known to be supported by the plugin from the data file).
+ *
+ * NOTE: It is highly recommended that this function returns a struct, and
+ * NOT a direct function pointer. Standard C++ (for real reasons) does not
+ * allow type casts from void* to a function pointer type. To provide
+ * additional functions a struct should be returned containing the extra
+ * function pointers (which is valid standard C++, and a much better idea
+ * for extensibility anyway).
+ */
+ void* (*extension_data)(const char * URI);
+
+} LV2_Descriptor;
+
+
+/* ****************************************************************** */
+
+
+/** Accessing Plugin Types.
+ *
+ * The exact mechanism by which plugins are loaded is host-dependent,
+ * however all most hosts will need to know is the URI of the plugin they
+ * wish to load. The environment variable LV2_PATH, if present, should
+ * contain a colon-separated path indicating directories (containing
+ * plugin bundle subdirectories) that should be searched (in order)
+ * for plugins. It is expected that hosts will use a library to provide
+ * this functionality.
+ *
+ * A plugin programmer must include a function called "lv2_descriptor"
+ * with the following function prototype within the shared object
+ * file. This function will have C-style linkage (if you are using
+ * C++ this is taken care of by the 'extern "C"' clause at the top of
+ * the file).
+ *
+ * A host will find the plugin shared object file by one means or another,
+ * find the lv2_descriptor() function, call it, and proceed from there.
+ *
+ * Plugin types are accessed by index (not ID) using values from 0
+ * upwards. Out of range indexes must result in this function returning
+ * NULL, so the plugin count can be determined by checking for the least
+ * index that results in NULL being returned. Index has no meaning,
+ * hosts MUST NOT depend on it remaining constant (ie when serialising)
+ * in any way. */
+const LV2_Descriptor * lv2_descriptor(uint32_t Index);
+
+
+/** Datatype corresponding to the lv2_descriptor() function. */
+typedef const LV2_Descriptor *
+(*LV2_Descriptor_Function)(uint32_t Index);
+
+
+/* ******************************************************************** */
+
+
+/* Put this (LV2_SYMBOL_EXPORT) before any functions that are to be loaded
+ * by the host as a symbol from the dynamic library.
+ */
+#ifdef WIN32
+#define LV2_SYMBOL_EXPORT __declspec(dllexport)
+#else
+#define LV2_SYMBOL_EXPORT
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LV2_H_INCLUDED */
+
Index: slv2/plugin.h
===================================================================
RCS file: slv2/plugin.h
diff -N slv2/plugin.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ slv2/plugin.h 23 Apr 2007 11:59:21 -0000 1.1
@@ -0,0 +1,330 @@
+/* SLV2
+ * Copyright (C) 2007 Dave Robillard <http://drobilla.net>
+ *
+ * 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_PLUGIN_H__
+#define __SLV2_PLUGIN_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <slv2/types.h>
+#include <slv2/port.h>
+#include <slv2/stringlist.h>
+
+/** \defgroup data Plugin data access
+ *
+ * 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 contains an in-memory cache of the plugin data, loaded
+ * on demand. Duplicating plugins should be avoided when possible for
+ * performance reasons.
+ *
+ * @{
+ */
+
+
+/** Check if this plugin is valid.
+ *
+ * This is used by plugin lists to avoid loading plugins that are not valid
+ * and will not work with libslv2 (eg plugins missing required fields, or
+ * having multiple values for mandatory single-valued fields, etc.
+ *
+ * Note that normal hosts do NOT need to use this - slv2 does not
+ * load invalid plugins into plugin lists. This is included for plugin
+ * testing utilities, etc.
+ *
+ * \return true if \a plugin is valid.
+ *
+ * Time = Query
+ */
+bool
+slv2_plugin_verify(SLV2Plugin plugin);
+
+
+#if 0
+/** Duplicate a plugin.
+ *
+ * Use this if you want to keep an SLV2Plugin around but free the list it came
+ * from. Freeing the returned plugin with slv2_plugin_free is the caller's
+ * responsibility.
+ *
+ * \return a newly allocated deep copy of \a plugin.
+ */
+SLV2Plugin
+slv2_plugin_duplicate(SLV2Plugin plugin);
+#endif
+
+
+/** Get the URI of \a plugin.
+ *
+ * Any serialization that refers to plugins should refer to them by this.
+ * Hosts SHOULD NOT save any filesystem paths, plugin indexes, etc. in saved
+ * files; save only the URI.
+ *
+ * The URI is a globally unique identifier for one specific plugin. Two
+ * plugins with the same URI are compatible in port signature, and should
+ * be guaranteed to work in a compatible and consistent way. If a plugin
+ * is upgraded in an incompatible way (eg if it has different ports), it
+ * MUST have a different URI than it's predecessor.
+ *
+ * \return a shared string which must not be modified or free()'d.
+ *
+ * Time = O(1)
+ */
+const char*
+slv2_plugin_get_uri(SLV2Plugin plugin);
+
+
+/** Get the (resolvable) URIs of the RDF data files that define a plugin.
+ *
+ * Note this always returns fully qualified URIs. If you want local
+ * filesystem paths, use slv2_uri_to_path.
+ *
+ * \return a list of complete URLs eg. "file:///foo/ABundle.lv2/aplug.ttl",
+ * which is shared and must not be modified or freed.
+ *
+ * Time = O(1)
+ */
+SLV2Strings
+slv2_plugin_get_data_uris(SLV2Plugin plugin);
+
+
+/** Get the (resolvable) URI of the shared library for \a plugin.
+ *
+ * Note this always returns a fully qualified URI. If you want a local
+ * filesystem path, use slv2_uri_to_path.
+ *
+ * \return a shared string which must not be modified or freed.
+ *
+ * Time = O(1)
+ */
+const char*
+slv2_plugin_get_library_uri(SLV2Plugin plugin);
+
+
+
+/** Get the name of \a plugin.
+ *
+ * This is guaranteed to return the untranslated name (the doap:name in the
+ * data file without a language tag). Returned value must be freed by
+ * the caller.
+ *
+ * Time = Query
+ */
+char*
+slv2_plugin_get_name(SLV2Plugin plugin);
+
+
+/** Get a value associated with the plugin in a plugin's data files.
+ *
+ * Returns the ?object of all triples found of the form:
+ *
+ * <code><plugin-uri> predicate ?object</code>
+ *
+ * May return NULL if the property was not found, or if object is not
+ * sensibly represented as an SLV2Strings (e.g. blank nodes).
+ *
+ * Return value must be freed by caller with slv2_strings_free.
+ *
+ * Time = Query
+ */
+SLV2Strings
+slv2_plugin_get_value(SLV2Plugin p,
+ const char* predicate);
+
+
+/** Get a value associated with some subject in a plugin's data files.
+ *
+ * Returns the ?object of all triples found of the form:
+ *
+ * <code>subject predicate ?object</code>
+ *
+ * This can be used to investigate URIs returned by slv2_plugin_get_value
+ * (if information about it is contained in the plugin's data files).
+ *
+ * May return NULL if the property was not found, or if object is not
+ * sensibly represented as an SLV2Strings (e.g. blank nodes).
+ *
+ * Return value must be freed by caller with slv2_strings_free.
+ *
+ * Time = Query
+ */
+SLV2Strings
+slv2_plugin_get_value_for_subject(SLV2Plugin p,
+ const char* subject,
+ const char* predicate);
+
+
+/** Get the LV2 Properties of a plugin.
+ *
+ * LV2 Properties are mandatory. Hosts MUST NOT use a plugin if they do not
+ * understand all the LV2 Properties associated with that plugin (if this is
+ * not what you want, see slv2_plugin_get_hints).
+ *
+ * Return value must be freed by caller with slv2_value_free.
+ *
+ * Time = Query
+ */
+SLV2Strings
+slv2_plugin_get_properties(SLV2Plugin p);
+
+
+/** Get the LV2 Hints of a plugin.
+ *
+ * LV2 Hints are suggestions that may be useful for a host. LV2 Hints may be
+ * ignored and the plugin will still function correctly.
+ *
+ * Return value must be freed by caller with slv2_value_free.
+ *
+ * Time = Query
+ */
+SLV2Strings
+slv2_plugin_get_hints(SLV2Plugin p);
+
+
+/** Get the number of ports on this plugin.
+ *
+ * Time = O(1)
+ */
+uint32_t
+slv2_plugin_get_num_ports(SLV2Plugin p);
+
+
+/** Return whether or not the plugin introduces (and reports) latency.
+ *
+ * The index of the latency port can be found with slv2_plugin_get_latency_port
+ * ONLY if this function returns true.
+ *
+ * Time = Query
+ */
+bool
+slv2_plugin_has_latency(SLV2Plugin p);
+
+
+/** Return the index of the plugin's latency port, or the empty string if the
+ * plugin has no latency.
+ *
+ * It is a fatal error to call this on a plugin without checking if the port
+ * exists by first calling slv2_plugin_has_latency.
+ *
+ * Any plugin that introduces unwanted latency that should be compensated for
+ * (by hosts with the ability/need) MUST provide this port, which is a control
+ * rate output port that reports the latency for each cycle in frames.
+ *
+ * Time = Query
+ */
+uint32_t
+slv2_plugin_get_latency_port(SLV2Plugin p);
+
+
+/** Get a plugin's supported host features / extensions.
+ *
+ * This returns a list of all supported features (both required and optional).
+ *
+ * Time = Query
+ */
+SLV2Strings
+slv2_plugin_get_supported_features(SLV2Plugin p);
+
+
+/** Get a plugin's requires host features / extensions.
+ *
+ * All feature URI's returned by this call MUST be passed to the plugin's
+ * instantiate method for the plugin to instantiate successfully.
+ *
+ * Time = Query
+ */
+SLV2Strings
+slv2_plugin_get_required_features(SLV2Plugin p);
+
+
+/** Get a plugin's optional host features / extensions.
+ *
+ * If the feature URI's returned by this method are passed to the plugin's
+ * instantiate method, those features will be used by the function, otherwise
+ * the plugin will act as it would if it did not support that feature at all.
+ *
+ * Time = Query
+ */
+SLV2Strings
+slv2_plugin_get_optional_features(SLV2Plugin p);
+
+
+/** Query a plugin for a single variable.
+ *
+ * \param plugin The plugin to query.
+ * \param sparql_str A SPARQL SELECT query.
+ * \param variable The variable to return results for.
+ * \return All matches for \a variable.
+ *
+ * Time = Query
+ */
+SLV2Strings
+slv2_plugin_simple_query(SLV2Plugin plugin,
+ const char* sparql_str,
+ const char* variable);
+
+
+/** Query a plugin and return the number of results found.
+ *
+ * \param plugin The plugin to query.
+ * \param sparql_str A SPARQL SELECT query.
+ *
+ * Time = Query
+ */
+unsigned
+slv2_plugin_query_count(SLV2Plugin plugin,
+ const char* sparql_str);
+
+
+/** Get a port on this plugin by \a index.
+ *
+ * To perform multiple calls on a port, the returned value should
+ * be cached and used repeatedly.
+ *
+ * Time = O(1)
+ */
+SLV2Port
+slv2_plugin_get_port_by_index(SLV2Plugin plugin,
+ uint32_t index);
+
+
+/** Get a port on this plugin by \a symbol.
+ *
+ * To perform multiple calls on a port, the returned value should
+ * be cached and used repeatedly.
+ *
+ * Time = O(n)
+ */
+SLV2Port
+slv2_plugin_get_port_by_symbol(SLV2Plugin plugin,
+ const char* symbol);
+
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __SLV2_PLUGIN_H__ */
+
Index: slv2/plugininstance.h
===================================================================
RCS file: slv2/plugininstance.h
diff -N slv2/plugininstance.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ slv2/plugininstance.h 23 Apr 2007 11:59:21 -0000 1.1
@@ -0,0 +1,218 @@
+/* SLV2
+ * Copyright (C) 2007 Dave Robillard <http://drobilla.net>
+ *
+ * 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_PLUGININSTANCE_H__
+#define __SLV2_PLUGININSTANCE_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <assert.h>
+#include <slv2/lv2.h>
+#include <slv2/plugin.h>
+#include <slv2/port.h>
+
+typedef struct _InstanceImpl* SLV2InstanceImpl;
+
+/** \defgroup lib Shared library access
+ *
+ * An SLV2Instance is an instantiated SLV2Plugin (eg a loaded dynamic
+ * library). These functions interact with the binary library code only,
+ * they do not read data files in any way.
+ *
+ * @{
+ */
+
+
+/** Instance of a plugin.
+ *
+ * The LV2 descriptor and handle of this are exposed to allow inlining of
+ * performance critical functions like slv2_instance_run (hiding things in
+ * lv2.h is pointless anyway). The remaining implementation details are
+ * in the opaque pimpl member.
+ */
+typedef struct _Instance {
+ const LV2_Descriptor* lv2_descriptor;
+ LV2_Handle lv2_handle;
+ SLV2InstanceImpl pimpl; ///< Move along now, nothing to see here
+}* SLV2Instance;
+
+
+
+/** Instantiate a plugin.
+ *
+ * The returned object represents shared library objects loaded into memory,
+ * it must be cleaned up with slv2_instance_free when no longer
+ * needed.
+ *
+ * \a plugin is not modified or directly referenced by the returned object
+ * (instances store only a copy of the plugin's URI).
+ *
+ * \a host_features NULL-terminated array of features the host supports.
+ * NULL may be passed if the host supports no additional features (unlike
+ * the LV2 specification - SLV2 takes care of it).
+ *
+ * \return NULL if instantiation failed.
+ */
+SLV2Instance
+slv2_plugin_instantiate(SLV2Plugin plugin,
+ uint32_t sample_rate,
+ const LV2_Host_Feature** host_features);
+
+
+/** Free a plugin instance.
+ *
+ * \a instance is invalid after this call.
+ */
+void
+slv2_instance_free(SLV2Instance instance);
+
+
+#ifndef LIBSLV2_SOURCE
+
+
+/** Get the URI of the plugin which \a instance is an instance of.
+ *
+ * Returned string is shared and must not be modified or deleted.
+ */
+static inline const char*
+slv2_instance_get_uri(SLV2Instance instance)
+{
+ assert(instance);
+ assert(instance->lv2_descriptor);
+
+ return instance->lv2_descriptor->URI;
+}
+
+
+/** Connect a port to a data location.
+ *
+ * This may be called regardless of whether the plugin is activated,
+ * activation and deactivation does not destroy port connections.
+ */
+static inline void
+slv2_instance_connect_port(SLV2Instance instance,
+ uint32_t port_index,
+ void* data_location)
+{
+ assert(instance);
+ assert(instance->lv2_descriptor);
+ assert(instance->lv2_descriptor->connect_port);
+
+ instance->lv2_descriptor->connect_port
+ (instance->lv2_handle, port_index, data_location);
+}
+
+
+/** Activate a plugin instance.
+ *
+ * This resets all state information in the plugin, except for port data
+ * locations (as set by slv2_instance_connect_port). This MUST be called
+ * before calling slv2_instance_run.
+ */
+static inline void
+slv2_instance_activate(SLV2Instance instance)
+{
+ assert(instance);
+ assert(instance->lv2_descriptor);
+
+ if (instance->lv2_descriptor->activate)
+ instance->lv2_descriptor->activate(instance->lv2_handle);
+}
+
+
+/** Run \a instance for \a sample_count frames.
+ *
+ * If the hint lv2:hardRtCapable is set for this plugin, this function is
+ * guaranteed not to block.
+ */
+static inline void
+slv2_instance_run(SLV2Instance instance,
+ uint32_t sample_count)
+{
+ assert(instance);
+ assert(instance->lv2_descriptor);
+ assert(instance->lv2_handle),
+ assert(instance->lv2_descriptor->run);
+
+ instance->lv2_descriptor->run(instance->lv2_handle, sample_count);
+}
+
+
+/** Deactivate a plugin instance.
+ *
+ * Note that to run the plugin after this you must activate it, which will
+ * reset all state information (except port connections).
+ */
+static inline void
+slv2_instance_deactivate(SLV2Instance instance)
+{
+ assert(instance);
+ assert(instance->lv2_descriptor);
+ assert(instance->lv2_handle);
+
+ if (instance->lv2_descriptor->deactivate)
+ instance->lv2_descriptor->deactivate(instance->lv2_handle);
+}
+
+
+/** Get the LV2_Descriptor of the plugin instance.
+ *
+ * Normally hosts should not need to access the LV2_Descriptor directly,
+ * use the slv2_instance_* functions.
+ *
+ * The returned descriptor is shared and must not be deleted.
+ */
+static inline const LV2_Descriptor*
+slv2_instance_get_descriptor(SLV2Instance instance)
+{
+ assert(instance);
+ assert(instance->lv2_descriptor);
+
+ return instance->lv2_descriptor;
+}
+
+
+/** Get the LV2_Handle of the plugin instance.
+ *
+ * Normally hosts should not need to access the LV2_Handle directly,
+ * use the slv2_instance_* functions.
+ *
+ * The returned handle is shared and must not be deleted.
+ */
+static inline LV2_Handle
+slv2_instance_get_handle(SLV2Instance instance)
+{
+ assert(instance);
+ assert(instance->lv2_descriptor);
+
+ return instance->lv2_handle;
+}
+
+#endif /* LIBSLV2_SOURCE */
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* __SLV2_PLUGININSTANCE_H__ */
+
Index: slv2/pluginlist.h
===================================================================
RCS file: slv2/pluginlist.h
diff -N slv2/pluginlist.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ slv2/pluginlist.h 23 Apr 2007 11:59:21 -0000 1.1
@@ -0,0 +1,95 @@
+/* SLV2
+ * Copyright (C) 2007 Dave Robillard <http://drobilla.net>
+ *
+ * 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_PLUGINLIST_H__
+#define __SLV2_PLUGINLIST_H__
+
+#include <slv2/plugin.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+typedef void* SLV2Plugins;
+
+
+/** \defgroup plugins Plugin lists
+ *
+ * These functions work with lists of plugins which come from an
+ * SLV2World. These lists contain only a weak reference to an LV2 plugin
+ * in the Model.
+ *
+ * @{
+ */
+
+
+/** Free a plugin list.
+ *
+ * Freeing a plugin list does not destroy the plugins it contains (plugins
+ * are owned by the world). \a list is invalid after this call.
+ */
+void
+slv2_plugins_free(SLV2World world,
+ SLV2Plugins list);
+
+
+/** Get the number of plugins in the list.
+ */
+unsigned
+slv2_plugins_size(SLV2Plugins list);
+
+
+/** Get a plugin from the list by URI.
+ *
+ * Return value is shared (stored in \a list) and must not be freed or
+ * modified by the caller in any way.
+ *
+ * Time = O(log2(n))
+ *
+ * \return NULL if plugin with \a url not found in \a list.
+ */
+SLV2Plugin
+slv2_plugins_get_by_uri(SLV2Plugins list,
+ const char* uri);
+
+
+/** Get a plugin from the list by index.
+ *
+ * \a index has no significance other than as an index into this list.
+ * Any \a index not less than slv2_list_get_length(list) will return NULL,
+ * so all plugins in a list can be enumerated by repeated calls
+ * to this function starting with \a index = 0.
+ *
+ * Time = O(1)
+ *
+ * \return NULL if \a index out of range.
+ */
+SLV2Plugin
+slv2_plugins_get_at(SLV2Plugins list,
+ unsigned index);
+
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __SLV2_PLUGINLIST_H__ */
+
Index: slv2/port.h
===================================================================
RCS file: slv2/port.h
diff -N slv2/port.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ slv2/port.h 23 Apr 2007 11:59:21 -0000 1.1
@@ -0,0 +1,138 @@
+/* SLV2
+ * Copyright (C) 2007 Dave Robillard <http://drobilla.net>
+ *
+ * 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_PORT_H__
+#define __SLV2_PORT_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <slv2/types.h>
+#include <slv2/plugin.h>
+#include <slv2/port.h>
+#include <slv2/stringlist.h>
+
+/** \addtogroup data
+ * @{
+ */
+
+
+/** Port equivalent to slv2_plugin_get_value.
+ *
+ * Time = Query
+ */
+SLV2Strings
+slv2_port_get_value(SLV2Plugin plugin,
+ SLV2Port port,
+ const char* property);
+
+
+/** Port equivalent to slv2_plugin_get_properties.
+ *
+ * Time = Query
+ */
+SLV2Strings
+slv2_port_get_properties(SLV2Plugin plugin,
+ SLV2Port port);
+
+
+/** Port equivalent to slv2_plugin_get_hints.
+ *
+ * Time = Query
+ */
+SLV2Strings
+slv2_port_get_hints(SLV2Plugin plugin,
+ SLV2Port port);
+
+
+/** Get the symbol of a port given the index.
+ *
+ * The 'symbol' is a short string, a valid C identifier.
+ * Returned string must be free()'d by caller.
+ *
+ * \return NULL when index is out of range
+ *
+ * Time = Query
+ */
+char*
+slv2_port_get_symbol(SLV2Plugin plugin,
+ SLV2Port port);
+
+/** Get the name of a port.
+ *
+ * This is guaranteed to return the untranslated name (the doap:name in the
+ * data file without a language tag). Returned value must be free()'d by
+ * the caller.
+ *
+ * Time = Query
+ */
+char*
+slv2_port_get_name(SLV2Plugin plugin,
+ SLV2Port port);
+
+
+/** Get the class (input/output, data type, rate...) of a port.
+ *
+ * Time = Query
+ */
+SLV2PortClass
+slv2_port_get_class(SLV2Plugin plugin,
+ SLV2Port port);
+
+
+/** Get the default value of a port.
+ *
+ * Only valid for ports with a data type of lv2:float.
+ *
+ * Time = Query
+ */
+float
+slv2_port_get_default_value(SLV2Plugin plugin,
+ SLV2Port port);
+
+
+/** Get the minimum value of a port.
+ *
+ * Only valid for ports with a data type of lv2:float.
+ *
+ * Time = Query
+ */
+float
+slv2_port_get_minimum_value(SLV2Plugin plugin,
+ SLV2Port port);
+
+
+/** Get the maximum value of a port.
+ *
+ * Only valid for ports with a data type of lv2:float.
+ *
+ * Time = Query
+ */
+float
+slv2_port_get_maximum_value(SLV2Plugin plugin,
+ SLV2Port port);
+
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __SLV2_PORT_H__ */
Index: slv2/slv2.h
===================================================================
RCS file: slv2/slv2.h
diff -N slv2/slv2.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ slv2/slv2.h 23 Apr 2007 11:59:21 -0000 1.1
@@ -0,0 +1,39 @@
+/* SLV2
+ * Copyright (C) 2007 Dave Robillard <http://drobilla.net>
+ *
+ * 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_H
+#define __SLV2_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <slv2/types.h>
+#include <slv2/world.h>
+#include <slv2/plugin.h>
+#include <slv2/port.h>
+#include <slv2/pluginlist.h>
+#include <slv2/plugininstance.h>
+#include <slv2/stringlist.h>
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __SLV2_H */
Index: slv2/stringlist.h
===================================================================
RCS file: slv2/stringlist.h
diff -N slv2/stringlist.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ slv2/stringlist.h 23 Apr 2007 11:59:21 -0000 1.1
@@ -0,0 +1,84 @@
+/* SLV2
+ * Copyright (C) 2007 Dave Robillard <http://drobilla.net>
+ *
+ * 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_STRINGLIST_H__
+#define __SLV2_STRINGLIST_H__
+
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/** \defgroup strings Collections of strings
+ *
+ * SLV2Strings is an ordered collection of strings which is fast for random
+ * access by index (i.e. a fancy array).
+ *
+ * @{
+ */
+
+
+typedef void* SLV2Strings;
+
+
+/** Allocate a new, empty SLV2Strings
+ */
+SLV2Strings
+slv2_strings_new();
+
+
+/** Get the number of elements in a string list.
+ */
+unsigned
+slv2_strings_size(SLV2Strings list);
+
+
+/** Get a string from a string list at the given index.
+ *
+ * @return the element at \a index, or NULL if index is out of range.
+ *
+ * Time = O(1)
+ */
+const char*
+slv2_strings_get_at(SLV2Strings list, unsigned index);
+
+
+/** Return whether \a list contains \a string.
+ *
+ * Time = O(n)
+ */
+bool
+slv2_strings_contains(SLV2Strings list, const char* string);
+
+
+/** Free a string list.
+ */
+void
+slv2_strings_free(SLV2Strings);
+
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __SLV2_STRINGLIST_H__ */
+
Index: slv2/types.h
===================================================================
RCS file: slv2/types.h
diff -N slv2/types.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ slv2/types.h 23 Apr 2007 11:59:21 -0000 1.1
@@ -0,0 +1,65 @@
+/* SLV2
+ * Copyright (C) 2007 Dave Robillard <http://drobilla.net>
+ *
+ * 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_TYPES_H__
+#define __SLV2_TYPES_H__
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/** Class (direction and type) of a port
+ *
+ * Note that ports may be of other classes not listed here, this is just
+ * to make the most common case simple. Use slv2_port_get_value(p, "rdf:type")
+ * if you need further class information.
+ */
+typedef enum _PortClass {
+ SLV2_UNKNOWN_PORT_CLASS,
+ SLV2_CONTROL_INPUT, /**< One input float per block */
+ SLV2_CONTROL_OUTPUT, /**< One output float per block */
+ SLV2_AUDIO_INPUT, /**< One input float per frame */
+ SLV2_AUDIO_OUTPUT, /**< One output float per frame */
+ SLV2_MIDI_INPUT, /**< MIDI input (LL extension) */
+ SLV2_MIDI_OUTPUT /**< MIDI output (LL extension) */
+} SLV2PortClass;
+
+
+/** A port on a plugin. Opaque, but valid to compare to NULL. */
+typedef struct _Port* SLV2Port;
+
+
+/** A plugin. Opaque, but valid to compare to NULL. */
+typedef struct _Plugin* SLV2Plugin;
+
+
+/** The world. Opaque, but valid to compare to NULL. */
+typedef struct _World* SLV2World;
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* __SLV2_TYPES_H__ */
+
Index: slv2/util.h
===================================================================
RCS file: slv2/util.h
diff -N slv2/util.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ slv2/util.h 23 Apr 2007 11:59:21 -0000 1.1
@@ -0,0 +1,71 @@
+/* SLV2
+ * Copyright (C) 2007 Dave Robillard <http://drobilla.net>
+ *
+ * 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_UTIL_H__
+#define __SLV2_UTIL_H__
+
+#include <stdarg.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/** \defgroup util Utility functions
+ *
+ * @{
+ */
+
+
+/** Convert a full URI (eg file://foo/bar/baz.ttl) to a local path (e.g.
/foo/bar/baz.ttl).
+ *
+ * Return value is shared and must not be deleted by caller.
+ * \return \a uri converted to a path, or NULL on failure (URI is not local).
+ */
+const char* slv2_uri_to_path(const char* uri);
+
+
+/** Append \a suffix to \a *dst, reallocating \a dst as necessary.
+ *
+ * \a dst will (possibly) be freed, it must be dynamically allocated with
malloc
+ * or NULL.
+ */
+void
+slv2_strappend(char** dst, const char* suffix);
+
+
+/** Join all arguments into one string.
+ *
+ * Arguments are not modified, return value must be free()'d.
+ */
+char*
+slv2_strjoin(const char* first, ...);
+
+
+char*
+slv2_vstrjoin(const char** first, va_list args_list);
+
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __SLV2_UTIL_H__ */
+
Index: slv2/world.h
===================================================================
RCS file: slv2/world.h
diff -N slv2/world.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ slv2/world.h 23 Apr 2007 11:59:21 -0000 1.1
@@ -0,0 +1,171 @@
+/* SLV2
+ * Copyright (C) 2007 Dave Robillard <http://drobilla.net>
+ *
+ * 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 <slv2/pluginlist.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/** \defgroup world Library context, data loading, etc.
+ *
+ * The "world" represents all library state, and the data found in bundles'
+ * manifest.ttl (ie it is an in-memory index of all things LV2 found).
+ * Plugins (and plugin extensions) and the LV2 specification (and LV2
+ * extensions) itself can be queried from the world for use.
+ *
+ * Normal hosts which just want to easily load plugins by URI are strongly
+ * recommended to simply call \ref slv2_world_load_all to find all installed
+ * data in the recommended way.
+ *
+ * Normal hosts should NOT have to refer to bundles directly under normal
+ * circumstances. However, functions are provided to load individual bundles
+ * explicitly, intended for hosts which depend on a specific bundle
+ * (which is 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.
+ *
+ * Time = Query
+ */
+void
+slv2_world_load_all(SLV2World world);
+
+
+/** Load a specific bundle.
+ *
+ * \arg bundle_uri 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 \b never attach any long-term significance to bundle paths
+ * as there are no guarantees they will remain consistent whatsoever.
+ * Plugins (and other things) are identified by URIs, \b not bundle or
+ * file names.
+ *
+ * This function should only be used by apps which ship with a special
+ * bundle (which it knows exists at some path because the bundle is
+ * shipped with the application).
+ *
+ * Time = Query
+ */
+void
+slv2_world_load_bundle(SLV2World world,
+ const char* bundle_uri);
+
+
+/** Return a list of all found plugins.
+ *
+ * The returned list contains just enough references to query
+ * or instantiate plugins. The data for a particular plugin will not be
+ * loaded into memory until a call to an slv2_plugin_* function results in
+ * a query (at which time the data is cached with the SLV2Plugin so future
+ * queries are very fast).
+ *
+ * Returned plugins contain a reference to this world, world must not be
+ * destroyed until plugins are finished with.
+ *
+ * Time = O(1)
+ */
+SLV2Plugins
+slv2_world_get_all_plugins(SLV2World world);
+
+
+/** Return a list of found plugins filtered by a user-defined filter function.
+ *
+ * All plugins currently found in \a world that return true when passed to
+ * \a include (a pointer to a function which takes an SLV2Plugin and returns
+ * a bool) will be in the returned list.
+ *
+ * Returned plugins contain a reference to this world, world must not be
+ * destroyed until plugins are finished with.
+ *
+ * Time = O(n * Time(include))
+ */
+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:
+<tt> \verbatim
+PREFIX : <http://lv2plug.in/ontology#>
+SELECT DISTINCT ?plugin WHERE {
+ ?plugin :port [ a :AudioPort; a :InputPort ] ;
+ :port [ a :AudioPort; a :OutputPort ] .
+}
+\endverbatim </tt>
+ *
+ * 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__ */
+
Index: src/plugin.c
===================================================================
RCS file: src/plugin.c
diff -N src/plugin.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/plugin.c 23 Apr 2007 11:59:21 -0000 1.1
@@ -0,0 +1,459 @@
+/* SLV2
+ * Copyright (C) 2007 Dave Robillard <http://drobilla.net>
+ *
+ * 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 <string.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <librdf.h>
+#include <slv2/plugin.h>
+#include <slv2/types.h>
+#include <slv2/util.h>
+#include <slv2/stringlist.h>
+#include "private_types.h"
+
+
+/* private */
+SLV2Plugin
+slv2_plugin_new(SLV2World world, librdf_uri* uri, const char* binary_uri)
+{
+ struct _Plugin* plugin = malloc(sizeof(struct _Plugin));
+ plugin->world = world;
+ plugin->plugin_uri = librdf_new_uri_from_uri(uri);
+ plugin->binary_uri = strdup(binary_uri);
+ plugin->data_uris = slv2_strings_new();
+ plugin->ports = raptor_new_sequence((void (*)(void*))&slv2_port_free,
NULL);
+ plugin->storage = NULL;
+ plugin->rdf = NULL;
+
+ return plugin;
+}
+
+
+/* private */
+void
+slv2_plugin_free(SLV2Plugin p)
+{
+ librdf_free_uri(p->plugin_uri);
+ p->plugin_uri = NULL;
+
+ //free(p->bundle_url);
+ free(p->binary_uri);
+
+ raptor_free_sequence(p->ports);
+ p->ports = NULL;
+
+ if (p->rdf) {
+ librdf_free_model(p->rdf);
+ p->rdf = NULL;
+ }
+
+ if (p->storage) {
+ librdf_free_storage(p->storage);
+ p->storage = NULL;
+ }
+
+ slv2_strings_free(p->data_uris);
+
+ free(p);
+}
+
+
+// FIXME: ew
+librdf_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->world = p->world;
+ result->plugin_uri = librdf_new_uri_from_uri(p->plugin_uri);
+
+ //result->bundle_url = strdup(p->bundle_url);
+ result->binary_uri = strdup(p->binary_uri);
+
+ result->data_uris = slv2_strings_new();
+ for (unsigned i=0; i < slv2_strings_size(p->data_uris); ++i)
+ raptor_sequence_push(result->data_uris,
strdup(slv2_strings_get_at(p->data_uris, i)));
+
+ result->ports = raptor_new_sequence((void (*)(void*))&slv2_port_free,
NULL);
+ 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->storage = NULL;
+ result->rdf = NULL;
+
+ return result;
+}
+*/
+
+
+/** comparator for sorting */
+int
+slv2_port_compare_by_index(const void* a, const void* b)
+{
+ SLV2Port port_a = *(SLV2Port*)a;
+ SLV2Port port_b = *(SLV2Port*)b;
+
+ if (port_a->index < port_b->index)
+ return -1;
+ else if (port_a->index == port_b->index)
+ return 0;
+ else //if (port_a->index > port_b->index)
+ return 1;
+}
+
+
+void
+slv2_plugin_load(SLV2Plugin p)
+{
+ //printf("Loading cache for %s\n", (const
char*)librdf_uri_as_string(p->plugin_uri));
+
+ if (!p->storage) {
+ assert(!p->rdf);
+ p->storage = librdf_new_storage(p->world->world, "hashes", NULL,
+ "hash-type='memory'");
+ p->rdf = librdf_new_model(p->world->world, p->storage, NULL);
+ }
+
+ // Parse all the plugin's data files into RDF model
+ for (unsigned i=0; i < slv2_strings_size(p->data_uris); ++i) {
+ const char* data_uri_str = slv2_strings_get_at(p->data_uris, i);
+ librdf_uri* data_uri = librdf_new_uri(p->world->world, (const
unsigned char*)data_uri_str);
+ librdf_parser_parse_into_model(p->world->parser, data_uri,
NULL, p->rdf);
+ librdf_free_uri(data_uri);
+ }
+
+ // Load ports
+ const unsigned char* query = (const unsigned char*)
+ "PREFIX : <http://lv2plug.in/ontology#>\n"
+ "SELECT DISTINCT ?port ?symbol ?index WHERE {\n"
+ "<> :port ?port .\n"
+ "?port :symbol ?symbol ;\n"
+ " :index ?index .\n"
+ "}";
+
+ 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);
+
+ while (!librdf_query_results_finished(results)) {
+
+ //librdf_node* port_node =
librdf_query_results_get_binding_value(results, 0);
+ librdf_node* symbol_node =
librdf_query_results_get_binding_value(results, 1);
+ librdf_node* index_node =
librdf_query_results_get_binding_value(results, 2);
+
+ //assert(librdf_node_is_blank(port_node));
+ assert(librdf_node_is_literal(symbol_node));
+ assert(librdf_node_is_literal(index_node));
+
+ //const char* id = (const
char*)librdf_node_get_blank_identifier(port_node);
+ const char* symbol = (const
char*)librdf_node_get_literal_value(symbol_node);
+ const char* index = (const
char*)librdf_node_get_literal_value(index_node);
+
+ //printf("%s: PORT: %s %s\n", p->plugin_uri, index, symbol);
+
+ // Create a new SLV2Port
+ SLV2Port port = slv2_port_new((unsigned)atoi(index), symbol);
+ raptor_sequence_push(p->ports, port);
+
+ librdf_free_node(symbol_node);
+ librdf_free_node(index_node);
+
+ librdf_query_results_next(results);
+ }
+
+ raptor_sequence_sort(p->ports, slv2_port_compare_by_index);
+
+ if (results)
+ librdf_free_query_results(results);
+
+ librdf_free_query(q);
+
+ //printf("%p %s: NUM PORTS: %d\n", (void*)p, p->plugin_uri,
slv2_plugin_get_num_ports(p));
+}
+
+
+const char*
+slv2_plugin_get_uri(SLV2Plugin p)
+{
+ return (const char*)librdf_uri_as_string(p->plugin_uri);
+}
+
+
+SLV2Strings
+slv2_plugin_get_data_uris(SLV2Plugin p)
+{
+ return p->data_uris;
+}
+
+
+const char*
+slv2_plugin_get_library_uri(SLV2Plugin p)
+{
+ return p->binary_uri;
+}
+
+
+bool
+slv2_plugin_verify(SLV2Plugin plugin)
+{
+ char* query_str =
+ "SELECT DISTINCT ?type ?name ?license ?port WHERE {\n"
+ "<> a ?type ;\n"
+ "doap:name ?name ;\n"
+ "doap:license ?license ;\n"
+ "lv2:port [ lv2:index ?port ] .\n}";
+
+ librdf_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 (!librdf_query_results_finished(results)) {
+ librdf_node* type_node =
librdf_query_results_get_binding_value(results, 0);
+ const char* const type_str = (const
char*)librdf_node_get_literal_value(type_node);
+ librdf_node* name_node =
librdf_query_results_get_binding_value(results, 1);
+ //const char* const name = (const
char*)librdf_node_get_literal_value(name_node);
+ librdf_node* license_node =
librdf_query_results_get_binding_value(results, 2);
+ librdf_node* port_node =
librdf_query_results_get_binding_value(results, 3);
+
+ if (!strcmp(type_str, "http://lv2plug.in/ontology#Plugin"))
+ has_type = true;
+
+ if (name_node)
+ has_name = true;
+
+ if (license_node)
+ has_license = true;
+
+ if (port_node)
+ has_port = true;
+
+ librdf_free_node(type_node);
+ librdf_free_node(name_node);
+ librdf_free_node(license_node);
+ librdf_free_node(port_node);
+
+ librdf_query_results_next(results);
+ }
+
+ librdf_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;
+ } else {
+ return true;
+ }
+}
+
+
+char*
+slv2_plugin_get_name(SLV2Plugin plugin)
+{
+ 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)
+ result = strdup(slv2_strings_get_at(prop, 0));
+
+ if (prop)
+ slv2_strings_free(prop);
+
+ return result;
+}
+
+
+SLV2Strings
+slv2_plugin_get_value(SLV2Plugin p,
+ const char* predicate)
+{
+ assert(predicate);
+
+ char* query = slv2_strjoin(
+ "SELECT DISTINCT ?value WHERE {"
+ "<> ", predicate, " ?value .\n"
+ "}\n", NULL);
+
+ SLV2Strings result = slv2_plugin_simple_query(p, query, "value");
+
+ free(query);
+
+ return result;
+}
+
+
+SLV2Strings
+slv2_plugin_get_value_for_subject(SLV2Plugin p,
+ const char* subject,
+ const char* predicate)
+{
+ assert(predicate);
+
+ char* query = slv2_strjoin(
+ "SELECT DISTINCT ?value WHERE {\n",
+ subject, " ", predicate, " ?value .\n"
+ "}\n", NULL);
+
+ SLV2Strings result = slv2_plugin_simple_query(p, query, "value");
+
+ free(query);
+
+ return result;
+}
+
+
+SLV2Strings
+slv2_plugin_get_properties(SLV2Plugin p)
+{
+ return slv2_plugin_get_value(p, "lv2:pluginProperty");
+}
+
+
+SLV2Strings
+slv2_plugin_get_hints(SLV2Plugin p)
+{
+ return slv2_plugin_get_value(p, "lv2:pluginHint");
+}
+
+
+uint32_t
+slv2_plugin_get_num_ports(SLV2Plugin p)
+{
+ return raptor_sequence_size(p->ports);
+}
+
+
+bool
+slv2_plugin_has_latency(SLV2Plugin p)
+{
+ const char* const query =
+ "SELECT DISTINCT ?port WHERE {\n"
+ " <> lv2:port ?port .\n"
+ " ?port lv2:portHint lv2:reportsLatency .\n"
+ "}\n";
+
+ SLV2Strings results = slv2_plugin_simple_query(p, query, "port");
+
+ bool exists = (slv2_strings_size(results) > 0);
+
+ slv2_strings_free(results);
+
+ return exists;
+}
+
+
+uint32_t
+slv2_plugin_get_latency_port(SLV2Plugin p)
+{
+ const char* const query =
+ "SELECT DISTINCT ?value WHERE {\n"
+ " <> lv2:port ?port .\n"
+ " ?port lv2:portHint lv2:reportsLatency ;\n"
+ " lv2:index ?index .\n"
+ "}\n";
+
+ SLV2Strings result = slv2_plugin_simple_query(p, query, "index");
+
+ // FIXME: need a sane error handling strategy
+ assert(slv2_strings_size(result) == 1);
+ char* endptr = 0;
+ uint32_t index = strtol(slv2_strings_get_at(result, 0), &endptr, 10);
+ // FIXME: check.. stuff..
+
+ return index;
+}
+
+
+SLV2Strings
+slv2_plugin_get_supported_features(SLV2Plugin p)
+{
+ const char* const query =
+ "SELECT DISTINCT ?feature WHERE {\n"
+ " { <> lv2:optionalHostFeature ?feature }\n"
+ " UNION\n"
+ " { <> lv2:requiredHostFeature ?feature }\n"
+ "}\n";
+
+ SLV2Strings result = slv2_plugin_simple_query(p, query, "feature");
+
+ return result;
+}
+
+
+SLV2Strings
+slv2_plugin_get_optional_features(SLV2Plugin p)
+{
+ const char* const query =
+ "SELECT DISTINCT ?feature WHERE {\n"
+ " <> lv2:optionalHostFeature ?feature .\n"
+ "}\n";
+
+ SLV2Strings result = slv2_plugin_simple_query(p, query, "feature");
+
+ return result;
+}
+
+
+SLV2Strings
+slv2_plugin_get_required_features(SLV2Plugin p)
+{
+ const char* const query =
+ "SELECT DISTINCT ?feature WHERE {\n"
+ " <> lv2:requiredHostFeature ?feature .\n"
+ "}\n";
+
+ SLV2Strings result = slv2_plugin_simple_query(p, query, "feature");
+
+ return result;
+}
+
+
+SLV2Port
+slv2_plugin_get_port_by_index(SLV2Plugin p,
+ uint32_t index)
+{
+ return raptor_sequence_get_at(p->ports, (int)index);
+}
+
+
+SLV2Port
+slv2_plugin_get_port_by_symbol(SLV2Plugin p,
+ const char* symbol)
+{
+ // FIXME: sort plugins and do a binary search
+ for (int i=0; i < raptor_sequence_size(p->ports); ++i) {
+ SLV2Port port = raptor_sequence_get_at(p->ports, i);
+ if (!strcmp(port->symbol, symbol))
+ return port;
+ }
+
+ return NULL;
+}
+
Index: src/plugininstance.c
===================================================================
RCS file: src/plugininstance.c
diff -N src/plugininstance.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/plugininstance.c 23 Apr 2007 11:59:21 -0000 1.1
@@ -0,0 +1,141 @@
+/* SLV2
+ * Copyright (C) 2007 Dave Robillard <http://drobilla.net>
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <dlfcn.h>
+#include <slv2/types.h>
+#include <slv2/plugin.h>
+#include <slv2/plugininstance.h>
+#include <slv2/util.h>
+#include "private_types.h"
+
+
+SLV2Instance
+slv2_plugin_instantiate(SLV2Plugin plugin,
+ uint32_t sample_rate,
+ const LV2_Host_Feature** host_features)
+{
+ struct _Instance* result = NULL;
+
+ bool local_host_features = (host_features == NULL);
+ if (local_host_features) {
+ host_features = malloc(sizeof(LV2_Host_Feature));
+ host_features[0] = NULL;
+ }
+
+ const char* const lib_uri = slv2_plugin_get_library_uri(plugin);
+ const char* const lib_path = slv2_uri_to_path(lib_uri);
+
+ if (!lib_path)
+ return NULL;
+
+ dlerror();
+ void* lib = dlopen(lib_path, RTLD_NOW);
+ if (!lib) {
+ fprintf(stderr, "Unable to open library %s (%s)\n", lib_path,
dlerror());
+ return NULL;
+ }
+
+ LV2_Descriptor_Function df = dlsym(lib, "lv2_descriptor");
+
+ if (!df) {
+ fprintf(stderr, "Could not find symbol 'lv2_descriptor', "
+ "%s is not a LV2 plugin.\n", lib_path);
+ dlclose(lib);
+ return NULL;
+ } else {
+ // Search for plugin by URI
+
+ // FIXME: Kluge to get bundle path (containing directory of
binary)
+ char* bundle_path = strdup(plugin->binary_uri);
+ char* const bundle_path_end = strrchr(bundle_path, '/');
+ if (bundle_path_end)
+ *(bundle_path_end+1) = '\0';
+ printf("Bundle path: %s\n", bundle_path);
+
+ for (uint32_t i=0; 1; ++i) {
+
+ const LV2_Descriptor* ld = df(i);
+
+ if (!ld) {
+ fprintf(stderr, "Did not find plugin %s in
%s\n",
+ slv2_plugin_get_uri(plugin),
lib_path);
+ dlclose(lib);
+ break; // return NULL
+ } else if (!strcmp(ld->URI,
slv2_plugin_get_uri(plugin))) {
+
+ printf("Found %s at index %u in:\n\t%s\n\n",
+
librdf_uri_as_string(plugin->plugin_uri), i, lib_path);
+
+ assert(ld->instantiate);
+
+ // Create SLV2Instance to return
+ result = malloc(sizeof(struct _Instance));
+ result->lv2_descriptor = ld;
+ result->lv2_handle = ld->instantiate(ld,
sample_rate, (char*)bundle_path, host_features);
+ struct _InstanceImpl* impl =
malloc(sizeof(struct _InstanceImpl));
+ impl->lib_handle = lib;
+ result->pimpl = impl;
+
+ break;
+ }
+ }
+
+ free(bundle_path);
+ }
+
+ assert(result);
+ assert(slv2_plugin_get_num_ports(plugin) > 0);
+
+ // Failed to instantiate
+ if (result->lv2_handle == NULL) {
+ //printf("Failed to instantiate %s\n", plugin->plugin_uri);
+ free(result);
+ return NULL;
+ }
+
+ // "Connect" all ports to NULL (catches bugs)
+ for (uint32_t i=0; i < slv2_plugin_get_num_ports(plugin); ++i)
+ result->lv2_descriptor->connect_port(result->lv2_handle, i,
NULL);
+
+ if (local_host_features)
+ free(host_features);
+
+ return result;
+}
+
+
+void
+slv2_instance_free(SLV2Instance instance)
+{
+ struct _Instance* i = (struct _Instance*)instance;
+ i->lv2_descriptor->cleanup(i->lv2_handle);
+ i->lv2_descriptor = NULL;
+ dlclose(i->pimpl->lib_handle);
+ i->pimpl->lib_handle = NULL;
+ free(i->pimpl);
+ i->pimpl = NULL;
+ free(i);
+}
+
+
Index: src/pluginlist.c
===================================================================
RCS file: src/pluginlist.c
diff -N src/pluginlist.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/pluginlist.c 23 Apr 2007 11:59:21 -0000 1.1
@@ -0,0 +1,318 @@
+/* SLV2
+ * Copyright (C) 2007 Dave Robillard <http://drobilla.net>
+ *
+ * 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 <limits.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <assert.h>
+#include <dirent.h>
+#include <librdf.h>
+#include <slv2/types.h>
+#include <slv2/plugin.h>
+#include <slv2/pluginlist.h>
+#include <slv2/stringlist.h>
+#include <slv2/util.h>
+#include "private_types.h"
+
+
+SLV2Plugins
+slv2_plugins_new()
+{
+ //return raptor_new_sequence((void (*)(void*))&slv2_plugin_free, NULL);
+ return raptor_new_sequence(NULL, NULL);
+}
+
+
+void
+slv2_plugins_free(SLV2World world, SLV2Plugins list)
+{
+ if (list != world->plugins)
+ raptor_free_sequence(list);
+}
+
+#if 0
+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)
+{
+ /* 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(load_list, slv2_path);
+ } else {
+ const char* const home = getenv("HOME");
+ const char* const suffix = "/.lv2:/usr/local/lib/lv2:usr/lib/lv2";
+ slv2_path = slv2_strjoin(home, suffix, NULL);
+
+ fprintf(stderr, "$LV2_PATH is unset. Using default path %s\n",
slv2_path);
+
+ /* pass 1: find all plugins */
+ slv2_plugins_load_path(load_list, slv2_path);
+
+ /* pass 2: find all data files for plugins */
+ 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);
+}
+
+
+/* This is the parser for manifest.ttl
+ * 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)
+{
+ 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));
+ if (bundle_base_url[strlen(bundle_base_url)-1] == '/')
+ strcat((char*)manifest_url, "manifest.ttl");
+ else
+ strcat((char*)manifest_url, "/manifest.ttl");
+
+ librdf_query_results *results;
+ librdf_uri *base_uri = librdf_new_uri(slv2_rdf_world, manifest_url);
+
+ /* Get all plugins explicitly mentioned in the manifest (discovery pass
1) */
+ char* query_string =
+ "PREFIX : <http://lv2plug.in/ontology#>\n\n"
+ "SELECT DISTINCT ?plugin_uri FROM <>\n"
+ "WHERE { ?plugin_uri a :Plugin }\n";
+
+ librdf_query *rq = librdf_new_query(slv2_rdf_world, "sparql", NULL,
+ (unsigned char*)query_string, base_uri);
+
+
+
+ //printf("%s\n\n", query_string);
+
+ results = librdf_query_execute(rq, model->model);
+
+ while (!librdf_query_results_finished(results)) {
+
+ librdf_node* literal =
librdf_query_results_get_binding_value(results, 0);
+ assert(literal);
+
+ if (!slv2_plugins_get_by_uri(list, (const
char*)librdf_node_get_literal_value(literal))) {
+ /* Create a new plugin */
+ struct _Plugin* new_plugin = slv2_plugin_new();
+ new_plugin->plugin_uri = strdup((const
char*)librdf_node_get_literal_value(literal));
+ new_plugin->bundle_url = strdup(bundle_base_url);
+ raptor_sequence_push(new_plugin->data_uris,
strdup((const char*)manifest_url));
+
+ raptor_sequence_push(list, new_plugin);
+
+ }
+
+ librdf_query_results_next(results);
+ }
+
+ if (results)
+ librdf_free_query_results(results);
+
+ librdf_free_query(rq);
+
+ /* Get all data files linked to plugins (discovery pass 2) */
+ query_string =
+ "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>\n"
+ "PREFIX : <http://lv2plug.in/ontology#>\n\n"
+ "SELECT DISTINCT ?subject ?data_uri ?binary FROM <>\n"
+ "WHERE { ?subject rdfs:seeAlso ?data_uri\n"
+ "OPTIONAL { ?subject :binary ?binary } }\n";
+
+ rq = librdf_new_query(slv2_rdf_world, "sparql", NULL,
+ (unsigned char*)query_string, base_uri);
+
+ //printf("%s\n\n", query_string);
+
+ results = librdf_query_execute(rq, slv2_model);
+
+ while (!librdf_query_results_finished(results)) {
+
+ const char* subject = (const
char*)librdf_node_get_literal_value(
+ librdf_query_results_get_binding_value(results,
0));
+
+ const char* data_uri = (const
char*)librdf_node_get_literal_value(
+ librdf_query_results_get_binding_value(results,
1));
+
+ const char* binary = (const char*)librdf_node_get_literal_value(
+ librdf_query_results_get_binding_value(results,
2));
+
+ SLV2Plugin plugin = slv2_plugins_get_by_uri(list, subject);
+
+ if (plugin && data_uri &&
!slv2_strings_contains(plugin->data_uris, data_uri))
+ raptor_sequence_push(plugin->data_uris,
strdup(data_uri));
+
+ if (plugin && binary && !plugin->lib_uri)
+ ((struct _Plugin*)plugin)->lib_uri = strdup(binary);
+
+ librdf_query_results_next(results);
+
+ }
+
+ if (results)
+ librdf_free_query_results(results);
+
+ librdf_free_query(rq);
+
+ librdf_free_uri(base_uri);
+ free(manifest_url);
+}
+
+
+/* Add all the plugins found in dir to list.
+ * (Private helper function, not exposed in public API)
+ */
+void
+slv2_plugins_load_dir(SLV2Plugins list, const char* dir)
+{
+ assert(list);
+
+ 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 = slv2_strjoin(dir, "/", pfile->d_name, NULL);
+ char* bundle_url = slv2_strjoin("file://", dir, "/",
pfile->d_name, NULL);
+ DIR* bundle_dir = opendir(bundle_path);
+
+ if (bundle_dir != NULL) {
+ closedir(bundle_dir);
+
+ slv2_plugins_load_bundle(list, bundle_url);
+ //printf("Loaded bundle %s\n", bundle_url);
+ }
+
+ free(bundle_path);
+ free(bundle_url);
+ }
+
+ closedir(pdir);
+}
+
+
+void
+slv2_plugins_load_path(SLV2Plugins list,
+ const char* lv2_path)
+{
+ assert(list);
+
+ 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_plugins_load_dir(list, dir);
+
+ *delim = 'X';
+ dir = delim + 1;
+ }
+
+ //char* slv2_path = strdup(slv2
+
+ free(path);
+}
+#endif
+
+unsigned
+slv2_plugins_size(SLV2Plugins list)
+{
+ return raptor_sequence_size(list);
+}
+
+
+SLV2Plugin
+slv2_plugins_get_by_uri(SLV2Plugins list, const char* uri)
+{
+ // good old fashioned binary search
+
+ int lower = 0;
+ int upper = raptor_sequence_size(list) - 1;
+ int i;
+
+ if (upper == 0)
+ return NULL;
+
+ while (upper >= lower) {
+ i = lower + ((upper - lower) / 2);
+
+ SLV2Plugin p = raptor_sequence_get_at(list, i);
+
+ int cmp = strcmp(slv2_plugin_get_uri(p), uri);
+
+ if (cmp == 0)
+ return p;
+ else if (cmp > 0)
+ upper = i - 1;
+ else
+ lower = i + 1;
+ }
+
+ return NULL;
+}
+
+
+SLV2Plugin
+slv2_plugins_get_at(SLV2Plugins list, unsigned index)
+{
+ assert(list);
+
+ if (index > INT_MAX)
+ return NULL;
+ else
+ return (SLV2Plugin)raptor_sequence_get_at(list, (int)index);
+}
+
Index: src/port.c
===================================================================
RCS file: src/port.c
diff -N src/port.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/port.c 23 Apr 2007 11:59:21 -0000 1.1
@@ -0,0 +1,240 @@
+/* SLV2
+ * Copyright (C) 2007 Dave Robillard <http://drobilla.net>
+ *
+ * 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 <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+#include <slv2/port.h>
+#include <slv2/types.h>
+#include <slv2/util.h>
+#include "private_types.h"
+
+
+/* private */
+SLV2Port
+slv2_port_new(uint32_t index, const char* symbol/*, const char* node_id*/)
+{
+ struct _Port* port = malloc(sizeof(struct _Port));
+ port->index = index;
+ port->symbol = strdup(symbol);
+ //port->node_id = strdup(node_id);
+ return port;
+}
+
+
+/* private */
+void
+slv2_port_free(SLV2Port port)
+{
+ free(port->symbol);
+ //free(port->node_id);
+ free(port);
+}
+
+
+/* private */
+SLV2Port
+slv2_port_duplicate(SLV2Port port)
+{
+ struct _Port* result = malloc(sizeof(struct _Port));
+ result->index = port->index;
+ result->symbol = strdup(port->symbol);
+ //result->node_id = strdup(port->node_id);
+ return result;
+}
+
+
+SLV2PortClass
+slv2_port_get_class(SLV2Plugin p,
+ SLV2Port port)
+{
+ SLV2Strings class = slv2_port_get_value(p, port, "rdf:type");
+ assert(class);
+
+ SLV2PortClass ret = SLV2_UNKNOWN_PORT_CLASS;
+
+ int io = -1; // 0 = in, 1 = out
+ enum { UNKNOWN, AUDIO, CONTROL, MIDI } type = UNKNOWN;
+
+ for (unsigned i=0; i < slv2_strings_size(class); ++i) {
+ const char* value = slv2_strings_get_at(class, i);
+ if (!strcmp(value, "http://lv2plug.in/ontology#InputPort"))
+ io = 0;
+ else if (!strcmp(value,
"http://lv2plug.in/ontology#OutputPort"))
+ io = 1;
+ else if (!strcmp(value,
"http://lv2plug.in/ontology#ControlPort"))
+ type = CONTROL;
+ else if (!strcmp(value, "http://lv2plug.in/ontology#AudioPort"))
+ type = AUDIO;
+ else if (!strcmp(value,
"http://ll-plugins.nongnu.org/lv2/ext/MidiPort"))
+ type = MIDI;
+ }
+
+ if (io == 0) {
+ if (type == AUDIO)
+ ret = SLV2_AUDIO_INPUT;
+ else if (type == CONTROL)
+ ret = SLV2_CONTROL_INPUT;
+ else if (type == MIDI)
+ ret = SLV2_MIDI_INPUT;
+ } else if (io == 1) {
+ if (type == AUDIO)
+ ret = SLV2_AUDIO_OUTPUT;
+ else if (type == CONTROL)
+ ret = SLV2_CONTROL_OUTPUT;
+ else if (type == MIDI)
+ ret = SLV2_MIDI_OUTPUT;
+ }
+
+ slv2_strings_free(class);
+
+ return ret;
+}
+
+
+SLV2Strings
+slv2_port_get_value(SLV2Plugin p,
+ SLV2Port port,
+ const char* property)
+{
+ assert(property);
+
+ SLV2Strings result = NULL;
+
+ char* query = slv2_strjoin(
+ "SELECT DISTINCT ?value WHERE {\n"
+ "?port lv2:symbol \"", port->symbol, "\";\n\t",
+ property, " ?value .\n}", 0);
+
+ result = slv2_plugin_simple_query(p, query, "value");
+
+ free(query);
+
+ return result;
+}
+
+
+char*
+slv2_port_get_symbol(SLV2Plugin p,
+ SLV2Port port)
+{
+ char* symbol = NULL;
+
+ SLV2Strings result = slv2_port_get_value(p, port, "lv2:symbol");
+
+ if (result && slv2_strings_size(result) == 1)
+ symbol = strdup(slv2_strings_get_at(result, 0));
+
+ slv2_strings_free(result);
+
+ return symbol;
+}
+
+
+char*
+slv2_port_get_name(SLV2Plugin p,
+ SLV2Port port)
+{
+ char* name = NULL;
+
+ SLV2Strings result = slv2_port_get_value(p, port, "lv2:name");
+
+ if (result && slv2_strings_size(result) == 1)
+ name = strdup(slv2_strings_get_at(result, 0));
+
+ slv2_strings_free(result);
+
+ return name;
+}
+
+
+float
+slv2_port_get_default_value(SLV2Plugin p,
+ SLV2Port port)
+{
+ // FIXME: do casting properly in the SPARQL query
+
+ float value = 0.0f;
+
+ SLV2Strings result = slv2_port_get_value(p, port, "lv2:default");
+
+ if (result && slv2_strings_size(result) == 1)
+ value = atof(slv2_strings_get_at(result, 0));
+
+ slv2_strings_free(result);
+
+ return value;
+}
+
+
+float
+slv2_port_get_minimum_value(SLV2Plugin p,
+ SLV2Port port)
+{
+ // FIXME: need better access to literal types
+
+ float value = 0.0f;
+
+ SLV2Strings result = slv2_port_get_value(p, port, "lv2:minimum");
+
+ if (result && slv2_strings_size(result) == 1)
+ value = atof(slv2_strings_get_at(result, 0));
+
+ slv2_strings_free(result);
+
+ return value;
+}
+
+
+float
+slv2_port_get_maximum_value(SLV2Plugin p,
+ SLV2Port port)
+{
+ // FIXME: need better access to literal types
+
+ float value = 0.0f;
+
+ SLV2Strings result = slv2_port_get_value(p, port, "lv2:maximum");
+
+ if (result && slv2_strings_size(result) == 1)
+ value = atof(slv2_strings_get_at(result, 0));
+
+ slv2_strings_free(result);
+
+ return value;
+}
+
+
+SLV2Strings
+slv2_port_get_properties(SLV2Plugin p,
+ SLV2Port port)
+{
+ return slv2_port_get_value(p, port, "lv2:portProperty");
+}
+
+
+SLV2Strings
+slv2_port_get_hints(SLV2Plugin p,
+ SLV2Port port)
+{
+ return slv2_port_get_value(p, port, "lv2:portHint");
+}
+
Index: src/private_types.h
===================================================================
RCS file: src/private_types.h
diff -N src/private_types.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/private_types.h 23 Apr 2007 11:59:21 -0000 1.1
@@ -0,0 +1,110 @@
+/* SLV2
+ * Copyright (C) 2007 Dave Robillard <http://drobilla.net>
+ *
+ * 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_PRIVATE_TYPES_H__
+#define __SLV2_PRIVATE_TYPES_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <librdf.h>
+#include <slv2/pluginlist.h>
+
+
+/** Reference to a port on some plugin.
+ */
+struct _Port {
+ uint32_t index; ///< LV2 index
+ char* symbol; ///< LV2 symbol
+ //char* node_id; ///< RDF Node ID
+};
+
+
+SLV2Port slv2_port_new(uint32_t index, const char* symbol/*, const char*
node_id*/);
+SLV2Port slv2_port_duplicate(SLV2Port port);
+void slv2_port_free(SLV2Port port);
+
+
+/** Record of an installed/available plugin.
+ *
+ * A simple reference to a plugin somewhere on the system. This just holds
+ * paths of relevant files, the actual data therein isn't loaded into memory.
+ */
+struct _Plugin {
+ struct _World* world;
+ librdf_uri* plugin_uri;
+// char* bundle_url; // Bundle directory plugin was loaded from
+ char* binary_uri; // lv2:binary
+ raptor_sequence* data_uris; // rdfs::seeAlso
+ raptor_sequence* ports;
+ librdf_storage* storage;
+ librdf_model* rdf;
+};
+
+SLV2Plugin slv2_plugin_new(SLV2World world, librdf_uri* uri, const char*
binary_uri);
+void slv2_plugin_load(SLV2Plugin p);
+void slv2_plugin_free(SLV2Plugin plugin);
+
+
+/** Create a new, empty plugin list.
+ *
+ * Returned object must be freed with slv2_plugins_free.
+ */
+SLV2Plugins
+slv2_plugins_new();
+
+
+/** Pimpl portion of SLV2Instance */
+struct _InstanceImpl {
+ void* lib_handle;
+};
+
+
+/** Model of LV2 (RDF) data loaded from bundles.
+ */
+struct _World {
+ librdf_world* world;
+ librdf_storage* storage;
+ librdf_model* model;
+ librdf_parser* parser;
+ SLV2Plugins plugins;
+};
+
+/** 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);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __SLV2_PRIVATE_TYPES_H__ */
+
Index: src/query.c
===================================================================
RCS file: src/query.c
diff -N src/query.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/query.c 23 Apr 2007 11:59:21 -0000 1.1
@@ -0,0 +1,224 @@
+/* SLV2
+ * Copyright (C) 2007 Dave Robillard <http://drobilla.net>
+ *
+ * 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 <string.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <librdf.h>
+#include <slv2/plugin.h>
+#include <slv2/util.h>
+#include <slv2/stringlist.h>
+#include "private_types.h"
+
+
+static const char* slv2_query_prefixes =
+ "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>\n"
+ "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>\n"
+ "PREFIX doap: <http://usefulinc.com/ns/doap#>\n"
+ "PREFIX lv2: <http://lv2plug.in/ontology#>\n";
+
+#if 0
+char*
+slv2_query_lang_filter(const char* variable)
+{
+ char* result = NULL;
+ char* const lang = (char*)getenv("LANG");
+ if (lang) {
+ // FILTER( LANG(?value) = "en" || LANG(?value) = "" )
+ result = slv2_strjoin(
+ //"FILTER (lang(?value) = \"", lang, "\"\n"), 0);
+ "FILTER( lang(?", variable, ") = \"", lang,
+ "\" || lang(?", variable, ") = \"\" )\n", NULL);
+ }
+
+ return result;
+}
+#endif
+
+SLV2Strings
+slv2_query_get_variable_bindings(librdf_query_results* results,
+ const char* variable)
+{
+ SLV2Strings result = NULL;
+
+ if (librdf_query_results_get_bindings_count(results) > 0)
+ result = slv2_strings_new();
+
+ while (!librdf_query_results_finished(results)) {
+
+ librdf_node* node =
+ librdf_query_results_get_binding_value_by_name(results, variable);
+
+ char* str = NULL;
+
+ switch (librdf_node_get_type(node)) {
+ case LIBRDF_NODE_TYPE_RESOURCE:
+ str = strdup((const
char*)librdf_uri_as_string(librdf_node_get_uri(node)));
+ break;
+ case LIBRDF_NODE_TYPE_LITERAL:
+ str = strdup((const
char*)librdf_node_get_literal_value(node));
+ break;
+ case LIBRDF_NODE_TYPE_BLANK:
+ str = strdup((const
char*)librdf_node_get_blank_identifier(node));
+ break;
+ case LIBRDF_NODE_TYPE_UNKNOWN:
+ default:
+ fprintf(stderr, "Unknown variable binding type for
?%s\n", variable);
+ break;
+ }
+
+ if (str) {
+ //printf("?%s = %s\n", variable, str);
+ raptor_sequence_push(result, str);
+ }
+
+ librdf_free_node(node);
+
+ librdf_query_results_next(results);
+ }
+
+ return result;
+}
+
+
+size_t
+slv2_query_count_bindings(librdf_query_results* results)
+{
+ size_t count = 0;
+
+ while (!librdf_query_results_finished(results)) {
+ ++count;
+ librdf_query_results_next(results);
+ }
+
+ return count;
+}
+
+
+librdf_query_results*
+slv2_plugin_query(SLV2Plugin plugin,
+ const char* sparql_str)
+{
+ if (!plugin->rdf)
+ slv2_plugin_load(plugin);
+
+ librdf_uri* base_uri = plugin->plugin_uri;
+
+ char* query_str = slv2_strjoin(slv2_query_prefixes, sparql_str, NULL);
+
+ //printf("******** Query \n%s********\n", query_str);
+
+ librdf_query *rq = librdf_new_query(plugin->world->world, "sparql",
NULL,
+ (const unsigned char*)query_str, base_uri);
+
+ if (!rq) {
+ fprintf(stderr, "ERROR: Could not create query\n");
+ return NULL;
+ }
+
+ // Add LV2 ontology to query sources
+ //librdf_query_add_data_graph(rq, slv2_ontology_uri,
+ // NULL, RASQAL_DATA_GRAPH_BACKGROUND);
+
+ // Add all plugin data files to query sources
+ /*for (unsigned i=0; i < slv2_strings_size(plugin->data_uris); ++i) {
+ const char* file_uri_str =
slv2_strings_get_at(plugin->data_uris, i);
+ raptor_uri* file_uri = raptor_new_uri((const unsigned
char*)file_uri_str);
+ librdf_query_add_data_graph(rq, file_uri,
+ NULL, RASQAL_DATA_GRAPH_BACKGROUND);
+ raptor_free_uri(file_uri);
+ }*/
+
+ librdf_query_results* results = librdf_query_execute(rq, plugin->rdf);
+
+ librdf_free_query(rq);
+
+ free(query_str);
+
+ // FIXME: results leaked internally in places?
+ return results;
+}
+
+
+/** Query a single variable */
+SLV2Strings
+slv2_plugin_simple_query(SLV2Plugin plugin,
+ const char* sparql_str,
+ const char* variable)
+{
+ librdf_query_results* results = slv2_plugin_query(plugin, sparql_str);
+ SLV2Strings ret = slv2_query_get_variable_bindings(results, variable);
+ librdf_free_query_results(results);
+
+ return ret;
+}
+
+
+/** Run a query and count number of matches.
+ *
+ * More efficient than slv2_plugin_simple_query if you're only interested
+ * in the number of results (ie slv2_plugin_num_ports).
+ */
+unsigned
+slv2_plugin_query_count(SLV2Plugin plugin,
+ const char* sparql_str)
+{
+ librdf_query_results* results = slv2_plugin_query(plugin, sparql_str);
+
+ if (results) {
+ unsigned ret = slv2_query_count_bindings(results);
+ librdf_free_query_results(results);
+ return ret;
+ } else {
+ return 0;
+ }
+}
+
+
+size_t
+slv2_query_count_results(SLV2Plugin p,
+ const char* query)
+{
+ char* query_str = slv2_strjoin(slv2_query_prefixes, query, NULL);
+
+ assert(p);
+ assert(query_str);
+
+ librdf_query *rq = librdf_new_query(p->world->world, "sparql", NULL,
+ (unsigned char*)query_str, NULL);
+
+ //printf("Query: \n%s\n\n", query_str);
+
+ // Add LV2 ontology to query sources
+ //librdf_query_add_data_graph(rq, slv2_ontology_uri,
+ // NULL, RASQAL_DATA_GRAPH_BACKGROUND);
+
+ librdf_query_results* results = librdf_query_execute(rq,
p->world->model);
+ assert(results);
+
+ size_t count = slv2_query_count_bindings(results);
+
+ librdf_free_query_results(results);
+ librdf_free_query(rq);
+
+ free(query_str);
+
+ return count;
+}
+
Index: src/stringlist.c
===================================================================
RCS file: src/stringlist.c
diff -N src/stringlist.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/stringlist.c 23 Apr 2007 11:59:21 -0000 1.1
@@ -0,0 +1,65 @@
+/* SLV2
+ * Copyright (C) 2007 Dave Robillard <http://drobilla.net>
+ *
+ * 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.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <raptor.h>
+#include <slv2/stringlist.h>
+
+
+SLV2Strings
+slv2_strings_new()
+{
+ return raptor_new_sequence(&free, NULL);
+}
+
+
+void
+slv2_strings_free(SLV2Strings list)
+{
+ raptor_free_sequence(list);
+}
+
+
+unsigned
+slv2_strings_size(SLV2Strings list)
+{
+ return raptor_sequence_size(list);
+}
+
+
+const char*
+slv2_strings_get_at(SLV2Strings list, unsigned index)
+{
+ if (index > INT_MAX)
+ return NULL;
+ else
+ return (const char*)raptor_sequence_get_at(list, (int)index);
+}
+
+
+bool
+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), str))
+ return true;
+
+ return false;
+}
Index: src/util.c
===================================================================
RCS file: src/util.c
diff -N src/util.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/util.c 23 Apr 2007 11:59:22 -0000 1.1
@@ -0,0 +1,86 @@
+/* SLV2
+ * Copyright (C) 2007 Dave Robillard <http://drobilla.net>
+ *
+ * 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 <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <stdarg.h>
+#include <slv2/util.h>
+
+
+void
+slv2_strappend(char** dst, const char* suffix)
+{
+ assert(dst);
+ assert(*dst);
+ assert(suffix);
+
+ const size_t new_length = strlen((char*)*dst) + strlen((char*)suffix) +
1;
+ *dst = realloc(*dst, (new_length * sizeof(char)));
+ assert(dst);
+ strcat((char*)*dst, (char*)suffix);
+}
+
+
+char*
+slv2_strjoin(const char* first, ...)
+{
+ size_t len = strlen(first);
+ char* result = NULL;
+ va_list args;
+
+ va_start(args, first);
+ while (1) {
+ const char* const s = va_arg(args, const char *);
+ if (s == NULL)
+ break;
+ len += strlen(s);
+ }
+ va_end(args);
+
+ result = malloc(len + 1);
+ if (!result)
+ return NULL;
+
+ strcpy(result, first);
+ va_start(args, first);
+ while (1) {
+ const char* const s = va_arg(args, const char *);
+ if (s == NULL)
+ break;
+ strcat(result, s);
+ }
+ va_end(args);
+
+ return result;
+}
+
+
+const char*
+slv2_uri_to_path(const char* uri)
+{
+ if (!strncmp(uri, "file://", (size_t)7))
+ return (char*)(uri + 7);
+ else
+ return NULL;
+}
+
+
+
Index: src/world.c
===================================================================
RCS file: src/world.c
diff -N src/world.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/world.c 23 Apr 2007 11:59:22 -0000 1.1
@@ -0,0 +1,326 @@
+/* SLV2
+ * Copyright (C) 2007 Dave Robillard <http://drobilla.net>
+ *
+ * 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 <string.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <string.h>
+#include <librdf.h>
+#include <slv2/world.h>
+#include <slv2/slv2.h>
+#include <slv2/util.h>
+//#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;*/
+
+ for (int i=0; i < raptor_sequence_size(world->plugins); ++i)
+ slv2_plugin_free(raptor_sequence_get_at(world->plugins, i));
+ raptor_free_sequence(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);
+}
+
+
+void
+slv2_world_load_bundle(SLV2World world, const char* bundle_uri_str)
+{
+ librdf_uri* bundle_uri = librdf_new_uri(world->world,
+ (const unsigned char*)bundle_uri_str);
+
+ 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);
+ librdf_free_uri(bundle_uri);
+}
+
+
+/** Load all bundles under a directory.
+ * 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* uri = slv2_strjoin("file://", dir, "/", pfile->d_name,
"/", NULL);
+
+ // FIXME: Probably a better way to check if a dir exists
+ DIR* bundle_dir = opendir(uri + 7);
+
+ if (bundle_dir != NULL) {
+ closedir(bundle_dir);
+ slv2_world_load_bundle(world, uri);
+ }
+
+ free(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");
+
+ /* 1. Read all manifest files into model */
+
+ 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);
+ }
+
+
+ /* 2. Query out things to cache */
+
+ // Find all plugins and associated data files
+ unsigned char* query_string = (unsigned char*)
+ "PREFIX : <http://lv2plug.in/ontology#>\n"
+ "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>\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,
+ strdup((const
char*)librdf_uri_as_string(data_uri)));
+
+ raptor_sequence_push(world->plugins, plugin);
+
+ librdf_free_node(plugin_node);
+ librdf_free_node(data_node);
+ librdf_free_node(binary_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)
+{
+ return world->plugins;
+}
+
+
+SLV2Plugins
+slv2_world_get_plugins_by_filter(SLV2World world, bool (*include)(SLV2Plugin))
+{
+ SLV2Plugins result = slv2_plugins_new();
+
+ for (int i=0; i < raptor_sequence_size(world->plugins); ++i) {
+ SLV2Plugin p = raptor_sequence_get_at(world->plugins, i);
+ if (include(p))
+ raptor_sequence_push(result, p);
+ }
+
+ 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
+
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Traverso-commit] traverso/src/3rdparty/slv2 slv2/lv2.h slv2/plug...,
Remon Sijrier <=