annotate framework/SVFileReader.cpp @ 285:32d8084f8543

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