1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2
3 /*
4 Sonic Visualiser
5 An audio file viewer and annotation editor.
6 Centre for Digital Music, Queen Mary, University of London.
7 This file copyright 2006 Chris Cannam and QMUL.
8
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License as
11 published by the Free Software Foundation; either version 2 of the
12 License, or (at your option) any later version. See the file
13 COPYING included with this distribution for more information.
14 */
15
16 #include "Document.h"
17
18 #include "Align.h"
19
20 #include "data/model/WaveFileModel.h"
21 #include "data/model/WritableWaveFileModel.h"
22 #include "data/model/DenseThreeDimensionalModel.h"
23 #include "data/model/DenseTimeValueModel.h"
24 #include "data/model/AggregateWaveModel.h"
25
26 #include "layer/Layer.h"
27 #include "widgets/CommandHistory.h"
28 #include "base/Command.h"
29 #include "view/View.h"
30 #include "base/PlayParameterRepository.h"
31 #include "base/PlayParameters.h"
32 #include "transform/TransformFactory.h"
33 #include "transform/ModelTransformerFactory.h"
34 #include "transform/FeatureExtractionModelTransformer.h"
35 #include <QApplication>
36 #include <QTextStream>
37 #include <QSettings>
38 #include <iostream>
39 #include <typeinfo>
40
41 #include "data/model/AlignmentModel.h"
42 #include "Align.h"
43
44 using std::vector;
45
46 #define DEBUG_DOCUMENT 1
47
48 //!!! still need to handle command history, documentRestored/documentModified
49
Document()50 Document::Document() :
51 m_autoAlignment(false),
52 m_align(new Align()),
53 m_isIncomplete(false)
54 {
55 connect(ModelTransformerFactory::getInstance(),
56 SIGNAL(transformFailed(QString, QString)),
57 this,
58 SIGNAL(modelGenerationFailed(QString, QString)));
59
60 connect(m_align, SIGNAL(alignmentComplete(ModelId)),
61 this, SIGNAL(alignmentComplete(ModelId)));
62 }
63
~Document()64 Document::~Document()
65 {
66 //!!! Document should really own the command history. atm we
67 //still refer to it in various places that don't have access to
68 //the document, be nice to fix that
69
70 #ifdef DEBUG_DOCUMENT
71 SVDEBUG << "\n\nDocument::~Document: about to clear command history" << endl;
72 #endif
73 CommandHistory::getInstance()->clear();
74
75 #ifdef DEBUG_DOCUMENT
76 SVCERR << "Document::~Document: about to delete layers" << endl;
77 #endif
78 while (!m_layers.empty()) {
79 deleteLayer(*m_layers.begin(), true);
80 }
81
82 #ifdef DEBUG_DOCUMENT
83 SVCERR << "Document::~Document: about to release normal models" << endl;
84 #endif
85 for (auto mr: m_models) {
86 ModelById::release(mr.first);
87 }
88
89 #ifdef DEBUG_DOCUMENT
90 SVCERR << "Document::~Document: about to release aggregate models" << endl;
91 #endif
92 for (auto m: m_aggregateModels) {
93 ModelById::release(m);
94 }
95
96 #ifdef DEBUG_DOCUMENT
97 SVCERR << "Document::~Document: about to release alignment models" << endl;
98 #endif
99 for (auto m: m_alignmentModels) {
100 ModelById::release(m);
101 }
102
103 #ifdef DEBUG_DOCUMENT
104 SVCERR << "Document::~Document: about to release main model" << endl;
105 #endif
106 if (!m_mainModel.isNone()) {
107 ModelById::release(m_mainModel);
108 }
109
110 m_mainModel = {};
111 emit mainModelChanged({});
112 }
113
114 Layer *
createLayer(LayerFactory::LayerType type)115 Document::createLayer(LayerFactory::LayerType type)
116 {
117 Layer *newLayer = LayerFactory::getInstance()->createLayer(type);
118 if (!newLayer) return nullptr;
119
120 newLayer->setObjectName(getUniqueLayerName(newLayer->objectName()));
121
122 m_layers.push_back(newLayer);
123
124 #ifdef DEBUG_DOCUMENT
125 SVDEBUG << "Document::createLayer: Added layer of type " << type
126 << ", now have " << m_layers.size() << " layers" << endl;
127 #endif
128
129 emit layerAdded(newLayer);
130
131 return newLayer;
132 }
133
134 Layer *
createMainModelLayer(LayerFactory::LayerType type)135 Document::createMainModelLayer(LayerFactory::LayerType type)
136 {
137 Layer *newLayer = createLayer(type);
138 if (!newLayer) return nullptr;
139 setModel(newLayer, m_mainModel);
140 return newLayer;
141 }
142
143 Layer *
createImportedLayer(ModelId modelId)144 Document::createImportedLayer(ModelId modelId)
145 {
146 LayerFactory::LayerTypeSet types =
147 LayerFactory::getInstance()->getValidLayerTypes(modelId);
148
149 if (types.empty()) {
150 SVCERR << "WARNING: Document::importLayer: no valid display layer for model" << endl;
151 return nullptr;
152 }
153
154 //!!! for now, just use the first suitable layer type
155 LayerFactory::LayerType type = *types.begin();
156
157 Layer *newLayer = LayerFactory::getInstance()->createLayer(type);
158 if (!newLayer) return nullptr;
159
160 newLayer->setObjectName(getUniqueLayerName(newLayer->objectName()));
161
162 addNonDerivedModel(modelId);
163 setModel(newLayer, modelId);
164
165 //!!! and all channels
166 setChannel(newLayer, -1);
167
168 m_layers.push_back(newLayer);
169
170 #ifdef DEBUG_DOCUMENT
171 SVDEBUG << "Document::createImportedLayer: Added layer of type " << type
172 << ", now have " << m_layers.size() << " layers" << endl;
173 #endif
174
175 emit layerAdded(newLayer);
176 return newLayer;
177 }
178
179 Layer *
createEmptyLayer(LayerFactory::LayerType type)180 Document::createEmptyLayer(LayerFactory::LayerType type)
181 {
182 if (m_mainModel.isNone()) return nullptr;
183
184 auto newModel =
185 LayerFactory::getInstance()->createEmptyModel(type, m_mainModel);
186 if (!newModel) return nullptr;
187
188 Layer *newLayer = createLayer(type);
189 if (!newLayer) {
190 return nullptr;
191 }
192
193 auto newModelId = ModelById::add(newModel);
194 addNonDerivedModel(newModelId);
195 setModel(newLayer, newModelId);
196
197 return newLayer;
198 }
199
200 Layer *
createDerivedLayer(LayerFactory::LayerType type,TransformId transform)201 Document::createDerivedLayer(LayerFactory::LayerType type,
202 TransformId transform)
203 {
204 Layer *newLayer = createLayer(type);
205 if (!newLayer) return nullptr;
206
207 newLayer->setObjectName(getUniqueLayerName
208 (TransformFactory::getInstance()->
209 getTransformFriendlyName(transform)));
210
211 return newLayer;
212 }
213
214 Layer *
createDerivedLayer(const Transform & transform,const ModelTransformer::Input & input)215 Document::createDerivedLayer(const Transform &transform,
216 const ModelTransformer::Input &input)
217 {
218 Transforms transforms;
219 transforms.push_back(transform);
220 vector<Layer *> layers = createDerivedLayers(transforms, input);
221 if (layers.empty()) return nullptr;
222 else return layers[0];
223 }
224
225 vector<Layer *>
createDerivedLayers(const Transforms & transforms,const ModelTransformer::Input & input)226 Document::createDerivedLayers(const Transforms &transforms,
227 const ModelTransformer::Input &input)
228 {
229 QString message;
230 vector<ModelId> newModels =
231 addDerivedModels(transforms, input, message, nullptr);
232
233 if (newModels.empty()) {
234 //!!! This identifier may be wrong!
235 emit modelGenerationFailed(transforms[0].getIdentifier(), message);
236 return vector<Layer *>();
237 } else if (message != "") {
238 //!!! This identifier may be wrong!
239 emit modelGenerationWarning(transforms[0].getIdentifier(), message);
240 }
241
242 QStringList names;
243 for (int i = 0; in_range_for(newModels, i); ++i) {
244 names.push_back(getUniqueLayerName
245 (TransformFactory::getInstance()->
246 getTransformFriendlyName
247 (transforms[i].getIdentifier())));
248 }
249
250 vector<Layer *> layers = createLayersForDerivedModels(newModels, names);
251 return layers;
252 }
253
254 class AdditionalModelConverter :
255 public ModelTransformerFactory::AdditionalModelHandler
256 {
257 public:
AdditionalModelConverter(Document * doc,Document::LayerCreationHandler * handler)258 AdditionalModelConverter(Document *doc,
259 Document::LayerCreationHandler *handler) :
260 m_doc(doc),
261 m_handler(handler) {
262 }
263
~AdditionalModelConverter()264 ~AdditionalModelConverter() override { }
265
266 void
setPrimaryLayers(vector<Layer * > layers)267 setPrimaryLayers(vector<Layer *> layers) {
268 m_primary = layers;
269 }
270
271 void
moreModelsAvailable(vector<ModelId> models)272 moreModelsAvailable(vector<ModelId> models) override {
273 SVDEBUG << "AdditionalModelConverter::moreModelsAvailable: " << models.size() << " model(s)" << endl;
274 // We can't automatically regenerate the additional models on
275 // reload - so they go in m_additionalModels instead of m_models
276 QStringList names;
277 foreach (ModelId modelId, models) {
278 m_doc->addAdditionalModel(modelId);
279 names.push_back(QString());
280 }
281 vector<Layer *> layers = m_doc->createLayersForDerivedModels
282 (models, names);
283 m_handler->layersCreated(this, m_primary, layers);
284 delete this;
285 }
286
287 void
noMoreModelsAvailable()288 noMoreModelsAvailable() override {
289 SVDEBUG << "AdditionalModelConverter::noMoreModelsAvailable" << endl;
290 m_handler->layersCreated(this, m_primary, vector<Layer *>());
291 delete this;
292 }
293
cancel()294 void cancel() {
295 foreach (Layer *layer, m_primary) {
296 m_doc->setModel(layer, {});
297 }
298 }
299
300 private:
301 Document *m_doc;
302 vector<Layer *> m_primary;
303 Document::LayerCreationHandler *m_handler; //!!! how to handle destruction of this?
304 };
305
306 Document::LayerCreationAsyncHandle
createDerivedLayersAsync(const Transforms & transforms,const ModelTransformer::Input & input,LayerCreationHandler * handler)307 Document::createDerivedLayersAsync(const Transforms &transforms,
308 const ModelTransformer::Input &input,
309 LayerCreationHandler *handler)
310 {
311 QString message;
312
313 AdditionalModelConverter *amc = new AdditionalModelConverter(this, handler);
314
315 vector<ModelId> newModels = addDerivedModels
316 (transforms, input, message, amc);
317
318 QStringList names;
319 for (int i = 0; in_range_for(newModels, i); ++i) {
320 names.push_back(getUniqueLayerName
321 (TransformFactory::getInstance()->
322 getTransformFriendlyName
323 (transforms[i].getIdentifier())));
324 }
325
326 vector<Layer *> layers = createLayersForDerivedModels(newModels, names);
327 amc->setPrimaryLayers(layers);
328
329 if (newModels.empty()) {
330 //!!! This identifier may be wrong!
331 emit modelGenerationFailed(transforms[0].getIdentifier(), message);
332 //!!! what to do with amc?
333 } else if (message != "") {
334 //!!! This identifier may be wrong!
335 emit modelGenerationWarning(transforms[0].getIdentifier(), message);
336 //!!! what to do with amc?
337 }
338
339 return amc;
340 }
341
342 void
cancelAsyncLayerCreation(Document::LayerCreationAsyncHandle h)343 Document::cancelAsyncLayerCreation(Document::LayerCreationAsyncHandle h)
344 {
345 AdditionalModelConverter *conv = static_cast<AdditionalModelConverter *>(h);
346 conv->cancel();
347 }
348
349 vector<Layer *>
createLayersForDerivedModels(vector<ModelId> newModels,QStringList names)350 Document::createLayersForDerivedModels(vector<ModelId> newModels,
351 QStringList names)
352 {
353 vector<Layer *> layers;
354
355 for (int i = 0; in_range_for(newModels, i); ++i) {
356
357 ModelId newModelId = newModels[i];
358
359 LayerFactory::LayerTypeSet types =
360 LayerFactory::getInstance()->getValidLayerTypes(newModelId);
361
362 if (types.empty()) {
363 SVCERR << "WARNING: Document::createLayerForTransformer: no valid display layer for output of transform " << names[i] << endl;
364 releaseModel(newModelId);
365 return vector<Layer *>();
366 }
367
368 //!!! for now, just use the first suitable layer type
369
370 Layer *newLayer = createLayer(*types.begin());
371 setModel(newLayer, newModelId);
372
373 //!!! We need to clone the model when adding the layer, so that it
374 //can be edited without affecting other layers that are based on
375 //the same model. Unfortunately we can't just clone it now,
376 //because it probably hasn't been completed yet -- the transform
377 //runs in the background. Maybe the transform has to handle
378 //cloning and cacheing models itself.
379 //
380 // Once we do clone models here, of course, we'll have to avoid
381 // leaking them too.
382 //
383 // We want the user to be able to add a model to a second layer
384 // _while it's still being calculated in the first_ and have it
385 // work quickly. That means we need to put the same physical
386 // model pointer in both layers, so they can't actually be cloned.
387
388 if (newLayer) {
389 newLayer->setObjectName(names[i]);
390 }
391
392 emit layerAdded(newLayer);
393 layers.push_back(newLayer);
394 }
395
396 return layers;
397 }
398
399 void
setMainModel(ModelId modelId)400 Document::setMainModel(ModelId modelId)
401 {
402 ModelId oldMainModel = m_mainModel;
403 m_mainModel = modelId;
404
405 emit modelAdded(m_mainModel);
406
407 if (auto model = ModelById::get(modelId)) {
408 emit activity(tr("Set main model to %1").arg(model->objectName()));
409 } else {
410 emit activity(tr("Clear main model"));
411 }
412
413 std::vector<Layer *> obsoleteLayers;
414 std::set<QString> failedTransformers;
415
416 // We need to ensure that no layer is left using oldMainModel or
417 // any of the old derived models as its model. Either replace the
418 // model, or delete the layer for each layer that is currently
419 // using one of these. Carry out this replacement before we
420 // delete any of the models.
421
422 #ifdef DEBUG_DOCUMENT
423 SVDEBUG << "Document::setMainModel: Have "
424 << m_layers.size() << " layers" << endl;
425 SVDEBUG << "Models now: ";
426 for (const auto &r: m_models) {
427 SVDEBUG << r.first << " ";
428 }
429 SVDEBUG << endl;
430 SVDEBUG << "Old main model: " << oldMainModel << endl;
431 #endif
432
433 for (Layer *layer: m_layers) {
434
435 ModelId modelId = layer->getModel();
436
437 #ifdef DEBUG_DOCUMENT
438 SVDEBUG << "Document::setMainModel: inspecting model "
439 << modelId << " in layer " << layer->objectName() << endl;
440 #endif
441
442 if (modelId == oldMainModel) {
443 #ifdef DEBUG_DOCUMENT
444 SVDEBUG << "... it uses the old main model, replacing" << endl;
445 #endif
446 LayerFactory::getInstance()->setModel(layer, m_mainModel);
447 continue;
448 }
449
450 if (modelId.isNone()) {
451 SVCERR << "WARNING: Document::setMainModel: Null model in layer "
452 << layer << endl;
453 // get rid of this hideous degenerate
454 obsoleteLayers.push_back(layer);
455 continue;
456 }
457
458 if (m_models.find(modelId) == m_models.end()) {
459 SVCERR << "WARNING: Document::setMainModel: Unknown model "
460 << modelId << " in layer " << layer << endl;
461 // and this one
462 obsoleteLayers.push_back(layer);
463 continue;
464 }
465
466 ModelRecord record = m_models[modelId];
467
468 if (!record.source.isNone() && (record.source == oldMainModel)) {
469
470 #ifdef DEBUG_DOCUMENT
471 SVDEBUG << "... it uses a model derived from the old main model, regenerating" << endl;
472 #endif
473
474 // This model was derived from the previous main
475 // model: regenerate it.
476
477 const Transform &transform = record.transform;
478 QString transformId = transform.getIdentifier();
479
480 //!!! We have a problem here if the number of channels in
481 //the main model has changed.
482
483 QString message;
484 ModelId replacementModel =
485 addDerivedModel(transform,
486 ModelTransformer::Input
487 (m_mainModel, record.channel),
488 message);
489
490 if (replacementModel.isNone()) {
491 SVCERR << "WARNING: Document::setMainModel: Failed to regenerate model for transform \""
492 << transformId << "\"" << " in layer " << layer << endl;
493 if (failedTransformers.find(transformId)
494 == failedTransformers.end()) {
495 emit modelRegenerationFailed(layer->objectName(),
496 transformId,
497 message);
498 failedTransformers.insert(transformId);
499 }
500 obsoleteLayers.push_back(layer);
501 } else {
502 if (message != "") {
503 emit modelRegenerationWarning(layer->objectName(),
504 transformId,
505 message);
506 }
507 #ifdef DEBUG_DOCUMENT
508 SVDEBUG << "Replacing model " << modelId << ") with model "
509 << replacementModel << ") in layer "
510 << layer << " (name " << layer->objectName() << ")"
511 << endl;
512
513 auto rm = ModelById::getAs<RangeSummarisableTimeValueModel>(replacementModel);
514 if (rm) {
515 SVDEBUG << "new model has " << rm->getChannelCount() << " channels " << endl;
516 } else {
517 SVDEBUG << "new model " << replacementModel << " is not a RangeSummarisableTimeValueModel!" << endl;
518 }
519 #endif
520 setModel(layer, replacementModel);
521 }
522 }
523 }
524
525 for (size_t k = 0; k < obsoleteLayers.size(); ++k) {
526 deleteLayer(obsoleteLayers[k], true);
527 }
528
529 std::set<ModelId> additionalModels;
530 for (const auto &rec : m_models) {
531 if (rec.second.additional) {
532 additionalModels.insert(rec.first);
533 }
534 }
535 for (ModelId a: additionalModels) {
536 m_models.erase(a);
537 }
538
539 for (const auto &rec : m_models) {
540
541 auto m = ModelById::get(rec.first);
542 if (!m) continue;
543
544 #ifdef DEBUG_DOCUMENT
545 SVDEBUG << "considering alignment for model " << rec.first << endl;
546 #endif
547
548 if (m_autoAlignment) {
549
550 alignModel(rec.first);
551
552 } else if (!oldMainModel.isNone() &&
553 (m->getAlignmentReference() == oldMainModel)) {
554
555 alignModel(rec.first);
556 }
557 }
558
559 if (m_autoAlignment) {
560 SVDEBUG << "Document::setMainModel: auto-alignment is on, aligning model if possible" << endl;
561 alignModel(m_mainModel);
562 } else {
563 SVDEBUG << "Document::setMainModel: auto-alignment is off" << endl;
564 }
565
566 emit mainModelChanged(m_mainModel);
567
568 if (!oldMainModel.isNone()) {
569
570 // Remove the playable explicitly - the main model's dtor will
571 // do this, but just in case something is still hanging onto a
572 // shared_ptr to the old main model so it doesn't get deleted
573 PlayParameterRepository::getInstance()->removePlayable
574 (oldMainModel.untyped);
575
576 ModelById::release(oldMainModel);
577 }
578 }
579
580 void
addAlreadyDerivedModel(const Transform & transform,const ModelTransformer::Input & input,ModelId outputModelToAdd)581 Document::addAlreadyDerivedModel(const Transform &transform,
582 const ModelTransformer::Input &input,
583 ModelId outputModelToAdd)
584 {
585 if (m_models.find(outputModelToAdd) != m_models.end()) {
586 SVCERR << "WARNING: Document::addAlreadyDerivedModel: Model already added"
587 << endl;
588 return;
589 }
590
591 #ifdef DEBUG_DOCUMENT
592 SVDEBUG << "Document::addAlreadyDerivedModel: source is " << input.getModel() << endl;
593 #endif
594
595 ModelRecord rec;
596 rec.source = input.getModel();
597 rec.channel = input.getChannel();
598 rec.transform = transform;
599 rec.additional = false;
600
601 if (auto m = ModelById::get(outputModelToAdd)) {
602 m->setSourceModel(input.getModel());
603 }
604
605 m_models[outputModelToAdd] = rec;
606
607 #ifdef DEBUG_DOCUMENT
608 SVDEBUG << "Document::addAlreadyDerivedModel: Added model " << outputModelToAdd << endl;
609 SVDEBUG << "Models now: ";
610 for (const auto &rec : m_models) {
611 SVDEBUG << rec.first << " ";
612 }
613 SVDEBUG << endl;
614 #endif
615
616 emit modelAdded(outputModelToAdd);
617 }
618
619 void
addNonDerivedModel(ModelId modelId)620 Document::addNonDerivedModel(ModelId modelId)
621 {
622 if (ModelById::isa<AggregateWaveModel>(modelId)) {
623 #ifdef DEBUG_DOCUMENT
624 SVCERR << "Document::addNonDerivedModel: Model " << modelId << " is an aggregate model, adding it to aggregates" << endl;
625 #endif
626 m_aggregateModels.insert(modelId);
627 return;
628 }
629 if (ModelById::isa<AlignmentModel>(modelId)) {
630 #ifdef DEBUG_DOCUMENT
631 SVCERR << "Document::addNonDerivedModel: Model " << modelId << " is an alignment model, adding it to alignments" << endl;
632 #endif
633 m_alignmentModels.insert(modelId);
634 return;
635 }
636
637 if (m_models.find(modelId) != m_models.end()) {
638 SVCERR << "WARNING: Document::addNonDerivedModel: Model already added"
639 << endl;
640 return;
641 }
642
643 ModelRecord rec;
644 rec.source = {};
645 rec.channel = 0;
646 rec.additional = false;
647
648 m_models[modelId] = rec;
649
650 #ifdef DEBUG_DOCUMENT
651 SVCERR << "Document::addNonDerivedModel: Added model " << modelId << endl;
652 SVCERR << "Models now: ";
653 for (const auto &rec : m_models) {
654 SVCERR << rec.first << " ";
655 }
656 SVCERR << endl;
657 #endif
658
659 if (m_autoAlignment) {
660 SVDEBUG << "Document::addNonDerivedModel: auto-alignment is on, aligning model if possible" << endl;
661 alignModel(modelId);
662 } else {
663 SVDEBUG << "Document(" << this << "): addNonDerivedModel: auto-alignment is off" << endl;
664 }
665
666 emit modelAdded(modelId);
667 }
668
669 void
addAdditionalModel(ModelId modelId)670 Document::addAdditionalModel(ModelId modelId)
671 {
672 if (m_models.find(modelId) != m_models.end()) {
673 SVCERR << "WARNING: Document::addAdditionalModel: Model already added"
674 << endl;
675 return;
676 }
677
678 ModelRecord rec;
679 rec.source = {};
680 rec.channel = 0;
681 rec.additional = true;
682
683 m_models[modelId] = rec;
684
685 #ifdef DEBUG_DOCUMENT
686 SVDEBUG << "Document::addAdditionalModel: Added model " << modelId << endl;
687 SVDEBUG << "Models now: ";
688 for (const auto &rec : m_models) {
689 SVDEBUG << rec.first << " ";
690 }
691 SVDEBUG << endl;
692 #endif
693
694 if (m_autoAlignment &&
695 ModelById::isa<RangeSummarisableTimeValueModel>(modelId)) {
696 SVDEBUG << "Document::addAdditionalModel: auto-alignment is on and model is an alignable type, aligning it if possible" << endl;
697 alignModel(modelId);
698 }
699
700 emit modelAdded(modelId);
701 }
702
703 ModelId
addDerivedModel(const Transform & transform,const ModelTransformer::Input & input,QString & message)704 Document::addDerivedModel(const Transform &transform,
705 const ModelTransformer::Input &input,
706 QString &message)
707 {
708 for (auto &rec : m_models) {
709 if (rec.second.transform == transform &&
710 rec.second.source == input.getModel() &&
711 rec.second.channel == input.getChannel()) {
712 SVDEBUG << "derived model taken from map " << endl;
713 return rec.first;
714 }
715 }
716
717 Transforms tt;
718 tt.push_back(transform);
719 vector<ModelId> mm = addDerivedModels(tt, input, message, nullptr);
720 if (mm.empty()) return {};
721 else return mm[0];
722 }
723
724 vector<ModelId>
addDerivedModels(const Transforms & transforms,const ModelTransformer::Input & input,QString & message,AdditionalModelConverter * amc)725 Document::addDerivedModels(const Transforms &transforms,
726 const ModelTransformer::Input &input,
727 QString &message,
728 AdditionalModelConverter *amc)
729 {
730 vector<ModelId> mm =
731 ModelTransformerFactory::getInstance()->transformMultiple
732 (transforms, input, message, amc);
733
734 for (int j = 0; in_range_for(mm, j); ++j) {
735
736 ModelId modelId = mm[j];
737 Transform applied = transforms[j];
738
739 if (modelId.isNone()) {
740 SVCERR << "WARNING: Document::addDerivedModel: no output model for transform " << applied.getIdentifier() << endl;
741 continue;
742 }
743
744 // The transform we actually used was presumably identical to
745 // the one asked for, except that the version of the plugin
746 // may differ. It's possible that the returned message
747 // contains a warning about this; that doesn't concern us
748 // here, but we do need to ensure that the transform we
749 // remember is correct for what was actually applied, with the
750 // current plugin version.
751
752 //!!! would be nice to short-circuit this -- the version is
753 //!!! static data, shouldn't have to construct a plugin for it
754 //!!! (which may be expensive in Piper-world)
755 applied.setPluginVersion
756 (TransformFactory::getInstance()->
757 getDefaultTransformFor(applied.getIdentifier(),
758 applied.getSampleRate())
759 .getPluginVersion());
760
761 addAlreadyDerivedModel(applied, input, modelId);
762 }
763
764 return mm;
765 }
766
767 void
releaseModel(ModelId modelId)768 Document::releaseModel(ModelId modelId)
769 {
770 // This is called when a layer has been deleted or has replaced
771 // its model, in order to reclaim storage for the old model. It
772 // could be a no-op without making any functional difference, as
773 // all the models stored in the ById pool are released when the
774 // document is deleted. But models can sometimes be large, so if
775 // we know no other layer is using one, we should release it. If
776 // we happen to release one that is being used, the ModelById
777 // borrowed-pointer mechanism will at least prevent memory errors,
778 // although the other code will have to stop whatever it's doing.
779
780 // "warning: expression with side effects will be evaluated despite
781 // being used as an operand to 'typeid'"
782 #ifdef __clang__
783 #pragma clang diagnostic ignored "-Wpotentially-evaluated-expression"
784 #endif
785
786 if (auto model = ModelById::get(modelId)) {
787 SVCERR << "Document::releaseModel(" << modelId << "), name "
788 << model->objectName() << ", type "
789 << typeid(*model.get()).name() << endl;
790 } else {
791 SVCERR << "Document::releaseModel(" << modelId << ")" << endl;
792 }
793
794 if (modelId.isNone()) {
795 return;
796 }
797
798 #ifdef DEBUG_DOCUMENT
799 SVCERR << "Document::releaseModel(" << modelId << ")" << endl;
800 #endif
801
802 if (modelId == m_mainModel) {
803 #ifdef DEBUG_DOCUMENT
804 SVCERR << "Document::releaseModel: It's the main model, ignoring"
805 << endl;
806 #endif
807 return;
808 }
809
810 if (m_models.find(modelId) == m_models.end()) {
811 // No point in releasing aggregate and alignment models,
812 // they're not large
813 #ifdef DEBUG_DOCUMENT
814 SVCERR << "Document::releaseModel: It's not a regular layer model, ignoring" << endl;
815 #endif
816 return;
817 }
818
819 for (auto layer: m_layers) {
820 if (layer->getModel() == modelId) {
821 #ifdef DEBUG_DOCUMENT
822 SVCERR << "Document::releaseModel: It's still in use in at least one layer (e.g. " << layer << ", \"" << layer->getLayerPresentationName() << "\"), ignoring" << endl;
823 #endif
824 return;
825 }
826 }
827
828 #ifdef DEBUG_DOCUMENT
829 SVCERR << "Document::releaseModel: Seems to be OK to release this one"
830 << endl;
831 #endif
832
833 int sourceCount = 0;
834
835 for (auto &m: m_models) {
836 if (m.second.source == modelId) {
837 ++sourceCount;
838 m.second.source = {};
839 }
840 }
841
842 if (sourceCount > 0) {
843 SVCERR << "Document::releaseModel: Request to release model "
844 << modelId << " even though it was source for "
845 << sourceCount << " other derived model(s) -- have cleared "
846 << "their source fields" << endl;
847 }
848
849 m_models.erase(modelId);
850 ModelById::release(modelId);
851 }
852
853 void
deleteLayer(Layer * layer,bool force)854 Document::deleteLayer(Layer *layer, bool force)
855 {
856 if (m_layerViewMap.find(layer) != m_layerViewMap.end() &&
857 m_layerViewMap[layer].size() > 0) {
858
859 if (force) {
860
861 SVDEBUG << "NOTE: Document::deleteLayer: Layer "
862 << layer << " [" << layer->objectName() << "]"
863 << " is still used in " << m_layerViewMap[layer].size()
864 << " views. Force flag set, so removing from them" << endl;
865
866 for (std::set<View *>::iterator j = m_layerViewMap[layer].begin();
867 j != m_layerViewMap[layer].end(); ++j) {
868 // don't use removeLayerFromView, as it issues a command
869 layer->setLayerDormant(*j, true);
870 (*j)->removeLayer(layer);
871 }
872
873 m_layerViewMap.erase(layer);
874
875 } else {
876
877 SVCERR << "WARNING: Document::deleteLayer: Layer "
878 << layer << " [" << layer->objectName() << "]"
879 << " is still used in " << m_layerViewMap[layer].size()
880 << " views! Force flag is not set, so not deleting" << endl;
881
882 return;
883 }
884 }
885
886 bool found = false;
887 for (auto itr = m_layers.begin(); itr != m_layers.end(); ++itr) {
888 if (*itr == layer) {
889 found = true;
890 m_layers.erase(itr);
891 break;
892 }
893 }
894 if (!found) {
895 SVDEBUG << "Document::deleteLayer: Layer "
896 << layer << " (typeid " << typeid(layer).name() <<
897 ") does not exist, or has already been deleted "
898 << "(this may not be as serious as it sounds)" << endl;
899 return;
900 }
901
902 #ifdef DEBUG_DOCUMENT
903 SVDEBUG << "Document::deleteLayer: Removing (and about to release model), now have "
904 << m_layers.size() << " layers" << endl;
905 #endif
906
907 releaseModel(layer->getModel());
908 emit layerRemoved(layer);
909 emit layerAboutToBeDeleted(layer);
910 delete layer;
911 }
912
913 void
setModel(Layer * layer,ModelId modelId)914 Document::setModel(Layer *layer, ModelId modelId)
915 {
916 if (!modelId.isNone() &&
917 modelId != m_mainModel &&
918 m_models.find(modelId) == m_models.end()) {
919 SVCERR << "ERROR: Document::setModel: Layer " << layer
920 << " (\"" << layer->objectName()
921 << "\") wants to use unregistered model " << modelId
922 << ": register the layer's model before setting it!"
923 << endl;
924 return;
925 }
926
927 ModelId previousModel = layer->getModel();
928
929 if (previousModel == modelId) {
930 SVDEBUG << "NOTE: Document::setModel: Layer " << layer << " (\""
931 << layer->objectName()
932 << "\") is already set to model "
933 << modelId << endl;
934 return;
935 }
936
937 if (!modelId.isNone() && !previousModel.isNone()) {
938 PlayParameterRepository::getInstance()->copyParameters
939 (previousModel.untyped, modelId.untyped);
940 }
941
942 LayerFactory::getInstance()->setModel(layer, modelId);
943
944 releaseModel(previousModel);
945 }
946
947 void
setChannel(Layer * layer,int channel)948 Document::setChannel(Layer *layer, int channel)
949 {
950 LayerFactory::getInstance()->setChannel(layer, channel);
951 }
952
953 void
addLayerToView(View * view,Layer * layer)954 Document::addLayerToView(View *view, Layer *layer)
955 {
956 ModelId modelId = layer->getModel();
957 if (modelId.isNone()) {
958 #ifdef DEBUG_DOCUMENT
959 SVDEBUG << "Document::addLayerToView: Layer (\""
960 << layer->objectName()
961 << "\") with no model being added to view: "
962 << "normally you want to set the model first" << endl;
963 #endif
964 } else {
965 if (modelId != m_mainModel &&
966 m_models.find(modelId) == m_models.end()) {
967 SVCERR << "ERROR: Document::addLayerToView: Layer " << layer
968 << " has unregistered model " << modelId
969 << " -- register the layer's model before adding the layer!" << endl;
970 return;
971 }
972 }
973
974 CommandHistory::getInstance()->addCommand
975 (new Document::AddLayerCommand(this, view, layer));
976 }
977
978 void
removeLayerFromView(View * view,Layer * layer)979 Document::removeLayerFromView(View *view, Layer *layer)
980 {
981 CommandHistory::getInstance()->addCommand
982 (new Document::RemoveLayerCommand(this, view, layer));
983 }
984
985 void
addToLayerViewMap(Layer * layer,View * view)986 Document::addToLayerViewMap(Layer *layer, View *view)
987 {
988 bool firstView = (m_layerViewMap.find(layer) == m_layerViewMap.end() ||
989 m_layerViewMap[layer].empty());
990
991 if (m_layerViewMap[layer].find(view) !=
992 m_layerViewMap[layer].end()) {
993 SVCERR << "WARNING: Document::addToLayerViewMap:"
994 << " Layer " << layer << " -> view " << view << " already in"
995 << " layer view map -- internal inconsistency" << endl;
996 }
997
998 m_layerViewMap[layer].insert(view);
999
1000 if (firstView) emit layerInAView(layer, true);
1001 }
1002
1003 void
removeFromLayerViewMap(Layer * layer,View * view)1004 Document::removeFromLayerViewMap(Layer *layer, View *view)
1005 {
1006 if (m_layerViewMap[layer].find(view) ==
1007 m_layerViewMap[layer].end()) {
1008 SVCERR << "WARNING: Document::removeFromLayerViewMap:"
1009 << " Layer " << layer << " -> view " << view << " not in"
1010 << " layer view map -- internal inconsistency" << endl;
1011 }
1012
1013 m_layerViewMap[layer].erase(view);
1014
1015 if (m_layerViewMap[layer].empty()) {
1016 m_layerViewMap.erase(layer);
1017 emit layerInAView(layer, false);
1018 }
1019 }
1020
1021 QString
getUniqueLayerName(QString candidate)1022 Document::getUniqueLayerName(QString candidate)
1023 {
1024 for (int count = 1; ; ++count) {
1025
1026 QString adjusted =
1027 (count > 1 ? QString("%1 <%2>").arg(candidate).arg(count) :
1028 candidate);
1029
1030 bool duplicate = false;
1031
1032 for (auto i = m_layers.begin(); i != m_layers.end(); ++i) {
1033 if ((*i)->objectName() == adjusted) {
1034 duplicate = true;
1035 break;
1036 }
1037 }
1038
1039 if (!duplicate) return adjusted;
1040 }
1041 }
1042
1043 std::vector<ModelId>
getTransformInputModels()1044 Document::getTransformInputModels()
1045 {
1046 std::vector<ModelId> models;
1047
1048 if (m_mainModel.isNone()) return models;
1049
1050 models.push_back(m_mainModel);
1051
1052 //!!! This will pick up all models, including those that aren't visible...
1053
1054 for (auto rec: m_models) {
1055
1056 ModelId modelId = rec.first;
1057 if (modelId == m_mainModel) continue;
1058
1059 auto dtvm = ModelById::getAs<DenseTimeValueModel>(modelId);
1060 if (dtvm) {
1061 models.push_back(modelId);
1062 }
1063 }
1064
1065 return models;
1066 }
1067
1068 bool
isKnownModel(const ModelId modelId) const1069 Document::isKnownModel(const ModelId modelId) const
1070 {
1071 if (modelId == m_mainModel) return true;
1072 for (auto rec: m_models) {
1073 if (rec.first == modelId) return true;
1074 }
1075 return false;
1076 }
1077
1078 bool
canAlign()1079 Document::canAlign()
1080 {
1081 return Align::canAlign();
1082 }
1083
1084 void
alignModel(ModelId modelId,bool forceRecalculate)1085 Document::alignModel(ModelId modelId, bool forceRecalculate)
1086 {
1087 SVDEBUG << "Document::alignModel(" << modelId << ", " << forceRecalculate
1088 << ") (main model is " << m_mainModel << ")" << endl;
1089
1090 auto rm = ModelById::getAs<RangeSummarisableTimeValueModel>(modelId);
1091 if (!rm) {
1092 SVDEBUG << "(model " << modelId << " is not an alignable sort)" << endl;
1093 return;
1094 }
1095
1096 if (m_mainModel.isNone()) {
1097 SVDEBUG << "(no main model to align to)" << endl;
1098 if (forceRecalculate && !rm->getAlignment().isNone()) {
1099 SVDEBUG << "(but model is aligned, and forceRecalculate is true, "
1100 << "so resetting alignment to nil)" << endl;
1101 rm->setAlignment({});
1102 }
1103 return;
1104 }
1105
1106 if (rm->getAlignmentReference() == m_mainModel) {
1107 SVDEBUG << "(model " << modelId << " is already aligned to main model "
1108 << m_mainModel << ")" << endl;
1109 if (!forceRecalculate) {
1110 return;
1111 } else {
1112 SVDEBUG << "(but forceRecalculate is true, so realigning anyway)"
1113 << endl;
1114 }
1115 }
1116
1117 if (modelId == m_mainModel) {
1118 // The reference has an empty alignment to itself. This makes
1119 // it possible to distinguish between the reference and any
1120 // unaligned model just by looking at the model itself,
1121 // without also knowing what the main model is
1122 SVDEBUG << "Document::alignModel(" << modelId
1123 << "): is main model, setting alignment to itself" << endl;
1124 auto alignment = std::make_shared<AlignmentModel>(modelId, modelId,
1125 ModelId());
1126
1127 ModelId alignmentModelId = ModelById::add(alignment);
1128 rm->setAlignment(alignmentModelId);
1129 m_alignmentModels.insert(alignmentModelId);
1130 return;
1131 }
1132
1133 auto w = ModelById::getAs<WritableWaveFileModel>(modelId);
1134 if (w && w->getWriteProportion() < 100) {
1135 SVDEBUG << "Document::alignModel(" << modelId
1136 << "): model write is not complete, deferring"
1137 << endl;
1138 connect(w.get(), SIGNAL(writeCompleted(ModelId)),
1139 this, SLOT(performDeferredAlignment(ModelId)));
1140 return;
1141 }
1142
1143 SVDEBUG << "Document::alignModel: aligning..." << endl;
1144 if (!rm->getAlignmentReference().isNone()) {
1145 SVDEBUG << "(Note: model " << rm << " is currently aligned to model "
1146 << rm->getAlignmentReference() << "; this will replace that)"
1147 << endl;
1148 }
1149
1150 QString err;
1151 if (!m_align->alignModel(this, m_mainModel, modelId, err)) {
1152 SVCERR << "Alignment failed: " << err << endl;
1153 emit alignmentFailed(err);
1154 }
1155 }
1156
1157 void
performDeferredAlignment(ModelId modelId)1158 Document::performDeferredAlignment(ModelId modelId)
1159 {
1160 SVDEBUG << "Document::performDeferredAlignment: aligning..." << endl;
1161 alignModel(modelId);
1162 }
1163
1164 void
alignModels()1165 Document::alignModels()
1166 {
1167 for (auto rec: m_models) {
1168 alignModel(rec.first);
1169 }
1170 alignModel(m_mainModel);
1171 }
1172
1173 void
realignModels()1174 Document::realignModels()
1175 {
1176 for (auto rec: m_models) {
1177 alignModel(rec.first, true);
1178 }
1179 alignModel(m_mainModel);
1180 }
1181
AddLayerCommand(Document * d,View * view,Layer * layer)1182 Document::AddLayerCommand::AddLayerCommand(Document *d,
1183 View *view,
1184 Layer *layer) :
1185 m_d(d),
1186 m_view(view),
1187 m_layer(layer),
1188 m_name(qApp->translate("AddLayerCommand", "Add %1 Layer").arg(layer->objectName())),
1189 m_added(false)
1190 {
1191 }
1192
~AddLayerCommand()1193 Document::AddLayerCommand::~AddLayerCommand()
1194 {
1195 #ifdef DEBUG_DOCUMENT
1196 SVDEBUG << "Document::AddLayerCommand::~AddLayerCommand" << endl;
1197 #endif
1198 if (!m_added) {
1199 m_d->deleteLayer(m_layer);
1200 }
1201 }
1202
1203 QString
getName() const1204 Document::AddLayerCommand::getName() const
1205 {
1206 #ifdef DEBUG_DOCUMENT
1207 SVDEBUG << "Document::AddLayerCommand::getName(): Name is "
1208 << m_name << endl;
1209 #endif
1210 return m_name;
1211 }
1212
1213 void
execute()1214 Document::AddLayerCommand::execute()
1215 {
1216 for (int i = 0; i < m_view->getLayerCount(); ++i) {
1217 if (m_view->getLayer(i) == m_layer) {
1218 // already there
1219 m_layer->setLayerDormant(m_view, false);
1220 m_added = true;
1221 return;
1222 }
1223 }
1224
1225 m_view->addLayer(m_layer);
1226 m_layer->setLayerDormant(m_view, false);
1227
1228 m_d->addToLayerViewMap(m_layer, m_view);
1229 m_added = true;
1230 }
1231
1232 void
unexecute()1233 Document::AddLayerCommand::unexecute()
1234 {
1235 m_view->removeLayer(m_layer);
1236 m_layer->setLayerDormant(m_view, true);
1237
1238 m_d->removeFromLayerViewMap(m_layer, m_view);
1239 m_added = false;
1240 }
1241
RemoveLayerCommand(Document * d,View * view,Layer * layer)1242 Document::RemoveLayerCommand::RemoveLayerCommand(Document *d,
1243 View *view,
1244 Layer *layer) :
1245 m_d(d),
1246 m_view(view),
1247 m_layer(layer),
1248 m_wasDormant(layer->isLayerDormant(view)),
1249 m_name(qApp->translate("RemoveLayerCommand", "Delete %1 Layer").arg(layer->objectName())),
1250 m_added(true)
1251 {
1252 }
1253
~RemoveLayerCommand()1254 Document::RemoveLayerCommand::~RemoveLayerCommand()
1255 {
1256 #ifdef DEBUG_DOCUMENT
1257 SVDEBUG << "Document::RemoveLayerCommand::~RemoveLayerCommand" << endl;
1258 #endif
1259 if (!m_added) {
1260 m_d->deleteLayer(m_layer);
1261 }
1262 }
1263
1264 QString
getName() const1265 Document::RemoveLayerCommand::getName() const
1266 {
1267 #ifdef DEBUG_DOCUMENT
1268 SVDEBUG << "Document::RemoveLayerCommand::getName(): Name is "
1269 << m_name << endl;
1270 #endif
1271 return m_name;
1272 }
1273
1274 void
execute()1275 Document::RemoveLayerCommand::execute()
1276 {
1277 bool have = false;
1278 for (int i = 0; i < m_view->getLayerCount(); ++i) {
1279 if (m_view->getLayer(i) == m_layer) {
1280 have = true;
1281 break;
1282 }
1283 }
1284
1285 if (!have) { // not there!
1286 m_layer->setLayerDormant(m_view, true);
1287 m_added = false;
1288 return;
1289 }
1290
1291 m_view->removeLayer(m_layer);
1292 m_layer->setLayerDormant(m_view, true);
1293
1294 m_d->removeFromLayerViewMap(m_layer, m_view);
1295 m_added = false;
1296 }
1297
1298 void
unexecute()1299 Document::RemoveLayerCommand::unexecute()
1300 {
1301 m_view->addLayer(m_layer);
1302 m_layer->setLayerDormant(m_view, m_wasDormant);
1303
1304 m_d->addToLayerViewMap(m_layer, m_view);
1305 m_added = true;
1306 }
1307
1308 void
toXml(QTextStream & out,QString indent,QString extraAttributes) const1309 Document::toXml(QTextStream &out, QString indent, QString extraAttributes) const
1310 {
1311 toXml(out, indent, extraAttributes, false);
1312 }
1313
1314 void
toXmlAsTemplate(QTextStream & out,QString indent,QString extraAttributes) const1315 Document::toXmlAsTemplate(QTextStream &out, QString indent, QString extraAttributes) const
1316 {
1317 toXml(out, indent, extraAttributes, true);
1318 }
1319
1320 void
toXml(QTextStream & out,QString indent,QString extraAttributes,bool asTemplate) const1321 Document::toXml(QTextStream &out, QString indent, QString extraAttributes,
1322 bool asTemplate) const
1323 {
1324 out << indent + QString("<data%1%2>\n")
1325 .arg(extraAttributes == "" ? "" : " ").arg(extraAttributes);
1326
1327 auto mainModel = ModelById::getAs<WaveFileModel>(m_mainModel);
1328 if (mainModel) {
1329
1330 #ifdef DEBUG_DOCUMENT
1331 SVDEBUG << "Document::toXml: writing main model" << endl;
1332 #endif
1333
1334 if (asTemplate) {
1335 writePlaceholderMainModel(out, indent + " ");
1336 } else {
1337 mainModel->toXml(out, indent + " ", "mainModel=\"true\"");
1338 }
1339
1340 auto playParameters =
1341 PlayParameterRepository::getInstance()->getPlayParameters
1342 (m_mainModel.untyped);
1343 if (playParameters) {
1344 playParameters->toXml
1345 (out, indent + " ",
1346 QString("model=\"%1\"")
1347 .arg(mainModel->getExportId()));
1348 }
1349 } else {
1350 #ifdef DEBUG_DOCUMENT
1351 SVDEBUG << "Document::toXml: have no main model to write" << endl;
1352 #endif
1353 }
1354
1355 // Models that are not used in a layer that is in a view should
1356 // not be written. Get our list of required models first.
1357
1358 std::set<ModelId> used;
1359
1360 for (LayerViewMap::const_iterator i = m_layerViewMap.begin();
1361 i != m_layerViewMap.end(); ++i) {
1362
1363 if (i->first && !i->second.empty()) { // Layer exists, is in views
1364 ModelId modelId = i->first->getModel();
1365 ModelId sourceId = i->first->getSourceModel();
1366 if (!modelId.isNone()) used.insert(modelId);
1367 if (!sourceId.isNone()) used.insert(sourceId);
1368 }
1369 }
1370
1371 // Write aggregate models first, so that when re-reading
1372 // derivations we already know about their existence. But only
1373 // those that are actually used
1374 //
1375 // Later note: This turns out not to be a great idea - we can't
1376 // use an aggregate model to drive a derivation unless its
1377 // component models have all also already been loaded. So we
1378 // really should have written non-aggregate read-only
1379 // (i.e. non-derived) wave-type models first, then aggregate
1380 // models, then models that have derivations. But we didn't do
1381 // that, so existing sessions will always have the aggregate
1382 // models first and we might as well stick with that.
1383
1384 for (auto modelId: m_aggregateModels) {
1385
1386 #ifdef DEBUG_DOCUMENT
1387 SVDEBUG << "Document::toXml: checking aggregate model "
1388 << modelId << endl;
1389 #endif
1390
1391 auto aggregate = ModelById::getAs<AggregateWaveModel>(modelId);
1392 if (!aggregate) continue;
1393 if (used.find(modelId) == used.end()) {
1394 #ifdef DEBUG_DOCUMENT
1395 SVDEBUG << "(unused, skipping)" << endl;
1396 #endif
1397 continue;
1398 }
1399
1400 #ifdef DEBUG_DOCUMENT
1401 SVDEBUG << "(used, writing)" << endl;
1402 #endif
1403
1404 aggregate->toXml(out, indent + " ");
1405 }
1406
1407 std::set<ModelId> written;
1408
1409 // Now write the other models in two passes: first the models that
1410 // aren't derived from anything (in case they are source
1411 // components for an aggregate model, in which case we need to
1412 // have seen them before we see any models derived from aggregates
1413 // that use them - see the lament above) and then the models that
1414 // have derivations.
1415
1416 const int nonDerivedPass = 0, derivedPass = 1;
1417 for (int pass = nonDerivedPass; pass <= derivedPass; ++pass) {
1418
1419 for (auto rec: m_models) {
1420
1421 ModelId modelId = rec.first;
1422
1423 if (used.find(modelId) == used.end()) continue;
1424
1425 auto model = ModelById::get(modelId);
1426 if (!model) continue;
1427
1428 #ifdef DEBUG_DOCUMENT
1429 SVDEBUG << "Document::toXml: looking at model " << modelId
1430 << " [pass = " << pass << "]" << endl;
1431 #endif
1432
1433 // We need an intelligent way to determine which models
1434 // need to be streamed (i.e. have been edited, or are
1435 // small) and which should not be (i.e. remain as
1436 // generated by a transform, and are large).
1437 //
1438 // At the moment we can get away with deciding not to
1439 // stream dense 3d models or writable wave file models,
1440 // provided they were generated from a transform, because
1441 // at the moment there is no way to edit those model types
1442 // so it should be safe to regenerate them. That won't
1443 // always work in future though. It would be particularly
1444 // nice to be able to ask the user, as well as making an
1445 // intelligent guess.
1446
1447 bool writeModel = true;
1448 bool haveDerivation = false;
1449
1450 if (!rec.second.source.isNone() &&
1451 rec.second.transform.getIdentifier() != "") {
1452 haveDerivation = true;
1453 }
1454
1455 if (pass == nonDerivedPass) {
1456 if (haveDerivation) {
1457 SVDEBUG << "skipping derived model " << model->objectName() << " during nonDerivedPass" << endl;
1458 continue;
1459 }
1460 } else {
1461 if (!haveDerivation) {
1462 SVDEBUG << "skipping non-derived model " << model->objectName() << " during derivedPass" << endl;
1463 continue;
1464 }
1465 }
1466
1467 if (haveDerivation) {
1468 if (ModelById::isa<WritableWaveFileModel>(modelId) ||
1469 ModelById::isa<DenseThreeDimensionalModel>(modelId)) {
1470 writeModel = false;
1471 }
1472 }
1473
1474 if (writeModel) {
1475 model->toXml(out, indent + " ");
1476 written.insert(modelId);
1477 }
1478
1479 if (haveDerivation) {
1480 writeBackwardCompatibleDerivation(out, indent + " ",
1481 modelId, rec.second);
1482 }
1483
1484 auto playParameters =
1485 PlayParameterRepository::getInstance()->getPlayParameters
1486 (modelId.untyped);
1487 if (playParameters) {
1488 playParameters->toXml
1489 (out, indent + " ",
1490 QString("model=\"%1\"")
1491 .arg(model->getExportId()));
1492 }
1493 }
1494 }
1495
1496 // We should write out the alignment models here. AlignmentModel
1497 // needs a toXml that writes out the export IDs of its reference
1498 // and aligned models, and then streams its path model. Note that
1499 // this will only work when the alignment is complete, so we
1500 // should probably wait for it if it isn't already by this point.
1501
1502 for (auto modelId: written) {
1503
1504 auto model = ModelById::get(modelId);
1505 if (!model) continue;
1506
1507 auto alignment = ModelById::get(model->getAlignment());
1508 if (!alignment) continue;
1509
1510 alignment->toXml(out, indent + " ");
1511 }
1512
1513 for (auto i = m_layers.begin(); i != m_layers.end(); ++i) {
1514 (*i)->toXml(out, indent + " ");
1515 }
1516
1517 out << indent + "</data>\n";
1518 }
1519
1520 void
writePlaceholderMainModel(QTextStream & out,QString indent) const1521 Document::writePlaceholderMainModel(QTextStream &out, QString indent) const
1522 {
1523 auto mainModel = ModelById::get(m_mainModel);
1524 if (!mainModel) return;
1525 out << indent;
1526 out << QString("<model id=\"%1\" name=\"placeholder\" sampleRate=\"%2\" type=\"wavefile\" file=\":samples/silent.wav\" mainModel=\"true\"/>\n")
1527 .arg(mainModel->getExportId())
1528 .arg(mainModel->getSampleRate());
1529 }
1530
1531 void
writeBackwardCompatibleDerivation(QTextStream & out,QString indent,ModelId targetModelId,const ModelRecord & rec) const1532 Document::writeBackwardCompatibleDerivation(QTextStream &out, QString indent,
1533 ModelId targetModelId,
1534 const ModelRecord &rec) const
1535 {
1536 // There is a lot of redundancy in the XML we output here, because
1537 // we want it to work with older SV session file reading code as
1538 // well.
1539 //
1540 // Formerly, a transform was described using a derivation element
1541 // which set out the source and target models, execution context
1542 // (step size, input channel etc) and transform id, containing a
1543 // plugin element which set out the transform parameters and so
1544 // on. (The plugin element came from a "configurationXml" string
1545 // obtained from PluginXml.)
1546 //
1547 // This has been replaced by a derivation element setting out the
1548 // source and target models and input channel, containing a
1549 // transform element which sets out everything in the Transform.
1550 //
1551 // In order to retain compatibility with older SV code, however,
1552 // we have to write out the same stuff into the derivation as
1553 // before, and manufacture an appropriate plugin element as well
1554 // as the transform element. In order that newer code knows it's
1555 // dealing with a newer format, we will also write an attribute
1556 // 'type="transform"' in the derivation element.
1557
1558 const Transform &transform = rec.transform;
1559
1560 auto targetModel = ModelById::get(targetModelId);
1561 if (!targetModel) return;
1562
1563 // Just for reference, this is what we would write if we didn't
1564 // have to be backward compatible:
1565 //
1566 // out << indent
1567 // << QString("<derivation type=\"transform\" source=\"%1\" "
1568 // "model=\"%2\" channel=\"%3\">\n")
1569 // .arg(rec.source->getExportId())
1570 // .arg(targetModel->getExportId())
1571 // .arg(rec.channel);
1572 //
1573 // transform.toXml(out, indent + " ");
1574 //
1575 // out << indent << "</derivation>\n";
1576 //
1577 // Unfortunately, we can't just do that. So we do this...
1578
1579 QString extentsAttributes;
1580 if (transform.getStartTime() != RealTime::zeroTime ||
1581 transform.getDuration() != RealTime::zeroTime) {
1582 extentsAttributes = QString("startFrame=\"%1\" duration=\"%2\" ")
1583 .arg(RealTime::realTime2Frame(transform.getStartTime(),
1584 targetModel->getSampleRate()))
1585 .arg(RealTime::realTime2Frame(transform.getDuration(),
1586 targetModel->getSampleRate()));
1587 }
1588
1589 out << indent;
1590 out << QString("<derivation type=\"transform\" source=\"%1\" "
1591 "model=\"%2\" channel=\"%3\" domain=\"%4\" "
1592 "stepSize=\"%5\" blockSize=\"%6\" %7windowType=\"%8\" "
1593 "transform=\"%9\">\n")
1594 .arg(ModelById::getExportId(rec.source))
1595 .arg(targetModel->getExportId())
1596 .arg(rec.channel)
1597 .arg(TransformFactory::getInstance()->getTransformInputDomain
1598 (transform.getIdentifier()))
1599 .arg(transform.getStepSize())
1600 .arg(transform.getBlockSize())
1601 .arg(extentsAttributes)
1602 .arg(int(transform.getWindowType()))
1603 .arg(XmlExportable::encodeEntities(transform.getIdentifier()));
1604
1605 transform.toXml(out, indent + " ");
1606
1607 out << indent << " "
1608 << TransformFactory::getInstance()->getPluginConfigurationXml(transform);
1609
1610 out << indent << "</derivation>\n";
1611 }
1612
1613