| Chris@439 | 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */ | 
| Chris@439 | 2 | 
| Chris@439 | 3 /* | 
| Chris@439 | 4     Sonic Visualiser | 
| Chris@439 | 5     An audio file viewer and annotation editor. | 
| Chris@439 | 6     Centre for Digital Music, Queen Mary, University of London. | 
| Chris@439 | 7     This file copyright 2008 QMUL. | 
| Chris@439 | 8 | 
| Chris@439 | 9     This program is free software; you can redistribute it and/or | 
| Chris@439 | 10     modify it under the terms of the GNU General Public License as | 
| Chris@439 | 11     published by the Free Software Foundation; either version 2 of the | 
| Chris@439 | 12     License, or (at your option) any later version.  See the file | 
| Chris@439 | 13     COPYING included with this distribution for more information. | 
| Chris@439 | 14 */ | 
| Chris@439 | 15 | 
| Chris@439 | 16 #include "RDFImporter.h" | 
| Chris@439 | 17 | 
| Chris@439 | 18 #include <map> | 
| Chris@439 | 19 #include <vector> | 
| Chris@439 | 20 | 
| Chris@439 | 21 #include <iostream> | 
| Chris@439 | 22 #include <cmath> | 
| Chris@439 | 23 | 
| Chris@439 | 24 #include "SimpleSPARQLQuery.h" | 
| Chris@439 | 25 | 
| Chris@439 | 26 #include "base/ProgressReporter.h" | 
| Chris@439 | 27 #include "base/RealTime.h" | 
| Chris@439 | 28 | 
| Chris@439 | 29 #include "data/model/SparseOneDimensionalModel.h" | 
| Chris@439 | 30 #include "data/model/SparseTimeValueModel.h" | 
| Chris@439 | 31 #include "data/model/EditableDenseThreeDimensionalModel.h" | 
| Chris@449 | 32 #include "data/model/NoteModel.h" | 
| Chris@510 | 33 #include "data/model/TextModel.h" | 
| Chris@449 | 34 #include "data/model/RegionModel.h" | 
| Chris@499 | 35 #include "data/model/WaveFileModel.h" | 
| Chris@499 | 36 | 
| Chris@499 | 37 #include "data/fileio/FileSource.h" | 
| Chris@439 | 38 | 
| Chris@439 | 39 using std::cerr; | 
| Chris@439 | 40 using std::endl; | 
| Chris@439 | 41 | 
| Chris@439 | 42 class RDFImporterImpl | 
| Chris@439 | 43 { | 
| Chris@439 | 44 public: | 
| Chris@439 | 45     RDFImporterImpl(QString url, int sampleRate); | 
| Chris@439 | 46     virtual ~RDFImporterImpl(); | 
| Chris@490 | 47 | 
| Chris@490 | 48     void setSampleRate(int sampleRate) { m_sampleRate = sampleRate; } | 
| Chris@439 | 49 | 
| Chris@439 | 50     bool isOK(); | 
| Chris@439 | 51     QString getErrorString() const; | 
| Chris@439 | 52 | 
| Chris@439 | 53     std::vector<Model *> getDataModels(ProgressReporter *); | 
| Chris@439 | 54 | 
| Chris@439 | 55 protected: | 
| Chris@439 | 56     QString m_uristring; | 
| Chris@439 | 57     QString m_errorString; | 
| Chris@499 | 58     std::map<QString, Model *> m_audioModelMap; | 
| Chris@439 | 59     int m_sampleRate; | 
| Chris@439 | 60 | 
| Chris@499 | 61     void getDataModelsAudio(std::vector<Model *> &, ProgressReporter *); | 
| Chris@440 | 62     void getDataModelsSparse(std::vector<Model *> &, ProgressReporter *); | 
| Chris@440 | 63     void getDataModelsDense(std::vector<Model *> &, ProgressReporter *); | 
| Chris@440 | 64 | 
| Chris@493 | 65     void getDenseModelTitle(Model *, QString, QString); | 
| Chris@493 | 66 | 
| Chris@440 | 67     void getDenseFeatureProperties(QString featureUri, | 
| Chris@440 | 68                                    int &sampleRate, int &windowLength, | 
| Chris@440 | 69                                    int &hopSize, int &width, int &height); | 
| Chris@440 | 70 | 
| Chris@449 | 71     void fillModel(Model *, long, long, bool, std::vector<float> &, QString); | 
| Chris@439 | 72 }; | 
| Chris@439 | 73 | 
| Chris@439 | 74 | 
| Chris@439 | 75 QString | 
| Chris@439 | 76 RDFImporter::getKnownExtensions() | 
| Chris@439 | 77 { | 
| Chris@439 | 78     return "*.rdf *.n3 *.ttl"; | 
| Chris@439 | 79 } | 
| Chris@439 | 80 | 
| Chris@439 | 81 RDFImporter::RDFImporter(QString url, int sampleRate) : | 
| Chris@439 | 82     m_d(new RDFImporterImpl(url, sampleRate)) | 
| Chris@439 | 83 { | 
| Chris@439 | 84 } | 
| Chris@439 | 85 | 
| Chris@439 | 86 RDFImporter::~RDFImporter() | 
| Chris@439 | 87 { | 
| Chris@439 | 88     delete m_d; | 
| Chris@439 | 89 } | 
| Chris@439 | 90 | 
| Chris@490 | 91 void | 
| Chris@490 | 92 RDFImporter::setSampleRate(int sampleRate) | 
| Chris@490 | 93 { | 
| Chris@490 | 94     m_d->setSampleRate(sampleRate); | 
| Chris@490 | 95 } | 
| Chris@490 | 96 | 
| Chris@439 | 97 bool | 
| Chris@439 | 98 RDFImporter::isOK() | 
| Chris@439 | 99 { | 
| Chris@439 | 100     return m_d->isOK(); | 
| Chris@439 | 101 } | 
| Chris@439 | 102 | 
| Chris@439 | 103 QString | 
| Chris@439 | 104 RDFImporter::getErrorString() const | 
| Chris@439 | 105 { | 
| Chris@439 | 106     return m_d->getErrorString(); | 
| Chris@439 | 107 } | 
| Chris@439 | 108 | 
| Chris@439 | 109 std::vector<Model *> | 
| Chris@439 | 110 RDFImporter::getDataModels(ProgressReporter *r) | 
| Chris@439 | 111 { | 
| Chris@439 | 112     return m_d->getDataModels(r); | 
| Chris@439 | 113 } | 
| Chris@439 | 114 | 
| Chris@439 | 115 RDFImporterImpl::RDFImporterImpl(QString uri, int sampleRate) : | 
| Chris@439 | 116     m_uristring(uri), | 
| Chris@439 | 117     m_sampleRate(sampleRate) | 
| Chris@439 | 118 { | 
| Chris@439 | 119 } | 
| Chris@439 | 120 | 
| Chris@439 | 121 RDFImporterImpl::~RDFImporterImpl() | 
| Chris@439 | 122 { | 
| Chris@492 | 123     SimpleSPARQLQuery::closeSingleSource(m_uristring); | 
| Chris@439 | 124 } | 
| Chris@439 | 125 | 
| Chris@439 | 126 bool | 
| Chris@439 | 127 RDFImporterImpl::isOK() | 
| Chris@439 | 128 { | 
| Chris@439 | 129     return (m_errorString == ""); | 
| Chris@439 | 130 } | 
| Chris@439 | 131 | 
| Chris@439 | 132 QString | 
| Chris@439 | 133 RDFImporterImpl::getErrorString() const | 
| Chris@439 | 134 { | 
| Chris@439 | 135     return m_errorString; | 
| Chris@439 | 136 } | 
| Chris@439 | 137 | 
| Chris@439 | 138 std::vector<Model *> | 
| Chris@439 | 139 RDFImporterImpl::getDataModels(ProgressReporter *reporter) | 
| Chris@439 | 140 { | 
| Chris@439 | 141     std::vector<Model *> models; | 
| Chris@439 | 142 | 
| Chris@499 | 143     getDataModelsAudio(models, reporter); | 
| Chris@499 | 144 | 
| Chris@490 | 145     if (m_sampleRate == 0) { | 
| Chris@490 | 146         std::cerr << "RDFImporter::getDataModels: invalid sample rate" << std::endl; | 
| Chris@490 | 147         return models; | 
| Chris@490 | 148     } | 
| Chris@490 | 149 | 
| Chris@508 | 150     QString error; | 
| Chris@508 | 151 | 
| Chris@508 | 152     if (!isOK()) error = m_errorString; | 
| Chris@508 | 153     m_errorString = ""; | 
| Chris@508 | 154 | 
| Chris@440 | 155     getDataModelsDense(models, reporter); | 
| Chris@440 | 156 | 
| Chris@440 | 157     if (!isOK()) error = m_errorString; | 
| Chris@440 | 158     m_errorString = ""; | 
| Chris@440 | 159 | 
| Chris@440 | 160     getDataModelsSparse(models, reporter); | 
| Chris@440 | 161 | 
| Chris@440 | 162     if (isOK()) m_errorString = error; | 
| Chris@440 | 163 | 
| Chris@440 | 164     return models; | 
| Chris@440 | 165 } | 
| Chris@440 | 166 | 
| Chris@440 | 167 void | 
| Chris@499 | 168 RDFImporterImpl::getDataModelsAudio(std::vector<Model *> &models, | 
| Chris@499 | 169                                     ProgressReporter *reporter) | 
| Chris@499 | 170 { | 
| Chris@499 | 171     SimpleSPARQLQuery query = SimpleSPARQLQuery | 
| Chris@499 | 172         (SimpleSPARQLQuery::QueryFromSingleSource, | 
| Chris@499 | 173          QString | 
| Chris@499 | 174          ( | 
| Chris@499 | 175              " PREFIX mo: <http://purl.org/ontology/mo/> " | 
| Chris@499 | 176              " SELECT ?signal ?source FROM <%1> " | 
| Chris@499 | 177              " WHERE { ?signal a mo:Signal ; mo:available_as ?source } " | 
| Chris@499 | 178              ) | 
| Chris@499 | 179          .arg(m_uristring)); | 
| Chris@499 | 180 | 
| Chris@499 | 181     SimpleSPARQLQuery::ResultList results = query.execute(); | 
| Chris@499 | 182 | 
| Chris@499 | 183     for (int i = 0; i < results.size(); ++i) { | 
| Chris@499 | 184 | 
| Chris@499 | 185         QString signal = results[i]["signal"].value; | 
| Chris@499 | 186         QString source = results[i]["source"].value; | 
| Chris@499 | 187 | 
| Chris@499 | 188         FileSource fs(source, reporter); | 
| Chris@499 | 189         if (fs.isAvailable()) { | 
| Chris@499 | 190             if (reporter) { | 
| Chris@499 | 191                 reporter->setMessage(RDFImporter::tr("Importing audio referenced in RDF...")); | 
| Chris@499 | 192             } | 
| Chris@499 | 193             fs.waitForData(); | 
| Chris@499 | 194             WaveFileModel *newModel = new WaveFileModel(fs, m_sampleRate); | 
| Chris@499 | 195             if (newModel->isOK()) { | 
| Chris@499 | 196                 std::cerr << "Successfully created wave file model from source at \"" << source.toStdString() << "\"" << std::endl; | 
| Chris@499 | 197                 models.push_back(newModel); | 
| Chris@499 | 198                 m_audioModelMap[signal] = newModel; | 
| Chris@499 | 199                 if (m_sampleRate == 0) { | 
| Chris@499 | 200                     m_sampleRate = newModel->getSampleRate(); | 
| Chris@499 | 201                 } | 
| Chris@499 | 202             } else { | 
| Chris@508 | 203                 m_errorString = QString("Failed to create wave file model from source at \"%1\"").arg(source); | 
| Chris@499 | 204                 delete newModel; | 
| Chris@499 | 205             } | 
| Chris@508 | 206         } else { | 
| Chris@508 | 207             m_errorString = QString("Signal source \"%1\" is not available").arg(source); | 
| Chris@499 | 208         } | 
| Chris@499 | 209     } | 
| Chris@499 | 210 } | 
| Chris@499 | 211 | 
| Chris@499 | 212 void | 
| Chris@440 | 213 RDFImporterImpl::getDataModelsDense(std::vector<Model *> &models, | 
| Chris@440 | 214                                     ProgressReporter *reporter) | 
| Chris@440 | 215 { | 
| Chris@499 | 216     if (reporter) { | 
| Chris@499 | 217         reporter->setMessage(RDFImporter::tr("Importing dense signal data from RDF...")); | 
| Chris@499 | 218     } | 
| Chris@499 | 219 | 
| Chris@440 | 220     SimpleSPARQLQuery query = SimpleSPARQLQuery | 
| Chris@489 | 221         (SimpleSPARQLQuery::QueryFromSingleSource, | 
| Chris@480 | 222          QString | 
| Chris@440 | 223          ( | 
| Chris@440 | 224              " PREFIX mo: <http://purl.org/ontology/mo/>" | 
| Chris@440 | 225              " PREFIX af: <http://purl.org/ontology/af/>" | 
| Chris@440 | 226 | 
| Chris@493 | 227              " SELECT ?feature ?feature_signal_type ?value " | 
| Chris@440 | 228              " FROM <%1> " | 
| Chris@440 | 229 | 
| Chris@440 | 230              " WHERE { " | 
| Chris@440 | 231 | 
| Chris@493 | 232              "   ?signal af:signal_feature ?feature . " | 
| Chris@440 | 233 | 
| Chris@440 | 234              "   ?feature a ?feature_signal_type ; " | 
| Chris@440 | 235              "            af:value ?value . " | 
| Chris@440 | 236 | 
| Chris@440 | 237              " } " | 
| Chris@440 | 238              ) | 
| Chris@440 | 239          .arg(m_uristring)); | 
| Chris@440 | 240 | 
| Chris@440 | 241     SimpleSPARQLQuery::ResultList results = query.execute(); | 
| Chris@440 | 242 | 
| Chris@440 | 243     if (!query.isOK()) { | 
| Chris@440 | 244         m_errorString = query.getErrorString(); | 
| Chris@440 | 245         return; | 
| Chris@440 | 246     } | 
| Chris@440 | 247 | 
| Chris@440 | 248     if (query.wasCancelled()) { | 
| Chris@440 | 249         m_errorString = "Query cancelled"; | 
| Chris@440 | 250         return; | 
| Chris@440 | 251     } | 
| Chris@440 | 252 | 
| Chris@440 | 253     for (int i = 0; i < results.size(); ++i) { | 
| Chris@440 | 254 | 
| Chris@440 | 255         QString feature = results[i]["feature"].value; | 
| Chris@440 | 256         QString type = results[i]["feature_signal_type"].value; | 
| Chris@440 | 257         QString value = results[i]["value"].value; | 
| Chris@440 | 258 | 
| Chris@440 | 259         int sampleRate = 0; | 
| Chris@440 | 260         int windowLength = 0; | 
| Chris@440 | 261         int hopSize = 0; | 
| Chris@440 | 262         int width = 0; | 
| Chris@440 | 263         int height = 0; | 
| Chris@440 | 264         getDenseFeatureProperties | 
| Chris@440 | 265             (feature, sampleRate, windowLength, hopSize, width, height); | 
| Chris@440 | 266 | 
| Chris@440 | 267         if (sampleRate != 0 && sampleRate != m_sampleRate) { | 
| Chris@440 | 268             cerr << "WARNING: Sample rate in dense feature description does not match our underlying rate -- using rate from feature description" << endl; | 
| Chris@440 | 269         } | 
| Chris@440 | 270         if (sampleRate == 0) sampleRate = m_sampleRate; | 
| Chris@440 | 271 | 
| Chris@440 | 272         if (hopSize == 0) { | 
| Chris@440 | 273             cerr << "WARNING: Dense feature description does not specify a hop size -- assuming 1" << endl; | 
| Chris@440 | 274             hopSize = 1; | 
| Chris@440 | 275         } | 
| Chris@440 | 276 | 
| Chris@440 | 277         if (height == 0) { | 
| Chris@440 | 278             cerr << "WARNING: Dense feature description does not specify feature signal dimensions -- assuming one-dimensional (height = 1)" << endl; | 
| Chris@440 | 279             height = 1; | 
| Chris@440 | 280         } | 
| Chris@440 | 281 | 
| Chris@440 | 282         QStringList values = value.split(' ', QString::SkipEmptyParts); | 
| Chris@440 | 283 | 
| Chris@440 | 284         if (values.empty()) { | 
| Chris@440 | 285             cerr << "WARNING: Dense feature description does not specify any values!" << endl; | 
| Chris@440 | 286             continue; | 
| Chris@440 | 287         } | 
| Chris@440 | 288 | 
| Chris@440 | 289         if (height == 1) { | 
| Chris@440 | 290 | 
| Chris@440 | 291             SparseTimeValueModel *m = new SparseTimeValueModel | 
| Chris@440 | 292                 (sampleRate, hopSize, false); | 
| Chris@440 | 293 | 
| Chris@440 | 294             for (int j = 0; j < values.size(); ++j) { | 
| Chris@440 | 295                 float f = values[j].toFloat(); | 
| Chris@440 | 296                 SparseTimeValueModel::Point point(j * hopSize, f, ""); | 
| Chris@440 | 297                 m->addPoint(point); | 
| Chris@440 | 298             } | 
| Chris@493 | 299 | 
| Chris@493 | 300             getDenseModelTitle(m, feature, type); | 
| Chris@440 | 301 | 
| Chris@440 | 302             models.push_back(m); | 
| Chris@440 | 303 | 
| Chris@440 | 304         } else { | 
| Chris@440 | 305 | 
| Chris@440 | 306             EditableDenseThreeDimensionalModel *m = | 
| Chris@440 | 307                 new EditableDenseThreeDimensionalModel(sampleRate, hopSize, | 
| Chris@440 | 308                                                        height, false); | 
| Chris@440 | 309 | 
| Chris@440 | 310             EditableDenseThreeDimensionalModel::Column column; | 
| Chris@440 | 311 | 
| Chris@440 | 312             int x = 0; | 
| Chris@440 | 313 | 
| Chris@440 | 314             for (int j = 0; j < values.size(); ++j) { | 
| Chris@440 | 315                 if (j % height == 0 && !column.empty()) { | 
| Chris@440 | 316                     m->setColumn(x++, column); | 
| Chris@440 | 317                     column.clear(); | 
| Chris@440 | 318                 } | 
| Chris@440 | 319                 column.push_back(values[j].toFloat()); | 
| Chris@440 | 320             } | 
| Chris@440 | 321 | 
| Chris@440 | 322             if (!column.empty()) { | 
| Chris@440 | 323                 m->setColumn(x++, column); | 
| Chris@440 | 324             } | 
| Chris@440 | 325 | 
| Chris@493 | 326             getDenseModelTitle(m, feature, type); | 
| Chris@493 | 327 | 
| Chris@440 | 328             models.push_back(m); | 
| Chris@440 | 329         } | 
| Chris@440 | 330     } | 
| Chris@440 | 331 } | 
| Chris@440 | 332 | 
| Chris@440 | 333 void | 
| Chris@493 | 334 RDFImporterImpl::getDenseModelTitle(Model *m, | 
| Chris@493 | 335                                     QString featureUri, | 
| Chris@493 | 336                                     QString featureTypeUri) | 
| Chris@493 | 337 { | 
| Chris@493 | 338     QString titleQuery = QString | 
| Chris@493 | 339         ( | 
| Chris@493 | 340             " PREFIX dc: <http://purl.org/dc/elements/1.1/> " | 
| Chris@493 | 341             " SELECT ?title " | 
| Chris@493 | 342             " FROM <%1> " | 
| Chris@493 | 343             " WHERE { " | 
| Chris@493 | 344             "   <%2> dc:title ?title . " | 
| Chris@493 | 345             " } " | 
| Chris@493 | 346             ).arg(m_uristring); | 
| Chris@493 | 347 | 
| Chris@493 | 348     SimpleSPARQLQuery::Value v; | 
| Chris@493 | 349 | 
| Chris@493 | 350     v = SimpleSPARQLQuery::singleResultQuery | 
| Chris@493 | 351         (SimpleSPARQLQuery::QueryFromSingleSource, | 
| Chris@493 | 352          titleQuery.arg(featureUri), | 
| Chris@493 | 353          "title"); | 
| Chris@493 | 354 | 
| Chris@493 | 355     if (v.value != "") { | 
| Chris@493 | 356         std::cerr << "RDFImporterImpl::getDenseModelTitle: Title (from signal) \"" << v.value.toStdString() << "\"" << std::endl; | 
| Chris@493 | 357         m->setObjectName(v.value); | 
| Chris@493 | 358         return; | 
| Chris@493 | 359     } | 
| Chris@493 | 360 | 
| Chris@493 | 361     v = SimpleSPARQLQuery::singleResultQuery | 
| Chris@493 | 362         (SimpleSPARQLQuery::QueryFromSingleSource, | 
| Chris@493 | 363          titleQuery.arg(featureTypeUri), | 
| Chris@493 | 364          "title"); | 
| Chris@493 | 365 | 
| Chris@493 | 366     if (v.value != "") { | 
| Chris@493 | 367         std::cerr << "RDFImporterImpl::getDenseModelTitle: Title (from signal type) \"" << v.value.toStdString() << "\"" << std::endl; | 
| Chris@493 | 368         m->setObjectName(v.value); | 
| Chris@493 | 369         return; | 
| Chris@493 | 370     } | 
| Chris@493 | 371 | 
| Chris@493 | 372     std::cerr << "RDFImporterImpl::getDenseModelTitle: No title available for feature <" << featureUri.toStdString() << ">" << std::endl; | 
| Chris@493 | 373 } | 
| Chris@493 | 374 | 
| Chris@493 | 375 void | 
| Chris@440 | 376 RDFImporterImpl::getDenseFeatureProperties(QString featureUri, | 
| Chris@440 | 377                                            int &sampleRate, int &windowLength, | 
| Chris@440 | 378                                            int &hopSize, int &width, int &height) | 
| Chris@440 | 379 { | 
| Chris@489 | 380     SimpleSPARQLQuery::QueryType s = SimpleSPARQLQuery::QueryFromSingleSource; | 
| Chris@489 | 381 | 
| Chris@440 | 382     QString dimensionsQuery | 
| Chris@440 | 383         ( | 
| Chris@440 | 384             " PREFIX mo: <http://purl.org/ontology/mo/>" | 
| Chris@440 | 385             " PREFIX af: <http://purl.org/ontology/af/>" | 
| Chris@440 | 386 | 
| Chris@440 | 387             " SELECT ?dimensions " | 
| Chris@440 | 388             " FROM <%1> " | 
| Chris@440 | 389 | 
| Chris@440 | 390             " WHERE { " | 
| Chris@440 | 391 | 
| Chris@440 | 392             "   <%2> af:dimensions ?dimensions . " | 
| Chris@440 | 393 | 
| Chris@440 | 394             " } " | 
| Chris@440 | 395             ); | 
| Chris@440 | 396 | 
| Chris@440 | 397     SimpleSPARQLQuery::Value dimensionsValue = | 
| Chris@489 | 398         SimpleSPARQLQuery::singleResultQuery | 
| Chris@489 | 399         (s, dimensionsQuery.arg(m_uristring).arg(featureUri), "dimensions"); | 
| Chris@440 | 400 | 
| Chris@440 | 401     cerr << "Dimensions = \"" << dimensionsValue.value.toStdString() << "\"" | 
| Chris@440 | 402          << endl; | 
| Chris@440 | 403 | 
| Chris@440 | 404     if (dimensionsValue.value != "") { | 
| Chris@440 | 405         QStringList dl = dimensionsValue.value.split(" "); | 
| Chris@440 | 406         if (dl.empty()) dl.push_back(dimensionsValue.value); | 
| Chris@440 | 407         if (dl.size() > 0) height = dl[0].toInt(); | 
| Chris@440 | 408         if (dl.size() > 1) width = dl[1].toInt(); | 
| Chris@440 | 409     } | 
| Chris@440 | 410 | 
| Chris@440 | 411     QString queryTemplate | 
| Chris@440 | 412         ( | 
| Chris@440 | 413             " PREFIX mo: <http://purl.org/ontology/mo/>" | 
| Chris@440 | 414             " PREFIX af: <http://purl.org/ontology/af/>" | 
| Chris@440 | 415             " PREFIX tl: <http://purl.org/NET/c4dm/timeline.owl#>" | 
| Chris@440 | 416 | 
| Chris@440 | 417             " SELECT ?%3 " | 
| Chris@440 | 418             " FROM <%1> " | 
| Chris@440 | 419 | 
| Chris@440 | 420             " WHERE { " | 
| Chris@440 | 421 | 
| Chris@440 | 422             "   <%2> mo:time ?time . " | 
| Chris@440 | 423 | 
| Chris@440 | 424             "   ?time a tl:Interval ; " | 
| Chris@440 | 425             "         tl:onTimeLine ?timeline . " | 
| Chris@440 | 426 | 
| Chris@440 | 427             "   ?map tl:rangeTimeLine ?timeline . " | 
| Chris@440 | 428 | 
| Chris@440 | 429             "   ?map tl:%3 ?%3 . " | 
| Chris@440 | 430 | 
| Chris@440 | 431             " } " | 
| Chris@440 | 432             ); | 
| Chris@440 | 433 | 
| Chris@440 | 434     // Another laborious workaround for rasqal's failure to handle | 
| Chris@440 | 435     // multiple optionals properly | 
| Chris@440 | 436 | 
| Chris@440 | 437     SimpleSPARQLQuery::Value srValue = | 
| Chris@489 | 438         SimpleSPARQLQuery::singleResultQuery(s, | 
| Chris@480 | 439                                              queryTemplate | 
| Chris@440 | 440                                              .arg(m_uristring).arg(featureUri) | 
| Chris@440 | 441                                              .arg("sampleRate"), | 
| Chris@440 | 442                                              "sampleRate"); | 
| Chris@440 | 443     if (srValue.value != "") { | 
| Chris@440 | 444         sampleRate = srValue.value.toInt(); | 
| Chris@440 | 445     } | 
| Chris@440 | 446 | 
| Chris@440 | 447     SimpleSPARQLQuery::Value hopValue = | 
| Chris@489 | 448         SimpleSPARQLQuery::singleResultQuery(s, | 
| Chris@480 | 449                                              queryTemplate | 
| Chris@440 | 450                                              .arg(m_uristring).arg(featureUri) | 
| Chris@440 | 451                                              .arg("hopSize"), | 
| Chris@440 | 452                                              "hopSize"); | 
| Chris@440 | 453     if (srValue.value != "") { | 
| Chris@440 | 454         hopSize = hopValue.value.toInt(); | 
| Chris@440 | 455     } | 
| Chris@440 | 456 | 
| Chris@440 | 457     SimpleSPARQLQuery::Value winValue = | 
| Chris@489 | 458         SimpleSPARQLQuery::singleResultQuery(s, | 
| Chris@480 | 459                                              queryTemplate | 
| Chris@440 | 460                                              .arg(m_uristring).arg(featureUri) | 
| Chris@440 | 461                                              .arg("windowLength"), | 
| Chris@440 | 462                                              "windowLength"); | 
| Chris@440 | 463     if (winValue.value != "") { | 
| Chris@440 | 464         windowLength = winValue.value.toInt(); | 
| Chris@440 | 465     } | 
| Chris@440 | 466 | 
| Chris@440 | 467     cerr << "sr = " << sampleRate << ", hop = " << hopSize << ", win = " << windowLength << endl; | 
| Chris@440 | 468 } | 
| Chris@440 | 469 | 
| Chris@440 | 470 void | 
| Chris@440 | 471 RDFImporterImpl::getDataModelsSparse(std::vector<Model *> &models, | 
| Chris@440 | 472                                      ProgressReporter *reporter) | 
| Chris@440 | 473 { | 
| Chris@499 | 474     if (reporter) { | 
| Chris@499 | 475         reporter->setMessage(RDFImporter::tr("Importing event data from RDF...")); | 
| Chris@499 | 476     } | 
| Chris@499 | 477 | 
| Chris@489 | 478     SimpleSPARQLQuery::QueryType s = SimpleSPARQLQuery::QueryFromSingleSource; | 
| Chris@489 | 479 | 
| Chris@439 | 480     // Our query is intended to retrieve every thing that has a time, | 
| Chris@439 | 481     // and every feature type and value associated with a thing that | 
| Chris@439 | 482     // has a time. | 
| Chris@439 | 483 | 
| Chris@439 | 484     // We will then need to refine this big bag of results into a set | 
| Chris@439 | 485     // of data models. | 
| Chris@439 | 486 | 
| Chris@439 | 487     // Results that have different source signals should go into | 
| Chris@439 | 488     // different models. | 
| Chris@439 | 489 | 
| Chris@439 | 490     // Results that have different feature types should go into | 
| Chris@439 | 491     // different models. | 
| Chris@439 | 492 | 
| Chris@439 | 493     // Results that are sparse should go into different models from | 
| Chris@439 | 494     // those that are dense (we need to examine the timestamps to | 
| Chris@439 | 495     // establish this -- if the timestamps are regular, the results | 
| Chris@439 | 496     // are dense -- so we can't do it as we go along, only after | 
| Chris@439 | 497     // collecting all results). | 
| Chris@439 | 498 | 
| Chris@439 | 499     // Timed things that have features associated with them should not | 
| Chris@439 | 500     // appear directly in any model -- their features should appear | 
| Chris@439 | 501     // instead -- and these should be different models from those used | 
| Chris@439 | 502     // for timed things that do not have features. | 
| Chris@439 | 503 | 
| Chris@439 | 504     // As we load the results, we'll push them into a partially | 
| Chris@439 | 505     // structured container that maps from source signal (URI as | 
| Chris@439 | 506     // string) -> feature type (likewise) -> time -> list of values. | 
| Chris@439 | 507     // If the source signal or feature type is unavailable, the empty | 
| Chris@439 | 508     // string will do. | 
| Chris@439 | 509 | 
| Chris@449 | 510     QString prefixes = QString( | 
| Chris@439 | 511         " PREFIX event: <http://purl.org/NET/c4dm/event.owl#>" | 
| Chris@449 | 512         " PREFIX tl: <http://purl.org/NET/c4dm/timeline.owl#>" | 
| Chris@439 | 513         " PREFIX mo: <http://purl.org/ontology/mo/>" | 
| Chris@439 | 514         " PREFIX af: <http://purl.org/ontology/af/>" | 
| Chris@449 | 515         " PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>" | 
| Chris@449 | 516         ); | 
| Chris@439 | 517 | 
| Chris@449 | 518     QString queryString = prefixes + QString( | 
| Chris@449 | 519 | 
| Chris@499 | 520         " SELECT ?signal ?timed_thing ?event_type ?value" | 
| Chris@439 | 521         " FROM <%1>" | 
| Chris@439 | 522 | 
| Chris@439 | 523         " WHERE {" | 
| Chris@440 | 524 | 
| Chris@440 | 525         "   ?signal a mo:Signal ." | 
| Chris@440 | 526 | 
| Chris@439 | 527         "   ?signal mo:time ?interval ." | 
| Chris@449 | 528         "   ?interval tl:onTimeLine ?tl ." | 
| Chris@449 | 529         "   ?time tl:onTimeLine ?tl ." | 
| Chris@449 | 530         "   ?timed_thing event:time ?time ." | 
| Chris@440 | 531         "   ?timed_thing a ?event_type ." | 
| Chris@440 | 532 | 
| Chris@439 | 533         "   OPTIONAL {" | 
| Chris@440 | 534         "     ?timed_thing af:feature ?value" | 
| Chris@439 | 535         "   }" | 
| Chris@439 | 536         " }" | 
| Chris@439 | 537 | 
| Chris@439 | 538         ).arg(m_uristring); | 
| Chris@439 | 539 | 
| Chris@449 | 540     QString timeQueryString = prefixes + QString( | 
| Chris@449 | 541 | 
| Chris@449 | 542         " SELECT ?time FROM <%1> " | 
| Chris@449 | 543         " WHERE { " | 
| Chris@449 | 544         "   <%2> event:time ?t . " | 
| Chris@449 | 545         "   ?t tl:at ?time . " | 
| Chris@449 | 546         " } " | 
| Chris@449 | 547 | 
| Chris@449 | 548         ).arg(m_uristring); | 
| Chris@449 | 549 | 
| Chris@449 | 550     QString rangeQueryString = prefixes + QString( | 
| Chris@449 | 551 | 
| Chris@449 | 552         " SELECT ?time ?duration FROM <%1> " | 
| Chris@449 | 553         " WHERE { " | 
| Chris@449 | 554         "   <%2> event:time ?t . " | 
| Chris@449 | 555         "   ?t tl:beginsAt ?time . " | 
| Chris@449 | 556         "   ?t tl:duration ?duration . " | 
| Chris@449 | 557         " } " | 
| Chris@449 | 558 | 
| Chris@449 | 559         ).arg(m_uristring); | 
| Chris@449 | 560 | 
| Chris@449 | 561     QString labelQueryString = prefixes + QString( | 
| Chris@449 | 562 | 
| Chris@449 | 563         " SELECT ?label FROM <%1> " | 
| Chris@449 | 564         " WHERE { " | 
| Chris@449 | 565         "   <%2> rdfs:label ?label . " | 
| Chris@449 | 566         " } " | 
| Chris@449 | 567 | 
| Chris@449 | 568         ).arg(m_uristring); | 
| Chris@449 | 569 | 
| Chris@510 | 570     QString textQueryString = prefixes + QString( | 
| Chris@510 | 571 | 
| Chris@510 | 572         " SELECT ?label FROM <%1> " | 
| Chris@510 | 573         " WHERE { " | 
| Chris@510 | 574         "   <%2> af:text ?label . " | 
| Chris@510 | 575         " } " | 
| Chris@510 | 576 | 
| Chris@510 | 577         ).arg(m_uristring); | 
| Chris@510 | 578 | 
| Chris@489 | 579     SimpleSPARQLQuery query(s, queryString); | 
| Chris@439 | 580     query.setProgressReporter(reporter); | 
| Chris@439 | 581 | 
| Chris@500 | 582 //    cerr << "Query will be: " << queryString.toStdString() << endl; | 
| Chris@439 | 583 | 
| Chris@439 | 584     SimpleSPARQLQuery::ResultList results = query.execute(); | 
| Chris@439 | 585 | 
| Chris@439 | 586     if (!query.isOK()) { | 
| Chris@439 | 587         m_errorString = query.getErrorString(); | 
| Chris@440 | 588         return; | 
| Chris@439 | 589     } | 
| Chris@439 | 590 | 
| Chris@439 | 591     if (query.wasCancelled()) { | 
| Chris@439 | 592         m_errorString = "Query cancelled"; | 
| Chris@440 | 593         return; | 
| Chris@439 | 594     } | 
| Chris@439 | 595 | 
| Chris@449 | 596     /* | 
| Chris@449 | 597       This function is now only used for sparse data (for dense data | 
| Chris@449 | 598       we would be in getDataModelsDense instead). | 
| Chris@449 | 599 | 
| Chris@449 | 600       For sparse data, the determining factors in deciding what model | 
| Chris@449 | 601       to use are: Do the features have values? and Do the features | 
| Chris@449 | 602       have duration? | 
| Chris@449 | 603 | 
| Chris@449 | 604       We can run through the results and check off whether we find | 
| Chris@449 | 605       values and duration for each of the source+type keys, and then | 
| Chris@449 | 606       run through the source+type keys pushing each of the results | 
| Chris@449 | 607       into a suitable model. | 
| Chris@449 | 608 | 
| Chris@449 | 609       Unfortunately, at this point we do not yet have any actual | 
| Chris@449 | 610       timing data (time/duration) -- just the time URI. | 
| Chris@449 | 611 | 
| Chris@449 | 612       What we _could_ do is to create one of each type of model at the | 
| Chris@449 | 613       start, for each of the source+type keys, and then push each | 
| Chris@449 | 614       feature into the relevant model depending on what we find out | 
| Chris@449 | 615       about it.  Then return only non-empty models. | 
| Chris@449 | 616     */ | 
| Chris@449 | 617 | 
| Chris@449 | 618     // Map from signal source to event type to dimensionality to | 
| Chris@449 | 619     // presence of duration to model ptr.  Whee! | 
| Chris@449 | 620     std::map<QString, std::map<QString, std::map<int, std::map<bool, Model *> > > > | 
| Chris@449 | 621         modelMap; | 
| Chris@449 | 622 | 
| Chris@439 | 623     for (int i = 0; i < results.size(); ++i) { | 
| Chris@439 | 624 | 
| Chris@499 | 625         if (i % 4 == 0) { | 
| Chris@499 | 626             if (reporter) reporter->setProgress(i/4); | 
| Chris@499 | 627         } | 
| Chris@499 | 628 | 
| Chris@499 | 629         QString source = results[i]["signal"].value; | 
| Chris@449 | 630         QString type = results[i]["event_type"].value; | 
| Chris@449 | 631         QString thinguri = results[i]["timed_thing"].value; | 
| Chris@449 | 632 | 
| Chris@449 | 633         RealTime time; | 
| Chris@449 | 634         RealTime duration; | 
| Chris@439 | 635 | 
| Chris@449 | 636         bool haveTime = false; | 
| Chris@449 | 637         bool haveDuration = false; | 
| Chris@439 | 638 | 
| Chris@510 | 639         QString label = ""; | 
| Chris@510 | 640         bool text = (type.contains("Text") || type.contains("text")); // Ha, ha | 
| Chris@510 | 641 | 
| Chris@510 | 642         if (text) { | 
| Chris@510 | 643             label = SimpleSPARQLQuery::singleResultQuery | 
| Chris@510 | 644                 (s, textQueryString.arg(thinguri), "label").value; | 
| Chris@510 | 645         } | 
| Chris@510 | 646 | 
| Chris@510 | 647         if (label == "") { | 
| Chris@510 | 648             label = SimpleSPARQLQuery::singleResultQuery | 
| Chris@510 | 649                 (s, labelQueryString.arg(thinguri), "label").value; | 
| Chris@510 | 650         } | 
| Chris@449 | 651 | 
| Chris@489 | 652         SimpleSPARQLQuery rangeQuery(s, rangeQueryString.arg(thinguri)); | 
| Chris@450 | 653         SimpleSPARQLQuery::ResultList rangeResults = rangeQuery.execute(); | 
| Chris@450 | 654         if (!rangeResults.empty()) { | 
| Chris@450 | 655 //                std::cerr << rangeResults.size() << " range results" << std::endl; | 
| Chris@450 | 656             time = RealTime::fromXsdDuration | 
| Chris@450 | 657                 (rangeResults[0]["time"].value.toStdString()); | 
| Chris@450 | 658             duration = RealTime::fromXsdDuration | 
| Chris@450 | 659                 (rangeResults[0]["duration"].value.toStdString()); | 
| Chris@450 | 660 //                std::cerr << "duration string " << rangeResults[0]["duration"].value.toStdString() << std::endl; | 
| Chris@449 | 661             haveTime = true; | 
| Chris@450 | 662             haveDuration = true; | 
| Chris@449 | 663         } else { | 
| Chris@450 | 664             QString timestring = SimpleSPARQLQuery::singleResultQuery | 
| Chris@489 | 665                 (s, timeQueryString.arg(thinguri), "time").value; | 
| Chris@450 | 666             if (timestring != "") { | 
| Chris@450 | 667                 time = RealTime::fromXsdDuration(timestring.toStdString()); | 
| Chris@449 | 668                 haveTime = true; | 
| Chris@449 | 669             } | 
| Chris@449 | 670         } | 
| Chris@439 | 671 | 
| Chris@439 | 672         QString valuestring = results[i]["value"].value; | 
| Chris@449 | 673         std::vector<float> values; | 
| Chris@449 | 674 | 
| Chris@439 | 675         if (valuestring != "") { | 
| Chris@449 | 676             QStringList vsl = valuestring.split(" ", QString::SkipEmptyParts); | 
| Chris@449 | 677             for (int j = 0; j < vsl.size(); ++j) { | 
| Chris@449 | 678                 bool success = false; | 
| Chris@449 | 679                 float v = vsl[j].toFloat(&success); | 
| Chris@449 | 680                 if (success) values.push_back(v); | 
| Chris@449 | 681             } | 
| Chris@439 | 682         } | 
| Chris@439 | 683 | 
| Chris@449 | 684         int dimensions = 1; | 
| Chris@449 | 685         if (values.size() == 1) dimensions = 2; | 
| Chris@449 | 686         else if (values.size() > 1) dimensions = 3; | 
| Chris@449 | 687 | 
| Chris@449 | 688         Model *model = 0; | 
| Chris@449 | 689 | 
| Chris@449 | 690         if (modelMap[source][type][dimensions].find(haveDuration) == | 
| Chris@449 | 691             modelMap[source][type][dimensions].end()) { | 
| Chris@449 | 692 | 
| Chris@449 | 693 /* | 
| Chris@449 | 694             std::cerr << "Creating new model: source = " << source.toStdString() | 
| Chris@449 | 695                       << ", type = " << type.toStdString() << ", dimensions = " | 
| Chris@449 | 696                       << dimensions << ", haveDuration = " << haveDuration | 
| Chris@449 | 697                       << ", time = " << time << ", duration = " << duration | 
| Chris@449 | 698                       << std::endl; | 
| Chris@449 | 699 */ | 
| Chris@449 | 700 | 
| Chris@449 | 701             if (!haveDuration) { | 
| Chris@449 | 702 | 
| Chris@449 | 703                 if (dimensions == 1) { | 
| Chris@449 | 704 | 
| Chris@510 | 705                     if (text) { | 
| Chris@510 | 706 | 
| Chris@510 | 707                         model = new TextModel(m_sampleRate, 1, false); | 
| Chris@510 | 708 | 
| Chris@510 | 709                     } else { | 
| Chris@510 | 710 | 
| Chris@510 | 711                         model = new SparseOneDimensionalModel(m_sampleRate, 1, false); | 
| Chris@510 | 712                     } | 
| Chris@449 | 713 | 
| Chris@449 | 714                 } else if (dimensions == 2) { | 
| Chris@449 | 715 | 
| Chris@510 | 716                     if (text) { | 
| Chris@510 | 717 | 
| Chris@510 | 718                         model = new TextModel(m_sampleRate, 1, false); | 
| Chris@510 | 719 | 
| Chris@510 | 720                     } else { | 
| Chris@510 | 721 | 
| Chris@510 | 722                         model = new SparseTimeValueModel(m_sampleRate, 1, false); | 
| Chris@510 | 723                     } | 
| Chris@449 | 724 | 
| Chris@449 | 725                 } else { | 
| Chris@449 | 726 | 
| Chris@449 | 727                     // We don't have a three-dimensional sparse model, | 
| Chris@449 | 728                     // so use a note model.  We do have some logic (in | 
| Chris@449 | 729                     // extractStructure below) for guessing whether | 
| Chris@449 | 730                     // this should after all have been a dense model, | 
| Chris@449 | 731                     // but it's hard to apply it because we don't have | 
| Chris@449 | 732                     // all the necessary timing data yet... hmm | 
| Chris@449 | 733 | 
| Chris@449 | 734                     model = new NoteModel(m_sampleRate, 1, false); | 
| Chris@449 | 735                 } | 
| Chris@449 | 736 | 
| Chris@449 | 737             } else { // haveDuration | 
| Chris@449 | 738 | 
| Chris@449 | 739                 if (dimensions == 1 || dimensions == 2) { | 
| Chris@449 | 740 | 
| Chris@449 | 741                     // If our units are frequency or midi pitch, we | 
| Chris@449 | 742                     // should be using a note model... hm | 
| Chris@449 | 743 | 
| Chris@449 | 744                     model = new RegionModel(m_sampleRate, 1, false); | 
| Chris@449 | 745 | 
| Chris@449 | 746                 } else { | 
| Chris@449 | 747 | 
| Chris@449 | 748                     // We don't have a three-dimensional sparse model, | 
| Chris@449 | 749                     // so use a note model.  We do have some logic (in | 
| Chris@449 | 750                     // extractStructure below) for guessing whether | 
| Chris@449 | 751                     // this should after all have been a dense model, | 
| Chris@449 | 752                     // but it's hard to apply it because we don't have | 
| Chris@449 | 753                     // all the necessary timing data yet... hmm | 
| Chris@449 | 754 | 
| Chris@449 | 755                     model = new NoteModel(m_sampleRate, 1, false); | 
| Chris@449 | 756                 } | 
| Chris@449 | 757             } | 
| Chris@449 | 758 | 
| Chris@499 | 759             if (m_audioModelMap.find(source) != m_audioModelMap.end()) { | 
| Chris@499 | 760                 std::cerr << "source model for " << model << " is " << m_audioModelMap[source] << std::endl; | 
| Chris@499 | 761                 model->setSourceModel(m_audioModelMap[source]); | 
| Chris@499 | 762             } | 
| Chris@499 | 763 | 
| Chris@493 | 764             QString titleQuery = QString | 
| Chris@493 | 765                 ( | 
| Chris@493 | 766                     " PREFIX dc: <http://purl.org/dc/elements/1.1/> " | 
| Chris@493 | 767                     " SELECT ?title " | 
| Chris@493 | 768                     " FROM <%1> " | 
| Chris@493 | 769                     " WHERE { " | 
| Chris@493 | 770                     "   <%2> dc:title ?title . " | 
| Chris@493 | 771                     " } " | 
| Chris@493 | 772                     ).arg(m_uristring).arg(type); | 
| Chris@493 | 773             QString title = SimpleSPARQLQuery::singleResultQuery | 
| Chris@493 | 774                 (s, titleQuery, "title").value; | 
| Chris@493 | 775             if (title != "") model->setObjectName(title); | 
| Chris@493 | 776 | 
| Chris@449 | 777             modelMap[source][type][dimensions][haveDuration] = model; | 
| Chris@449 | 778             models.push_back(model); | 
| Chris@449 | 779         } | 
| Chris@449 | 780 | 
| Chris@449 | 781         model = modelMap[source][type][dimensions][haveDuration]; | 
| Chris@449 | 782 | 
| Chris@449 | 783         if (model) { | 
| Chris@449 | 784             long ftime = RealTime::realTime2Frame(time, m_sampleRate); | 
| Chris@449 | 785             long fduration = RealTime::realTime2Frame(duration, m_sampleRate); | 
| Chris@449 | 786             fillModel(model, ftime, fduration, haveDuration, values, label); | 
| Chris@439 | 787         } | 
| Chris@439 | 788     } | 
| Chris@439 | 789 } | 
| Chris@439 | 790 | 
| Chris@439 | 791 void | 
| Chris@449 | 792 RDFImporterImpl::fillModel(Model *model, | 
| Chris@449 | 793                            long ftime, | 
| Chris@449 | 794                            long fduration, | 
| Chris@449 | 795                            bool haveDuration, | 
| Chris@449 | 796                            std::vector<float> &values, | 
| Chris@449 | 797                            QString label) | 
| Chris@449 | 798 { | 
| Chris@493 | 799 //    std::cerr << "RDFImporterImpl::fillModel: adding point at frame " << ftime << std::endl; | 
| Chris@492 | 800 | 
| Chris@449 | 801     SparseOneDimensionalModel *sodm = | 
| Chris@449 | 802         dynamic_cast<SparseOneDimensionalModel *>(model); | 
| Chris@449 | 803     if (sodm) { | 
| Chris@449 | 804         SparseOneDimensionalModel::Point point(ftime, label); | 
| Chris@449 | 805         sodm->addPoint(point); | 
| Chris@449 | 806         return; | 
| Chris@449 | 807     } | 
| Chris@449 | 808 | 
| Chris@510 | 809     TextModel *tm = | 
| Chris@510 | 810         dynamic_cast<TextModel *>(model); | 
| Chris@510 | 811     if (tm) { | 
| Chris@510 | 812         TextModel::Point point | 
| Chris@510 | 813             (ftime, | 
| Chris@510 | 814              values.empty() ? 0.5f : values[0] < 0.f ? 0.f : values[0] > 1.f ? 1.f : values[0], // I was young and feckless once too | 
| Chris@510 | 815              label); | 
| Chris@510 | 816         tm->addPoint(point); | 
| Chris@510 | 817         return; | 
| Chris@510 | 818     } | 
| Chris@510 | 819 | 
| Chris@449 | 820     SparseTimeValueModel *stvm = | 
| Chris@449 | 821         dynamic_cast<SparseTimeValueModel *>(model); | 
| Chris@449 | 822     if (stvm) { | 
| Chris@449 | 823         SparseTimeValueModel::Point point | 
| Chris@449 | 824             (ftime, values.empty() ? 0.f : values[0], label); | 
| Chris@449 | 825         stvm->addPoint(point); | 
| Chris@449 | 826         return; | 
| Chris@449 | 827     } | 
| Chris@449 | 828 | 
| Chris@449 | 829     NoteModel *nm = | 
| Chris@449 | 830         dynamic_cast<NoteModel *>(model); | 
| Chris@449 | 831     if (nm) { | 
| Chris@449 | 832         if (haveDuration) { | 
| Chris@449 | 833             float value = 0.f, level = 1.f; | 
| Chris@449 | 834             if (!values.empty()) { | 
| Chris@449 | 835                 value = values[0]; | 
| Chris@449 | 836                 if (values.size() > 1) { | 
| Chris@449 | 837                     level = values[1]; | 
| Chris@449 | 838                 } | 
| Chris@449 | 839             } | 
| Chris@449 | 840             NoteModel::Point point(ftime, value, fduration, level, label); | 
| Chris@449 | 841             nm->addPoint(point); | 
| Chris@449 | 842         } else { | 
| Chris@449 | 843             float value = 0.f, duration = 1.f, level = 1.f; | 
| Chris@449 | 844             if (!values.empty()) { | 
| Chris@449 | 845                 value = values[0]; | 
| Chris@449 | 846                 if (values.size() > 1) { | 
| Chris@449 | 847                     duration = values[1]; | 
| Chris@449 | 848                     if (values.size() > 2) { | 
| Chris@449 | 849                         level = values[2]; | 
| Chris@449 | 850                     } | 
| Chris@449 | 851                 } | 
| Chris@449 | 852             } | 
| Chris@449 | 853             NoteModel::Point point(ftime, value, duration, level, label); | 
| Chris@449 | 854             nm->addPoint(point); | 
| Chris@449 | 855         } | 
| Chris@449 | 856         return; | 
| Chris@449 | 857     } | 
| Chris@449 | 858 | 
| Chris@449 | 859     RegionModel *rm = | 
| Chris@449 | 860         dynamic_cast<RegionModel *>(model); | 
| Chris@449 | 861     if (rm) { | 
| Chris@449 | 862         if (haveDuration) { | 
| Chris@449 | 863             RegionModel::Point point | 
| Chris@449 | 864                 (ftime, values.empty() ? 0.f : values[0], fduration, label); | 
| Chris@449 | 865             rm->addPoint(point); | 
| Chris@449 | 866         } else { | 
| Chris@449 | 867             // This won't actually happen -- we only create region models | 
| Chris@449 | 868             // if we do have duration -- but just for completeness | 
| Chris@449 | 869             float value = 0.f, duration = 1.f; | 
| Chris@449 | 870             if (!values.empty()) { | 
| Chris@449 | 871                 value = values[0]; | 
| Chris@449 | 872                 if (values.size() > 1) { | 
| Chris@449 | 873                     duration = values[1]; | 
| Chris@449 | 874                 } | 
| Chris@449 | 875             } | 
| Chris@449 | 876             RegionModel::Point point(ftime, value, duration, label); | 
| Chris@449 | 877             rm->addPoint(point); | 
| Chris@449 | 878         } | 
| Chris@449 | 879         return; | 
| Chris@449 | 880     } | 
| Chris@449 | 881 | 
| Chris@449 | 882     std::cerr << "WARNING: RDFImporterImpl::fillModel: Unknown or unexpected model type" << std::endl; | 
| Chris@449 | 883     return; | 
| Chris@449 | 884 } | 
| Chris@449 | 885 | 
| Chris@490 | 886 RDFImporter::RDFDocumentType | 
| Chris@490 | 887 RDFImporter::identifyDocumentType(QString url) | 
| Chris@490 | 888 { | 
| Chris@490 | 889     bool haveAudio = false; | 
| Chris@490 | 890     bool haveAnnotations = false; | 
| Chris@449 | 891 | 
| Chris@499 | 892     // This query is not expected to return any values, but if it | 
| Chris@499 | 893     // executes successfully (leaving no error in the error string) | 
| Chris@499 | 894     // then we know we have RDF | 
| Chris@499 | 895     SimpleSPARQLQuery q(SimpleSPARQLQuery::QueryFromSingleSource, | 
| Chris@499 | 896                         QString(" SELECT ?x FROM <%1> WHERE { ?x <y> <z> } ") | 
| Chris@499 | 897                         .arg(url)); | 
| Chris@499 | 898 | 
| Chris@499 | 899     SimpleSPARQLQuery::ResultList r = q.execute(); | 
| Chris@499 | 900     if (!q.isOK()) { | 
| Chris@499 | 901         return NotRDF; | 
| Chris@499 | 902     } | 
| Chris@499 | 903 | 
| Chris@490 | 904     SimpleSPARQLQuery::Value value = | 
| Chris@490 | 905         SimpleSPARQLQuery::singleResultQuery | 
| Chris@490 | 906         (SimpleSPARQLQuery::QueryFromSingleSource, | 
| Chris@490 | 907          QString | 
| Chris@490 | 908          (" PREFIX mo: <http://purl.org/ontology/mo/> " | 
| Chris@490 | 909           " SELECT ?url FROM <%1> " | 
| Chris@490 | 910           " WHERE { ?signal a mo:Signal ; mo:available_as ?url } " | 
| Chris@490 | 911              ).arg(url), | 
| Chris@490 | 912          "url"); | 
| Chris@490 | 913 | 
| Chris@490 | 914     if (value.type == SimpleSPARQLQuery::URIValue) { | 
| Chris@490 | 915         haveAudio = true; | 
| Chris@490 | 916     } | 
| Chris@490 | 917 | 
| Chris@490 | 918     value = | 
| Chris@490 | 919         SimpleSPARQLQuery::singleResultQuery | 
| Chris@490 | 920         (SimpleSPARQLQuery::QueryFromSingleSource, | 
| Chris@490 | 921          QString | 
| Chris@490 | 922          (" PREFIX event: <http://purl.org/NET/c4dm/event.owl#> " | 
| Chris@490 | 923           " SELECT ?thing FROM <%1> " | 
| Chris@490 | 924           " WHERE { ?thing event:time ?time } " | 
| Chris@490 | 925              ).arg(url), | 
| Chris@490 | 926          "thing"); | 
| Chris@490 | 927 | 
| Chris@490 | 928     if (value.type == SimpleSPARQLQuery::URIValue) { | 
| Chris@490 | 929         haveAnnotations = true; | 
| Chris@490 | 930     } | 
| Chris@490 | 931 | 
| Chris@490 | 932     if (!haveAnnotations) { | 
| Chris@490 | 933 | 
| Chris@490 | 934         value = | 
| Chris@490 | 935             SimpleSPARQLQuery::singleResultQuery | 
| Chris@490 | 936             (SimpleSPARQLQuery::QueryFromSingleSource, | 
| Chris@490 | 937              QString | 
| Chris@490 | 938              (" PREFIX af: <http://purl.org/ontology/af/> " | 
| Chris@490 | 939               " SELECT ?thing FROM <%1> " | 
| Chris@490 | 940               " WHERE { ?signal af:signal_feature ?thing } " | 
| Chris@490 | 941              ).arg(url), | 
| Chris@490 | 942              "thing"); | 
| Chris@490 | 943 | 
| Chris@490 | 944         if (value.type == SimpleSPARQLQuery::URIValue) { | 
| Chris@490 | 945             haveAnnotations = true; | 
| Chris@490 | 946         } | 
| Chris@490 | 947     } | 
| Chris@490 | 948 | 
| Chris@490 | 949     if (haveAudio) { | 
| Chris@490 | 950         if (haveAnnotations) { | 
| Chris@490 | 951             return AudioRefAndAnnotations; | 
| Chris@490 | 952         } else { | 
| Chris@490 | 953             return AudioRef; | 
| Chris@490 | 954         } | 
| Chris@490 | 955     } else { | 
| Chris@490 | 956         if (haveAnnotations) { | 
| Chris@490 | 957             return Annotations; | 
| Chris@490 | 958         } else { | 
| Chris@499 | 959             return OtherRDFDocument; | 
| Chris@490 | 960         } | 
| Chris@490 | 961     } | 
| Chris@492 | 962 | 
| Chris@492 | 963     SimpleSPARQLQuery::closeSingleSource(url); | 
| Chris@490 | 964 } | 
| Chris@490 | 965 | 
| Chris@490 | 966 |