annotate framework/Document.cpp @ 342:4eccff14b4d8 tonioni

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