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