summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--examples/plugins/Amp-slv2.lv2/Makefile2
-rw-r--r--include/lv2.ttl4
-rw-r--r--slv2/plugin.h21
-rw-r--r--slv2/private_types.h3
-rw-r--r--slv2/query.h5
-rw-r--r--src/plugin.c63
-rw-r--r--src/plugininstance.c2
-rw-r--r--src/port.c11
-rw-r--r--src/query.c65
9 files changed, 136 insertions, 40 deletions
diff --git a/examples/plugins/Amp-slv2.lv2/Makefile b/examples/plugins/Amp-slv2.lv2/Makefile
index 55180c2..eb7dfe1 100644
--- a/examples/plugins/Amp-slv2.lv2/Makefile
+++ b/examples/plugins/Amp-slv2.lv2/Makefile
@@ -1,4 +1,4 @@
-CFLAGS = -Wall -I../../../include -fPIC
+CFLAGS = -Wall -I../../../include -fPIC -g -O0
all: amp.so
diff --git a/include/lv2.ttl b/include/lv2.ttl
index c7d1ac9..75b2aa3 100644
--- a/include/lv2.ttl
+++ b/include/lv2.ttl
@@ -55,7 +55,7 @@ To be used by a host a Plugin must have at least the following properties:
rdf:type (with object :Plugin)
doap:name (one without language tag)
doap:licence
- lv2:port
+ :port
""" .
@@ -147,7 +147,7 @@ Plugins will write values to this array during their run method.
:dataType a rdf:Property ;
rdfs:domain :Port ;
- rdfs:range lv2:DataType ;
+ rdfs:range :DataType ;
rdfs:label "Port Data type" ;
rdfs:comment """
Relates a Port to the data type(s) it can accept. Hosts that do not support
diff --git a/slv2/plugin.h b/slv2/plugin.h
index 01dfc60..2b2a295 100644
--- a/slv2/plugin.h
+++ b/slv2/plugin.h
@@ -158,6 +158,27 @@ slv2_plugin_get_property(const SLV2Plugin* p,
uint32_t
slv2_plugin_get_num_ports(const 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.
+ */
+bool
+slv2_plugin_has_latency(const 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.
+ */
+uint32_t
+slv2_plugin_get_latency_port(const SLV2Plugin* p);
+
/** @} */
diff --git a/slv2/private_types.h b/slv2/private_types.h
index a9c60bf..fdfba65 100644
--- a/slv2/private_types.h
+++ b/slv2/private_types.h
@@ -23,6 +23,7 @@
extern "C" {
#endif
+#include <stdbool.h>
#include <stddef.h>
#include <lv2.h>
@@ -30,7 +31,7 @@ extern "C" {
/* If you're a user of SLV2, stop reading this file RIGHT NOW.
* Unfortunately it needs to be exposed to allow inlining of some things that
* really need to be inlined, but these are opaque types. Don't even think
- * about writing code that depends on any information here....
+ * about writing code that depends on any information here :)
*/
diff --git a/slv2/query.h b/slv2/query.h
index 9bba619..9f1c93d 100644
--- a/slv2/query.h
+++ b/slv2/query.h
@@ -86,8 +86,11 @@ rasqal_query_results*
slv2_plugin_run_query(const SLV2Plugin* p,
const char* query_string);
+size_t
+slv2_query_get_num_results(rasqal_query_results* results, const char* var_name);
+
SLV2Property
-slv2_query_get_results(rasqal_query_results* results);
+slv2_query_get_results(rasqal_query_results* results, const char* var_name);
/** Free an SLV2Property. */
void
diff --git a/src/plugin.c b/src/plugin.c
index a6b2344..a024077 100644
--- a/src/plugin.c
+++ b/src/plugin.c
@@ -156,7 +156,7 @@ slv2_plugin_get_property(const SLV2Plugin* p,
rasqal_query_results* results = slv2_plugin_run_query(p, query);
- struct _Property* result = slv2_query_get_results(results);
+ SLV2Property result = slv2_query_get_results(results, "value");
rasqal_free_query_results(results);
rasqal_finish();
@@ -169,8 +169,6 @@ slv2_plugin_get_property(const SLV2Plugin* p,
uint32_t
slv2_plugin_get_num_ports(const SLV2Plugin* p)
{
- uint32_t result = 0;
-
rasqal_init();
char* query = strjoin(
@@ -179,12 +177,32 @@ slv2_plugin_get_num_ports(const SLV2Plugin* p)
"} \n", NULL);
rasqal_query_results* results = slv2_plugin_run_query(p, query);
+ const size_t result = slv2_query_get_num_results(results, "value");
- while (!rasqal_query_results_finished(results)) {
- ++result;
- rasqal_query_results_next(results);
- }
+ rasqal_free_query_results(results);
+ rasqal_finish();
+ free(query);
+ return result;
+}
+
+
+bool
+slv2_plugin_has_latency(const SLV2Plugin* p)
+{
+ assert(p);
+
+ rasqal_init();
+
+ char* query =
+ "SELECT DISTINCT ?value FROM data: WHERE { \n"
+ " plugin: lv2:port ?port . \n"
+ " ?port lv2:portHint lv2:reportsLatency . \n"
+ "}\n";
+
+ rasqal_query_results* results = slv2_plugin_run_query(p, query);
+ bool result = ( rasqal_query_results_get_bindings_count(results) > 0 );
+
rasqal_free_query_results(results);
rasqal_finish();
free(query);
@@ -192,3 +210,34 @@ slv2_plugin_get_num_ports(const SLV2Plugin* p)
return result;
}
+uint32_t
+slv2_plugin_get_latency_port(const SLV2Plugin* p)
+{
+ assert(p);
+
+ rasqal_init();
+
+ char* query =
+ "SELECT DISTINCT ?value FROM data: WHERE { \n"
+ " plugin: lv2:port ?port . \n"
+ " ?port lv2:portHint lv2:reportsLatency ; \n"
+ " lv2:index ?index . \n"
+ "}\n";
+
+ rasqal_query_results* results = slv2_plugin_run_query(p, query);
+
+ struct _Property* result = slv2_query_get_results(results, "index");
+
+ // FIXME: need a sane error handling strategy
+ assert(result->num_values == 1);
+ char* endptr = 0;
+ uint32_t index = strtol(result->values[0], &endptr, 10);
+ // FIXME: check.. stuff..
+
+ rasqal_free_query_results(results);
+ rasqal_finish();
+ free(query);
+
+ return index;
+}
+
diff --git a/src/plugininstance.c b/src/plugininstance.c
index 6665fd7..f70866a 100644
--- a/src/plugininstance.c
+++ b/src/plugininstance.c
@@ -85,7 +85,7 @@ slv2_plugin_instantiate(const SLV2Plugin* plugin,
assert(result);
assert(slv2_plugin_get_num_ports(plugin) > 0);
- // Connect all ports to NULL (catches bugs)
+ // "Connect" all ports to NULL (catches bugs)
for (uint32_t i=0; i < slv2_plugin_get_num_ports(plugin); ++i)
result->descriptor->connect_port(result->lv2_handle, i, NULL);
diff --git a/src/port.c b/src/port.c
index db18ab8..111517d 100644
--- a/src/port.c
+++ b/src/port.c
@@ -61,6 +61,8 @@ slv2_port_get_data_type(SLV2Plugin* p,
assert(type->values);
char* ret = type->values[0];
+ type->values[0] = NULL; // prevent deletion
+
slv2_property_free(type);
return ret;
}
@@ -87,7 +89,7 @@ slv2_port_get_property(SLV2Plugin* p,
rasqal_query_results* results = slv2_plugin_run_query(p, query);
- SLV2Property result = slv2_query_get_results(results);
+ SLV2Property result = slv2_query_get_results(results, "value");
rasqal_free_query_results(results);
rasqal_finish();
@@ -107,8 +109,11 @@ slv2_port_get_symbol(SLV2Plugin* p,
SLV2Property prop
= slv2_port_get_property(p, index, "lv2:symbol");
- if (prop && prop->num_values == 1)
- result = strdup(prop->values[0]);
+ if (prop && prop->num_values == 1) {
+ result = prop->values[0];
+ prop->values[0] = NULL; // prevent deletion
+ }
+
slv2_property_free(prop);
return result;
diff --git a/src/query.c b/src/query.c
index 0517331..8f3ef40 100644
--- a/src/query.c
+++ b/src/query.c
@@ -83,40 +83,57 @@ slv2_plugin_run_query(const SLV2Plugin* p,
return results;
}
+size_t
+slv2_query_get_num_results(rasqal_query_results* results, const char* var_name)
+{
+ size_t result = 0;
+
+ while (!rasqal_query_results_finished(results)) {
+ if (!strcmp(rasqal_query_results_get_binding_name(results, 0), var_name)) {
+ ++result;
+ }
+ rasqal_query_results_next(results);
+ }
+
+ return result;
+}
SLV2Property
-slv2_query_get_results(rasqal_query_results* results)
+slv2_query_get_results(rasqal_query_results* results, const char* var_name)
{
struct _Property* result = NULL;
-
- if (rasqal_query_results_get_count(results) > 0) {
- result = malloc(sizeof(struct _Property));
- result->num_values = 0;
- result->values = NULL;
- }
-
- while (!rasqal_query_results_finished(results)) {
-
- rasqal_literal* literal =
- rasqal_query_results_get_binding_value_by_name(results, "value");
- assert(literal != NULL);
-
- // Add value on to the array. Yes, this is disgusting.
- result->num_values++;
- // FIXME LEAK:
- result->values = realloc(result->values, result->num_values * sizeof(char*));
- result->values[result->num_values-1] = strdup(rasqal_literal_as_string(literal));
-
- rasqal_query_results_next(results);
- }
- return result;
+ if (rasqal_query_results_get_bindings_count(results) > 0) {
+ result = malloc(sizeof(struct _Property));
+ result->num_values = 0;
+ result->values = NULL;
+ }
+
+ while (!rasqal_query_results_finished(results)) {
+
+ rasqal_literal* literal =
+ rasqal_query_results_get_binding_value_by_name(results, var_name);
+ assert(literal != NULL);
+
+ // Add value on to the array, reallocing all the way.
+ // Yes, this is disgusting. Roughly as disgusting as the rasqal query
+ // results API. coincidentally.
+ result->num_values++;
+ result->values = realloc(result->values, result->num_values * sizeof(char*));
+ result->values[result->num_values-1] = strdup(rasqal_literal_as_string(literal));
+
+ rasqal_query_results_next(results);
+ }
+
+ return result;
}
void
slv2_property_free(struct _Property* prop)
{
- //struct _Property* prop = (struct _Property*)property;
+ for (size_t i=0; i < prop->num_values; ++i)
+ free(prop->values[i]);
+
free(prop->values);
free(prop);
}