From 17ec1c5594772a89a5284449754b56ccb705ebe4 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Wed, 7 Feb 2007 01:45:53 +0000 Subject: Added lv2.ttl installation, lv2.ttl added as source by default to queries. Changed port API to work by referring to either index or symbol. Plugged some leaks. Added access to plugin/port hints/properties. Updated lv2.ttl. git-svn-id: http://svn.drobilla.net/lad/slv2@285 a436a847-0d15-0410-975c-d299462d15a1 --- src/Makefile.am | 5 +- src/library.c | 44 +++++++++++++++ src/plugin.c | 106 ++++++++++++++++++----------------- src/pluginlist.c | 4 +- src/port.c | 167 ++++++++++++++++++++++++++++++++++++++++--------------- src/query.c | 91 +++++++++++++++++++----------- 6 files changed, 283 insertions(+), 134 deletions(-) create mode 100644 src/library.c (limited to 'src') 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 + * + * 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 + + +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: \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 #include #include +#include #include #include #include #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 #include #include +#include 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: \n" - "PREFIX rdfs: \n" - "PREFIX doap: \n" - "PREFIX lv2: \n" - "PREFIX plugin: <", plugin_uri, "> \n", - "PREFIX data: <", data_file_url, "> \n\n", NULL); + "PREFIX rdf: \n" + "PREFIX rdfs: \n" + "PREFIX doap: \n" + "PREFIX lv2: \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]); -- cgit v1.2.1