changeset 490:c3fb8258e34d

* Make it possible to import an entire session from an RDF document. However, at the moment the timings of events appear to be constrained by how far the audio decoder has got through its audio file at the time the event is queried -- need to investigate.
author Chris Cannam
date Fri, 21 Nov 2008 18:03:14 +0000
parents 82ab61fa9223
children 6f8ee19984ad
files rdf/RDFImporter.cpp rdf/RDFImporter.h rdf/SimpleSPARQLQuery.cpp
diffstat 3 files changed, 152 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/rdf/RDFImporter.cpp	Fri Nov 21 16:12:29 2008 +0000
+++ b/rdf/RDFImporter.cpp	Fri Nov 21 18:03:14 2008 +0000
@@ -40,15 +40,20 @@
 public:
     RDFImporterImpl(QString url, int sampleRate);
     virtual ~RDFImporterImpl();
+
+    void setSampleRate(int sampleRate) { m_sampleRate = sampleRate; }
     
     bool isOK();
     QString getErrorString() const;
 
+    QString getAudioAvailableUrl() const { return m_audioAvailableAt; }
+
     std::vector<Model *> getDataModels(ProgressReporter *);
 
 protected:
     QString m_uristring;
     QString m_errorString;
+    QString m_audioAvailableAt;
     int m_sampleRate;
 
     void getDataModelsSparse(std::vector<Model *> &, ProgressReporter *);
@@ -79,6 +84,12 @@
     delete m_d;
 }
 
+void
+RDFImporter::setSampleRate(int sampleRate)
+{
+    m_d->setSampleRate(sampleRate);
+}
+
 bool
 RDFImporter::isOK()
 {
@@ -91,6 +102,12 @@
     return m_d->getErrorString();
 }
 
+QString
+RDFImporter::getAudioAvailableUrl() const
+{
+    return m_d->getAudioAvailableUrl();
+}
+
 std::vector<Model *>
 RDFImporter::getDataModels(ProgressReporter *r)
 {
@@ -101,6 +118,19 @@
     m_uristring(uri),
     m_sampleRate(sampleRate)
 {
+    SimpleSPARQLQuery::Value value =
+        SimpleSPARQLQuery::singleResultQuery
+        (SimpleSPARQLQuery::QueryFromSingleSource,
+         QString
+         (" PREFIX mo: <http://purl.org/ontology/mo/> "
+          " SELECT ?url FROM <%1> "
+          " WHERE { ?signal a mo:Signal ; mo:available_as ?url } "
+             ).arg(uri),
+         "url");
+
+    if (value.type == SimpleSPARQLQuery::URIValue) {
+        m_audioAvailableAt = value.value;
+    }
 }
 
 RDFImporterImpl::~RDFImporterImpl()
@@ -124,6 +154,11 @@
 {
     std::vector<Model *> models;
 
+    if (m_sampleRate == 0) {
+        std::cerr << "RDFImporter::getDataModels: invalid sample rate" << std::endl;
+        return models;
+    }
+
     getDataModelsDense(models, reporter);
 
     QString error;
@@ -703,4 +738,70 @@
     return;
 }
 
+RDFImporter::RDFDocumentType
+RDFImporter::identifyDocumentType(QString url)
+{
+    bool haveAudio = false;
+    bool haveAnnotations = false;
 
+    SimpleSPARQLQuery::Value value =
+        SimpleSPARQLQuery::singleResultQuery
+        (SimpleSPARQLQuery::QueryFromSingleSource,
+         QString
+         (" PREFIX mo: <http://purl.org/ontology/mo/> "
+          " SELECT ?url FROM <%1> "
+          " WHERE { ?signal a mo:Signal ; mo:available_as ?url } "
+             ).arg(url),
+         "url");
+
+    if (value.type == SimpleSPARQLQuery::URIValue) {
+        haveAudio = true;
+    }
+
+    value =
+        SimpleSPARQLQuery::singleResultQuery
+        (SimpleSPARQLQuery::QueryFromSingleSource,
+         QString
+         (" PREFIX event: <http://purl.org/NET/c4dm/event.owl#> "
+          " SELECT ?thing FROM <%1> "
+          " WHERE { ?thing event:time ?time } "
+             ).arg(url),
+         "thing");
+
+    if (value.type == SimpleSPARQLQuery::URIValue) {
+        haveAnnotations = true;
+    }
+
+    if (!haveAnnotations) {
+        
+        value =
+            SimpleSPARQLQuery::singleResultQuery
+            (SimpleSPARQLQuery::QueryFromSingleSource,
+             QString
+             (" PREFIX af: <http://purl.org/ontology/af/> "
+              " SELECT ?thing FROM <%1> "
+              " WHERE { ?signal af:signal_feature ?thing } "
+             ).arg(url),
+             "thing");
+        
+        if (value.type == SimpleSPARQLQuery::URIValue) {
+            haveAnnotations = true;
+        }
+    }
+
+    if (haveAudio) {
+        if (haveAnnotations) {
+            return AudioRefAndAnnotations;
+        } else {
+            return AudioRef;
+        }
+    } else {
+        if (haveAnnotations) {
+            return Annotations;
+        } else {
+            return OtherDocument;
+        }
+    }
+}
+
+
--- a/rdf/RDFImporter.h	Fri Nov 21 16:12:29 2008 +0000
+++ b/rdf/RDFImporter.h	Fri Nov 21 18:03:14 2008 +0000
@@ -37,14 +37,27 @@
      */
     static QString getKnownExtensions();
 
-    RDFImporter(QString url, int sampleRate);
+    RDFImporter(QString url, int sampleRate = 0);
     virtual ~RDFImporter();
 
+    void setSampleRate(int sampleRate);
+
     bool isOK();
     QString getErrorString() const;
 
+    QString getAudioAvailableUrl() const;
+
     std::vector<Model *> getDataModels(ProgressReporter *reporter);
 
+    enum RDFDocumentType {
+        AudioRefAndAnnotations,
+        Annotations,
+        AudioRef,
+        OtherDocument
+    };
+
+    static RDFDocumentType identifyDocumentType(QString url);
+
 protected:
     RDFImporterImpl *m_d;
 };
--- a/rdf/SimpleSPARQLQuery.cpp	Fri Nov 21 16:12:29 2008 +0000
+++ b/rdf/SimpleSPARQLQuery.cpp	Fri Nov 21 18:03:14 2008 +0000
@@ -31,7 +31,7 @@
 
 #include <redland.h>
 
-//#define DEBUG_SIMPLE_SPARQL_QUERY 1
+#define DEBUG_SIMPLE_SPARQL_QUERY 1
 
 #include <iostream>
 
@@ -115,8 +115,6 @@
 
     librdf_uri *getUri(QString uriString, QString &errorString)
     {
-        QMutexLocker locker(&m_mutex);
-
         if (m_parsedUris.find(uriString) != m_parsedUris.end()) {
             return m_parsedUris[uriString];
         }
@@ -143,7 +141,7 @@
             errorString = QString("Failed to parse RDF from URI \"%1\"")
                 .arg(uriString);
             librdf_free_parser(parser);
-            librdf_free_uri(uri);
+//            librdf_free_uri(uri);
             return 0;
 
         } else {
@@ -315,7 +313,7 @@
 {
     ResultList list;
 
-    m_mutex.lock();
+    QMutexLocker locker(&m_mutex);
 
     if (m_type == QueryFromModel) {
         if (!m_redland) {
@@ -323,7 +321,6 @@
             // added to the model yet (m_redland is only created when
             // addSourceToModel is called)
             cerr << "SimpleSPARQLQuery::execute: NOTE: No sources have been added to data model yet, so no results are possible" << endl;
-            m_mutex.unlock();
             return list;
         }
     }
@@ -336,7 +333,6 @@
                 cerr << "ERROR: SimpleSPARQLQuery::execute: Failed to initialise Rasqal query engine" << endl;
                 delete m_rasqal;
                 m_rasqal = 0;
-                m_mutex.unlock();
                 return list;
             }
         }
@@ -348,8 +344,6 @@
 #endif
     }
 
-    m_mutex.unlock();
-
     if (m_type == QueryFromSingleSource) {
         return executeDirectParser();
     } else {
@@ -426,6 +420,11 @@
             const unsigned char *name =
                 rasqal_query_results_get_binding_name(results, i);
 
+            if (!name) {
+                std::cerr << "WARNING: Result " << i << " of query has no name" << std::endl;
+                continue;
+            }
+
             rasqal_literal *literal =
                 rasqal_query_results_get_binding_value(results, i);
 
@@ -437,10 +436,16 @@
             }
 
             ValueType type = LiteralValue;
-            if (literal->type == RASQAL_LITERAL_URI) type = URIValue;
-            else if (literal->type == RASQAL_LITERAL_BLANK) type = BlankValue;
+            if (literal->type == RASQAL_LITERAL_BLANK) type = BlankValue;
+            else if (literal->type == RASQAL_LITERAL_URI) type = URIValue;
 
-            QString text = (const char *)rasqal_literal_as_string(literal);
+            QString text;
+            const char *lit = (const char *)rasqal_literal_as_string(literal);
+            if (!lit) {
+                std::cerr << "WARNING: Result " << i << " of query has null value" << std::endl;
+            } else {
+                text = lit;
+            }
 
 #ifdef DEBUG_SIMPLE_SPARQL_QUERY
             std::cerr << i << ". " << key.toStdString() << " -> " << text.toStdString() << " (type " << type << ")" << std::endl;
@@ -539,6 +544,11 @@
             const char *name =
                 librdf_query_results_get_binding_name(results, i);
 
+            if (!name) {
+                std::cerr << "WARNING: Result " << i << " of query has no name" << std::endl;
+                continue;
+            }
+
             librdf_node *node =
                 librdf_query_results_get_binding_value(results, i);
 
@@ -556,12 +566,24 @@
 
                 type = URIValue;
                 librdf_uri *uri = librdf_node_get_uri(node);
-                text = (const char *)librdf_uri_as_string(uri);
+                const char *us = (const char *)librdf_uri_as_string(uri);
+
+                if (!us) {
+                    std::cerr << "WARNING: Result " << i << " of query claims URI type, but has null URI" << std::endl;
+                } else {
+                    text = us;
+                }
 
             } else if (librdf_node_is_literal(node)) {
 
                 type = LiteralValue;
-                text = (const char *)librdf_node_get_literal_value(node);
+
+                const char *lit = (const char *)librdf_node_get_literal_value(node);
+                if (!lit) {
+                    std::cerr << "WARNING: Result " << i << " of query claims literal type, but has no literal" << std::endl;
+                } else {
+                    text = lit;
+                }
 
             } else if (librdf_node_is_blank(node)) {
 
@@ -617,7 +639,7 @@
 {
     QString err;
 
-    m_mutex.lock();
+    QMutexLocker locker(&m_mutex);
 
     if (!m_redland) {
         m_redland = new WredlandWorldWrapper();
@@ -625,13 +647,10 @@
             cerr << "ERROR: SimpleSPARQLQuery::addSourceToModel: Failed to initialise Redland datastore" << endl;
             delete m_redland;
             m_redland = 0;
-            m_mutex.unlock();
             return false;
         }
     }
 
-    m_mutex.unlock();
-
     librdf_uri *uri = m_redland->getUri(sourceUri, err);
 
     if (!uri) {