fix crash when copy'ing latent plugins
[ardour.git] / libs / ardour / audio_library.cc
index f49fb4e280bc073f8160e8ad2afbf003f9869244..2f09a37633062d55fc13f0be90c864c08a3be54c 100644 (file)
@@ -1,6 +1,5 @@
 /*
-    Copyright (C) 2003 Paul Davis 
-    Author: Taybin Rutkin
+    Copyright (C) 2003-2006 Paul Davis
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
-    $Id$
 */
 
-#include <cstdio> // Needed so that libraptor (included in lrdf) won't complain
-#include <iostream>
+#ifdef WAF_BUILD
+#include "libardour-config.h"
+#endif
+
 #include <sstream>
-#include <cctype>
 
+#include <libxml/uri.h>
+
+#ifdef HAVE_LRDF
 #include <lrdf.h>
+#endif
+
+#include <glibmm/miscutils.h>
 
-#include <pbd/compose.h>
+#include <glibmm/convert.h>
 
-#include <ardour/ardour.h>
-#include <ardour/configuration.h>
-#include <ardour/audio_library.h>
-#include <ardour/utils.h>
+#include "pbd/compose.h"
+#include "pbd/error.h"
+#include "pbd/file_utils.h"
 
-#include "i18n.h"
+#include "ardour/audio_library.h"
+#include "ardour/filesystem_paths.h"
+
+#include "pbd/i18n.h"
 
 using namespace std;
+using namespace PBD;
 using namespace ARDOUR;
 
-namespace std {
-struct UriSorter {
-       bool operator() (string a, string b) const { 
-               return cmp_nocase(Library->get_label(a), Library->get_label(b)) == -1; 
-       }
-}; 
-};
+namespace {
+       const char* const sfdb_file_name = "sfdb";
+} // anonymous namespace
 
-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";
+static const char* TAG = "http://ardour.org/ontology/Tag";
 
 AudioLibrary::AudioLibrary ()
 {
-       src = "file:" + Config->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");
-
-       lrdf_read_file(src.c_str());
+       std::string sfdb_file_path(user_config_directory ());
 
-       lrdf_statement pattern;
+       sfdb_file_path = Glib::build_filename (sfdb_file_path, sfdb_file_name);
 
-       pattern.subject = GROUP;
-       pattern.predicate = RDF_TYPE;
-       pattern.object = RDFS_CLASS;
-       pattern.object_type = lrdf_uri;
+       src = Glib::filename_to_uri (sfdb_file_path);
 
-       lrdf_statement* matches = lrdf_matches(&pattern);
+       // workaround for possible bug in raptor that crashes when saving to a
+       // non-existant file.
 
-       // if empty DB, create basic schema
-       if (matches == 0) {
-               initialize_db ();
-               save_changes();
-       } 
+       touch_file(sfdb_file_path);
 
-       lrdf_free_statements(matches);
+#ifdef HAVE_LRDF
+       lrdf_read_file(src.c_str());
+#endif
 }
 
 AudioLibrary::~AudioLibrary ()
 {
 }
 
-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");
-}
-
 void
 AudioLibrary::save_changes ()
 {
+#ifdef HAVE_LRDF
        if (lrdf_export_by_source(src.c_str(), src.substr(5).c_str())) {
-               warning << string_compose(_("Could not open %1.  Audio Library not saved"), src) << endmsg;
+               PBD::warning << string_compose(_("Could not open %1.  Audio Library not saved"), src) << endmsg;
        }
-}
-
-string
-AudioLibrary::add_group (string group, string parent_uri)
-{
-       string local_group(string_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;
+#endif
 }
 
 void
-AudioLibrary::remove_group (string uri)
+AudioLibrary::set_tags (string member, vector<string> tags)
 {
-       list<string> items;
-       list<string>::iterator i;
-
-       get_members(items, uri);
-       for (i = items.begin(); i != items.end(); ++i) {
-               remove_member(*i);
-       }
-       
-       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);
+#ifdef HAVE_LRDF
+       sort (tags.begin(), tags.end());
+       tags.erase (unique(tags.begin(), tags.end()), tags.end());
 
-       lrdf_statement* current = matches;
-       while (current != 0) {
-               groups.push_back(current->subject);
-               current = current->next;
-       }
-
-       lrdf_free_statements(matches);
-       free (pattern.object);
+       const string file_uri(Glib::filename_to_uri (member));
 
-       UriSorter cmp;
-       groups.sort(cmp);
-       groups.unique();
-}
+       lrdf_remove_uri_matches (file_uri.c_str());
 
-string
-AudioLibrary::add_member (string member, string parent_uri)
-{
-       string local_member(string_compose("file:sfdb/soundfile/%1", get_uid()));
-       string file_uri(string_compose("file:%1", member));
-
-       lrdf_add_triple(src.c_str(), local_member.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);
+       for (vector<string>::iterator i = tags.begin(); i != tags.end(); ++i) {
+               lrdf_add_triple (src.c_str(), file_uri.c_str(), TAG, (*i).c_str(), lrdf_literal);
        }
-
-       save_changes ();
-
-        added_member (local_member, parent_uri); /* EMIT SIGNAL */
-
-       return local_member;
+#endif
 }
 
-void
-AudioLibrary::remove_member (string uri)
+vector<string>
+AudioLibrary::get_tags (string member)
 {
-       lrdf_remove_uri_matches (uri.c_str());
-
-       save_changes ();
+       vector<string> tags;
+#ifdef HAVE_LRDF
+       char * uri = strdup(Glib::filename_to_uri(member).c_str());
 
-        removed_member(uri); /* EMIT SIGNAL */
-}
-
-void
-AudioLibrary::get_members (list<string>& members, string parent_uri)
-{
        lrdf_statement pattern;
+       pattern.subject = uri;
+       pattern.predicate = const_cast<char*>(TAG);
+       pattern.object = 0;
+       pattern.object_type = lrdf_literal;
 
-       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* matches = lrdf_matches (&pattern);
 
        lrdf_statement* current = matches;
        while (current != 0) {
-               members.push_back(current->subject);
+               tags.push_back (current->object);
+
                current = current->next;
        }
 
-       lrdf_free_statements(matches);
-       free (pattern.object);
+       lrdf_free_statements (matches);
 
-       UriSorter cmp;
-       members.sort(cmp);
-       members.unique();
+       sort (tags.begin(), tags.end());
+       free (uri);
+#endif
+       return tags;
 }
 
 void
-AudioLibrary::search_members_and (list<string>& members, 
-                                                                 const map<string,string>& fields)
+AudioLibrary::search_members_and (vector<string>& members, const vector<string>& tags)
 {
+#ifdef HAVE_LRDF
        lrdf_statement **head;
        lrdf_statement* pattern = 0;
        lrdf_statement* old = 0;
        head = &pattern;
 
-       map<string,string>::const_iterator i;
-       for (i = fields.begin(); i != fields.end(); ++i){
+       vector<string>::const_iterator i;
+       for (i = tags.begin(); i != tags.end(); ++i){
                pattern = new lrdf_statement;
-               pattern->subject = "?";
-               pattern->predicate = strdup(field_uri(i->first).c_str());
-               pattern->object = strdup((i->second).c_str());
+               pattern->subject = const_cast<char*>("?");
+               pattern->predicate = const_cast<char*>(TAG);
+               pattern->object = strdup((*i).c_str());
                pattern->next = old;
 
                old = pattern;
@@ -275,239 +154,21 @@ AudioLibrary::search_members_and (list<string>& members,
        if (*head != 0) {
                lrdf_uris* ulist = lrdf_match_multi(*head);
                for (uint32_t j = 0; ulist && j < ulist->count; ++j) {
-//                     printf("AND: %s\n", ulist->items[j]);
-                       members.push_back(ulist->items[j]);
+                       members.push_back(Glib::filename_from_uri(ulist->items[j]));
                }
                lrdf_free_uris(ulist);
 
-               UriSorter cmp;
-               members.sort(cmp);
-               members.unique();
+           sort(members.begin(), members.end());
+           unique(members.begin(), members.end());
        }
 
        // memory clean up
        pattern = *head;
        while(pattern){
-               free(pattern->predicate);
                free(pattern->object);
                old = pattern;
                pattern = pattern->next;
                delete old;
        }
+#endif
 }
-
-void
-AudioLibrary::search_members_or (list<string>& members, 
-                                                                const map<string,string>& fields)
-{
-       map<string,string>::const_iterator i;
-
-       lrdf_statement pattern;
-       for (i = fields.begin(); i != fields.end(); ++i) {
-               pattern.subject = 0;
-               pattern.predicate = strdup(field_uri(i->first).c_str());
-               pattern.object = strdup((i->second).c_str());
-               pattern.object_type = lrdf_literal;
-
-               lrdf_statement* matched = lrdf_matches(&pattern);
-
-               lrdf_statement* old = matched;
-               while(matched) {
-//                     printf ("OR: %s\n", matched->subject);
-                       members.push_back(matched->subject);
-                       matched = matched->next;
-               }
-
-               free(pattern.predicate);
-               free(pattern.object);
-               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-";
-       }
-}
-
-void
-AudioLibrary::add_field (string name)
-{
-       string local_field = field_uri(name);
-       lrdf_statement pattern;
-       pattern.subject = strdup(local_field.c_str());
-       pattern.predicate = RDF_TYPE;
-       pattern.object = RDF_BASE "Property";
-       pattern.object_type = lrdf_uri;
-
-       if(lrdf_exists_match(&pattern)) {
-               return;
-       }
-
-       // of type rdf:Property
-       lrdf_add_triple(src.c_str(), local_field.c_str(), RDF_TYPE, 
-                       RDF_BASE "Property", lrdf_uri);
-       // of range ardour:Soundfile
-       lrdf_add_triple(src.c_str(), local_field.c_str(), RDFS_BASE "range",
-                       SOUNDFILE, lrdf_uri);
-       // of domain rdf:Literal
-       lrdf_add_triple(src.c_str(), local_field.c_str(), RDFS_BASE "domain", 
-                                       RDF_BASE "Literal", lrdf_uri);
-
-       set_label (local_field, name);
-       
-       save_changes();
-
-        fields_changed(); /* EMIT SIGNAL */
-}
-
-void
-AudioLibrary::get_fields (list<string>& fields)
-{
-       lrdf_statement pattern;
-
-       pattern.subject = 0;
-       pattern.predicate = RDFS_BASE "range";
-       pattern.object = SOUNDFILE;
-       pattern.object_type = lrdf_uri;
-
-       lrdf_statement* matches = lrdf_matches(&pattern);
-
-       lrdf_statement* current = matches;
-       while (current != 0) {
-               fields.push_back(get_label(current->subject));
-
-               current = current->next;
-       }
-
-       lrdf_free_statements(matches);
-
-       fields.sort();
-       fields.unique();
-}
-
-void
-AudioLibrary::remove_field (string name)
-{
-       lrdf_remove_uri_matches(field_uri(name).c_str());
-       save_changes();
-        fields_changed (); /* EMIT SIGNAL */
-}
-
-string 
-AudioLibrary::get_field (string uri, string field)
-{
-       lrdf_statement pattern;
-
-       pattern.subject = strdup(uri.c_str());
-
-       pattern.predicate = strdup(field_uri(field).c_str());
-
-       pattern.object = 0;
-       pattern.object_type = lrdf_literal;
-
-       lrdf_statement* matches = lrdf_matches(&pattern);
-       free(pattern.subject);
-       free(pattern.predicate);
-
-       stringstream object;
-       if (matches != 0){
-               object << matches->object;
-       }
-
-       lrdf_free_statements(matches);
-       return object.str();
-}
-
-void 
-AudioLibrary::set_field (string uri, string field, string literal)
-{
-       lrdf_statement pattern;
-
-       pattern.subject = strdup(uri.c_str());
-
-       string local_field = field_uri(field);
-       pattern.predicate = strdup(local_field.c_str());
-
-       pattern.object = 0;
-       pattern.object_type = lrdf_literal;
-
-       lrdf_remove_matches(&pattern);
-       free(pattern.subject);
-       free(pattern.predicate);
-
-       lrdf_add_triple(src.c_str(), uri.c_str(), local_field.c_str(), 
-                       literal.c_str(), lrdf_literal);
-
-       save_changes();
-
-        fields_changed(); /* EMIT SIGNAL */
-}
-
-string
-AudioLibrary::field_uri (string name)
-{
-       stringstream local_field;
-       local_field << "file:sfdb/fields/" << name;
-
-       return local_field.str();
-}
-
-string
-AudioLibrary::get_label (string uri)
-{
-       lrdf_statement pattern;
-       pattern.subject = strdup(uri.c_str());
-       pattern.predicate = RDFS_BASE "label";
-       pattern.object = 0;
-       pattern.object_type = lrdf_literal;
-
-       lrdf_statement* matches = lrdf_matches (&pattern);
-       free(pattern.subject);
-
-       stringstream label;
-       if (matches != 0){
-               label << matches->object;
-       }
-
-       lrdf_free_statements(matches);
-
-       return label.str();
-}
-
-void
-AudioLibrary::set_label (string uri, string label)
-{
-       lrdf_statement pattern;
-       pattern.subject = strdup(uri.c_str());
-       pattern.predicate = RDFS_BASE "label";
-       pattern.object = 0;
-       pattern.object_type = lrdf_literal;
-
-       lrdf_remove_matches(&pattern);
-       free(pattern.subject);
-
-       lrdf_add_triple(src.c_str(), uri.c_str(), RDFS_BASE "label", 
-                       label.c_str(), lrdf_literal);
-}
-