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