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");