annotate framework/SVFileReader.cpp @ 180:84b2c1a4984a

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