comparison document/Document.cpp @ 201:de783e8ee5f0

* Hoist alignment model set/query up to Model, so any models can be aligned * Add Model::aboutToDelete and aboutToBeDeleted for management of models that are contained by or referred to by other models instead of only the document
author Chris Cannam
date Wed, 24 Oct 2007 15:21:38 +0000
parents 29c356da4ae4
children
comparison
equal deleted inserted replaced
200:1871581e4da9 201:de783e8ee5f0
28 #include "transform/TransformFactory.h" 28 #include "transform/TransformFactory.h"
29 #include <QApplication> 29 #include <QApplication>
30 #include <QTextStream> 30 #include <QTextStream>
31 #include <iostream> 31 #include <iostream>
32 32
33 // For alignment:
34 #include "data/model/AggregateWaveModel.h"
35 #include "data/model/SparseTimeValueModel.h"
36 #include "data/model/AlignmentModel.h"
37
33 //!!! still need to handle command history, documentRestored/documentModified 38 //!!! still need to handle command history, documentRestored/documentModified
34 39
35 Document::Document() : 40 Document::Document() :
36 m_mainModel(0) 41 m_mainModel(0)
37 { 42 {
58 std::cerr << "Document::~Document: WARNING: " 63 std::cerr << "Document::~Document: WARNING: "
59 << m_models.size() << " model(s) still remain -- " 64 << m_models.size() << " model(s) still remain -- "
60 << "should have been garbage collected when deleting layers" 65 << "should have been garbage collected when deleting layers"
61 << std::endl; 66 << std::endl;
62 while (!m_models.empty()) { 67 while (!m_models.empty()) {
63 if (m_models.begin()->first == m_mainModel) { 68 Model *model = m_models.begin()->first;
69 if (model == m_mainModel) {
64 // just in case! 70 // just in case!
65 std::cerr << "Document::~Document: WARNING: Main model is also" 71 std::cerr << "Document::~Document: WARNING: Main model is also"
66 << " in models list!" << std::endl; 72 << " in models list!" << std::endl;
67 } else { 73 } else if (model) {
68 emit modelAboutToBeDeleted(m_models.begin()->first); 74 emit modelAboutToBeDeleted(model);
69 delete m_models.begin()->first; 75 model->aboutToDelete();
76 delete model;
70 } 77 }
71 m_models.erase(m_models.begin()); 78 m_models.erase(m_models.begin());
72 } 79 }
73 } 80 }
74 81
75 // std::cerr << "Document::~Document: About to get rid of main model" 82 // std::cerr << "Document::~Document: About to get rid of main model"
76 // << std::endl; 83 // << std::endl;
77 emit modelAboutToBeDeleted(m_mainModel); 84 if (m_mainModel) {
85 emit modelAboutToBeDeleted(m_mainModel);
86 m_mainModel->aboutToDelete();
87 }
88
78 emit mainModelChanged(0); 89 emit mainModelChanged(0);
79 delete m_mainModel; 90 delete m_mainModel;
80 91
81 } 92 }
82 93
437 << sourceCount << " other derived model(s) -- resetting " 448 << sourceCount << " other derived model(s) -- resetting "
438 << "their source fields appropriately" << std::endl; 449 << "their source fields appropriately" << std::endl;
439 } 450 }
440 451
441 emit modelAboutToBeDeleted(model); 452 emit modelAboutToBeDeleted(model);
453 model->aboutToDelete();
442 m_models.erase(model); 454 m_models.erase(model);
443 delete model; 455 delete model;
444 } 456 }
445 } 457 }
446 458
645 models.push_back(dtvm); 657 models.push_back(dtvm);
646 } 658 }
647 } 659 }
648 660
649 return models; 661 return models;
662 }
663
664 void
665 Document::alignModel(Model *model)
666 {
667 if (!m_mainModel || model == m_mainModel) return;
668
669 RangeSummarisableTimeValueModel *rm =
670 dynamic_cast<RangeSummarisableTimeValueModel *>(model);
671 if (!rm) return;
672
673 // This involves creating three new models:
674
675 // 1. an AggregateWaveModel to provide the mixdowns of the main
676 // model and the new model in its two channels, as input to the
677 // MATCH plugin
678
679 // 2. a SparseTimeValueModel, which is the model automatically
680 // created by FeatureExtractionPluginTransform when running the
681 // MATCH plugin (thus containing the alignment path)
682
683 // 3. an AlignmentModel, which stores the path model and carries
684 // out alignment lookups on it.
685
686 // The first two of these are provided as arguments to the
687 // constructor for the third, which takes responsibility for
688 // deleting them. The AlignmentModel, meanwhile, is passed to the
689 // new model we are aligning, which also takes responsibility for
690 // it. We should not have to delete any of these new models here.
691
692 AggregateWaveModel::ChannelSpecList components;
693
694 components.push_back(AggregateWaveModel::ModelChannelSpec
695 (m_mainModel, -1));
696
697 components.push_back(AggregateWaveModel::ModelChannelSpec
698 (rm, -1));
699
700 Model *aggregate = new AggregateWaveModel(components);
701
702 TransformId id = "vamp:match-vamp-plugin:match:path";
703
704 TransformFactory *factory = TransformFactory::getInstance();
705
706 Model *transformOutput = factory->transform
707 (id, aggregate,
708 factory->getDefaultContextForTransform(id, aggregate),
709 "<plugin param-serialise=\"1\"/>");
710
711 SparseTimeValueModel *path = dynamic_cast<SparseTimeValueModel *>
712 (transformOutput);
713
714 if (!path) {
715 std::cerr << "Document::alignModel: ERROR: Failed to create alignment path (no MATCH plugin?)" << std::endl;
716 delete transformOutput;
717 delete aggregate;
718 return;
719 }
720
721 AlignmentModel *alignmentModel = new AlignmentModel
722 (m_mainModel, model, aggregate, path);
723
724 rm->setAlignment(alignmentModel);
725 }
726
727 void
728 Document::alignModels()
729 {
730 for (ModelMap::iterator i = m_models.begin(); i != m_models.end(); ++i) {
731 alignModel(i->first);
732 }
650 } 733 }
651 734
652 Document::AddLayerCommand::AddLayerCommand(Document *d, 735 Document::AddLayerCommand::AddLayerCommand(Document *d,
653 View *view, 736 View *view,
654 Layer *layer) : 737 Layer *layer) :