annotate framework/SVFileReader.cpp @ 451:dc1a360f2b69

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