2 Copyright (C) 2003 Paul Davis
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include <cstdio> // Needed so that libraptor (included in lrdf) won't complain
29 #include <pbd/compose.h>
31 #include <ardour/ardour.h>
32 #include <ardour/configuration.h>
33 #include <ardour/audio_library.h>
34 #include <ardour/utils.h>
39 using namespace ARDOUR;
43 bool operator() (string a, string b) const {
44 return cmp_nocase(Library->get_label(a), Library->get_label(b)) == -1;
49 static char* GROUP = "http://ardour.org/ontology/Group";
50 static char* SOUNDFILE = "http://ardour.org/ontology/Soundfile";
51 static char* hasFile = "http://ardour.org/ontology/hasFile";
52 static char* memberOf = "http://ardour.org/ontology/memberOf";
53 static char* subGroupOf = "http://ardour.org/ontology/subGroupOf";
55 AudioLibrary::AudioLibrary ()
57 src = "file:" + Config->get_user_ardour_path() + "sfdb";
59 // workaround for possible bug in raptor that crashes when saving to a
61 touch_file(Config->get_user_ardour_path() + "sfdb");
63 lrdf_read_file(src.c_str());
65 lrdf_statement pattern;
67 pattern.subject = GROUP;
68 pattern.predicate = RDF_TYPE;
69 pattern.object = RDFS_CLASS;
70 pattern.object_type = lrdf_uri;
72 lrdf_statement* matches = lrdf_matches(&pattern);
74 // if empty DB, create basic schema
80 lrdf_free_statements(matches);
83 AudioLibrary::~AudioLibrary ()
88 AudioLibrary::initialize_db ()
90 // define ardour:Group
91 lrdf_add_triple(src.c_str(), GROUP, RDF_TYPE, RDFS_CLASS, lrdf_uri);
92 // define ardour:Soundfile
93 lrdf_add_triple(src.c_str(), SOUNDFILE, RDF_TYPE, RDFS_CLASS, lrdf_uri);
95 // add intergral fields
96 add_field("channels");
97 add_field("samplerate");
98 add_field("resolution");
103 AudioLibrary::save_changes ()
105 if (lrdf_export_by_source(src.c_str(), src.substr(5).c_str())) {
106 warning << string_compose(_("Could not open %1. Audio Library not saved"), src) << endmsg;
111 AudioLibrary::add_group (string group, string parent_uri)
113 string local_group(string_compose("file:sfbd/group/%1", get_uid()));
115 lrdf_add_triple(src.c_str(), local_group.c_str(),
116 RDFS_BASE "label", group.c_str(), lrdf_literal);
118 if (parent_uri == ""){
119 lrdf_add_triple(src.c_str(), local_group.c_str(),
120 subGroupOf, GROUP, lrdf_uri);
122 lrdf_add_triple(src.c_str(), local_group.c_str(),
123 subGroupOf, parent_uri.c_str(), lrdf_uri);
126 added_group(local_group, parent_uri); /* EMIT SIGNAL */
132 AudioLibrary::remove_group (string uri)
135 list<string>::iterator i;
137 get_members(items, uri);
138 for (i = items.begin(); i != items.end(); ++i) {
144 get_groups(items, uri);
145 for (i = items.begin(); i != items.end(); ++i) {
149 lrdf_remove_uri_matches(uri.c_str());
151 removed_group(uri); /* EMIT SIGNAL */
155 AudioLibrary::get_groups (list<string>& groups, string parent_uri)
157 lrdf_statement pattern;
160 pattern.predicate = subGroupOf;
161 if (parent_uri == ""){
162 pattern.object = strdup(GROUP);
164 pattern.object = strdup(parent_uri.c_str());
167 lrdf_statement* matches = lrdf_matches(&pattern);
169 lrdf_statement* current = matches;
170 while (current != 0) {
171 groups.push_back(current->subject);
172 current = current->next;
175 lrdf_free_statements(matches);
176 free (pattern.object);
184 AudioLibrary::add_member (string member, string parent_uri)
186 string local_member(string_compose("file:sfdb/soundfile/%1", get_uid()));
187 string file_uri(string_compose("file:%1", member));
189 lrdf_add_triple(src.c_str(), local_member.c_str(), RDF_TYPE,
190 SOUNDFILE, lrdf_uri);
191 lrdf_add_triple(src.c_str(), local_member.c_str(), hasFile,
192 file_uri.c_str(), lrdf_uri);
194 string::size_type size = member.find_last_of('/');
195 string label = member.substr(++size);
197 lrdf_add_triple(src.c_str(), local_member.c_str(), RDFS_BASE "label",
198 label.c_str(), lrdf_literal);
200 if (parent_uri == ""){
201 lrdf_add_triple(src.c_str(), local_member.c_str(), memberOf,
204 lrdf_add_triple(src.c_str(), local_member.c_str(), memberOf,
205 parent_uri.c_str(), lrdf_uri);
208 added_member (local_member, parent_uri); /* EMIT SIGNAL */
214 AudioLibrary::remove_member (string uri)
216 lrdf_remove_uri_matches (uri.c_str());
218 removed_member(uri); /* EMIT SIGNAL */
222 AudioLibrary::get_members (list<string>& members, string parent_uri)
224 lrdf_statement pattern;
227 pattern.predicate = memberOf;
228 if (parent_uri == ""){
229 pattern.object = strdup(GROUP);
231 pattern.object = strdup(parent_uri.c_str());
234 lrdf_statement* matches = lrdf_matches(&pattern);
236 lrdf_statement* current = matches;
237 while (current != 0) {
238 members.push_back(current->subject);
239 current = current->next;
242 lrdf_free_statements(matches);
243 free (pattern.object);
251 AudioLibrary::search_members_and (list<string>& members,
252 const map<string,string>& fields)
254 lrdf_statement **head;
255 lrdf_statement* pattern = 0;
256 lrdf_statement* old = 0;
259 map<string,string>::const_iterator i;
260 for (i = fields.begin(); i != fields.end(); ++i){
261 pattern = new lrdf_statement;
262 pattern->subject = "?";
263 pattern->predicate = strdup(field_uri(i->first).c_str());
264 pattern->object = strdup((i->second).c_str());
271 lrdf_uris* ulist = lrdf_match_multi(*head);
272 for (uint32_t j = 0; ulist && j < ulist->count; ++j) {
273 // printf("AND: %s\n", ulist->items[j]);
274 members.push_back(ulist->items[j]);
276 lrdf_free_uris(ulist);
286 free(pattern->predicate);
287 free(pattern->object);
289 pattern = pattern->next;
295 AudioLibrary::search_members_or (list<string>& members,
296 const map<string,string>& fields)
298 map<string,string>::const_iterator i;
300 lrdf_statement pattern;
301 for (i = fields.begin(); i != fields.end(); ++i) {
303 pattern.predicate = strdup(field_uri(i->first).c_str());
304 pattern.object = strdup((i->second).c_str());
305 pattern.object_type = lrdf_literal;
307 lrdf_statement* matched = lrdf_matches(&pattern);
309 lrdf_statement* old = matched;
311 // printf ("OR: %s\n", matched->subject);
312 members.push_back(matched->subject);
313 matched = matched->next;
316 free(pattern.predicate);
317 free(pattern.object);
318 lrdf_free_statements (old);
327 AudioLibrary::get_member_filename (string uri)
329 lrdf_statement pattern;
330 pattern.subject = strdup(uri.c_str());
331 pattern.predicate = hasFile;
333 pattern.object_type = lrdf_uri;
335 lrdf_statement* matches = lrdf_matches(&pattern);
337 string file = matches->object;
338 lrdf_free_statements(matches);
340 string::size_type pos = file.find(":");
341 return file.substr(++pos);
343 warning << _("Could not find member filename") << endmsg;
349 AudioLibrary::add_field (string name)
351 string local_field = field_uri(name);
352 lrdf_statement pattern;
353 pattern.subject = strdup(local_field.c_str());
354 pattern.predicate = RDF_TYPE;
355 pattern.object = RDF_BASE "Property";
356 pattern.object_type = lrdf_uri;
358 if(lrdf_exists_match(&pattern)) {
362 // of type rdf:Property
363 lrdf_add_triple(src.c_str(), local_field.c_str(), RDF_TYPE,
364 RDF_BASE "Property", lrdf_uri);
365 // of range ardour:Soundfile
366 lrdf_add_triple(src.c_str(), local_field.c_str(), RDFS_BASE "range",
367 SOUNDFILE, lrdf_uri);
368 // of domain rdf:Literal
369 lrdf_add_triple(src.c_str(), local_field.c_str(), RDFS_BASE "domain",
370 RDF_BASE "Literal", lrdf_uri);
372 set_label (local_field, name);
374 fields_changed(); /* EMIT SIGNAL */
378 AudioLibrary::get_fields (list<string>& fields)
380 lrdf_statement pattern;
383 pattern.predicate = RDFS_BASE "range";
384 pattern.object = SOUNDFILE;
385 pattern.object_type = lrdf_uri;
387 lrdf_statement* matches = lrdf_matches(&pattern);
389 lrdf_statement* current = matches;
390 while (current != 0) {
391 fields.push_back(get_label(current->subject));
393 current = current->next;
396 lrdf_free_statements(matches);
403 AudioLibrary::remove_field (string name)
405 lrdf_remove_uri_matches(field_uri(name).c_str());
406 fields_changed (); /* EMIT SIGNAL */
410 AudioLibrary::get_field (string uri, string field)
412 lrdf_statement pattern;
414 pattern.subject = strdup(uri.c_str());
416 pattern.predicate = strdup(field_uri(field).c_str());
419 pattern.object_type = lrdf_literal;
421 lrdf_statement* matches = lrdf_matches(&pattern);
422 free(pattern.subject);
423 free(pattern.predicate);
427 object << matches->object;
430 lrdf_free_statements(matches);
435 AudioLibrary::set_field (string uri, string field, string literal)
437 lrdf_statement pattern;
439 pattern.subject = strdup(uri.c_str());
441 string local_field = field_uri(field);
442 pattern.predicate = strdup(local_field.c_str());
445 pattern.object_type = lrdf_literal;
447 lrdf_remove_matches(&pattern);
448 free(pattern.subject);
449 free(pattern.predicate);
451 lrdf_add_triple(src.c_str(), uri.c_str(), local_field.c_str(),
452 literal.c_str(), lrdf_literal);
454 fields_changed(); /* EMIT SIGNAL */
458 AudioLibrary::field_uri (string name)
460 stringstream local_field;
461 local_field << "file:sfdb/fields/" << name;
463 return local_field.str();
467 AudioLibrary::get_label (string uri)
469 lrdf_statement pattern;
470 pattern.subject = strdup(uri.c_str());
471 pattern.predicate = RDFS_BASE "label";
473 pattern.object_type = lrdf_literal;
475 lrdf_statement* matches = lrdf_matches (&pattern);
476 free(pattern.subject);
480 label << matches->object;
483 lrdf_free_statements(matches);
489 AudioLibrary::set_label (string uri, string label)
491 lrdf_statement pattern;
492 pattern.subject = strdup(uri.c_str());
493 pattern.predicate = RDFS_BASE "label";
495 pattern.object_type = lrdf_literal;
497 lrdf_remove_matches(&pattern);
498 free(pattern.subject);
500 lrdf_add_triple(src.c_str(), uri.c_str(), RDFS_BASE "label",
501 label.c_str(), lrdf_literal);