annotate framework/Document.cpp @ 588:d122d3595a32

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