annotate framework/Document.cpp @ 403:eb84b06301da

Restore the old prev/next layer commands (that were never enabled because they didn't work) using the new fixed order layer list (so they now do work)
author Chris Cannam
date Tue, 02 Sep 2014 16:06:41 +0100
parents a4c2a4685cf1
children edfdb1d5db3c
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@45 631 rec.refcount = 0;
Chris@329 632 rec.additional = false;
Chris@45 633
Chris@45 634 m_models[model] = rec;
Chris@45 635
Chris@137 636 #ifdef DEBUG_DOCUMENT
Chris@233 637 SVDEBUG << "Document::addImportedModel: Added model " << model << endl;
Chris@293 638 cerr << "Models now: ";
Chris@137 639 for (ModelMap::const_iterator i = m_models.begin(); i != m_models.end(); ++i) {
Chris@293 640 cerr << i->first << " ";
Chris@137 641 }
Chris@293 642 cerr << endl;
Chris@137 643 #endif
Chris@137 644
Chris@387 645 if (m_autoAlignment) {
Chris@387 646 SVDEBUG << "Document::addImportedModel: auto-alignment is on, aligning model if possible" << endl;
Chris@387 647 alignModel(model);
Chris@387 648 } else {
Chris@387 649 SVDEBUG << "Document(" << this << "): addImportedModel: auto-alignment is off" << endl;
Chris@387 650 }
Chris@47 651
Chris@45 652 emit modelAdded(model);
Chris@45 653 }
Chris@45 654
Chris@329 655 void
Chris@329 656 Document::addAdditionalModel(Model *model)
Chris@329 657 {
Chris@329 658 if (m_models.find(model) != m_models.end()) {
Chris@329 659 cerr << "WARNING: Document::addAdditionalModel: Model already added"
Chris@329 660 << endl;
Chris@329 661 return;
Chris@329 662 }
Chris@329 663
Chris@329 664 ModelRecord rec;
Chris@329 665 rec.source = 0;
Chris@329 666 rec.refcount = 0;
Chris@329 667 rec.additional = true;
Chris@329 668
Chris@329 669 m_models[model] = rec;
Chris@329 670
Chris@329 671 #ifdef DEBUG_DOCUMENT
Chris@329 672 SVDEBUG << "Document::addAdditionalModel: Added model " << model << endl;
Chris@329 673 cerr << "Models now: ";
Chris@329 674 for (ModelMap::const_iterator i = m_models.begin(); i != m_models.end(); ++i) {
Chris@329 675 cerr << i->first << " ";
Chris@329 676 }
Chris@329 677 cerr << endl;
Chris@329 678 #endif
Chris@329 679
Chris@387 680 if (m_autoAlignment) {
Chris@387 681 SVDEBUG << "Document::addAdditionalModel: auto-alignment is on, aligning model if possible" << endl;
Chris@387 682 alignModel(model);
Chris@387 683 }
Chris@329 684
Chris@329 685 emit modelAdded(model);
Chris@329 686 }
Chris@329 687
Chris@45 688 Model *
Chris@72 689 Document::addDerivedModel(const Transform &transform,
Chris@78 690 const ModelTransformer::Input &input,
Chris@296 691 QString &message)
Chris@45 692 {
Chris@45 693 for (ModelMap::iterator i = m_models.begin(); i != m_models.end(); ++i) {
Chris@297 694 if (i->second.transform == transform &&
Chris@297 695 i->second.source == input.getModel() &&
Chris@72 696 i->second.channel == input.getChannel()) {
Chris@297 697 std::cerr << "derived model taken from map " << std::endl;
Chris@297 698 return i->first;
Chris@297 699 }
Chris@45 700 }
Chris@45 701
Chris@297 702 Transforms tt;
Chris@297 703 tt.push_back(transform);
Chris@329 704 vector<Model *> mm = addDerivedModels(tt, input, message, 0);
Chris@297 705 if (mm.empty()) return 0;
Chris@297 706 else return mm[0];
Chris@297 707 }
Chris@45 708
Chris@297 709 vector<Model *>
Chris@297 710 Document::addDerivedModels(const Transforms &transforms,
Chris@297 711 const ModelTransformer::Input &input,
Chris@329 712 QString &message,
Chris@329 713 AdditionalModelConverter *amc)
Chris@297 714 {
Chris@297 715 vector<Model *> mm =
Chris@297 716 ModelTransformerFactory::getInstance()->transformMultiple
Chris@329 717 (transforms, input, message, amc);
Chris@83 718
Chris@297 719 for (int j = 0; j < (int)mm.size(); ++j) {
Chris@83 720
Chris@297 721 Model *model = mm[j];
Chris@297 722
Chris@297 723 // The transform we actually used was presumably identical to
Chris@297 724 // the one asked for, except that the version of the plugin
Chris@297 725 // may differ. It's possible that the returned message
Chris@297 726 // contains a warning about this; that doesn't concern us
Chris@297 727 // here, but we do need to ensure that the transform we
Chris@297 728 // remember is correct for what was actually applied, with the
Chris@297 729 // current plugin version.
Chris@297 730
Chris@297 731 Transform applied = transforms[j];
Chris@297 732 applied.setPluginVersion
Chris@297 733 (TransformFactory::getInstance()->
Chris@297 734 getDefaultTransformFor(applied.getIdentifier(),
Chris@297 735 lrintf(applied.getSampleRate()))
Chris@297 736 .getPluginVersion());
Chris@297 737
Chris@297 738 if (!model) {
Chris@297 739 cerr << "WARNING: Document::addDerivedModel: no output model for transform " << applied.getIdentifier() << endl;
Chris@297 740 } else {
Chris@329 741 addAlreadyDerivedModel(applied, input, model);
Chris@297 742 }
Chris@45 743 }
gyorgyf@270 744
Chris@297 745 return mm;
Chris@45 746 }
Chris@45 747
Chris@45 748 void
Chris@45 749 Document::releaseModel(Model *model) // Will _not_ release main model!
Chris@45 750 {
Chris@45 751 if (model == 0) {
Chris@45 752 return;
Chris@45 753 }
Chris@45 754
Chris@45 755 if (model == m_mainModel) {
Chris@45 756 return;
Chris@45 757 }
Chris@45 758
Chris@45 759 bool toDelete = false;
Chris@45 760
Chris@45 761 if (m_models.find(model) != m_models.end()) {
Chris@45 762
Chris@45 763 if (m_models[model].refcount == 0) {
Chris@293 764 cerr << "WARNING: Document::releaseModel: model " << model
Chris@293 765 << " reference count is zero already!" << endl;
Chris@45 766 } else {
Chris@45 767 if (--m_models[model].refcount == 0) {
Chris@45 768 toDelete = true;
Chris@45 769 }
Chris@45 770 }
Chris@45 771 } else {
Chris@293 772 cerr << "WARNING: Document::releaseModel: Unfound model "
Chris@293 773 << model << endl;
Chris@45 774 toDelete = true;
Chris@45 775 }
Chris@45 776
Chris@45 777 if (toDelete) {
Chris@45 778
Chris@45 779 int sourceCount = 0;
Chris@45 780
Chris@45 781 for (ModelMap::iterator i = m_models.begin(); i != m_models.end(); ++i) {
Chris@45 782 if (i->second.source == model) {
Chris@45 783 ++sourceCount;
Chris@45 784 i->second.source = 0;
Chris@45 785 }
Chris@45 786 }
Chris@45 787
Chris@45 788 if (sourceCount > 0) {
Chris@233 789 SVDEBUG << "Document::releaseModel: Deleting model "
Chris@45 790 << model << " even though it is source for "
Chris@45 791 << sourceCount << " other derived model(s) -- resetting "
Chris@229 792 << "their source fields appropriately" << endl;
Chris@45 793 }
Chris@45 794
Chris@79 795 model->aboutToDelete();
Chris@45 796 emit modelAboutToBeDeleted(model);
Chris@45 797 m_models.erase(model);
Chris@137 798
Chris@137 799 #ifdef DEBUG_DOCUMENT
Chris@233 800 SVDEBUG << "Document::releaseModel: Deleted model " << model << endl;
Chris@293 801 cerr << "Models now: ";
Chris@137 802 for (ModelMap::const_iterator i = m_models.begin(); i != m_models.end(); ++i) {
Chris@293 803 cerr << i->first << " ";
Chris@137 804 }
Chris@293 805 cerr << endl;
Chris@137 806 #endif
Chris@137 807
Chris@45 808 delete model;
Chris@45 809 }
Chris@45 810 }
Chris@45 811
Chris@45 812 void
Chris@45 813 Document::deleteLayer(Layer *layer, bool force)
Chris@45 814 {
Chris@45 815 if (m_layerViewMap.find(layer) != m_layerViewMap.end() &&
Chris@45 816 m_layerViewMap[layer].size() > 0) {
Chris@45 817
Chris@293 818 cerr << "WARNING: Document::deleteLayer: Layer "
Chris@228 819 << layer << " [" << layer->objectName() << "]"
Chris@45 820 << " is still used in " << m_layerViewMap[layer].size()
Chris@293 821 << " views!" << endl;
Chris@45 822
Chris@45 823 if (force) {
Chris@45 824
Chris@77 825 #ifdef DEBUG_DOCUMENT
Chris@293 826 cerr << "(force flag set -- deleting from all views)" << endl;
Chris@77 827 #endif
Chris@45 828
Chris@45 829 for (std::set<View *>::iterator j = m_layerViewMap[layer].begin();
Chris@45 830 j != m_layerViewMap[layer].end(); ++j) {
Chris@45 831 // don't use removeLayerFromView, as it issues a command
Chris@45 832 layer->setLayerDormant(*j, true);
Chris@45 833 (*j)->removeLayer(layer);
Chris@45 834 }
Chris@45 835
Chris@45 836 m_layerViewMap.erase(layer);
Chris@45 837
Chris@45 838 } else {
Chris@45 839 return;
Chris@45 840 }
Chris@45 841 }
Chris@45 842
Chris@45 843 if (m_layers.find(layer) == m_layers.end()) {
Chris@233 844 SVDEBUG << "Document::deleteLayer: Layer "
Chris@212 845 << layer << " (" << typeid(layer).name() <<
Chris@212 846 ") does not exist, or has already been deleted "
Chris@229 847 << "(this may not be as serious as it sounds)" << endl;
Chris@45 848 return;
Chris@45 849 }
Chris@45 850
Chris@45 851 m_layers.erase(layer);
Chris@45 852
Chris@132 853 #ifdef DEBUG_DOCUMENT
Chris@233 854 SVDEBUG << "Document::deleteLayer: Removing, now have "
Chris@229 855 << m_layers.size() << " layers" << endl;
Chris@132 856 #endif
Chris@52 857
Chris@45 858 releaseModel(layer->getModel());
Chris@45 859 emit layerRemoved(layer);
Chris@45 860 emit layerAboutToBeDeleted(layer);
Chris@45 861 delete layer;
Chris@45 862 }
Chris@45 863
Chris@45 864 void
Chris@45 865 Document::setModel(Layer *layer, Model *model)
Chris@45 866 {
Chris@45 867 if (model &&
Chris@45 868 model != m_mainModel &&
Chris@45 869 m_models.find(model) == m_models.end()) {
Chris@293 870 cerr << "ERROR: Document::setModel: Layer " << layer
Chris@294 871 << " (\"" << layer->objectName()
Chris@45 872 << "\") wants to use unregistered model " << model
Chris@45 873 << ": register the layer's model before setting it!"
Chris@293 874 << endl;
Chris@45 875 return;
Chris@45 876 }
Chris@45 877
Chris@45 878 Model *previousModel = layer->getModel();
Chris@45 879
Chris@45 880 if (previousModel == model) {
Chris@233 881 SVDEBUG << "NOTE: Document::setModel: Layer " << layer << " (\""
Chris@229 882 << layer->objectName() << "\") is already set to model "
Chris@45 883 << model << " (\""
Chris@229 884 << (model ? model->objectName(): "(null)")
Chris@229 885 << "\")" << endl;
Chris@45 886 return;
Chris@45 887 }
Chris@45 888
Chris@45 889 if (model && model != m_mainModel) {
Chris@45 890 m_models[model].refcount ++;
Chris@45 891 }
Chris@45 892
Chris@45 893 if (model && previousModel) {
Chris@45 894 PlayParameterRepository::getInstance()->copyParameters
Chris@45 895 (previousModel, model);
Chris@45 896 }
Chris@45 897
Chris@45 898 LayerFactory::getInstance()->setModel(layer, model);
gyorgyf@272 899 // std::cerr << "layer type: " << LayerFactory::getInstance()->getLayerTypeName(LayerFactory::getInstance()->getLayerType(layer)) << std::endl;
Chris@45 900
Chris@45 901 if (previousModel) {
Chris@45 902 releaseModel(previousModel);
Chris@45 903 }
Chris@45 904 }
Chris@45 905
Chris@45 906 void
Chris@45 907 Document::setChannel(Layer *layer, int channel)
Chris@45 908 {
Chris@45 909 LayerFactory::getInstance()->setChannel(layer, channel);
Chris@45 910 }
Chris@45 911
Chris@45 912 void
Chris@45 913 Document::addLayerToView(View *view, Layer *layer)
Chris@45 914 {
Chris@45 915 Model *model = layer->getModel();
Chris@45 916 if (!model) {
Chris@77 917 #ifdef DEBUG_DOCUMENT
Chris@233 918 SVDEBUG << "Document::addLayerToView: Layer (\""
Chris@229 919 << layer->objectName() << "\") with no model being added to view: "
Chris@229 920 << "normally you want to set the model first" << endl;
Chris@77 921 #endif
Chris@45 922 } else {
Chris@45 923 if (model != m_mainModel &&
Chris@45 924 m_models.find(model) == m_models.end()) {
Chris@293 925 cerr << "ERROR: Document::addLayerToView: Layer " << layer
Chris@45 926 << " has unregistered model " << model
Chris@293 927 << " -- register the layer's model before adding the layer!" << endl;
Chris@45 928 return;
Chris@45 929 }
Chris@45 930 }
Chris@45 931
Chris@45 932 CommandHistory::getInstance()->addCommand
Chris@45 933 (new Document::AddLayerCommand(this, view, layer));
Chris@45 934 }
Chris@45 935
Chris@45 936 void
Chris@45 937 Document::removeLayerFromView(View *view, Layer *layer)
Chris@45 938 {
Chris@45 939 CommandHistory::getInstance()->addCommand
Chris@45 940 (new Document::RemoveLayerCommand(this, view, layer));
Chris@45 941 }
Chris@45 942
Chris@45 943 void
Chris@45 944 Document::addToLayerViewMap(Layer *layer, View *view)
Chris@45 945 {
Chris@45 946 bool firstView = (m_layerViewMap.find(layer) == m_layerViewMap.end() ||
Chris@45 947 m_layerViewMap[layer].empty());
Chris@45 948
Chris@45 949 if (m_layerViewMap[layer].find(view) !=
Chris@45 950 m_layerViewMap[layer].end()) {
Chris@293 951 cerr << "WARNING: Document::addToLayerViewMap:"
Chris@45 952 << " Layer " << layer << " -> view " << view << " already in"
Chris@293 953 << " layer view map -- internal inconsistency" << endl;
Chris@45 954 }
Chris@45 955
Chris@45 956 m_layerViewMap[layer].insert(view);
Chris@45 957
Chris@45 958 if (firstView) emit layerInAView(layer, true);
Chris@45 959 }
Chris@45 960
Chris@45 961 void
Chris@45 962 Document::removeFromLayerViewMap(Layer *layer, View *view)
Chris@45 963 {
Chris@45 964 if (m_layerViewMap[layer].find(view) ==
Chris@45 965 m_layerViewMap[layer].end()) {
Chris@293 966 cerr << "WARNING: Document::removeFromLayerViewMap:"
Chris@45 967 << " Layer " << layer << " -> view " << view << " not in"
Chris@293 968 << " layer view map -- internal inconsistency" << endl;
Chris@45 969 }
Chris@45 970
Chris@45 971 m_layerViewMap[layer].erase(view);
Chris@45 972
Chris@45 973 if (m_layerViewMap[layer].empty()) {
Chris@45 974 m_layerViewMap.erase(layer);
Chris@45 975 emit layerInAView(layer, false);
Chris@45 976 }
Chris@45 977 }
Chris@45 978
Chris@45 979 QString
Chris@45 980 Document::getUniqueLayerName(QString candidate)
Chris@45 981 {
Chris@45 982 for (int count = 1; ; ++count) {
Chris@45 983
Chris@45 984 QString adjusted =
Chris@45 985 (count > 1 ? QString("%1 <%2>").arg(candidate).arg(count) :
Chris@45 986 candidate);
Chris@45 987
Chris@45 988 bool duplicate = false;
Chris@45 989
Chris@45 990 for (LayerSet::iterator i = m_layers.begin(); i != m_layers.end(); ++i) {
Chris@45 991 if ((*i)->objectName() == adjusted) {
Chris@45 992 duplicate = true;
Chris@45 993 break;
Chris@45 994 }
Chris@45 995 }
Chris@45 996
Chris@45 997 if (!duplicate) return adjusted;
Chris@45 998 }
Chris@45 999 }
Chris@45 1000
Chris@45 1001 std::vector<Model *>
Chris@72 1002 Document::getTransformInputModels()
Chris@45 1003 {
Chris@45 1004 std::vector<Model *> models;
Chris@45 1005
Chris@45 1006 if (!m_mainModel) return models;
Chris@45 1007
Chris@45 1008 models.push_back(m_mainModel);
Chris@45 1009
Chris@45 1010 //!!! This will pick up all models, including those that aren't visible...
Chris@45 1011
Chris@45 1012 for (ModelMap::iterator i = m_models.begin(); i != m_models.end(); ++i) {
Chris@45 1013
Chris@45 1014 Model *model = i->first;
Chris@45 1015 if (!model || model == m_mainModel) continue;
Chris@45 1016 DenseTimeValueModel *dtvm = dynamic_cast<DenseTimeValueModel *>(model);
Chris@45 1017
Chris@45 1018 if (dtvm) {
Chris@45 1019 models.push_back(dtvm);
Chris@45 1020 }
Chris@45 1021 }
Chris@45 1022
Chris@45 1023 return models;
Chris@45 1024 }
Chris@45 1025
Chris@50 1026 bool
Chris@77 1027 Document::isKnownModel(const Model *model) const
Chris@77 1028 {
Chris@77 1029 if (model == m_mainModel) return true;
Chris@77 1030 return (m_models.find(const_cast<Model *>(model)) != m_models.end());
Chris@77 1031 }
Chris@77 1032
Chris@90 1033 TransformId
Chris@90 1034 Document::getAlignmentTransformName()
Chris@90 1035 {
Chris@90 1036 QSettings settings;
Chris@90 1037 settings.beginGroup("Alignment");
Chris@90 1038 TransformId id =
Chris@90 1039 settings.value("transform-id",
Chris@90 1040 "vamp:match-vamp-plugin:match:path").toString();
Chris@90 1041 settings.endGroup();
Chris@90 1042 return id;
Chris@90 1043 }
Chris@90 1044
Chris@77 1045 bool
Chris@51 1046 Document::canAlign()
Chris@50 1047 {
Chris@90 1048 TransformId id = getAlignmentTransformName();
Chris@54 1049 TransformFactory *factory = TransformFactory::getInstance();
Chris@54 1050 return factory->haveTransform(id);
Chris@50 1051 }
Chris@50 1052
Chris@45 1053 void
Chris@45 1054 Document::alignModel(Model *model)
Chris@45 1055 {
Chris@387 1056 SVDEBUG << "Document::alignModel(" << model << ")" << endl;
Chris@387 1057
Chris@387 1058 if (!m_mainModel) {
Chris@387 1059 SVDEBUG << "(no main model to align to)" << endl;
Chris@387 1060 return;
Chris@387 1061 }
Chris@45 1062
Chris@45 1063 RangeSummarisableTimeValueModel *rm =
Chris@45 1064 dynamic_cast<RangeSummarisableTimeValueModel *>(model);
Chris@387 1065 if (!rm) {
Chris@387 1066 SVDEBUG << "(main model is not alignable-to)" << endl;
Chris@387 1067 return;
Chris@387 1068 }
Chris@48 1069
Chris@86 1070 if (rm->getAlignmentReference() == m_mainModel) {
Chris@387 1071 SVDEBUG << "(model " << rm << " is already aligned to main model " << m_mainModel << ")" << endl;
Chris@86 1072 return;
Chris@86 1073 }
Chris@45 1074
Chris@86 1075 if (model == m_mainModel) {
Chris@86 1076 // The reference has an empty alignment to itself. This makes
Chris@86 1077 // it possible to distinguish between the reference and any
Chris@86 1078 // unaligned model just by looking at the model itself,
Chris@86 1079 // without also knowing what the main model is
Chris@233 1080 SVDEBUG << "Document::alignModel(" << model << "): is main model, setting appropriately" << endl;
Chris@86 1081 rm->setAlignment(new AlignmentModel(model, model, 0, 0));
Chris@86 1082 return;
Chris@86 1083 }
Chris@86 1084
Chris@45 1085 // This involves creating three new models:
Chris@45 1086
Chris@45 1087 // 1. an AggregateWaveModel to provide the mixdowns of the main
Chris@45 1088 // model and the new model in its two channels, as input to the
Chris@45 1089 // MATCH plugin
Chris@45 1090
Chris@45 1091 // 2. a SparseTimeValueModel, which is the model automatically
Chris@53 1092 // created by FeatureExtractionPluginTransformer when running the
Chris@45 1093 // MATCH plugin (thus containing the alignment path)
Chris@45 1094
Chris@45 1095 // 3. an AlignmentModel, which stores the path model and carries
Chris@45 1096 // out alignment lookups on it.
Chris@45 1097
Chris@45 1098 // The first two of these are provided as arguments to the
Chris@45 1099 // constructor for the third, which takes responsibility for
Chris@45 1100 // deleting them. The AlignmentModel, meanwhile, is passed to the
Chris@45 1101 // new model we are aligning, which also takes responsibility for
Chris@45 1102 // it. We should not have to delete any of these new models here.
Chris@45 1103
Chris@45 1104 AggregateWaveModel::ChannelSpecList components;
Chris@45 1105
Chris@45 1106 components.push_back(AggregateWaveModel::ModelChannelSpec
Chris@45 1107 (m_mainModel, -1));
Chris@45 1108
Chris@45 1109 components.push_back(AggregateWaveModel::ModelChannelSpec
Chris@45 1110 (rm, -1));
Chris@45 1111
Chris@112 1112 Model *aggregateModel = new AggregateWaveModel(components);
Chris@112 1113 ModelTransformer::Input aggregate(aggregateModel);
Chris@45 1114
Chris@72 1115 TransformId id = "vamp:match-vamp-plugin:match:path"; //!!! configure
Chris@45 1116
Chris@72 1117 TransformFactory *tf = TransformFactory::getInstance();
Chris@45 1118
Chris@72 1119 Transform transform = tf->getDefaultTransformFor
Chris@112 1120 (id, aggregateModel->getSampleRate());
Chris@57 1121
Chris@72 1122 transform.setStepSize(transform.getBlockSize()/2);
Chris@72 1123 transform.setParameter("serialise", 1);
Chris@64 1124
Chris@233 1125 SVDEBUG << "Document::alignModel: Alignment transform step size " << transform.getStepSize() << ", block size " << transform.getBlockSize() << endl;
Chris@81 1126
Chris@72 1127 ModelTransformerFactory *mtf = ModelTransformerFactory::getInstance();
Chris@72 1128
Chris@78 1129 QString message;
Chris@78 1130 Model *transformOutput = mtf->transform(transform, aggregate, message);
Chris@64 1131
Chris@64 1132 if (!transformOutput) {
Chris@72 1133 transform.setStepSize(0);
Chris@78 1134 transformOutput = mtf->transform(transform, aggregate, message);
Chris@64 1135 }
Chris@45 1136
Chris@45 1137 SparseTimeValueModel *path = dynamic_cast<SparseTimeValueModel *>
Chris@45 1138 (transformOutput);
Chris@45 1139
Chris@45 1140 if (!path) {
Chris@293 1141 cerr << "Document::alignModel: ERROR: Failed to create alignment path (no MATCH plugin?)" << endl;
Chris@78 1142 emit alignmentFailed(id, message);
Chris@45 1143 delete transformOutput;
Chris@112 1144 delete aggregateModel;
Chris@45 1145 return;
Chris@45 1146 }
Chris@45 1147
Chris@112 1148 path->setCompletion(0);
Chris@112 1149
Chris@45 1150 AlignmentModel *alignmentModel = new AlignmentModel
Chris@112 1151 (m_mainModel, model, aggregateModel, path);
Chris@45 1152
Chris@45 1153 rm->setAlignment(alignmentModel);
Chris@45 1154 }
Chris@45 1155
Chris@45 1156 void
Chris@45 1157 Document::alignModels()
Chris@45 1158 {
Chris@45 1159 for (ModelMap::iterator i = m_models.begin(); i != m_models.end(); ++i) {
Chris@45 1160 alignModel(i->first);
Chris@45 1161 }
Chris@86 1162 alignModel(m_mainModel);
Chris@45 1163 }
Chris@45 1164
Chris@45 1165 Document::AddLayerCommand::AddLayerCommand(Document *d,
Chris@45 1166 View *view,
Chris@45 1167 Layer *layer) :
Chris@45 1168 m_d(d),
Chris@45 1169 m_view(view),
Chris@45 1170 m_layer(layer),
Chris@45 1171 m_name(qApp->translate("AddLayerCommand", "Add %1 Layer").arg(layer->objectName())),
Chris@45 1172 m_added(false)
Chris@45 1173 {
Chris@45 1174 }
Chris@45 1175
Chris@45 1176 Document::AddLayerCommand::~AddLayerCommand()
Chris@45 1177 {
Chris@77 1178 #ifdef DEBUG_DOCUMENT
Chris@233 1179 SVDEBUG << "Document::AddLayerCommand::~AddLayerCommand" << endl;
Chris@77 1180 #endif
Chris@45 1181 if (!m_added) {
Chris@45 1182 m_d->deleteLayer(m_layer);
Chris@45 1183 }
Chris@45 1184 }
Chris@45 1185
Chris@159 1186 QString
Chris@159 1187 Document::AddLayerCommand::getName() const
Chris@159 1188 {
Chris@165 1189 #ifdef DEBUG_DOCUMENT
Chris@233 1190 SVDEBUG << "Document::AddLayerCommand::getName(): Name is "
Chris@229 1191 << m_name << endl;
Chris@165 1192 #endif
Chris@159 1193 return m_name;
Chris@159 1194 }
Chris@159 1195
Chris@45 1196 void
Chris@45 1197 Document::AddLayerCommand::execute()
Chris@45 1198 {
Chris@45 1199 for (int i = 0; i < m_view->getLayerCount(); ++i) {
Chris@45 1200 if (m_view->getLayer(i) == m_layer) {
Chris@45 1201 // already there
Chris@45 1202 m_layer->setLayerDormant(m_view, false);
Chris@45 1203 m_added = true;
Chris@45 1204 return;
Chris@45 1205 }
Chris@45 1206 }
Chris@45 1207
Chris@45 1208 m_view->addLayer(m_layer);
Chris@45 1209 m_layer->setLayerDormant(m_view, false);
Chris@45 1210
Chris@45 1211 m_d->addToLayerViewMap(m_layer, m_view);
Chris@45 1212 m_added = true;
Chris@45 1213 }
Chris@45 1214
Chris@45 1215 void
Chris@45 1216 Document::AddLayerCommand::unexecute()
Chris@45 1217 {
Chris@45 1218 m_view->removeLayer(m_layer);
Chris@45 1219 m_layer->setLayerDormant(m_view, true);
Chris@45 1220
Chris@45 1221 m_d->removeFromLayerViewMap(m_layer, m_view);
Chris@45 1222 m_added = false;
Chris@45 1223 }
Chris@45 1224
Chris@45 1225 Document::RemoveLayerCommand::RemoveLayerCommand(Document *d,
Chris@45 1226 View *view,
Chris@45 1227 Layer *layer) :
Chris@45 1228 m_d(d),
Chris@45 1229 m_view(view),
Chris@45 1230 m_layer(layer),
Chris@339 1231 m_wasDormant(layer->isLayerDormant(view)),
Chris@45 1232 m_name(qApp->translate("RemoveLayerCommand", "Delete %1 Layer").arg(layer->objectName())),
Chris@45 1233 m_added(true)
Chris@45 1234 {
Chris@45 1235 }
Chris@45 1236
Chris@45 1237 Document::RemoveLayerCommand::~RemoveLayerCommand()
Chris@45 1238 {
Chris@77 1239 #ifdef DEBUG_DOCUMENT
Chris@233 1240 SVDEBUG << "Document::RemoveLayerCommand::~RemoveLayerCommand" << endl;
Chris@77 1241 #endif
Chris@45 1242 if (!m_added) {
Chris@45 1243 m_d->deleteLayer(m_layer);
Chris@45 1244 }
Chris@45 1245 }
Chris@45 1246
Chris@159 1247 QString
Chris@159 1248 Document::RemoveLayerCommand::getName() const
Chris@159 1249 {
Chris@171 1250 #ifdef DEBUG_DOCUMENT
Chris@233 1251 SVDEBUG << "Document::RemoveLayerCommand::getName(): Name is "
Chris@229 1252 << m_name << endl;
Chris@171 1253 #endif
Chris@159 1254 return m_name;
Chris@159 1255 }
Chris@159 1256
Chris@45 1257 void
Chris@45 1258 Document::RemoveLayerCommand::execute()
Chris@45 1259 {
Chris@45 1260 bool have = false;
Chris@45 1261 for (int i = 0; i < m_view->getLayerCount(); ++i) {
Chris@45 1262 if (m_view->getLayer(i) == m_layer) {
Chris@45 1263 have = true;
Chris@45 1264 break;
Chris@45 1265 }
Chris@45 1266 }
Chris@45 1267
Chris@45 1268 if (!have) { // not there!
Chris@45 1269 m_layer->setLayerDormant(m_view, true);
Chris@45 1270 m_added = false;
Chris@45 1271 return;
Chris@45 1272 }
Chris@45 1273
Chris@45 1274 m_view->removeLayer(m_layer);
Chris@45 1275 m_layer->setLayerDormant(m_view, true);
Chris@45 1276
Chris@45 1277 m_d->removeFromLayerViewMap(m_layer, m_view);
Chris@45 1278 m_added = false;
Chris@45 1279 }
Chris@45 1280
Chris@45 1281 void
Chris@45 1282 Document::RemoveLayerCommand::unexecute()
Chris@45 1283 {
Chris@45 1284 m_view->addLayer(m_layer);
Chris@339 1285 m_layer->setLayerDormant(m_view, m_wasDormant);
Chris@45 1286
Chris@45 1287 m_d->addToLayerViewMap(m_layer, m_view);
Chris@45 1288 m_added = true;
Chris@45 1289 }
Chris@45 1290
Chris@45 1291 void
Chris@45 1292 Document::toXml(QTextStream &out, QString indent, QString extraAttributes) const
Chris@45 1293 {
Chris@226 1294 toXml(out, indent, extraAttributes, false);
Chris@226 1295 }
Chris@226 1296
Chris@226 1297 void
Chris@226 1298 Document::toXmlAsTemplate(QTextStream &out, QString indent, QString extraAttributes) const
Chris@226 1299 {
Chris@226 1300 toXml(out, indent, extraAttributes, true);
Chris@226 1301 }
Chris@226 1302
Chris@226 1303 void
Chris@226 1304 Document::toXml(QTextStream &out, QString indent, QString extraAttributes,
Chris@226 1305 bool asTemplate) const
Chris@226 1306 {
Chris@45 1307 out << indent + QString("<data%1%2>\n")
Chris@45 1308 .arg(extraAttributes == "" ? "" : " ").arg(extraAttributes);
Chris@45 1309
Chris@45 1310 if (m_mainModel) {
Chris@108 1311
Chris@226 1312 if (asTemplate) {
Chris@226 1313 writePlaceholderMainModel(out, indent + " ");
Chris@226 1314 } else {
Chris@226 1315 m_mainModel->toXml(out, indent + " ", "mainModel=\"true\"");
Chris@226 1316 }
Chris@108 1317
Chris@108 1318 PlayParameters *playParameters =
Chris@108 1319 PlayParameterRepository::getInstance()->getPlayParameters(m_mainModel);
Chris@108 1320 if (playParameters) {
Chris@108 1321 playParameters->toXml
Chris@108 1322 (out, indent + " ",
Chris@108 1323 QString("model=\"%1\"")
Chris@108 1324 .arg(XmlExportable::getObjectExportId(m_mainModel)));
Chris@108 1325 }
Chris@45 1326 }
Chris@45 1327
Chris@45 1328 // Models that are not used in a layer that is in a view should
Chris@45 1329 // not be written. Get our list of required models first.
Chris@45 1330
Chris@45 1331 std::set<const Model *> used;
Chris@45 1332
Chris@45 1333 for (LayerViewMap::const_iterator i = m_layerViewMap.begin();
Chris@45 1334 i != m_layerViewMap.end(); ++i) {
Chris@45 1335
Chris@45 1336 if (i->first && !i->second.empty() && i->first->getModel()) {
Chris@45 1337 used.insert(i->first->getModel());
Chris@45 1338 }
Chris@45 1339 }
Chris@45 1340
Chris@111 1341 std::set<Model *> written;
Chris@111 1342
Chris@45 1343 for (ModelMap::const_iterator i = m_models.begin();
Chris@45 1344 i != m_models.end(); ++i) {
Chris@45 1345
Chris@111 1346 Model *model = i->first;
Chris@45 1347 const ModelRecord &rec = i->second;
Chris@45 1348
Chris@45 1349 if (used.find(model) == used.end()) continue;
Chris@45 1350
Chris@45 1351 // We need an intelligent way to determine which models need
Chris@45 1352 // to be streamed (i.e. have been edited, or are small) and
Chris@45 1353 // which should not be (i.e. remain as generated by a
Chris@45 1354 // transform, and are large).
Chris@45 1355 //
Chris@45 1356 // At the moment we can get away with deciding not to stream
Chris@45 1357 // dense 3d models or writable wave file models, provided they
Chris@45 1358 // were generated from a transform, because at the moment there
Chris@45 1359 // is no way to edit those model types so it should be safe to
Chris@45 1360 // regenerate them. That won't always work in future though.
Chris@45 1361 // It would be particularly nice to be able to ask the user,
Chris@45 1362 // as well as making an intelligent guess.
Chris@45 1363
Chris@45 1364 bool writeModel = true;
Chris@45 1365 bool haveDerivation = false;
Chris@45 1366
Chris@72 1367 if (rec.source && rec.transform.getIdentifier() != "") {
Chris@45 1368 haveDerivation = true;
Chris@45 1369 }
Chris@45 1370
Chris@45 1371 if (haveDerivation) {
Chris@45 1372 if (dynamic_cast<const WritableWaveFileModel *>(model)) {
Chris@45 1373 writeModel = false;
Chris@45 1374 } else if (dynamic_cast<const DenseThreeDimensionalModel *>(model)) {
Chris@45 1375 writeModel = false;
Chris@45 1376 }
Chris@45 1377 }
Chris@45 1378
Chris@45 1379 if (writeModel) {
Chris@111 1380 model->toXml(out, indent + " ");
Chris@111 1381 written.insert(model);
Chris@45 1382 }
Chris@45 1383
Chris@45 1384 if (haveDerivation) {
Chris@72 1385 writeBackwardCompatibleDerivation(out, indent + " ",
Chris@111 1386 model, rec);
Chris@45 1387 }
Chris@45 1388
Chris@45 1389 //!!! We should probably own the PlayParameterRepository
Chris@45 1390 PlayParameters *playParameters =
Chris@111 1391 PlayParameterRepository::getInstance()->getPlayParameters(model);
Chris@45 1392 if (playParameters) {
Chris@45 1393 playParameters->toXml
Chris@45 1394 (out, indent + " ",
Chris@45 1395 QString("model=\"%1\"")
Chris@111 1396 .arg(XmlExportable::getObjectExportId(model)));
Chris@45 1397 }
Chris@45 1398 }
Chris@45 1399
Chris@111 1400 //!!!
Chris@111 1401
Chris@111 1402 // We should write out the alignment models here. AlignmentModel
Chris@111 1403 // needs a toXml that writes out the export IDs of its reference
Chris@111 1404 // and aligned models, and then streams its path model. Note that
Chris@111 1405 // this will only work when the alignment is complete, so we
Chris@111 1406 // should probably wait for it if it isn't already by this point.
Chris@111 1407
Chris@111 1408 for (std::set<Model *>::const_iterator i = written.begin();
Chris@111 1409 i != written.end(); ++i) {
Chris@111 1410
Chris@111 1411 const Model *model = *i;
Chris@111 1412 const AlignmentModel *alignment = model->getAlignment();
Chris@111 1413 if (!alignment) continue;
Chris@111 1414
Chris@111 1415 alignment->toXml(out, indent + " ");
Chris@111 1416 }
Chris@111 1417
Chris@45 1418 for (LayerSet::const_iterator i = m_layers.begin();
Chris@45 1419 i != m_layers.end(); ++i) {
Chris@45 1420
Chris@45 1421 (*i)->toXml(out, indent + " ");
Chris@45 1422 }
Chris@45 1423
Chris@45 1424 out << indent + "</data>\n";
Chris@45 1425 }
Chris@45 1426
Chris@72 1427 void
Chris@226 1428 Document::writePlaceholderMainModel(QTextStream &out, QString indent) const
Chris@226 1429 {
Chris@226 1430 out << indent;
Chris@226 1431 out << QString("<model id=\"%1\" name=\"placeholder\" sampleRate=\"%2\" type=\"wavefile\" file=\":samples/silent.wav\" mainModel=\"true\"/>\n")
Chris@226 1432 .arg(getObjectExportId(m_mainModel))
Chris@226 1433 .arg(m_mainModel->getSampleRate());
Chris@226 1434 }
Chris@226 1435
Chris@226 1436 void
Chris@72 1437 Document::writeBackwardCompatibleDerivation(QTextStream &out, QString indent,
Chris@72 1438 Model *targetModel,
Chris@72 1439 const ModelRecord &rec) const
Chris@72 1440 {
Chris@72 1441 // There is a lot of redundancy in the XML we output here, because
Chris@72 1442 // we want it to work with older SV session file reading code as
Chris@72 1443 // well.
Chris@72 1444 //
Chris@72 1445 // Formerly, a transform was described using a derivation element
Chris@72 1446 // which set out the source and target models, execution context
Chris@72 1447 // (step size, input channel etc) and transform id, containing a
Chris@72 1448 // plugin element which set out the transform parameters and so
Chris@72 1449 // on. (The plugin element came from a "configurationXml" string
Chris@72 1450 // obtained from PluginXml.)
Chris@72 1451 //
Chris@72 1452 // This has been replaced by a derivation element setting out the
Chris@72 1453 // source and target models and input channel, containing a
Chris@72 1454 // transform element which sets out everything in the Transform.
Chris@72 1455 //
Chris@72 1456 // In order to retain compatibility with older SV code, however,
Chris@72 1457 // we have to write out the same stuff into the derivation as
Chris@72 1458 // before, and manufacture an appropriate plugin element as well
Chris@72 1459 // as the transform element. In order that newer code knows it's
Chris@72 1460 // dealing with a newer format, we will also write an attribute
Chris@72 1461 // 'type="transform"' in the derivation element.
Chris@45 1462
Chris@72 1463 const Transform &transform = rec.transform;
Chris@72 1464
Chris@72 1465 // Just for reference, this is what we would write if we didn't
Chris@72 1466 // have to be backward compatible:
Chris@72 1467 //
Chris@72 1468 // out << indent
Chris@72 1469 // << QString("<derivation type=\"transform\" source=\"%1\" "
Chris@72 1470 // "model=\"%2\" channel=\"%3\">\n")
Chris@72 1471 // .arg(XmlExportable::getObjectExportId(rec.source))
Chris@72 1472 // .arg(XmlExportable::getObjectExportId(targetModel))
Chris@72 1473 // .arg(rec.channel);
Chris@72 1474 //
Chris@72 1475 // transform.toXml(out, indent + " ");
Chris@72 1476 //
Chris@72 1477 // out << indent << "</derivation>\n";
Chris@72 1478 //
Chris@72 1479 // Unfortunately, we can't just do that. So we do this...
Chris@72 1480
Chris@72 1481 QString extentsAttributes;
Chris@72 1482 if (transform.getStartTime() != RealTime::zeroTime ||
Chris@72 1483 transform.getDuration() != RealTime::zeroTime) {
Chris@72 1484 extentsAttributes = QString("startFrame=\"%1\" duration=\"%2\" ")
Chris@72 1485 .arg(RealTime::realTime2Frame(transform.getStartTime(),
Chris@72 1486 targetModel->getSampleRate()))
Chris@72 1487 .arg(RealTime::realTime2Frame(transform.getDuration(),
Chris@72 1488 targetModel->getSampleRate()));
Chris@72 1489 }
Chris@72 1490
Chris@72 1491 out << indent;
Chris@72 1492 out << QString("<derivation type=\"transform\" source=\"%1\" "
Chris@72 1493 "model=\"%2\" channel=\"%3\" domain=\"%4\" "
Chris@72 1494 "stepSize=\"%5\" blockSize=\"%6\" %7windowType=\"%8\" "
Chris@72 1495 "transform=\"%9\">\n")
Chris@72 1496 .arg(XmlExportable::getObjectExportId(rec.source))
Chris@72 1497 .arg(XmlExportable::getObjectExportId(targetModel))
Chris@72 1498 .arg(rec.channel)
Chris@72 1499 .arg(TransformFactory::getInstance()->getTransformInputDomain
Chris@72 1500 (transform.getIdentifier()))
Chris@72 1501 .arg(transform.getStepSize())
Chris@72 1502 .arg(transform.getBlockSize())
Chris@72 1503 .arg(extentsAttributes)
Chris@72 1504 .arg(int(transform.getWindowType()))
Chris@72 1505 .arg(XmlExportable::encodeEntities(transform.getIdentifier()));
Chris@72 1506
Chris@72 1507 transform.toXml(out, indent + " ");
Chris@72 1508
Chris@72 1509 out << indent << " "
Chris@72 1510 << TransformFactory::getInstance()->getPluginConfigurationXml(transform);
Chris@72 1511
Chris@72 1512 out << indent << "</derivation>\n";
Chris@72 1513 }
Chris@72 1514