Schema bug fixes (parsable now).

Fixed some leaks.
Internal query API cleanups.
Added latency reporting support.



git-svn-id: http://svn.drobilla.net/lad@110 a436a847-0d15-0410-975c-d299462d15a1
This commit is contained in:
dave 2006-09-02 08:26:17 +00:00
parent 1abd854fe1
commit 3a79a86998
9 changed files with 137 additions and 41 deletions

View File

@ -1,4 +1,4 @@
CFLAGS = -Wall -I../../../include -fPIC
CFLAGS = -Wall -I../../../include -fPIC -g -O0
all: amp.so

View File

@ -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

View File

@ -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);
/** @} */

View File

@ -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 :)
*/

View File

@ -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

View File

@ -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;
}

View File

@ -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);

View File

@ -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;

View File

@ -83,40 +83,57 @@ slv2_plugin_run_query(const SLV2Plugin* p,
return results;
}
SLV2Property
slv2_query_get_results(rasqal_query_results* results)
size_t
slv2_query_get_num_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);
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, const char* var_name)
{
struct _Property* result = NULL;
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);
}