annotate framework/Document.cpp @ 496:4f1d280903ad tony-2.0-integration

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