comparison document/Document.cpp @ 0:cd5d7ff8ef38

* Reorganising code base. This revision will not compile.
author Chris Cannam
date Mon, 31 Jul 2006 12:03:45 +0000
parents
children 40116f709d3b
comparison
equal deleted inserted replaced
-1:000000000000 0:cd5d7ff8ef38
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.
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 "model/WaveFileModel.h"
19 #include "base/Layer.h"
20 #include "base/CommandHistory.h"
21 #include "base/Command.h"
22 #include "base/View.h"
23 #include "base/PlayParameterRepository.h"
24 #include "base/PlayParameters.h"
25 #include "transform/TransformFactory.h"
26 #include <iostream>
27
28 //!!! still need to handle command history, documentRestored/documentModified
29
30 Document::Document() :
31 m_mainModel(0)
32 {
33 }
34
35 Document::~Document()
36 {
37 //!!! Document should really own the command history. atm we
38 //still refer to it in various places that don't have access to
39 //the document, be nice to fix that
40
41 // std::cerr << "\n\nDocument::~Document: about to clear command history" << std::endl;
42 CommandHistory::getInstance()->clear();
43
44 // std::cerr << "Document::~Document: about to delete layers" << std::endl;
45 while (!m_layers.empty()) {
46 deleteLayer(*m_layers.begin(), true);
47 }
48
49 if (!m_models.empty()) {
50 std::cerr << "Document::~Document: WARNING: "
51 << m_models.size() << " model(s) still remain -- "
52 << "should have been garbage collected when deleting layers"
53 << std::endl;
54 while (!m_models.empty()) {
55 if (m_models.begin()->first == m_mainModel) {
56 // just in case!
57 std::cerr << "Document::~Document: WARNING: Main model is also"
58 << " in models list!" << std::endl;
59 } else {
60 emit modelAboutToBeDeleted(m_models.begin()->first);
61 delete m_models.begin()->first;
62 }
63 m_models.erase(m_models.begin());
64 }
65 }
66
67 // std::cerr << "Document::~Document: About to get rid of main model"
68 // << std::endl;
69 emit modelAboutToBeDeleted(m_mainModel);
70 emit mainModelChanged(0);
71 delete m_mainModel;
72
73 }
74
75 Layer *
76 Document::createLayer(LayerFactory::LayerType type)
77 {
78 Layer *newLayer = LayerFactory::getInstance()->createLayer(type);
79 if (!newLayer) return 0;
80
81 newLayer->setObjectName(getUniqueLayerName(newLayer->objectName()));
82
83 m_layers.insert(newLayer);
84 emit layerAdded(newLayer);
85
86 return newLayer;
87 }
88
89 Layer *
90 Document::createMainModelLayer(LayerFactory::LayerType type)
91 {
92 Layer *newLayer = createLayer(type);
93 if (!newLayer) return 0;
94 setModel(newLayer, m_mainModel);
95 return newLayer;
96 }
97
98 Layer *
99 Document::createImportedLayer(Model *model)
100 {
101 LayerFactory::LayerTypeSet types =
102 LayerFactory::getInstance()->getValidLayerTypes(model);
103
104 if (types.empty()) {
105 std::cerr << "WARNING: Document::importLayer: no valid display layer for model" << std::endl;
106 return 0;
107 }
108
109 //!!! for now, just use the first suitable layer type
110 LayerFactory::LayerType type = *types.begin();
111
112 Layer *newLayer = LayerFactory::getInstance()->createLayer(type);
113 if (!newLayer) return 0;
114
115 newLayer->setObjectName(getUniqueLayerName(newLayer->objectName()));
116
117 addImportedModel(model);
118 setModel(newLayer, model);
119
120 //!!! and all channels
121 setChannel(newLayer, -1);
122
123 m_layers.insert(newLayer);
124 emit layerAdded(newLayer);
125 return newLayer;
126 }
127
128 Layer *
129 Document::createEmptyLayer(LayerFactory::LayerType type)
130 {
131 Model *newModel =
132 LayerFactory::getInstance()->createEmptyModel(type, m_mainModel);
133 if (!newModel) return 0;
134
135 Layer *newLayer = createLayer(type);
136 if (!newLayer) {
137 delete newModel;
138 return 0;
139 }
140
141 addImportedModel(newModel);
142 setModel(newLayer, newModel);
143
144 return newLayer;
145 }
146
147 Layer *
148 Document::createDerivedLayer(LayerFactory::LayerType type,
149 TransformName transform)
150 {
151 Layer *newLayer = createLayer(type);
152 if (!newLayer) return 0;
153
154 newLayer->setObjectName(getUniqueLayerName
155 (TransformFactory::getInstance()->
156 getTransformFriendlyName(transform)));
157
158 return newLayer;
159 }
160
161 Layer *
162 Document::createDerivedLayer(TransformName transform,
163 Model *inputModel,
164 int channel,
165 QString configurationXml)
166 {
167 Model *newModel = createModelForTransform(transform, inputModel,
168 channel, configurationXml);
169 if (!newModel) {
170 // error already printed to stderr by createModelForTransform
171 emit modelGenerationFailed(transform);
172 return 0;
173 }
174
175 LayerFactory::LayerTypeSet types =
176 LayerFactory::getInstance()->getValidLayerTypes(newModel);
177
178 if (types.empty()) {
179 std::cerr << "WARNING: Document::createLayerForTransform: no valid display layer for output of transform " << transform.toStdString() << std::endl;
180 delete newModel;
181 return 0;
182 }
183
184 //!!! for now, just use the first suitable layer type
185
186 Layer *newLayer = createLayer(*types.begin());
187 setModel(newLayer, newModel);
188
189 //!!! We need to clone the model when adding the layer, so that it
190 //can be edited without affecting other layers that are based on
191 //the same model. Unfortunately we can't just clone it now,
192 //because it probably hasn't been completed yet -- the transform
193 //runs in the background. Maybe the transform has to handle
194 //cloning and cacheing models itself.
195 //
196 // Once we do clone models here, of course, we'll have to avoid
197 // leaking them too.
198 //
199 // We want the user to be able to add a model to a second layer
200 // _while it's still being calculated in the first_ and have it
201 // work quickly. That means we need to put the same physical
202 // model pointer in both layers, so they can't actually be cloned.
203
204 if (newLayer) {
205 newLayer->setObjectName(getUniqueLayerName
206 (TransformFactory::getInstance()->
207 getTransformFriendlyName(transform)));
208 }
209
210 emit layerAdded(newLayer);
211 return newLayer;
212 }
213
214 void
215 Document::setMainModel(WaveFileModel *model)
216 {
217 Model *oldMainModel = m_mainModel;
218 m_mainModel = model;
219
220 emit modelAdded(m_mainModel);
221
222 std::vector<Layer *> obsoleteLayers;
223 std::set<QString> failedTransforms;
224
225 // We need to ensure that no layer is left using oldMainModel or
226 // any of the old derived models as its model. Either replace the
227 // model, or delete the layer for each layer that is currently
228 // using one of these. Carry out this replacement before we
229 // delete any of the models.
230
231 for (LayerSet::iterator i = m_layers.begin(); i != m_layers.end(); ++i) {
232
233 Layer *layer = *i;
234 Model *model = layer->getModel();
235
236 if (model == oldMainModel) {
237 LayerFactory::getInstance()->setModel(layer, m_mainModel);
238 continue;
239 }
240
241 if (m_models.find(model) == m_models.end()) {
242 std::cerr << "WARNING: Document::setMainModel: Unknown model "
243 << model << " in layer " << layer << std::endl;
244 // get rid of this hideous degenerate
245 obsoleteLayers.push_back(layer);
246 continue;
247 }
248
249 if (m_models[model].source == oldMainModel) {
250
251 // This model was derived from the previous main
252 // model: regenerate it.
253
254 TransformName transform = m_models[model].transform;
255 int channel = m_models[model].channel;
256
257 Model *replacementModel =
258 createModelForTransform(transform,
259 m_mainModel,
260 channel,
261 m_models[model].configurationXml);
262
263 if (!replacementModel) {
264 std::cerr << "WARNING: Document::setMainModel: Failed to regenerate model for transform \""
265 << transform.toStdString() << "\"" << " in layer " << layer << std::endl;
266 if (failedTransforms.find(transform) == failedTransforms.end()) {
267 emit modelRegenerationFailed(layer->objectName(),
268 transform);
269 failedTransforms.insert(transform);
270 }
271 obsoleteLayers.push_back(layer);
272 } else {
273 setModel(layer, replacementModel);
274 }
275 }
276 }
277
278 for (size_t k = 0; k < obsoleteLayers.size(); ++k) {
279 deleteLayer(obsoleteLayers[k], true);
280 }
281
282 emit mainModelChanged(m_mainModel);
283
284 // we already emitted modelAboutToBeDeleted for this
285 delete oldMainModel;
286 }
287
288 void
289 Document::addDerivedModel(TransformName transform,
290 Model *inputModel,
291 int channel,
292 Model *outputModelToAdd,
293 QString configurationXml)
294 {
295 if (m_models.find(outputModelToAdd) != m_models.end()) {
296 std::cerr << "WARNING: Document::addDerivedModel: Model already added"
297 << std::endl;
298 return;
299 }
300
301 ModelRecord rec;
302 rec.source = inputModel;
303 rec.transform = transform;
304 rec.channel = channel;
305 rec.configurationXml = configurationXml;
306 rec.refcount = 0;
307
308 m_models[outputModelToAdd] = rec;
309
310 emit modelAdded(outputModelToAdd);
311 }
312
313
314 void
315 Document::addImportedModel(Model *model)
316 {
317 if (m_models.find(model) != m_models.end()) {
318 std::cerr << "WARNING: Document::addImportedModel: Model already added"
319 << std::endl;
320 return;
321 }
322
323 ModelRecord rec;
324 rec.source = 0;
325 rec.transform = "";
326 rec.channel = -1;
327 rec.refcount = 0;
328
329 m_models[model] = rec;
330
331 emit modelAdded(model);
332 }
333
334 Model *
335 Document::createModelForTransform(TransformName transform,
336 Model *inputModel,
337 int channel,
338 QString configurationXml)
339 {
340 Model *model = 0;
341
342 for (ModelMap::iterator i = m_models.begin(); i != m_models.end(); ++i) {
343 if (i->second.transform == transform &&
344 i->second.source == inputModel &&
345 i->second.channel == channel &&
346 i->second.configurationXml == configurationXml) {
347 return i->first;
348 }
349 }
350
351 model = TransformFactory::getInstance()->transform
352 (transform, inputModel, channel, configurationXml);
353
354 if (!model) {
355 std::cerr << "WARNING: Document::createModelForTransform: no output model for transform " << transform.toStdString() << std::endl;
356 } else {
357 addDerivedModel(transform, inputModel, channel, model, configurationXml);
358 }
359
360 return model;
361 }
362
363 void
364 Document::releaseModel(Model *model) // Will _not_ release main model!
365 {
366 if (model == 0) {
367 return;
368 }
369
370 if (model == m_mainModel) {
371 return;
372 }
373
374 bool toDelete = false;
375
376 if (m_models.find(model) != m_models.end()) {
377
378 if (m_models[model].refcount == 0) {
379 std::cerr << "WARNING: Document::releaseModel: model " << model
380 << " reference count is zero already!" << std::endl;
381 } else {
382 if (--m_models[model].refcount == 0) {
383 toDelete = true;
384 }
385 }
386 } else {
387 std::cerr << "WARNING: Document::releaseModel: Unfound model "
388 << model << std::endl;
389 toDelete = true;
390 }
391
392 if (toDelete) {
393
394 int sourceCount = 0;
395
396 for (ModelMap::iterator i = m_models.begin(); i != m_models.end(); ++i) {
397 if (i->second.source == model) {
398 ++sourceCount;
399 i->second.source = 0;
400 }
401 }
402
403 if (sourceCount > 0) {
404 std::cerr << "Document::releaseModel: Deleting model "
405 << model << " even though it is source for "
406 << sourceCount << " other derived model(s) -- resetting "
407 << "their source fields appropriately" << std::endl;
408 }
409
410 emit modelAboutToBeDeleted(model);
411 m_models.erase(model);
412 delete model;
413 }
414 }
415
416 void
417 Document::deleteLayer(Layer *layer, bool force)
418 {
419 if (m_layerViewMap.find(layer) != m_layerViewMap.end() &&
420 m_layerViewMap[layer].size() > 0) {
421
422 std::cerr << "WARNING: Document::deleteLayer: Layer "
423 << layer << " [" << layer->objectName().toStdString() << "]"
424 << " is still used in " << m_layerViewMap[layer].size()
425 << " views!" << std::endl;
426
427 if (force) {
428
429 std::cerr << "(force flag set -- deleting from all views)" << std::endl;
430
431 for (std::set<View *>::iterator j = m_layerViewMap[layer].begin();
432 j != m_layerViewMap[layer].end(); ++j) {
433 // don't use removeLayerFromView, as it issues a command
434 layer->setLayerDormant(*j, true);
435 (*j)->removeLayer(layer);
436 }
437
438 m_layerViewMap.erase(layer);
439
440 } else {
441 return;
442 }
443 }
444
445 if (m_layers.find(layer) == m_layers.end()) {
446 std::cerr << "Document::deleteLayer: Layer "
447 << layer << " does not exist, or has already been deleted "
448 << "(this may not be as serious as it sounds)" << std::endl;
449 return;
450 }
451
452 m_layers.erase(layer);
453
454 releaseModel(layer->getModel());
455 emit layerRemoved(layer);
456 emit layerAboutToBeDeleted(layer);
457 delete layer;
458 }
459
460 void
461 Document::setModel(Layer *layer, Model *model)
462 {
463 if (model &&
464 model != m_mainModel &&
465 m_models.find(model) == m_models.end()) {
466 std::cerr << "ERROR: Document::setModel: Layer " << layer
467 << " is using unregistered model " << model
468 << ": register the layer's model before setting it!"
469 << std::endl;
470 return;
471 }
472
473 if (layer->getModel()) {
474 if (layer->getModel() == model) {
475 std::cerr << "WARNING: Document::setModel: Layer is already set to this model" << std::endl;
476 return;
477 }
478 releaseModel(layer->getModel());
479 }
480
481 if (model && model != m_mainModel) {
482 m_models[model].refcount ++;
483 }
484
485 LayerFactory::getInstance()->setModel(layer, model);
486 }
487
488 void
489 Document::setChannel(Layer *layer, int channel)
490 {
491 LayerFactory::getInstance()->setChannel(layer, channel);
492 }
493
494 void
495 Document::addLayerToView(View *view, Layer *layer)
496 {
497 Model *model = layer->getModel();
498 if (!model) {
499 std::cerr << "Document::addLayerToView: Layer with no model being added to view: normally you want to set the model first" << std::endl;
500 } else {
501 if (model != m_mainModel &&
502 m_models.find(model) == m_models.end()) {
503 std::cerr << "ERROR: Document::addLayerToView: Layer " << layer
504 << " has unregistered model " << model
505 << " -- register the layer's model before adding the layer!" << std::endl;
506 return;
507 }
508 }
509
510 CommandHistory::getInstance()->addCommand
511 (new Document::AddLayerCommand(this, view, layer));
512 }
513
514 void
515 Document::removeLayerFromView(View *view, Layer *layer)
516 {
517 CommandHistory::getInstance()->addCommand
518 (new Document::RemoveLayerCommand(this, view, layer));
519 }
520
521 void
522 Document::addToLayerViewMap(Layer *layer, View *view)
523 {
524 bool firstView = (m_layerViewMap.find(layer) == m_layerViewMap.end() ||
525 m_layerViewMap[layer].empty());
526
527 if (m_layerViewMap[layer].find(view) !=
528 m_layerViewMap[layer].end()) {
529 std::cerr << "WARNING: Document::addToLayerViewMap:"
530 << " Layer " << layer << " -> view " << view << " already in"
531 << " layer view map -- internal inconsistency" << std::endl;
532 }
533
534 m_layerViewMap[layer].insert(view);
535
536 if (firstView) emit layerInAView(layer, true);
537 }
538
539 void
540 Document::removeFromLayerViewMap(Layer *layer, View *view)
541 {
542 if (m_layerViewMap[layer].find(view) ==
543 m_layerViewMap[layer].end()) {
544 std::cerr << "WARNING: Document::removeFromLayerViewMap:"
545 << " Layer " << layer << " -> view " << view << " not in"
546 << " layer view map -- internal inconsistency" << std::endl;
547 }
548
549 m_layerViewMap[layer].erase(view);
550
551 if (m_layerViewMap[layer].empty()) {
552 m_layerViewMap.erase(layer);
553 emit layerInAView(layer, false);
554 }
555 }
556
557 QString
558 Document::getUniqueLayerName(QString candidate)
559 {
560 for (int count = 1; ; ++count) {
561
562 QString adjusted =
563 (count > 1 ? QString("%1 <%2>").arg(candidate).arg(count) :
564 candidate);
565
566 bool duplicate = false;
567
568 for (LayerSet::iterator i = m_layers.begin(); i != m_layers.end(); ++i) {
569 if ((*i)->objectName() == adjusted) {
570 duplicate = true;
571 break;
572 }
573 }
574
575 if (!duplicate) return adjusted;
576 }
577 }
578
579 Document::AddLayerCommand::AddLayerCommand(Document *d,
580 View *view,
581 Layer *layer) :
582 m_d(d),
583 m_view(view),
584 m_layer(layer),
585 m_name(d->tr("Add %1 Layer").arg(layer->objectName())),
586 m_added(false)
587 {
588 }
589
590 Document::AddLayerCommand::~AddLayerCommand()
591 {
592 // std::cerr << "Document::AddLayerCommand::~AddLayerCommand" << std::endl;
593 if (!m_added) {
594 m_d->deleteLayer(m_layer);
595 }
596 }
597
598 void
599 Document::AddLayerCommand::execute()
600 {
601 for (int i = 0; i < m_view->getLayerCount(); ++i) {
602 if (m_view->getLayer(i) == m_layer) {
603 // already there
604 m_layer->setLayerDormant(m_view, false);
605 m_added = true;
606 return;
607 }
608 }
609
610 m_view->addLayer(m_layer);
611 m_layer->setLayerDormant(m_view, false);
612
613 m_d->addToLayerViewMap(m_layer, m_view);
614 m_added = true;
615 }
616
617 void
618 Document::AddLayerCommand::unexecute()
619 {
620 m_view->removeLayer(m_layer);
621 m_layer->setLayerDormant(m_view, true);
622
623 m_d->removeFromLayerViewMap(m_layer, m_view);
624 m_added = false;
625 }
626
627 Document::RemoveLayerCommand::RemoveLayerCommand(Document *d,
628 View *view,
629 Layer *layer) :
630 m_d(d),
631 m_view(view),
632 m_layer(layer),
633 m_name(d->tr("Delete %1 Layer").arg(layer->objectName())),
634 m_added(true)
635 {
636 }
637
638 Document::RemoveLayerCommand::~RemoveLayerCommand()
639 {
640 // std::cerr << "Document::RemoveLayerCommand::~RemoveLayerCommand" << std::endl;
641 if (!m_added) {
642 m_d->deleteLayer(m_layer);
643 }
644 }
645
646 void
647 Document::RemoveLayerCommand::execute()
648 {
649 bool have = false;
650 for (int i = 0; i < m_view->getLayerCount(); ++i) {
651 if (m_view->getLayer(i) == m_layer) {
652 have = true;
653 break;
654 }
655 }
656
657 if (!have) { // not there!
658 m_layer->setLayerDormant(m_view, true);
659 m_added = false;
660 return;
661 }
662
663 m_view->removeLayer(m_layer);
664 m_layer->setLayerDormant(m_view, true);
665
666 m_d->removeFromLayerViewMap(m_layer, m_view);
667 m_added = false;
668 }
669
670 void
671 Document::RemoveLayerCommand::unexecute()
672 {
673 m_view->addLayer(m_layer);
674 m_layer->setLayerDormant(m_view, false);
675
676 m_d->addToLayerViewMap(m_layer, m_view);
677 m_added = true;
678 }
679
680 void
681 Document::toXml(QTextStream &out, QString indent, QString extraAttributes) const
682 {
683 out << indent + QString("<data%1%2>\n")
684 .arg(extraAttributes == "" ? "" : " ").arg(extraAttributes);
685
686 if (m_mainModel) {
687 m_mainModel->toXml(out, indent + " ", "mainModel=\"true\"");
688 }
689
690 for (ModelMap::const_iterator i = m_models.begin();
691 i != m_models.end(); ++i) {
692
693 i->first->toXml(out, indent + " ");
694
695 const ModelRecord &rec = i->second;
696
697 if (rec.source && rec.transform != "") {
698
699 out << indent;
700 out << QString(" <derivation source=\"%1\" model=\"%2\" channel=\"%3\" transform=\"%4\"")
701 .arg(XmlExportable::getObjectExportId(rec.source))
702 .arg(XmlExportable::getObjectExportId(i->first))
703 .arg(rec.channel)
704 .arg(XmlExportable::encodeEntities(rec.transform));
705
706 if (rec.configurationXml != "") {
707 out << ">\n " + indent + rec.configurationXml
708 + "\n" + indent + " </derivation>\n";
709 } else {
710 out << "/>\n";
711 }
712 }
713
714 //!!! We should probably own the PlayParameterRepository
715 PlayParameters *playParameters =
716 PlayParameterRepository::getInstance()->getPlayParameters(i->first);
717 if (playParameters) {
718 playParameters->toXml
719 (out, indent + " ",
720 QString("model=\"%1\"")
721 .arg(XmlExportable::getObjectExportId(i->first)));
722 }
723 }
724
725 for (LayerSet::const_iterator i = m_layers.begin();
726 i != m_layers.end(); ++i) {
727
728 (*i)->toXml(out, indent + " ");
729 }
730
731 out << indent + "</data>\n";
732 }
733
734 QString
735 Document::toXmlString(QString indent, QString extraAttributes) const
736 {
737 QString s;
738
739 {
740 QTextStream out(&s);
741 toXml(out, indent, extraAttributes);
742 }
743
744 return s;
745 }
746