annotate framework/SVFileReader.cpp @ 140:9ccaa8fd9b9f

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