Mercurial > hg > svapp
comparison framework/SVFileReader.cpp @ 685:7540733f5480 by-id
Overhaul SV file reader etc
author | Chris Cannam |
---|---|
date | Thu, 04 Jul 2019 14:31:22 +0100 |
parents | c7406ebcd51c |
children | 610fa108fbcc |
comparison
equal
deleted
inserted
replaced
684:5e9b1956b609 | 685:7540733f5480 |
---|---|
56 QString location) : | 56 QString location) : |
57 m_document(document), | 57 m_document(document), |
58 m_paneCallback(callback), | 58 m_paneCallback(callback), |
59 m_location(location), | 59 m_location(location), |
60 m_currentPane(nullptr), | 60 m_currentPane(nullptr), |
61 m_currentDataset(XmlExportable::NO_ID), | |
61 m_currentLayer(nullptr), | 62 m_currentLayer(nullptr), |
62 m_currentDataset(nullptr), | 63 m_pendingDerivedModel(XmlExportable::NO_ID), |
63 m_currentDerivedModel(nullptr), | |
64 m_currentDerivedModelId(-1), | |
65 m_currentPlayParameters(nullptr), | 64 m_currentPlayParameters(nullptr), |
66 m_currentTransformSource(nullptr), | |
67 m_currentTransformChannel(0), | 65 m_currentTransformChannel(0), |
68 m_currentTransformIsNewStyle(true), | 66 m_currentTransformIsNewStyle(true), |
69 m_datasetSeparator(" "), | 67 m_datasetSeparator(" "), |
70 m_inRow(false), | 68 m_inRow(false), |
71 m_inLayer(false), | 69 m_inLayer(false), |
106 SVCERR << "WARNING: SV-XML: File ended with " | 104 SVCERR << "WARNING: SV-XML: File ended with " |
107 << m_awaitingDatasets.size() << " unfilled model dataset(s)" | 105 << m_awaitingDatasets.size() << " unfilled model dataset(s)" |
108 << endl; | 106 << endl; |
109 } | 107 } |
110 | 108 |
111 std::set<Model *> unaddedModels; | 109 std::set<ModelId> unaddedModels; |
112 | 110 |
113 for (std::map<int, Model *>::iterator i = m_models.begin(); | 111 for (auto i: m_models) { |
114 i != m_models.end(); ++i) { | 112 if (m_addedModels.find(i.second) == m_addedModels.end()) { |
115 if (m_addedModels.find(i->second) == m_addedModels.end()) { | 113 unaddedModels.insert(i.second); |
116 unaddedModels.insert(i->second); | |
117 } | 114 } |
118 } | 115 } |
119 | 116 |
120 if (!unaddedModels.empty()) { | 117 if (!unaddedModels.empty()) { |
121 SVCERR << "WARNING: SV-XML: File contained " | 118 SVCERR << "WARNING: SV-XML: File contained " |
122 << unaddedModels.size() << " unused models" | 119 << unaddedModels.size() << " unused models" |
123 << endl; | 120 << endl; |
124 while (!unaddedModels.empty()) { | 121 for (auto m: unaddedModels) { |
125 delete *unaddedModels.begin(); | 122 ModelById::release(m); |
126 unaddedModels.erase(unaddedModels.begin()); | 123 } |
127 } | 124 } |
128 } | 125 |
126 if (!m_paths.empty()) { | |
127 SVCERR << "WARNING: SV-XML: File contained " | |
128 << m_paths.size() << " unused paths" | |
129 << endl; | |
130 for (auto p: m_paths) { | |
131 delete p.second; | |
132 } | |
133 } | |
129 } | 134 } |
130 | 135 |
131 bool | 136 bool |
132 SVFileReader::startElement(const QString &, const QString &, | 137 SVFileReader::startElement(const QString &, const QString &, |
133 const QString &qName, | 138 const QString &qName, |
275 { | 280 { |
276 QString name = qName.toLower(); | 281 QString name = qName.toLower(); |
277 | 282 |
278 if (name == "dataset") { | 283 if (name == "dataset") { |
279 | 284 |
280 if (m_currentDataset) { | 285 if (m_currentDataset != XmlExportable::NO_ID) { |
281 | 286 |
282 bool foundInAwaiting = false; | 287 bool foundInAwaiting = false; |
283 | 288 |
284 for (std::map<int, int>::iterator i = m_awaitingDatasets.begin(); | 289 for (auto i: m_awaitingDatasets) { |
285 i != m_awaitingDatasets.end(); ++i) { | 290 if (i.second == m_currentDataset) { |
286 if (haveModel(i->second) && | 291 m_awaitingDatasets.erase(i.first); |
287 m_models[i->second] == m_currentDataset) { | |
288 m_awaitingDatasets.erase(i); | |
289 foundInAwaiting = true; | 292 foundInAwaiting = true; |
290 break; | 293 break; |
291 } | 294 } |
292 } | 295 } |
293 | 296 |
294 if (!foundInAwaiting) { | 297 if (!foundInAwaiting) { |
295 SVCERR << "WARNING: SV-XML: Dataset precedes model, or no model uses dataset" << endl; | 298 SVCERR << "WARNING: SV-XML: Dataset precedes model, or no model uses dataset" << endl; |
296 } | 299 } |
297 } | 300 } |
298 | 301 |
299 m_currentDataset = nullptr; | 302 m_currentDataset = XmlExportable::NO_ID; |
300 | 303 |
301 } else if (name == "data") { | 304 } else if (name == "data") { |
302 | 305 |
303 addUnaddedModels(); | 306 addUnaddedModels(); |
304 m_inData = false; | 307 m_inData = false; |
305 | 308 |
306 } else if (name == "derivation") { | 309 } else if (name == "derivation") { |
307 | 310 |
308 if (!m_currentDerivedModel) { | 311 if (m_currentDerivedModel.isNone()) { |
309 if (m_currentDerivedModelId < 0) { | 312 if (m_pendingDerivedModel == XmlExportable::NO_ID) { |
310 SVCERR << "WARNING: SV-XML: Bad derivation output model id " | 313 SVCERR << "WARNING: SV-XML: No valid output model id " |
311 << m_currentDerivedModelId << endl; | 314 << "for derivation" << endl; |
312 } else if (haveModel(m_currentDerivedModelId)) { | 315 } else if (haveModel(m_pendingDerivedModel)) { |
313 SVCERR << "WARNING: SV-XML: Derivation has existing model " | 316 SVCERR << "WARNING: SV-XML: Derivation has existing model " |
314 << m_currentDerivedModelId | 317 << m_pendingDerivedModel |
315 << " as target, not regenerating" << endl; | 318 << " as target, not regenerating" << endl; |
316 } else { | 319 } else { |
317 QString message; | 320 QString message; |
318 m_currentDerivedModel = m_models[m_currentDerivedModelId] = | 321 m_currentDerivedModel = m_models[m_pendingDerivedModel] = |
319 m_document->addDerivedModel | 322 m_document->addDerivedModel |
320 (m_currentTransform, | 323 (m_currentTransform, |
321 ModelTransformer::Input(m_currentTransformSource, | 324 ModelTransformer::Input(m_currentTransformSource, |
322 m_currentTransformChannel), | 325 m_currentTransformChannel), |
323 message); | 326 message); |
324 if (!m_currentDerivedModel) { | 327 if (m_currentDerivedModel.isNone()) { |
325 emit modelRegenerationFailed(tr("(derived model in SV-XML)"), | 328 emit modelRegenerationFailed(tr("(derived model in SV-XML)"), |
326 m_currentTransform.getIdentifier(), | 329 m_currentTransform.getIdentifier(), |
327 message); | 330 message); |
328 } else if (message != "") { | 331 } else if (message != "") { |
329 emit modelRegenerationWarning(tr("(derived model in SV-XML)"), | 332 emit modelRegenerationWarning(tr("(derived model in SV-XML)"), |
338 m_currentTransformChannel), | 341 m_currentTransformChannel), |
339 m_currentDerivedModel); | 342 m_currentDerivedModel); |
340 } | 343 } |
341 | 344 |
342 m_addedModels.insert(m_currentDerivedModel); | 345 m_addedModels.insert(m_currentDerivedModel); |
343 m_currentDerivedModel = nullptr; | 346 m_currentDerivedModel = {}; |
344 m_currentDerivedModelId = -1; | 347 m_pendingDerivedModel = XmlExportable::NO_ID; |
345 m_currentTransformSource = nullptr; | 348 m_currentTransformSource = {}; |
346 m_currentTransform = Transform(); | 349 m_currentTransform = Transform(); |
347 m_currentTransformChannel = -1; | 350 m_currentTransformChannel = -1; |
348 | 351 |
349 } else if (name == "row") { | 352 } else if (name == "row") { |
350 m_inRow = false; | 353 m_inRow = false; |
404 } | 407 } |
405 | 408 |
406 void | 409 void |
407 SVFileReader::makeAggregateModels() | 410 SVFileReader::makeAggregateModels() |
408 { | 411 { |
409 std::map<int, PendingAggregateRec> stillPending; | 412 std::map<ExportId, PendingAggregateRec> stillPending; |
410 | 413 |
411 for (auto p: m_pendingAggregates) { | 414 for (auto p: m_pendingAggregates) { |
412 | 415 |
413 int id = p.first; | 416 int id = p.first; |
414 const PendingAggregateRec &rec = p.second; | 417 const PendingAggregateRec &rec = p.second; |
415 bool skip = false; | 418 bool skip = false; |
416 | 419 |
417 AggregateWaveModel::ChannelSpecList specs; | 420 AggregateWaveModel::ChannelSpecList specs; |
418 for (int componentId: rec.components) { | 421 for (ExportId componentId: rec.components) { |
419 bool found = false; | 422 bool found = false; |
420 if (m_models.find(componentId) != m_models.end()) { | 423 if (m_models.find(componentId) != m_models.end()) { |
421 RangeSummarisableTimeValueModel *rs = | 424 ModelId modelId = m_models[componentId]; |
422 dynamic_cast<RangeSummarisableTimeValueModel *> | 425 auto rs = ModelById::getAs<RangeSummarisableTimeValueModel> |
423 (m_models[componentId]); | 426 (modelId); |
424 if (rs) { | 427 if (rs) { |
425 //!!! NB difference between model id and model | |
426 //!!! export id - we need to be clearer about this | |
427 specs.push_back(AggregateWaveModel::ModelChannelSpec | 428 specs.push_back(AggregateWaveModel::ModelChannelSpec |
428 (rs->getId(), -1)); | 429 (modelId, -1)); |
429 found = true; | 430 found = true; |
431 } else { | |
432 SVDEBUG << "SVFileReader::makeAggregateModels: " | |
433 << "Component model id " << componentId | |
434 << "in aggregate model id " << id | |
435 << "does not appear to be convertible to " | |
436 << "RangeSummarisableTimeValueModel" | |
437 << endl; | |
430 } | 438 } |
431 } | 439 } |
432 if (!found) { | 440 if (!found) { |
433 SVDEBUG << "SVFileReader::makeAggregateModels:" | 441 SVDEBUG << "SVFileReader::makeAggregateModels: " |
434 << "Unknown component model id " | 442 << "Unknown component model id " |
435 << componentId << " in aggregate model id " << id | 443 << componentId << " in aggregate model id " << id |
436 << ", hoping we won't be needing it just yet" | 444 << ", hoping we won't be needing it just yet" |
437 << endl; | 445 << endl; |
438 skip = true; | 446 skip = true; |
440 } | 448 } |
441 | 449 |
442 if (skip) { | 450 if (skip) { |
443 stillPending[id] = rec; | 451 stillPending[id] = rec; |
444 } else { | 452 } else { |
445 AggregateWaveModel *model = new AggregateWaveModel(specs); | 453 auto model = std::make_shared<AggregateWaveModel>(specs); |
446 model->setObjectName(rec.name); | 454 model->setObjectName(rec.name); |
447 | 455 m_models[id] = ModelById::add(model); |
448 SVDEBUG << "SVFileReader::makeAggregateModels: created aggregate model id " | 456 |
449 << id << " with " << specs.size() << " components" << endl; | 457 SVDEBUG << "SVFileReader::makeAggregateModels: created aggregate " |
450 | 458 << "model id " << id << " with " << specs.size() |
451 m_models[id] = model; | 459 << " components" << endl; |
452 } | 460 } |
453 } | 461 } |
454 | 462 |
455 m_pendingAggregates = stillPending; | 463 m_pendingAggregates = stillPending; |
456 } | 464 } |
457 | 465 |
458 void | 466 void |
459 SVFileReader::addUnaddedModels() | 467 SVFileReader::addUnaddedModels() |
460 { | 468 { |
461 makeAggregateModels(); | 469 makeAggregateModels(); |
462 | 470 |
463 for (std::map<int, Model *>::iterator i = m_models.begin(); | 471 for (auto i: m_models) { |
464 i != m_models.end(); ++i) { | 472 |
465 | 473 ModelId modelId = i.second; |
466 Model *model = i->second; | 474 |
467 | 475 if (m_addedModels.find(modelId) != m_addedModels.end()) { |
468 if (m_addedModels.find(model) != m_addedModels.end()) { | |
469 // already added this one | 476 // already added this one |
470 continue; | 477 continue; |
471 } | 478 } |
472 | 479 |
473 // don't want to add path and alignment models to the | 480 //!!! todo: review this (i.e. who causes the release of what) |
474 // document, because their lifespans are entirely dictated by | 481 |
475 // the models that "own" them even though they were read | 482 // don't want to add alignment models to the document, because |
476 // independently from the .sv file. (pity we don't have a | 483 // their lifespans are entirely dictated by the models that |
477 // nicer way to handle this) | 484 // "own" them even though they were read independently from |
478 if (!dynamic_cast<PathModel *>(model) && | 485 // the .sv file. (pity we don't have a nicer way to handle |
479 !dynamic_cast<AlignmentModel *>(model)) { | 486 // this) |
480 | 487 if (!ModelById::isa<AlignmentModel>(modelId)) { |
481 m_document->addImportedModel(model); | 488 m_document->addImportedModel(modelId); |
482 } | 489 } |
483 | 490 |
484 // but we add all models including path and alignment ones to | 491 // but we add all models including alignment ones to the added |
485 // the added set, so they don't get deleted from our own | 492 // set, so they don't get released by our own destructor |
486 // destructor | 493 m_addedModels.insert(modelId); |
487 m_addedModels.insert(model); | |
488 } | 494 } |
489 } | 495 } |
490 | 496 |
491 bool | 497 bool |
492 SVFileReader::readModel(const QXmlAttributes &attributes) | 498 SVFileReader::readModel(const QXmlAttributes &attributes) |
538 if (Preferences::getInstance()->getFixedSampleRate() != 0) { | 544 if (Preferences::getInstance()->getFixedSampleRate() != 0) { |
539 rate = Preferences::getInstance()->getFixedSampleRate(); | 545 rate = Preferences::getInstance()->getFixedSampleRate(); |
540 } else if (rate == 0 && | 546 } else if (rate == 0 && |
541 !isMainModel && | 547 !isMainModel && |
542 Preferences::getInstance()->getResampleOnLoad()) { | 548 Preferences::getInstance()->getResampleOnLoad()) { |
543 WaveFileModel *mm = m_document->getMainModel(); | 549 auto mm = ModelById::getAs<WaveFileModel> |
550 (m_document->getMainModel()); | |
544 if (mm) rate = mm->getSampleRate(); | 551 if (mm) rate = mm->getSampleRate(); |
545 } | 552 } |
546 | 553 |
547 model = new ReadOnlyWaveFileModel(file, rate); | 554 model = new ReadOnlyWaveFileModel(file, rate); |
548 if (!model->isOK()) { | 555 if (!model->isOK()) { |
555 m_document->setIncomplete(true); | 562 m_document->setIncomplete(true); |
556 return false; | 563 return false; |
557 } | 564 } |
558 | 565 |
559 model->setObjectName(name); | 566 model->setObjectName(name); |
560 m_models[id] = model; | 567 |
568 ModelId modelId = model->getId(); | |
569 ModelById::add(std::shared_ptr<Model>(model)); | |
570 m_models[id] = modelId; | |
571 | |
561 if (isMainModel) { | 572 if (isMainModel) { |
562 m_document->setMainModel(model); | 573 m_document->setMainModel(modelId); |
563 m_addedModels.insert(model); | 574 m_addedModels.insert(modelId); |
564 } | 575 } |
565 // Derived models will be added when their derivation | 576 // Derived models will be added when their derivation |
566 // is found. | 577 // is found. |
567 | 578 |
568 return true; | 579 return true; |
570 } else if (type == "aggregatewave") { | 581 } else if (type == "aggregatewave") { |
571 | 582 |
572 QString components = attributes.value("components"); | 583 QString components = attributes.value("components"); |
573 QStringList componentIdStrings = components.split(","); | 584 QStringList componentIdStrings = components.split(","); |
574 std::vector<int> componentIds; | 585 std::vector<int> componentIds; |
575 for (auto cid: componentIdStrings) { | 586 for (auto cidStr: componentIdStrings) { |
576 bool ok = false; | 587 bool ok = false; |
577 int id = cid.toInt(&ok); | 588 int cid = cidStr.toInt(&ok); |
578 if (!ok) { | 589 if (!ok) { |
579 SVCERR << "SVFileReader::readModel: Failed to convert component model id from part \"" << cid << "\" in \"" << components << "\"" << endl; | 590 SVCERR << "SVFileReader::readModel: Failed to convert component model id from part \"" << cidStr << "\" in \"" << components << "\"" << endl; |
580 } else { | 591 } else { |
581 componentIds.push_back(id); | 592 componentIds.push_back(cid); |
582 } | 593 } |
583 } | 594 } |
584 PendingAggregateRec rec { name, sampleRate, componentIds }; | 595 PendingAggregateRec rec { name, sampleRate, componentIds }; |
585 m_pendingAggregates[id] = rec; | 596 m_pendingAggregates[id] = rec; |
586 | 597 |
603 if (dimensions == 3) { | 614 if (dimensions == 3) { |
604 | 615 |
605 READ_MANDATORY(int, windowSize, toInt); | 616 READ_MANDATORY(int, windowSize, toInt); |
606 READ_MANDATORY(int, yBinCount, toInt); | 617 READ_MANDATORY(int, yBinCount, toInt); |
607 | 618 |
608 EditableDenseThreeDimensionalModel *model = | 619 auto model = std::make_shared<EditableDenseThreeDimensionalModel> |
609 new EditableDenseThreeDimensionalModel | |
610 (sampleRate, windowSize, yBinCount, | 620 (sampleRate, windowSize, yBinCount, |
611 EditableDenseThreeDimensionalModel::NoCompression); | 621 EditableDenseThreeDimensionalModel::NoCompression); |
622 | |
623 model->setObjectName(name); | |
624 m_models[id] = ModelById::add(model); | |
612 | 625 |
613 float minimum = attributes.value("minimum").trimmed().toFloat(&ok); | 626 float minimum = attributes.value("minimum").trimmed().toFloat(&ok); |
614 if (ok) model->setMinimumLevel(minimum); | 627 if (ok) model->setMinimumLevel(minimum); |
615 | 628 |
616 float maximum = attributes.value("maximum").trimmed().toFloat(&ok); | 629 float maximum = attributes.value("maximum").trimmed().toFloat(&ok); |
620 if (ok) m_awaitingDatasets[dataset] = id; | 633 if (ok) m_awaitingDatasets[dataset] = id; |
621 | 634 |
622 int startFrame = attributes.value("startFrame").trimmed().toInt(&ok); | 635 int startFrame = attributes.value("startFrame").trimmed().toInt(&ok); |
623 if (ok) model->setStartFrame(startFrame); | 636 if (ok) model->setStartFrame(startFrame); |
624 | 637 |
625 model->setObjectName(name); | |
626 m_models[id] = model; | |
627 return true; | 638 return true; |
628 | 639 |
629 } else { | 640 } else { |
630 | 641 |
631 SVCERR << "WARNING: SV-XML: Unexpected dense model dimension (" | 642 SVCERR << "WARNING: SV-XML: Unexpected dense model dimension (" |
636 READ_MANDATORY(int, dimensions, toInt); | 647 READ_MANDATORY(int, dimensions, toInt); |
637 | 648 |
638 if (dimensions == 1) { | 649 if (dimensions == 1) { |
639 | 650 |
640 READ_MANDATORY(int, resolution, toInt); | 651 READ_MANDATORY(int, resolution, toInt); |
641 | 652 |
642 if (attributes.value("subtype") == "image") { | 653 if (attributes.value("subtype") == "image") { |
643 | 654 |
644 bool notifyOnAdd = (attributes.value("notifyOnAdd") == "true"); | 655 bool notifyOnAdd = (attributes.value("notifyOnAdd") == "true"); |
645 ImageModel *model = new ImageModel(sampleRate, resolution, | 656 auto model = std::make_shared<ImageModel> |
646 notifyOnAdd); | 657 (sampleRate, resolution, notifyOnAdd); |
647 model->setObjectName(name); | 658 model->setObjectName(name); |
648 m_models[id] = model; | 659 m_models[id] = ModelById::add(model); |
649 | 660 |
650 } else { | 661 } else { |
651 | 662 |
652 SparseOneDimensionalModel *model = new SparseOneDimensionalModel | 663 auto model = std::make_shared<SparseOneDimensionalModel> |
653 (sampleRate, resolution); | 664 (sampleRate, resolution); |
654 model->setObjectName(name); | 665 model->setObjectName(name); |
655 m_models[id] = model; | 666 m_models[id] = ModelById::add(model); |
656 } | 667 } |
657 | 668 |
658 int dataset = attributes.value("dataset").trimmed().toInt(&ok); | 669 int dataset = attributes.value("dataset").trimmed().toInt(&ok); |
659 if (ok) m_awaitingDatasets[dataset] = id; | 670 if (ok) m_awaitingDatasets[dataset] = id; |
660 | 671 |
677 | 688 |
678 QString units = attributes.value("units"); | 689 QString units = attributes.value("units"); |
679 | 690 |
680 if (dimensions == 2) { | 691 if (dimensions == 2) { |
681 if (attributes.value("subtype") == "text") { | 692 if (attributes.value("subtype") == "text") { |
682 TextModel *model = new TextModel | 693 auto model = std::make_shared<TextModel> |
683 (sampleRate, resolution, notifyOnAdd); | 694 (sampleRate, resolution, notifyOnAdd); |
684 model->setObjectName(name); | 695 model->setObjectName(name); |
685 m_models[id] = model; | 696 m_models[id] = ModelById::add(model); |
686 } else if (attributes.value("subtype") == "path") { | 697 } else if (attributes.value("subtype") == "path") { |
687 PathModel *model = new PathModel | 698 // Paths are no longer actually models |
688 (sampleRate, resolution, notifyOnAdd); | 699 Path *path = new Path(sampleRate, resolution); |
689 model->setObjectName(name); | 700 m_paths[id] = path; |
690 m_models[id] = model; | |
691 } else { | 701 } else { |
692 SparseTimeValueModel *model; | 702 std::shared_ptr<SparseTimeValueModel> model; |
693 if (haveMinMax) { | 703 if (haveMinMax) { |
694 model = new SparseTimeValueModel | 704 model = std::make_shared<SparseTimeValueModel> |
695 (sampleRate, resolution, minimum, maximum, notifyOnAdd); | 705 (sampleRate, resolution, minimum, maximum, |
706 notifyOnAdd); | |
696 } else { | 707 } else { |
697 model = new SparseTimeValueModel | 708 model = std::make_shared<SparseTimeValueModel> |
698 (sampleRate, resolution, notifyOnAdd); | 709 (sampleRate, resolution, notifyOnAdd); |
699 } | 710 } |
700 model->setScaleUnits(units); | 711 model->setScaleUnits(units); |
701 model->setObjectName(name); | 712 model->setObjectName(name); |
702 m_models[id] = model; | 713 m_models[id] = ModelById::add(model); |
703 } | 714 } |
704 } else { | 715 } else { |
705 if (attributes.value("subtype") == "region") { | 716 if (attributes.value("subtype") == "region") { |
706 RegionModel *model; | 717 std::shared_ptr<RegionModel> model; |
707 if (haveMinMax) { | 718 if (haveMinMax) { |
708 model = new RegionModel | 719 model = std::make_shared<RegionModel> |
709 (sampleRate, resolution, minimum, maximum, notifyOnAdd); | 720 (sampleRate, resolution, minimum, maximum, |
721 notifyOnAdd); | |
710 } else { | 722 } else { |
711 model = new RegionModel | 723 model = std::make_shared<RegionModel> |
712 (sampleRate, resolution, notifyOnAdd); | 724 (sampleRate, resolution, notifyOnAdd); |
713 } | 725 } |
714 model->setValueQuantization(valueQuantization); | 726 model->setValueQuantization(valueQuantization); |
715 model->setScaleUnits(units); | 727 model->setScaleUnits(units); |
716 model->setObjectName(name); | 728 model->setObjectName(name); |
717 m_models[id] = model; | 729 m_models[id] = ModelById::add(model); |
718 } else if (attributes.value("subtype") == "flexinote") { | 730 } else if (attributes.value("subtype") == "flexinote") { |
719 NoteModel *model; | 731 std::shared_ptr<NoteModel> model; |
720 if (haveMinMax) { | 732 if (haveMinMax) { |
721 model = new NoteModel | 733 model = std::make_shared<NoteModel> |
722 (sampleRate, resolution, minimum, maximum, | 734 (sampleRate, resolution, minimum, maximum, |
723 notifyOnAdd, | 735 notifyOnAdd, |
724 NoteModel::FLEXI_NOTE); | 736 NoteModel::FLEXI_NOTE); |
725 } else { | 737 } else { |
726 model = new NoteModel | 738 model = std::make_shared<NoteModel> |
727 (sampleRate, resolution, notifyOnAdd, | 739 (sampleRate, resolution, notifyOnAdd, |
728 NoteModel::FLEXI_NOTE); | 740 NoteModel::FLEXI_NOTE); |
729 } | 741 } |
730 model->setValueQuantization(valueQuantization); | 742 model->setValueQuantization(valueQuantization); |
731 model->setScaleUnits(units); | 743 model->setScaleUnits(units); |
732 model->setObjectName(name); | 744 model->setObjectName(name); |
733 m_models[id] = model; | 745 m_models[id] = ModelById::add(model); |
734 } else { | 746 } else { |
735 // note models written out by SV 1.3 and earlier | 747 // note models written out by SV 1.3 and earlier |
736 // have no subtype, so we can't test that | 748 // have no subtype, so we can't test that |
737 NoteModel *model; | 749 std::shared_ptr<NoteModel> model; |
738 if (haveMinMax) { | 750 if (haveMinMax) { |
739 model = new NoteModel | 751 model = std::make_shared<NoteModel> |
740 (sampleRate, resolution, minimum, maximum, notifyOnAdd); | 752 (sampleRate, resolution, minimum, maximum, notifyOnAdd); |
741 } else { | 753 } else { |
742 model = new NoteModel | 754 model = std::make_shared<NoteModel> |
743 (sampleRate, resolution, notifyOnAdd); | 755 (sampleRate, resolution, notifyOnAdd); |
744 } | 756 } |
745 model->setValueQuantization(valueQuantization); | 757 model->setValueQuantization(valueQuantization); |
746 model->setScaleUnits(units); | 758 model->setScaleUnits(units); |
747 model->setObjectName(name); | 759 model->setObjectName(name); |
748 m_models[id] = model; | 760 m_models[id] = ModelById::add(model); |
749 } | 761 } |
750 } | 762 } |
751 | 763 |
752 int dataset = attributes.value("dataset").trimmed().toInt(&ok); | 764 int dataset = attributes.value("dataset").trimmed().toInt(&ok); |
753 if (ok) m_awaitingDatasets[dataset] = id; | 765 if (ok) m_awaitingDatasets[dataset] = id; |
764 | 776 |
765 READ_MANDATORY(int, reference, toInt); | 777 READ_MANDATORY(int, reference, toInt); |
766 READ_MANDATORY(int, aligned, toInt); | 778 READ_MANDATORY(int, aligned, toInt); |
767 READ_MANDATORY(int, path, toInt); | 779 READ_MANDATORY(int, path, toInt); |
768 | 780 |
769 Model *refModel = nullptr, *alignedModel = nullptr, *pathModel = nullptr; | 781 ModelId refModel, alignedModel; |
782 Path *pathPtr = nullptr; | |
770 | 783 |
771 if (m_models.find(reference) != m_models.end()) { | 784 if (m_models.find(reference) != m_models.end()) { |
772 refModel = m_models[reference]; | 785 refModel = m_models[reference]; |
773 } else { | 786 } else { |
774 SVCERR << "WARNING: SV-XML: Unknown reference model id " | 787 SVCERR << "WARNING: SV-XML: Unknown reference model id " |
782 SVCERR << "WARNING: SV-XML: Unknown aligned model id " | 795 SVCERR << "WARNING: SV-XML: Unknown aligned model id " |
783 << aligned << " in alignment model id " << id | 796 << aligned << " in alignment model id " << id |
784 << endl; | 797 << endl; |
785 } | 798 } |
786 | 799 |
787 if (m_models.find(path) != m_models.end()) { | 800 if (m_paths.find(path) != m_paths.end()) { |
788 pathModel = m_models[path]; | 801 pathPtr = m_paths[path]; |
789 } else { | 802 } else { |
790 SVCERR << "WARNING: SV-XML: Unknown path model id " | 803 SVCERR << "WARNING: SV-XML: Unknown path id " |
791 << path << " in alignment model id " << id | 804 << path << " in alignment model id " << id |
792 << endl; | 805 << endl; |
793 } | 806 } |
794 | 807 |
795 if (refModel && alignedModel && pathModel) { | 808 if (!refModel.isNone() && !alignedModel.isNone() && pathPtr) { |
796 AlignmentModel *model = new AlignmentModel | 809 auto model = std::make_shared<AlignmentModel> |
797 (refModel, alignedModel, nullptr); | 810 (refModel, alignedModel, ModelId()); |
798 PathModel *pm = dynamic_cast<PathModel *>(pathModel); | 811 model->setPath(*pathPtr); |
799 if (!pm) { | |
800 SVCERR << "WARNING: SV-XML: Model id " << path | |
801 << " referenced as path for alignment " << id | |
802 << " is not a path model" << endl; | |
803 } else { | |
804 model->setPath(pm); | |
805 pm->setCompletion(100); | |
806 } | |
807 model->setObjectName(name); | 812 model->setObjectName(name); |
808 m_models[id] = model; | 813 m_models[id] = ModelById::add(model); |
809 alignedModel->setAlignment(model); | 814 if (auto am = ModelById::get(alignedModel)) { |
815 am->setAlignment(m_models[id]); | |
816 } | |
810 return true; | 817 return true; |
818 } | |
819 | |
820 if (pathPtr) { | |
821 delete pathPtr; | |
822 m_paths.erase(path); | |
811 } | 823 } |
812 | 824 |
813 } else { | 825 } else { |
814 | 826 |
815 SVCERR << "WARNING: SV-XML: Unexpected model type \"" | 827 SVCERR << "WARNING: SV-XML: Unexpected model type \"" |
972 bool modelOk = false; | 984 bool modelOk = false; |
973 modelId = attributes.value("model").trimmed().toInt(&modelOk); | 985 modelId = attributes.value("model").trimmed().toInt(&modelOk); |
974 | 986 |
975 if (modelOk) { | 987 if (modelOk) { |
976 if (haveModel(modelId)) { | 988 if (haveModel(modelId)) { |
977 Model *model = m_models[modelId]; | 989 m_document->setModel(layer, m_models[modelId]); |
978 m_document->setModel(layer, model); | |
979 } else { | 990 } else { |
980 SVCERR << "WARNING: SV-XML: Unknown model id " << modelId | 991 SVCERR << "WARNING: SV-XML: Unknown model id " << modelId |
981 << " in layer definition" << endl; | 992 << " in layer definition" << endl; |
982 if (!layer->canExistWithoutModel()) { | 993 if (!layer->canExistWithoutModel()) { |
983 // Don't add a layer with an unknown model id | 994 // Don't add a layer with an unknown model id |
984 // unless it explicitly supports this state | 995 // unless it explicitly supports this state |
985 m_document->deleteLayer(layer); | 996 m_document->deleteLayer(layer); |
986 m_layers[id] = layer = nullptr; | 997 m_layers[id] = layer = nullptr; |
1028 if (m_awaitingDatasets.find(id) == m_awaitingDatasets.end()) { | 1039 if (m_awaitingDatasets.find(id) == m_awaitingDatasets.end()) { |
1029 SVCERR << "WARNING: SV-XML: Unwanted dataset " << id << endl; | 1040 SVCERR << "WARNING: SV-XML: Unwanted dataset " << id << endl; |
1030 return false; | 1041 return false; |
1031 } | 1042 } |
1032 | 1043 |
1033 int modelId = m_awaitingDatasets[id]; | 1044 int awaitingId = m_awaitingDatasets[id]; |
1045 | |
1046 ModelId modelId; | |
1047 Path *path = nullptr; | |
1034 | 1048 |
1035 Model *model = nullptr; | 1049 if (haveModel(awaitingId)) { |
1036 if (haveModel(modelId)) { | 1050 modelId = m_models[awaitingId]; |
1037 model = m_models[modelId]; | 1051 } else if (m_paths.find(awaitingId) != m_paths.end()) { |
1052 path = m_paths[awaitingId]; | |
1038 } else { | 1053 } else { |
1039 SVCERR << "WARNING: SV-XML: Internal error: Unknown model " << modelId | 1054 SVCERR << "WARNING: SV-XML: Internal error: Unknown model or path " |
1040 << " expecting dataset " << id << endl; | 1055 << modelId << " awaiting dataset " << id << endl; |
1041 return false; | 1056 return false; |
1042 } | 1057 } |
1043 | 1058 |
1044 bool good = false; | 1059 bool good = false; |
1045 | 1060 |
1046 switch (dimensions) { | 1061 switch (dimensions) { |
1047 case 1: | 1062 case 1: |
1048 if (dynamic_cast<SparseOneDimensionalModel *>(model)) good = true; | 1063 good = |
1049 else if (dynamic_cast<ImageModel *>(model)) good = true; | 1064 (ModelById::isa<SparseOneDimensionalModel>(modelId) || |
1065 ModelById::isa<ImageModel>(modelId)); | |
1050 break; | 1066 break; |
1051 | 1067 |
1052 case 2: | 1068 case 2: |
1053 if (dynamic_cast<SparseTimeValueModel *>(model)) good = true; | 1069 good = |
1054 else if (dynamic_cast<TextModel *>(model)) good = true; | 1070 (ModelById::isa<SparseTimeValueModel>(modelId) || |
1055 else if (dynamic_cast<PathModel *>(model)) good = true; | 1071 ModelById::isa<TextModel>(modelId) || |
1072 path); | |
1056 break; | 1073 break; |
1057 | 1074 |
1058 case 3: | 1075 case 3: |
1059 if (dynamic_cast<NoteModel *>(model)) good = true; | 1076 if (ModelById::isa<EditableDenseThreeDimensionalModel>(modelId)) { |
1060 else if (dynamic_cast<RegionModel *>(model)) good = true; | 1077 good = true; |
1061 else if (dynamic_cast<EditableDenseThreeDimensionalModel *>(model)) { | |
1062 m_datasetSeparator = attributes.value("separator"); | 1078 m_datasetSeparator = attributes.value("separator"); |
1063 good = true; | 1079 } else { |
1080 good = | |
1081 (ModelById::isa<NoteModel>(modelId) || | |
1082 ModelById::isa<RegionModel>(modelId)); | |
1064 } | 1083 } |
1065 break; | 1084 break; |
1066 } | 1085 } |
1067 | 1086 |
1068 if (!good) { | 1087 if (!good) { |
1069 SVCERR << "WARNING: SV-XML: Model id " << modelId << " has wrong number of dimensions or inappropriate type for " << dimensions << "-D dataset " << id << endl; | 1088 SVCERR << "WARNING: SV-XML: Model id " << modelId << " has wrong number of dimensions or inappropriate type for " << dimensions << "-D dataset " << id << endl; |
1070 m_currentDataset = nullptr; | 1089 m_currentDataset = XmlExportable::NO_ID; |
1071 return false; | 1090 return false; |
1072 } | 1091 } |
1073 | 1092 |
1074 m_currentDataset = model; | 1093 m_currentDataset = awaitingId; |
1075 return true; | 1094 return true; |
1076 } | 1095 } |
1077 | 1096 |
1078 bool | 1097 bool |
1079 SVFileReader::addPointToDataset(const QXmlAttributes &attributes) | 1098 SVFileReader::addPointToDataset(const QXmlAttributes &attributes) |
1080 { | 1099 { |
1081 bool ok = false; | 1100 bool ok = false; |
1082 | 1101 |
1083 READ_MANDATORY(int, frame, toInt); | 1102 READ_MANDATORY(int, frame, toInt); |
1084 | 1103 |
1085 // SVDEBUG << "SVFileReader::addPointToDataset: frame = " << frame << endl; | 1104 if (m_paths.find(m_currentDataset) != m_paths.end()) { |
1086 | 1105 Path *path = m_paths[m_currentDataset]; |
1087 SparseOneDimensionalModel *sodm = dynamic_cast<SparseOneDimensionalModel *> | 1106 int mapframe = attributes.value("mapframe").trimmed().toInt(&ok); |
1088 (m_currentDataset); | 1107 path->add(PathPoint(frame, mapframe)); |
1089 | 1108 return ok; |
1090 if (sodm) { | 1109 } |
1091 // SVCERR << "Current dataset is a sparse one dimensional model" << endl; | 1110 |
1111 if (!haveModel(m_currentDataset)) { | |
1112 SVCERR << "WARNING: SV-XML: Point element found in non-point dataset" | |
1113 << endl; | |
1114 return false; | |
1115 } | |
1116 | |
1117 ModelId modelId = m_models[m_currentDataset]; | |
1118 | |
1119 if (auto sodm = ModelById::getAs<SparseOneDimensionalModel>(modelId)) { | |
1092 QString label = attributes.value("label"); | 1120 QString label = attributes.value("label"); |
1093 sodm->add(Event(frame, label)); | 1121 sodm->add(Event(frame, label)); |
1094 return true; | 1122 return true; |
1095 } | 1123 } |
1096 | 1124 |
1097 SparseTimeValueModel *stvm = dynamic_cast<SparseTimeValueModel *> | 1125 if (auto stvm = ModelById::getAs<SparseTimeValueModel>(modelId)) { |
1098 (m_currentDataset); | |
1099 | |
1100 if (stvm) { | |
1101 // SVCERR << "Current dataset is a sparse time-value model" << endl; | |
1102 float value = 0.0; | 1126 float value = 0.0; |
1103 value = attributes.value("value").trimmed().toFloat(&ok); | 1127 value = attributes.value("value").trimmed().toFloat(&ok); |
1104 QString label = attributes.value("label"); | 1128 QString label = attributes.value("label"); |
1105 stvm->add(Event(frame, value, label)); | 1129 stvm->add(Event(frame, value, label)); |
1106 return ok; | 1130 return ok; |
1107 } | 1131 } |
1108 | 1132 |
1109 NoteModel *nm = dynamic_cast<NoteModel *>(m_currentDataset); | 1133 if (auto nm = ModelById::getAs<NoteModel>(modelId)) { |
1110 | |
1111 if (nm) { | |
1112 // SVCERR << "Current dataset is a note model" << endl; | |
1113 float value = 0.0; | 1134 float value = 0.0; |
1114 value = attributes.value("value").trimmed().toFloat(&ok); | 1135 value = attributes.value("value").trimmed().toFloat(&ok); |
1115 int duration = 0; | 1136 int duration = 0; |
1116 duration = attributes.value("duration").trimmed().toInt(&ok); | 1137 duration = attributes.value("duration").trimmed().toInt(&ok); |
1117 QString label = attributes.value("label"); | 1138 QString label = attributes.value("label"); |
1122 } | 1143 } |
1123 nm->add(Event(frame, value, duration, level, label)); | 1144 nm->add(Event(frame, value, duration, level, label)); |
1124 return ok; | 1145 return ok; |
1125 } | 1146 } |
1126 | 1147 |
1127 RegionModel *rm = dynamic_cast<RegionModel *>(m_currentDataset); | 1148 if (auto rm = ModelById::getAs<RegionModel>(modelId)) { |
1128 | |
1129 if (rm) { | |
1130 // SVCERR << "Current dataset is a region model" << endl; | |
1131 float value = 0.0; | 1149 float value = 0.0; |
1132 value = attributes.value("value").trimmed().toFloat(&ok); | 1150 value = attributes.value("value").trimmed().toFloat(&ok); |
1133 int duration = 0; | 1151 int duration = 0; |
1134 duration = attributes.value("duration").trimmed().toInt(&ok); | 1152 duration = attributes.value("duration").trimmed().toInt(&ok); |
1135 QString label = attributes.value("label"); | 1153 QString label = attributes.value("label"); |
1136 rm->add(Event(frame, value, duration, label)); | 1154 rm->add(Event(frame, value, duration, label)); |
1137 return ok; | 1155 return ok; |
1138 } | 1156 } |
1139 | 1157 |
1140 TextModel *tm = dynamic_cast<TextModel *>(m_currentDataset); | 1158 if (auto tm = ModelById::getAs<TextModel>(modelId)) { |
1141 | |
1142 if (tm) { | |
1143 // SVCERR << "Current dataset is a text model" << endl; | |
1144 float height = 0.0; | 1159 float height = 0.0; |
1145 height = attributes.value("height").trimmed().toFloat(&ok); | 1160 height = attributes.value("height").trimmed().toFloat(&ok); |
1146 QString label = attributes.value("label"); | 1161 QString label = attributes.value("label"); |
1147 // SVDEBUG << "SVFileReader::addPointToDataset: TextModel: frame = " << frame << ", height = " << height << ", label = " << label << ", ok = " << ok << endl; | |
1148 tm->add(Event(frame, height, label)); | 1162 tm->add(Event(frame, height, label)); |
1149 return ok; | 1163 return ok; |
1150 } | 1164 } |
1151 | 1165 |
1152 PathModel *pm = dynamic_cast<PathModel *>(m_currentDataset); | 1166 if (auto im = ModelById::getAs<ImageModel>(modelId)) { |
1153 | |
1154 if (pm) { | |
1155 // SVCERR << "Current dataset is a path model" << endl; | |
1156 int mapframe = attributes.value("mapframe").trimmed().toInt(&ok); | |
1157 // SVDEBUG << "SVFileReader::addPointToDataset: PathModel: frame = " << frame << ", mapframe = " << mapframe << ", ok = " << ok << endl; | |
1158 pm->add(PathPoint(frame, mapframe)); | |
1159 return ok; | |
1160 } | |
1161 | |
1162 ImageModel *im = dynamic_cast<ImageModel *>(m_currentDataset); | |
1163 | |
1164 if (im) { | |
1165 // SVCERR << "Current dataset is an image model" << endl; | |
1166 QString image = attributes.value("image"); | 1167 QString image = attributes.value("image"); |
1167 QString label = attributes.value("label"); | 1168 QString label = attributes.value("label"); |
1168 // SVDEBUG << "SVFileReader::addPointToDataset: ImageModel: frame = " << frame << ", image = " << image << ", label = " << label << ", ok = " << ok << endl; | |
1169 im->add(Event(frame).withURI(image).withLabel(label)); | 1169 im->add(Event(frame).withURI(image).withLabel(label)); |
1170 return ok; | 1170 return ok; |
1171 } | 1171 } |
1172 | 1172 |
1173 SVCERR << "WARNING: SV-XML: Point element found in non-point dataset" << endl; | 1173 SVCERR << "WARNING: SV-XML: Point element found in non-point dataset" |
1174 << endl; | |
1174 | 1175 |
1175 return false; | 1176 return false; |
1176 } | 1177 } |
1177 | 1178 |
1178 bool | 1179 bool |
1179 SVFileReader::addBinToDataset(const QXmlAttributes &attributes) | 1180 SVFileReader::addBinToDataset(const QXmlAttributes &attributes) |
1180 { | 1181 { |
1181 EditableDenseThreeDimensionalModel *dtdm = | 1182 if (!haveModel(m_currentDataset)) { |
1182 dynamic_cast<EditableDenseThreeDimensionalModel *> | 1183 SVCERR << "WARNING: SV-XML: Bin definition found in incompatible dataset" |
1183 (m_currentDataset); | 1184 << endl; |
1184 | 1185 return false; |
1185 if (dtdm) { | 1186 } |
1187 | |
1188 ModelId modelId = m_models[m_currentDataset]; | |
1189 | |
1190 if (auto dtdm = ModelById::getAs<EditableDenseThreeDimensionalModel> | |
1191 (modelId)) { | |
1186 | 1192 |
1187 bool ok = false; | 1193 bool ok = false; |
1188 int n = attributes.value("number").trimmed().toInt(&ok); | 1194 int n = attributes.value("number").trimmed().toInt(&ok); |
1189 if (!ok) { | 1195 if (!ok) { |
1190 SVCERR << "WARNING: SV-XML: Missing or invalid bin number" | 1196 SVCERR << "WARNING: SV-XML: Missing or invalid bin number" |
1191 << endl; | 1197 << endl; |
1192 return false; | 1198 return false; |
1193 } | 1199 } |
1194 | 1200 |
1195 QString name = attributes.value("name"); | 1201 QString name = attributes.value("name"); |
1196 | |
1197 dtdm->setBinName(n, name); | 1202 dtdm->setBinName(n, name); |
1198 return true; | 1203 return true; |
1199 } | 1204 } |
1200 | 1205 |
1201 SVCERR << "WARNING: SV-XML: Bin definition found in incompatible dataset" << endl; | 1206 SVCERR << "WARNING: SV-XML: Bin definition found in incompatible dataset" |
1207 << endl; | |
1202 | 1208 |
1203 return false; | 1209 return false; |
1204 } | 1210 } |
1205 | 1211 |
1206 | 1212 |
1225 } | 1231 } |
1226 | 1232 |
1227 bool | 1233 bool |
1228 SVFileReader::readRowData(const QString &text) | 1234 SVFileReader::readRowData(const QString &text) |
1229 { | 1235 { |
1230 EditableDenseThreeDimensionalModel *dtdm = | 1236 if (!haveModel(m_currentDataset)) { |
1231 dynamic_cast<EditableDenseThreeDimensionalModel *> | 1237 SVCERR << "WARNING: SV-XML: Row data found in non-row dataset" << endl; |
1232 (m_currentDataset); | 1238 return false; |
1233 | 1239 } |
1240 | |
1241 ModelId modelId = m_models[m_currentDataset]; | |
1234 bool warned = false; | 1242 bool warned = false; |
1235 | 1243 |
1236 if (dtdm) { | 1244 if (auto dtdm = ModelById::getAs<EditableDenseThreeDimensionalModel> |
1245 (modelId)) { | |
1246 | |
1237 QStringList data = text.split(m_datasetSeparator); | 1247 QStringList data = text.split(m_datasetSeparator); |
1238 | 1248 |
1239 DenseThreeDimensionalModel::Column values; | 1249 DenseThreeDimensionalModel::Column values; |
1240 | 1250 |
1241 for (QStringList::iterator i = data.begin(); i != data.end(); ++i) { | 1251 for (QStringList::iterator i = data.begin(); i != data.end(); ++i) { |
1262 dtdm->setColumn(m_rowNumber, values); | 1272 dtdm->setColumn(m_rowNumber, values); |
1263 return true; | 1273 return true; |
1264 } | 1274 } |
1265 | 1275 |
1266 SVCERR << "WARNING: SV-XML: Row data found in non-row dataset" << endl; | 1276 SVCERR << "WARNING: SV-XML: Row data found in non-row dataset" << endl; |
1267 | |
1268 return false; | 1277 return false; |
1269 } | 1278 } |
1270 | 1279 |
1271 bool | 1280 bool |
1272 SVFileReader::readDerivation(const QXmlAttributes &attributes) | 1281 SVFileReader::readDerivation(const QXmlAttributes &attributes) |
1273 { | 1282 { |
1274 int modelId = 0; | 1283 int modelExportId = 0; |
1275 bool modelOk = false; | 1284 bool modelOk = false; |
1276 modelId = attributes.value("model").trimmed().toInt(&modelOk); | 1285 modelExportId = attributes.value("model").trimmed().toInt(&modelOk); |
1277 | 1286 |
1278 if (!modelOk) { | 1287 if (!modelOk) { |
1279 SVCERR << "WARNING: SV-XML: No model id specified for derivation" << endl; | 1288 SVCERR << "WARNING: SV-XML: No model id specified for derivation" << endl; |
1280 return false; | 1289 return false; |
1281 } | 1290 } |
1282 | 1291 |
1283 if (haveModel(modelId)) { | 1292 if (haveModel(modelExportId)) { |
1284 m_currentDerivedModel = m_models[modelId]; | 1293 m_currentDerivedModel = m_models[modelExportId]; |
1285 } else { | 1294 } else { |
1286 // we'll regenerate the model when the derivation element ends | 1295 // we'll regenerate the model when the derivation element ends |
1287 m_currentDerivedModel = nullptr; | 1296 m_currentDerivedModel = {}; |
1288 } | 1297 } |
1289 | 1298 |
1290 m_currentDerivedModelId = modelId; | 1299 m_pendingDerivedModel = modelExportId; |
1291 | 1300 |
1292 int sourceId = 0; | 1301 int sourceId = 0; |
1293 bool sourceOk = false; | 1302 bool sourceOk = false; |
1294 sourceId = attributes.value("source").trimmed().toInt(&sourceOk); | 1303 sourceId = attributes.value("source").trimmed().toInt(&sourceOk); |
1295 | 1304 |
1330 if (ok) m_currentTransform.setBlockSize(blockSize); | 1339 if (ok) m_currentTransform.setBlockSize(blockSize); |
1331 | 1340 |
1332 int windowType = attributes.value("windowType").trimmed().toInt(&ok); | 1341 int windowType = attributes.value("windowType").trimmed().toInt(&ok); |
1333 if (ok) m_currentTransform.setWindowType(WindowType(windowType)); | 1342 if (ok) m_currentTransform.setWindowType(WindowType(windowType)); |
1334 | 1343 |
1335 if (!m_currentTransformSource) return true; | 1344 auto currentTransformSourceModel = ModelById::get(m_currentTransformSource); |
1345 if (!currentTransformSourceModel) return true; | |
1346 | |
1347 sv_samplerate_t sampleRate = currentTransformSourceModel->getSampleRate(); | |
1336 | 1348 |
1337 QString startFrameStr = attributes.value("startFrame"); | 1349 QString startFrameStr = attributes.value("startFrame"); |
1338 QString durationStr = attributes.value("duration"); | 1350 QString durationStr = attributes.value("duration"); |
1339 | 1351 |
1340 int startFrame = 0; | 1352 int startFrame = 0; |
1348 duration = durationStr.trimmed().toInt(&ok); | 1360 duration = durationStr.trimmed().toInt(&ok); |
1349 if (!ok) duration = 0; | 1361 if (!ok) duration = 0; |
1350 } | 1362 } |
1351 | 1363 |
1352 m_currentTransform.setStartTime | 1364 m_currentTransform.setStartTime |
1353 (RealTime::frame2RealTime | 1365 (RealTime::frame2RealTime(startFrame, sampleRate)); |
1354 (startFrame, m_currentTransformSource->getSampleRate())); | |
1355 | 1366 |
1356 m_currentTransform.setDuration | 1367 m_currentTransform.setDuration |
1357 (RealTime::frame2RealTime | 1368 (RealTime::frame2RealTime(duration, sampleRate)); |
1358 (duration, m_currentTransformSource->getSampleRate())); | |
1359 | 1369 |
1360 return true; | 1370 return true; |
1361 } | 1371 } |
1362 | 1372 |
1363 bool | 1373 bool |
1364 SVFileReader::readPlayParameters(const QXmlAttributes &attributes) | 1374 SVFileReader::readPlayParameters(const QXmlAttributes &attributes) |
1365 { | 1375 { |
1366 m_currentPlayParameters = nullptr; | 1376 m_currentPlayParameters = nullptr; |
1367 | 1377 |
1368 int modelId = 0; | 1378 int modelExportId = 0; |
1369 bool modelOk = false; | 1379 bool modelOk = false; |
1370 modelId = attributes.value("model").trimmed().toInt(&modelOk); | 1380 modelExportId = attributes.value("model").trimmed().toInt(&modelOk); |
1371 | 1381 |
1372 if (!modelOk) { | 1382 if (!modelOk) { |
1373 SVCERR << "WARNING: SV-XML: No model id specified for play parameters" << endl; | 1383 SVCERR << "WARNING: SV-XML: No model id specified for play parameters" << endl; |
1374 return false; | 1384 return false; |
1375 } | 1385 } |
1376 | 1386 |
1377 if (haveModel(modelId)) { | 1387 if (haveModel(modelExportId)) { |
1378 | 1388 |
1379 bool ok = false; | 1389 bool ok = false; |
1380 | 1390 |
1381 PlayParameters *parameters = PlayParameterRepository::getInstance()-> | 1391 PlayParameters *parameters = PlayParameterRepository::getInstance()-> |
1382 getPlayParameters(m_models[modelId]); | 1392 getPlayParameters(m_models[modelExportId].untyped); |
1383 | 1393 |
1384 if (!parameters) { | 1394 if (!parameters) { |
1385 SVCERR << "WARNING: SV-XML: Play parameters for model " | 1395 SVCERR << "WARNING: SV-XML: Play parameters for model " |
1386 << modelId | 1396 << modelExportId |
1387 << " not found - has model been added to document?" | 1397 << " not found - has model been added to document?" |
1388 << endl; | 1398 << endl; |
1389 return false; | 1399 return false; |
1390 } | 1400 } |
1391 | 1401 |
1401 QString clipId = attributes.value("clipId"); | 1411 QString clipId = attributes.value("clipId"); |
1402 if (clipId != "") parameters->setPlayClipId(clipId); | 1412 if (clipId != "") parameters->setPlayClipId(clipId); |
1403 | 1413 |
1404 m_currentPlayParameters = parameters; | 1414 m_currentPlayParameters = parameters; |
1405 | 1415 |
1406 // SVCERR << "Current play parameters for model: " << m_models[modelId] << ": " << m_currentPlayParameters << endl; | 1416 // SVCERR << "Current play parameters for model: " << m_models[modelExportId] << ": " << m_currentPlayParameters << endl; |
1407 | 1417 |
1408 } else { | 1418 } else { |
1409 | 1419 |
1410 SVCERR << "WARNING: SV-XML: Unknown model " << modelId | 1420 SVCERR << "WARNING: SV-XML: Unknown model " << modelExportId |
1411 << " for play parameters" << endl; | 1421 << " for play parameters" << endl; |
1412 return false; | 1422 return false; |
1413 } | 1423 } |
1414 | 1424 |
1415 return true; | 1425 return true; |
1416 } | 1426 } |
1417 | 1427 |
1418 bool | 1428 bool |
1419 SVFileReader::readPlugin(const QXmlAttributes &attributes) | 1429 SVFileReader::readPlugin(const QXmlAttributes &attributes) |
1420 { | 1430 { |
1421 if (m_currentDerivedModelId >= 0) { | 1431 if (m_pendingDerivedModel != XmlExportable::NO_ID) { |
1422 return readPluginForTransform(attributes); | 1432 return readPluginForTransform(attributes); |
1423 } else if (m_currentPlayParameters) { | 1433 } else if (m_currentPlayParameters) { |
1424 return readPluginForPlayback(attributes); | 1434 return readPluginForPlayback(attributes); |
1425 } else { | 1435 } else { |
1426 SVCERR << "WARNING: SV-XML: Plugin found outside derivation or play parameters" << endl; | 1436 SVCERR << "WARNING: SV-XML: Plugin found outside derivation or play parameters" << endl; |
1467 } | 1477 } |
1468 | 1478 |
1469 bool | 1479 bool |
1470 SVFileReader::readTransform(const QXmlAttributes &attributes) | 1480 SVFileReader::readTransform(const QXmlAttributes &attributes) |
1471 { | 1481 { |
1472 if (m_currentDerivedModelId < 0) { | 1482 if (m_pendingDerivedModel == XmlExportable::NO_ID) { |
1473 SVCERR << "WARNING: SV-XML: Transform found outside derivation" << endl; | 1483 SVCERR << "WARNING: SV-XML: Transform found outside derivation" << endl; |
1474 return false; | 1484 return false; |
1475 } | 1485 } |
1476 | 1486 |
1477 m_currentTransform = Transform(); | 1487 m_currentTransform = Transform(); |
1480 } | 1490 } |
1481 | 1491 |
1482 bool | 1492 bool |
1483 SVFileReader::readParameter(const QXmlAttributes &attributes) | 1493 SVFileReader::readParameter(const QXmlAttributes &attributes) |
1484 { | 1494 { |
1485 if (m_currentDerivedModelId < 0) { | 1495 if (m_pendingDerivedModel == XmlExportable::NO_ID) { |
1486 SVCERR << "WARNING: SV-XML: Parameter found outside derivation" << endl; | 1496 SVCERR << "WARNING: SV-XML: Parameter found outside derivation" << endl; |
1487 return false; | 1497 return false; |
1488 } | 1498 } |
1489 | 1499 |
1490 QString name = attributes.value("name"); | 1500 QString name = attributes.value("name"); |