annotate document/SVFileReader.cpp @ 88:51be0daa1386

Several changes related to referring to remote URLs for sessions and files: * Pull file dialog wrapper functions out from MainWindow into FileFinder * If a file referred to in a session is not found at its expected location, try a few other alternatives (same location as the session file or same location as the last audio file) before asking the user to locate it * Allow user to give a URL when locating an audio file, not just locate on the filesystem * Make wave file models remember the "original" location (e.g. URL) of the audio file, not just the actual location from which the data was loaded (e.g. local copy of that URL) -- when saving a session, use the original location so as not to refer to a temporary file * Clean up incompletely-downloaded local copies of files
author Chris Cannam
date Thu, 11 Jan 2007 13:29:58 +0000
parents 8944f3005a15
children e6c4b27cba2c
rev   line source
Chris@0 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@0 2
Chris@0 3 /*
Chris@0 4 Sonic Visualiser
Chris@0 5 An audio file viewer and annotation editor.
Chris@0 6 Centre for Digital Music, Queen Mary, University of London.
Chris@77 7 This file copyright 2006 Chris Cannam and QMUL.
Chris@0 8
Chris@0 9 This program is free software; you can redistribute it and/or
Chris@0 10 modify it under the terms of the GNU General Public License as
Chris@0 11 published by the Free Software Foundation; either version 2 of the
Chris@0 12 License, or (at your option) any later version. See the file
Chris@0 13 COPYING included with this distribution for more information.
Chris@0 14 */
Chris@0 15
Chris@0 16 #include "SVFileReader.h"
Chris@0 17
Chris@1 18 #include "layer/Layer.h"
Chris@1 19 #include "view/View.h"
Chris@0 20 #include "base/PlayParameters.h"
Chris@0 21 #include "base/PlayParameterRepository.h"
Chris@0 22
Chris@1 23 #include "data/fileio/AudioFileReaderFactory.h"
Chris@87 24 #include "data/fileio/FileFinder.h"
Chris@87 25 #include "data/fileio/RemoteFile.h"
Chris@0 26
Chris@1 27 #include "data/model/WaveFileModel.h"
Chris@3 28 #include "data/model/EditableDenseThreeDimensionalModel.h"
Chris@1 29 #include "data/model/SparseOneDimensionalModel.h"
Chris@1 30 #include "data/model/SparseTimeValueModel.h"
Chris@1 31 #include "data/model/NoteModel.h"
Chris@1 32 #include "data/model/TextModel.h"
Chris@0 33
Chris@1 34 #include "view/Pane.h"
Chris@0 35
Chris@1 36 #include "Document.h"
Chris@0 37
Chris@0 38 #include <QString>
Chris@0 39 #include <QMessageBox>
Chris@0 40 #include <QFileDialog>
Chris@0 41
Chris@0 42 #include <iostream>
Chris@0 43
Chris@55 44 /*
Chris@55 45 Some notes about the SV XML format. We're very lazy with our XML:
Chris@55 46 there's no schema or DTD, and we depend heavily on elements being
Chris@55 47 in a particular order.
Chris@55 48
Chris@55 49 <sv>
Chris@55 50
Chris@55 51 <data>
Chris@55 52
Chris@55 53 <!-- The data section contains definitions of both models and
Chris@55 54 visual layers. Layers are considered data in the document;
Chris@55 55 the structure of views that displays the layers is not. -->
Chris@55 56
Chris@55 57 <!-- id numbers are unique within the data type (i.e. no two
Chris@55 58 models can have the same id, but a model can have the same
Chris@55 59 id as a layer, etc). SV generates its id numbers just for
Chris@55 60 the purpose of cross-referencing within the current file;
Chris@55 61 they don't necessarily have any meaning once the file has
Chris@55 62 been loaded. -->
Chris@55 63
Chris@55 64 <model id="0" name="..." type="..." ... />
Chris@55 65 <model id="1" name="..." type="..." ... />
Chris@55 66
Chris@55 67 <!-- Models that have data associated with them store it
Chris@55 68 in a neighbouring dataset element. The dataset must follow
Chris@55 69 the model and precede any derivation or layer elements that
Chris@55 70 refer to the model. -->
Chris@55 71
Chris@55 72 <model id="2" name="..." type="..." dataset="0" ... />
Chris@55 73
Chris@55 74 <dataset id="0" type="...">
Chris@55 75 <point frame="..." value="..." ... />
Chris@55 76 </dataset>
Chris@55 77
Chris@55 78 <!-- Where one model is derived from another via a transform,
Chris@55 79 it has an associated derivation element. This must follow
Chris@55 80 both the source and target model elements. The source and
Chris@55 81 model attributes give the source model id and target model
Chris@55 82 id respectively. A model can have both dataset and
Chris@55 83 derivation elements; if it does, dataset must appear first.
Chris@55 84 If the model's data are not stored, but instead the model
Chris@55 85 is to be regenerated completely from the transform when
Chris@55 86 the session is reloaded, then the model should have _only_
Chris@55 87 a derivation element, and no model element should appear
Chris@55 88 for it at all. -->
Chris@55 89
Chris@55 90 <derivation source="0" model="2" transform="..." ...>
Chris@55 91 <plugin id="..." ... />
Chris@55 92 </derivation>
Chris@55 93
Chris@55 94 <!-- The playparameters element lists playback settings for
Chris@55 95 a model. -->
Chris@55 96
Chris@55 97 <playparameters mute="false" pan="0" gain="1" model="1" ... />
Chris@55 98
Chris@55 99 <!-- Layer elements. The models must have already been defined.
Chris@55 100 The same model may appear in more than one layer (of more
Chris@55 101 than one type). -->
Chris@55 102
Chris@55 103 <layer id="1" type="..." name="..." model="0" ... />
Chris@55 104 <layer id="2" type="..." name="..." model="1" ... />
Chris@55 105
Chris@55 106 </data>
Chris@55 107
Chris@55 108
Chris@55 109 <display>
Chris@55 110
Chris@55 111 <!-- The display element contains visual structure for the
Chris@55 112 layers. It's simpler than the data section. -->
Chris@55 113
Chris@55 114 <!-- Overall preferred window size for this session. -->
Chris@55 115
Chris@55 116 <window width="..." height="..."/>
Chris@55 117
Chris@55 118 <!-- List of view elements to stack up. Each one contains
Chris@55 119 a list of layers in stacking order, back to front. -->
Chris@55 120
Chris@55 121 <view type="pane" ...>
Chris@55 122 <layer id="1"/>
Chris@55 123 <layer id="2"/>
Chris@55 124 </view>
Chris@55 125
Chris@55 126 <!-- The layer elements just refer to layers defined in the
Chris@55 127 data section, so they don't have to have any attributes
Chris@55 128 other than the id. For sort-of-historical reasons SV
Chris@55 129 actually does repeat the other attributes here, but
Chris@55 130 it doesn't need to. -->
Chris@55 131
Chris@55 132 <view type="pane" ...>
Chris@55 133 <layer id="2"/>
Chris@55 134 <view>
Chris@55 135
Chris@55 136 </display>
Chris@55 137
Chris@55 138
Chris@55 139 <!-- List of selected regions by audio frame extents. -->
Chris@55 140
Chris@55 141 <selections>
Chris@55 142 <selection start="..." end="..."/>
Chris@55 143 </selections>
Chris@55 144
Chris@55 145
Chris@55 146 </sv>
Chris@55 147
Chris@55 148 */
Chris@55 149
Chris@55 150
Chris@0 151 SVFileReader::SVFileReader(Document *document,
Chris@87 152 SVFileReaderPaneCallback &callback,
Chris@87 153 QString location) :
Chris@0 154 m_document(document),
Chris@0 155 m_paneCallback(callback),
Chris@87 156 m_location(location),
Chris@0 157 m_currentPane(0),
Chris@0 158 m_currentDataset(0),
Chris@0 159 m_currentDerivedModel(0),
Chris@55 160 m_currentDerivedModelId(-1),
Chris@0 161 m_currentPlayParameters(0),
Chris@0 162 m_datasetSeparator(" "),
Chris@0 163 m_inRow(false),
Chris@0 164 m_rowNumber(0),
Chris@0 165 m_ok(false)
Chris@0 166 {
Chris@0 167 }
Chris@0 168
Chris@0 169 void
Chris@0 170 SVFileReader::parse(const QString &xmlData)
Chris@0 171 {
Chris@0 172 QXmlInputSource inputSource;
Chris@0 173 inputSource.setData(xmlData);
Chris@0 174 parse(inputSource);
Chris@0 175 }
Chris@0 176
Chris@0 177 void
Chris@0 178 SVFileReader::parse(QXmlInputSource &inputSource)
Chris@0 179 {
Chris@0 180 QXmlSimpleReader reader;
Chris@0 181 reader.setContentHandler(this);
Chris@0 182 reader.setErrorHandler(this);
Chris@0 183 m_ok = reader.parse(inputSource);
Chris@0 184 }
Chris@0 185
Chris@0 186 bool
Chris@0 187 SVFileReader::isOK()
Chris@0 188 {
Chris@0 189 return m_ok;
Chris@0 190 }
Chris@0 191
Chris@0 192 SVFileReader::~SVFileReader()
Chris@0 193 {
Chris@0 194 if (!m_awaitingDatasets.empty()) {
Chris@0 195 std::cerr << "WARNING: SV-XML: File ended with "
Chris@0 196 << m_awaitingDatasets.size() << " unfilled model dataset(s)"
Chris@0 197 << std::endl;
Chris@0 198 }
Chris@0 199
Chris@0 200 std::set<Model *> unaddedModels;
Chris@0 201
Chris@0 202 for (std::map<int, Model *>::iterator i = m_models.begin();
Chris@0 203 i != m_models.end(); ++i) {
Chris@0 204 if (m_addedModels.find(i->second) == m_addedModels.end()) {
Chris@0 205 unaddedModels.insert(i->second);
Chris@0 206 }
Chris@0 207 }
Chris@0 208
Chris@0 209 if (!unaddedModels.empty()) {
Chris@0 210 std::cerr << "WARNING: SV-XML: File contained "
Chris@0 211 << unaddedModels.size() << " unused models"
Chris@0 212 << std::endl;
Chris@0 213 while (!unaddedModels.empty()) {
Chris@0 214 delete *unaddedModels.begin();
Chris@0 215 unaddedModels.erase(unaddedModels.begin());
Chris@0 216 }
Chris@0 217 }
Chris@0 218 }
Chris@0 219
Chris@0 220 bool
Chris@0 221 SVFileReader::startElement(const QString &, const QString &,
Chris@0 222 const QString &qName,
Chris@0 223 const QXmlAttributes &attributes)
Chris@0 224 {
Chris@0 225 QString name = qName.toLower();
Chris@0 226
Chris@0 227 bool ok = false;
Chris@0 228
Chris@0 229 // Valid element names:
Chris@0 230 //
Chris@0 231 // sv
Chris@0 232 // data
Chris@0 233 // dataset
Chris@0 234 // display
Chris@0 235 // derivation
Chris@0 236 // playparameters
Chris@0 237 // layer
Chris@0 238 // model
Chris@0 239 // point
Chris@0 240 // row
Chris@0 241 // view
Chris@0 242 // window
Chris@0 243
Chris@0 244 if (name == "sv") {
Chris@0 245
Chris@0 246 // nothing needed
Chris@0 247 ok = true;
Chris@0 248
Chris@0 249 } else if (name == "data") {
Chris@0 250
Chris@0 251 // nothing needed
Chris@0 252 m_inData = true;
Chris@0 253 ok = true;
Chris@0 254
Chris@0 255 } else if (name == "display") {
Chris@0 256
Chris@0 257 // nothing needed
Chris@0 258 ok = true;
Chris@0 259
Chris@0 260 } else if (name == "window") {
Chris@0 261
Chris@0 262 ok = readWindow(attributes);
Chris@0 263
Chris@0 264 } else if (name == "model") {
Chris@0 265
Chris@0 266 ok = readModel(attributes);
Chris@0 267
Chris@0 268 } else if (name == "dataset") {
Chris@0 269
Chris@0 270 ok = readDatasetStart(attributes);
Chris@0 271
Chris@0 272 } else if (name == "bin") {
Chris@0 273
Chris@0 274 ok = addBinToDataset(attributes);
Chris@0 275
Chris@0 276 } else if (name == "point") {
Chris@0 277
Chris@0 278 ok = addPointToDataset(attributes);
Chris@0 279
Chris@0 280 } else if (name == "row") {
Chris@0 281
Chris@0 282 ok = addRowToDataset(attributes);
Chris@0 283
Chris@0 284 } else if (name == "layer") {
Chris@0 285
Chris@0 286 addUnaddedModels(); // all models must be specified before first layer
Chris@0 287 ok = readLayer(attributes);
Chris@0 288
Chris@0 289 } else if (name == "view") {
Chris@0 290
Chris@0 291 m_inView = true;
Chris@0 292 ok = readView(attributes);
Chris@0 293
Chris@0 294 } else if (name == "derivation") {
Chris@0 295
Chris@0 296 ok = readDerivation(attributes);
Chris@0 297
Chris@0 298 } else if (name == "playparameters") {
Chris@0 299
Chris@0 300 ok = readPlayParameters(attributes);
Chris@0 301
Chris@0 302 } else if (name == "plugin") {
Chris@0 303
Chris@0 304 ok = readPlugin(attributes);
Chris@0 305
Chris@0 306 } else if (name == "selections") {
Chris@0 307
Chris@0 308 m_inSelections = true;
Chris@0 309 ok = true;
Chris@0 310
Chris@0 311 } else if (name == "selection") {
Chris@0 312
Chris@0 313 ok = readSelection(attributes);
Chris@0 314 }
Chris@0 315
Chris@0 316 if (!ok) {
Chris@0 317 std::cerr << "WARNING: SV-XML: Failed to completely process element \""
Chris@0 318 << name.toLocal8Bit().data() << "\"" << std::endl;
Chris@0 319 }
Chris@0 320
Chris@0 321 return true;
Chris@0 322 }
Chris@0 323
Chris@0 324 bool
Chris@0 325 SVFileReader::characters(const QString &text)
Chris@0 326 {
Chris@0 327 bool ok = false;
Chris@0 328
Chris@0 329 if (m_inRow) {
Chris@0 330 ok = readRowData(text);
Chris@0 331 if (!ok) {
Chris@0 332 std::cerr << "WARNING: SV-XML: Failed to read row data content for row " << m_rowNumber << std::endl;
Chris@0 333 }
Chris@0 334 }
Chris@0 335
Chris@0 336 return true;
Chris@0 337 }
Chris@0 338
Chris@0 339 bool
Chris@0 340 SVFileReader::endElement(const QString &, const QString &,
Chris@0 341 const QString &qName)
Chris@0 342 {
Chris@0 343 QString name = qName.toLower();
Chris@0 344
Chris@0 345 if (name == "dataset") {
Chris@0 346
Chris@0 347 if (m_currentDataset) {
Chris@0 348
Chris@0 349 bool foundInAwaiting = false;
Chris@0 350
Chris@0 351 for (std::map<int, int>::iterator i = m_awaitingDatasets.begin();
Chris@0 352 i != m_awaitingDatasets.end(); ++i) {
Chris@0 353 if (m_models[i->second] == m_currentDataset) {
Chris@0 354 m_awaitingDatasets.erase(i);
Chris@0 355 foundInAwaiting = true;
Chris@0 356 break;
Chris@0 357 }
Chris@0 358 }
Chris@0 359
Chris@0 360 if (!foundInAwaiting) {
Chris@0 361 std::cerr << "WARNING: SV-XML: Dataset precedes model, or no model uses dataset" << std::endl;
Chris@0 362 }
Chris@0 363 }
Chris@0 364
Chris@0 365 m_currentDataset = 0;
Chris@0 366
Chris@0 367 } else if (name == "data") {
Chris@0 368
Chris@0 369 addUnaddedModels();
Chris@0 370 m_inData = false;
Chris@0 371
Chris@0 372 } else if (name == "derivation") {
Chris@55 373
Chris@55 374 if (!m_currentDerivedModel) {
Chris@55 375 if (m_currentDerivedModel < 0) {
Chris@55 376 std::cerr << "WARNING: SV-XML: Bad derivation output model id "
Chris@55 377 << m_currentDerivedModelId << std::endl;
Chris@55 378 } else if (m_models[m_currentDerivedModelId]) {
Chris@55 379 std::cerr << "WARNING: SV-XML: Derivation has existing model "
Chris@55 380 << m_currentDerivedModelId
Chris@55 381 << " as target, not regenerating" << std::endl;
Chris@55 382 } else {
Chris@55 383 m_currentDerivedModel = m_models[m_currentDerivedModelId] =
Chris@55 384 m_document->addDerivedModel(m_currentTransform,
Chris@55 385 m_currentTransformSource,
Chris@55 386 m_currentTransformContext,
Chris@55 387 m_currentTransformConfiguration);
Chris@55 388 }
Chris@55 389 } else {
Chris@0 390 m_document->addDerivedModel(m_currentTransform,
Chris@55 391 m_currentTransformSource,
Chris@30 392 m_currentTransformContext,
Chris@0 393 m_currentDerivedModel,
Chris@0 394 m_currentTransformConfiguration);
Chris@0 395 }
Chris@0 396
Chris@55 397 m_addedModels.insert(m_currentDerivedModel);
Chris@55 398 m_currentDerivedModel = 0;
Chris@55 399 m_currentDerivedModelId = -1;
Chris@55 400 m_currentTransform = "";
Chris@55 401 m_currentTransformConfiguration = "";
Chris@55 402
Chris@0 403 } else if (name == "row") {
Chris@0 404 m_inRow = false;
Chris@0 405 } else if (name == "view") {
Chris@0 406 m_inView = false;
Chris@0 407 } else if (name == "selections") {
Chris@0 408 m_inSelections = false;
Chris@0 409 } else if (name == "playparameters") {
Chris@0 410 m_currentPlayParameters = 0;
Chris@0 411 }
Chris@0 412
Chris@0 413 return true;
Chris@0 414 }
Chris@0 415
Chris@0 416 bool
Chris@0 417 SVFileReader::error(const QXmlParseException &exception)
Chris@0 418 {
Chris@0 419 m_errorString =
Chris@0 420 QString("ERROR: SV-XML: %1 at line %2, column %3")
Chris@0 421 .arg(exception.message())
Chris@0 422 .arg(exception.lineNumber())
Chris@0 423 .arg(exception.columnNumber());
Chris@0 424 std::cerr << m_errorString.toLocal8Bit().data() << std::endl;
Chris@0 425 return QXmlDefaultHandler::error(exception);
Chris@0 426 }
Chris@0 427
Chris@0 428 bool
Chris@0 429 SVFileReader::fatalError(const QXmlParseException &exception)
Chris@0 430 {
Chris@0 431 m_errorString =
Chris@0 432 QString("FATAL ERROR: SV-XML: %1 at line %2, column %3")
Chris@0 433 .arg(exception.message())
Chris@0 434 .arg(exception.lineNumber())
Chris@0 435 .arg(exception.columnNumber());
Chris@0 436 std::cerr << m_errorString.toLocal8Bit().data() << std::endl;
Chris@0 437 return QXmlDefaultHandler::fatalError(exception);
Chris@0 438 }
Chris@0 439
Chris@0 440
Chris@0 441 #define READ_MANDATORY(TYPE, NAME, CONVERSION) \
Chris@0 442 TYPE NAME = attributes.value(#NAME).trimmed().CONVERSION(&ok); \
Chris@0 443 if (!ok) { \
Chris@0 444 std::cerr << "WARNING: SV-XML: Missing or invalid mandatory " #TYPE " attribute \"" #NAME "\"" << std::endl; \
Chris@0 445 return false; \
Chris@0 446 }
Chris@0 447
Chris@0 448 bool
Chris@0 449 SVFileReader::readWindow(const QXmlAttributes &attributes)
Chris@0 450 {
Chris@0 451 bool ok = false;
Chris@0 452
Chris@0 453 READ_MANDATORY(int, width, toInt);
Chris@0 454 READ_MANDATORY(int, height, toInt);
Chris@0 455
Chris@0 456 m_paneCallback.setWindowSize(width, height);
Chris@0 457 return true;
Chris@0 458 }
Chris@0 459
Chris@0 460 void
Chris@0 461 SVFileReader::addUnaddedModels()
Chris@0 462 {
Chris@0 463 std::set<Model *> unaddedModels;
Chris@0 464
Chris@0 465 for (std::map<int, Model *>::iterator i = m_models.begin();
Chris@0 466 i != m_models.end(); ++i) {
Chris@0 467 if (m_addedModels.find(i->second) == m_addedModels.end()) {
Chris@0 468 unaddedModels.insert(i->second);
Chris@0 469 }
Chris@0 470 }
Chris@0 471
Chris@0 472 for (std::set<Model *>::iterator i = unaddedModels.begin();
Chris@0 473 i != unaddedModels.end(); ++i) {
Chris@0 474 m_document->addImportedModel(*i);
Chris@0 475 m_addedModels.insert(*i);
Chris@0 476 }
Chris@0 477 }
Chris@0 478
Chris@0 479 bool
Chris@0 480 SVFileReader::readModel(const QXmlAttributes &attributes)
Chris@0 481 {
Chris@0 482 bool ok = false;
Chris@0 483
Chris@0 484 READ_MANDATORY(int, id, toInt);
Chris@0 485
Chris@0 486 if (m_models.find(id) != m_models.end()) {
Chris@0 487 std::cerr << "WARNING: SV-XML: Ignoring duplicate model id " << id
Chris@0 488 << std::endl;
Chris@0 489 return false;
Chris@0 490 }
Chris@0 491
Chris@0 492 QString name = attributes.value("name");
Chris@0 493
Chris@0 494 READ_MANDATORY(int, sampleRate, toInt);
Chris@0 495
Chris@0 496 QString type = attributes.value("type").trimmed();
Chris@0 497 bool mainModel = (attributes.value("mainModel").trimmed() == "true");
Chris@55 498
Chris@0 499 if (type == "wavefile") {
Chris@0 500
Chris@87 501 WaveFileModel *model = 0;
Chris@88 502 FileFinder *ff = FileFinder::getInstance();
Chris@88 503 QString originalPath = attributes.value("file");
Chris@88 504 QString path = ff->find(FileFinder::AudioFile,
Chris@88 505 originalPath, m_location);
Chris@87 506 QUrl url(path);
Chris@87 507
Chris@87 508 if (RemoteFile::canHandleScheme(url)) {
Chris@87 509
Chris@87 510 RemoteFile rf(url);
Chris@87 511 rf.wait();
Chris@87 512
Chris@87 513 if (rf.isOK()) {
Chris@88 514
Chris@88 515 model = new WaveFileModel(rf.getLocalFilename(), path);
Chris@87 516 if (!model->isOK()) {
Chris@87 517 delete model;
Chris@87 518 model = 0;
Chris@87 519 //!!! and delete local file?
Chris@87 520 }
Chris@87 521 }
Chris@87 522 } else {
Chris@87 523
Chris@87 524 model = new WaveFileModel(path);
Chris@87 525 if (!model->isOK()) {
Chris@87 526 delete model;
Chris@87 527 model = 0;
Chris@87 528 }
Chris@87 529 }
Chris@87 530
Chris@87 531 if (!model) return false;
Chris@87 532
Chris@0 533 m_models[id] = model;
Chris@0 534 if (mainModel) {
Chris@0 535 m_document->setMainModel(model);
Chris@0 536 m_addedModels.insert(model);
Chris@0 537 }
Chris@0 538 // Derived models will be added when their derivation
Chris@0 539 // is found.
Chris@0 540
Chris@0 541 return true;
Chris@0 542
Chris@0 543 } else if (type == "dense") {
Chris@0 544
Chris@0 545 READ_MANDATORY(int, dimensions, toInt);
Chris@0 546
Chris@55 547 // Currently the only dense model we support here is the dense
Chris@55 548 // 3d model. Dense time-value models are always file-backed
Chris@55 549 // waveform data, at this point, and they come in as wavefile
Chris@55 550 // models.
Chris@0 551
Chris@0 552 if (dimensions == 3) {
Chris@0 553
Chris@0 554 READ_MANDATORY(int, windowSize, toInt);
Chris@0 555 READ_MANDATORY(int, yBinCount, toInt);
Chris@0 556
Chris@3 557 EditableDenseThreeDimensionalModel *model =
Chris@3 558 new EditableDenseThreeDimensionalModel
Chris@3 559 (sampleRate, windowSize, yBinCount);
Chris@0 560
Chris@0 561 float minimum = attributes.value("minimum").trimmed().toFloat(&ok);
Chris@0 562 if (ok) model->setMinimumLevel(minimum);
Chris@0 563
Chris@0 564 float maximum = attributes.value("maximum").trimmed().toFloat(&ok);
Chris@0 565 if (ok) model->setMaximumLevel(maximum);
Chris@0 566
Chris@0 567 int dataset = attributes.value("dataset").trimmed().toInt(&ok);
Chris@0 568 if (ok) m_awaitingDatasets[dataset] = id;
Chris@0 569
Chris@0 570 m_models[id] = model;
Chris@0 571 return true;
Chris@0 572
Chris@0 573 } else {
Chris@0 574
Chris@0 575 std::cerr << "WARNING: SV-XML: Unexpected dense model dimension ("
Chris@0 576 << dimensions << ")" << std::endl;
Chris@0 577 }
Chris@0 578 } else if (type == "sparse") {
Chris@0 579
Chris@0 580 READ_MANDATORY(int, dimensions, toInt);
Chris@0 581
Chris@0 582 if (dimensions == 1) {
Chris@0 583
Chris@0 584 READ_MANDATORY(int, resolution, toInt);
Chris@0 585
Chris@0 586 SparseOneDimensionalModel *model = new SparseOneDimensionalModel
Chris@0 587 (sampleRate, resolution);
Chris@0 588 m_models[id] = model;
Chris@0 589
Chris@0 590 int dataset = attributes.value("dataset").trimmed().toInt(&ok);
Chris@0 591 if (ok) m_awaitingDatasets[dataset] = id;
Chris@0 592
Chris@0 593 return true;
Chris@0 594
Chris@0 595 } else if (dimensions == 2 || dimensions == 3) {
Chris@0 596
Chris@0 597 READ_MANDATORY(int, resolution, toInt);
Chris@0 598
Chris@0 599 float minimum = attributes.value("minimum").trimmed().toFloat(&ok);
Chris@0 600 float maximum = attributes.value("maximum").trimmed().toFloat(&ok);
Chris@0 601 float valueQuantization =
Chris@0 602 attributes.value("valueQuantization").trimmed().toFloat(&ok);
Chris@0 603
Chris@0 604 bool notifyOnAdd = (attributes.value("notifyOnAdd") == "true");
Chris@0 605
Chris@0 606 QString units = attributes.value("units");
Chris@0 607
Chris@0 608 if (dimensions == 2) {
Chris@0 609 if (attributes.value("subtype") == "text") {
Chris@0 610 TextModel *model = new TextModel
Chris@0 611 (sampleRate, resolution, notifyOnAdd);
Chris@0 612 m_models[id] = model;
Chris@0 613 } else {
Chris@0 614 SparseTimeValueModel *model = new SparseTimeValueModel
Chris@0 615 (sampleRate, resolution, minimum, maximum, notifyOnAdd);
Chris@0 616 model->setScaleUnits(units);
Chris@0 617 m_models[id] = model;
Chris@0 618 }
Chris@0 619 } else {
Chris@0 620 NoteModel *model = new NoteModel
Chris@0 621 (sampleRate, resolution, minimum, maximum, notifyOnAdd);
Chris@0 622 model->setValueQuantization(valueQuantization);
Chris@0 623 model->setScaleUnits(units);
Chris@0 624 m_models[id] = model;
Chris@0 625 }
Chris@0 626
Chris@0 627 int dataset = attributes.value("dataset").trimmed().toInt(&ok);
Chris@0 628 if (ok) m_awaitingDatasets[dataset] = id;
Chris@0 629
Chris@0 630 return true;
Chris@0 631
Chris@0 632 } else {
Chris@0 633
Chris@0 634 std::cerr << "WARNING: SV-XML: Unexpected sparse model dimension ("
Chris@0 635 << dimensions << ")" << std::endl;
Chris@0 636 }
Chris@0 637 } else {
Chris@0 638
Chris@0 639 std::cerr << "WARNING: SV-XML: Unexpected model type \""
Chris@88 640 << type.toLocal8Bit().data() << "\" for model id " << id << std::endl;
Chris@0 641 }
Chris@0 642
Chris@0 643 return false;
Chris@0 644 }
Chris@0 645
Chris@0 646 bool
Chris@0 647 SVFileReader::readView(const QXmlAttributes &attributes)
Chris@0 648 {
Chris@0 649 QString type = attributes.value("type");
Chris@0 650 m_currentPane = 0;
Chris@0 651
Chris@0 652 if (type != "pane") {
Chris@0 653 std::cerr << "WARNING: SV-XML: Unexpected view type \""
Chris@0 654 << type.toLocal8Bit().data() << "\"" << std::endl;
Chris@0 655 return false;
Chris@0 656 }
Chris@0 657
Chris@0 658 m_currentPane = m_paneCallback.addPane();
Chris@0 659
Chris@0 660 if (!m_currentPane) {
Chris@0 661 std::cerr << "WARNING: SV-XML: Internal error: Failed to add pane!"
Chris@0 662 << std::endl;
Chris@0 663 return false;
Chris@0 664 }
Chris@0 665
Chris@0 666 bool ok = false;
Chris@0 667
Chris@0 668 View *view = m_currentPane;
Chris@0 669
Chris@0 670 // The view properties first
Chris@0 671
Chris@0 672 READ_MANDATORY(size_t, centre, toUInt);
Chris@0 673 READ_MANDATORY(size_t, zoom, toUInt);
Chris@0 674 READ_MANDATORY(int, followPan, toInt);
Chris@0 675 READ_MANDATORY(int, followZoom, toInt);
Chris@0 676 READ_MANDATORY(int, light, toInt);
Chris@0 677 QString tracking = attributes.value("tracking");
Chris@0 678
Chris@0 679 // Specify the follow modes before we set the actual values
Chris@0 680 view->setFollowGlobalPan(followPan);
Chris@0 681 view->setFollowGlobalZoom(followZoom);
Chris@0 682 view->setPlaybackFollow(tracking == "scroll" ? View::PlaybackScrollContinuous :
Chris@0 683 tracking == "page" ? View::PlaybackScrollPage
Chris@0 684 : View::PlaybackIgnore);
Chris@0 685
Chris@0 686 // Then set these values
Chris@0 687 view->setCentreFrame(centre);
Chris@0 688 view->setZoomLevel(zoom);
Chris@0 689 view->setLightBackground(light);
Chris@0 690
Chris@0 691 // And pane properties
Chris@0 692 READ_MANDATORY(int, centreLineVisible, toInt);
Chris@0 693 m_currentPane->setCentreLineVisible(centreLineVisible);
Chris@0 694
Chris@0 695 int height = attributes.value("height").toInt(&ok);
Chris@0 696 if (ok) {
Chris@0 697 m_currentPane->resize(m_currentPane->width(), height);
Chris@0 698 }
Chris@0 699
Chris@0 700 return true;
Chris@0 701 }
Chris@0 702
Chris@0 703 bool
Chris@0 704 SVFileReader::readLayer(const QXmlAttributes &attributes)
Chris@0 705 {
Chris@0 706 QString type = attributes.value("type");
Chris@0 707
Chris@0 708 int id;
Chris@0 709 bool ok = false;
Chris@0 710 id = attributes.value("id").trimmed().toInt(&ok);
Chris@0 711
Chris@0 712 if (!ok) {
Chris@0 713 std::cerr << "WARNING: SV-XML: No layer id for layer of type \""
Chris@0 714 << type.toLocal8Bit().data()
Chris@0 715 << "\"" << std::endl;
Chris@0 716 return false;
Chris@0 717 }
Chris@0 718
Chris@0 719 Layer *layer = 0;
Chris@0 720 bool isNewLayer = false;
Chris@0 721
Chris@0 722 // Layers are expected to be defined in layer elements in the data
Chris@0 723 // section, and referred to in layer elements in the view
Chris@0 724 // sections. So if we're in the data section, we expect this
Chris@0 725 // layer not to exist already; if we're in the view section, we
Chris@0 726 // expect it to exist.
Chris@0 727
Chris@0 728 if (m_inData) {
Chris@0 729
Chris@0 730 if (m_layers.find(id) != m_layers.end()) {
Chris@0 731 std::cerr << "WARNING: SV-XML: Ignoring duplicate layer id " << id
Chris@0 732 << " in data section" << std::endl;
Chris@0 733 return false;
Chris@0 734 }
Chris@0 735
Chris@0 736 layer = m_layers[id] = m_document->createLayer
Chris@0 737 (LayerFactory::getInstance()->getLayerTypeForName(type));
Chris@0 738
Chris@0 739 if (layer) {
Chris@0 740 m_layers[id] = layer;
Chris@0 741 isNewLayer = true;
Chris@0 742 }
Chris@0 743
Chris@0 744 } else {
Chris@0 745
Chris@0 746 if (!m_currentPane) {
Chris@0 747 std::cerr << "WARNING: SV-XML: No current pane for layer " << id
Chris@0 748 << " in view section" << std::endl;
Chris@0 749 return false;
Chris@0 750 }
Chris@0 751
Chris@0 752 if (m_layers.find(id) != m_layers.end()) {
Chris@0 753
Chris@0 754 layer = m_layers[id];
Chris@0 755
Chris@0 756 } else {
Chris@0 757 std::cerr << "WARNING: SV-XML: Layer id " << id
Chris@0 758 << " in view section has not been defined -- defining it here"
Chris@0 759 << std::endl;
Chris@0 760
Chris@0 761 layer = m_document->createLayer
Chris@0 762 (LayerFactory::getInstance()->getLayerTypeForName(type));
Chris@0 763
Chris@0 764 if (layer) {
Chris@0 765 m_layers[id] = layer;
Chris@0 766 isNewLayer = true;
Chris@0 767 }
Chris@0 768 }
Chris@0 769 }
Chris@0 770
Chris@0 771 if (!layer) {
Chris@0 772 std::cerr << "WARNING: SV-XML: Failed to add layer of type \""
Chris@0 773 << type.toLocal8Bit().data()
Chris@0 774 << "\"" << std::endl;
Chris@0 775 return false;
Chris@0 776 }
Chris@0 777
Chris@0 778 if (isNewLayer) {
Chris@0 779
Chris@0 780 QString name = attributes.value("name");
Chris@0 781 layer->setObjectName(name);
Chris@0 782
Chris@0 783 int modelId;
Chris@0 784 bool modelOk = false;
Chris@0 785 modelId = attributes.value("model").trimmed().toInt(&modelOk);
Chris@0 786
Chris@0 787 if (modelOk) {
Chris@0 788 if (m_models.find(modelId) != m_models.end()) {
Chris@0 789 Model *model = m_models[modelId];
Chris@0 790 m_document->setModel(layer, model);
Chris@0 791 } else {
Chris@0 792 std::cerr << "WARNING: SV-XML: Unknown model id " << modelId
Chris@0 793 << " in layer definition" << std::endl;
Chris@0 794 }
Chris@0 795 }
Chris@0 796
Chris@0 797 layer->setProperties(attributes);
Chris@0 798 }
Chris@0 799
Chris@0 800 if (!m_inData && m_currentPane) {
Chris@84 801
Chris@84 802 QString visible = attributes.value("visible");
Chris@84 803 bool dormant = (visible == "false");
Chris@84 804
Chris@84 805 // We need to do this both before and after adding the layer
Chris@84 806 // to the view -- we need it to be dormant if appropriate
Chris@84 807 // before it's actually added to the view so that any property
Chris@84 808 // box gets the right state when it's added, but the add layer
Chris@84 809 // command sets dormant to false because it assumes it may be
Chris@84 810 // restoring a previously dormant layer, so we need to set it
Chris@84 811 // again afterwards too. Hm
Chris@84 812 layer->setLayerDormant(m_currentPane, dormant);
Chris@84 813
Chris@0 814 m_document->addLayerToView(m_currentPane, layer);
Chris@84 815
Chris@84 816 layer->setLayerDormant(m_currentPane, dormant);
Chris@0 817 }
Chris@0 818
Chris@0 819 return true;
Chris@0 820 }
Chris@0 821
Chris@0 822 bool
Chris@0 823 SVFileReader::readDatasetStart(const QXmlAttributes &attributes)
Chris@0 824 {
Chris@0 825 bool ok = false;
Chris@0 826
Chris@0 827 READ_MANDATORY(int, id, toInt);
Chris@0 828 READ_MANDATORY(int, dimensions, toInt);
Chris@0 829
Chris@0 830 if (m_awaitingDatasets.find(id) == m_awaitingDatasets.end()) {
Chris@0 831 std::cerr << "WARNING: SV-XML: Unwanted dataset " << id << std::endl;
Chris@0 832 return false;
Chris@0 833 }
Chris@0 834
Chris@0 835 int modelId = m_awaitingDatasets[id];
Chris@0 836
Chris@0 837 Model *model = 0;
Chris@0 838 if (m_models.find(modelId) != m_models.end()) {
Chris@0 839 model = m_models[modelId];
Chris@0 840 } else {
Chris@0 841 std::cerr << "WARNING: SV-XML: Internal error: Unknown model " << modelId
Chris@0 842 << " expecting dataset " << id << std::endl;
Chris@0 843 return false;
Chris@0 844 }
Chris@0 845
Chris@0 846 bool good = false;
Chris@0 847
Chris@0 848 switch (dimensions) {
Chris@0 849 case 1:
Chris@0 850 if (dynamic_cast<SparseOneDimensionalModel *>(model)) good = true;
Chris@0 851 break;
Chris@0 852
Chris@0 853 case 2:
Chris@0 854 if (dynamic_cast<SparseTimeValueModel *>(model)) good = true;
Chris@0 855 else if (dynamic_cast<TextModel *>(model)) good = true;
Chris@0 856 break;
Chris@0 857
Chris@0 858 case 3:
Chris@0 859 if (dynamic_cast<NoteModel *>(model)) good = true;
Chris@3 860 else if (dynamic_cast<EditableDenseThreeDimensionalModel *>(model)) {
Chris@0 861 m_datasetSeparator = attributes.value("separator");
Chris@0 862 good = true;
Chris@0 863 }
Chris@0 864 break;
Chris@0 865 }
Chris@0 866
Chris@0 867 if (!good) {
Chris@0 868 std::cerr << "WARNING: SV-XML: Model id " << modelId << " has wrong number of dimensions for " << dimensions << "-D dataset " << id << std::endl;
Chris@0 869 m_currentDataset = 0;
Chris@0 870 return false;
Chris@0 871 }
Chris@0 872
Chris@0 873 m_currentDataset = model;
Chris@0 874 return true;
Chris@0 875 }
Chris@0 876
Chris@0 877 bool
Chris@0 878 SVFileReader::addPointToDataset(const QXmlAttributes &attributes)
Chris@0 879 {
Chris@0 880 bool ok = false;
Chris@0 881
Chris@0 882 READ_MANDATORY(int, frame, toInt);
Chris@0 883
Chris@0 884 SparseOneDimensionalModel *sodm = dynamic_cast<SparseOneDimensionalModel *>
Chris@0 885 (m_currentDataset);
Chris@0 886
Chris@0 887 if (sodm) {
Chris@0 888 QString label = attributes.value("label");
Chris@0 889 sodm->addPoint(SparseOneDimensionalModel::Point(frame, label));
Chris@0 890 return true;
Chris@0 891 }
Chris@0 892
Chris@0 893 SparseTimeValueModel *stvm = dynamic_cast<SparseTimeValueModel *>
Chris@0 894 (m_currentDataset);
Chris@0 895
Chris@0 896 if (stvm) {
Chris@0 897 float value = 0.0;
Chris@0 898 value = attributes.value("value").trimmed().toFloat(&ok);
Chris@0 899 QString label = attributes.value("label");
Chris@0 900 stvm->addPoint(SparseTimeValueModel::Point(frame, value, label));
Chris@0 901 return ok;
Chris@0 902 }
Chris@0 903
Chris@0 904 NoteModel *nm = dynamic_cast<NoteModel *>(m_currentDataset);
Chris@0 905
Chris@0 906 if (nm) {
Chris@0 907 float value = 0.0;
Chris@0 908 value = attributes.value("value").trimmed().toFloat(&ok);
Chris@0 909 float duration = 0.0;
Chris@0 910 duration = attributes.value("duration").trimmed().toFloat(&ok);
Chris@0 911 QString label = attributes.value("label");
Chris@0 912 nm->addPoint(NoteModel::Point(frame, value, duration, label));
Chris@0 913 return ok;
Chris@0 914 }
Chris@0 915
Chris@0 916 TextModel *tm = dynamic_cast<TextModel *>(m_currentDataset);
Chris@0 917
Chris@0 918 if (tm) {
Chris@0 919 float height = 0.0;
Chris@0 920 height = attributes.value("height").trimmed().toFloat(&ok);
Chris@0 921 QString label = attributes.value("label");
Chris@0 922 tm->addPoint(TextModel::Point(frame, height, label));
Chris@0 923 return ok;
Chris@0 924 }
Chris@0 925
Chris@0 926 std::cerr << "WARNING: SV-XML: Point element found in non-point dataset" << std::endl;
Chris@0 927
Chris@0 928 return false;
Chris@0 929 }
Chris@0 930
Chris@0 931 bool
Chris@0 932 SVFileReader::addBinToDataset(const QXmlAttributes &attributes)
Chris@0 933 {
Chris@3 934 EditableDenseThreeDimensionalModel *dtdm =
Chris@3 935 dynamic_cast<EditableDenseThreeDimensionalModel *>
Chris@0 936 (m_currentDataset);
Chris@0 937
Chris@0 938 if (dtdm) {
Chris@0 939
Chris@0 940 bool ok = false;
Chris@0 941 int n = attributes.value("number").trimmed().toInt(&ok);
Chris@0 942 if (!ok) {
Chris@0 943 std::cerr << "WARNING: SV-XML: Missing or invalid bin number"
Chris@0 944 << std::endl;
Chris@0 945 return false;
Chris@0 946 }
Chris@0 947
Chris@0 948 QString name = attributes.value("name");
Chris@0 949
Chris@0 950 dtdm->setBinName(n, name);
Chris@0 951 return true;
Chris@0 952 }
Chris@0 953
Chris@0 954 std::cerr << "WARNING: SV-XML: Bin definition found in incompatible dataset" << std::endl;
Chris@0 955
Chris@0 956 return false;
Chris@0 957 }
Chris@0 958
Chris@0 959
Chris@0 960 bool
Chris@0 961 SVFileReader::addRowToDataset(const QXmlAttributes &attributes)
Chris@0 962 {
Chris@0 963 m_inRow = false;
Chris@0 964
Chris@0 965 bool ok = false;
Chris@0 966 m_rowNumber = attributes.value("n").trimmed().toInt(&ok);
Chris@0 967 if (!ok) {
Chris@0 968 std::cerr << "WARNING: SV-XML: Missing or invalid row number"
Chris@0 969 << std::endl;
Chris@0 970 return false;
Chris@0 971 }
Chris@0 972
Chris@0 973 m_inRow = true;
Chris@0 974
Chris@0 975 // std::cerr << "SV-XML: In row " << m_rowNumber << std::endl;
Chris@0 976
Chris@0 977 return true;
Chris@0 978 }
Chris@0 979
Chris@0 980 bool
Chris@0 981 SVFileReader::readRowData(const QString &text)
Chris@0 982 {
Chris@3 983 EditableDenseThreeDimensionalModel *dtdm =
Chris@3 984 dynamic_cast<EditableDenseThreeDimensionalModel *>
Chris@0 985 (m_currentDataset);
Chris@0 986
Chris@0 987 bool warned = false;
Chris@0 988
Chris@0 989 if (dtdm) {
Chris@0 990 QStringList data = text.split(m_datasetSeparator);
Chris@0 991
Chris@51 992 DenseThreeDimensionalModel::Column values;
Chris@0 993
Chris@0 994 for (QStringList::iterator i = data.begin(); i != data.end(); ++i) {
Chris@0 995
Chris@51 996 if (values.size() == dtdm->getHeight()) {
Chris@0 997 if (!warned) {
Chris@0 998 std::cerr << "WARNING: SV-XML: Too many y-bins in 3-D dataset row "
Chris@0 999 << m_rowNumber << std::endl;
Chris@0 1000 warned = true;
Chris@0 1001 }
Chris@0 1002 }
Chris@0 1003
Chris@0 1004 bool ok;
Chris@0 1005 float value = i->toFloat(&ok);
Chris@0 1006 if (!ok) {
Chris@0 1007 std::cerr << "WARNING: SV-XML: Bad floating-point value "
Chris@0 1008 << i->toLocal8Bit().data()
Chris@0 1009 << " in row data" << std::endl;
Chris@0 1010 } else {
Chris@0 1011 values.push_back(value);
Chris@0 1012 }
Chris@0 1013 }
Chris@0 1014
Chris@51 1015 dtdm->setColumn(m_rowNumber, values);
Chris@0 1016 return true;
Chris@0 1017 }
Chris@0 1018
Chris@0 1019 std::cerr << "WARNING: SV-XML: Row data found in non-row dataset" << std::endl;
Chris@0 1020
Chris@0 1021 return false;
Chris@0 1022 }
Chris@0 1023
Chris@0 1024 bool
Chris@0 1025 SVFileReader::readDerivation(const QXmlAttributes &attributes)
Chris@0 1026 {
Chris@0 1027 int modelId = 0;
Chris@0 1028 bool modelOk = false;
Chris@0 1029 modelId = attributes.value("model").trimmed().toInt(&modelOk);
Chris@0 1030
Chris@0 1031 if (!modelOk) {
Chris@0 1032 std::cerr << "WARNING: SV-XML: No model id specified for derivation" << std::endl;
Chris@0 1033 return false;
Chris@0 1034 }
Chris@55 1035
Chris@55 1036 QString transform = attributes.value("transform");
Chris@55 1037
Chris@55 1038 if (m_models.find(modelId) != m_models.end()) {
Chris@55 1039 m_currentDerivedModel = m_models[modelId];
Chris@55 1040 } else {
Chris@55 1041 // we'll regenerate the model when the derivation element ends
Chris@55 1042 m_currentDerivedModel = 0;
Chris@55 1043 }
Chris@0 1044
Chris@55 1045 m_currentDerivedModelId = modelId;
Chris@0 1046
Chris@55 1047 int sourceId = 0;
Chris@55 1048 bool sourceOk = false;
Chris@55 1049 sourceId = attributes.value("source").trimmed().toInt(&sourceOk);
Chris@0 1050
Chris@55 1051 if (sourceOk && m_models[sourceId]) {
Chris@55 1052 m_currentTransformSource = m_models[sourceId];
Chris@55 1053 } else {
Chris@55 1054 m_currentTransformSource = m_document->getMainModel();
Chris@55 1055 }
Chris@0 1056
Chris@55 1057 m_currentTransform = transform;
Chris@55 1058 m_currentTransformConfiguration = "";
Chris@30 1059
Chris@55 1060 m_currentTransformContext = PluginTransform::ExecutionContext();
Chris@30 1061
Chris@55 1062 bool ok = false;
Chris@55 1063 int channel = attributes.value("channel").trimmed().toInt(&ok);
Chris@55 1064 if (ok) m_currentTransformContext.channel = channel;
Chris@30 1065
Chris@55 1066 int domain = attributes.value("domain").trimmed().toInt(&ok);
Chris@55 1067 if (ok) m_currentTransformContext.domain = Vamp::Plugin::InputDomain(domain);
Chris@30 1068
Chris@55 1069 int stepSize = attributes.value("stepSize").trimmed().toInt(&ok);
Chris@55 1070 if (ok) m_currentTransformContext.stepSize = stepSize;
Chris@30 1071
Chris@55 1072 int blockSize = attributes.value("blockSize").trimmed().toInt(&ok);
Chris@55 1073 if (ok) m_currentTransformContext.blockSize = blockSize;
Chris@0 1074
Chris@55 1075 int windowType = attributes.value("windowType").trimmed().toInt(&ok);
Chris@55 1076 if (ok) m_currentTransformContext.windowType = WindowType(windowType);
Chris@0 1077
Chris@0 1078 return true;
Chris@0 1079 }
Chris@0 1080
Chris@0 1081 bool
Chris@0 1082 SVFileReader::readPlayParameters(const QXmlAttributes &attributes)
Chris@0 1083 {
Chris@0 1084 m_currentPlayParameters = 0;
Chris@0 1085
Chris@0 1086 int modelId = 0;
Chris@0 1087 bool modelOk = false;
Chris@0 1088 modelId = attributes.value("model").trimmed().toInt(&modelOk);
Chris@0 1089
Chris@0 1090 if (!modelOk) {
Chris@0 1091 std::cerr << "WARNING: SV-XML: No model id specified for play parameters" << std::endl;
Chris@0 1092 return false;
Chris@0 1093 }
Chris@0 1094
Chris@0 1095 if (m_models.find(modelId) != m_models.end()) {
Chris@0 1096
Chris@0 1097 bool ok = false;
Chris@0 1098
Chris@0 1099 PlayParameters *parameters = PlayParameterRepository::getInstance()->
Chris@0 1100 getPlayParameters(m_models[modelId]);
Chris@0 1101
Chris@0 1102 if (!parameters) {
Chris@0 1103 std::cerr << "WARNING: SV-XML: Play parameters for model "
Chris@0 1104 << modelId
Chris@0 1105 << " not found - has model been added to document?"
Chris@0 1106 << std::endl;
Chris@0 1107 return false;
Chris@0 1108 }
Chris@0 1109
Chris@0 1110 bool muted = (attributes.value("mute").trimmed() == "true");
Chris@83 1111 parameters->setPlayMuted(muted);
Chris@0 1112
Chris@0 1113 float pan = attributes.value("pan").toFloat(&ok);
Chris@0 1114 if (ok) parameters->setPlayPan(pan);
Chris@0 1115
Chris@0 1116 float gain = attributes.value("gain").toFloat(&ok);
Chris@0 1117 if (ok) parameters->setPlayGain(gain);
Chris@0 1118
Chris@0 1119 QString pluginId = attributes.value("pluginId");
Chris@0 1120 if (pluginId != "") parameters->setPlayPluginId(pluginId);
Chris@0 1121
Chris@0 1122 m_currentPlayParameters = parameters;
Chris@0 1123
Chris@0 1124 // std::cerr << "Current play parameters for model: " << m_models[modelId] << ": " << m_currentPlayParameters << std::endl;
Chris@0 1125
Chris@0 1126 } else {
Chris@0 1127
Chris@0 1128 std::cerr << "WARNING: SV-XML: Unknown model " << modelId
Chris@0 1129 << " for play parameters" << std::endl;
Chris@0 1130 return false;
Chris@0 1131 }
Chris@0 1132
Chris@0 1133 return true;
Chris@0 1134 }
Chris@0 1135
Chris@0 1136 bool
Chris@0 1137 SVFileReader::readPlugin(const QXmlAttributes &attributes)
Chris@0 1138 {
Chris@55 1139 if (m_currentDerivedModelId < 0 && !m_currentPlayParameters) {
Chris@0 1140 std::cerr << "WARNING: SV-XML: Plugin found outside derivation or play parameters" << std::endl;
Chris@0 1141 return false;
Chris@0 1142 }
Chris@0 1143
Chris@0 1144 QString configurationXml = "<plugin";
Chris@0 1145
Chris@0 1146 for (int i = 0; i < attributes.length(); ++i) {
Chris@0 1147 configurationXml += QString(" %1=\"%2\"")
Chris@55 1148 .arg(attributes.qName(i))
Chris@55 1149 .arg(XmlExportable::encodeEntities(attributes.value(i)));
Chris@0 1150 }
Chris@0 1151
Chris@0 1152 configurationXml += "/>";
Chris@0 1153
Chris@0 1154 if (m_currentPlayParameters) {
Chris@0 1155 m_currentPlayParameters->setPlayPluginConfiguration(configurationXml);
Chris@0 1156 } else {
Chris@0 1157 m_currentTransformConfiguration += configurationXml;
Chris@0 1158 }
Chris@0 1159
Chris@0 1160 return true;
Chris@0 1161 }
Chris@0 1162
Chris@0 1163 bool
Chris@0 1164 SVFileReader::readSelection(const QXmlAttributes &attributes)
Chris@0 1165 {
Chris@0 1166 bool ok;
Chris@0 1167
Chris@0 1168 READ_MANDATORY(int, start, toInt);
Chris@0 1169 READ_MANDATORY(int, end, toInt);
Chris@0 1170
Chris@0 1171 m_paneCallback.addSelection(start, end);
Chris@0 1172
Chris@0 1173 return true;
Chris@0 1174 }
Chris@0 1175