annotate framework/Document.cpp @ 451:dc1a360f2b69

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