annotate framework/SVFileReader.cpp @ 183:da514e36839a

* If, when a model is removed from a layer, it is found that the only remaining layers representing that model are ruler layers, then stop playing the model (probable fix to bug reported by Tim Crawford)
author Chris Cannam
date Wed, 23 Sep 2009 11:19:43 +0000
parents b35c7af2e1d0
children fe83e6e68683
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@45 415 m_document->addImportedModel(*i);
Chris@45 416 m_addedModels.insert(*i);
Chris@45 417 }
Chris@45 418 }
Chris@45 419
Chris@45 420 bool
Chris@45 421 SVFileReader::readModel(const QXmlAttributes &attributes)
Chris@45 422 {
Chris@45 423 bool ok = false;
Chris@45 424
Chris@45 425 READ_MANDATORY(int, id, toInt);
Chris@45 426
Chris@45 427 if (haveModel(id)) {
Chris@45 428 std::cerr << "WARNING: SV-XML: Ignoring duplicate model id " << id
Chris@45 429 << std::endl;
Chris@45 430 return false;
Chris@45 431 }
Chris@45 432
Chris@45 433 QString name = attributes.value("name");
Chris@45 434
Chris@45 435 std::cerr << "SVFileReader::readModel: model name \"" << name.toStdString() << "\"" << std::endl;
Chris@45 436
Chris@45 437 READ_MANDATORY(int, sampleRate, toInt);
Chris@45 438
Chris@45 439 QString type = attributes.value("type").trimmed();
Chris@45 440 bool mainModel = (attributes.value("mainModel").trimmed() == "true");
Chris@45 441
Chris@45 442 if (type == "wavefile") {
Chris@45 443
Chris@45 444 WaveFileModel *model = 0;
Chris@45 445 FileFinder *ff = FileFinder::getInstance();
Chris@45 446 QString originalPath = attributes.value("file");
Chris@45 447 QString path = ff->find(FileFinder::AudioFile,
Chris@45 448 originalPath, m_location);
Chris@45 449
Chris@109 450 ProgressDialog dialog(tr("Opening file or URL..."), true, 2000);
Chris@109 451 FileSource file(path, &dialog);
Chris@45 452 file.waitForStatus();
Chris@45 453
Chris@45 454 if (!file.isOK()) {
Chris@45 455 std::cerr << "SVFileReader::readModel: Failed to retrieve file \"" << path.toStdString() << "\" for wave file model: " << file.getErrorString().toStdString() << std::endl;
Chris@45 456 } else if (!file.isAvailable()) {
Chris@45 457 std::cerr << "SVFileReader::readModel: Failed to retrieve file \"" << path.toStdString() << "\" for wave file model: Source unavailable" << std::endl;
Chris@45 458 } else {
Chris@45 459
Chris@45 460 file.waitForData();
Chris@116 461
Chris@116 462 size_t rate = 0;
Chris@116 463
Chris@116 464 if (!mainModel &&
Chris@116 465 Preferences::getInstance()->getResampleOnLoad()) {
Chris@116 466 WaveFileModel *mm = m_document->getMainModel();
Chris@116 467 if (mm) rate = mm->getSampleRate();
Chris@116 468 }
Chris@116 469
Chris@116 470 model = new WaveFileModel(file, rate);
Chris@45 471 if (!model->isOK()) {
Chris@45 472 delete model;
Chris@45 473 model = 0;
Chris@45 474 }
Chris@45 475 }
Chris@45 476
Chris@45 477 if (!model) return false;
Chris@45 478
Chris@45 479 model->setObjectName(name);
Chris@45 480 m_models[id] = model;
Chris@45 481 if (mainModel) {
Chris@45 482 m_document->setMainModel(model);
Chris@45 483 m_addedModels.insert(model);
Chris@45 484 }
Chris@45 485 // Derived models will be added when their derivation
Chris@45 486 // is found.
Chris@45 487
Chris@45 488 return true;
Chris@45 489
Chris@45 490 } else if (type == "dense") {
Chris@45 491
Chris@45 492 READ_MANDATORY(int, dimensions, toInt);
Chris@45 493
Chris@45 494 // Currently the only dense model we support here is the dense
Chris@45 495 // 3d model. Dense time-value models are always file-backed
Chris@45 496 // waveform data, at this point, and they come in as wavefile
Chris@45 497 // models.
Chris@45 498
Chris@45 499 if (dimensions == 3) {
Chris@45 500
Chris@45 501 READ_MANDATORY(int, windowSize, toInt);
Chris@45 502 READ_MANDATORY(int, yBinCount, toInt);
Chris@45 503
Chris@45 504 EditableDenseThreeDimensionalModel *model =
Chris@45 505 new EditableDenseThreeDimensionalModel
Chris@153 506 (sampleRate, windowSize, yBinCount,
Chris@153 507 EditableDenseThreeDimensionalModel::NoCompression);
Chris@45 508
Chris@45 509 float minimum = attributes.value("minimum").trimmed().toFloat(&ok);
Chris@45 510 if (ok) model->setMinimumLevel(minimum);
Chris@45 511
Chris@45 512 float maximum = attributes.value("maximum").trimmed().toFloat(&ok);
Chris@45 513 if (ok) model->setMaximumLevel(maximum);
Chris@45 514
Chris@45 515 int dataset = attributes.value("dataset").trimmed().toInt(&ok);
Chris@45 516 if (ok) m_awaitingDatasets[dataset] = id;
Chris@45 517
Chris@181 518 int startFrame = attributes.value("startFrame").trimmed().toInt(&ok);
Chris@181 519 if (ok) model->setStartFrame(startFrame);
Chris@181 520
Chris@45 521 model->setObjectName(name);
Chris@45 522 m_models[id] = model;
Chris@45 523 return true;
Chris@45 524
Chris@45 525 } else {
Chris@45 526
Chris@45 527 std::cerr << "WARNING: SV-XML: Unexpected dense model dimension ("
Chris@45 528 << dimensions << ")" << std::endl;
Chris@45 529 }
Chris@45 530 } else if (type == "sparse") {
Chris@45 531
Chris@45 532 READ_MANDATORY(int, dimensions, toInt);
Chris@45 533
Chris@45 534 if (dimensions == 1) {
Chris@45 535
Chris@45 536 READ_MANDATORY(int, resolution, toInt);
Chris@45 537
Chris@45 538 if (attributes.value("subtype") == "image") {
Chris@45 539
Chris@45 540 bool notifyOnAdd = (attributes.value("notifyOnAdd") == "true");
Chris@45 541 ImageModel *model = new ImageModel(sampleRate, resolution,
Chris@45 542 notifyOnAdd);
Chris@45 543 model->setObjectName(name);
Chris@45 544 m_models[id] = model;
Chris@45 545
Chris@45 546 } else {
Chris@45 547
Chris@45 548 SparseOneDimensionalModel *model = new SparseOneDimensionalModel
Chris@45 549 (sampleRate, resolution);
Chris@45 550 model->setObjectName(name);
Chris@45 551 m_models[id] = model;
Chris@45 552 }
Chris@45 553
Chris@45 554 int dataset = attributes.value("dataset").trimmed().toInt(&ok);
Chris@45 555 if (ok) m_awaitingDatasets[dataset] = id;
Chris@45 556
Chris@45 557 return true;
Chris@45 558
Chris@45 559 } else if (dimensions == 2 || dimensions == 3) {
Chris@45 560
Chris@45 561 READ_MANDATORY(int, resolution, toInt);
Chris@45 562
Chris@45 563 bool haveMinMax = true;
Chris@45 564 float minimum = attributes.value("minimum").trimmed().toFloat(&ok);
Chris@45 565 if (!ok) haveMinMax = false;
Chris@45 566 float maximum = attributes.value("maximum").trimmed().toFloat(&ok);
Chris@45 567 if (!ok) haveMinMax = false;
Chris@45 568
Chris@45 569 float valueQuantization =
Chris@45 570 attributes.value("valueQuantization").trimmed().toFloat(&ok);
Chris@45 571
Chris@45 572 bool notifyOnAdd = (attributes.value("notifyOnAdd") == "true");
Chris@45 573
Chris@45 574 QString units = attributes.value("units");
Chris@45 575
Chris@45 576 if (dimensions == 2) {
Chris@45 577 if (attributes.value("subtype") == "text") {
Chris@45 578 TextModel *model = new TextModel
Chris@45 579 (sampleRate, resolution, notifyOnAdd);
Chris@45 580 model->setObjectName(name);
Chris@45 581 m_models[id] = model;
Chris@111 582 } else if (attributes.value("subtype") == "path") {
Chris@111 583 PathModel *model = new PathModel
Chris@111 584 (sampleRate, resolution, notifyOnAdd);
Chris@111 585 model->setObjectName(name);
Chris@111 586 m_models[id] = model;
Chris@45 587 } else {
Chris@45 588 SparseTimeValueModel *model;
Chris@45 589 if (haveMinMax) {
Chris@45 590 model = new SparseTimeValueModel
Chris@45 591 (sampleRate, resolution, minimum, maximum, notifyOnAdd);
Chris@45 592 } else {
Chris@45 593 model = new SparseTimeValueModel
Chris@45 594 (sampleRate, resolution, notifyOnAdd);
Chris@45 595 }
Chris@45 596 model->setScaleUnits(units);
Chris@45 597 model->setObjectName(name);
Chris@45 598 m_models[id] = model;
Chris@45 599 }
Chris@45 600 } else {
Chris@137 601 if (attributes.value("subtype") == "region") {
Chris@137 602 RegionModel *model;
Chris@137 603 if (haveMinMax) {
Chris@137 604 model = new RegionModel
Chris@137 605 (sampleRate, resolution, minimum, maximum, notifyOnAdd);
Chris@137 606 } else {
Chris@137 607 model = new RegionModel
Chris@137 608 (sampleRate, resolution, notifyOnAdd);
Chris@137 609 }
Chris@137 610 model->setValueQuantization(valueQuantization);
Chris@137 611 model->setScaleUnits(units);
Chris@137 612 model->setObjectName(name);
Chris@137 613 m_models[id] = model;
Chris@45 614 } else {
Chris@137 615 // note models written out by SV 1.3 and earlier
Chris@137 616 // have no subtype, so we can't test that
Chris@137 617 NoteModel *model;
Chris@137 618 if (haveMinMax) {
Chris@137 619 model = new NoteModel
Chris@137 620 (sampleRate, resolution, minimum, maximum, notifyOnAdd);
Chris@137 621 } else {
Chris@137 622 model = new NoteModel
Chris@137 623 (sampleRate, resolution, notifyOnAdd);
Chris@137 624 }
Chris@137 625 model->setValueQuantization(valueQuantization);
Chris@137 626 model->setScaleUnits(units);
Chris@137 627 model->setObjectName(name);
Chris@137 628 m_models[id] = model;
Chris@45 629 }
Chris@137 630 }
Chris@45 631
Chris@45 632 int dataset = attributes.value("dataset").trimmed().toInt(&ok);
Chris@45 633 if (ok) m_awaitingDatasets[dataset] = id;
Chris@45 634
Chris@45 635 return true;
Chris@45 636
Chris@45 637 } else {
Chris@45 638
Chris@45 639 std::cerr << "WARNING: SV-XML: Unexpected sparse model dimension ("
Chris@45 640 << dimensions << ")" << std::endl;
Chris@45 641 }
Chris@111 642
Chris@111 643 } else if (type == "alignment") {
Chris@111 644
Chris@111 645 READ_MANDATORY(int, reference, toInt);
Chris@111 646 READ_MANDATORY(int, aligned, toInt);
Chris@111 647 READ_MANDATORY(int, path, toInt);
Chris@111 648
Chris@111 649 Model *refModel = 0, *alignedModel = 0, *pathModel = 0;
Chris@111 650
Chris@111 651 if (m_models.find(reference) != m_models.end()) {
Chris@111 652 refModel = m_models[reference];
Chris@111 653 } else {
Chris@111 654 std::cerr << "WARNING: SV-XML: Unknown reference model id "
Chris@111 655 << reference << " in alignment model id " << id
Chris@111 656 << std::endl;
Chris@111 657 }
Chris@111 658
Chris@111 659 if (m_models.find(aligned) != m_models.end()) {
Chris@111 660 alignedModel = m_models[aligned];
Chris@111 661 } else {
Chris@111 662 std::cerr << "WARNING: SV-XML: Unknown aligned model id "
Chris@111 663 << aligned << " in alignment model id " << id
Chris@111 664 << std::endl;
Chris@111 665 }
Chris@111 666
Chris@111 667 if (m_models.find(path) != m_models.end()) {
Chris@111 668 pathModel = m_models[path];
Chris@111 669 } else {
Chris@111 670 std::cerr << "WARNING: SV-XML: Unknown path model id "
Chris@111 671 << path << " in alignment model id " << id
Chris@111 672 << std::endl;
Chris@111 673 }
Chris@111 674
Chris@111 675 if (refModel && alignedModel && pathModel) {
Chris@111 676 AlignmentModel *model = new AlignmentModel
Chris@111 677 (refModel, alignedModel, 0, 0);
Chris@111 678 PathModel *pm = dynamic_cast<PathModel *>(pathModel);
Chris@111 679 if (!pm) {
Chris@111 680 std::cerr << "WARNING: SV-XML: Model id " << path
Chris@111 681 << " referenced as path for alignment " << id
Chris@111 682 << " is not a path model" << std::endl;
Chris@111 683 } else {
Chris@111 684 model->setPath(pm);
Chris@111 685 pm->setCompletion(100);
Chris@111 686 }
Chris@111 687 model->setObjectName(name);
Chris@111 688 m_models[id] = model;
Chris@111 689 alignedModel->setAlignment(model);
Chris@111 690 return true;
Chris@111 691 }
Chris@111 692
Chris@45 693 } else {
Chris@45 694
Chris@45 695 std::cerr << "WARNING: SV-XML: Unexpected model type \""
Chris@45 696 << type.toLocal8Bit().data() << "\" for model id " << id << std::endl;
Chris@45 697 }
Chris@45 698
Chris@45 699 return false;
Chris@45 700 }
Chris@45 701
Chris@45 702 bool
Chris@45 703 SVFileReader::readView(const QXmlAttributes &attributes)
Chris@45 704 {
Chris@45 705 QString type = attributes.value("type");
Chris@45 706 m_currentPane = 0;
Chris@45 707
Chris@45 708 if (type != "pane") {
Chris@45 709 std::cerr << "WARNING: SV-XML: Unexpected view type \""
Chris@45 710 << type.toLocal8Bit().data() << "\"" << std::endl;
Chris@45 711 return false;
Chris@45 712 }
Chris@45 713
Chris@45 714 m_currentPane = m_paneCallback.addPane();
Chris@45 715
Chris@45 716 if (!m_currentPane) {
Chris@45 717 std::cerr << "WARNING: SV-XML: Internal error: Failed to add pane!"
Chris@45 718 << std::endl;
Chris@45 719 return false;
Chris@45 720 }
Chris@45 721
Chris@45 722 bool ok = false;
Chris@45 723
Chris@45 724 View *view = m_currentPane;
Chris@45 725
Chris@45 726 // The view properties first
Chris@45 727
Chris@45 728 READ_MANDATORY(size_t, centre, toUInt);
Chris@45 729 READ_MANDATORY(size_t, zoom, toUInt);
Chris@45 730 READ_MANDATORY(int, followPan, toInt);
Chris@45 731 READ_MANDATORY(int, followZoom, toInt);
Chris@45 732 QString tracking = attributes.value("tracking");
Chris@45 733
Chris@45 734 // Specify the follow modes before we set the actual values
Chris@45 735 view->setFollowGlobalPan(followPan);
Chris@45 736 view->setFollowGlobalZoom(followZoom);
Chris@45 737 view->setPlaybackFollow(tracking == "scroll" ? PlaybackScrollContinuous :
Chris@45 738 tracking == "page" ? PlaybackScrollPage
Chris@45 739 : PlaybackIgnore);
Chris@45 740
Chris@45 741 // Then set these values
Chris@45 742 view->setCentreFrame(centre);
Chris@45 743 view->setZoomLevel(zoom);
Chris@45 744
Chris@45 745 // And pane properties
Chris@45 746 READ_MANDATORY(int, centreLineVisible, toInt);
Chris@45 747 m_currentPane->setCentreLineVisible(centreLineVisible);
Chris@45 748
Chris@45 749 int height = attributes.value("height").toInt(&ok);
Chris@45 750 if (ok) {
Chris@45 751 m_currentPane->resize(m_currentPane->width(), height);
Chris@45 752 }
Chris@45 753
Chris@45 754 return true;
Chris@45 755 }
Chris@45 756
Chris@45 757 bool
Chris@45 758 SVFileReader::readLayer(const QXmlAttributes &attributes)
Chris@45 759 {
Chris@45 760 QString type = attributes.value("type");
Chris@45 761
Chris@45 762 int id;
Chris@45 763 bool ok = false;
Chris@45 764 id = attributes.value("id").trimmed().toInt(&ok);
Chris@45 765
Chris@45 766 if (!ok) {
Chris@45 767 std::cerr << "WARNING: SV-XML: No layer id for layer of type \""
Chris@45 768 << type.toLocal8Bit().data()
Chris@45 769 << "\"" << std::endl;
Chris@45 770 return false;
Chris@45 771 }
Chris@45 772
Chris@45 773 Layer *layer = 0;
Chris@45 774 bool isNewLayer = false;
Chris@45 775
Chris@45 776 // Layers are expected to be defined in layer elements in the data
Chris@45 777 // section, and referred to in layer elements in the view
Chris@45 778 // sections. So if we're in the data section, we expect this
Chris@45 779 // layer not to exist already; if we're in the view section, we
Chris@45 780 // expect it to exist.
Chris@45 781
Chris@45 782 if (m_inData) {
Chris@45 783
Chris@45 784 if (m_layers.find(id) != m_layers.end()) {
Chris@45 785 std::cerr << "WARNING: SV-XML: Ignoring duplicate layer id " << id
Chris@45 786 << " in data section" << std::endl;
Chris@45 787 return false;
Chris@45 788 }
Chris@45 789
Chris@45 790 layer = m_layers[id] = m_document->createLayer
Chris@45 791 (LayerFactory::getInstance()->getLayerTypeForName(type));
Chris@45 792
Chris@45 793 if (layer) {
Chris@45 794 m_layers[id] = layer;
Chris@45 795 isNewLayer = true;
Chris@45 796 }
Chris@45 797
Chris@45 798 } else {
Chris@45 799
Chris@45 800 if (!m_currentPane) {
Chris@45 801 std::cerr << "WARNING: SV-XML: No current pane for layer " << id
Chris@45 802 << " in view section" << std::endl;
Chris@45 803 return false;
Chris@45 804 }
Chris@45 805
Chris@45 806 if (m_layers.find(id) != m_layers.end()) {
Chris@45 807
Chris@45 808 layer = m_layers[id];
Chris@45 809
Chris@45 810 } else {
Chris@45 811 std::cerr << "WARNING: SV-XML: Layer id " << id
Chris@45 812 << " in view section has not been defined -- defining it here"
Chris@45 813 << std::endl;
Chris@45 814
Chris@45 815 layer = m_document->createLayer
Chris@45 816 (LayerFactory::getInstance()->getLayerTypeForName(type));
Chris@45 817
Chris@45 818 if (layer) {
Chris@45 819 m_layers[id] = layer;
Chris@45 820 isNewLayer = true;
Chris@45 821 }
Chris@45 822 }
Chris@45 823 }
Chris@45 824
Chris@45 825 if (!layer) {
Chris@45 826 std::cerr << "WARNING: SV-XML: Failed to add layer of type \""
Chris@45 827 << type.toLocal8Bit().data()
Chris@45 828 << "\"" << std::endl;
Chris@45 829 return false;
Chris@45 830 }
Chris@45 831
Chris@45 832 if (isNewLayer) {
Chris@45 833
Chris@45 834 QString name = attributes.value("name");
Chris@45 835 layer->setObjectName(name);
Chris@45 836
Chris@89 837 QString presentationName = attributes.value("presentationName");
Chris@89 838 layer->setPresentationName(presentationName);
Chris@89 839
Chris@45 840 int modelId;
Chris@45 841 bool modelOk = false;
Chris@45 842 modelId = attributes.value("model").trimmed().toInt(&modelOk);
Chris@45 843
Chris@45 844 if (modelOk) {
Chris@45 845 if (haveModel(modelId)) {
Chris@45 846 Model *model = m_models[modelId];
Chris@45 847 m_document->setModel(layer, model);
Chris@45 848 } else {
Chris@45 849 std::cerr << "WARNING: SV-XML: Unknown model id " << modelId
Chris@45 850 << " in layer definition" << std::endl;
Chris@45 851 }
Chris@45 852 }
Chris@45 853
Chris@45 854 layer->setProperties(attributes);
Chris@45 855 }
Chris@45 856
Chris@45 857 if (!m_inData && m_currentPane) {
Chris@45 858
Chris@45 859 QString visible = attributes.value("visible");
Chris@45 860 bool dormant = (visible == "false");
Chris@45 861
Chris@45 862 // We need to do this both before and after adding the layer
Chris@45 863 // to the view -- we need it to be dormant if appropriate
Chris@45 864 // before it's actually added to the view so that any property
Chris@45 865 // box gets the right state when it's added, but the add layer
Chris@45 866 // command sets dormant to false because it assumes it may be
Chris@45 867 // restoring a previously dormant layer, so we need to set it
Chris@45 868 // again afterwards too. Hm
Chris@45 869 layer->setLayerDormant(m_currentPane, dormant);
Chris@45 870
Chris@45 871 m_document->addLayerToView(m_currentPane, layer);
Chris@45 872
Chris@45 873 layer->setLayerDormant(m_currentPane, dormant);
Chris@45 874 }
Chris@45 875
Chris@45 876 m_currentLayer = layer;
Chris@45 877 m_inLayer = true;
Chris@45 878
Chris@45 879 return true;
Chris@45 880 }
Chris@45 881
Chris@45 882 bool
Chris@45 883 SVFileReader::readDatasetStart(const QXmlAttributes &attributes)
Chris@45 884 {
Chris@45 885 bool ok = false;
Chris@45 886
Chris@45 887 READ_MANDATORY(int, id, toInt);
Chris@45 888 READ_MANDATORY(int, dimensions, toInt);
Chris@45 889
Chris@45 890 if (m_awaitingDatasets.find(id) == m_awaitingDatasets.end()) {
Chris@45 891 std::cerr << "WARNING: SV-XML: Unwanted dataset " << id << std::endl;
Chris@45 892 return false;
Chris@45 893 }
Chris@45 894
Chris@45 895 int modelId = m_awaitingDatasets[id];
Chris@45 896
Chris@45 897 Model *model = 0;
Chris@45 898 if (haveModel(modelId)) {
Chris@45 899 model = m_models[modelId];
Chris@45 900 } else {
Chris@45 901 std::cerr << "WARNING: SV-XML: Internal error: Unknown model " << modelId
Chris@45 902 << " expecting dataset " << id << std::endl;
Chris@45 903 return false;
Chris@45 904 }
Chris@45 905
Chris@45 906 bool good = false;
Chris@45 907
Chris@45 908 switch (dimensions) {
Chris@45 909 case 1:
Chris@45 910 if (dynamic_cast<SparseOneDimensionalModel *>(model)) good = true;
Chris@45 911 else if (dynamic_cast<ImageModel *>(model)) good = true;
Chris@45 912 break;
Chris@45 913
Chris@45 914 case 2:
Chris@45 915 if (dynamic_cast<SparseTimeValueModel *>(model)) good = true;
Chris@45 916 else if (dynamic_cast<TextModel *>(model)) good = true;
Chris@111 917 else if (dynamic_cast<PathModel *>(model)) good = true;
Chris@45 918 break;
Chris@45 919
Chris@45 920 case 3:
Chris@45 921 if (dynamic_cast<NoteModel *>(model)) good = true;
Chris@137 922 else if (dynamic_cast<RegionModel *>(model)) good = true;
Chris@45 923 else if (dynamic_cast<EditableDenseThreeDimensionalModel *>(model)) {
Chris@45 924 m_datasetSeparator = attributes.value("separator");
Chris@45 925 good = true;
Chris@45 926 }
Chris@45 927 break;
Chris@45 928 }
Chris@45 929
Chris@45 930 if (!good) {
Chris@45 931 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 932 m_currentDataset = 0;
Chris@45 933 return false;
Chris@45 934 }
Chris@45 935
Chris@45 936 m_currentDataset = model;
Chris@45 937 return true;
Chris@45 938 }
Chris@45 939
Chris@45 940 bool
Chris@45 941 SVFileReader::addPointToDataset(const QXmlAttributes &attributes)
Chris@45 942 {
Chris@45 943 bool ok = false;
Chris@45 944
Chris@45 945 READ_MANDATORY(int, frame, toInt);
Chris@45 946
Chris@45 947 // std::cerr << "SVFileReader::addPointToDataset: frame = " << frame << std::endl;
Chris@45 948
Chris@45 949 SparseOneDimensionalModel *sodm = dynamic_cast<SparseOneDimensionalModel *>
Chris@45 950 (m_currentDataset);
Chris@45 951
Chris@45 952 if (sodm) {
Chris@45 953 // std::cerr << "Current dataset is a sparse one dimensional model" << std::endl;
Chris@45 954 QString label = attributes.value("label");
Chris@45 955 sodm->addPoint(SparseOneDimensionalModel::Point(frame, label));
Chris@45 956 return true;
Chris@45 957 }
Chris@45 958
Chris@45 959 SparseTimeValueModel *stvm = dynamic_cast<SparseTimeValueModel *>
Chris@45 960 (m_currentDataset);
Chris@45 961
Chris@45 962 if (stvm) {
Chris@45 963 // std::cerr << "Current dataset is a sparse time-value model" << std::endl;
Chris@45 964 float value = 0.0;
Chris@45 965 value = attributes.value("value").trimmed().toFloat(&ok);
Chris@45 966 QString label = attributes.value("label");
Chris@45 967 stvm->addPoint(SparseTimeValueModel::Point(frame, value, label));
Chris@45 968 return ok;
Chris@45 969 }
Chris@45 970
Chris@45 971 NoteModel *nm = dynamic_cast<NoteModel *>(m_currentDataset);
Chris@45 972
Chris@45 973 if (nm) {
Chris@45 974 // std::cerr << "Current dataset is a note model" << std::endl;
Chris@45 975 float value = 0.0;
Chris@45 976 value = attributes.value("value").trimmed().toFloat(&ok);
Chris@45 977 size_t duration = 0;
Chris@45 978 duration = attributes.value("duration").trimmed().toUInt(&ok);
Chris@45 979 QString label = attributes.value("label");
Chris@61 980 float level = attributes.value("level").trimmed().toFloat(&ok);
Chris@61 981 if (!ok) { // level is optional
Chris@61 982 level = 1.f;
Chris@61 983 ok = true;
Chris@61 984 }
Chris@61 985 nm->addPoint(NoteModel::Point(frame, value, duration, level, label));
Chris@45 986 return ok;
Chris@45 987 }
Chris@45 988
Chris@137 989 RegionModel *rm = dynamic_cast<RegionModel *>(m_currentDataset);
Chris@137 990
Chris@137 991 if (rm) {
Chris@137 992 // std::cerr << "Current dataset is a note model" << std::endl;
Chris@137 993 float value = 0.0;
Chris@137 994 value = attributes.value("value").trimmed().toFloat(&ok);
Chris@137 995 size_t duration = 0;
Chris@137 996 duration = attributes.value("duration").trimmed().toUInt(&ok);
Chris@137 997 QString label = attributes.value("label");
Chris@137 998 rm->addPoint(RegionModel::Point(frame, value, duration, label));
Chris@137 999 return ok;
Chris@137 1000 }
Chris@137 1001
Chris@45 1002 TextModel *tm = dynamic_cast<TextModel *>(m_currentDataset);
Chris@45 1003
Chris@45 1004 if (tm) {
Chris@45 1005 // std::cerr << "Current dataset is a text model" << std::endl;
Chris@45 1006 float height = 0.0;
Chris@45 1007 height = attributes.value("height").trimmed().toFloat(&ok);
Chris@45 1008 QString label = attributes.value("label");
Chris@45 1009 // std::cerr << "SVFileReader::addPointToDataset: TextModel: frame = " << frame << ", height = " << height << ", label = " << label.toStdString() << ", ok = " << ok << std::endl;
Chris@45 1010 tm->addPoint(TextModel::Point(frame, height, label));
Chris@45 1011 return ok;
Chris@45 1012 }
Chris@45 1013
Chris@111 1014 PathModel *pm = dynamic_cast<PathModel *>(m_currentDataset);
Chris@111 1015
Chris@111 1016 if (pm) {
Chris@111 1017 // std::cerr << "Current dataset is a path model" << std::endl;
Chris@111 1018 int mapframe = attributes.value("mapframe").trimmed().toInt(&ok);
Chris@111 1019 // std::cerr << "SVFileReader::addPointToDataset: PathModel: frame = " << frame << ", mapframe = " << mapframe << ", ok = " << ok << std::endl;
Chris@111 1020 pm->addPoint(PathModel::Point(frame, mapframe));
Chris@111 1021 return ok;
Chris@111 1022 }
Chris@111 1023
Chris@45 1024 ImageModel *im = dynamic_cast<ImageModel *>(m_currentDataset);
Chris@45 1025
Chris@45 1026 if (im) {
Chris@45 1027 // std::cerr << "Current dataset is an image model" << std::endl;
Chris@45 1028 QString image = attributes.value("image");
Chris@45 1029 QString label = attributes.value("label");
Chris@45 1030 // std::cerr << "SVFileReader::addPointToDataset: ImageModel: frame = " << frame << ", image = " << image.toStdString() << ", label = " << label.toStdString() << ", ok = " << ok << std::endl;
Chris@45 1031 im->addPoint(ImageModel::Point(frame, image, label));
Chris@45 1032 return ok;
Chris@45 1033 }
Chris@45 1034
Chris@45 1035 std::cerr << "WARNING: SV-XML: Point element found in non-point dataset" << std::endl;
Chris@45 1036
Chris@45 1037 return false;
Chris@45 1038 }
Chris@45 1039
Chris@45 1040 bool
Chris@45 1041 SVFileReader::addBinToDataset(const QXmlAttributes &attributes)
Chris@45 1042 {
Chris@45 1043 EditableDenseThreeDimensionalModel *dtdm =
Chris@45 1044 dynamic_cast<EditableDenseThreeDimensionalModel *>
Chris@45 1045 (m_currentDataset);
Chris@45 1046
Chris@45 1047 if (dtdm) {
Chris@45 1048
Chris@45 1049 bool ok = false;
Chris@45 1050 int n = attributes.value("number").trimmed().toInt(&ok);
Chris@45 1051 if (!ok) {
Chris@45 1052 std::cerr << "WARNING: SV-XML: Missing or invalid bin number"
Chris@45 1053 << std::endl;
Chris@45 1054 return false;
Chris@45 1055 }
Chris@45 1056
Chris@45 1057 QString name = attributes.value("name");
Chris@45 1058
Chris@45 1059 dtdm->setBinName(n, name);
Chris@45 1060 return true;
Chris@45 1061 }
Chris@45 1062
Chris@45 1063 std::cerr << "WARNING: SV-XML: Bin definition found in incompatible dataset" << std::endl;
Chris@45 1064
Chris@45 1065 return false;
Chris@45 1066 }
Chris@45 1067
Chris@45 1068
Chris@45 1069 bool
Chris@45 1070 SVFileReader::addRowToDataset(const QXmlAttributes &attributes)
Chris@45 1071 {
Chris@45 1072 m_inRow = false;
Chris@45 1073
Chris@45 1074 bool ok = false;
Chris@45 1075 m_rowNumber = attributes.value("n").trimmed().toInt(&ok);
Chris@45 1076 if (!ok) {
Chris@45 1077 std::cerr << "WARNING: SV-XML: Missing or invalid row number"
Chris@45 1078 << std::endl;
Chris@45 1079 return false;
Chris@45 1080 }
Chris@45 1081
Chris@45 1082 m_inRow = true;
Chris@45 1083
Chris@45 1084 // std::cerr << "SV-XML: In row " << m_rowNumber << std::endl;
Chris@45 1085
Chris@45 1086 return true;
Chris@45 1087 }
Chris@45 1088
Chris@45 1089 bool
Chris@45 1090 SVFileReader::readRowData(const QString &text)
Chris@45 1091 {
Chris@45 1092 EditableDenseThreeDimensionalModel *dtdm =
Chris@45 1093 dynamic_cast<EditableDenseThreeDimensionalModel *>
Chris@45 1094 (m_currentDataset);
Chris@45 1095
Chris@45 1096 bool warned = false;
Chris@45 1097
Chris@45 1098 if (dtdm) {
Chris@45 1099 QStringList data = text.split(m_datasetSeparator);
Chris@45 1100
Chris@45 1101 DenseThreeDimensionalModel::Column values;
Chris@45 1102
Chris@45 1103 for (QStringList::iterator i = data.begin(); i != data.end(); ++i) {
Chris@45 1104
Chris@45 1105 if (values.size() == dtdm->getHeight()) {
Chris@45 1106 if (!warned) {
Chris@45 1107 std::cerr << "WARNING: SV-XML: Too many y-bins in 3-D dataset row "
Chris@45 1108 << m_rowNumber << std::endl;
Chris@45 1109 warned = true;
Chris@45 1110 }
Chris@45 1111 }
Chris@45 1112
Chris@45 1113 bool ok;
Chris@45 1114 float value = i->toFloat(&ok);
Chris@45 1115 if (!ok) {
Chris@45 1116 std::cerr << "WARNING: SV-XML: Bad floating-point value "
Chris@45 1117 << i->toLocal8Bit().data()
Chris@45 1118 << " in row data" << std::endl;
Chris@45 1119 } else {
Chris@45 1120 values.push_back(value);
Chris@45 1121 }
Chris@45 1122 }
Chris@45 1123
Chris@45 1124 dtdm->setColumn(m_rowNumber, values);
Chris@45 1125 return true;
Chris@45 1126 }
Chris@45 1127
Chris@45 1128 std::cerr << "WARNING: SV-XML: Row data found in non-row dataset" << std::endl;
Chris@45 1129
Chris@45 1130 return false;
Chris@45 1131 }
Chris@45 1132
Chris@45 1133 bool
Chris@45 1134 SVFileReader::readDerivation(const QXmlAttributes &attributes)
Chris@45 1135 {
Chris@45 1136 int modelId = 0;
Chris@45 1137 bool modelOk = false;
Chris@45 1138 modelId = attributes.value("model").trimmed().toInt(&modelOk);
Chris@45 1139
Chris@45 1140 if (!modelOk) {
Chris@45 1141 std::cerr << "WARNING: SV-XML: No model id specified for derivation" << std::endl;
Chris@45 1142 return false;
Chris@45 1143 }
Chris@45 1144
Chris@45 1145 if (haveModel(modelId)) {
Chris@45 1146 m_currentDerivedModel = m_models[modelId];
Chris@45 1147 } else {
Chris@45 1148 // we'll regenerate the model when the derivation element ends
Chris@45 1149 m_currentDerivedModel = 0;
Chris@45 1150 }
Chris@45 1151
Chris@45 1152 m_currentDerivedModelId = modelId;
Chris@45 1153
Chris@45 1154 int sourceId = 0;
Chris@45 1155 bool sourceOk = false;
Chris@45 1156 sourceId = attributes.value("source").trimmed().toInt(&sourceOk);
Chris@45 1157
Chris@45 1158 if (sourceOk && haveModel(sourceId)) {
Chris@72 1159 m_currentTransformSource = m_models[sourceId];
Chris@45 1160 } else {
Chris@72 1161 m_currentTransformSource = m_document->getMainModel();
Chris@45 1162 }
Chris@45 1163
Chris@72 1164 m_currentTransform = Transform();
Chris@45 1165
Chris@45 1166 bool ok = false;
Chris@45 1167 int channel = attributes.value("channel").trimmed().toInt(&ok);
Chris@72 1168 if (ok) m_currentTransformChannel = channel;
Chris@72 1169 else m_currentTransformChannel = -1;
Chris@45 1170
Chris@72 1171 QString type = attributes.value("type");
Chris@72 1172
Chris@72 1173 if (type == "transform") {
Chris@72 1174 m_currentTransformIsNewStyle = true;
Chris@72 1175 return true;
Chris@72 1176 } else {
Chris@72 1177 m_currentTransformIsNewStyle = false;
Chris@72 1178 std::cerr << "NOTE: SV-XML: Reading old-style derivation element"
Chris@72 1179 << std::endl;
Chris@72 1180 }
Chris@72 1181
Chris@72 1182 QString transformId = attributes.value("transform");
Chris@72 1183
Chris@72 1184 m_currentTransform.setIdentifier(transformId);
Chris@45 1185
Chris@45 1186 int stepSize = attributes.value("stepSize").trimmed().toInt(&ok);
Chris@72 1187 if (ok) m_currentTransform.setStepSize(stepSize);
Chris@45 1188
Chris@45 1189 int blockSize = attributes.value("blockSize").trimmed().toInt(&ok);
Chris@72 1190 if (ok) m_currentTransform.setBlockSize(blockSize);
Chris@45 1191
Chris@45 1192 int windowType = attributes.value("windowType").trimmed().toInt(&ok);
Chris@72 1193 if (ok) m_currentTransform.setWindowType(WindowType(windowType));
Chris@72 1194
Chris@72 1195 if (!m_currentTransformSource) return true;
Chris@45 1196
Chris@45 1197 QString startFrameStr = attributes.value("startFrame");
Chris@45 1198 QString durationStr = attributes.value("duration");
Chris@45 1199
Chris@45 1200 size_t startFrame = 0;
Chris@45 1201 size_t duration = 0;
Chris@45 1202
Chris@45 1203 if (startFrameStr != "") {
Chris@45 1204 startFrame = startFrameStr.trimmed().toInt(&ok);
Chris@45 1205 if (!ok) startFrame = 0;
Chris@45 1206 }
Chris@45 1207 if (durationStr != "") {
Chris@45 1208 duration = durationStr.trimmed().toInt(&ok);
Chris@45 1209 if (!ok) duration = 0;
Chris@45 1210 }
Chris@45 1211
Chris@72 1212 m_currentTransform.setStartTime
Chris@72 1213 (RealTime::frame2RealTime
Chris@72 1214 (startFrame, m_currentTransformSource->getSampleRate()));
Chris@72 1215
Chris@72 1216 m_currentTransform.setDuration
Chris@72 1217 (RealTime::frame2RealTime
Chris@72 1218 (duration, m_currentTransformSource->getSampleRate()));
Chris@45 1219
Chris@45 1220 return true;
Chris@45 1221 }
Chris@45 1222
Chris@45 1223 bool
Chris@45 1224 SVFileReader::readPlayParameters(const QXmlAttributes &attributes)
Chris@45 1225 {
Chris@45 1226 m_currentPlayParameters = 0;
Chris@45 1227
Chris@45 1228 int modelId = 0;
Chris@45 1229 bool modelOk = false;
Chris@45 1230 modelId = attributes.value("model").trimmed().toInt(&modelOk);
Chris@45 1231
Chris@45 1232 if (!modelOk) {
Chris@45 1233 std::cerr << "WARNING: SV-XML: No model id specified for play parameters" << std::endl;
Chris@45 1234 return false;
Chris@45 1235 }
Chris@45 1236
Chris@45 1237 if (haveModel(modelId)) {
Chris@45 1238
Chris@45 1239 bool ok = false;
Chris@45 1240
Chris@45 1241 PlayParameters *parameters = PlayParameterRepository::getInstance()->
Chris@45 1242 getPlayParameters(m_models[modelId]);
Chris@45 1243
Chris@45 1244 if (!parameters) {
Chris@45 1245 std::cerr << "WARNING: SV-XML: Play parameters for model "
Chris@45 1246 << modelId
Chris@45 1247 << " not found - has model been added to document?"
Chris@45 1248 << std::endl;
Chris@45 1249 return false;
Chris@45 1250 }
Chris@45 1251
Chris@45 1252 bool muted = (attributes.value("mute").trimmed() == "true");
Chris@45 1253 parameters->setPlayMuted(muted);
Chris@45 1254
Chris@45 1255 float pan = attributes.value("pan").toFloat(&ok);
Chris@45 1256 if (ok) parameters->setPlayPan(pan);
Chris@45 1257
Chris@45 1258 float gain = attributes.value("gain").toFloat(&ok);
Chris@45 1259 if (ok) parameters->setPlayGain(gain);
Chris@45 1260
Chris@45 1261 QString pluginId = attributes.value("pluginId");
Chris@45 1262 if (pluginId != "") parameters->setPlayPluginId(pluginId);
Chris@45 1263
Chris@45 1264 m_currentPlayParameters = parameters;
Chris@45 1265
Chris@45 1266 // std::cerr << "Current play parameters for model: " << m_models[modelId] << ": " << m_currentPlayParameters << std::endl;
Chris@45 1267
Chris@45 1268 } else {
Chris@45 1269
Chris@45 1270 std::cerr << "WARNING: SV-XML: Unknown model " << modelId
Chris@45 1271 << " for play parameters" << std::endl;
Chris@45 1272 return false;
Chris@45 1273 }
Chris@45 1274
Chris@45 1275 return true;
Chris@45 1276 }
Chris@45 1277
Chris@45 1278 bool
Chris@45 1279 SVFileReader::readPlugin(const QXmlAttributes &attributes)
Chris@45 1280 {
Chris@45 1281 if (m_currentDerivedModelId < 0 && !m_currentPlayParameters) {
Chris@45 1282 std::cerr << "WARNING: SV-XML: Plugin found outside derivation or play parameters" << std::endl;
Chris@45 1283 return false;
Chris@45 1284 }
Chris@45 1285
Chris@72 1286 if (!m_currentPlayParameters && m_currentTransformIsNewStyle) {
Chris@72 1287 return true;
Chris@72 1288 }
Chris@72 1289
Chris@45 1290 QString configurationXml = "<plugin";
Chris@45 1291
Chris@45 1292 for (int i = 0; i < attributes.length(); ++i) {
Chris@45 1293 configurationXml += QString(" %1=\"%2\"")
Chris@45 1294 .arg(attributes.qName(i))
Chris@45 1295 .arg(XmlExportable::encodeEntities(attributes.value(i)));
Chris@45 1296 }
Chris@45 1297
Chris@45 1298 configurationXml += "/>";
Chris@45 1299
Chris@45 1300 if (m_currentPlayParameters) {
Chris@45 1301 m_currentPlayParameters->setPlayPluginConfiguration(configurationXml);
Chris@45 1302 } else {
Chris@72 1303 TransformFactory::getInstance()->
Chris@72 1304 setParametersFromPluginConfigurationXml(m_currentTransform,
Chris@72 1305 configurationXml);
Chris@45 1306 }
Chris@45 1307
Chris@45 1308 return true;
Chris@45 1309 }
Chris@45 1310
Chris@45 1311 bool
Chris@72 1312 SVFileReader::readTransform(const QXmlAttributes &attributes)
Chris@72 1313 {
Chris@72 1314 if (m_currentDerivedModelId < 0) {
Chris@72 1315 std::cerr << "WARNING: SV-XML: Transform found outside derivation" << std::endl;
Chris@72 1316 return false;
Chris@72 1317 }
Chris@72 1318
Chris@82 1319 m_currentTransform = Transform();
Chris@72 1320 m_currentTransform.setFromXmlAttributes(attributes);
Chris@72 1321 return true;
Chris@72 1322 }
Chris@72 1323
Chris@72 1324 bool
Chris@72 1325 SVFileReader::readParameter(const QXmlAttributes &attributes)
Chris@72 1326 {
Chris@72 1327 if (m_currentDerivedModelId < 0) {
Chris@72 1328 std::cerr << "WARNING: SV-XML: Parameter found outside derivation" << std::endl;
Chris@72 1329 return false;
Chris@72 1330 }
Chris@72 1331
Chris@72 1332 QString name = attributes.value("name");
Chris@72 1333 if (name == "") {
Chris@72 1334 std::cerr << "WARNING: SV-XML: Ignoring nameless transform parameter"
Chris@72 1335 << std::endl;
Chris@72 1336 return false;
Chris@72 1337 }
Chris@72 1338
Chris@72 1339 float value = attributes.value("value").trimmed().toFloat();
Chris@72 1340
Chris@72 1341 m_currentTransform.setParameter(name, value);
Chris@72 1342 return true;
Chris@72 1343 }
Chris@72 1344
Chris@72 1345 bool
Chris@45 1346 SVFileReader::readSelection(const QXmlAttributes &attributes)
Chris@45 1347 {
Chris@45 1348 bool ok;
Chris@45 1349
Chris@45 1350 READ_MANDATORY(int, start, toInt);
Chris@45 1351 READ_MANDATORY(int, end, toInt);
Chris@45 1352
Chris@45 1353 m_paneCallback.addSelection(start, end);
Chris@45 1354
Chris@45 1355 return true;
Chris@45 1356 }
Chris@45 1357
Chris@45 1358 bool
Chris@45 1359 SVFileReader::readMeasurement(const QXmlAttributes &attributes)
Chris@45 1360 {
Chris@45 1361 std::cerr << "SVFileReader::readMeasurement: inLayer "
Chris@45 1362 << m_inLayer << ", layer " << m_currentLayer << std::endl;
Chris@45 1363
Chris@45 1364 if (!m_inLayer) {
Chris@45 1365 std::cerr << "WARNING: SV-XML: Measurement found outside layer" << std::endl;
Chris@45 1366 return false;
Chris@45 1367 }
Chris@45 1368
Chris@45 1369 m_currentLayer->addMeasurementRect(attributes);
Chris@45 1370 return true;
Chris@45 1371 }
Chris@45 1372
Chris@45 1373 SVFileReaderPaneCallback::~SVFileReaderPaneCallback()
Chris@45 1374 {
Chris@45 1375 }
Chris@45 1376
Chris@140 1377
Chris@140 1378 class SVFileIdentifier : public QXmlDefaultHandler
Chris@140 1379 {
Chris@140 1380 public:
Chris@140 1381 SVFileIdentifier() :
Chris@140 1382 m_inSv(false),
Chris@140 1383 m_inData(false),
Chris@140 1384 m_type(SVFileReader::UnknownFileType)
Chris@140 1385 { }
Chris@140 1386 virtual ~SVFileIdentifier() { }
Chris@140 1387
Chris@140 1388 void parse(QXmlInputSource &source) {
Chris@140 1389 QXmlSimpleReader reader;
Chris@140 1390 reader.setContentHandler(this);
Chris@140 1391 reader.setErrorHandler(this);
Chris@140 1392 reader.parse(source);
Chris@140 1393 }
Chris@140 1394
Chris@140 1395 SVFileReader::FileType getType() const { return m_type; }
Chris@140 1396
Chris@140 1397 virtual bool startElement(const QString &,
Chris@140 1398 const QString &,
Chris@140 1399 const QString &qName,
Chris@140 1400 const QXmlAttributes& atts)
Chris@140 1401 {
Chris@140 1402 QString name = qName.toLower();
Chris@140 1403
Chris@140 1404 // SV session files have an sv element containing a data
Chris@140 1405 // element containing a model element with mainModel="true".
Chris@140 1406
Chris@140 1407 // If the sv element is present but the rest does not satisfy,
Chris@140 1408 // then it's (probably) an SV layer file.
Chris@140 1409
Chris@140 1410 // Otherwise, it's of unknown type.
Chris@140 1411
Chris@140 1412 if (name == "sv") {
Chris@140 1413 m_inSv = true;
Chris@140 1414 if (m_type == SVFileReader::UnknownFileType) {
Chris@140 1415 m_type = SVFileReader::SVLayerFile;
Chris@140 1416 }
Chris@140 1417 return true;
Chris@140 1418 } else if (name == "data") {
Chris@140 1419 if (!m_inSv) return true;
Chris@140 1420 m_inData = true;
Chris@140 1421 } else if (name == "model") {
Chris@140 1422 if (!m_inData) return true;
Chris@140 1423 if (atts.value("mainModel").trimmed() == "true") {
Chris@140 1424 if (m_type == SVFileReader::SVLayerFile) {
Chris@140 1425 m_type = SVFileReader::SVSessionFile;
Chris@140 1426 return false; // done
Chris@140 1427 }
Chris@140 1428 }
Chris@140 1429 }
Chris@140 1430 return true;
Chris@140 1431 }
Chris@140 1432
Chris@140 1433 virtual bool endElement(const QString &,
Chris@140 1434 const QString &,
Chris@140 1435 const QString &qName)
Chris@140 1436 {
Chris@140 1437 QString name = qName.toLower();
Chris@140 1438
Chris@140 1439 if (name == "sv") {
Chris@140 1440 if (m_inSv) {
Chris@140 1441 m_inSv = false;
Chris@140 1442 return false; // done
Chris@140 1443 }
Chris@140 1444 } else if (name == "data") {
Chris@140 1445 if (m_inData) {
Chris@140 1446 m_inData = false;
Chris@140 1447 return false; // also done, nothing after the first
Chris@140 1448 // data element is of use here
Chris@140 1449 }
Chris@140 1450 }
Chris@140 1451 return true;
Chris@140 1452 }
Chris@140 1453
Chris@140 1454 private:
Chris@140 1455 bool m_inSv;
Chris@140 1456 bool m_inData;
Chris@140 1457 SVFileReader::FileType m_type;
Chris@140 1458 };
Chris@140 1459
Chris@140 1460
Chris@140 1461 SVFileReader::FileType
Chris@140 1462 SVFileReader::identifyXmlFile(QString path)
Chris@140 1463 {
Chris@140 1464 QFile file(path);
Chris@140 1465 SVFileIdentifier identifier;
Chris@140 1466 QXmlInputSource source(&file);
Chris@140 1467 identifier.parse(source);
Chris@140 1468 return identifier.getType();
Chris@140 1469 }
Chris@140 1470
Chris@140 1471
Chris@140 1472