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
28 #include <sys/types.h>
34 #include <pbd/compose.h>
36 #include <ardour/ardour.h>
37 #include <ardour/configuration.h>
38 #include <ardour/audio_library.h>
39 #include <ardour/utils.h>
44 using namespace ARDOUR;
46 static char* SOUNDFILE = "http://ardour.org/ontology/Soundfile";
48 AudioLibrary::AudioLibrary ()
50 // sfdb_paths.push_back("/Users/taybin/sounds");
52 src = "file:" + Config->get_user_ardour_path() + "sfdb";
54 // workaround for possible bug in raptor that crashes when saving to a
56 touch_file(Config->get_user_ardour_path() + "sfdb");
58 lrdf_read_file(src.c_str());
60 lrdf_statement pattern;
62 pattern.subject = SOUNDFILE;
63 pattern.predicate = RDF_TYPE;
64 pattern.object = RDFS_CLASS;
65 pattern.object_type = lrdf_uri;
67 lrdf_statement* matches = lrdf_matches(&pattern);
69 // if empty DB, create basic schema
75 lrdf_free_statements(matches);
80 AudioLibrary::~AudioLibrary ()
85 AudioLibrary::initialize_db ()
87 // define ardour:Soundfile
88 lrdf_add_triple(src.c_str(), SOUNDFILE, RDF_TYPE, RDFS_CLASS, lrdf_uri);
90 // add intergral fields
91 add_field(_("channels"));
92 add_field(_("samplerate"));
93 add_field(_("resolution"));
94 add_field(_("format"));
98 AudioLibrary::save_changes ()
100 if (lrdf_export_by_source(src.c_str(), src.substr(5).c_str())) {
101 warning << string_compose(_("Could not open %1. Audio Library not saved"), src) << endmsg;
106 AudioLibrary::add_member (string member)
108 string file_uri(string_compose("file:%1", member));
110 lrdf_add_triple(src.c_str(), file_uri.c_str(), RDF_TYPE,
111 SOUNDFILE, lrdf_uri);
115 AudioLibrary::remove_member (string uri)
117 lrdf_remove_uri_matches (uri.c_str());
121 AudioLibrary::search_members_and (vector<string>& members,
122 const map<string,string>& fields)
124 lrdf_statement **head;
125 lrdf_statement* pattern = 0;
126 lrdf_statement* old = 0;
129 map<string,string>::const_iterator i;
130 for (i = fields.begin(); i != fields.end(); ++i){
131 pattern = new lrdf_statement;
132 pattern->subject = "?";
133 pattern->predicate = strdup(field_uri(i->first).c_str());
134 pattern->object = strdup((i->second).c_str());
141 lrdf_uris* ulist = lrdf_match_multi(*head);
142 for (uint32_t j = 0; ulist && j < ulist->count; ++j) {
143 // printf("AND: %s\n", ulist->items[j]);
144 members.push_back(ulist->items[j]);
146 lrdf_free_uris(ulist);
148 compact_vector(members);
154 free(pattern->predicate);
155 free(pattern->object);
157 pattern = pattern->next;
163 AudioLibrary::search_members_or (vector<string>& members,
164 const map<string,string>& fields)
166 map<string,string>::const_iterator i;
168 lrdf_statement pattern;
169 for (i = fields.begin(); i != fields.end(); ++i) {
171 pattern.predicate = strdup(field_uri(i->first).c_str());
172 pattern.object = strdup((i->second).c_str());
173 pattern.object_type = lrdf_literal;
175 lrdf_statement* matched = lrdf_matches(&pattern);
177 lrdf_statement* old = matched;
179 // printf ("OR: %s\n", matched->subject);
180 members.push_back(matched->subject);
181 matched = matched->next;
184 free(pattern.predicate);
185 free(pattern.object);
186 lrdf_free_statements (old);
189 compact_vector(members);
193 AudioLibrary::add_field (string name)
195 string local_field = field_uri(name);
196 lrdf_statement pattern;
197 pattern.subject = strdup(local_field.c_str());
198 pattern.predicate = RDF_TYPE;
199 pattern.object = RDF_BASE "Property";
200 pattern.object_type = lrdf_uri;
202 if(lrdf_exists_match(&pattern)) {
206 // of type rdf:Property
207 lrdf_add_triple(src.c_str(), local_field.c_str(), RDF_TYPE,
208 RDF_BASE "Property", lrdf_uri);
209 // of range ardour:Soundfile
210 lrdf_add_triple(src.c_str(), local_field.c_str(), RDFS_BASE "range",
211 SOUNDFILE, lrdf_uri);
212 // of domain rdf:Literal
213 lrdf_add_triple(src.c_str(), local_field.c_str(), RDFS_BASE "domain",
214 RDF_BASE "Literal", lrdf_uri);
216 set_label (local_field, name);
218 fields_changed(); /* EMIT SIGNAL */
222 AudioLibrary::get_fields (vector<string>& fields)
224 lrdf_statement pattern;
227 pattern.predicate = RDFS_BASE "range";
228 pattern.object = SOUNDFILE;
229 pattern.object_type = lrdf_uri;
231 lrdf_statement* matches = lrdf_matches(&pattern);
233 lrdf_statement* current = matches;
234 while (current != 0) {
235 fields.push_back(get_label(current->subject));
237 current = current->next;
240 lrdf_free_statements(matches);
242 compact_vector(fields);
246 AudioLibrary::remove_field (string name)
248 lrdf_remove_uri_matches(field_uri(name).c_str());
249 fields_changed (); /* EMIT SIGNAL */
253 AudioLibrary::get_field (string uri, string field)
255 lrdf_statement pattern;
257 pattern.subject = strdup(uri.c_str());
259 pattern.predicate = strdup(field_uri(field).c_str());
262 pattern.object_type = lrdf_literal;
264 lrdf_statement* matches = lrdf_matches(&pattern);
265 free(pattern.subject);
266 free(pattern.predicate);
270 object << matches->object;
273 lrdf_free_statements(matches);
278 AudioLibrary::set_field (string uri, string field, string literal)
280 lrdf_statement pattern;
282 pattern.subject = strdup(uri.c_str());
284 string local_field = field_uri(field);
285 pattern.predicate = strdup(local_field.c_str());
288 pattern.object_type = lrdf_literal;
290 lrdf_remove_matches(&pattern);
291 free(pattern.subject);
292 free(pattern.predicate);
294 lrdf_add_triple(src.c_str(), uri.c_str(), local_field.c_str(),
295 literal.c_str(), lrdf_literal);
297 fields_changed(); /* EMIT SIGNAL */
301 AudioLibrary::field_uri (string name)
303 stringstream local_field;
304 local_field << "file:sfdb/fields/" << name;
306 return local_field.str();
310 AudioLibrary::get_label (string uri)
312 lrdf_statement pattern;
313 pattern.subject = strdup(uri.c_str());
314 pattern.predicate = RDFS_BASE "label";
316 pattern.object_type = lrdf_literal;
318 lrdf_statement* matches = lrdf_matches (&pattern);
319 free(pattern.subject);
323 label << matches->object;
326 lrdf_free_statements(matches);
332 AudioLibrary::set_label (string uri, string label)
334 lrdf_statement pattern;
335 pattern.subject = strdup(uri.c_str());
336 pattern.predicate = RDFS_BASE "label";
338 pattern.object_type = lrdf_literal;
340 lrdf_remove_matches(&pattern);
341 free(pattern.subject);
343 lrdf_add_triple(src.c_str(), uri.c_str(), RDFS_BASE "label",
344 label.c_str(), lrdf_literal);
348 AudioLibrary::compact_vector(vector<string>& vec)
350 sort(vec.begin(), vec.end());
351 unique(vec.begin(), vec.end());
355 AudioLibrary::set_paths (vector<string> paths)
361 AudioLibrary::get_paths ()
367 AudioLibrary::scan_paths ()
369 if (sfdb_paths.size() < 1) {
373 vector<char *> pathv(sfdb_paths.size());
375 for (i = 0; i < sfdb_paths.size(); ++i) {
376 pathv[i] = new char[sfdb_paths[i].length() +1];
377 sfdb_paths[i].copy(pathv[i], string::npos);
378 pathv[i][sfdb_paths[i].length()] = 0;
382 FTS* ft = fts_open(&pathv[0], FTS_LOGICAL|FTS_NOSTAT|FTS_PHYSICAL|FTS_XDEV, 0);
384 error << strerror(errno) << endmsg;
389 s.predicate = RDF_TYPE;
390 s.object = SOUNDFILE;
391 s.object_type = lrdf_uri;
393 while (FTSENT* file = fts_read(ft)) {
394 if ((file->fts_info & FTS_F) && (safe_file_extension(file->fts_name))) {
396 filename.append(file->fts_accpath);
397 s.subject = strdup(filename.c_str());
398 if (lrdf_exists_match(&s)) {
401 add_member(file->fts_accpath);
402 cout << file->fts_accpath << endl;
409 for (i = 0; i < pathv.size(); ++i) {
417 AudioLibrary::safe_file_extension(string file)
419 return !(file.rfind(".wav") == string::npos &&
420 file.rfind(".aiff")== string::npos &&
421 file.rfind(".aif") == string::npos &&
422 file.rfind(".snd") == string::npos &&
423 file.rfind(".au") == string::npos &&
424 file.rfind(".raw") == string::npos &&
425 file.rfind(".sf") == string::npos &&
426 file.rfind(".cdr") == string::npos &&
427 file.rfind(".smp") == string::npos &&
428 file.rfind(".maud")== string::npos &&
429 file.rfind(".vwe") == string::npos &&
430 file.rfind(".paf") == string::npos &&
431 file.rfind(".voc") == string::npos);