annotate framework/SVFileReader.cpp @ 403:eb84b06301da

Restore the old prev/next layer commands (that were never enabled because they didn't work) using the new fixed order layer list (so they now do work)
author Chris Cannam
date Tue, 02 Sep 2014 16:06:41 +0100
parents 6a84102c006a
children 7657075ecfca
rev   line source
Chris@45 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@45 2
Chris@45 3 /*
Chris@45 4 Sonic Visualiser
Chris@45 5 An audio file viewer and annotation editor.
Chris@45 6 Centre for Digital Music, Queen Mary, University of London.
Chris@45 7 This file copyright 2006 Chris Cannam and QMUL.
Chris@45 8
Chris@45 9 This program is free software; you can redistribute it and/or
Chris@45 10 modify it under the terms of the GNU General Public License as
Chris@45 11 published by the Free Software Foundation; either version 2 of the
Chris@45 12 License, or (at your option) any later version. See the file
Chris@45 13 COPYING included with this distribution for more information.
Chris@45 14 */
Chris@45 15
Chris@45 16 #include "SVFileReader.h"
Chris@45 17
Chris@45 18 #include "layer/Layer.h"
Chris@45 19 #include "view/View.h"
Chris@45 20 #include "base/PlayParameters.h"
Chris@45 21 #include "base/PlayParameterRepository.h"
Chris@116 22 #include "base/Preferences.h"
Chris@45 23
Chris@45 24 #include "data/fileio/AudioFileReaderFactory.h"
Chris@45 25 #include "data/fileio/FileSource.h"
Chris@45 26
Chris@170 27 #include "data/fileio/FileFinder.h"
Chris@109 28
Chris@45 29 #include "data/model/WaveFileModel.h"
Chris@45 30 #include "data/model/EditableDenseThreeDimensionalModel.h"
Chris@45 31 #include "data/model/SparseOneDimensionalModel.h"
Chris@45 32 #include "data/model/SparseTimeValueModel.h"
Chris@45 33 #include "data/model/NoteModel.h"
Chris@343 34 #include "data/model/FlexiNoteModel.h"
Chris@137 35 #include "data/model/RegionModel.h"
Chris@45 36 #include "data/model/TextModel.h"
Chris@45 37 #include "data/model/ImageModel.h"
Chris@111 38 #include "data/model/AlignmentModel.h"
Chris@45 39
Chris@106 40 #include "transform/TransformFactory.h"
Chris@72 41
Chris@45 42 #include "view/Pane.h"
Chris@45 43
Chris@109 44 #include "widgets/ProgressDialog.h"
Chris@109 45
Chris@45 46 #include "Document.h"
Chris@45 47
Chris@45 48 #include <QString>
Chris@45 49 #include <QMessageBox>
Chris@45 50 #include <QFileDialog>
Chris@45 51
Chris@45 52 #include <iostream>
Chris@45 53
Chris@45 54 SVFileReader::SVFileReader(Document *document,
Chris@45 55 SVFileReaderPaneCallback &callback,
Chris@45 56 QString location) :
Chris@45 57 m_document(document),
Chris@45 58 m_paneCallback(callback),
Chris@45 59 m_location(location),
Chris@45 60 m_currentPane(0),
Chris@45 61 m_currentDataset(0),
Chris@45 62 m_currentDerivedModel(0),
Chris@45 63 m_currentDerivedModelId(-1),
Chris@45 64 m_currentPlayParameters(0),
Chris@72 65 m_currentTransformSource(0),
Chris@45 66 m_datasetSeparator(" "),
Chris@45 67 m_inRow(false),
Chris@45 68 m_inLayer(false),
Chris@45 69 m_inView(false),
Chris@45 70 m_rowNumber(0),
Chris@45 71 m_ok(false)
Chris@45 72 {
Chris@45 73 }
Chris@45 74
Chris@45 75 void
Chris@45 76 SVFileReader::parse(const QString &xmlData)
Chris@45 77 {
Chris@45 78 QXmlInputSource inputSource;
Chris@45 79 inputSource.setData(xmlData);
Chris@45 80 parse(inputSource);
Chris@45 81 }
Chris@45 82
Chris@45 83 void
Chris@45 84 SVFileReader::parse(QXmlInputSource &inputSource)
Chris@45 85 {
Chris@45 86 QXmlSimpleReader reader;
Chris@45 87 reader.setContentHandler(this);
Chris@45 88 reader.setErrorHandler(this);
Chris@45 89 m_ok = reader.parse(inputSource);
Chris@45 90 }
Chris@45 91
Chris@45 92 bool
Chris@45 93 SVFileReader::isOK()
Chris@45 94 {
Chris@45 95 return m_ok;
Chris@45 96 }
Chris@45 97
Chris@45 98 SVFileReader::~SVFileReader()
Chris@45 99 {
Chris@45 100 if (!m_awaitingDatasets.empty()) {
Chris@293 101 cerr << "WARNING: SV-XML: File ended with "
Chris@45 102 << m_awaitingDatasets.size() << " unfilled model dataset(s)"
Chris@293 103 << endl;
Chris@45 104 }
Chris@45 105
Chris@45 106 std::set<Model *> unaddedModels;
Chris@45 107
Chris@45 108 for (std::map<int, Model *>::iterator i = m_models.begin();
Chris@45 109 i != m_models.end(); ++i) {
Chris@45 110 if (m_addedModels.find(i->second) == m_addedModels.end()) {
Chris@45 111 unaddedModels.insert(i->second);
Chris@45 112 }
Chris@45 113 }
Chris@45 114
Chris@45 115 if (!unaddedModels.empty()) {
Chris@293 116 cerr << "WARNING: SV-XML: File contained "
Chris@45 117 << unaddedModels.size() << " unused models"
Chris@293 118 << endl;
Chris@45 119 while (!unaddedModels.empty()) {
Chris@45 120 delete *unaddedModels.begin();
Chris@45 121 unaddedModels.erase(unaddedModels.begin());
Chris@45 122 }
Chris@45 123 }
Chris@45 124 }
Chris@45 125
Chris@45 126 bool
Chris@45 127 SVFileReader::startElement(const QString &, const QString &,
Chris@45 128 const QString &qName,
Chris@45 129 const QXmlAttributes &attributes)
Chris@45 130 {
Chris@45 131 QString name = qName.toLower();
Chris@45 132
Chris@45 133 bool ok = false;
Chris@45 134
Chris@45 135 // Valid element names:
Chris@45 136 //
Chris@45 137 // sv
Chris@45 138 // data
Chris@45 139 // dataset
Chris@45 140 // display
Chris@45 141 // derivation
Chris@45 142 // playparameters
Chris@45 143 // layer
Chris@45 144 // model
Chris@45 145 // point
Chris@45 146 // row
Chris@45 147 // view
Chris@45 148 // window
Chris@72 149 // plugin
Chris@72 150 // transform
Chris@72 151 // selections
Chris@72 152 // selection
Chris@72 153 // measurement
Chris@45 154
Chris@45 155 if (name == "sv") {
Chris@45 156
Chris@45 157 // nothing needed
Chris@45 158 ok = true;
Chris@45 159
Chris@45 160 } else if (name == "data") {
Chris@45 161
Chris@45 162 // nothing needed
Chris@45 163 m_inData = true;
Chris@45 164 ok = true;
Chris@45 165
Chris@45 166 } else if (name == "display") {
Chris@45 167
Chris@45 168 // nothing needed
Chris@45 169 ok = true;
Chris@45 170
Chris@45 171 } else if (name == "window") {
Chris@45 172
Chris@45 173 ok = readWindow(attributes);
Chris@45 174
Chris@45 175 } else if (name == "model") {
Chris@45 176
Chris@45 177 ok = readModel(attributes);
Chris@45 178
Chris@45 179 } else if (name == "dataset") {
Chris@45 180
Chris@45 181 ok = readDatasetStart(attributes);
Chris@45 182
Chris@45 183 } else if (name == "bin") {
Chris@45 184
Chris@45 185 ok = addBinToDataset(attributes);
Chris@45 186
Chris@45 187 } else if (name == "point") {
Chris@45 188
Chris@45 189 ok = addPointToDataset(attributes);
Chris@45 190
Chris@45 191 } else if (name == "row") {
Chris@45 192
Chris@45 193 ok = addRowToDataset(attributes);
Chris@45 194
Chris@45 195 } else if (name == "layer") {
Chris@45 196
Chris@45 197 addUnaddedModels(); // all models must be specified before first layer
Chris@45 198 ok = readLayer(attributes);
Chris@45 199
Chris@45 200 } else if (name == "view") {
Chris@45 201
Chris@45 202 m_inView = true;
Chris@45 203 ok = readView(attributes);
Chris@45 204
Chris@45 205 } else if (name == "derivation") {
Chris@45 206
Chris@45 207 ok = readDerivation(attributes);
Chris@45 208
Chris@45 209 } else if (name == "playparameters") {
Chris@45 210
Chris@45 211 ok = readPlayParameters(attributes);
Chris@45 212
Chris@45 213 } else if (name == "plugin") {
Chris@45 214
Chris@45 215 ok = readPlugin(attributes);
Chris@45 216
Chris@45 217 } else if (name == "selections") {
Chris@45 218
Chris@45 219 m_inSelections = true;
Chris@45 220 ok = true;
Chris@45 221
Chris@45 222 } else if (name == "selection") {
Chris@45 223
Chris@45 224 ok = readSelection(attributes);
Chris@45 225
Chris@45 226 } else if (name == "measurement") {
Chris@45 227
Chris@45 228 ok = readMeasurement(attributes);
Chris@45 229
Chris@72 230 } else if (name == "transform") {
Chris@72 231
Chris@72 232 ok = readTransform(attributes);
Chris@72 233
Chris@72 234 } else if (name == "parameter") {
Chris@72 235
Chris@72 236 ok = readParameter(attributes);
Chris@72 237
Chris@45 238 } else {
Chris@293 239 cerr << "WARNING: SV-XML: Unexpected element \""
Chris@294 240 << name << "\"" << endl;
Chris@45 241 }
Chris@45 242
Chris@45 243 if (!ok) {
Chris@293 244 cerr << "WARNING: SV-XML: Failed to completely process element \""
Chris@294 245 << name << "\"" << endl;
Chris@45 246 }
Chris@45 247
Chris@45 248 return true;
Chris@45 249 }
Chris@45 250
Chris@45 251 bool
Chris@45 252 SVFileReader::characters(const QString &text)
Chris@45 253 {
Chris@45 254 bool ok = false;
Chris@45 255
Chris@45 256 if (m_inRow) {
Chris@45 257 ok = readRowData(text);
Chris@45 258 if (!ok) {
Chris@293 259 cerr << "WARNING: SV-XML: Failed to read row data content for row " << m_rowNumber << endl;
Chris@45 260 }
Chris@45 261 }
Chris@45 262
Chris@45 263 return true;
Chris@45 264 }
Chris@45 265
Chris@45 266 bool
Chris@45 267 SVFileReader::endElement(const QString &, const QString &,
Chris@45 268 const QString &qName)
Chris@45 269 {
Chris@45 270 QString name = qName.toLower();
Chris@45 271
Chris@45 272 if (name == "dataset") {
Chris@45 273
Chris@45 274 if (m_currentDataset) {
Chris@45 275
Chris@45 276 bool foundInAwaiting = false;
Chris@45 277
Chris@45 278 for (std::map<int, int>::iterator i = m_awaitingDatasets.begin();
Chris@45 279 i != m_awaitingDatasets.end(); ++i) {
Chris@45 280 if (haveModel(i->second) &&
Chris@45 281 m_models[i->second] == m_currentDataset) {
Chris@45 282 m_awaitingDatasets.erase(i);
Chris@45 283 foundInAwaiting = true;
Chris@45 284 break;
Chris@45 285 }
Chris@45 286 }
Chris@45 287
Chris@45 288 if (!foundInAwaiting) {
Chris@293 289 cerr << "WARNING: SV-XML: Dataset precedes model, or no model uses dataset" << endl;
Chris@45 290 }
Chris@45 291 }
Chris@45 292
Chris@45 293 m_currentDataset = 0;
Chris@45 294
Chris@45 295 } else if (name == "data") {
Chris@45 296
Chris@45 297 addUnaddedModels();
Chris@45 298 m_inData = false;
Chris@45 299
Chris@45 300 } else if (name == "derivation") {
Chris@45 301
Chris@45 302 if (!m_currentDerivedModel) {
Chris@358 303 if (m_currentDerivedModelId < 0) {
Chris@293 304 cerr << "WARNING: SV-XML: Bad derivation output model id "
Chris@293 305 << m_currentDerivedModelId << endl;
Chris@45 306 } else if (haveModel(m_currentDerivedModelId)) {
Chris@293 307 cerr << "WARNING: SV-XML: Derivation has existing model "
Chris@45 308 << m_currentDerivedModelId
Chris@293 309 << " as target, not regenerating" << endl;
Chris@45 310 } else {
Chris@78 311 QString message;
Chris@45 312 m_currentDerivedModel = m_models[m_currentDerivedModelId] =
Chris@72 313 m_document->addDerivedModel
Chris@72 314 (m_currentTransform,
Chris@72 315 ModelTransformer::Input(m_currentTransformSource,
Chris@78 316 m_currentTransformChannel),
Chris@78 317 message);
Chris@79 318 if (!m_currentDerivedModel) {
Chris@79 319 emit modelRegenerationFailed(tr("(derived model in SV-XML)"),
Chris@79 320 m_currentTransform.getIdentifier(),
Chris@79 321 message);
Chris@79 322 } else if (message != "") {
Chris@79 323 emit modelRegenerationWarning(tr("(derived model in SV-XML)"),
Chris@79 324 m_currentTransform.getIdentifier(),
Chris@79 325 message);
Chris@79 326 }
Chris@45 327 }
Chris@45 328 } else {
Chris@329 329 m_document->addAlreadyDerivedModel
Chris@72 330 (m_currentTransform,
Chris@72 331 ModelTransformer::Input(m_currentTransformSource,
Chris@72 332 m_currentTransformChannel),
Chris@72 333 m_currentDerivedModel);
Chris@45 334 }
Chris@45 335
Chris@45 336 m_addedModels.insert(m_currentDerivedModel);
Chris@45 337 m_currentDerivedModel = 0;
Chris@45 338 m_currentDerivedModelId = -1;
Chris@72 339 m_currentTransformSource = 0;
Chris@72 340 m_currentTransform = Transform();
Chris@72 341 m_currentTransformChannel = -1;
Chris@45 342
Chris@45 343 } else if (name == "row") {
Chris@45 344 m_inRow = false;
Chris@45 345 } else if (name == "layer") {
Chris@45 346 m_inLayer = false;
Chris@45 347 } else if (name == "view") {
Chris@45 348 m_inView = false;
Chris@45 349 } else if (name == "selections") {
Chris@45 350 m_inSelections = false;
Chris@45 351 } else if (name == "playparameters") {
Chris@45 352 m_currentPlayParameters = 0;
Chris@45 353 }
Chris@45 354
Chris@45 355 return true;
Chris@45 356 }
Chris@45 357
Chris@45 358 bool
Chris@45 359 SVFileReader::error(const QXmlParseException &exception)
Chris@45 360 {
Chris@45 361 m_errorString =
Chris@45 362 QString("ERROR: SV-XML: %1 at line %2, column %3")
Chris@45 363 .arg(exception.message())
Chris@45 364 .arg(exception.lineNumber())
Chris@45 365 .arg(exception.columnNumber());
Chris@294 366 cerr << m_errorString << endl;
Chris@45 367 return QXmlDefaultHandler::error(exception);
Chris@45 368 }
Chris@45 369
Chris@45 370 bool
Chris@45 371 SVFileReader::fatalError(const QXmlParseException &exception)
Chris@45 372 {
Chris@45 373 m_errorString =
Chris@45 374 QString("FATAL ERROR: SV-XML: %1 at line %2, column %3")
Chris@45 375 .arg(exception.message())
Chris@45 376 .arg(exception.lineNumber())
Chris@45 377 .arg(exception.columnNumber());
Chris@294 378 cerr << m_errorString << endl;
Chris@45 379 return QXmlDefaultHandler::fatalError(exception);
Chris@45 380 }
Chris@45 381
Chris@45 382
Chris@45 383 #define READ_MANDATORY(TYPE, NAME, CONVERSION) \
Chris@45 384 TYPE NAME = attributes.value(#NAME).trimmed().CONVERSION(&ok); \
Chris@45 385 if (!ok) { \
Chris@293 386 cerr << "WARNING: SV-XML: Missing or invalid mandatory " #TYPE " attribute \"" #NAME "\"" << endl; \
Chris@45 387 return false; \
Chris@45 388 }
Chris@45 389
Chris@45 390 bool
Chris@45 391 SVFileReader::readWindow(const QXmlAttributes &attributes)
Chris@45 392 {
Chris@45 393 bool ok = false;
Chris@45 394
Chris@45 395 READ_MANDATORY(int, width, toInt);
Chris@45 396 READ_MANDATORY(int, height, toInt);
Chris@45 397
Chris@45 398 m_paneCallback.setWindowSize(width, height);
Chris@45 399 return true;
Chris@45 400 }
Chris@45 401
Chris@45 402 void
Chris@45 403 SVFileReader::addUnaddedModels()
Chris@45 404 {
Chris@45 405 std::set<Model *> unaddedModels;
Chris@45 406
Chris@45 407 for (std::map<int, Model *>::iterator i = m_models.begin();
Chris@45 408 i != m_models.end(); ++i) {
Chris@45 409 if (m_addedModels.find(i->second) == m_addedModels.end()) {
Chris@45 410 unaddedModels.insert(i->second);
Chris@45 411 }
Chris@45 412 }
Chris@45 413
Chris@45 414 for (std::set<Model *>::iterator i = unaddedModels.begin();
Chris@45 415 i != unaddedModels.end(); ++i) {
Chris@212 416 Model *model = *i;
Chris@212 417 // don't want to add these models, because their lifespans
Chris@212 418 // are entirely dictated by the models that "own" them even
Chris@212 419 // though they were read independently from the .sv file.
Chris@212 420 // (pity we don't have a nicer way)
Chris@212 421 if (!dynamic_cast<PathModel *>(model) &&
Chris@212 422 !dynamic_cast<AlignmentModel *>(model)) {
Chris@212 423 m_document->addImportedModel(model);
Chris@212 424 }
Chris@212 425 // but we add all models here, so they don't get deleted
Chris@212 426 // when the file loader is destroyed
Chris@212 427 m_addedModels.insert(model);
Chris@45 428 }
Chris@45 429 }
Chris@45 430
Chris@45 431 bool
Chris@45 432 SVFileReader::readModel(const QXmlAttributes &attributes)
Chris@45 433 {
Chris@45 434 bool ok = false;
Chris@45 435
Chris@45 436 READ_MANDATORY(int, id, toInt);
Chris@45 437
Chris@45 438 if (haveModel(id)) {
Chris@293 439 cerr << "WARNING: SV-XML: Ignoring duplicate model id " << id
Chris@293 440 << endl;
Chris@45 441 return false;
Chris@45 442 }
Chris@45 443
Chris@45 444 QString name = attributes.value("name");
Chris@45 445
Chris@233 446 SVDEBUG << "SVFileReader::readModel: model name \"" << name << "\"" << endl;
Chris@45 447
Chris@45 448 READ_MANDATORY(int, sampleRate, toInt);
Chris@45 449
Chris@45 450 QString type = attributes.value("type").trimmed();
Chris@362 451 bool isMainModel = (attributes.value("mainModel").trimmed() == "true");
Chris@45 452
Chris@45 453 if (type == "wavefile") {
Chris@45 454
Chris@45 455 WaveFileModel *model = 0;
Chris@45 456 FileFinder *ff = FileFinder::getInstance();
Chris@45 457 QString originalPath = attributes.value("file");
Chris@45 458 QString path = ff->find(FileFinder::AudioFile,
Chris@45 459 originalPath, m_location);
Chris@45 460
Chris@248 461 SVDEBUG << "Wave file originalPath = " << originalPath << ", path = "
Chris@248 462 << path << endl;
Chris@248 463
Chris@109 464 ProgressDialog dialog(tr("Opening file or URL..."), true, 2000);
Chris@109 465 FileSource file(path, &dialog);
Chris@45 466 file.waitForStatus();
Chris@45 467
Chris@45 468 if (!file.isOK()) {
Chris@293 469 cerr << "SVFileReader::readModel: Failed to retrieve file \"" << path << "\" for wave file model: " << file.getErrorString() << endl;
Chris@45 470 } else if (!file.isAvailable()) {
Chris@293 471 cerr << "SVFileReader::readModel: Failed to retrieve file \"" << path << "\" for wave file model: Source unavailable" << endl;
Chris@45 472 } else {
Chris@45 473
Chris@45 474 file.waitForData();
Chris@116 475
Chris@368 476 int rate = sampleRate;
Chris@116 477
Chris@360 478 if (Preferences::getInstance()->getFixedSampleRate() != 0) {
Chris@360 479 rate = Preferences::getInstance()->getFixedSampleRate();
Chris@362 480 } else if (rate == 0 &&
Chris@362 481 !isMainModel &&
Chris@360 482 Preferences::getInstance()->getResampleOnLoad()) {
Chris@116 483 WaveFileModel *mm = m_document->getMainModel();
Chris@116 484 if (mm) rate = mm->getSampleRate();
Chris@116 485 }
Chris@116 486
Chris@116 487 model = new WaveFileModel(file, rate);
Chris@45 488 if (!model->isOK()) {
Chris@45 489 delete model;
Chris@45 490 model = 0;
Chris@45 491 }
Chris@45 492 }
Chris@45 493
Chris@45 494 if (!model) return false;
Chris@45 495
Chris@45 496 model->setObjectName(name);
Chris@45 497 m_models[id] = model;
Chris@362 498 if (isMainModel) {
Chris@45 499 m_document->setMainModel(model);
Chris@45 500 m_addedModels.insert(model);
Chris@45 501 }
Chris@45 502 // Derived models will be added when their derivation
Chris@45 503 // is found.
Chris@45 504
Chris@45 505 return true;
Chris@45 506
Chris@45 507 } else if (type == "dense") {
Chris@45 508
Chris@45 509 READ_MANDATORY(int, dimensions, toInt);
Chris@45 510
Chris@45 511 // Currently the only dense model we support here is the dense
Chris@45 512 // 3d model. Dense time-value models are always file-backed
Chris@45 513 // waveform data, at this point, and they come in as wavefile
Chris@45 514 // models.
Chris@45 515
Chris@45 516 if (dimensions == 3) {
Chris@45 517
Chris@45 518 READ_MANDATORY(int, windowSize, toInt);
Chris@45 519 READ_MANDATORY(int, yBinCount, toInt);
Chris@45 520
Chris@45 521 EditableDenseThreeDimensionalModel *model =
Chris@45 522 new EditableDenseThreeDimensionalModel
Chris@153 523 (sampleRate, windowSize, yBinCount,
Chris@153 524 EditableDenseThreeDimensionalModel::NoCompression);
Chris@45 525
Chris@45 526 float minimum = attributes.value("minimum").trimmed().toFloat(&ok);
Chris@45 527 if (ok) model->setMinimumLevel(minimum);
Chris@45 528
Chris@45 529 float maximum = attributes.value("maximum").trimmed().toFloat(&ok);
Chris@45 530 if (ok) model->setMaximumLevel(maximum);
Chris@45 531
Chris@45 532 int dataset = attributes.value("dataset").trimmed().toInt(&ok);
Chris@45 533 if (ok) m_awaitingDatasets[dataset] = id;
Chris@45 534
Chris@181 535 int startFrame = attributes.value("startFrame").trimmed().toInt(&ok);
Chris@181 536 if (ok) model->setStartFrame(startFrame);
Chris@181 537
Chris@45 538 model->setObjectName(name);
Chris@45 539 m_models[id] = model;
Chris@45 540 return true;
Chris@45 541
Chris@45 542 } else {
Chris@45 543
Chris@293 544 cerr << "WARNING: SV-XML: Unexpected dense model dimension ("
Chris@293 545 << dimensions << ")" << endl;
Chris@45 546 }
Chris@45 547 } else if (type == "sparse") {
Chris@45 548
Chris@45 549 READ_MANDATORY(int, dimensions, toInt);
Chris@45 550
Chris@45 551 if (dimensions == 1) {
Chris@45 552
Chris@45 553 READ_MANDATORY(int, resolution, toInt);
Chris@45 554
Chris@45 555 if (attributes.value("subtype") == "image") {
Chris@45 556
Chris@45 557 bool notifyOnAdd = (attributes.value("notifyOnAdd") == "true");
Chris@45 558 ImageModel *model = new ImageModel(sampleRate, resolution,
Chris@45 559 notifyOnAdd);
Chris@45 560 model->setObjectName(name);
Chris@45 561 m_models[id] = model;
Chris@45 562
Chris@45 563 } else {
Chris@45 564
Chris@45 565 SparseOneDimensionalModel *model = new SparseOneDimensionalModel
Chris@45 566 (sampleRate, resolution);
Chris@45 567 model->setObjectName(name);
Chris@45 568 m_models[id] = model;
Chris@45 569 }
Chris@45 570
Chris@45 571 int dataset = attributes.value("dataset").trimmed().toInt(&ok);
Chris@45 572 if (ok) m_awaitingDatasets[dataset] = id;
Chris@45 573
Chris@45 574 return true;
Chris@45 575
Chris@45 576 } else if (dimensions == 2 || dimensions == 3) {
Chris@45 577
Chris@45 578 READ_MANDATORY(int, resolution, toInt);
Chris@45 579
Chris@45 580 bool haveMinMax = true;
Chris@45 581 float minimum = attributes.value("minimum").trimmed().toFloat(&ok);
Chris@45 582 if (!ok) haveMinMax = false;
Chris@45 583 float maximum = attributes.value("maximum").trimmed().toFloat(&ok);
Chris@45 584 if (!ok) haveMinMax = false;
Chris@45 585
Chris@45 586 float valueQuantization =
Chris@45 587 attributes.value("valueQuantization").trimmed().toFloat(&ok);
Chris@45 588
Chris@45 589 bool notifyOnAdd = (attributes.value("notifyOnAdd") == "true");
Chris@45 590
Chris@45 591 QString units = attributes.value("units");
Chris@45 592
Chris@45 593 if (dimensions == 2) {
Chris@45 594 if (attributes.value("subtype") == "text") {
Chris@45 595 TextModel *model = new TextModel
Chris@45 596 (sampleRate, resolution, notifyOnAdd);
Chris@45 597 model->setObjectName(name);
Chris@45 598 m_models[id] = model;
Chris@111 599 } else if (attributes.value("subtype") == "path") {
Chris@111 600 PathModel *model = new PathModel
Chris@111 601 (sampleRate, resolution, notifyOnAdd);
Chris@111 602 model->setObjectName(name);
Chris@111 603 m_models[id] = model;
Chris@45 604 } else {
Chris@45 605 SparseTimeValueModel *model;
Chris@45 606 if (haveMinMax) {
Chris@45 607 model = new SparseTimeValueModel
Chris@45 608 (sampleRate, resolution, minimum, maximum, notifyOnAdd);
Chris@45 609 } else {
Chris@45 610 model = new SparseTimeValueModel
Chris@45 611 (sampleRate, resolution, notifyOnAdd);
Chris@45 612 }
Chris@45 613 model->setScaleUnits(units);
Chris@45 614 model->setObjectName(name);
Chris@45 615 m_models[id] = model;
Chris@45 616 }
Chris@45 617 } else {
Chris@137 618 if (attributes.value("subtype") == "region") {
Chris@137 619 RegionModel *model;
Chris@137 620 if (haveMinMax) {
Chris@137 621 model = new RegionModel
Chris@137 622 (sampleRate, resolution, minimum, maximum, notifyOnAdd);
Chris@137 623 } else {
Chris@137 624 model = new RegionModel
Chris@137 625 (sampleRate, resolution, notifyOnAdd);
Chris@137 626 }
Chris@137 627 model->setValueQuantization(valueQuantization);
Chris@137 628 model->setScaleUnits(units);
Chris@137 629 model->setObjectName(name);
Chris@137 630 m_models[id] = model;
Chris@343 631 } else if (attributes.value("subtype") == "flexinote") {
Chris@343 632 FlexiNoteModel *model;
Chris@343 633 if (haveMinMax) {
Chris@343 634 model = new FlexiNoteModel
Chris@343 635 (sampleRate, resolution, minimum, maximum, notifyOnAdd);
Chris@343 636 } else {
Chris@343 637 model = new FlexiNoteModel
Chris@343 638 (sampleRate, resolution, notifyOnAdd);
Chris@343 639 }
Chris@343 640 model->setValueQuantization(valueQuantization);
Chris@343 641 model->setScaleUnits(units);
Chris@343 642 model->setObjectName(name);
Chris@343 643 m_models[id] = model;
Chris@45 644 } else {
Chris@137 645 // note models written out by SV 1.3 and earlier
Chris@137 646 // have no subtype, so we can't test that
Chris@137 647 NoteModel *model;
Chris@137 648 if (haveMinMax) {
Chris@137 649 model = new NoteModel
Chris@137 650 (sampleRate, resolution, minimum, maximum, notifyOnAdd);
Chris@137 651 } else {
Chris@137 652 model = new NoteModel
Chris@137 653 (sampleRate, resolution, notifyOnAdd);
Chris@137 654 }
Chris@137 655 model->setValueQuantization(valueQuantization);
Chris@137 656 model->setScaleUnits(units);
Chris@137 657 model->setObjectName(name);
Chris@137 658 m_models[id] = model;
Chris@45 659 }
Chris@137 660 }
Chris@45 661
Chris@45 662 int dataset = attributes.value("dataset").trimmed().toInt(&ok);
Chris@45 663 if (ok) m_awaitingDatasets[dataset] = id;
Chris@45 664
Chris@45 665 return true;
Chris@45 666
Chris@45 667 } else {
Chris@45 668
Chris@293 669 cerr << "WARNING: SV-XML: Unexpected sparse model dimension ("
Chris@293 670 << dimensions << ")" << endl;
Chris@45 671 }
Chris@111 672
Chris@111 673 } else if (type == "alignment") {
Chris@111 674
Chris@111 675 READ_MANDATORY(int, reference, toInt);
Chris@111 676 READ_MANDATORY(int, aligned, toInt);
Chris@111 677 READ_MANDATORY(int, path, toInt);
Chris@111 678
Chris@111 679 Model *refModel = 0, *alignedModel = 0, *pathModel = 0;
Chris@111 680
Chris@111 681 if (m_models.find(reference) != m_models.end()) {
Chris@111 682 refModel = m_models[reference];
Chris@111 683 } else {
Chris@293 684 cerr << "WARNING: SV-XML: Unknown reference model id "
Chris@111 685 << reference << " in alignment model id " << id
Chris@293 686 << endl;
Chris@111 687 }
Chris@111 688
Chris@111 689 if (m_models.find(aligned) != m_models.end()) {
Chris@111 690 alignedModel = m_models[aligned];
Chris@111 691 } else {
Chris@293 692 cerr << "WARNING: SV-XML: Unknown aligned model id "
Chris@111 693 << aligned << " in alignment model id " << id
Chris@293 694 << endl;
Chris@111 695 }
Chris@111 696
Chris@111 697 if (m_models.find(path) != m_models.end()) {
Chris@111 698 pathModel = m_models[path];
Chris@111 699 } else {
Chris@293 700 cerr << "WARNING: SV-XML: Unknown path model id "
Chris@111 701 << path << " in alignment model id " << id
Chris@293 702 << endl;
Chris@111 703 }
Chris@111 704
Chris@111 705 if (refModel && alignedModel && pathModel) {
Chris@111 706 AlignmentModel *model = new AlignmentModel
Chris@111 707 (refModel, alignedModel, 0, 0);
Chris@111 708 PathModel *pm = dynamic_cast<PathModel *>(pathModel);
Chris@111 709 if (!pm) {
Chris@293 710 cerr << "WARNING: SV-XML: Model id " << path
Chris@111 711 << " referenced as path for alignment " << id
Chris@293 712 << " is not a path model" << endl;
Chris@111 713 } else {
Chris@111 714 model->setPath(pm);
Chris@111 715 pm->setCompletion(100);
Chris@111 716 }
Chris@111 717 model->setObjectName(name);
Chris@111 718 m_models[id] = model;
Chris@111 719 alignedModel->setAlignment(model);
Chris@111 720 return true;
Chris@111 721 }
Chris@111 722
Chris@45 723 } else {
Chris@45 724
Chris@293 725 cerr << "WARNING: SV-XML: Unexpected model type \""
Chris@294 726 << type << "\" for model id " << id << endl;
Chris@45 727 }
Chris@45 728
Chris@45 729 return false;
Chris@45 730 }
Chris@45 731
Chris@45 732 bool
Chris@45 733 SVFileReader::readView(const QXmlAttributes &attributes)
Chris@45 734 {
Chris@45 735 QString type = attributes.value("type");
Chris@45 736 m_currentPane = 0;
Chris@45 737
Chris@45 738 if (type != "pane") {
Chris@293 739 cerr << "WARNING: SV-XML: Unexpected view type \""
Chris@294 740 << type << "\"" << endl;
Chris@45 741 return false;
Chris@45 742 }
Chris@45 743
Chris@45 744 m_currentPane = m_paneCallback.addPane();
Chris@45 745
Chris@342 746 cerr << "SVFileReader::addPane: pane is " << m_currentPane << endl;
Chris@342 747
Chris@45 748 if (!m_currentPane) {
Chris@293 749 cerr << "WARNING: SV-XML: Internal error: Failed to add pane!"
Chris@293 750 << endl;
Chris@45 751 return false;
Chris@45 752 }
Chris@45 753
Chris@45 754 bool ok = false;
Chris@45 755
Chris@45 756 View *view = m_currentPane;
Chris@45 757
Chris@45 758 // The view properties first
Chris@45 759
Chris@366 760 READ_MANDATORY(int, centre, toInt);
Chris@366 761 READ_MANDATORY(int, zoom, toInt);
Chris@45 762 READ_MANDATORY(int, followPan, toInt);
Chris@45 763 READ_MANDATORY(int, followZoom, toInt);
Chris@45 764 QString tracking = attributes.value("tracking");
Chris@45 765
Chris@45 766 // Specify the follow modes before we set the actual values
Chris@45 767 view->setFollowGlobalPan(followPan);
Chris@45 768 view->setFollowGlobalZoom(followZoom);
Chris@45 769 view->setPlaybackFollow(tracking == "scroll" ? PlaybackScrollContinuous :
Chris@379 770 tracking == "page" ? PlaybackScrollPageWithCentre :
Chris@379 771 tracking == "daw" ? PlaybackScrollPage
Chris@45 772 : PlaybackIgnore);
Chris@45 773
Chris@45 774 // Then set these values
Chris@45 775 view->setCentreFrame(centre);
Chris@45 776 view->setZoomLevel(zoom);
Chris@45 777
Chris@45 778 // And pane properties
Chris@45 779 READ_MANDATORY(int, centreLineVisible, toInt);
Chris@45 780 m_currentPane->setCentreLineVisible(centreLineVisible);
Chris@45 781
Chris@45 782 int height = attributes.value("height").toInt(&ok);
Chris@45 783 if (ok) {
Chris@45 784 m_currentPane->resize(m_currentPane->width(), height);
Chris@45 785 }
Chris@45 786
Chris@45 787 return true;
Chris@45 788 }
Chris@45 789
Chris@45 790 bool
Chris@45 791 SVFileReader::readLayer(const QXmlAttributes &attributes)
Chris@45 792 {
Chris@45 793 QString type = attributes.value("type");
Chris@45 794
Chris@45 795 int id;
Chris@45 796 bool ok = false;
Chris@45 797 id = attributes.value("id").trimmed().toInt(&ok);
Chris@45 798
Chris@45 799 if (!ok) {
Chris@293 800 cerr << "WARNING: SV-XML: No layer id for layer of type \""
Chris@294 801 << type
Chris@293 802 << "\"" << endl;
Chris@45 803 return false;
Chris@45 804 }
Chris@45 805
Chris@45 806 Layer *layer = 0;
Chris@45 807 bool isNewLayer = false;
Chris@45 808
Chris@45 809 // Layers are expected to be defined in layer elements in the data
Chris@45 810 // section, and referred to in layer elements in the view
Chris@45 811 // sections. So if we're in the data section, we expect this
Chris@45 812 // layer not to exist already; if we're in the view section, we
Chris@45 813 // expect it to exist.
Chris@45 814
Chris@45 815 if (m_inData) {
Chris@45 816
Chris@45 817 if (m_layers.find(id) != m_layers.end()) {
Chris@293 818 cerr << "WARNING: SV-XML: Ignoring duplicate layer id " << id
Chris@293 819 << " in data section" << endl;
Chris@45 820 return false;
Chris@45 821 }
Chris@45 822
Chris@45 823 layer = m_layers[id] = m_document->createLayer
Chris@45 824 (LayerFactory::getInstance()->getLayerTypeForName(type));
Chris@45 825
Chris@45 826 if (layer) {
Chris@45 827 m_layers[id] = layer;
Chris@45 828 isNewLayer = true;
Chris@45 829 }
Chris@45 830
Chris@45 831 } else {
Chris@45 832
Chris@45 833 if (!m_currentPane) {
Chris@293 834 cerr << "WARNING: SV-XML: No current pane for layer " << id
Chris@293 835 << " in view section" << endl;
Chris@45 836 return false;
Chris@45 837 }
Chris@45 838
Chris@45 839 if (m_layers.find(id) != m_layers.end()) {
Chris@45 840
Chris@45 841 layer = m_layers[id];
Chris@45 842
Chris@45 843 } else {
Chris@293 844 cerr << "WARNING: SV-XML: Layer id " << id
Chris@45 845 << " in view section has not been defined -- defining it here"
Chris@293 846 << endl;
Chris@45 847
Chris@45 848 layer = m_document->createLayer
Chris@45 849 (LayerFactory::getInstance()->getLayerTypeForName(type));
Chris@45 850
Chris@45 851 if (layer) {
Chris@45 852 m_layers[id] = layer;
Chris@45 853 isNewLayer = true;
Chris@45 854 }
Chris@45 855 }
Chris@45 856 }
Chris@45 857
Chris@45 858 if (!layer) {
Chris@293 859 cerr << "WARNING: SV-XML: Failed to add layer of type \""
Chris@294 860 << type
Chris@293 861 << "\"" << endl;
Chris@45 862 return false;
Chris@45 863 }
Chris@45 864
Chris@45 865 if (isNewLayer) {
Chris@45 866
Chris@45 867 QString name = attributes.value("name");
Chris@45 868 layer->setObjectName(name);
Chris@45 869
Chris@89 870 QString presentationName = attributes.value("presentationName");
Chris@89 871 layer->setPresentationName(presentationName);
Chris@89 872
Chris@45 873 int modelId;
Chris@45 874 bool modelOk = false;
Chris@45 875 modelId = attributes.value("model").trimmed().toInt(&modelOk);
Chris@45 876
Chris@45 877 if (modelOk) {
Chris@45 878 if (haveModel(modelId)) {
Chris@45 879 Model *model = m_models[modelId];
Chris@45 880 m_document->setModel(layer, model);
Chris@45 881 } else {
Chris@293 882 cerr << "WARNING: SV-XML: Unknown model id " << modelId
Chris@293 883 << " in layer definition" << endl;
Chris@45 884 }
Chris@45 885 }
Chris@45 886
Chris@45 887 layer->setProperties(attributes);
Chris@45 888 }
Chris@45 889
Chris@45 890 if (!m_inData && m_currentPane) {
Chris@45 891
Chris@45 892 QString visible = attributes.value("visible");
Chris@45 893 bool dormant = (visible == "false");
Chris@45 894
Chris@45 895 // We need to do this both before and after adding the layer
Chris@45 896 // to the view -- we need it to be dormant if appropriate
Chris@45 897 // before it's actually added to the view so that any property
Chris@45 898 // box gets the right state when it's added, but the add layer
Chris@45 899 // command sets dormant to false because it assumes it may be
Chris@45 900 // restoring a previously dormant layer, so we need to set it
Chris@45 901 // again afterwards too. Hm
Chris@45 902 layer->setLayerDormant(m_currentPane, dormant);
Chris@45 903
Chris@45 904 m_document->addLayerToView(m_currentPane, layer);
Chris@45 905
Chris@45 906 layer->setLayerDormant(m_currentPane, dormant);
Chris@45 907 }
Chris@45 908
Chris@45 909 m_currentLayer = layer;
Chris@45 910 m_inLayer = true;
Chris@45 911
Chris@45 912 return true;
Chris@45 913 }
Chris@45 914
Chris@45 915 bool
Chris@45 916 SVFileReader::readDatasetStart(const QXmlAttributes &attributes)
Chris@45 917 {
Chris@45 918 bool ok = false;
Chris@45 919
Chris@45 920 READ_MANDATORY(int, id, toInt);
Chris@45 921 READ_MANDATORY(int, dimensions, toInt);
Chris@45 922
Chris@45 923 if (m_awaitingDatasets.find(id) == m_awaitingDatasets.end()) {
Chris@293 924 cerr << "WARNING: SV-XML: Unwanted dataset " << id << endl;
Chris@45 925 return false;
Chris@45 926 }
Chris@45 927
Chris@45 928 int modelId = m_awaitingDatasets[id];
Chris@45 929
Chris@45 930 Model *model = 0;
Chris@45 931 if (haveModel(modelId)) {
Chris@45 932 model = m_models[modelId];
Chris@45 933 } else {
Chris@293 934 cerr << "WARNING: SV-XML: Internal error: Unknown model " << modelId
Chris@293 935 << " expecting dataset " << id << endl;
Chris@45 936 return false;
Chris@45 937 }
Chris@45 938
Chris@45 939 bool good = false;
Chris@45 940
Chris@45 941 switch (dimensions) {
Chris@45 942 case 1:
Chris@45 943 if (dynamic_cast<SparseOneDimensionalModel *>(model)) good = true;
Chris@45 944 else if (dynamic_cast<ImageModel *>(model)) good = true;
Chris@45 945 break;
Chris@45 946
Chris@45 947 case 2:
Chris@45 948 if (dynamic_cast<SparseTimeValueModel *>(model)) good = true;
Chris@45 949 else if (dynamic_cast<TextModel *>(model)) good = true;
Chris@111 950 else if (dynamic_cast<PathModel *>(model)) good = true;
Chris@45 951 break;
Chris@45 952
Chris@45 953 case 3:
Chris@45 954 if (dynamic_cast<NoteModel *>(model)) good = true;
Chris@343 955 else if (dynamic_cast<FlexiNoteModel *>(model)) good = true;
Chris@137 956 else if (dynamic_cast<RegionModel *>(model)) good = true;
Chris@45 957 else if (dynamic_cast<EditableDenseThreeDimensionalModel *>(model)) {
Chris@45 958 m_datasetSeparator = attributes.value("separator");
Chris@45 959 good = true;
Chris@45 960 }
Chris@45 961 break;
Chris@45 962 }
Chris@45 963
Chris@45 964 if (!good) {
Chris@293 965 cerr << "WARNING: SV-XML: Model id " << modelId << " has wrong number of dimensions or inappropriate type for " << dimensions << "-D dataset " << id << endl;
Chris@45 966 m_currentDataset = 0;
Chris@45 967 return false;
Chris@45 968 }
Chris@45 969
Chris@45 970 m_currentDataset = model;
Chris@45 971 return true;
Chris@45 972 }
Chris@45 973
Chris@45 974 bool
Chris@45 975 SVFileReader::addPointToDataset(const QXmlAttributes &attributes)
Chris@45 976 {
Chris@45 977 bool ok = false;
Chris@45 978
Chris@45 979 READ_MANDATORY(int, frame, toInt);
Chris@45 980
Chris@233 981 // SVDEBUG << "SVFileReader::addPointToDataset: frame = " << frame << endl;
Chris@45 982
Chris@45 983 SparseOneDimensionalModel *sodm = dynamic_cast<SparseOneDimensionalModel *>
Chris@45 984 (m_currentDataset);
Chris@45 985
Chris@45 986 if (sodm) {
Chris@293 987 // cerr << "Current dataset is a sparse one dimensional model" << endl;
Chris@45 988 QString label = attributes.value("label");
Chris@45 989 sodm->addPoint(SparseOneDimensionalModel::Point(frame, label));
Chris@45 990 return true;
Chris@45 991 }
Chris@45 992
Chris@45 993 SparseTimeValueModel *stvm = dynamic_cast<SparseTimeValueModel *>
Chris@45 994 (m_currentDataset);
Chris@45 995
Chris@45 996 if (stvm) {
Chris@343 997 cerr << "Current dataset is a sparse time-value model" << endl;
Chris@45 998 float value = 0.0;
Chris@45 999 value = attributes.value("value").trimmed().toFloat(&ok);
Chris@45 1000 QString label = attributes.value("label");
Chris@45 1001 stvm->addPoint(SparseTimeValueModel::Point(frame, value, label));
Chris@45 1002 return ok;
Chris@45 1003 }
Chris@45 1004
Chris@45 1005 NoteModel *nm = dynamic_cast<NoteModel *>(m_currentDataset);
Chris@45 1006
Chris@45 1007 if (nm) {
Chris@343 1008 cerr << "Current dataset is a note model" << endl;
Chris@45 1009 float value = 0.0;
Chris@45 1010 value = attributes.value("value").trimmed().toFloat(&ok);
Chris@366 1011 int duration = 0;
Chris@366 1012 duration = attributes.value("duration").trimmed().toInt(&ok);
Chris@45 1013 QString label = attributes.value("label");
Chris@61 1014 float level = attributes.value("level").trimmed().toFloat(&ok);
Chris@61 1015 if (!ok) { // level is optional
Chris@61 1016 level = 1.f;
Chris@61 1017 ok = true;
Chris@61 1018 }
Chris@61 1019 nm->addPoint(NoteModel::Point(frame, value, duration, level, label));
Chris@45 1020 return ok;
Chris@45 1021 }
Chris@45 1022
Chris@343 1023 FlexiNoteModel *fnm = dynamic_cast<FlexiNoteModel *>(m_currentDataset);
Chris@343 1024
Chris@343 1025 if (fnm) {
Chris@343 1026 cerr << "Current dataset is a flexinote model" << endl;
Chris@343 1027 float value = 0.0;
Chris@343 1028 value = attributes.value("value").trimmed().toFloat(&ok);
Chris@366 1029 int duration = 0;
Chris@366 1030 duration = attributes.value("duration").trimmed().toInt(&ok);
Chris@343 1031 QString label = attributes.value("label");
Chris@343 1032 float level = attributes.value("level").trimmed().toFloat(&ok);
Chris@343 1033 if (!ok) { // level is optional
Chris@343 1034 level = 1.f;
Chris@343 1035 ok = true;
Chris@343 1036 }
Chris@343 1037 fnm->addPoint(FlexiNoteModel::Point(frame, value, duration, level, label));
Chris@343 1038 return ok;
Chris@343 1039 }
Chris@343 1040
Chris@137 1041 RegionModel *rm = dynamic_cast<RegionModel *>(m_currentDataset);
Chris@137 1042
Chris@137 1043 if (rm) {
Chris@343 1044 cerr << "Current dataset is a region model" << endl;
Chris@137 1045 float value = 0.0;
Chris@137 1046 value = attributes.value("value").trimmed().toFloat(&ok);
Chris@366 1047 int duration = 0;
Chris@366 1048 duration = attributes.value("duration").trimmed().toInt(&ok);
Chris@137 1049 QString label = attributes.value("label");
Chris@137 1050 rm->addPoint(RegionModel::Point(frame, value, duration, label));
Chris@137 1051 return ok;
Chris@137 1052 }
Chris@137 1053
Chris@45 1054 TextModel *tm = dynamic_cast<TextModel *>(m_currentDataset);
Chris@45 1055
Chris@45 1056 if (tm) {
Chris@293 1057 // cerr << "Current dataset is a text model" << endl;
Chris@45 1058 float height = 0.0;
Chris@45 1059 height = attributes.value("height").trimmed().toFloat(&ok);
Chris@45 1060 QString label = attributes.value("label");
Chris@233 1061 // SVDEBUG << "SVFileReader::addPointToDataset: TextModel: frame = " << frame << ", height = " << height << ", label = " << label << ", ok = " << ok << endl;
Chris@45 1062 tm->addPoint(TextModel::Point(frame, height, label));
Chris@45 1063 return ok;
Chris@45 1064 }
Chris@45 1065
Chris@111 1066 PathModel *pm = dynamic_cast<PathModel *>(m_currentDataset);
Chris@111 1067
Chris@111 1068 if (pm) {
Chris@293 1069 // cerr << "Current dataset is a path model" << endl;
Chris@111 1070 int mapframe = attributes.value("mapframe").trimmed().toInt(&ok);
Chris@233 1071 // SVDEBUG << "SVFileReader::addPointToDataset: PathModel: frame = " << frame << ", mapframe = " << mapframe << ", ok = " << ok << endl;
Chris@111 1072 pm->addPoint(PathModel::Point(frame, mapframe));
Chris@111 1073 return ok;
Chris@111 1074 }
Chris@111 1075
Chris@45 1076 ImageModel *im = dynamic_cast<ImageModel *>(m_currentDataset);
Chris@45 1077
Chris@45 1078 if (im) {
Chris@293 1079 // cerr << "Current dataset is an image model" << endl;
Chris@45 1080 QString image = attributes.value("image");
Chris@45 1081 QString label = attributes.value("label");
Chris@233 1082 // SVDEBUG << "SVFileReader::addPointToDataset: ImageModel: frame = " << frame << ", image = " << image << ", label = " << label << ", ok = " << ok << endl;
Chris@45 1083 im->addPoint(ImageModel::Point(frame, image, label));
Chris@45 1084 return ok;
Chris@45 1085 }
Chris@45 1086
Chris@293 1087 cerr << "WARNING: SV-XML: Point element found in non-point dataset" << endl;
Chris@45 1088
Chris@45 1089 return false;
Chris@45 1090 }
Chris@45 1091
Chris@45 1092 bool
Chris@45 1093 SVFileReader::addBinToDataset(const QXmlAttributes &attributes)
Chris@45 1094 {
Chris@45 1095 EditableDenseThreeDimensionalModel *dtdm =
Chris@45 1096 dynamic_cast<EditableDenseThreeDimensionalModel *>
Chris@45 1097 (m_currentDataset);
Chris@45 1098
Chris@45 1099 if (dtdm) {
Chris@45 1100
Chris@45 1101 bool ok = false;
Chris@45 1102 int n = attributes.value("number").trimmed().toInt(&ok);
Chris@45 1103 if (!ok) {
Chris@293 1104 cerr << "WARNING: SV-XML: Missing or invalid bin number"
Chris@293 1105 << endl;
Chris@45 1106 return false;
Chris@45 1107 }
Chris@45 1108
Chris@45 1109 QString name = attributes.value("name");
Chris@45 1110
Chris@45 1111 dtdm->setBinName(n, name);
Chris@45 1112 return true;
Chris@45 1113 }
Chris@45 1114
Chris@293 1115 cerr << "WARNING: SV-XML: Bin definition found in incompatible dataset" << endl;
Chris@45 1116
Chris@45 1117 return false;
Chris@45 1118 }
Chris@45 1119
Chris@45 1120
Chris@45 1121 bool
Chris@45 1122 SVFileReader::addRowToDataset(const QXmlAttributes &attributes)
Chris@45 1123 {
Chris@45 1124 m_inRow = false;
Chris@45 1125
Chris@45 1126 bool ok = false;
Chris@45 1127 m_rowNumber = attributes.value("n").trimmed().toInt(&ok);
Chris@45 1128 if (!ok) {
Chris@293 1129 cerr << "WARNING: SV-XML: Missing or invalid row number"
Chris@293 1130 << endl;
Chris@45 1131 return false;
Chris@45 1132 }
Chris@45 1133
Chris@45 1134 m_inRow = true;
Chris@45 1135
Chris@293 1136 // cerr << "SV-XML: In row " << m_rowNumber << endl;
Chris@45 1137
Chris@45 1138 return true;
Chris@45 1139 }
Chris@45 1140
Chris@45 1141 bool
Chris@45 1142 SVFileReader::readRowData(const QString &text)
Chris@45 1143 {
Chris@45 1144 EditableDenseThreeDimensionalModel *dtdm =
Chris@45 1145 dynamic_cast<EditableDenseThreeDimensionalModel *>
Chris@45 1146 (m_currentDataset);
Chris@45 1147
Chris@45 1148 bool warned = false;
Chris@45 1149
Chris@45 1150 if (dtdm) {
Chris@45 1151 QStringList data = text.split(m_datasetSeparator);
Chris@45 1152
Chris@45 1153 DenseThreeDimensionalModel::Column values;
Chris@45 1154
Chris@45 1155 for (QStringList::iterator i = data.begin(); i != data.end(); ++i) {
Chris@45 1156
Chris@358 1157 if (values.size() == (int)dtdm->getHeight()) {
Chris@45 1158 if (!warned) {
Chris@293 1159 cerr << "WARNING: SV-XML: Too many y-bins in 3-D dataset row "
Chris@293 1160 << m_rowNumber << endl;
Chris@45 1161 warned = true;
Chris@45 1162 }
Chris@45 1163 }
Chris@45 1164
Chris@45 1165 bool ok;
Chris@45 1166 float value = i->toFloat(&ok);
Chris@45 1167 if (!ok) {
Chris@293 1168 cerr << "WARNING: SV-XML: Bad floating-point value "
Chris@45 1169 << i->toLocal8Bit().data()
Chris@293 1170 << " in row data" << endl;
Chris@45 1171 } else {
Chris@45 1172 values.push_back(value);
Chris@45 1173 }
Chris@45 1174 }
Chris@45 1175
Chris@45 1176 dtdm->setColumn(m_rowNumber, values);
Chris@45 1177 return true;
Chris@45 1178 }
Chris@45 1179
Chris@293 1180 cerr << "WARNING: SV-XML: Row data found in non-row dataset" << endl;
Chris@45 1181
Chris@45 1182 return false;
Chris@45 1183 }
Chris@45 1184
Chris@45 1185 bool
Chris@45 1186 SVFileReader::readDerivation(const QXmlAttributes &attributes)
Chris@45 1187 {
Chris@45 1188 int modelId = 0;
Chris@45 1189 bool modelOk = false;
Chris@45 1190 modelId = attributes.value("model").trimmed().toInt(&modelOk);
Chris@45 1191
Chris@45 1192 if (!modelOk) {
Chris@293 1193 cerr << "WARNING: SV-XML: No model id specified for derivation" << endl;
Chris@45 1194 return false;
Chris@45 1195 }
Chris@45 1196
Chris@45 1197 if (haveModel(modelId)) {
Chris@45 1198 m_currentDerivedModel = m_models[modelId];
Chris@45 1199 } else {
Chris@45 1200 // we'll regenerate the model when the derivation element ends
Chris@45 1201 m_currentDerivedModel = 0;
Chris@45 1202 }
Chris@45 1203
Chris@45 1204 m_currentDerivedModelId = modelId;
Chris@45 1205
Chris@45 1206 int sourceId = 0;
Chris@45 1207 bool sourceOk = false;
Chris@45 1208 sourceId = attributes.value("source").trimmed().toInt(&sourceOk);
Chris@45 1209
Chris@45 1210 if (sourceOk && haveModel(sourceId)) {
Chris@72 1211 m_currentTransformSource = m_models[sourceId];
Chris@45 1212 } else {
Chris@72 1213 m_currentTransformSource = m_document->getMainModel();
Chris@45 1214 }
Chris@45 1215
Chris@72 1216 m_currentTransform = Transform();
Chris@45 1217
Chris@45 1218 bool ok = false;
Chris@45 1219 int channel = attributes.value("channel").trimmed().toInt(&ok);
Chris@72 1220 if (ok) m_currentTransformChannel = channel;
Chris@72 1221 else m_currentTransformChannel = -1;
Chris@45 1222
Chris@72 1223 QString type = attributes.value("type");
Chris@72 1224
Chris@72 1225 if (type == "transform") {
Chris@72 1226 m_currentTransformIsNewStyle = true;
Chris@72 1227 return true;
Chris@72 1228 } else {
Chris@72 1229 m_currentTransformIsNewStyle = false;
Chris@233 1230 SVDEBUG << "NOTE: SV-XML: Reading old-style derivation element"
Chris@229 1231 << endl;
Chris@72 1232 }
Chris@72 1233
Chris@72 1234 QString transformId = attributes.value("transform");
Chris@72 1235
Chris@72 1236 m_currentTransform.setIdentifier(transformId);
Chris@45 1237
Chris@45 1238 int stepSize = attributes.value("stepSize").trimmed().toInt(&ok);
Chris@72 1239 if (ok) m_currentTransform.setStepSize(stepSize);
Chris@45 1240
Chris@45 1241 int blockSize = attributes.value("blockSize").trimmed().toInt(&ok);
Chris@72 1242 if (ok) m_currentTransform.setBlockSize(blockSize);
Chris@45 1243
Chris@45 1244 int windowType = attributes.value("windowType").trimmed().toInt(&ok);
Chris@72 1245 if (ok) m_currentTransform.setWindowType(WindowType(windowType));
Chris@72 1246
Chris@72 1247 if (!m_currentTransformSource) return true;
Chris@45 1248
Chris@45 1249 QString startFrameStr = attributes.value("startFrame");
Chris@45 1250 QString durationStr = attributes.value("duration");
Chris@45 1251
Chris@366 1252 int startFrame = 0;
Chris@366 1253 int duration = 0;
Chris@45 1254
Chris@45 1255 if (startFrameStr != "") {
Chris@45 1256 startFrame = startFrameStr.trimmed().toInt(&ok);
Chris@45 1257 if (!ok) startFrame = 0;
Chris@45 1258 }
Chris@45 1259 if (durationStr != "") {
Chris@45 1260 duration = durationStr.trimmed().toInt(&ok);
Chris@45 1261 if (!ok) duration = 0;
Chris@45 1262 }
Chris@45 1263
Chris@72 1264 m_currentTransform.setStartTime
Chris@72 1265 (RealTime::frame2RealTime
Chris@72 1266 (startFrame, m_currentTransformSource->getSampleRate()));
Chris@72 1267
Chris@72 1268 m_currentTransform.setDuration
Chris@72 1269 (RealTime::frame2RealTime
Chris@72 1270 (duration, m_currentTransformSource->getSampleRate()));
Chris@45 1271
Chris@45 1272 return true;
Chris@45 1273 }
Chris@45 1274
Chris@45 1275 bool
Chris@45 1276 SVFileReader::readPlayParameters(const QXmlAttributes &attributes)
Chris@45 1277 {
Chris@45 1278 m_currentPlayParameters = 0;
Chris@45 1279
Chris@45 1280 int modelId = 0;
Chris@45 1281 bool modelOk = false;
Chris@45 1282 modelId = attributes.value("model").trimmed().toInt(&modelOk);
Chris@45 1283
Chris@45 1284 if (!modelOk) {
Chris@293 1285 cerr << "WARNING: SV-XML: No model id specified for play parameters" << endl;
Chris@45 1286 return false;
Chris@45 1287 }
Chris@45 1288
Chris@45 1289 if (haveModel(modelId)) {
Chris@45 1290
Chris@45 1291 bool ok = false;
Chris@45 1292
Chris@45 1293 PlayParameters *parameters = PlayParameterRepository::getInstance()->
Chris@45 1294 getPlayParameters(m_models[modelId]);
Chris@45 1295
Chris@45 1296 if (!parameters) {
Chris@293 1297 cerr << "WARNING: SV-XML: Play parameters for model "
Chris@45 1298 << modelId
Chris@45 1299 << " not found - has model been added to document?"
Chris@293 1300 << endl;
Chris@45 1301 return false;
Chris@45 1302 }
Chris@45 1303
Chris@45 1304 bool muted = (attributes.value("mute").trimmed() == "true");
Chris@45 1305 parameters->setPlayMuted(muted);
Chris@45 1306
Chris@45 1307 float pan = attributes.value("pan").toFloat(&ok);
Chris@45 1308 if (ok) parameters->setPlayPan(pan);
Chris@45 1309
Chris@45 1310 float gain = attributes.value("gain").toFloat(&ok);
Chris@45 1311 if (ok) parameters->setPlayGain(gain);
Chris@45 1312
Chris@309 1313 QString clipId = attributes.value("clipId");
Chris@309 1314 if (clipId != "") parameters->setPlayClipId(clipId);
Chris@45 1315
Chris@45 1316 m_currentPlayParameters = parameters;
Chris@45 1317
Chris@293 1318 // cerr << "Current play parameters for model: " << m_models[modelId] << ": " << m_currentPlayParameters << endl;
Chris@45 1319
Chris@45 1320 } else {
Chris@45 1321
Chris@293 1322 cerr << "WARNING: SV-XML: Unknown model " << modelId
Chris@293 1323 << " for play parameters" << endl;
Chris@45 1324 return false;
Chris@45 1325 }
Chris@45 1326
Chris@45 1327 return true;
Chris@45 1328 }
Chris@45 1329
Chris@45 1330 bool
Chris@45 1331 SVFileReader::readPlugin(const QXmlAttributes &attributes)
Chris@45 1332 {
Chris@308 1333 if (m_currentDerivedModelId >= 0) {
Chris@308 1334 return readPluginForTransform(attributes);
Chris@308 1335 } else if (m_currentPlayParameters) {
Chris@308 1336 return readPluginForPlayback(attributes);
Chris@308 1337 } else {
Chris@293 1338 cerr << "WARNING: SV-XML: Plugin found outside derivation or play parameters" << endl;
Chris@45 1339 return false;
Chris@45 1340 }
Chris@308 1341 }
Chris@45 1342
Chris@308 1343 bool
Chris@308 1344 SVFileReader::readPluginForTransform(const QXmlAttributes &attributes)
Chris@308 1345 {
Chris@308 1346 if (m_currentTransformIsNewStyle) {
Chris@308 1347 // Not needed, we have the transform element instead
Chris@72 1348 return true;
Chris@72 1349 }
Chris@72 1350
Chris@45 1351 QString configurationXml = "<plugin";
Chris@308 1352
Chris@45 1353 for (int i = 0; i < attributes.length(); ++i) {
Chris@45 1354 configurationXml += QString(" %1=\"%2\"")
Chris@45 1355 .arg(attributes.qName(i))
Chris@45 1356 .arg(XmlExportable::encodeEntities(attributes.value(i)));
Chris@45 1357 }
Chris@45 1358
Chris@45 1359 configurationXml += "/>";
Chris@45 1360
Chris@308 1361 TransformFactory::getInstance()->
Chris@308 1362 setParametersFromPluginConfigurationXml(m_currentTransform,
Chris@308 1363 configurationXml);
Chris@308 1364 return true;
Chris@308 1365 }
Chris@308 1366
Chris@308 1367 bool
Chris@308 1368 SVFileReader::readPluginForPlayback(const QXmlAttributes &attributes)
Chris@308 1369 {
Chris@308 1370 // Obsolete but supported for compatibility
Chris@308 1371
Chris@308 1372 QString ident = attributes.value("identifier");
Chris@308 1373 if (ident == "sample_player") {
Chris@309 1374 QString clipId = attributes.value("program");
Chris@309 1375 if (clipId != "") m_currentPlayParameters->setPlayClipId(clipId);
Chris@45 1376 }
Chris@45 1377
Chris@45 1378 return true;
Chris@45 1379 }
Chris@45 1380
Chris@45 1381 bool
Chris@72 1382 SVFileReader::readTransform(const QXmlAttributes &attributes)
Chris@72 1383 {
Chris@72 1384 if (m_currentDerivedModelId < 0) {
Chris@293 1385 cerr << "WARNING: SV-XML: Transform found outside derivation" << endl;
Chris@72 1386 return false;
Chris@72 1387 }
Chris@72 1388
Chris@82 1389 m_currentTransform = Transform();
Chris@72 1390 m_currentTransform.setFromXmlAttributes(attributes);
Chris@72 1391 return true;
Chris@72 1392 }
Chris@72 1393
Chris@72 1394 bool
Chris@72 1395 SVFileReader::readParameter(const QXmlAttributes &attributes)
Chris@72 1396 {
Chris@72 1397 if (m_currentDerivedModelId < 0) {
Chris@293 1398 cerr << "WARNING: SV-XML: Parameter found outside derivation" << endl;
Chris@72 1399 return false;
Chris@72 1400 }
Chris@72 1401
Chris@72 1402 QString name = attributes.value("name");
Chris@72 1403 if (name == "") {
Chris@293 1404 cerr << "WARNING: SV-XML: Ignoring nameless transform parameter"
Chris@293 1405 << endl;
Chris@72 1406 return false;
Chris@72 1407 }
Chris@72 1408
Chris@72 1409 float value = attributes.value("value").trimmed().toFloat();
Chris@72 1410
Chris@72 1411 m_currentTransform.setParameter(name, value);
Chris@72 1412 return true;
Chris@72 1413 }
Chris@72 1414
Chris@72 1415 bool
Chris@45 1416 SVFileReader::readSelection(const QXmlAttributes &attributes)
Chris@45 1417 {
Chris@45 1418 bool ok;
Chris@45 1419
Chris@45 1420 READ_MANDATORY(int, start, toInt);
Chris@45 1421 READ_MANDATORY(int, end, toInt);
Chris@45 1422
Chris@45 1423 m_paneCallback.addSelection(start, end);
Chris@45 1424
Chris@45 1425 return true;
Chris@45 1426 }
Chris@45 1427
Chris@45 1428 bool
Chris@45 1429 SVFileReader::readMeasurement(const QXmlAttributes &attributes)
Chris@45 1430 {
Chris@233 1431 SVDEBUG << "SVFileReader::readMeasurement: inLayer "
Chris@229 1432 << m_inLayer << ", layer " << m_currentLayer << endl;
Chris@45 1433
Chris@45 1434 if (!m_inLayer) {
Chris@293 1435 cerr << "WARNING: SV-XML: Measurement found outside layer" << endl;
Chris@45 1436 return false;
Chris@45 1437 }
Chris@45 1438
Chris@45 1439 m_currentLayer->addMeasurementRect(attributes);
Chris@45 1440 return true;
Chris@45 1441 }
Chris@45 1442
Chris@45 1443 SVFileReaderPaneCallback::~SVFileReaderPaneCallback()
Chris@45 1444 {
Chris@45 1445 }
Chris@45 1446
Chris@140 1447
Chris@140 1448 class SVFileIdentifier : public QXmlDefaultHandler
Chris@140 1449 {
Chris@140 1450 public:
Chris@140 1451 SVFileIdentifier() :
Chris@140 1452 m_inSv(false),
Chris@140 1453 m_inData(false),
Chris@140 1454 m_type(SVFileReader::UnknownFileType)
Chris@140 1455 { }
Chris@140 1456 virtual ~SVFileIdentifier() { }
Chris@140 1457
Chris@140 1458 void parse(QXmlInputSource &source) {
Chris@140 1459 QXmlSimpleReader reader;
Chris@140 1460 reader.setContentHandler(this);
Chris@140 1461 reader.setErrorHandler(this);
Chris@140 1462 reader.parse(source);
Chris@140 1463 }
Chris@140 1464
Chris@140 1465 SVFileReader::FileType getType() const { return m_type; }
Chris@140 1466
Chris@140 1467 virtual bool startElement(const QString &,
Chris@140 1468 const QString &,
Chris@140 1469 const QString &qName,
Chris@140 1470 const QXmlAttributes& atts)
Chris@140 1471 {
Chris@140 1472 QString name = qName.toLower();
Chris@140 1473
Chris@140 1474 // SV session files have an sv element containing a data
Chris@140 1475 // element containing a model element with mainModel="true".
Chris@140 1476
Chris@140 1477 // If the sv element is present but the rest does not satisfy,
Chris@140 1478 // then it's (probably) an SV layer file.
Chris@140 1479
Chris@140 1480 // Otherwise, it's of unknown type.
Chris@140 1481
Chris@140 1482 if (name == "sv") {
Chris@140 1483 m_inSv = true;
Chris@140 1484 if (m_type == SVFileReader::UnknownFileType) {
Chris@140 1485 m_type = SVFileReader::SVLayerFile;
Chris@140 1486 }
Chris@140 1487 return true;
Chris@140 1488 } else if (name == "data") {
Chris@140 1489 if (!m_inSv) return true;
Chris@140 1490 m_inData = true;
Chris@140 1491 } else if (name == "model") {
Chris@140 1492 if (!m_inData) return true;
Chris@140 1493 if (atts.value("mainModel").trimmed() == "true") {
Chris@140 1494 if (m_type == SVFileReader::SVLayerFile) {
Chris@140 1495 m_type = SVFileReader::SVSessionFile;
Chris@140 1496 return false; // done
Chris@140 1497 }
Chris@140 1498 }
Chris@140 1499 }
Chris@140 1500 return true;
Chris@140 1501 }
Chris@140 1502
Chris@140 1503 virtual bool endElement(const QString &,
Chris@140 1504 const QString &,
Chris@140 1505 const QString &qName)
Chris@140 1506 {
Chris@140 1507 QString name = qName.toLower();
Chris@140 1508
Chris@140 1509 if (name == "sv") {
Chris@140 1510 if (m_inSv) {
Chris@140 1511 m_inSv = false;
Chris@140 1512 return false; // done
Chris@140 1513 }
Chris@140 1514 } else if (name == "data") {
Chris@140 1515 if (m_inData) {
Chris@140 1516 m_inData = false;
Chris@140 1517 return false; // also done, nothing after the first
Chris@140 1518 // data element is of use here
Chris@140 1519 }
Chris@140 1520 }
Chris@140 1521 return true;
Chris@140 1522 }
Chris@140 1523
Chris@140 1524 private:
Chris@140 1525 bool m_inSv;
Chris@140 1526 bool m_inData;
Chris@140 1527 SVFileReader::FileType m_type;
Chris@140 1528 };
Chris@140 1529
Chris@140 1530
Chris@140 1531 SVFileReader::FileType
Chris@140 1532 SVFileReader::identifyXmlFile(QString path)
Chris@140 1533 {
Chris@140 1534 QFile file(path);
Chris@140 1535 SVFileIdentifier identifier;
Chris@140 1536 QXmlInputSource source(&file);
Chris@140 1537 identifier.parse(source);
Chris@140 1538 return identifier.getType();
Chris@140 1539 }
Chris@140 1540
Chris@140 1541
Chris@140 1542