annotate data/fileio/SVFileReader.cpp @ 263:71dfc6ab3b54

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