*/
#include <cstdio> // Needed so that libraptor (included in lrdf) won't complain
+#include <cerrno>
#include <iostream>
#include <sstream>
#include <cctype>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fts.h>
+
#include <lrdf.h>
#include <pbd/compose.h>
using namespace std;
using namespace ARDOUR;
+using namespace PBD;
-namespace std {
-struct UriSorter {
- bool operator() (string a, string b) const {
- return cmp_nocase(Library->get_label(a), Library->get_label(b)) == -1;
- }
-};
-};
-
-static char* GROUP = "http://ardour.org/ontology/Group";
static char* SOUNDFILE = "http://ardour.org/ontology/Soundfile";
-static char* hasFile = "http://ardour.org/ontology/hasFile";
-static char* memberOf = "http://ardour.org/ontology/memberOf";
-static char* subGroupOf = "http://ardour.org/ontology/subGroupOf";
+
+string AudioLibrary::state_node_name = "AudioLibrary";
AudioLibrary::AudioLibrary ()
{
- src = "file:" + Config->get_user_ardour_path() + "sfdb";
+// sfdb_paths.push_back("/Users/taybin/sounds");
+
+ src = "file:" + get_user_ardour_path() + "sfdb";
// workaround for possible bug in raptor that crashes when saving to a
// non-existant file.
- touch_file(Config->get_user_ardour_path() + "sfdb");
+ touch_file(get_user_ardour_path() + "sfdb");
lrdf_read_file(src.c_str());
lrdf_statement pattern;
- pattern.subject = GROUP;
+ pattern.subject = SOUNDFILE;
pattern.predicate = RDF_TYPE;
pattern.object = RDFS_CLASS;
pattern.object_type = lrdf_uri;
void
AudioLibrary::initialize_db ()
{
- // define ardour:Group
- lrdf_add_triple(src.c_str(), GROUP, RDF_TYPE, RDFS_CLASS, lrdf_uri);
// define ardour:Soundfile
lrdf_add_triple(src.c_str(), SOUNDFILE, RDF_TYPE, RDFS_CLASS, lrdf_uri);
// add intergral fields
- add_field("channels");
- add_field("samplerate");
- add_field("resolution");
- add_field("format");
+ add_field(_("channels"));
+ add_field(_("samplerate"));
+ add_field(_("resolution"));
+ add_field(_("format"));
}
void
AudioLibrary::save_changes ()
{
if (lrdf_export_by_source(src.c_str(), src.substr(5).c_str())) {
- warning << compose(_("Could not open %1. Audio Library not saved"), src) << endmsg;
- }
-}
-
-string
-AudioLibrary::add_group (string group, string parent_uri)
-{
- string local_group(compose("file:sfbd/group/%1", get_uid()));
-
- lrdf_add_triple(src.c_str(), local_group.c_str(),
- RDFS_BASE "label", group.c_str(), lrdf_literal);
-
- if (parent_uri == ""){
- lrdf_add_triple(src.c_str(), local_group.c_str(),
- subGroupOf, GROUP, lrdf_uri);
- } else {
- lrdf_add_triple(src.c_str(), local_group.c_str(),
- subGroupOf, parent_uri.c_str(), lrdf_uri);
- }
-
- added_group(local_group, parent_uri); /* EMIT SIGNAL */
-
- return local_group;
-}
-
-void
-AudioLibrary::remove_group (string uri)
-{
- list<string> items;
- list<string>::iterator i;
-
- get_members(items, uri);
- for (i = items.begin(); i != items.end(); ++i) {
- remove_member(*i);
+ warning << string_compose(_("Could not open %1. Audio Library not saved"), src) << endmsg;
}
-
- items.clear();
-
- get_groups(items, uri);
- for (i = items.begin(); i != items.end(); ++i) {
- remove_group(*i);
- }
-
- lrdf_remove_uri_matches(uri.c_str());
- save_changes ();
-
- removed_group(uri); /* EMIT SIGNAL */
}
void
-AudioLibrary::get_groups (list<string>& groups, string parent_uri)
-{
- lrdf_statement pattern;
-
- pattern.subject = 0;
- pattern.predicate = subGroupOf;
- if (parent_uri == ""){
- pattern.object = strdup(GROUP);
- } else {
- pattern.object = strdup(parent_uri.c_str());
- }
-
- lrdf_statement* matches = lrdf_matches(&pattern);
-
- lrdf_statement* current = matches;
- while (current != 0) {
- groups.push_back(current->subject);
- current = current->next;
- }
-
- lrdf_free_statements(matches);
- free (pattern.object);
-
- UriSorter cmp;
- groups.sort(cmp);
- groups.unique();
-}
-
-string
-AudioLibrary::add_member (string member, string parent_uri)
+AudioLibrary::add_member (string member)
{
- string local_member(compose("file:sfdb/soundfile/%1", get_uid()));
- string file_uri(compose("file:%1", member));
+ string file_uri(string_compose("file:%1", member));
- lrdf_add_triple(src.c_str(), local_member.c_str(), RDF_TYPE,
+ lrdf_add_triple(src.c_str(), file_uri.c_str(), RDF_TYPE,
SOUNDFILE, lrdf_uri);
- lrdf_add_triple(src.c_str(), local_member.c_str(), hasFile,
- file_uri.c_str(), lrdf_uri);
-
- string::size_type size = member.find_last_of('/');
- string label = member.substr(++size);
-
- lrdf_add_triple(src.c_str(), local_member.c_str(), RDFS_BASE "label",
- label.c_str(), lrdf_literal);
-
- if (parent_uri == ""){
- lrdf_add_triple(src.c_str(), local_member.c_str(), memberOf,
- GROUP, lrdf_uri);
- } else {
- lrdf_add_triple(src.c_str(), local_member.c_str(), memberOf,
- parent_uri.c_str(), lrdf_uri);
- }
-
- save_changes ();
-
- added_member (local_member, parent_uri); /* EMIT SIGNAL */
-
- return local_member;
}
void
AudioLibrary::remove_member (string uri)
{
lrdf_remove_uri_matches (uri.c_str());
-
- save_changes ();
-
- removed_member(uri); /* EMIT SIGNAL */
-}
-
-void
-AudioLibrary::get_members (list<string>& members, string parent_uri)
-{
- lrdf_statement pattern;
-
- pattern.subject = 0;
- pattern.predicate = memberOf;
- if (parent_uri == ""){
- pattern.object = strdup(GROUP);
- } else {
- pattern.object = strdup(parent_uri.c_str());
- }
-
- lrdf_statement* matches = lrdf_matches(&pattern);
-
- lrdf_statement* current = matches;
- while (current != 0) {
- members.push_back(current->subject);
- current = current->next;
- }
-
- lrdf_free_statements(matches);
- free (pattern.object);
-
- UriSorter cmp;
- members.sort(cmp);
- members.unique();
}
void
-AudioLibrary::search_members_and (list<string>& members,
+AudioLibrary::search_members_and (vector<string>& members,
const map<string,string>& fields)
{
lrdf_statement **head;
}
lrdf_free_uris(ulist);
- UriSorter cmp;
- members.sort(cmp);
- members.unique();
+ compact_vector(members);
}
// memory clean up
}
void
-AudioLibrary::search_members_or (list<string>& members,
+AudioLibrary::search_members_or (vector<string>& members,
const map<string,string>& fields)
{
map<string,string>::const_iterator i;
lrdf_free_statements (old);
}
- UriSorter cmp;
- members.sort(cmp);
- members.unique();
-}
-
-string
-AudioLibrary::get_member_filename (string uri)
-{
- lrdf_statement pattern;
- pattern.subject = strdup(uri.c_str());
- pattern.predicate = hasFile;
- pattern.object = 0;
- pattern.object_type = lrdf_uri;
-
- lrdf_statement* matches = lrdf_matches(&pattern);
- if (matches) {
- string file = matches->object;
- lrdf_free_statements(matches);
-
- string::size_type pos = file.find(":");
- return file.substr(++pos);
- } else {
- warning << _("Could not find member filename") << endmsg;
- return "-Unknown-";
- }
+ compact_vector(members);
}
void
set_label (local_field, name);
- save_changes();
-
- fields_changed(); /* EMIT SIGNAL */
+ fields_changed(); /* EMIT SIGNAL */
}
void
-AudioLibrary::get_fields (list<string>& fields)
+AudioLibrary::get_fields (vector<string>& fields)
{
lrdf_statement pattern;
lrdf_free_statements(matches);
- fields.sort();
- fields.unique();
+ compact_vector(fields);
}
void
AudioLibrary::remove_field (string name)
{
lrdf_remove_uri_matches(field_uri(name).c_str());
- save_changes();
- fields_changed (); /* EMIT SIGNAL */
+ fields_changed (); /* EMIT SIGNAL */
}
string
lrdf_add_triple(src.c_str(), uri.c_str(), local_field.c_str(),
literal.c_str(), lrdf_literal);
- save_changes();
-
fields_changed(); /* EMIT SIGNAL */
}
label.c_str(), lrdf_literal);
}
+void
+AudioLibrary::compact_vector(vector<string>& vec)
+{
+ sort(vec.begin(), vec.end());
+ unique(vec.begin(), vec.end());
+}
+
+void
+AudioLibrary::set_paths (vector<string> paths)
+{
+ sfdb_paths = paths;
+
+ scan_paths ();
+}
+
+vector<string>
+AudioLibrary::get_paths ()
+{
+ return sfdb_paths;
+}
+
+void
+AudioLibrary::scan_paths ()
+{
+ if (sfdb_paths.size() < 1) {
+ return;
+ }
+
+ vector<char *> pathv(sfdb_paths.size());
+ unsigned int i;
+ for (i = 0; i < sfdb_paths.size(); ++i) {
+ pathv[i] = new char[sfdb_paths[i].length() +1];
+ sfdb_paths[i].copy(pathv[i], string::npos);
+ pathv[i][sfdb_paths[i].length()] = 0;
+ }
+ pathv[i] = 0;
+
+ FTS* ft = fts_open(&pathv[0], FTS_LOGICAL|FTS_NOSTAT|FTS_PHYSICAL|FTS_XDEV, 0);
+ if (errno) {
+ error << strerror(errno) << endmsg;
+ return;
+ }
+
+ lrdf_statement s;
+ s.predicate = RDF_TYPE;
+ s.object = SOUNDFILE;
+ s.object_type = lrdf_uri;
+ string filename;
+ while (FTSENT* file = fts_read(ft)) {
+ if ((file->fts_info & FTS_F) && (safe_file_extension(file->fts_name))) {
+ filename = "file:";
+ filename.append(file->fts_accpath);
+ s.subject = strdup(filename.c_str());
+ if (lrdf_exists_match(&s)) {
+ continue;
+ } else {
+ add_member(file->fts_accpath);
+ cout << file->fts_accpath << endl;
+ }
+ free(s.subject);
+ }
+ }
+ fts_close(ft);
+
+ for (i = 0; i < pathv.size(); ++i) {
+ delete[] pathv[i];
+ }
+
+ save_changes();
+}
+
+bool
+AudioLibrary::safe_file_extension(string file)
+{
+ return !(file.rfind(".wav") == string::npos &&
+ file.rfind(".aiff")== string::npos &&
+ file.rfind(".aif") == string::npos &&
+ file.rfind(".snd") == string::npos &&
+ file.rfind(".au") == string::npos &&
+ file.rfind(".raw") == string::npos &&
+ file.rfind(".sf") == string::npos &&
+ file.rfind(".cdr") == string::npos &&
+ file.rfind(".smp") == string::npos &&
+ file.rfind(".maud")== string::npos &&
+ file.rfind(".vwe") == string::npos &&
+ file.rfind(".paf") == string::npos &&
+#ifdef HAVE_COREAUDIO
+ file.rfind(".mp3") == string::npos &&
+ file.rfind(".aac") == string::npos &&
+ file.rfind(".mp4") == string::npos &&
+#endif // HAVE_COREAUDIO
+ file.rfind(".voc") == string::npos);
+}
+
+XMLNode&
+AudioLibrary::get_state ()
+{
+ XMLNode* root = new XMLNode(X_("AudioLibrary"));
+
+ for (vector<string>::iterator i = sfdb_paths.begin(); i != sfdb_paths.end(); ++i) {
+ XMLNode* node = new XMLNode(X_("Path"));
+ node->add_property("value", *i);
+ root->add_child_nocopy(*node);
+ }
+
+ return *root;
+}
+
+int
+AudioLibrary::set_state (const XMLNode& node)
+{
+ if (node.name() != X_("AudioLibrary")) {
+ fatal << "programming error: AudioLibrary: incorrect XML node sent to set_state()" << endmsg;
+ return -1;
+ }
+
+ XMLNodeList nodes = node.children(X_("Path"));
+
+ vector<string> paths;
+ XMLProperty* prop;
+ XMLNode* child;
+ for (XMLNodeConstIterator iter = nodes.begin(); iter != nodes.end(); ++iter) {
+ child = *iter;
+
+ if ((prop = child->property(X_("value"))) != 0) {
+ paths.push_back(prop->value());
+ }
+ }
+
+ set_paths (paths);
+
+ return 0;
+}