summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--configure.ac14
-rw-r--r--data/Makefile.am3
-rw-r--r--data/lv2.ttl28
-rw-r--r--hosts/lv2_jack_host.c15
-rw-r--r--hosts/lv2_simple_jack_host.c30
-rw-r--r--slv2/Makefile.am1
-rw-r--r--slv2/library.h53
-rw-r--r--slv2/plugin.h61
-rw-r--r--slv2/port.h72
-rw-r--r--slv2/query.h22
-rw-r--r--slv2/slv2.h6
-rw-r--r--slv2/types.h27
-rw-r--r--src/Makefile.am5
-rw-r--r--src/library.c44
-rw-r--r--src/plugin.c106
-rw-r--r--src/pluginlist.c4
-rw-r--r--src/port.c167
-rw-r--r--src/query.c91
-rw-r--r--utils/Makefile.am6
-rw-r--r--utils/lv2_inspect.c106
-rw-r--r--utils/lv2_list.c4
21 files changed, 644 insertions, 221 deletions
diff --git a/configure.ac b/configure.ac
index 2485744..bbc7590 100644
--- a/configure.ac
+++ b/configure.ac
@@ -81,6 +81,17 @@ if test "$build_ladspa2lv2" = "yes"; then
fi
AM_CONDITIONAL(BUILD_LADSPA2SLV2, [test "$build_ladspa2lv2" = "yes"])
+
+# Check ontology install directory
+AC_MSG_CHECKING([where to install lv2.ttl])
+AC_ARG_WITH(lv2-ttl-dir,
+ AS_HELP_STRING([--with-lv2-ttl-dir=DIR],
+ [directory where lv2.ttl should be installed ($datadir/lv2)]),
+ [lv2ttldir=$withval], [lv2ttldir=$datadir/lv2])
+AC_MSG_RESULT($lv2ttldir)
+lv2ttlpath="$lv2ttldir/lv2.ttl"
+AC_SUBST(lv2ttlpath)
+
# Write output files
AC_CONFIG_FILES([Makefile])
AC_CONFIG_FILES([src/Makefile])
@@ -98,7 +109,8 @@ AC_MSG_RESULT([])
AC_MSG_RESULT([**********************************************************************])
AC_MSG_RESULT([SLV2 build configuration:])
AC_MSG_RESULT([])
-AC_MSG_RESULT([Building JACK clients: $build_jack])
+AC_MSG_RESULT([Building JACK clients: $build_jack])
+AC_MSG_RESULT([Ontology install location: $lv2ttlpath])
AC_MSG_RESULT([**********************************************************************])
AC_MSG_RESULT([])
diff --git a/data/Makefile.am b/data/Makefile.am
index 1ebf317..65c8a66 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -1 +1,2 @@
-EXTRA_DIST = lv2.ttl
+ontologydir = $(datadir)/lv2
+ontology_DATA = lv2.ttl
diff --git a/data/lv2.ttl b/data/lv2.ttl
index 9ba6974..6f02475 100644
--- a/data/lv2.ttl
+++ b/data/lv2.ttl
@@ -1,7 +1,7 @@
# RDF Schema for LV2 plugins
# *** PROVISIONAL ***
#
-# Revision 2007-01-03
+# Revision 2007-02-06
#
# This document describes the classes and properties that are defined by the
# core LV2 specification. See <http://lv2plug.in> for more information.
@@ -153,6 +153,17 @@ Plugins will write values to this array during their run method.
+##################################
+# Optional Plugin RDF:Properties #
+##################################
+
+:documentation a rdf:Property ;
+ rdfs:domain :Plugin ;
+ rdfs:label "documentation" ;
+ rdfs:comment "Relates a Plugin to some text/audio/video documentation either online or included with the plugin package" .
+
+
+
#################################
# Mandatory Port RDF:Properties #
#################################
@@ -228,7 +239,7 @@ minimum, and maximum), though future extensions may define more.
:ScalePoint a rdfs:Class ;
rdfs:subClassOf :Point ;
- rdfs:comment "A single :Float Point (for control inputs)" .
+ rdfs:comment "A single :float Point (for control inputs)" .
:scalePoint a rdf:Property ;
rdfs:domain :Port ;
@@ -250,7 +261,7 @@ information available.
rdfs:comment """
A hint to the host for the minimum useful value that the port will use.
This is a "soft" limit - the plugin is required to gracefully accept all
-values in the range of :Float.
+values in the range of :float.
""" .
:maximum a rdf:Property ;
@@ -259,7 +270,7 @@ values in the range of :Float.
rdfs:comment """
A hint to the host for the maximum useful value that the port will use.
This is a "soft" limit - the plugin is required to gracefully accept all
-values in the range of :Float.
+values in the range of :float.
""" .
@@ -268,8 +279,8 @@ values in the range of :Float.
# Data Type #
#############
-:Float a rdfs:DataType ;
- rdfs:label "32-bit Floating Point" ;
+:float a :DataType ;
+ rdfs:label "32-bit floating point" ;
rdfs:comment """
Value conforming to the 32bit IEEE-754 floating point specification.""".
@@ -340,11 +351,6 @@ plugin can still function correctly, it is NOT a Property, it is a Hint.
rdfs:label "hint" ;
rdfs:comment "Relates Ports to PortProperties." .
-:documentation a rdf:Property ;
- rdfs:domain :Plugin ;
- rdfs:label "documentation" ;
- rdfs:comment "Relates a Plugin to some text/audio/video documentation either online or included with the plugin package" .
-
###############
diff --git a/hosts/lv2_jack_host.c b/hosts/lv2_jack_host.c
index e5e51a3..03d57d9 100644
--- a/hosts/lv2_jack_host.c
+++ b/hosts/lv2_jack_host.c
@@ -35,6 +35,7 @@ struct Port {
enum Direction { INPUT, OUTPUT} direction;
enum Type { UNKNOWN, FLOAT, MIDI } type;
+ SLV2PortID id;
jack_port_t* jack_port; /**< For audio and MIDI ports, otherwise NULL */
float control; /**< For control ports, otherwise 0.0f */
LV2_MIDI* midi_buffer; /**< For midi ports, otherwise NULL */
@@ -65,6 +66,8 @@ main(int argc, char** argv)
host.num_ports = 0;
host.ports = NULL;
+ slv2_init();
+
/* Find all installed plugins */
SLV2List plugins = slv2_list_new();
slv2_list_load_all(plugins);
@@ -143,6 +146,8 @@ main(int argc, char** argv)
}
jack_client_close(host.jack_client);
+ slv2_finish();
+
return 0;
}
@@ -170,6 +175,7 @@ create_port(struct JackHost* host,
//struct Port* port = (Port*)malloc(sizeof(Port));
struct Port* const port = &host->ports[port_index];
+ port->id = slv2_port_by_index(port_index);
port->type = UNKNOWN;
port->jack_port = NULL;
port->control = 0.0f;
@@ -177,17 +183,18 @@ create_port(struct JackHost* host,
slv2_instance_connect_port(host->instance, port_index, NULL);
- char* type_str = slv2_port_get_data_type(host->plugin, port_index);
+ char* type_str = slv2_port_get_data_type(host->plugin, port->id);
+
if (!strcmp(type_str, SLV2_DATA_TYPE_FLOAT))
port->type = FLOAT;
else if (!strcmp(type_str, SLV2_DATA_TYPE_MIDI))
port->type = MIDI;
/* Get the port symbol (label) for console printing */
- char* symbol = slv2_port_get_symbol(host->plugin, port_index);
+ char* symbol = slv2_port_get_symbol(host->plugin, port->id);
/* Get the 'class' (not data type) of the port (control input, audio output, etc) */
- enum SLV2PortClass class = slv2_port_get_class(host->plugin, port_index);
+ enum SLV2PortClass class = slv2_port_get_class(host->plugin, port->id);
if (port->type == FLOAT) {
@@ -195,7 +202,7 @@ create_port(struct JackHost* host,
switch (class) {
case SLV2_CONTROL_RATE_INPUT:
port->direction = INPUT;
- port->control = slv2_port_get_default_value(host->plugin, port_index);
+ port->control = slv2_port_get_default_value(host->plugin, port->id);
slv2_instance_connect_port(host->instance, port_index, &port->control);
printf("Set %s to %f\n", symbol, host->ports[port_index].control);
break;
diff --git a/hosts/lv2_simple_jack_host.c b/hosts/lv2_simple_jack_host.c
index 4b7493f..ef386b7 100644
--- a/hosts/lv2_simple_jack_host.c
+++ b/hosts/lv2_simple_jack_host.c
@@ -49,6 +49,8 @@ main(int argc, char** argv)
host.jack_ports = NULL;
host.controls = NULL;
+ slv2_init();
+
/* Find all installed plugins */
SLV2List plugins = slv2_list_new();
slv2_list_load_all(plugins);
@@ -125,6 +127,8 @@ main(int argc, char** argv)
}
jack_client_close(host.jack_client);
+ slv2_finish();
+
return 0;
}
@@ -147,40 +151,42 @@ die(const char* msg)
*/
void
create_port(struct JackHost* host,
- uint32_t port_index)
+ uint32_t index)
{
+ SLV2PortID id = slv2_port_by_index(index);
+
/* Make sure this is a float port */
- char* type = slv2_port_get_data_type(host->plugin, port_index);
+ char* type = slv2_port_get_data_type(host->plugin, id);
if (strcmp(type, SLV2_DATA_TYPE_FLOAT))
die("Unrecognized data type, aborting.");
free(type);
/* Get the port symbol (label) for console printing */
- char* symbol = slv2_port_get_symbol(host->plugin, port_index);
+ char* symbol = slv2_port_get_symbol(host->plugin, id);
/* Initialize the port array elements */
- host->jack_ports[port_index] = NULL;
- host->controls[port_index] = 0.0f;
+ host->jack_ports[index] = NULL;
+ host->controls[index] = 0.0f;
/* Get the 'class' of the port (control input, audio output, etc) */
- enum SLV2PortClass class = slv2_port_get_class(host->plugin, port_index);
+ enum SLV2PortClass class = slv2_port_get_class(host->plugin, id);
/* Connect the port based on it's 'class' */
switch (class) {
case SLV2_CONTROL_RATE_INPUT:
- host->controls[port_index] = slv2_port_get_default_value(host->plugin, port_index);
- slv2_instance_connect_port(host->instance, port_index, &host->controls[port_index]);
- printf("Set %s to %f\n", symbol, host->controls[port_index]);
+ host->controls[index] = slv2_port_get_default_value(host->plugin, id);
+ slv2_instance_connect_port(host->instance, index, &host->controls[index]);
+ printf("Set %s to %f\n", symbol, host->controls[index]);
break;
case SLV2_CONTROL_RATE_OUTPUT:
- slv2_instance_connect_port(host->instance, port_index, &host->controls[port_index]);
+ slv2_instance_connect_port(host->instance, index, &host->controls[index]);
break;
case SLV2_AUDIO_RATE_INPUT:
- host->jack_ports[port_index] = jack_port_register(host->jack_client,
+ host->jack_ports[index] = jack_port_register(host->jack_client,
symbol, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
break;
case SLV2_AUDIO_RATE_OUTPUT:
- host->jack_ports[port_index] = jack_port_register(host->jack_client,
+ host->jack_ports[index] = jack_port_register(host->jack_client,
symbol, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
break;
default:
diff --git a/slv2/Makefile.am b/slv2/Makefile.am
index 2fcb5b7..5fba079 100644
--- a/slv2/Makefile.am
+++ b/slv2/Makefile.am
@@ -5,6 +5,7 @@ slv2include_HEADERS = \
types.h \
private_types.h \
slv2.h \
+ library.h \
plugin.h \
query.h \
port.h \
diff --git a/slv2/library.h b/slv2/library.h
new file mode 100644
index 0000000..9c94139
--- /dev/null
+++ b/slv2/library.h
@@ -0,0 +1,53 @@
+/* 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_LIBRARY_H
+#define __SLV2_LIBRARY_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/** Initialize SLV2.
+ *
+ * This MUST be called before calling any other SLV2 functions, or fatal
+ * errors will likely occur.
+ */
+void
+slv2_init();
+
+
+/** Finialize SLV2.
+ *
+ * Frees any resources allocated by slv2_init().
+ */
+void
+slv2_finish();
+
+
+/** The URI of the lv2.ttl file.
+ */
+extern raptor_uri* slv2_ontology_uri;
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __SLV2_LIBRARY_H */
diff --git a/slv2/plugin.h b/slv2/plugin.h
index 839137f..d646504 100644
--- a/slv2/plugin.h
+++ b/slv2/plugin.h
@@ -136,21 +136,45 @@ char*
slv2_plugin_get_name(const SLV2Plugin* plugin);
-/** Request some property of the plugin.
+/** Request some arbitrary RDF object of the plugin.
*
* May return NULL if the property was not found (ie is not defined in the
- * data file).
+ * data file), or if object is not sensibly represented as an SLV2Value
+ * (e.g. blank nodes).
*
- * Return value must be free()'d by caller.
+ * Return value must be freed by caller with slv2_value_free.
*
- * Note that some properties may have multiple values. If the property is a
+ * Note that this may return multiple values. If the property is a
* string with multiple languages defined, the translation according to
* $LANG will be returned if it is set. Otherwise all values will be
* returned.
*/
-SLV2Property
-slv2_plugin_get_property(const SLV2Plugin* p,
- const char* property);
+SLV2Value
+slv2_plugin_get_value(const SLV2Plugin* p,
+ 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.
+ */
+SLV2Value
+slv2_plugin_get_properties(const 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.
+ */
+SLV2Value
+slv2_plugin_get_hints(const SLV2Plugin* p);
/** Get the number of ports on this plugin.
@@ -179,29 +203,12 @@ slv2_plugin_has_latency(const SLV2Plugin* p);
uint32_t
slv2_plugin_get_latency_port(const SLV2Plugin* p);
-#if 0
-/** Return whether or not a plugin supports the given host feature / extension.
- *
- * This will return true for both supported and required host features.
- */
-bool
-slv2_plugin_supports_feature(const SLV2Plugin* p, const char* feature_uri);
-
-
-/** Return whether or not a plugin requires the given host feature / extension.
- *
- * If a plugin requires a feature, that feature MUST be passed to the plugin's
- * instantiate method or the plugin will fail to instantiate.
- */
-bool
-slv2_plugin_requires_features(const SLV2Plugin* p, const char* feature_uri);
-#endif
/** Get a plugin's supported host features / extensions.
*
* This returns a list of all supported features (both required and optional).
*/
-SLV2Property
+SLV2Value
slv2_plugin_get_supported_features(const SLV2Plugin* p);
@@ -210,7 +217,7 @@ slv2_plugin_get_supported_features(const SLV2Plugin* p);
* All feature URI's returned by this call MUST be passed to the plugin's
* instantiate method for the plugin to instantiate successfully.
*/
-SLV2Property
+SLV2Value
slv2_plugin_get_required_features(const SLV2Plugin* p);
@@ -220,7 +227,7 @@ slv2_plugin_get_required_features(const SLV2Plugin* p);
* 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.
*/
-SLV2Property
+SLV2Value
slv2_plugin_get_optional_features(const SLV2Plugin* p);
diff --git a/slv2/port.h b/slv2/port.h
index 4e352a8..8e5b006 100644
--- a/slv2/port.h
+++ b/slv2/port.h
@@ -31,14 +31,38 @@ extern "C" {
*/
-/** Get a property of a port, by port index.
- *
- * Return value must be freed by caller with slv2_property_free.
+/** Create an ID to reference a port by index.
*/
-SLV2Property
-slv2_port_get_property(SLV2Plugin* plugin,
- uint32_t index,
- const char* property);
+SLV2PortID
+slv2_port_by_index(uint32_t index);
+
+
+/** Create an ID to reference a port by symbol.
+ */
+SLV2PortID
+slv2_port_by_symbol(const char* symbol);
+
+
+/** Port equivalent to slv2_plugin_get_value.
+ */
+SLV2Value
+slv2_port_get_value(SLV2Plugin* plugin,
+ SLV2PortID id,
+ const char* property);
+
+
+/** Port equivalent to slv2_plugin_get_properties.
+ */
+SLV2Value
+slv2_port_get_properties(const SLV2Plugin* p,
+ SLV2PortID id);
+
+
+/** Port equivalent to slv2_plugin_get_hints.
+ */
+SLV2Value
+slv2_port_get_hints(const SLV2Plugin* p,
+ SLV2PortID id);
/** Get the symbol of a port given the index.
@@ -49,15 +73,25 @@ slv2_port_get_property(SLV2Plugin* plugin,
* \return NULL when index is out of range
*/
char*
-slv2_port_get_symbol(SLV2Plugin* plugin,
- uint32_t index);
+slv2_port_get_symbol(SLV2Plugin* plugin,
+ SLV2PortID id);
+
+/** 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.
+ */
+char*
+slv2_port_get_name(SLV2Plugin* plugin,
+ SLV2PortID id);
/** Get the class (direction and rate) of a port.
*/
enum SLV2PortClass
-slv2_port_get_class(SLV2Plugin* plugin,
- uint32_t index);
+slv2_port_get_class(SLV2Plugin* plugin,
+ SLV2PortID id);
/** Get the data type of a port (as a URI).
@@ -68,8 +102,8 @@ slv2_port_get_class(SLV2Plugin* plugin,
* Returned string must be free()'d by caller.
*/
char*
-slv2_port_get_data_type(SLV2Plugin* plugin,
- uint32_t index);
+slv2_port_get_data_type(SLV2Plugin* plugin,
+ SLV2PortID id);
/** Get the default value of a port.
@@ -77,8 +111,8 @@ slv2_port_get_data_type(SLV2Plugin* plugin,
* Only valid for ports with a data type of lv2:float.
*/
float
-slv2_port_get_default_value(SLV2Plugin* plugin,
- uint32_t index);
+slv2_port_get_default_value(SLV2Plugin* plugin,
+ SLV2PortID id);
/** Get the minimum value of a port.
@@ -86,8 +120,8 @@ slv2_port_get_default_value(SLV2Plugin* plugin,
* Only valid for ports with a data type of lv2:float.
*/
float
-slv2_port_get_minimum_value(SLV2Plugin* plugin,
- uint32_t index);
+slv2_port_get_minimum_value(SLV2Plugin* plugin,
+ SLV2PortID id);
/** Get the maximum value of a port.
@@ -95,8 +129,8 @@ slv2_port_get_minimum_value(SLV2Plugin* plugin,
* Only valid for ports with a data type of lv2:float.
*/
float
-slv2_port_get_maximum_value(SLV2Plugin* plugin,
- uint32_t index);
+slv2_port_get_maximum_value(SLV2Plugin* plugin,
+ SLV2PortID id);
/** @} */
diff --git a/slv2/query.h b/slv2/query.h
index 28df4a6..3faba15 100644
--- a/slv2/query.h
+++ b/slv2/query.h
@@ -27,6 +27,10 @@ extern "C" {
#include "plugin.h"
#include "types.h"
+
+// FIXME: much of this should not be exposed
+
+
/** \defgroup query SPARQL query helpers
*
* This part is in progress, incomplete, a random mishmash of crap that
@@ -74,6 +78,16 @@ char*
slv2_query_lang_filter(const char* variable);
+rasqal_query_results*
+slv2_plugin_query(SLV2Plugin* plugin,
+ const char* sparql_str);
+
+SLV2Value
+slv2_plugin_simple_query(SLV2Plugin* plugin,
+ const char* sparql_str,
+ const char* variable);
+
+#if 0
/** Run a SPARQL query on a plugin's data file and return variable matches.
*
* Header from slv2query_header will be prepended to passed query string (so
@@ -82,12 +96,11 @@ slv2_query_lang_filter(const char* variable);
*
* Returned is a list of all matches for the query variable \a var_name.
*/
-SLV2Property
+SLV2Value
slv2_query_get_results(const SLV2Plugin* p,
const char* query_string,
const char* var_name);
-
/** Run a SPARQL query on a plugin's data file and just count the matches.
*
* Header from slv2query_header will be prepended to passed query string (so
@@ -99,12 +112,9 @@ slv2_query_get_results(const SLV2Plugin* p,
size_t
slv2_query_count_results(const SLV2Plugin* p,
const char* query_string);
+#endif
-/** Free an SLV2Property. */
-void
-slv2_property_free(SLV2Property);
-
/** @} */
diff --git a/slv2/slv2.h b/slv2/slv2.h
index b3c9f63..44744c9 100644
--- a/slv2/slv2.h
+++ b/slv2/slv2.h
@@ -22,13 +22,17 @@
#ifdef __cplusplus
extern "C" {
#endif
-
+
+#include <rasqal.h>
+
+#include <slv2/library.h>
#include <slv2/types.h>
#include <slv2/plugin.h>
#include <slv2/plugininstance.h>
#include <slv2/pluginlist.h>
#include <slv2/port.h>
+
#ifdef __cplusplus
}
#endif
diff --git a/slv2/types.h b/slv2/types.h
index ca695b4..19f1f2b 100644
--- a/slv2/types.h
+++ b/slv2/types.h
@@ -19,23 +19,42 @@
#ifndef __SLV2_TYPES_H__
#define __SLV2_TYPES_H__
+#include <stddef.h>
+#include <stdbool.h>
+#include <stdint.h>
+
#ifdef __cplusplus
extern "C" {
#endif
-#include <stddef.h>
-
/* A property, resulting from a query.
*
* Note that properties may have many values.
*/
-struct _Property {
+struct _Value {
size_t num_values;
char** values;
};
-typedef struct _Property* SLV2Property;
+typedef struct _Value* SLV2Value;
+
+
+/** Free an SLV2Value. */
+void
+slv2_value_free(SLV2Value);
+
+
+/** Port ID type, to allow passing either symbol or index
+ * to port related functions.
+ */
+struct _PortID {
+ bool is_index; /**< Otherwise, symbol */
+ uint32_t index;
+ const char* symbol;
+};
+
+typedef struct _PortID SLV2PortID;
/** Class (direction and rate) of a port */
diff --git a/src/Makefile.am b/src/Makefile.am
index 5f6cea2..4f81d9a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,4 +1,4 @@
-AM_CFLAGS = -std=c99 -I$(top_srcdir)/include -I$(top_srcdir) @RASQAL_CFLAGS@ -DLIBSLV2_SOURCE
+AM_CFLAGS = -std=c99 -I$(top_srcdir)/include -I$(top_srcdir) @RASQAL_CFLAGS@ -DLIBSLV2_SOURCE -DLV2_TTL_PATH=\"@lv2ttlpath@\"
AM_LDFLAGS = `pkg-config --libs rasqal`
lib_LTLIBRARIES = libslv2.la
@@ -11,4 +11,5 @@ libslv2_la_SOURCES = \
port.c \
pluginlist.c \
util.c \
- plugininstance.c
+ plugininstance.c \
+ library.c
diff --git a/src/library.c b/src/library.c
new file mode 100644
index 0000000..591218d
--- /dev/null
+++ b/src/library.c
@@ -0,0 +1,44 @@
+/* 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 "config.h"
+#include <slv2/slv2.h>
+
+
+raptor_uri* slv2_ontology_uri = NULL;
+
+
+void
+slv2_init()
+{
+ rasqal_init();
+
+ slv2_ontology_uri = raptor_new_uri((const unsigned char*)
+ "file://" LV2_TTL_PATH);
+}
+
+
+void
+slv2_finish()
+{
+ rasqal_finish();
+
+ raptor_free_uri(slv2_ontology_uri);
+ slv2_ontology_uri = NULL;
+}
+
diff --git a/src/plugin.c b/src/plugin.c
index 0d9b26b..970b82f 100644
--- a/src/plugin.c
+++ b/src/plugin.c
@@ -93,7 +93,7 @@ slv2_plugin_verify(const SLV2Plugin* plugin)
size_t num_values = 0;
- struct _Property* prop = slv2_plugin_get_property(plugin, "doap:name");
+ struct _Value* prop = slv2_plugin_get_value(plugin, "doap:name");
if (prop) {
num_values = prop->num_values;
free(prop);
@@ -101,7 +101,7 @@ slv2_plugin_verify(const SLV2Plugin* plugin)
if (num_values < 1)
return false;
/*
- prop = slv2_plugin_get_property(plugin, "doap:license");
+ prop = slv2_plugin_get_value(plugin, "doap:license");
num_values = prop->num_values;
free(prop);
if (num_values < 1)
@@ -116,7 +116,7 @@ slv2_plugin_get_name(const SLV2Plugin* plugin)
{
// FIXME: leak
char* result = NULL;
- struct _Property* prop = slv2_plugin_get_property(plugin, "doap:name");
+ struct _Value* prop = slv2_plugin_get_value(plugin, "doap:name");
// FIXME: guaranteed to be the untagged one?
if (prop && prop->num_values >= 1)
@@ -126,11 +126,11 @@ slv2_plugin_get_name(const SLV2Plugin* plugin)
}
-SLV2Property
-slv2_plugin_get_property(const SLV2Plugin* p,
- const char* property)
+SLV2Value
+slv2_plugin_get_value(const SLV2Plugin* p,
+ const char* predicate)
{
- assert(property);
+ assert(predicate);
/*
char* header = slv2_query_header(p);
@@ -147,11 +147,11 @@ slv2_plugin_get_property(const SLV2Plugin* p,
free(lang_filter);*/
char* query = strjoin(
- "SELECT DISTINCT ?value FROM data: WHERE { \n"
- "plugin: ", property, " ?value . \n"
- "} \n", NULL);
+ "SELECT DISTINCT ?value FROM data: WHERE {\n"
+ "plugin: ", predicate, " ?value .\n"
+ "}\n", NULL);
- SLV2Property result = slv2_query_get_results(p, query, "value");
+ SLV2Value result = slv2_plugin_simple_query(p, query, "value");
free(query);
@@ -159,19 +159,33 @@ slv2_plugin_get_property(const SLV2Plugin* p,
}
+SLV2Value
+slv2_plugin_get_properties(const SLV2Plugin* p)
+{
+ return slv2_plugin_get_value(p, "lv2:pluginProperty");
+}
+
+
+SLV2Value
+slv2_plugin_get_hints(const SLV2Plugin* p)
+{
+ return slv2_plugin_get_value(p, "lv2:pluginHint");
+}
+
+
uint32_t
slv2_plugin_get_num_ports(const SLV2Plugin* p)
{
const char* const query =
- "SELECT DISTINCT ?value FROM data: WHERE { \n"
- "plugin: lv2:port ?value . \n"
- "} \n";
+ "SELECT DISTINCT ?value FROM data: WHERE {\n"
+ "plugin: lv2:port ?value .\n"
+ "}\n";
- SLV2Property results = slv2_query_get_results(p, query, "value");
+ SLV2Value results = slv2_plugin_simple_query(p, query, "value");
size_t count = results->num_values;
- slv2_property_free(results);
+ slv2_value_free(results);
return count;
}
@@ -181,16 +195,16 @@ bool
slv2_plugin_has_latency(const SLV2Plugin* p)
{
const char* const query =
- "SELECT DISTINCT ?value FROM data: WHERE { \n"
- " plugin: lv2:port ?port . \n"
- " ?port lv2:portHint lv2:reportsLatency . \n"
+ "SELECT DISTINCT ?port FROM data: WHERE {\n"
+ " plugin: lv2:port ?port .\n"
+ " ?port lv2:portHint lv2:reportsLatency .\n"
"}\n";
- SLV2Property results = slv2_query_get_results(p, query, "port");
+ SLV2Value results = slv2_plugin_simple_query(p, query, "port");
bool exists = (results->num_values > 0);
- slv2_property_free(results);
+ slv2_value_free(results);
return exists;
}
@@ -200,13 +214,13 @@ uint32_t
slv2_plugin_get_latency_port(const SLV2Plugin* p)
{
const char* const query =
- "SELECT DISTINCT ?value FROM data: WHERE { \n"
- " plugin: lv2:port ?port . \n"
- " ?port lv2:portHint lv2:reportsLatency ; \n"
- " lv2:index ?index . \n"
+ "SELECT DISTINCT ?value FROM data: WHERE {\n"
+ " plugin: lv2:port ?port .\n"
+ " ?port lv2:portHint lv2:reportsLatency ;\n"
+ " lv2:index ?index .\n"
"}\n";
- SLV2Property result = slv2_query_get_results(p, query, "index");
+ SLV2Value result = slv2_plugin_simple_query(p, query, "index");
// FIXME: need a sane error handling strategy
assert(result->num_values == 1);
@@ -217,58 +231,46 @@ slv2_plugin_get_latency_port(const SLV2Plugin* p)
return index;
}
-/*
-bool
-slv2_plugin_supports_feature(const SLV2Plugin* p, const char* feature_uri)
-{
-}
-
-
-bool
-slv2_plugin_requires_feature(const SLV2Plugin* p, const char* feature_uri)
-{
-}
-*/
-SLV2Property
+SLV2Value
slv2_plugin_get_supported_features(const SLV2Plugin* p)
{
const char* const query =
- "SELECT DISTINCT ?feature FROM data: WHERE { \n"
- " { plugin: lv2:optionalHostFeature ?feature } \n"
- " UNION \n"
- " { plugin: lv2:requiredHostFeature ?feature } \n"
+ "SELECT DISTINCT ?feature FROM data: WHERE {\n"
+ " { plugin: lv2:optionalHostFeature ?feature }\n"
+ " UNION\n"
+ " { plugin: lv2:requiredHostFeature ?feature }\n"
"}\n";
- SLV2Property result = slv2_query_get_results(p, query, "feature");
+ SLV2Value result = slv2_plugin_simple_query(p, query, "feature");
return result;
}
-SLV2Property
+SLV2Value
slv2_plugin_get_optional_features(const SLV2Plugin* p)
{
const char* const query =
- "SELECT DISTINCT ?feature FROM data: WHERE { \n"
- " plugin: lv2:optionalHostFeature ?feature . \n"
+ "SELECT DISTINCT ?feature FROM data: WHERE {\n"
+ " plugin: lv2:optionalHostFeature ?feature .\n"
"}\n";
- SLV2Property result = slv2_query_get_results(p, query, "feature");
+ SLV2Value result = slv2_plugin_simple_query(p, query, "feature");
return result;
}
-SLV2Property
+SLV2Value
slv2_plugin_get_required_features(const SLV2Plugin* p)
{
const char* const query =
- "SELECT DISTINCT ?feature FROM data: WHERE { \n"
- " plugin: lv2:requiredHostFeature ?feature . \n"
+ "SELECT DISTINCT ?feature FROM data: WHERE {\n"
+ " plugin: lv2:requiredHostFeature ?feature .\n"
"}\n";
- SLV2Property result = slv2_query_get_results(p, query, "feature");
+ SLV2Value result = slv2_plugin_simple_query(p, query, "feature");
return result;
}
diff --git a/src/pluginlist.c b/src/pluginlist.c
index 75b506a..3c8e409 100644
--- a/src/pluginlist.c
+++ b/src/pluginlist.c
@@ -85,10 +85,9 @@ slv2_list_load_bundle(SLV2List list,
else
strcat((char*)manifest_url, "/manifest.ttl");
- rasqal_init();
rasqal_query_results *results;
raptor_uri *base_url = raptor_new_uri(manifest_url);
- rasqal_query *rq = rasqal_new_query("sparql", (unsigned char*)base_url);
+ rasqal_query *rq = rasqal_new_query("sparql", NULL);
char* query_string =
"PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n"
@@ -146,7 +145,6 @@ slv2_list_load_bundle(SLV2List list,
//rasqal_free_query(rq); // FIXME: crashes? leak?
raptor_free_uri(base_url);
}
- rasqal_finish();
free(manifest_url);
}
diff --git a/src/port.c b/src/port.c
index d014f60..eb4ba48 100644
--- a/src/port.c
+++ b/src/port.c
@@ -20,42 +20,70 @@
#include <assert.h>
#include <stdlib.h>
#include <string.h>
+#include <limits.h>
#include <slv2/port.h>
#include <slv2/types.h>
#include <slv2/query.h>
#include "util.h"
+
+SLV2PortID
+slv2_port_by_index(uint32_t index)
+{
+ SLV2PortID ret;
+ ret.is_index = true;
+ ret.index = index;
+ ret.symbol = NULL;
+ return ret;
+}
+
+
+SLV2PortID
+slv2_port_by_symbol(const char* symbol)
+{
+ SLV2PortID ret;
+ ret.is_index = false;
+ ret.index = UINT_MAX;
+ ret.symbol = symbol;
+ return ret;
+}
+
+
enum SLV2PortClass
slv2_port_get_class(SLV2Plugin* p,
- uint32_t index)
+ SLV2PortID id)
{
- struct _Property* class = slv2_port_get_property(p, index, "rdf:type");
+ struct _Value* class = slv2_port_get_value(p, id, "rdf:type");
assert(class);
- assert(class->num_values == 1);
+ assert(class->num_values > 0);
assert(class->values);
-
- // FIXME FIXME FIXME: leak
+
+ enum SLV2PortClass ret;
if (!strcmp((char*)class->values[0], "http://lv2plug.in/ontology#ControlRateInputPort"))
- return SLV2_CONTROL_RATE_INPUT;
+ ret = SLV2_CONTROL_RATE_INPUT;
else if (!strcmp((char*)class->values[0], "http://lv2plug.in/ontology#ControlRateOutputPort"))
- return SLV2_CONTROL_RATE_OUTPUT;
+ ret = SLV2_CONTROL_RATE_OUTPUT;
else if (!strcmp((char*)class->values[0], "http://lv2plug.in/ontology#AudioRateInputPort"))
- return SLV2_AUDIO_RATE_INPUT;
+ ret = SLV2_AUDIO_RATE_INPUT;
else if (!strcmp((char*)class->values[0], "http://lv2plug.in/ontology#AudioRateOutputPort"))
- return SLV2_AUDIO_RATE_OUTPUT;
+ ret = SLV2_AUDIO_RATE_OUTPUT;
else {
fprintf(stderr, "Unknown port class: %s\n", class->values[0]);
- return SLV2_UNKNOWN_PORT_CLASS;
+ ret = SLV2_UNKNOWN_PORT_CLASS;
}
+
+ slv2_value_free(class);
+
+ return ret;
}
char*
slv2_port_get_data_type(SLV2Plugin* p,
- uint32_t index)
+ SLV2PortID id)
{
- SLV2Property type = slv2_port_get_property(p, index, "lv2:datatype");
+ SLV2Value type = slv2_port_get_value(p, id, "lv2:datatype");
assert(type);
assert(type->num_values == 1);
assert(type->values);
@@ -63,30 +91,45 @@ slv2_port_get_data_type(SLV2Plugin* p,
char* ret = type->values[0];
type->values[0] = NULL; // prevent deletion
- slv2_property_free(type);
+ slv2_value_free(type);
return ret;
}
-SLV2Property
-slv2_port_get_property(SLV2Plugin* p,
- uint32_t index,
- const char* property)
+SLV2Value
+slv2_port_get_value(SLV2Plugin* p,
+ SLV2PortID id,
+ const char* property)
{
assert(property);
- char index_str[16];
- snprintf(index_str, (size_t)16, "%u", index);
-
- char* query = strjoin(
- "SELECT DISTINCT ?value FROM data: WHERE { \n"
- "plugin: lv2:port ?port . \n"
- "?port lv2:index ", index_str, " . \n"
- "?port ", property, " ?value . \n}\n", NULL);
+ SLV2Value result = NULL;
- SLV2Property result = slv2_query_get_results(p, query, "value");
-
- free(query);
+ if (id.is_index) {
+ char index_str[16];
+ snprintf(index_str, (size_t)16, "%u", id.index);
+
+ char* query = strjoin(
+ "SELECT DISTINCT ?value FROM data: WHERE { \n"
+ "plugin: lv2:port ?port . \n"
+ "?port lv2:index ", index_str, " ;\n\t",
+ property, " ?value . \n}\n", NULL);
+
+ result = slv2_plugin_simple_query(p, query, "value");
+
+ free(query);
+ } else {
+
+ char* query = strjoin(
+ "SELECT DISTINCT ?value FROM data: WHERE { \n"
+ "plugin: lv2:port ?port . \n"
+ "?port lv2:symbol ", id.symbol, " ;\n\t",
+ property, " ?value . \n}\n", NULL);
+
+ result = slv2_plugin_simple_query(p, query, "value");
+
+ free(query);
+ }
return result;
}
@@ -94,19 +137,39 @@ slv2_port_get_property(SLV2Plugin* p,
char*
slv2_port_get_symbol(SLV2Plugin* p,
- uint32_t index)
+ SLV2PortID id)
{
char* result = NULL;
- SLV2Property prop
- = slv2_port_get_property(p, index, "lv2:symbol");
+ SLV2Value prop
+ = slv2_port_get_value(p, id, "lv2:symbol");
if (prop && prop->num_values == 1) {
result = prop->values[0];
prop->values[0] = NULL; // prevent deletion
}
- slv2_property_free(prop);
+ slv2_value_free(prop);
+
+ return result;
+}
+
+
+char*
+slv2_port_get_name(SLV2Plugin* p,
+ SLV2PortID id)
+{
+ char* result = NULL;
+
+ SLV2Value prop
+ = slv2_port_get_value(p, id, "lv2:name");
+
+ if (prop && prop->num_values == 1) {
+ result = prop->values[0];
+ prop->values[0] = NULL; // prevent deletion
+ }
+
+ slv2_value_free(prop);
return result;
}
@@ -114,19 +177,19 @@ slv2_port_get_symbol(SLV2Plugin* p,
float
slv2_port_get_default_value(SLV2Plugin* p,
- uint32_t index)
+ SLV2PortID id)
{
// FIXME: do casting properly in the SPARQL query
float result = 0.0f;
- SLV2Property prop
- = slv2_port_get_property(p, index, "lv2:default");
+ SLV2Value prop
+ = slv2_port_get_value(p, id, "lv2:default");
if (prop && prop->num_values == 1)
result = atof((char*)prop->values[0]);
- slv2_property_free(prop);
+ slv2_value_free(prop);
return result;
}
@@ -134,19 +197,19 @@ slv2_port_get_default_value(SLV2Plugin* p,
float
slv2_port_get_minimum_value(SLV2Plugin* p,
- uint32_t index)
+ SLV2PortID id)
{
// FIXME: do casting properly in the SPARQL query
float result = 0.0f;
- SLV2Property prop
- = slv2_port_get_property(p, index, "lv2:minimum");
+ SLV2Value prop
+ = slv2_port_get_value(p, id, "lv2:minimum");
if (prop && prop->num_values == 1)
result = atof((char*)prop->values[0]);
- slv2_property_free(prop);
+ slv2_value_free(prop);
return result;
}
@@ -154,20 +217,36 @@ slv2_port_get_minimum_value(SLV2Plugin* p,
float
slv2_port_get_maximum_value(SLV2Plugin* p,
- uint32_t index)
+ SLV2PortID id)
{
// FIXME: do casting properly in the SPARQL query
float result = 0.0f;
- SLV2Property prop
- = slv2_port_get_property(p, index, "lv2:maximum");
+ SLV2Value prop
+ = slv2_port_get_value(p, id, "lv2:maximum");
if (prop && prop->num_values == 1)
result = atof((char*)prop->values[0]);
- slv2_property_free(prop);
+ slv2_value_free(prop);
return result;
}
+
+SLV2Value
+slv2_port_get_properties(const SLV2Plugin* p,
+ SLV2PortID id)
+{
+ return slv2_port_get_value(p, id, "lv2:portProperty");
+}
+
+
+SLV2Value
+slv2_port_get_hints(const SLV2Plugin* p,
+ SLV2PortID id)
+{
+ return slv2_port_get_value(p, id, "lv2:portHint");
+}
+
diff --git a/src/query.c b/src/query.c
index a6eda89..6149531 100644
--- a/src/query.c
+++ b/src/query.c
@@ -21,6 +21,7 @@
#include <assert.h>
#include <slv2/plugin.h>
#include <slv2/query.h>
+#include <slv2/library.h>
char*
@@ -30,12 +31,12 @@ slv2_query_header(const SLV2Plugin* p)
const char* const data_file_url = slv2_plugin_get_data_url(p);
char* query_string = strjoin(
- "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"
- "PREFIX plugin: <", plugin_uri, "> \n",
- "PREFIX data: <", data_file_url, "> \n\n", NULL);
+ "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"
+ "PREFIX plugin: <", plugin_uri, ">\n",
+ "PREFIX data: <", data_file_url, ">\n\n", NULL);
return query_string;
}
@@ -58,13 +59,14 @@ slv2_query_lang_filter(const char* variable)
}
-SLV2Property
-slv2_query_get_variable_bindings(rasqal_query_results* results, const char* var_name)
+SLV2Value
+slv2_query_get_variable_bindings(rasqal_query_results* results,
+ const char* variable)
{
- struct _Property* result = NULL;
+ struct _Value* result = NULL;
if (rasqal_query_results_get_bindings_count(results) > 0) {
- result = malloc(sizeof(struct _Property));
+ result = malloc(sizeof(struct _Value));
result->num_values = 0;
result->values = NULL;
}
@@ -72,7 +74,7 @@ slv2_query_get_variable_bindings(rasqal_query_results* results, const char* var_
while (!rasqal_query_results_finished(results)) {
rasqal_literal* literal =
- rasqal_query_results_get_binding_value_by_name(results, (const unsigned char*)var_name);
+ rasqal_query_results_get_binding_value_by_name(results, (const unsigned char*)variable);
assert(literal != NULL);
// Add value on to the array, reallocing all the way.
@@ -102,41 +104,60 @@ slv2_query_count_variable_bindings(rasqal_query_results* results)
return count;
}
-
-SLV2Property
-slv2_query_get_results(const SLV2Plugin* p,
- const char* query,
- const char* var_name)
+
+rasqal_query_results*
+slv2_plugin_query(SLV2Plugin* plugin,
+ const char* sparql_str)
{
- char* header = slv2_query_header(p);
- char* query_str = strjoin(header, query, NULL);
-
- assert(p);
- assert(query_str);
-
- rasqal_init();
+ raptor_uri* base_uri = raptor_new_uri((unsigned char*)slv2_plugin_get_uri(plugin));
rasqal_query *rq = rasqal_new_query("sparql", NULL);
+
+ char* header = slv2_query_header(plugin);
+ char* query_str = strjoin(header, sparql_str, NULL);
//printf("Query: \n%s\n\n", query_str);
- rasqal_query_prepare(rq, (unsigned char*)query_str, NULL);
+ rasqal_query_prepare(rq, (unsigned char*)query_str, base_uri);
+
+ // Add LV2 ontology to query sources
+ rasqal_query_add_data_graph(rq, slv2_ontology_uri,
+ NULL, RASQAL_DATA_GRAPH_BACKGROUND);
+
rasqal_query_results* results = rasqal_query_execute(rq);
assert(results);
- SLV2Property ret = slv2_query_get_variable_bindings(results, var_name);
- rasqal_free_query_results(results);
rasqal_free_query(rq);
+ raptor_free_uri(base_uri);
+
+ // FIXME: results leaked?
+ return results;
+
+ /*
+ SLV2Value ret = slv2_query_get_variable_bindings(results, var_name);
- rasqal_finish();
-
- free(query_str);
- free(header);
+ rasqal_free_query_results(results);
+ rasqal_free_query(rq);
+
+ return ret;*/
+}
+
+
+/** Query a single variable */
+SLV2Value
+slv2_plugin_simple_query(SLV2Plugin* plugin,
+ const char* sparql_str,
+ const char* variable)
+{
+ rasqal_query_results* results = slv2_plugin_query(plugin, sparql_str);
+ SLV2Value ret = slv2_query_get_variable_bindings(results, variable);
+ rasqal_free_query_results(results);
return ret;
}
+// FIXME: stupid interface
size_t
slv2_query_count_results(const SLV2Plugin* p,
const char* query)
@@ -147,13 +168,16 @@ slv2_query_count_results(const SLV2Plugin* p,
assert(p);
assert(query_str);
- rasqal_init();
-
rasqal_query *rq = rasqal_new_query("sparql", NULL);
//printf("Query: \n%s\n\n", query_str);
rasqal_query_prepare(rq, (unsigned char*)query_str, NULL);
+
+ // Add LV2 ontology to query sources
+ rasqal_query_add_data_graph(rq, slv2_ontology_uri,
+ NULL, RASQAL_DATA_GRAPH_BACKGROUND);
+
rasqal_query_results* results = rasqal_query_execute(rq);
assert(results);
@@ -170,6 +194,7 @@ slv2_query_count_results(const SLV2Plugin* p,
return count;
}
+
/*
size_t
slv2_query_get_num_results(rasqal_query_results* results, const char* var_name)
@@ -188,7 +213,7 @@ slv2_query_get_num_results(rasqal_query_results* results, const char* var_name)
*/
void
-slv2_property_free(struct _Property* prop)
+slv2_value_free(struct _Value* prop)
{
for (size_t i=0; i < prop->num_values; ++i)
free(prop->values[i]);
diff --git a/utils/Makefile.am b/utils/Makefile.am
index 4dff275..09935fc 100644
--- a/utils/Makefile.am
+++ b/utils/Makefile.am
@@ -1,11 +1,15 @@
AM_CFLAGS = -I$(top_srcdir) @RASQAL_CFLAGS@
-bin_PROGRAMS = lv2_list
+bin_PROGRAMS = lv2_list lv2_inspect
lv2_list_CFLAGS = "-std=c99"
lv2_list_SOURCES = lv2_list.c
lv2_list_LDADD = ../src/libslv2.la
+lv2_inspect_CFLAGS = "-std=c99"
+lv2_inspect_SOURCES = lv2_inspect.c
+lv2_inspect_LDADD = ../src/libslv2.la
+
if BUILD_LADSPA2SLV2
bin_PROGRAMS += ladspa2lv2
diff --git a/utils/lv2_inspect.c b/utils/lv2_inspect.c
new file mode 100644
index 0000000..c8ffd55
--- /dev/null
+++ b/utils/lv2_inspect.c
@@ -0,0 +1,106 @@
+/* lv2_inspect - Display information about an LV2 plugin.
+ * Copyright (C) 2007 Dave Robillard <drobilla.net>
+ *
+ * This program 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 program 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 <stdlib.h>
+#include <stdio.h>
+#include <slv2/slv2.h>
+
+
+void
+print_port(SLV2Plugin* p, uint32_t index)
+{
+ SLV2PortID id = slv2_port_by_index(index);
+
+ char* str = NULL;
+
+ printf("\n\tPort %d:\n", index);
+
+ str = slv2_port_get_symbol(p, id);
+ printf("\t\tSymbol: %s\n", str);
+ free(str);
+
+ str = slv2_port_get_name(p, id);
+ printf("\t\tName: %s\n", str);
+ free(str);
+}
+
+
+void
+print_plugin(SLV2Plugin* p)
+{
+ char* str = NULL;
+
+ printf("<%s>\n", slv2_plugin_get_uri(p));
+
+ printf("\tData URL: %s\n", slv2_plugin_get_data_url(p));
+ printf("\tLibrary URL: %s\n\n", slv2_plugin_get_library_url(p));
+
+ str = slv2_plugin_get_name(p);
+ printf("\tName: %s\n", str);
+ free(str);
+
+ if (slv2_plugin_has_latency(p))
+ printf("\tHas latency: yes\n");
+ else
+ printf("\tHas latency: no\n");
+
+ printf("\tProperties:\n");
+ SLV2Value v = slv2_plugin_get_properties(p);
+ for (size_t i=0; i < v->num_values; ++i)
+ printf("\t\t%s\n", v->values[i]);
+ slv2_value_free(v);
+
+ printf("\tHints:\n");
+ v = slv2_plugin_get_hints(p);
+ for (size_t i=0; i < v->num_values; ++i)
+ printf("\t\t%s\n", v->values[i]);
+ slv2_value_free(v);
+
+ uint32_t num_ports = slv2_plugin_get_num_ports(p);
+ for (uint32_t i=0; i < num_ports; ++i)
+ print_port(p, i);
+}
+
+
+
+int
+main(int argc, char** argv)
+{
+ slv2_init();
+
+ if (argc != 2) {
+ fprintf(stderr, "Usage: %s PLUGIN_URI\n", argv[0]);
+ return -1;
+ }
+
+ SLV2List plugins = slv2_list_new();
+ slv2_list_load_all(plugins);
+
+ SLV2Plugin* p = slv2_list_get_plugin_by_uri(plugins, argv[1]);
+
+ if (!p) {
+ fprintf(stderr, "Plugin not found.\n");
+ return -1;
+ }
+
+ print_plugin(p);
+
+ slv2_finish();
+
+ return 0;
+}
diff --git a/utils/lv2_list.c b/utils/lv2_list.c
index e1cba6d..923cba9 100644
--- a/utils/lv2_list.c
+++ b/utils/lv2_list.c
@@ -33,11 +33,15 @@ list_plugins(SLV2List list)
int
main()//int argc, char** argv)
{
+ slv2_init();
+
SLV2List plugins = slv2_list_new();
slv2_list_load_all(plugins);
list_plugins(plugins);
+ slv2_finish();
+
return 0;
}