annotate rdf/RDFImporter.cpp @ 690:1424aa29ae95

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