1 : /* SLV2
2 : * Copyright (C) 2007-2009 Dave Robillard <http://drobilla.net>
3 : *
4 : * This library is free software; you can redistribute it and/or modify it
5 : * under the terms of the GNU General Public License as published by the Free
6 : * Software Foundation; either version 2 of the License, or (at your option)
7 : * any later version.
8 : *
9 : * This library is distributed in the hope that it will be useful, but WITHOUT
10 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 : * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 : * for more details.
13 : *
14 : * You should have received a copy of the GNU General Public License along
15 : * with this program; if not, write to the Free Software Foundation, Inc.,
16 : * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
17 : */
18 :
19 : #define _XOPEN_SOURCE 500
20 :
21 : #include <assert.h>
22 : #include <math.h>
23 : #include <stdlib.h>
24 : #include <string.h>
25 : #include <librdf.h>
26 : #include "slv2/types.h"
27 : #include "slv2/collections.h"
28 : #include "slv2/plugin.h"
29 : #include "slv2/pluginclass.h"
30 : #include "slv2/query.h"
31 : #include "slv2/util.h"
32 : #include "slv2_internal.h"
33 :
34 :
35 : /* private
36 : * ownership of uri is taken */
37 : SLV2Plugin
38 : slv2_plugin_new(SLV2World world, SLV2Value uri, librdf_uri* bundle_uri)
39 2628 : {
40 2628 : assert(bundle_uri);
41 2628 : struct _SLV2Plugin* plugin = malloc(sizeof(struct _SLV2Plugin));
42 2628 : plugin->world = world;
43 2628 : plugin->plugin_uri = uri;
44 2628 : plugin->bundle_uri = slv2_value_new_librdf_uri(world, bundle_uri);
45 2628 : plugin->binary_uri = NULL;
46 2628 : plugin->plugin_class = NULL;
47 2628 : plugin->data_uris = slv2_values_new();
48 2628 : plugin->ports = NULL;
49 2628 : plugin->storage = NULL;
50 2628 : plugin->rdf = NULL;
51 :
52 2628 : return plugin;
53 : }
54 :
55 :
56 : /* private */
57 : void
58 : slv2_plugin_free(SLV2Plugin p)
59 2628 : {
60 2628 : slv2_value_free(p->plugin_uri);
61 2628 : p->plugin_uri = NULL;
62 :
63 2628 : slv2_value_free(p->bundle_uri);
64 2628 : p->bundle_uri = NULL;
65 :
66 2628 : slv2_value_free(p->binary_uri);
67 2628 : p->binary_uri = NULL;
68 :
69 2628 : if (p->ports)
70 3 : raptor_free_sequence(p->ports);
71 2628 : p->ports = NULL;
72 :
73 2628 : if (p->rdf) {
74 7 : librdf_free_model(p->rdf);
75 7 : p->rdf = NULL;
76 : }
77 :
78 2628 : if (p->storage) {
79 7 : librdf_free_storage(p->storage);
80 7 : p->storage = NULL;
81 : }
82 :
83 2628 : slv2_values_free(p->data_uris);
84 2628 : p->data_uris = NULL;
85 :
86 2628 : free(p);
87 2628 : }
88 :
89 :
90 : /** comparator for sorting */
91 : #if 0
92 : static int
93 : slv2_port_compare_by_index(const void* a, const void* b)
94 : {
95 : SLV2Port port_a = *(SLV2Port*)a;
96 : SLV2Port port_b = *(SLV2Port*)b;
97 :
98 : if (port_a->index < port_b->index)
99 : return -1;
100 : else if (port_a->index == port_b->index)
101 : return 0;
102 : else //if (port_a->index > port_b->index)
103 : return 1;
104 : }
105 : #endif
106 :
107 :
108 : /* private */
109 : void
110 : slv2_plugin_load_if_necessary(SLV2Plugin p)
111 66 : {
112 66 : if (!p->rdf)
113 6 : slv2_plugin_load(p);
114 66 : }
115 :
116 :
117 : /* private */
118 : void
119 : slv2_plugin_load_ports_if_necessary(SLV2Plugin p)
120 99 : {
121 99 : if (!p->rdf)
122 1 : slv2_plugin_load(p);
123 :
124 99 : if (!p->ports) {
125 3 : p->ports = raptor_new_sequence((void (*)(void*))&slv2_port_free, NULL);
126 :
127 : const unsigned char* query = (const unsigned char*)
128 : "PREFIX : <http://lv2plug.in/ns/lv2core#>\n"
129 : "SELECT DISTINCT ?type ?symbol ?index WHERE {\n"
130 : "<> :port ?port .\n"
131 : "?port a ?type ;\n"
132 : " :symbol ?symbol ;\n"
133 : " :index ?index .\n"
134 3 : "} ORDER BY (?index)";
135 :
136 : librdf_query* q = librdf_new_query(p->world->world, "sparql",
137 3 : NULL, query, slv2_value_as_librdf_uri(p->plugin_uri));
138 :
139 3 : librdf_query_results* results = librdf_query_execute(q, p->rdf);
140 :
141 3 : int num_ports = 0;
142 3 : int last_index = -1;
143 :
144 22 : while (!librdf_query_results_finished(results)) {
145 :
146 16 : librdf_node* type_node = librdf_query_results_get_binding_value(results, 0);
147 16 : librdf_node* symbol_node = librdf_query_results_get_binding_value(results, 1);
148 16 : librdf_node* index_node = librdf_query_results_get_binding_value(results, 2);
149 :
150 16 : assert(librdf_node_is_literal(symbol_node));
151 16 : assert(librdf_node_is_literal(index_node));
152 :
153 16 : const char* symbol = (const char*)librdf_node_get_literal_value(symbol_node);
154 16 : const char* index = (const char*)librdf_node_get_literal_value(index_node);
155 :
156 : //printf("PORT: %s %s %s\n", type, index, symbol);
157 :
158 16 : const int this_index = atoi(index);
159 16 : SLV2Port this_port = NULL;
160 :
161 : // ORDER BY guarantees order
162 16 : assert(this_index <= num_ports);
163 :
164 : // Create a new SLV2Port, and add to template
165 16 : if (this_index == num_ports) {
166 8 : assert(this_index == last_index + 1);
167 8 : this_port = slv2_port_new(p->world, (unsigned)atoi(index), symbol);
168 8 : raptor_sequence_push(p->ports, this_port);
169 8 : ++num_ports;
170 8 : ++last_index;
171 :
172 : // More information about a port we already created
173 8 : } else if (this_index < num_ports) {
174 8 : this_port = slv2_plugin_get_port_by_index(p, this_index);
175 : }
176 :
177 16 : if (this_port) {
178 16 : raptor_sequence_push(this_port->classes,
179 : slv2_value_new_librdf_uri(p->world, librdf_node_get_uri(type_node)));
180 : }
181 :
182 16 : librdf_free_node(type_node);
183 16 : librdf_free_node(symbol_node);
184 16 : librdf_free_node(index_node);
185 :
186 16 : librdf_query_results_next(results);
187 : }
188 :
189 3 : librdf_free_query_results(results);
190 3 : librdf_free_query(q);
191 : }
192 99 : }
193 :
194 :
195 : void
196 : slv2_plugin_load(SLV2Plugin p)
197 7 : {
198 : //printf("Loading cache for %s\n", slv2_value_as_string(p->plugin_uri));
199 :
200 7 : if (!p->storage) {
201 7 : assert(!p->rdf);
202 7 : p->storage = librdf_new_storage(p->world->world, "trees", NULL, NULL);
203 7 : if (!p->storage)
204 0 : p->storage = librdf_new_storage(p->world->world, "memory", NULL, NULL);
205 7 : p->rdf = librdf_new_model(p->world->world, p->storage, NULL);
206 : }
207 :
208 : // Parse all the plugin's data files into RDF model
209 21 : for (unsigned i=0; i < slv2_values_size(p->data_uris); ++i) {
210 14 : SLV2Value data_uri_val = slv2_values_get_at(p->data_uris, i);
211 : librdf_uri* data_uri = librdf_new_uri(p->world->world,
212 14 : (const unsigned char*)slv2_value_as_uri(data_uri_val));
213 14 : librdf_parser_parse_into_model(p->world->parser, data_uri, NULL, p->rdf);
214 14 : librdf_free_uri(data_uri);
215 : }
216 7 : }
217 :
218 :
219 : SLV2Value
220 : slv2_plugin_get_uri(SLV2Plugin p)
221 54154 : {
222 54154 : assert(p);
223 54154 : assert(p->plugin_uri);
224 54154 : return p->plugin_uri;
225 : }
226 :
227 :
228 : SLV2Value
229 : slv2_plugin_get_bundle_uri(SLV2Plugin p)
230 3 : {
231 3 : assert(p);
232 3 : assert(p->bundle_uri);
233 3 : return p->bundle_uri;
234 : }
235 :
236 :
237 : SLV2Value
238 : slv2_plugin_get_library_uri(SLV2Plugin p)
239 3 : {
240 3 : assert(p);
241 3 : slv2_plugin_load_if_necessary(p);
242 3 : if (!p->binary_uri) {
243 : const unsigned char* query = (const unsigned char*)
244 : "PREFIX : <http://lv2plug.in/ns/lv2core#>\n"
245 1 : "SELECT ?binary WHERE { <> :binary ?binary . }";
246 :
247 : librdf_query* q = librdf_new_query(p->world->world, "sparql",
248 1 : NULL, query, slv2_value_as_librdf_uri(p->plugin_uri));
249 :
250 1 : librdf_query_results* results = librdf_query_execute(q, p->rdf);
251 :
252 1 : if (!librdf_query_results_finished(results)) {
253 1 : librdf_node* binary_node = librdf_query_results_get_binding_value(results, 0);
254 1 : librdf_uri* binary_uri = librdf_node_get_uri(binary_node);
255 :
256 1 : if (binary_uri) {
257 1 : SLV2Value binary = slv2_value_new_librdf_uri(p->world, binary_uri);
258 1 : p->binary_uri = binary;
259 : }
260 :
261 1 : librdf_free_node(binary_node);
262 : }
263 :
264 1 : librdf_free_query_results(results);
265 1 : librdf_free_query(q);
266 : }
267 3 : return p->binary_uri;
268 : }
269 :
270 :
271 : SLV2Values
272 : slv2_plugin_get_data_uris(SLV2Plugin p)
273 2 : {
274 2 : return p->data_uris;
275 : }
276 :
277 :
278 : SLV2PluginClass
279 : slv2_plugin_get_class(SLV2Plugin p)
280 2 : {
281 2 : slv2_plugin_load_if_necessary(p);
282 2 : if (!p->plugin_class) {
283 : const unsigned char* query = (const unsigned char*)
284 2 : "SELECT DISTINCT ?class WHERE { <> a ?class }";
285 :
286 : librdf_query* q = librdf_new_query(p->world->world, "sparql",
287 2 : NULL, query, slv2_value_as_librdf_uri(p->plugin_uri));
288 :
289 2 : librdf_query_results* results = librdf_query_execute(q, p->rdf);
290 :
291 4 : while (!librdf_query_results_finished(results)) {
292 2 : librdf_node* class_node = librdf_query_results_get_binding_value(results, 0);
293 2 : librdf_uri* class_uri = librdf_node_get_uri(class_node);
294 :
295 2 : if (!class_uri) {
296 0 : librdf_query_results_next(results);
297 0 : continue;
298 : }
299 :
300 2 : SLV2Value class = slv2_value_new_librdf_uri(p->world, class_uri);
301 :
302 2 : if ( ! slv2_value_equals(class, p->world->lv2_plugin_class->uri)) {
303 :
304 : SLV2PluginClass plugin_class = slv2_plugin_classes_get_by_uri(
305 2 : p->world->plugin_classes, class);
306 :
307 2 : librdf_free_node(class_node);
308 :
309 2 : if (plugin_class) {
310 2 : p->plugin_class = plugin_class;
311 2 : slv2_value_free(class);
312 2 : break;
313 : }
314 : }
315 :
316 0 : slv2_value_free(class);
317 0 : librdf_query_results_next(results);
318 : }
319 :
320 2 : if (p->plugin_class == NULL)
321 0 : p->plugin_class = p->world->lv2_plugin_class;
322 :
323 2 : librdf_free_query_results(results);
324 2 : librdf_free_query(q);
325 : }
326 :
327 2 : return p->plugin_class;
328 : }
329 :
330 :
331 : bool
332 : slv2_plugin_verify(SLV2Plugin plugin)
333 5 : {
334 : char* query_str =
335 : "SELECT DISTINCT ?type ?name ?license ?port WHERE {\n"
336 : "<> a ?type ;\n"
337 : "doap:name ?name ;\n"
338 : "doap:license ?license ;\n"
339 5 : "lv2:port [ lv2:index ?port ] .\n}";
340 :
341 5 : SLV2Results results = slv2_plugin_query_sparql(plugin, query_str);
342 :
343 5 : bool has_type = false;
344 5 : bool has_name = false;
345 5 : bool has_license = false;
346 5 : bool has_port = false;
347 :
348 14 : while (!librdf_query_results_finished(results->rdf_results)) {
349 4 : librdf_node* type_node = librdf_query_results_get_binding_value(results->rdf_results, 0);
350 4 : librdf_node* name_node = librdf_query_results_get_binding_value(results->rdf_results, 1);
351 4 : librdf_node* license_node = librdf_query_results_get_binding_value(results->rdf_results, 2);
352 4 : librdf_node* port_node = librdf_query_results_get_binding_value(results->rdf_results, 3);
353 :
354 4 : if (librdf_node_get_type(type_node) == LIBRDF_NODE_TYPE_RESOURCE)
355 4 : has_type = true;
356 :
357 4 : if (name_node)
358 4 : has_name = true;
359 :
360 4 : if (license_node)
361 4 : has_license = true;
362 :
363 4 : if (port_node)
364 4 : has_port = true;
365 :
366 4 : librdf_free_node(type_node);
367 4 : librdf_free_node(name_node);
368 4 : librdf_free_node(license_node);
369 4 : librdf_free_node(port_node);
370 :
371 4 : librdf_query_results_next(results->rdf_results);
372 : }
373 :
374 5 : slv2_results_free(results);
375 :
376 5 : if ( ! (has_type && has_name && has_license && has_port) ) {
377 1 : fprintf(stderr, "Invalid LV2 Plugin %s\n",
378 : slv2_value_as_uri(slv2_plugin_get_uri(plugin)));
379 1 : return false;
380 : } else {
381 4 : return true;
382 : }
383 : }
384 :
385 :
386 : SLV2Value
387 : slv2_plugin_get_name(SLV2Plugin plugin)
388 3 : {
389 3 : SLV2Values results = slv2_plugin_get_value_by_qname_i18n(plugin, "doap:name");
390 3 : SLV2Value ret = NULL;
391 :
392 3 : if (results) {
393 3 : SLV2Value val = slv2_values_get_at(results, 0);
394 3 : if (slv2_value_is_string(val))
395 3 : ret = slv2_value_duplicate(val);
396 3 : slv2_values_free(results);
397 : } else {
398 0 : results = slv2_plugin_get_value_by_qname(plugin, "doap:name");
399 0 : SLV2Value val = slv2_values_get_at(results, 0);
400 0 : if (slv2_value_is_string(val))
401 0 : ret = slv2_value_duplicate(val);
402 0 : slv2_values_free(results);
403 : }
404 :
405 3 : return ret;
406 : }
407 :
408 :
409 : SLV2Values
410 : slv2_plugin_get_value(SLV2Plugin p,
411 : SLV2Value predicate)
412 3 : {
413 3 : char* query = NULL;
414 :
415 : /* Hack around broken RASQAL, full URI predicates don't work :/ */
416 3 : query = slv2_strjoin(
417 : "PREFIX slv2predicate: <", slv2_value_as_string(predicate), ">\n",
418 : "SELECT DISTINCT ?value WHERE {\n"
419 : "<> slv2predicate: ?value .\n"
420 : "}\n", NULL);
421 :
422 3 : SLV2Values result = slv2_plugin_query_variable(p, query, 0);
423 :
424 3 : free(query);
425 :
426 3 : return result;
427 : }
428 :
429 :
430 : /* internal */
431 : SLV2Values
432 : slv2_plugin_get_value_by_qname(SLV2Plugin p,
433 : const char* predicate)
434 20 : {
435 : char* query = slv2_strjoin(
436 : "SELECT DISTINCT ?value WHERE { \n"
437 : "<> ", predicate, " ?value . \n"
438 20 : "}\n", NULL);
439 :
440 20 : SLV2Values result = slv2_plugin_query_variable(p, query, 0);
441 :
442 20 : free(query);
443 :
444 20 : return result;
445 : }
446 :
447 :
448 : /* internal: get i18n value if possible */
449 : SLV2Values
450 : slv2_plugin_get_value_by_qname_i18n(SLV2Plugin p,
451 : const char* predicate)
452 3 : {
453 : char* query = slv2_strjoin(
454 : "SELECT DISTINCT ?value WHERE { \n"
455 : "<> ", predicate, " ?value . \n"
456 : "FILTER(lang(?value) = \"", slv2_get_lang(), "\") \n"
457 3 : "}\n", NULL);
458 :
459 3 : SLV2Values result = slv2_plugin_query_variable(p, query, 0);
460 :
461 3 : free(query);
462 :
463 3 : return result;
464 : }
465 :
466 :
467 : SLV2Values
468 : slv2_plugin_get_value_for_subject(SLV2Plugin p,
469 : SLV2Value subject,
470 : SLV2Value predicate)
471 2 : {
472 2 : if ( ! slv2_value_is_uri(subject)) {
473 0 : fprintf(stderr, "slv2_plugin_get_value_for_subject error: "
474 : "subject is not a URI\n");
475 0 : return NULL;
476 : }
477 :
478 2 : char* query = NULL;
479 :
480 :
481 :
482 2 : char* subject_token = slv2_value_get_turtle_token(subject);
483 :
484 : /* Hack around broken RASQAL, full URI predicates don't work :/ */
485 2 : query = slv2_strjoin(
486 : "PREFIX slv2predicate: <", slv2_value_as_string(predicate), ">\n",
487 : "SELECT DISTINCT ?value WHERE {\n",
488 : subject_token, " slv2predicate: ?value .\n"
489 : "}\n", NULL);
490 :
491 2 : SLV2Values result = slv2_plugin_query_variable(p, query, 0);
492 :
493 2 : free(query);
494 2 : free(subject_token);
495 :
496 2 : return result;
497 : }
498 :
499 :
500 : SLV2Values
501 : slv2_plugin_get_properties(SLV2Plugin p)
502 0 : {
503 : // FIXME: APIBREAK: This predicate does not even exist. Remove this function.
504 0 : return slv2_plugin_get_value_by_qname(p, "lv2:pluginProperty");
505 : }
506 :
507 :
508 : SLV2Values
509 : slv2_plugin_get_hints(SLV2Plugin p)
510 0 : {
511 : // FIXME: APIBREAK: This predicate does not even exist. Remove this function.
512 0 : return slv2_plugin_get_value_by_qname(p, "lv2:pluginHint");
513 : }
514 :
515 :
516 : uint32_t
517 : slv2_plugin_get_num_ports(SLV2Plugin p)
518 65 : {
519 65 : slv2_plugin_load_ports_if_necessary(p);
520 65 : return raptor_sequence_size(p->ports);
521 : }
522 :
523 :
524 : void
525 : slv2_plugin_get_port_float_values(SLV2Plugin p,
526 : const char* qname,
527 : float* values)
528 6 : {
529 6 : slv2_plugin_load_ports_if_necessary(p);
530 :
531 24 : for (int i = 0; i < raptor_sequence_size(p->ports); ++i)
532 18 : values[i] = NAN;
533 :
534 : unsigned char* query = (unsigned char*)slv2_strjoin(
535 : "PREFIX : <http://lv2plug.in/ns/lv2core#>\n"
536 : "SELECT DISTINCT ?index ?value WHERE {\n"
537 : "<> :port ?port .\n"
538 : "?port :index ?index .\n"
539 : "?port ", qname, " ?value .\n"
540 6 : "} ", NULL);
541 :
542 : librdf_query* q = librdf_new_query(p->world->world, "sparql",
543 6 : NULL, query, slv2_value_as_librdf_uri(p->plugin_uri));
544 :
545 6 : librdf_query_results* results = librdf_query_execute(q, p->rdf);
546 :
547 24 : while (!librdf_query_results_finished(results)) {
548 12 : librdf_node* idx_node = librdf_query_results_get_binding_value(results, 0);
549 12 : librdf_node* val_node = librdf_query_results_get_binding_value(results, 1);
550 12 : if (idx_node && val_node && librdf_node_is_literal(idx_node)
551 : && librdf_node_is_literal(val_node)) {
552 12 : const int idx = atoi((const char*)librdf_node_get_literal_value(idx_node));
553 12 : const float val = atof((const char*)librdf_node_get_literal_value(val_node));
554 12 : values[idx] = val;
555 12 : librdf_free_node(idx_node);
556 12 : librdf_free_node(val_node);
557 : }
558 12 : librdf_query_results_next(results);
559 : }
560 :
561 6 : librdf_free_query_results(results);
562 6 : librdf_free_query(q);
563 6 : free(query);
564 6 : }
565 :
566 :
567 : void
568 : slv2_plugin_get_port_ranges_float(SLV2Plugin p,
569 : float* min_values,
570 : float* max_values,
571 : float* def_values)
572 2 : {
573 2 : if (min_values)
574 2 : slv2_plugin_get_port_float_values(p, ":minimum", min_values);
575 :
576 2 : if (max_values)
577 2 : slv2_plugin_get_port_float_values(p, ":maximum", max_values);
578 :
579 2 : if (def_values)
580 2 : slv2_plugin_get_port_float_values(p, ":default", def_values);
581 2 : }
582 :
583 :
584 : uint32_t
585 : slv2_plugin_get_num_ports_of_class(SLV2Plugin p,
586 : SLV2Value class_1, ...)
587 16 : {
588 16 : slv2_plugin_load_ports_if_necessary(p);
589 :
590 16 : uint32_t ret = 0;
591 : va_list args;
592 :
593 64 : for (unsigned i=0; i < slv2_plugin_get_num_ports(p); ++i) {
594 48 : SLV2Port port = raptor_sequence_get_at(p->ports, i);
595 48 : if (!slv2_port_is_a(p, port, class_1))
596 24 : continue;
597 :
598 24 : va_start(args, class_1);
599 :
600 24 : bool matches = true;
601 54 : for (SLV2Value class_i = NULL; (class_i = va_arg(args, SLV2Value)) != NULL ; ) {
602 12 : if (!slv2_port_is_a(p, port, class_i)) {
603 6 : va_end(args);
604 6 : matches = false;
605 6 : break;
606 : }
607 : }
608 :
609 24 : if (matches)
610 18 : ++ret;
611 :
612 24 : va_end(args);
613 : }
614 :
615 16 : return ret;
616 : }
617 :
618 :
619 : bool
620 : slv2_plugin_has_latency(SLV2Plugin p)
621 2 : {
622 : const char* const query =
623 : "SELECT ?index WHERE {\n"
624 : " <> lv2:port ?port .\n"
625 : " ?port lv2:portProperty lv2:reportsLatency ;\n"
626 : " lv2:index ?index .\n"
627 2 : "}\n";
628 :
629 2 : SLV2Values results = slv2_plugin_query_variable(p, query, 0);
630 2 : const bool latent = (slv2_values_size(results) > 0);
631 2 : slv2_values_free(results);
632 :
633 2 : return latent;
634 : }
635 :
636 :
637 : uint32_t
638 : slv2_plugin_get_latency_port_index(SLV2Plugin p)
639 2 : {
640 : const char* const query =
641 : "SELECT ?index WHERE {\n"
642 : " <> lv2:port ?port .\n"
643 : " ?port lv2:portProperty lv2:reportsLatency ;\n"
644 : " lv2:index ?index .\n"
645 2 : "}\n";
646 :
647 2 : SLV2Values result = slv2_plugin_query_variable(p, query, 0);
648 :
649 : // FIXME: need a sane error handling strategy
650 2 : assert(slv2_values_size(result) > 0);
651 2 : SLV2Value val = slv2_values_get_at(result, 0);
652 2 : assert(slv2_value_is_int(val));
653 :
654 2 : int ret = slv2_value_as_int(val);
655 2 : slv2_values_free(result);
656 2 : return ret;
657 : }
658 :
659 :
660 : bool
661 : slv2_plugin_has_feature(SLV2Plugin p,
662 : SLV2Value feature)
663 6 : {
664 6 : SLV2Values features = slv2_plugin_get_supported_features(p);
665 :
666 6 : const bool ret = features && feature && slv2_values_contains(features, feature);
667 :
668 6 : slv2_values_free(features);
669 6 : return ret;
670 : }
671 :
672 :
673 : SLV2Values
674 : slv2_plugin_get_supported_features(SLV2Plugin p)
675 8 : {
676 8 : SLV2Values optional = slv2_plugin_get_optional_features(p);
677 8 : SLV2Values required = slv2_plugin_get_required_features(p);
678 :
679 8 : SLV2Values result = slv2_values_new();
680 8 : unsigned n_optional = slv2_values_size(optional);
681 8 : unsigned n_required = slv2_values_size(required);
682 8 : unsigned i = 0;
683 16 : for ( ; i < n_optional; ++i)
684 8 : slv2_values_set_at(result, i, raptor_sequence_pop(optional));
685 16 : for ( ; i < n_optional + n_required; ++i)
686 8 : slv2_values_set_at(result, i, raptor_sequence_pop(required));
687 :
688 8 : slv2_values_free(optional);
689 8 : slv2_values_free(required);
690 :
691 8 : return result;
692 : }
693 :
694 :
695 : SLV2Values
696 : slv2_plugin_get_optional_features(SLV2Plugin p)
697 10 : {
698 10 : return slv2_plugin_get_value_by_qname(p, "lv2:optionalFeature");
699 : }
700 :
701 :
702 : SLV2Values
703 : slv2_plugin_get_required_features(SLV2Plugin p)
704 10 : {
705 10 : return slv2_plugin_get_value_by_qname(p, "lv2:requiredFeature");
706 : }
707 :
708 :
709 : SLV2Port
710 : slv2_plugin_get_port_by_index(SLV2Plugin p,
711 : uint32_t index)
712 10 : {
713 10 : slv2_plugin_load_ports_if_necessary(p);
714 10 : return raptor_sequence_get_at(p->ports, (int)index);
715 : }
716 :
717 :
718 : SLV2Port
719 : slv2_plugin_get_port_by_symbol(SLV2Plugin p,
720 : SLV2Value symbol)
721 2 : {
722 2 : slv2_plugin_load_ports_if_necessary(p);
723 4 : for (int i=0; i < raptor_sequence_size(p->ports); ++i) {
724 3 : SLV2Port port = raptor_sequence_get_at(p->ports, i);
725 3 : if (slv2_value_equals(port->symbol, symbol))
726 1 : return port;
727 : }
728 :
729 1 : return NULL;
730 : }
731 :
732 :
733 : SLV2Value
734 : slv2_plugin_get_author_name(SLV2Plugin plugin)
735 2 : {
736 2 : SLV2Value ret = NULL;
737 :
738 : const char* const query =
739 : "SELECT ?name WHERE {\n"
740 : " <> doap:maintainer ?maint . \n"
741 : " ?maint foaf:name ?name . \n"
742 2 : "}\n";
743 :
744 2 : SLV2Values results = slv2_plugin_query_variable(plugin, query, 0);
745 :
746 2 : if (results && slv2_values_size(results) > 0) {
747 2 : SLV2Value val = slv2_values_get_at(results, 0);
748 2 : if (slv2_value_is_string(val))
749 2 : ret = slv2_value_duplicate(val);
750 : }
751 :
752 2 : if (results)
753 2 : slv2_values_free(results);
754 :
755 2 : return ret;
756 : }
757 :
758 :
759 : SLV2Value
760 : slv2_plugin_get_author_email(SLV2Plugin plugin)
761 2 : {
762 2 : SLV2Value ret = NULL;
763 :
764 : const char* const query =
765 : "SELECT ?email WHERE {\n"
766 : " <> doap:maintainer ?maint . \n"
767 : " ?maint foaf:mbox ?email . \n"
768 2 : "}\n";
769 :
770 2 : SLV2Values results = slv2_plugin_query_variable(plugin, query, 0);
771 :
772 2 : if (results && slv2_values_size(results) > 0) {
773 2 : SLV2Value val = slv2_values_get_at(results, 0);
774 2 : if (slv2_value_is_uri(val))
775 2 : ret = slv2_value_duplicate(val);
776 : }
777 :
778 2 : if (results)
779 2 : slv2_values_free(results);
780 :
781 2 : return ret;
782 : }
783 :
784 :
785 : SLV2Value
786 : slv2_plugin_get_author_homepage(SLV2Plugin plugin)
787 2 : {
788 2 : SLV2Value ret = NULL;
789 :
790 : const char* const query =
791 : "SELECT ?page WHERE {\n"
792 : " <> doap:maintainer ?maint . \n"
793 : " ?maint foaf:homepage ?page . \n"
794 2 : "}\n";
795 :
796 2 : SLV2Values results = slv2_plugin_query_variable(plugin, query, 0);
797 :
798 2 : if (results && slv2_values_size(results) > 0) {
799 2 : SLV2Value val = slv2_values_get_at(results, 0);
800 2 : if (slv2_value_is_uri(val))
801 2 : ret = slv2_value_duplicate(val);
802 : }
803 :
804 2 : if (results)
805 2 : slv2_values_free(results);
806 :
807 2 : return ret;
808 : }
809 :
810 :
811 : SLV2UIs
812 : slv2_plugin_get_uis(SLV2Plugin plugin)
813 3 : {
814 : const char* const query_str =
815 : "PREFIX uiext: <http://lv2plug.in/ns/extensions/ui#>\n"
816 : "SELECT DISTINCT ?uri ?type ?binary WHERE {\n"
817 : "<> uiext:ui ?uri .\n"
818 : "?uri a ?type ;\n"
819 : " uiext:binary ?binary .\n"
820 3 : "}\n";
821 :
822 3 : SLV2Results results = slv2_plugin_query_sparql(plugin, query_str);
823 :
824 3 : SLV2UIs result = slv2_uis_new();
825 :
826 10 : while (!librdf_query_results_finished(results->rdf_results)) {
827 4 : librdf_node* uri_node = librdf_query_results_get_binding_value(results->rdf_results, 0);
828 4 : librdf_node* type_node = librdf_query_results_get_binding_value(results->rdf_results, 1);
829 4 : librdf_node* binary_node = librdf_query_results_get_binding_value(results->rdf_results, 2);
830 :
831 : SLV2UI ui = slv2_ui_new(plugin->world,
832 : librdf_node_get_uri(uri_node),
833 : librdf_node_get_uri(type_node),
834 4 : librdf_node_get_uri(binary_node));
835 :
836 4 : raptor_sequence_push(result, ui);
837 :
838 4 : librdf_free_node(uri_node);
839 4 : librdf_free_node(type_node);
840 4 : librdf_free_node(binary_node);
841 :
842 4 : librdf_query_results_next(results->rdf_results);
843 : }
844 :
845 3 : slv2_results_free(results);
846 :
847 3 : if (slv2_uis_size(result) > 0) {
848 1 : return result;
849 : } else {
850 2 : slv2_uis_free(result);
851 2 : return NULL;
852 : }
853 : }
854 :
|