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 : #include "slv2-config.h"
20 :
21 : #define _XOPEN_SOURCE 500
22 : #include <string.h>
23 : #include <stdlib.h>
24 : #include <dirent.h>
25 : #include <string.h>
26 : #include <librdf.h>
27 : #include "slv2/types.h"
28 : #include "slv2/world.h"
29 : #include "slv2/slv2.h"
30 : #include "slv2/util.h"
31 : #include "slv2_internal.h"
32 :
33 :
34 : /* private */
35 : static SLV2World
36 : slv2_world_new_internal(SLV2World world)
37 10 : {
38 10 : assert(world);
39 10 : assert(world->world);
40 :
41 10 : world->storage = librdf_new_storage(world->world, "trees", NULL, NULL);
42 10 : if (!world->storage) {
43 0 : fprintf(stderr, "Warning: Unable to create \"trees\" RDF storage.\n"
44 : "Performance can be improved by upgrading librdf.\n");
45 0 : world->storage = librdf_new_storage(world->world, "hashes", NULL,
46 : "hash-type='memory'");
47 : }
48 :
49 10 : if (!world->storage)
50 0 : goto fail;
51 :
52 10 : world->model = librdf_new_model(world->world, world->storage, NULL);
53 10 : if (!world->model)
54 0 : goto fail;
55 :
56 10 : world->parser = librdf_new_parser(world->world, "turtle", NULL, NULL);
57 10 : if (!world->parser)
58 0 : goto fail;
59 :
60 10 : world->plugin_classes = slv2_plugin_classes_new();
61 :
62 10 : world->plugins = slv2_plugins_new();
63 :
64 10 : world->lv2_specification_node = librdf_new_node_from_uri_string(world->world,
65 : (const unsigned char*)"http://lv2plug.in/ns/lv2core#Specification");
66 :
67 10 : world->lv2_plugin_node = librdf_new_node_from_uri_string(world->world,
68 : (const unsigned char*)"http://lv2plug.in/ns/lv2core#Plugin");
69 :
70 10 : world->rdf_a_node = librdf_new_node_from_uri_string(world->world,
71 : (const unsigned char*)"http://www.w3.org/1999/02/22-rdf-syntax-ns#type");
72 :
73 10 : world->xsd_integer_node = librdf_new_node_from_uri_string(world->world,
74 : (const unsigned char*)"http://www.w3.org/2001/XMLSchema#integer");
75 :
76 10 : world->xsd_decimal_node = librdf_new_node_from_uri_string(world->world,
77 : (const unsigned char*)"http://www.w3.org/2001/XMLSchema#decimal");
78 :
79 10 : world->lv2_plugin_class = slv2_plugin_class_new(world, NULL,
80 : librdf_node_get_uri(world->lv2_plugin_node), "Plugin");
81 :
82 10 : return world;
83 :
84 0 : fail:
85 0 : /* keep on rockin' in the */ free(world);
86 0 : return NULL;
87 : }
88 :
89 :
90 : SLV2World
91 : slv2_world_new()
92 10 : {
93 10 : SLV2World world = (SLV2World)malloc(sizeof(struct _SLV2World));
94 :
95 10 : world->world = librdf_new_world();
96 10 : if (!world->world) {
97 0 : free(world);
98 0 : return NULL;
99 : }
100 :
101 10 : world->local_world = true;
102 :
103 10 : librdf_world_open(world->world);
104 :
105 10 : return slv2_world_new_internal(world);
106 : }
107 :
108 :
109 : SLV2World
110 : slv2_world_new_using_rdf_world(librdf_world* rdf_world)
111 0 : {
112 0 : if (rdf_world == NULL)
113 0 : return slv2_world_new();
114 :
115 0 : SLV2World world = (SLV2World)malloc(sizeof(struct _SLV2World));
116 :
117 0 : world->world = rdf_world;
118 0 : world->local_world = false;
119 :
120 0 : return slv2_world_new_internal(world);
121 : }
122 :
123 :
124 : void
125 : slv2_world_free(SLV2World world)
126 10 : {
127 10 : slv2_plugin_class_free(world->lv2_plugin_class);
128 10 : world->lv2_plugin_class = NULL;
129 :
130 10 : librdf_free_node(world->lv2_specification_node);
131 10 : librdf_free_node(world->lv2_plugin_node);
132 10 : librdf_free_node(world->rdf_a_node);
133 10 : librdf_free_node(world->xsd_integer_node);
134 10 : librdf_free_node(world->xsd_decimal_node);
135 :
136 2638 : for (int i=0; i < raptor_sequence_size(world->plugins); ++i)
137 2628 : slv2_plugin_free(raptor_sequence_get_at(world->plugins, i));
138 10 : raptor_free_sequence(world->plugins);
139 10 : world->plugins = NULL;
140 :
141 10 : raptor_free_sequence(world->plugin_classes);
142 10 : world->plugin_classes = NULL;
143 :
144 10 : librdf_free_parser(world->parser);
145 10 : world->parser = NULL;
146 :
147 10 : librdf_free_model(world->model);
148 10 : world->model = NULL;
149 :
150 10 : librdf_free_storage(world->storage);
151 10 : world->storage = NULL;
152 :
153 10 : if (world->local_world)
154 10 : librdf_free_world(world->world);
155 :
156 10 : world->world = NULL;
157 :
158 10 : free(world);
159 10 : }
160 :
161 :
162 : /** Load the entire contents of a file into the world model.
163 : */
164 : void
165 : slv2_world_load_file(SLV2World world, librdf_uri* file_uri)
166 18 : {
167 18 : librdf_parser_parse_into_model(world->parser, file_uri, NULL, world->model);
168 18 : }
169 :
170 :
171 :
172 : void
173 : slv2_world_load_bundle(SLV2World world, SLV2Value bundle_uri)
174 1044 : {
175 : librdf_uri* manifest_uri = librdf_new_uri_relative_to_base(
176 1044 : bundle_uri->val.uri_val, (const unsigned char*)"manifest.ttl");
177 :
178 : /* Parse the manifest into a temporary model */
179 1044 : librdf_storage* manifest_storage = librdf_new_storage(world->world, "trees", NULL, NULL);
180 1044 : if (manifest_storage == NULL)
181 0 : manifest_storage = librdf_new_storage(world->world, "memory", NULL, NULL);
182 :
183 : librdf_model* manifest_model = librdf_new_model(world->world,
184 1044 : manifest_storage, NULL);
185 1044 : librdf_parser_parse_into_model(world->parser, manifest_uri, NULL,
186 : manifest_model);
187 :
188 : /* Query statement: ?plugin a lv2:Plugin */
189 : librdf_statement* q = librdf_new_statement_from_nodes(world->world,
190 : NULL, librdf_new_node_from_node(world->rdf_a_node),
191 1044 : librdf_new_node_from_node(world->lv2_plugin_node));
192 :
193 1044 : librdf_stream* results = librdf_model_find_statements(manifest_model, q);
194 :
195 5049 : while (!librdf_stream_end(results)) {
196 2961 : librdf_statement* s = librdf_stream_get_object(results);
197 :
198 2961 : librdf_node* plugin_node = librdf_new_node_from_node(librdf_statement_get_subject(s));
199 :
200 : /* Add ?plugin rdfs:seeAlso <manifest.ttl>*/
201 2961 : librdf_node* subject = plugin_node;
202 : librdf_node* predicate = librdf_new_node_from_uri_string(world->world,
203 2961 : (unsigned char*)"http://www.w3.org/2000/01/rdf-schema#seeAlso");
204 : librdf_node* object = librdf_new_node_from_uri(world->world,
205 2961 : manifest_uri);
206 :
207 2961 : librdf_model_add(world->model, subject, predicate, object);
208 :
209 : /* Add ?plugin slv2:bundleURI <file://some/path> */
210 2961 : subject = librdf_new_node_from_node(plugin_node);
211 2961 : predicate = librdf_new_node_from_uri_string(world->world,
212 : (unsigned char*)"http://drobilla.net/ns/slv2#bundleURI");
213 2961 : object = librdf_new_node_from_uri(world->world, bundle_uri->val.uri_val);
214 :
215 2961 : librdf_model_add(world->model, subject, predicate, object);
216 :
217 2961 : librdf_stream_next(results);
218 : }
219 :
220 1044 : librdf_free_stream(results);
221 1044 : librdf_free_statement(q);
222 :
223 : /* Query statement: ?specification a lv2:Specification */
224 1044 : q = librdf_new_statement_from_nodes(world->world,
225 : NULL, librdf_new_node_from_node(world->rdf_a_node),
226 : librdf_new_node_from_node(world->lv2_specification_node));
227 :
228 1044 : results = librdf_model_find_statements(manifest_model, q);
229 :
230 2097 : while (!librdf_stream_end(results)) {
231 9 : librdf_statement* s = librdf_stream_get_object(results);
232 :
233 9 : librdf_node* spec_node = librdf_new_node_from_node(librdf_statement_get_subject(s));
234 :
235 : /* Add ?specification rdfs:seeAlso <manifest.ttl> */
236 9 : librdf_node* subject = spec_node;
237 : librdf_node* predicate = librdf_new_node_from_uri_string(world->world,
238 9 : (unsigned char*)"http://www.w3.org/2000/01/rdf-schema#seeAlso");
239 : librdf_node* object = librdf_new_node_from_uri(world->world,
240 9 : manifest_uri);
241 :
242 9 : librdf_model_add(world->model, subject, predicate, object);
243 :
244 : /* Add ?specification slv2:bundleURI <file://some/path> */
245 9 : subject = librdf_new_node_from_node(spec_node);
246 9 : predicate = librdf_new_node_from_uri_string(world->world,
247 : (unsigned char*)"http://drobilla.net/ns/slv2#bundleURI");
248 9 : object = librdf_new_node_from_uri(world->world, bundle_uri->val.uri_val);
249 :
250 9 : librdf_model_add(world->model, subject, predicate, object);
251 :
252 9 : librdf_stream_next(results);
253 : }
254 :
255 1044 : librdf_free_stream(results);
256 1044 : librdf_free_statement(q);
257 :
258 : /* Join the temporary model to the main model */
259 1044 : librdf_stream* manifest_stream = librdf_model_as_stream(manifest_model);
260 1044 : librdf_model_add_statements(world->model, manifest_stream);
261 1044 : librdf_free_stream(manifest_stream);
262 :
263 1044 : librdf_free_model(manifest_model);
264 1044 : librdf_free_storage(manifest_storage);
265 1044 : librdf_free_uri(manifest_uri);
266 1044 : }
267 :
268 :
269 : /** Load all bundles under a directory.
270 : * Private.
271 : */
272 : void
273 : slv2_world_load_directory(SLV2World world, const char* dir)
274 27 : {
275 27 : DIR* pdir = opendir(dir);
276 27 : if (!pdir)
277 0 : return;
278 :
279 : struct dirent* pfile;
280 1179 : while ((pfile = readdir(pdir))) {
281 1125 : if (!strcmp(pfile->d_name, ".") || !strcmp(pfile->d_name, ".."))
282 : continue;
283 :
284 1071 : char* uri = slv2_strjoin("file://", dir, "/", pfile->d_name, "/", NULL);
285 :
286 : // FIXME: Probably a better way to check if a dir exists
287 1071 : DIR* bundle_dir = opendir(uri + 7);
288 :
289 1071 : if (bundle_dir != NULL) {
290 1044 : closedir(bundle_dir);
291 1044 : SLV2Value uri_val = slv2_value_new_uri(world, uri);
292 1044 : slv2_world_load_bundle(world, uri_val);
293 1044 : slv2_value_free(uri_val);
294 : }
295 :
296 1071 : free(uri);
297 : }
298 :
299 27 : closedir(pdir);
300 : }
301 :
302 :
303 : void
304 : slv2_world_load_path(SLV2World world,
305 : const char* lv2_path)
306 9 : {
307 9 : char* path = slv2_strjoin(lv2_path, ":", NULL);
308 9 : char* dir = path; // Pointer into path
309 :
310 : // Go through string replacing ':' with '\0', using the substring,
311 : // then replacing it with 'X' and moving on. i.e. strtok on crack.
312 45 : while (strchr(path, ':') != NULL) {
313 27 : char* delim = strchr(path, ':');
314 27 : *delim = '\0';
315 :
316 27 : slv2_world_load_directory(world, dir);
317 :
318 27 : *delim = 'X';
319 27 : dir = delim + 1;
320 : }
321 :
322 9 : free(path);
323 9 : }
324 :
325 :
326 : /** Comparator for sorting SLV2Plugins */
327 : int
328 : slv2_plugin_compare_by_uri(const void* a, const void* b)
329 1387827 : {
330 1387827 : SLV2Plugin plugin_a = *(SLV2Plugin*)a;
331 1387827 : SLV2Plugin plugin_b = *(SLV2Plugin*)b;
332 :
333 1387827 : return strcmp(slv2_value_as_uri(plugin_a->plugin_uri),
334 : slv2_value_as_uri(plugin_b->plugin_uri));
335 : }
336 :
337 :
338 : /** Comparator for sorting SLV2PluginClasses */
339 : int
340 : slv2_plugin_class_compare_by_uri(const void* a, const void* b)
341 20970 : {
342 20970 : SLV2PluginClass class_a = *(SLV2PluginClass*)a;
343 20970 : SLV2PluginClass class_b = *(SLV2PluginClass*)b;
344 :
345 20970 : return strcmp(slv2_value_as_uri(class_a->uri),
346 : slv2_value_as_uri(class_b->uri));
347 : }
348 :
349 :
350 : void
351 : slv2_world_load_specifications(SLV2World world)
352 9 : {
353 : unsigned char* query_string = (unsigned char*)
354 : "PREFIX : <http://lv2plug.in/ns/lv2core#>\n"
355 : "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>\n"
356 : "SELECT DISTINCT ?spec ?data WHERE {\n"
357 : " ?spec a :Specification ;\n"
358 : " rdfs:seeAlso ?data .\n"
359 9 : "}\n";
360 :
361 9 : librdf_query* q = librdf_new_query(world->world, "sparql", NULL, query_string, NULL);
362 :
363 9 : librdf_query_results* results = librdf_query_execute(q, world->model);
364 :
365 36 : while (!librdf_query_results_finished(results)) {
366 18 : librdf_node* spec_node = librdf_query_results_get_binding_value(results, 0);
367 : //librdf_uri* spec_uri = librdf_node_get_uri(spec_node);
368 18 : librdf_node* data_node = librdf_query_results_get_binding_value(results, 1);
369 18 : librdf_uri* data_uri = librdf_node_get_uri(data_node);
370 :
371 18 : slv2_world_load_file(world, data_uri);
372 :
373 18 : librdf_free_node(spec_node);
374 18 : librdf_free_node(data_node);
375 :
376 18 : librdf_query_results_next(results);
377 : }
378 :
379 9 : librdf_free_query_results(results);
380 9 : librdf_free_query(q);
381 9 : }
382 :
383 :
384 : void
385 : slv2_world_load_plugin_classes(SLV2World world)
386 9 : {
387 : // FIXME: This will need to be a bit more clever when more data is around
388 : // then the ontology (ie classes which aren't LV2 plugin_classes)
389 :
390 : // FIXME: This loads things that aren't plugin categories
391 :
392 : unsigned char* query_string = (unsigned char*)
393 : "PREFIX : <http://lv2plug.in/ns/lv2core#>\n"
394 : "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>\n"
395 : "SELECT DISTINCT ?class ?parent ?label WHERE {\n"
396 : //" ?plugin a ?class .\n"
397 : " ?class a rdfs:Class; rdfs:subClassOf ?parent; rdfs:label ?label\n"
398 9 : "}\n"; // ORDER BY ?class\n";
399 :
400 : librdf_query* q = librdf_new_query(world->world, "sparql",
401 9 : NULL, query_string, NULL);
402 :
403 9 : librdf_query_results* results = librdf_query_execute(q, world->model);
404 :
405 423 : while (!librdf_query_results_finished(results)) {
406 405 : librdf_node* class_node = librdf_query_results_get_binding_value(results, 0);
407 405 : librdf_uri* class_uri = librdf_node_get_uri(class_node);
408 405 : librdf_node* parent_node = librdf_query_results_get_binding_value(results, 1);
409 405 : librdf_uri* parent_uri = librdf_node_get_uri(parent_node);
410 405 : librdf_node* label_node = librdf_query_results_get_binding_value(results, 2);
411 405 : const char* label = (const char*)librdf_node_get_literal_value(label_node);
412 :
413 405 : assert(class_uri);
414 :
415 : SLV2PluginClass plugin_class = slv2_plugin_class_new(world,
416 405 : parent_uri, class_uri, label);
417 405 : raptor_sequence_push(world->plugin_classes, plugin_class);
418 : // FIXME: Slow! ORDER BY broken in certain versions of redland?
419 405 : raptor_sequence_sort(world->plugin_classes, slv2_plugin_class_compare_by_uri);
420 :
421 405 : librdf_free_node(class_node);
422 405 : librdf_free_node(parent_node);
423 405 : librdf_free_node(label_node);
424 :
425 405 : librdf_query_results_next(results);
426 : }
427 :
428 : // FIXME: filter list here
429 :
430 9 : librdf_free_query_results(results);
431 9 : librdf_free_query(q);
432 9 : }
433 :
434 :
435 : void
436 : slv2_world_load_all(SLV2World world)
437 9 : {
438 9 : char* lv2_path = getenv("LV2_PATH");
439 :
440 : /* 1. Read all manifest files into model */
441 :
442 9 : if (lv2_path) {
443 0 : slv2_world_load_path(world, lv2_path);
444 : } else {
445 9 : const char* const home = getenv("HOME");
446 9 : if (home) {
447 : #ifdef __APPLE__
448 : const char* const suffix = "/Library/Audio/Plug-Ins/LV2:/Library/Audio/Plug-Ins/LV2"
449 : ":/usr/local/lib/lv2:/usr/lib/lv2";
450 : #else
451 9 : const char* const suffix = "/.lv2:/usr/local/lib/lv2:/usr/lib/lv2";
452 : #endif
453 9 : lv2_path = slv2_strjoin(home, suffix, NULL);
454 : } else {
455 : #ifdef __APPLE__
456 : lv2_path = strdup("/Library/Audio/Plug-Ins/LV2:/usr/local/lib/lv2:/usr/lib/lv2");
457 : #else
458 0 : lv2_path = strdup("/usr/local/lib/lv2:/usr/lib/lv2");
459 : #endif
460 : }
461 :
462 9 : slv2_world_load_path(world, lv2_path);
463 :
464 9 : free(lv2_path);
465 : }
466 :
467 :
468 : /* 2. Query out things to cache */
469 :
470 9 : slv2_world_load_specifications(world);
471 :
472 9 : slv2_world_load_plugin_classes(world);
473 :
474 : // Find all plugins and associated data files
475 : unsigned char* query_string = (unsigned char*)
476 : "PREFIX : <http://lv2plug.in/ns/lv2core#>\n"
477 : "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>\n"
478 : "PREFIX slv2: <http://drobilla.net/ns/slv2#>\n"
479 : "SELECT DISTINCT ?plugin ?data ?bundle\n"
480 9 : "WHERE { ?plugin a :Plugin; slv2:bundleURI ?bundle; rdfs:seeAlso ?data }\n";
481 : //"ORDER BY ?plugin\n";
482 :
483 : librdf_query* q = librdf_new_query(world->world, "sparql",
484 9 : NULL, query_string, NULL);
485 :
486 9 : librdf_query_results* results = librdf_query_execute(q, world->model);
487 :
488 7434 : while (!librdf_query_results_finished(results)) {
489 :
490 7416 : librdf_node* plugin_node = librdf_query_results_get_binding_value(results, 0);
491 7416 : librdf_uri* plugin_uri = librdf_node_get_uri(plugin_node);
492 7416 : librdf_node* data_node = librdf_query_results_get_binding_value(results, 1);
493 7416 : librdf_uri* data_uri = librdf_node_get_uri(data_node);
494 7416 : librdf_node* bundle_node = librdf_query_results_get_binding_value(results, 2);
495 7416 : librdf_uri* bundle_uri = librdf_node_get_uri(bundle_node);
496 :
497 7416 : assert(plugin_uri);
498 7416 : assert(data_uri);
499 :
500 7416 : SLV2Value uri = slv2_value_new_librdf_uri(world, plugin_uri);
501 7416 : SLV2Plugin plugin = slv2_plugins_get_by_uri(world->plugins, uri);
502 :
503 : // Create a new SLV2Plugin
504 7416 : if (!plugin) {
505 2628 : plugin = slv2_plugin_new(world, uri, bundle_uri);
506 2628 : raptor_sequence_push(world->plugins, plugin);
507 : // FIXME: Slow! ORDER BY broken in certain versions of redland?
508 2628 : raptor_sequence_sort(world->plugins, slv2_plugin_compare_by_uri);
509 : } else {
510 4788 : slv2_value_free(uri);
511 : }
512 :
513 7416 : plugin->world = world;
514 :
515 : // FIXME: check for duplicates
516 7416 : raptor_sequence_push(plugin->data_uris,
517 : slv2_value_new_librdf_uri(plugin->world, data_uri));
518 :
519 7416 : librdf_free_node(plugin_node);
520 7416 : librdf_free_node(data_node);
521 7416 : librdf_free_node(bundle_node);
522 :
523 7416 : librdf_query_results_next(results);
524 : }
525 :
526 9 : if (results)
527 9 : librdf_free_query_results(results);
528 :
529 9 : librdf_free_query(q);
530 9 : }
531 :
532 :
533 : #if 0
534 : void
535 : slv2_world_serialize(const char* filename)
536 : {
537 : librdf_uri* lv2_uri = librdf_new_uri(slv2_rdf_world,
538 : (unsigned char*)"http://lv2plug.in/ns/lv2core#");
539 :
540 : librdf_uri* rdfs_uri = librdf_new_uri(slv2_rdf_world,
541 : (unsigned char*)"http://www.w3.org/2000/01/rdf-schema#");
542 :
543 : // Write out test file
544 : librdf_serializer* serializer = librdf_new_serializer(slv2_rdf_world,
545 : "turtle", NULL, NULL);
546 : librdf_serializer_set_namespace(serializer, lv2_uri, "");
547 : librdf_serializer_set_namespace(serializer, rdfs_uri, "rdfs");
548 : librdf_serializer_serialize_world_to_file(serializer, filename, NULL, slv2_model);
549 : librdf_free_serializer(serializer);
550 : }
551 : #endif
552 :
553 :
554 : SLV2PluginClass
555 : slv2_world_get_plugin_class(SLV2World world)
556 1 : {
557 1 : return world->lv2_plugin_class;
558 : }
559 :
560 :
561 : SLV2PluginClasses
562 : slv2_world_get_plugin_classes(SLV2World world)
563 1 : {
564 1 : return world->plugin_classes;
565 : }
566 :
567 :
568 : SLV2Plugins
569 : slv2_world_get_all_plugins(SLV2World world)
570 7 : {
571 7 : return world->plugins;
572 : }
573 :
574 :
575 : SLV2Plugins
576 : slv2_world_get_plugins_by_filter(SLV2World world, bool (*include)(SLV2Plugin))
577 4 : {
578 4 : SLV2Plugins result = slv2_plugins_new();
579 :
580 1172 : for (int i=0; i < raptor_sequence_size(world->plugins); ++i) {
581 1168 : SLV2Plugin p = raptor_sequence_get_at(world->plugins, i);
582 1168 : if (include(p))
583 293 : raptor_sequence_push(result, p);
584 : }
585 :
586 4 : return result;
587 : }
588 :
589 :
590 : #if 0
591 : SLV2Plugins
592 : slv2_world_get_plugins_by_query(SLV2World world, const char* query)
593 : {
594 : SLV2Plugins list = slv2_plugins_new();
595 :
596 : librdf_query* rq = librdf_new_query(world->world, "sparql",
597 : NULL, (const unsigned char*)query, NULL);
598 :
599 : librdf_query_results* results = librdf_query_execute(rq, world->model);
600 :
601 : while (!librdf_query_results_finished(results)) {
602 : librdf_node* plugin_node = librdf_query_results_get_binding_value(results, 0);
603 : librdf_uri* plugin_uri = librdf_node_get_uri(plugin_node);
604 :
605 : SLV2Plugin plugin = slv2_plugins_get_by_uri(list,
606 : (const char*)librdf_uri_as_string(plugin_uri));
607 :
608 : /* Create a new SLV2Plugin */
609 : if (!plugin) {
610 : SLV2Plugin new_plugin = slv2_plugin_new(world, plugin_uri);
611 : raptor_sequence_push(list, new_plugin);
612 : }
613 :
614 : librdf_free_node(plugin_node);
615 :
616 : librdf_query_results_next(results);
617 : }
618 :
619 : if (results)
620 : librdf_free_query_results(results);
621 :
622 : librdf_free_query(rq);
623 :
624 : return list;
625 : }
626 : #endif
627 :
|