annotate document/SVFileReader.cpp @ 52:527598e2fa10

* Handle generator transforms (plugins whose channel count isn't dependent on number of audio inputs, as they have none) * Be less keen to suspend writing FFT data in spectrogram repaint -- only do it if we find we actually need to query the FFT data (i.e. we aren't repainting an area that hasn't been generated at all yet)
author Chris Cannam
date Tue, 10 Oct 2006 19:04:57 +0000
parents 5f9fdca0c7d8
children ca1e3f5657d5
rev   line source
Chris@0 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@0 2
Chris@0 3 /*
Chris@0 4 Sonic Visualiser
Chris@0 5 An audio file viewer and annotation editor.
Chris@0 6 Centre for Digital Music, Queen Mary, University of London.
Chris@0 7 This file copyright 2006 Chris Cannam.
Chris@0 8
Chris@0 9 This program is free software; you can redistribute it and/or
Chris@0 10 modify it under the terms of the GNU General Public License as
Chris@0 11 published by the Free Software Foundation; either version 2 of the
Chris@0 12 License, or (at your option) any later version. See the file
Chris@0 13 COPYING included with this distribution for more information.
Chris@0 14 */
Chris@0 15
Chris@0 16 #include "SVFileReader.h"
Chris@0 17
Chris@1 18 #include "layer/Layer.h"
Chris@1 19 #include "view/View.h"
Chris@0 20 #include "base/PlayParameters.h"
Chris@0 21 #include "base/PlayParameterRepository.h"
Chris@0 22
Chris@1 23 #include "data/fileio/AudioFileReaderFactory.h"
Chris@0 24
Chris@1 25 #include "data/model/WaveFileModel.h"
Chris@3 26 #include "data/model/EditableDenseThreeDimensionalModel.h"
Chris@1 27 #include "data/model/SparseOneDimensionalModel.h"
Chris@1 28 #include "data/model/SparseTimeValueModel.h"
Chris@1 29 #include "data/model/NoteModel.h"
Chris@1 30 #include "data/model/TextModel.h"
Chris@0 31
Chris@1 32 #include "view/Pane.h"
Chris@0 33
Chris@1 34 #include "Document.h"
Chris@0 35
Chris@0 36 #include <QString>
Chris@0 37 #include <QMessageBox>
Chris@0 38 #include <QFileDialog>
Chris@0 39
Chris@0 40 #include <iostream>
Chris@0 41
Chris@0 42 SVFileReader::SVFileReader(Document *document,
Chris@0 43 SVFileReaderPaneCallback &callback) :
Chris@0 44 m_document(document),
Chris@0 45 m_paneCallback(callback),
Chris@0 46 m_currentPane(0),
Chris@0 47 m_currentDataset(0),
Chris@0 48 m_currentDerivedModel(0),
Chris@0 49 m_currentPlayParameters(0),
Chris@0 50 m_datasetSeparator(" "),
Chris@0 51 m_inRow(false),
Chris@0 52 m_rowNumber(0),
Chris@0 53 m_ok(false)
Chris@0 54 {
Chris@0 55 }
Chris@0 56
Chris@0 57 void
Chris@0 58 SVFileReader::parse(const QString &xmlData)
Chris@0 59 {
Chris@0 60 QXmlInputSource inputSource;
Chris@0 61 inputSource.setData(xmlData);
Chris@0 62 parse(inputSource);
Chris@0 63 }
Chris@0 64
Chris@0 65 void
Chris@0 66 SVFileReader::parse(QXmlInputSource &inputSource)
Chris@0 67 {
Chris@0 68 QXmlSimpleReader reader;
Chris@0 69 reader.setContentHandler(this);
Chris@0 70 reader.setErrorHandler(this);
Chris@0 71 m_ok = reader.parse(inputSource);
Chris@0 72 }
Chris@0 73
Chris@0 74 bool
Chris@0 75 SVFileReader::isOK()
Chris@0 76 {
Chris@0 77 return m_ok;
Chris@0 78 }
Chris@0 79
Chris@0 80 SVFileReader::~SVFileReader()
Chris@0 81 {
Chris@0 82 if (!m_awaitingDatasets.empty()) {
Chris@0 83 std::cerr << "WARNING: SV-XML: File ended with "
Chris@0 84 << m_awaitingDatasets.size() << " unfilled model dataset(s)"
Chris@0 85 << std::endl;
Chris@0 86 }
Chris@0 87
Chris@0 88 std::set<Model *> unaddedModels;
Chris@0 89
Chris@0 90 for (std::map<int, Model *>::iterator i = m_models.begin();
Chris@0 91 i != m_models.end(); ++i) {
Chris@0 92 if (m_addedModels.find(i->second) == m_addedModels.end()) {
Chris@0 93 unaddedModels.insert(i->second);
Chris@0 94 }
Chris@0 95 }
Chris@0 96
Chris@0 97 if (!unaddedModels.empty()) {
Chris@0 98 std::cerr << "WARNING: SV-XML: File contained "
Chris@0 99 << unaddedModels.size() << " unused models"
Chris@0 100 << std::endl;
Chris@0 101 while (!unaddedModels.empty()) {
Chris@0 102 delete *unaddedModels.begin();
Chris@0 103 unaddedModels.erase(unaddedModels.begin());
Chris@0 104 }
Chris@0 105 }
Chris@0 106 }
Chris@0 107
Chris@0 108 bool
Chris@0 109 SVFileReader::startElement(const QString &, const QString &,
Chris@0 110 const QString &qName,
Chris@0 111 const QXmlAttributes &attributes)
Chris@0 112 {
Chris@0 113 QString name = qName.toLower();
Chris@0 114
Chris@0 115 bool ok = false;
Chris@0 116
Chris@0 117 // Valid element names:
Chris@0 118 //
Chris@0 119 // sv
Chris@0 120 // data
Chris@0 121 // dataset
Chris@0 122 // display
Chris@0 123 // derivation
Chris@0 124 // playparameters
Chris@0 125 // layer
Chris@0 126 // model
Chris@0 127 // point
Chris@0 128 // row
Chris@0 129 // view
Chris@0 130 // window
Chris@0 131
Chris@0 132 if (name == "sv") {
Chris@0 133
Chris@0 134 // nothing needed
Chris@0 135 ok = true;
Chris@0 136
Chris@0 137 } else if (name == "data") {
Chris@0 138
Chris@0 139 // nothing needed
Chris@0 140 m_inData = true;
Chris@0 141 ok = true;
Chris@0 142
Chris@0 143 } else if (name == "display") {
Chris@0 144
Chris@0 145 // nothing needed
Chris@0 146 ok = true;
Chris@0 147
Chris@0 148 } else if (name == "window") {
Chris@0 149
Chris@0 150 ok = readWindow(attributes);
Chris@0 151
Chris@0 152 } else if (name == "model") {
Chris@0 153
Chris@0 154 ok = readModel(attributes);
Chris@0 155
Chris@0 156 } else if (name == "dataset") {
Chris@0 157
Chris@0 158 ok = readDatasetStart(attributes);
Chris@0 159
Chris@0 160 } else if (name == "bin") {
Chris@0 161
Chris@0 162 ok = addBinToDataset(attributes);
Chris@0 163
Chris@0 164 } else if (name == "point") {
Chris@0 165
Chris@0 166 ok = addPointToDataset(attributes);
Chris@0 167
Chris@0 168 } else if (name == "row") {
Chris@0 169
Chris@0 170 ok = addRowToDataset(attributes);
Chris@0 171
Chris@0 172 } else if (name == "layer") {
Chris@0 173
Chris@0 174 addUnaddedModels(); // all models must be specified before first layer
Chris@0 175 ok = readLayer(attributes);
Chris@0 176
Chris@0 177 } else if (name == "view") {
Chris@0 178
Chris@0 179 m_inView = true;
Chris@0 180 ok = readView(attributes);
Chris@0 181
Chris@0 182 } else if (name == "derivation") {
Chris@0 183
Chris@0 184 ok = readDerivation(attributes);
Chris@0 185
Chris@0 186 } else if (name == "playparameters") {
Chris@0 187
Chris@0 188 ok = readPlayParameters(attributes);
Chris@0 189
Chris@0 190 } else if (name == "plugin") {
Chris@0 191
Chris@0 192 ok = readPlugin(attributes);
Chris@0 193
Chris@0 194 } else if (name == "selections") {
Chris@0 195
Chris@0 196 m_inSelections = true;
Chris@0 197 ok = true;
Chris@0 198
Chris@0 199 } else if (name == "selection") {
Chris@0 200
Chris@0 201 ok = readSelection(attributes);
Chris@0 202 }
Chris@0 203
Chris@0 204 if (!ok) {
Chris@0 205 std::cerr << "WARNING: SV-XML: Failed to completely process element \""
Chris@0 206 << name.toLocal8Bit().data() << "\"" << std::endl;
Chris@0 207 }
Chris@0 208
Chris@0 209 return true;
Chris@0 210 }
Chris@0 211
Chris@0 212 bool
Chris@0 213 SVFileReader::characters(const QString &text)
Chris@0 214 {
Chris@0 215 bool ok = false;
Chris@0 216
Chris@0 217 if (m_inRow) {
Chris@0 218 ok = readRowData(text);
Chris@0 219 if (!ok) {
Chris@0 220 std::cerr << "WARNING: SV-XML: Failed to read row data content for row " << m_rowNumber << std::endl;
Chris@0 221 }
Chris@0 222 }
Chris@0 223
Chris@0 224 return true;
Chris@0 225 }
Chris@0 226
Chris@0 227 bool
Chris@0 228 SVFileReader::endElement(const QString &, const QString &,
Chris@0 229 const QString &qName)
Chris@0 230 {
Chris@0 231 QString name = qName.toLower();
Chris@0 232
Chris@0 233 if (name == "dataset") {
Chris@0 234
Chris@0 235 if (m_currentDataset) {
Chris@0 236
Chris@0 237 bool foundInAwaiting = false;
Chris@0 238
Chris@0 239 for (std::map<int, int>::iterator i = m_awaitingDatasets.begin();
Chris@0 240 i != m_awaitingDatasets.end(); ++i) {
Chris@0 241 if (m_models[i->second] == m_currentDataset) {
Chris@0 242 m_awaitingDatasets.erase(i);
Chris@0 243 foundInAwaiting = true;
Chris@0 244 break;
Chris@0 245 }
Chris@0 246 }
Chris@0 247
Chris@0 248 if (!foundInAwaiting) {
Chris@0 249 std::cerr << "WARNING: SV-XML: Dataset precedes model, or no model uses dataset" << std::endl;
Chris@0 250 }
Chris@0 251 }
Chris@0 252
Chris@0 253 m_currentDataset = 0;
Chris@0 254
Chris@0 255 } else if (name == "data") {
Chris@0 256
Chris@0 257 addUnaddedModels();
Chris@0 258 m_inData = false;
Chris@0 259
Chris@0 260 } else if (name == "derivation") {
Chris@0 261
Chris@0 262 if (m_currentDerivedModel) {
Chris@0 263 m_document->addDerivedModel(m_currentTransform,
Chris@0 264 m_document->getMainModel(), //!!!
Chris@30 265 m_currentTransformContext,
Chris@0 266 m_currentDerivedModel,
Chris@0 267 m_currentTransformConfiguration);
Chris@0 268 m_addedModels.insert(m_currentDerivedModel);
Chris@0 269 m_currentDerivedModel = 0;
Chris@0 270 m_currentTransform = "";
Chris@0 271 m_currentTransformConfiguration = "";
Chris@0 272 }
Chris@0 273
Chris@0 274 } else if (name == "row") {
Chris@0 275 m_inRow = false;
Chris@0 276 } else if (name == "view") {
Chris@0 277 m_inView = false;
Chris@0 278 } else if (name == "selections") {
Chris@0 279 m_inSelections = false;
Chris@0 280 } else if (name == "playparameters") {
Chris@0 281 m_currentPlayParameters = 0;
Chris@0 282 }
Chris@0 283
Chris@0 284 return true;
Chris@0 285 }
Chris@0 286
Chris@0 287 bool
Chris@0 288 SVFileReader::error(const QXmlParseException &exception)
Chris@0 289 {
Chris@0 290 m_errorString =
Chris@0 291 QString("ERROR: SV-XML: %1 at line %2, column %3")
Chris@0 292 .arg(exception.message())
Chris@0 293 .arg(exception.lineNumber())
Chris@0 294 .arg(exception.columnNumber());
Chris@0 295 std::cerr << m_errorString.toLocal8Bit().data() << std::endl;
Chris@0 296 return QXmlDefaultHandler::error(exception);
Chris@0 297 }
Chris@0 298
Chris@0 299 bool
Chris@0 300 SVFileReader::fatalError(const QXmlParseException &exception)
Chris@0 301 {
Chris@0 302 m_errorString =
Chris@0 303 QString("FATAL ERROR: SV-XML: %1 at line %2, column %3")
Chris@0 304 .arg(exception.message())
Chris@0 305 .arg(exception.lineNumber())
Chris@0 306 .arg(exception.columnNumber());
Chris@0 307 std::cerr << m_errorString.toLocal8Bit().data() << std::endl;
Chris@0 308 return QXmlDefaultHandler::fatalError(exception);
Chris@0 309 }
Chris@0 310
Chris@0 311
Chris@0 312 #define READ_MANDATORY(TYPE, NAME, CONVERSION) \
Chris@0 313 TYPE NAME = attributes.value(#NAME).trimmed().CONVERSION(&ok); \
Chris@0 314 if (!ok) { \
Chris@0 315 std::cerr << "WARNING: SV-XML: Missing or invalid mandatory " #TYPE " attribute \"" #NAME "\"" << std::endl; \
Chris@0 316 return false; \
Chris@0 317 }
Chris@0 318
Chris@0 319 bool
Chris@0 320 SVFileReader::readWindow(const QXmlAttributes &attributes)
Chris@0 321 {
Chris@0 322 bool ok = false;
Chris@0 323
Chris@0 324 READ_MANDATORY(int, width, toInt);
Chris@0 325 READ_MANDATORY(int, height, toInt);
Chris@0 326
Chris@0 327 m_paneCallback.setWindowSize(width, height);
Chris@0 328 return true;
Chris@0 329 }
Chris@0 330
Chris@0 331 void
Chris@0 332 SVFileReader::addUnaddedModels()
Chris@0 333 {
Chris@0 334 std::set<Model *> unaddedModels;
Chris@0 335
Chris@0 336 for (std::map<int, Model *>::iterator i = m_models.begin();
Chris@0 337 i != m_models.end(); ++i) {
Chris@0 338 if (m_addedModels.find(i->second) == m_addedModels.end()) {
Chris@0 339 unaddedModels.insert(i->second);
Chris@0 340 }
Chris@0 341 }
Chris@0 342
Chris@0 343 for (std::set<Model *>::iterator i = unaddedModels.begin();
Chris@0 344 i != unaddedModels.end(); ++i) {
Chris@0 345 m_document->addImportedModel(*i);
Chris@0 346 m_addedModels.insert(*i);
Chris@0 347 }
Chris@0 348 }
Chris@0 349
Chris@0 350 bool
Chris@0 351 SVFileReader::readModel(const QXmlAttributes &attributes)
Chris@0 352 {
Chris@0 353 bool ok = false;
Chris@0 354
Chris@0 355 READ_MANDATORY(int, id, toInt);
Chris@0 356
Chris@0 357 if (m_models.find(id) != m_models.end()) {
Chris@0 358 std::cerr << "WARNING: SV-XML: Ignoring duplicate model id " << id
Chris@0 359 << std::endl;
Chris@0 360 return false;
Chris@0 361 }
Chris@0 362
Chris@0 363 QString name = attributes.value("name");
Chris@0 364
Chris@0 365 READ_MANDATORY(int, sampleRate, toInt);
Chris@0 366
Chris@0 367 QString type = attributes.value("type").trimmed();
Chris@0 368 bool mainModel = (attributes.value("mainModel").trimmed() == "true");
Chris@0 369
Chris@0 370 if (type == "wavefile") {
Chris@0 371
Chris@0 372 QString file = attributes.value("file");
Chris@0 373 WaveFileModel *model = new WaveFileModel(file);
Chris@0 374
Chris@0 375 while (!model->isOK()) {
Chris@0 376
Chris@0 377 delete model;
Chris@0 378 model = 0;
Chris@0 379
Chris@0 380 if (QMessageBox::question(0,
Chris@0 381 QMessageBox::tr("Failed to open file"),
Chris@0 382 QMessageBox::tr("Audio file \"%1\" could not be opened.\nLocate it?").arg(file),
Chris@0 383 QMessageBox::Ok,
Chris@0 384 QMessageBox::Cancel) == QMessageBox::Ok) {
Chris@0 385
Chris@0 386 QString path = QFileDialog::getOpenFileName
Chris@0 387 (0, QFileDialog::tr("Locate file \"%1\"").arg(QFileInfo(file).fileName()), file,
Chris@0 388 QFileDialog::tr("Audio files (%1)\nAll files (*.*)")
Chris@0 389 .arg(AudioFileReaderFactory::getKnownExtensions()));
Chris@0 390
Chris@0 391 if (path != "") {
Chris@0 392 model = new WaveFileModel(path);
Chris@0 393 } else {
Chris@0 394 return false;
Chris@0 395 }
Chris@0 396 } else {
Chris@0 397 return false;
Chris@0 398 }
Chris@0 399 }
Chris@0 400
Chris@0 401 m_models[id] = model;
Chris@0 402 if (mainModel) {
Chris@0 403 m_document->setMainModel(model);
Chris@0 404 m_addedModels.insert(model);
Chris@0 405 }
Chris@0 406 // Derived models will be added when their derivation
Chris@0 407 // is found.
Chris@0 408
Chris@0 409 return true;
Chris@0 410
Chris@0 411 } else if (type == "dense") {
Chris@0 412
Chris@0 413 READ_MANDATORY(int, dimensions, toInt);
Chris@0 414
Chris@0 415 // Currently the only dense model we support here
Chris@0 416 // is the dense 3d model. Dense time-value models
Chris@0 417 // are always file-backed waveform data, at this
Chris@0 418 // point, and they come in as the wavefile model
Chris@0 419 // type above.
Chris@0 420
Chris@0 421 if (dimensions == 3) {
Chris@0 422
Chris@0 423 READ_MANDATORY(int, windowSize, toInt);
Chris@0 424 READ_MANDATORY(int, yBinCount, toInt);
Chris@0 425
Chris@3 426 EditableDenseThreeDimensionalModel *model =
Chris@3 427 new EditableDenseThreeDimensionalModel
Chris@3 428 (sampleRate, windowSize, yBinCount);
Chris@0 429
Chris@0 430 float minimum = attributes.value("minimum").trimmed().toFloat(&ok);
Chris@0 431 if (ok) model->setMinimumLevel(minimum);
Chris@0 432
Chris@0 433 float maximum = attributes.value("maximum").trimmed().toFloat(&ok);
Chris@0 434 if (ok) model->setMaximumLevel(maximum);
Chris@0 435
Chris@0 436 int dataset = attributes.value("dataset").trimmed().toInt(&ok);
Chris@0 437 if (ok) m_awaitingDatasets[dataset] = id;
Chris@0 438
Chris@0 439 m_models[id] = model;
Chris@0 440 return true;
Chris@0 441
Chris@0 442 } else {
Chris@0 443
Chris@0 444 std::cerr << "WARNING: SV-XML: Unexpected dense model dimension ("
Chris@0 445 << dimensions << ")" << std::endl;
Chris@0 446 }
Chris@0 447 } else if (type == "sparse") {
Chris@0 448
Chris@0 449 READ_MANDATORY(int, dimensions, toInt);
Chris@0 450
Chris@0 451 if (dimensions == 1) {
Chris@0 452
Chris@0 453 READ_MANDATORY(int, resolution, toInt);
Chris@0 454
Chris@0 455 SparseOneDimensionalModel *model = new SparseOneDimensionalModel
Chris@0 456 (sampleRate, resolution);
Chris@0 457 m_models[id] = model;
Chris@0 458
Chris@0 459 int dataset = attributes.value("dataset").trimmed().toInt(&ok);
Chris@0 460 if (ok) m_awaitingDatasets[dataset] = id;
Chris@0 461
Chris@0 462 return true;
Chris@0 463
Chris@0 464 } else if (dimensions == 2 || dimensions == 3) {
Chris@0 465
Chris@0 466 READ_MANDATORY(int, resolution, toInt);
Chris@0 467
Chris@0 468 float minimum = attributes.value("minimum").trimmed().toFloat(&ok);
Chris@0 469 float maximum = attributes.value("maximum").trimmed().toFloat(&ok);
Chris@0 470 float valueQuantization =
Chris@0 471 attributes.value("valueQuantization").trimmed().toFloat(&ok);
Chris@0 472
Chris@0 473 bool notifyOnAdd = (attributes.value("notifyOnAdd") == "true");
Chris@0 474
Chris@0 475 QString units = attributes.value("units");
Chris@0 476
Chris@0 477 if (dimensions == 2) {
Chris@0 478 if (attributes.value("subtype") == "text") {
Chris@0 479 TextModel *model = new TextModel
Chris@0 480 (sampleRate, resolution, notifyOnAdd);
Chris@0 481 m_models[id] = model;
Chris@0 482 } else {
Chris@0 483 SparseTimeValueModel *model = new SparseTimeValueModel
Chris@0 484 (sampleRate, resolution, minimum, maximum, notifyOnAdd);
Chris@0 485 model->setScaleUnits(units);
Chris@0 486 m_models[id] = model;
Chris@0 487 }
Chris@0 488 } else {
Chris@0 489 NoteModel *model = new NoteModel
Chris@0 490 (sampleRate, resolution, minimum, maximum, notifyOnAdd);
Chris@0 491 model->setValueQuantization(valueQuantization);
Chris@0 492 model->setScaleUnits(units);
Chris@0 493 m_models[id] = model;
Chris@0 494 }
Chris@0 495
Chris@0 496 int dataset = attributes.value("dataset").trimmed().toInt(&ok);
Chris@0 497 if (ok) m_awaitingDatasets[dataset] = id;
Chris@0 498
Chris@0 499 return true;
Chris@0 500
Chris@0 501 } else {
Chris@0 502
Chris@0 503 std::cerr << "WARNING: SV-XML: Unexpected sparse model dimension ("
Chris@0 504 << dimensions << ")" << std::endl;
Chris@0 505 }
Chris@0 506 } else {
Chris@0 507
Chris@0 508 std::cerr << "WARNING: SV-XML: Unexpected model type \""
Chris@0 509 << type.toLocal8Bit().data() << "\" for model id" << id << std::endl;
Chris@0 510 }
Chris@0 511
Chris@0 512 return false;
Chris@0 513 }
Chris@0 514
Chris@0 515 bool
Chris@0 516 SVFileReader::readView(const QXmlAttributes &attributes)
Chris@0 517 {
Chris@0 518 QString type = attributes.value("type");
Chris@0 519 m_currentPane = 0;
Chris@0 520
Chris@0 521 if (type != "pane") {
Chris@0 522 std::cerr << "WARNING: SV-XML: Unexpected view type \""
Chris@0 523 << type.toLocal8Bit().data() << "\"" << std::endl;
Chris@0 524 return false;
Chris@0 525 }
Chris@0 526
Chris@0 527 m_currentPane = m_paneCallback.addPane();
Chris@0 528
Chris@0 529 if (!m_currentPane) {
Chris@0 530 std::cerr << "WARNING: SV-XML: Internal error: Failed to add pane!"
Chris@0 531 << std::endl;
Chris@0 532 return false;
Chris@0 533 }
Chris@0 534
Chris@0 535 bool ok = false;
Chris@0 536
Chris@0 537 View *view = m_currentPane;
Chris@0 538
Chris@0 539 // The view properties first
Chris@0 540
Chris@0 541 READ_MANDATORY(size_t, centre, toUInt);
Chris@0 542 READ_MANDATORY(size_t, zoom, toUInt);
Chris@0 543 READ_MANDATORY(int, followPan, toInt);
Chris@0 544 READ_MANDATORY(int, followZoom, toInt);
Chris@0 545 READ_MANDATORY(int, light, toInt);
Chris@0 546 QString tracking = attributes.value("tracking");
Chris@0 547
Chris@0 548 // Specify the follow modes before we set the actual values
Chris@0 549 view->setFollowGlobalPan(followPan);
Chris@0 550 view->setFollowGlobalZoom(followZoom);
Chris@0 551 view->setPlaybackFollow(tracking == "scroll" ? View::PlaybackScrollContinuous :
Chris@0 552 tracking == "page" ? View::PlaybackScrollPage
Chris@0 553 : View::PlaybackIgnore);
Chris@0 554
Chris@0 555 // Then set these values
Chris@0 556 view->setCentreFrame(centre);
Chris@0 557 view->setZoomLevel(zoom);
Chris@0 558 view->setLightBackground(light);
Chris@0 559
Chris@0 560 // And pane properties
Chris@0 561 READ_MANDATORY(int, centreLineVisible, toInt);
Chris@0 562 m_currentPane->setCentreLineVisible(centreLineVisible);
Chris@0 563
Chris@0 564 int height = attributes.value("height").toInt(&ok);
Chris@0 565 if (ok) {
Chris@0 566 m_currentPane->resize(m_currentPane->width(), height);
Chris@0 567 }
Chris@0 568
Chris@0 569 return true;
Chris@0 570 }
Chris@0 571
Chris@0 572 bool
Chris@0 573 SVFileReader::readLayer(const QXmlAttributes &attributes)
Chris@0 574 {
Chris@0 575 QString type = attributes.value("type");
Chris@0 576
Chris@0 577 int id;
Chris@0 578 bool ok = false;
Chris@0 579 id = attributes.value("id").trimmed().toInt(&ok);
Chris@0 580
Chris@0 581 if (!ok) {
Chris@0 582 std::cerr << "WARNING: SV-XML: No layer id for layer of type \""
Chris@0 583 << type.toLocal8Bit().data()
Chris@0 584 << "\"" << std::endl;
Chris@0 585 return false;
Chris@0 586 }
Chris@0 587
Chris@0 588 Layer *layer = 0;
Chris@0 589 bool isNewLayer = false;
Chris@0 590
Chris@0 591 // Layers are expected to be defined in layer elements in the data
Chris@0 592 // section, and referred to in layer elements in the view
Chris@0 593 // sections. So if we're in the data section, we expect this
Chris@0 594 // layer not to exist already; if we're in the view section, we
Chris@0 595 // expect it to exist.
Chris@0 596
Chris@0 597 if (m_inData) {
Chris@0 598
Chris@0 599 if (m_layers.find(id) != m_layers.end()) {
Chris@0 600 std::cerr << "WARNING: SV-XML: Ignoring duplicate layer id " << id
Chris@0 601 << " in data section" << std::endl;
Chris@0 602 return false;
Chris@0 603 }
Chris@0 604
Chris@0 605 layer = m_layers[id] = m_document->createLayer
Chris@0 606 (LayerFactory::getInstance()->getLayerTypeForName(type));
Chris@0 607
Chris@0 608 if (layer) {
Chris@0 609 m_layers[id] = layer;
Chris@0 610 isNewLayer = true;
Chris@0 611 }
Chris@0 612
Chris@0 613 } else {
Chris@0 614
Chris@0 615 if (!m_currentPane) {
Chris@0 616 std::cerr << "WARNING: SV-XML: No current pane for layer " << id
Chris@0 617 << " in view section" << std::endl;
Chris@0 618 return false;
Chris@0 619 }
Chris@0 620
Chris@0 621 if (m_layers.find(id) != m_layers.end()) {
Chris@0 622
Chris@0 623 layer = m_layers[id];
Chris@0 624
Chris@0 625 } else {
Chris@0 626 std::cerr << "WARNING: SV-XML: Layer id " << id
Chris@0 627 << " in view section has not been defined -- defining it here"
Chris@0 628 << std::endl;
Chris@0 629
Chris@0 630 layer = m_document->createLayer
Chris@0 631 (LayerFactory::getInstance()->getLayerTypeForName(type));
Chris@0 632
Chris@0 633 if (layer) {
Chris@0 634 m_layers[id] = layer;
Chris@0 635 isNewLayer = true;
Chris@0 636 }
Chris@0 637 }
Chris@0 638 }
Chris@0 639
Chris@0 640 if (!layer) {
Chris@0 641 std::cerr << "WARNING: SV-XML: Failed to add layer of type \""
Chris@0 642 << type.toLocal8Bit().data()
Chris@0 643 << "\"" << std::endl;
Chris@0 644 return false;
Chris@0 645 }
Chris@0 646
Chris@0 647 if (isNewLayer) {
Chris@0 648
Chris@0 649 QString name = attributes.value("name");
Chris@0 650 layer->setObjectName(name);
Chris@0 651
Chris@0 652 int modelId;
Chris@0 653 bool modelOk = false;
Chris@0 654 modelId = attributes.value("model").trimmed().toInt(&modelOk);
Chris@0 655
Chris@0 656 if (modelOk) {
Chris@0 657 if (m_models.find(modelId) != m_models.end()) {
Chris@0 658 Model *model = m_models[modelId];
Chris@0 659 m_document->setModel(layer, model);
Chris@0 660 } else {
Chris@0 661 std::cerr << "WARNING: SV-XML: Unknown model id " << modelId
Chris@0 662 << " in layer definition" << std::endl;
Chris@0 663 }
Chris@0 664 }
Chris@0 665
Chris@0 666 layer->setProperties(attributes);
Chris@0 667 }
Chris@0 668
Chris@0 669 if (!m_inData && m_currentPane) {
Chris@0 670 m_document->addLayerToView(m_currentPane, layer);
Chris@0 671 }
Chris@0 672
Chris@0 673 return true;
Chris@0 674 }
Chris@0 675
Chris@0 676 bool
Chris@0 677 SVFileReader::readDatasetStart(const QXmlAttributes &attributes)
Chris@0 678 {
Chris@0 679 bool ok = false;
Chris@0 680
Chris@0 681 READ_MANDATORY(int, id, toInt);
Chris@0 682 READ_MANDATORY(int, dimensions, toInt);
Chris@0 683
Chris@0 684 if (m_awaitingDatasets.find(id) == m_awaitingDatasets.end()) {
Chris@0 685 std::cerr << "WARNING: SV-XML: Unwanted dataset " << id << std::endl;
Chris@0 686 return false;
Chris@0 687 }
Chris@0 688
Chris@0 689 int modelId = m_awaitingDatasets[id];
Chris@0 690
Chris@0 691 Model *model = 0;
Chris@0 692 if (m_models.find(modelId) != m_models.end()) {
Chris@0 693 model = m_models[modelId];
Chris@0 694 } else {
Chris@0 695 std::cerr << "WARNING: SV-XML: Internal error: Unknown model " << modelId
Chris@0 696 << " expecting dataset " << id << std::endl;
Chris@0 697 return false;
Chris@0 698 }
Chris@0 699
Chris@0 700 bool good = false;
Chris@0 701
Chris@0 702 switch (dimensions) {
Chris@0 703 case 1:
Chris@0 704 if (dynamic_cast<SparseOneDimensionalModel *>(model)) good = true;
Chris@0 705 break;
Chris@0 706
Chris@0 707 case 2:
Chris@0 708 if (dynamic_cast<SparseTimeValueModel *>(model)) good = true;
Chris@0 709 else if (dynamic_cast<TextModel *>(model)) good = true;
Chris@0 710 break;
Chris@0 711
Chris@0 712 case 3:
Chris@0 713 if (dynamic_cast<NoteModel *>(model)) good = true;
Chris@3 714 else if (dynamic_cast<EditableDenseThreeDimensionalModel *>(model)) {
Chris@0 715 m_datasetSeparator = attributes.value("separator");
Chris@0 716 good = true;
Chris@0 717 }
Chris@0 718 break;
Chris@0 719 }
Chris@0 720
Chris@0 721 if (!good) {
Chris@0 722 std::cerr << "WARNING: SV-XML: Model id " << modelId << " has wrong number of dimensions for " << dimensions << "-D dataset " << id << std::endl;
Chris@0 723 m_currentDataset = 0;
Chris@0 724 return false;
Chris@0 725 }
Chris@0 726
Chris@0 727 m_currentDataset = model;
Chris@0 728 return true;
Chris@0 729 }
Chris@0 730
Chris@0 731 bool
Chris@0 732 SVFileReader::addPointToDataset(const QXmlAttributes &attributes)
Chris@0 733 {
Chris@0 734 bool ok = false;
Chris@0 735
Chris@0 736 READ_MANDATORY(int, frame, toInt);
Chris@0 737
Chris@0 738 SparseOneDimensionalModel *sodm = dynamic_cast<SparseOneDimensionalModel *>
Chris@0 739 (m_currentDataset);
Chris@0 740
Chris@0 741 if (sodm) {
Chris@0 742 QString label = attributes.value("label");
Chris@0 743 sodm->addPoint(SparseOneDimensionalModel::Point(frame, label));
Chris@0 744 return true;
Chris@0 745 }
Chris@0 746
Chris@0 747 SparseTimeValueModel *stvm = dynamic_cast<SparseTimeValueModel *>
Chris@0 748 (m_currentDataset);
Chris@0 749
Chris@0 750 if (stvm) {
Chris@0 751 float value = 0.0;
Chris@0 752 value = attributes.value("value").trimmed().toFloat(&ok);
Chris@0 753 QString label = attributes.value("label");
Chris@0 754 stvm->addPoint(SparseTimeValueModel::Point(frame, value, label));
Chris@0 755 return ok;
Chris@0 756 }
Chris@0 757
Chris@0 758 NoteModel *nm = dynamic_cast<NoteModel *>(m_currentDataset);
Chris@0 759
Chris@0 760 if (nm) {
Chris@0 761 float value = 0.0;
Chris@0 762 value = attributes.value("value").trimmed().toFloat(&ok);
Chris@0 763 float duration = 0.0;
Chris@0 764 duration = attributes.value("duration").trimmed().toFloat(&ok);
Chris@0 765 QString label = attributes.value("label");
Chris@0 766 nm->addPoint(NoteModel::Point(frame, value, duration, label));
Chris@0 767 return ok;
Chris@0 768 }
Chris@0 769
Chris@0 770 TextModel *tm = dynamic_cast<TextModel *>(m_currentDataset);
Chris@0 771
Chris@0 772 if (tm) {
Chris@0 773 float height = 0.0;
Chris@0 774 height = attributes.value("height").trimmed().toFloat(&ok);
Chris@0 775 QString label = attributes.value("label");
Chris@0 776 tm->addPoint(TextModel::Point(frame, height, label));
Chris@0 777 return ok;
Chris@0 778 }
Chris@0 779
Chris@0 780 std::cerr << "WARNING: SV-XML: Point element found in non-point dataset" << std::endl;
Chris@0 781
Chris@0 782 return false;
Chris@0 783 }
Chris@0 784
Chris@0 785 bool
Chris@0 786 SVFileReader::addBinToDataset(const QXmlAttributes &attributes)
Chris@0 787 {
Chris@3 788 EditableDenseThreeDimensionalModel *dtdm =
Chris@3 789 dynamic_cast<EditableDenseThreeDimensionalModel *>
Chris@0 790 (m_currentDataset);
Chris@0 791
Chris@0 792 if (dtdm) {
Chris@0 793
Chris@0 794 bool ok = false;
Chris@0 795 int n = attributes.value("number").trimmed().toInt(&ok);
Chris@0 796 if (!ok) {
Chris@0 797 std::cerr << "WARNING: SV-XML: Missing or invalid bin number"
Chris@0 798 << std::endl;
Chris@0 799 return false;
Chris@0 800 }
Chris@0 801
Chris@0 802 QString name = attributes.value("name");
Chris@0 803
Chris@0 804 dtdm->setBinName(n, name);
Chris@0 805 return true;
Chris@0 806 }
Chris@0 807
Chris@0 808 std::cerr << "WARNING: SV-XML: Bin definition found in incompatible dataset" << std::endl;
Chris@0 809
Chris@0 810 return false;
Chris@0 811 }
Chris@0 812
Chris@0 813
Chris@0 814 bool
Chris@0 815 SVFileReader::addRowToDataset(const QXmlAttributes &attributes)
Chris@0 816 {
Chris@0 817 m_inRow = false;
Chris@0 818
Chris@0 819 bool ok = false;
Chris@0 820 m_rowNumber = attributes.value("n").trimmed().toInt(&ok);
Chris@0 821 if (!ok) {
Chris@0 822 std::cerr << "WARNING: SV-XML: Missing or invalid row number"
Chris@0 823 << std::endl;
Chris@0 824 return false;
Chris@0 825 }
Chris@0 826
Chris@0 827 m_inRow = true;
Chris@0 828
Chris@0 829 // std::cerr << "SV-XML: In row " << m_rowNumber << std::endl;
Chris@0 830
Chris@0 831 return true;
Chris@0 832 }
Chris@0 833
Chris@0 834 bool
Chris@0 835 SVFileReader::readRowData(const QString &text)
Chris@0 836 {
Chris@3 837 EditableDenseThreeDimensionalModel *dtdm =
Chris@3 838 dynamic_cast<EditableDenseThreeDimensionalModel *>
Chris@0 839 (m_currentDataset);
Chris@0 840
Chris@0 841 bool warned = false;
Chris@0 842
Chris@0 843 if (dtdm) {
Chris@0 844 QStringList data = text.split(m_datasetSeparator);
Chris@0 845
Chris@51 846 DenseThreeDimensionalModel::Column values;
Chris@0 847
Chris@0 848 for (QStringList::iterator i = data.begin(); i != data.end(); ++i) {
Chris@0 849
Chris@51 850 if (values.size() == dtdm->getHeight()) {
Chris@0 851 if (!warned) {
Chris@0 852 std::cerr << "WARNING: SV-XML: Too many y-bins in 3-D dataset row "
Chris@0 853 << m_rowNumber << std::endl;
Chris@0 854 warned = true;
Chris@0 855 }
Chris@0 856 }
Chris@0 857
Chris@0 858 bool ok;
Chris@0 859 float value = i->toFloat(&ok);
Chris@0 860 if (!ok) {
Chris@0 861 std::cerr << "WARNING: SV-XML: Bad floating-point value "
Chris@0 862 << i->toLocal8Bit().data()
Chris@0 863 << " in row data" << std::endl;
Chris@0 864 } else {
Chris@0 865 values.push_back(value);
Chris@0 866 }
Chris@0 867 }
Chris@0 868
Chris@51 869 dtdm->setColumn(m_rowNumber, values);
Chris@0 870 return true;
Chris@0 871 }
Chris@0 872
Chris@0 873 std::cerr << "WARNING: SV-XML: Row data found in non-row dataset" << std::endl;
Chris@0 874
Chris@0 875 return false;
Chris@0 876 }
Chris@0 877
Chris@0 878 bool
Chris@0 879 SVFileReader::readDerivation(const QXmlAttributes &attributes)
Chris@0 880 {
Chris@0 881 int modelId = 0;
Chris@0 882 bool modelOk = false;
Chris@0 883 modelId = attributes.value("model").trimmed().toInt(&modelOk);
Chris@0 884
Chris@0 885 if (!modelOk) {
Chris@0 886 std::cerr << "WARNING: SV-XML: No model id specified for derivation" << std::endl;
Chris@0 887 return false;
Chris@0 888 }
Chris@0 889
Chris@0 890 QString transform = attributes.value("transform");
Chris@0 891
Chris@0 892 if (m_models.find(modelId) != m_models.end()) {
Chris@0 893
Chris@0 894 m_currentDerivedModel = m_models[modelId];
Chris@0 895 m_currentTransform = transform;
Chris@0 896 m_currentTransformConfiguration = "";
Chris@0 897
Chris@30 898 m_currentTransformContext = PluginTransform::ExecutionContext();
Chris@30 899
Chris@0 900 bool ok = false;
Chris@0 901 int channel = attributes.value("channel").trimmed().toInt(&ok);
Chris@30 902 if (ok) m_currentTransformContext.channel = channel;
Chris@30 903
Chris@30 904 int domain = attributes.value("domain").trimmed().toInt(&ok);
Chris@30 905 if (ok) m_currentTransformContext.domain = Vamp::Plugin::InputDomain(domain);
Chris@30 906
Chris@30 907 int stepSize = attributes.value("stepSize").trimmed().toInt(&ok);
Chris@30 908 if (ok) m_currentTransformContext.stepSize = stepSize;
Chris@30 909
Chris@30 910 int blockSize = attributes.value("blockSize").trimmed().toInt(&ok);
Chris@30 911 if (ok) m_currentTransformContext.blockSize = blockSize;
Chris@30 912
Chris@30 913 int windowType = attributes.value("windowType").trimmed().toInt(&ok);
Chris@30 914 if (ok) m_currentTransformContext.windowType = WindowType(windowType);
Chris@0 915
Chris@0 916 } else {
Chris@0 917 std::cerr << "WARNING: SV-XML: Unknown derived model " << modelId
Chris@0 918 << " for transform \"" << transform.toLocal8Bit().data() << "\""
Chris@0 919 << std::endl;
Chris@0 920 return false;
Chris@0 921 }
Chris@0 922
Chris@0 923 return true;
Chris@0 924 }
Chris@0 925
Chris@0 926 bool
Chris@0 927 SVFileReader::readPlayParameters(const QXmlAttributes &attributes)
Chris@0 928 {
Chris@0 929 m_currentPlayParameters = 0;
Chris@0 930
Chris@0 931 int modelId = 0;
Chris@0 932 bool modelOk = false;
Chris@0 933 modelId = attributes.value("model").trimmed().toInt(&modelOk);
Chris@0 934
Chris@0 935 if (!modelOk) {
Chris@0 936 std::cerr << "WARNING: SV-XML: No model id specified for play parameters" << std::endl;
Chris@0 937 return false;
Chris@0 938 }
Chris@0 939
Chris@0 940 if (m_models.find(modelId) != m_models.end()) {
Chris@0 941
Chris@0 942 bool ok = false;
Chris@0 943
Chris@0 944 PlayParameters *parameters = PlayParameterRepository::getInstance()->
Chris@0 945 getPlayParameters(m_models[modelId]);
Chris@0 946
Chris@0 947 if (!parameters) {
Chris@0 948 std::cerr << "WARNING: SV-XML: Play parameters for model "
Chris@0 949 << modelId
Chris@0 950 << " not found - has model been added to document?"
Chris@0 951 << std::endl;
Chris@0 952 return false;
Chris@0 953 }
Chris@0 954
Chris@0 955 bool muted = (attributes.value("mute").trimmed() == "true");
Chris@0 956 if (ok) parameters->setPlayMuted(muted);
Chris@0 957
Chris@0 958 float pan = attributes.value("pan").toFloat(&ok);
Chris@0 959 if (ok) parameters->setPlayPan(pan);
Chris@0 960
Chris@0 961 float gain = attributes.value("gain").toFloat(&ok);
Chris@0 962 if (ok) parameters->setPlayGain(gain);
Chris@0 963
Chris@0 964 QString pluginId = attributes.value("pluginId");
Chris@0 965 if (pluginId != "") parameters->setPlayPluginId(pluginId);
Chris@0 966
Chris@0 967 m_currentPlayParameters = parameters;
Chris@0 968
Chris@0 969 // std::cerr << "Current play parameters for model: " << m_models[modelId] << ": " << m_currentPlayParameters << std::endl;
Chris@0 970
Chris@0 971 } else {
Chris@0 972
Chris@0 973 std::cerr << "WARNING: SV-XML: Unknown model " << modelId
Chris@0 974 << " for play parameters" << std::endl;
Chris@0 975 return false;
Chris@0 976 }
Chris@0 977
Chris@0 978 return true;
Chris@0 979 }
Chris@0 980
Chris@0 981 bool
Chris@0 982 SVFileReader::readPlugin(const QXmlAttributes &attributes)
Chris@0 983 {
Chris@0 984 if (!m_currentDerivedModel && !m_currentPlayParameters) {
Chris@0 985 std::cerr << "WARNING: SV-XML: Plugin found outside derivation or play parameters" << std::endl;
Chris@0 986 return false;
Chris@0 987 }
Chris@0 988
Chris@0 989 QString configurationXml = "<plugin";
Chris@0 990
Chris@0 991 for (int i = 0; i < attributes.length(); ++i) {
Chris@0 992 configurationXml += QString(" %1=\"%2\"")
Chris@0 993 .arg(attributes.qName(i)).arg(attributes.value(i));
Chris@0 994 }
Chris@0 995
Chris@0 996 configurationXml += "/>";
Chris@0 997
Chris@0 998 if (m_currentPlayParameters) {
Chris@0 999 m_currentPlayParameters->setPlayPluginConfiguration(configurationXml);
Chris@0 1000 } else {
Chris@0 1001 m_currentTransformConfiguration += configurationXml;
Chris@0 1002 }
Chris@0 1003
Chris@0 1004 return true;
Chris@0 1005 }
Chris@0 1006
Chris@0 1007 bool
Chris@0 1008 SVFileReader::readSelection(const QXmlAttributes &attributes)
Chris@0 1009 {
Chris@0 1010 bool ok;
Chris@0 1011
Chris@0 1012 READ_MANDATORY(int, start, toInt);
Chris@0 1013 READ_MANDATORY(int, end, toInt);
Chris@0 1014
Chris@0 1015 m_paneCallback.addSelection(start, end);
Chris@0 1016
Chris@0 1017 return true;
Chris@0 1018 }
Chris@0 1019