annotate framework/Document.cpp @ 562:3c846b06c518 3.0-integration

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