annotate framework/Document.cpp @ 332:151b7c5864e3 tonioni

Need to call back on handler even when there are no additional layers (because it has not yet learned about the primary layers)
author Chris Cannam
date Wed, 05 Mar 2014 09:45:10 +0000
parents f72d58d1ccb0
children dd07d48d7d4f
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
Chris@45 111 Layer *
Chris@45 112 Document::createLayer(LayerFactory::LayerType type)
Chris@45 113 {
Chris@45 114 Layer *newLayer = LayerFactory::getInstance()->createLayer(type);
Chris@45 115 if (!newLayer) return 0;
Chris@45 116
Chris@45 117 newLayer->setObjectName(getUniqueLayerName(newLayer->objectName()));
Chris@45 118
Chris@45 119 m_layers.insert(newLayer);
Chris@52 120
Chris@77 121 #ifdef DEBUG_DOCUMENT
Chris@233 122 SVDEBUG << "Document::createLayer: Added layer of type " << type
Chris@229 123 << ", now have " << m_layers.size() << " layers" << endl;
Chris@77 124 #endif
Chris@52 125
Chris@45 126 emit layerAdded(newLayer);
Chris@45 127
Chris@45 128 return newLayer;
Chris@45 129 }
Chris@45 130
Chris@45 131 Layer *
Chris@45 132 Document::createMainModelLayer(LayerFactory::LayerType type)
Chris@45 133 {
Chris@45 134 Layer *newLayer = createLayer(type);
Chris@45 135 if (!newLayer) return 0;
Chris@45 136 setModel(newLayer, m_mainModel);
Chris@45 137 return newLayer;
Chris@45 138 }
Chris@45 139
Chris@45 140 Layer *
Chris@45 141 Document::createImportedLayer(Model *model)
Chris@45 142 {
Chris@45 143 LayerFactory::LayerTypeSet types =
Chris@45 144 LayerFactory::getInstance()->getValidLayerTypes(model);
Chris@45 145
Chris@45 146 if (types.empty()) {
Chris@293 147 cerr << "WARNING: Document::importLayer: no valid display layer for model" << endl;
Chris@45 148 return 0;
Chris@45 149 }
Chris@45 150
Chris@45 151 //!!! for now, just use the first suitable layer type
Chris@45 152 LayerFactory::LayerType type = *types.begin();
Chris@45 153
Chris@45 154 Layer *newLayer = LayerFactory::getInstance()->createLayer(type);
Chris@45 155 if (!newLayer) return 0;
Chris@45 156
Chris@45 157 newLayer->setObjectName(getUniqueLayerName(newLayer->objectName()));
Chris@45 158
Chris@45 159 addImportedModel(model);
Chris@45 160 setModel(newLayer, model);
Chris@45 161
Chris@45 162 //!!! and all channels
Chris@45 163 setChannel(newLayer, -1);
Chris@45 164
Chris@45 165 m_layers.insert(newLayer);
Chris@52 166
Chris@77 167 #ifdef DEBUG_DOCUMENT
Chris@233 168 SVDEBUG << "Document::createImportedLayer: Added layer of type " << type
Chris@229 169 << ", now have " << m_layers.size() << " layers" << endl;
Chris@77 170 #endif
Chris@52 171
Chris@45 172 emit layerAdded(newLayer);
Chris@45 173 return newLayer;
Chris@45 174 }
Chris@45 175
Chris@45 176 Layer *
Chris@45 177 Document::createEmptyLayer(LayerFactory::LayerType type)
Chris@45 178 {
Chris@61 179 if (!m_mainModel) return 0;
Chris@61 180
Chris@45 181 Model *newModel =
Chris@45 182 LayerFactory::getInstance()->createEmptyModel(type, m_mainModel);
Chris@45 183 if (!newModel) return 0;
Chris@45 184
Chris@45 185 Layer *newLayer = createLayer(type);
Chris@45 186 if (!newLayer) {
Chris@45 187 delete newModel;
Chris@45 188 return 0;
Chris@45 189 }
Chris@45 190
Chris@45 191 addImportedModel(newModel);
Chris@45 192 setModel(newLayer, newModel);
Chris@45 193
Chris@45 194 return newLayer;
Chris@45 195 }
Chris@45 196
Chris@45 197 Layer *
Chris@45 198 Document::createDerivedLayer(LayerFactory::LayerType type,
Chris@54 199 TransformId transform)
Chris@45 200 {
Chris@45 201 Layer *newLayer = createLayer(type);
Chris@45 202 if (!newLayer) return 0;
Chris@45 203
Chris@45 204 newLayer->setObjectName(getUniqueLayerName
Chris@54 205 (TransformFactory::getInstance()->
Chris@54 206 getTransformFriendlyName(transform)));
Chris@45 207
Chris@45 208 return newLayer;
Chris@45 209 }
Chris@297 210
Chris@45 211 Layer *
Chris@72 212 Document::createDerivedLayer(const Transform &transform,
Chris@72 213 const ModelTransformer::Input &input)
Chris@45 214 {
Chris@297 215 Transforms transforms;
Chris@297 216 transforms.push_back(transform);
Chris@297 217 vector<Layer *> layers = createDerivedLayers(transforms, input);
Chris@297 218 if (layers.empty()) return 0;
Chris@297 219 else return layers[0];
Chris@297 220 }
Chris@297 221
Chris@297 222 vector<Layer *>
Chris@297 223 Document::createDerivedLayers(const Transforms &transforms,
Chris@297 224 const ModelTransformer::Input &input)
Chris@297 225 {
Chris@78 226 QString message;
Chris@329 227 vector<Model *> newModels = addDerivedModels(transforms, input, message, 0);
Chris@297 228
Chris@297 229 if (newModels.empty()) {
Chris@297 230 //!!! This identifier may be wrong!
Chris@297 231 emit modelGenerationFailed(transforms[0].getIdentifier(), message);
Chris@297 232 return vector<Layer *>();
Chris@78 233 } else if (message != "") {
Chris@297 234 //!!! This identifier may be wrong!
Chris@297 235 emit modelGenerationWarning(transforms[0].getIdentifier(), message);
Chris@45 236 }
Chris@45 237
Chris@329 238 QStringList names;
Chris@329 239 for (int i = 0; i < newModels.size(); ++i) {
Chris@329 240 names.push_back(getUniqueLayerName
Chris@329 241 (TransformFactory::getInstance()->
Chris@329 242 getTransformFriendlyName
Chris@329 243 (transforms[i].getIdentifier())));
Chris@329 244 }
Chris@329 245
Chris@329 246 vector<Layer *> layers = createLayersForDerivedModels(newModels, names);
Chris@329 247 return layers;
Chris@329 248 }
Chris@329 249
Chris@329 250 class AdditionalModelConverter :
Chris@329 251 public ModelTransformerFactory::AdditionalModelHandler
Chris@329 252 {
Chris@329 253 public:
Chris@329 254 AdditionalModelConverter(Document *doc,
Chris@329 255 Document::LayerCreationHandler *handler) :
Chris@329 256 m_doc(doc),
Chris@329 257 m_handler(handler) {
Chris@329 258 }
Chris@329 259
Chris@329 260 virtual ~AdditionalModelConverter() { }
Chris@329 261
Chris@329 262 void
Chris@329 263 setPrimaryLayers(vector<Layer *> layers) {
Chris@329 264 m_primary = layers;
Chris@329 265 }
Chris@329 266
Chris@329 267 void
Chris@329 268 moreModelsAvailable(vector<Model *> models) {
Chris@329 269 std::cerr << "AdditionalModelConverter::moreModelsAvailable: " << models.size() << " model(s)" << std::endl;
Chris@329 270 // We can't automatically regenerate the additional models on
Chris@329 271 // reload -- we should delete them instead
Chris@329 272 QStringList names;
Chris@329 273 foreach (Model *model, models) {
Chris@329 274 m_doc->addAdditionalModel(model);
Chris@329 275 names.push_back(QString());
Chris@329 276 }
Chris@329 277 vector<Layer *> layers = m_doc->createLayersForDerivedModels
Chris@329 278 (models, names);
Chris@329 279 m_handler->layersCreated(m_primary, layers);
Chris@329 280 delete this;
Chris@329 281 }
Chris@329 282
Chris@329 283 void
Chris@329 284 noMoreModelsAvailable() {
Chris@329 285 std::cerr << "AdditionalModelConverter::noMoreModelsAvailable" << std::endl;
Chris@332 286 m_handler->layersCreated(m_primary, vector<Layer *>());
Chris@329 287 delete this;
Chris@329 288 }
Chris@329 289
Chris@329 290 private:
Chris@329 291 Document *m_doc;
Chris@329 292 vector<Layer *> m_primary;
Chris@329 293 Document::LayerCreationHandler *m_handler; //!!! how to handle destruction of this?
Chris@329 294 };
Chris@329 295
Chris@329 296 void
Chris@329 297 Document::createDerivedLayersAsync(const Transforms &transforms,
Chris@329 298 const ModelTransformer::Input &input,
Chris@329 299 LayerCreationHandler *handler)
Chris@329 300 {
Chris@329 301 QString message;
Chris@329 302
Chris@329 303 AdditionalModelConverter *amc = new AdditionalModelConverter(this, handler);
Chris@329 304
Chris@329 305 vector<Model *> newModels = addDerivedModels
Chris@329 306 (transforms, input, message, amc);
Chris@329 307
Chris@329 308 QStringList names;
Chris@329 309 for (int i = 0; i < newModels.size(); ++i) {
Chris@329 310 names.push_back(getUniqueLayerName
Chris@329 311 (TransformFactory::getInstance()->
Chris@329 312 getTransformFriendlyName
Chris@329 313 (transforms[i].getIdentifier())));
Chris@329 314 }
Chris@329 315
Chris@329 316 vector<Layer *> layers = createLayersForDerivedModels(newModels, names);
Chris@329 317 amc->setPrimaryLayers(layers);
Chris@329 318
Chris@329 319 if (newModels.empty()) {
Chris@329 320 //!!! This identifier may be wrong!
Chris@329 321 emit modelGenerationFailed(transforms[0].getIdentifier(), message);
Chris@329 322 } else if (message != "") {
Chris@329 323 //!!! This identifier may be wrong!
Chris@329 324 emit modelGenerationWarning(transforms[0].getIdentifier(), message);
Chris@329 325 }
Chris@329 326 }
Chris@329 327
Chris@329 328 vector<Layer *>
Chris@329 329 Document::createLayersForDerivedModels(vector<Model *> newModels,
Chris@329 330 QStringList names)
Chris@329 331 {
Chris@297 332 vector<Layer *> layers;
Chris@329 333
Chris@297 334 for (int i = 0; i < (int)newModels.size(); ++i) {
Chris@297 335
Chris@297 336 Model *newModel = newModels[i];
Chris@297 337
Chris@297 338 LayerFactory::LayerTypeSet types =
Chris@297 339 LayerFactory::getInstance()->getValidLayerTypes(newModel);
Chris@297 340
Chris@297 341 if (types.empty()) {
Chris@329 342 cerr << "WARNING: Document::createLayerForTransformer: no valid display layer for output of transform " << names[i] << endl;
Chris@297 343 //!!! inadequate cleanup:
Chris@297 344 newModel->aboutToDelete();
Chris@297 345 emit modelAboutToBeDeleted(newModel);
Chris@297 346 m_models.erase(newModel);
Chris@297 347 delete newModel;
Chris@297 348 return vector<Layer *>();
Chris@297 349 }
Chris@297 350
Chris@297 351 //!!! for now, just use the first suitable layer type
Chris@297 352
Chris@297 353 Layer *newLayer = createLayer(*types.begin());
Chris@297 354 setModel(newLayer, newModel);
Chris@297 355
Chris@297 356 //!!! We need to clone the model when adding the layer, so that it
Chris@297 357 //can be edited without affecting other layers that are based on
Chris@297 358 //the same model. Unfortunately we can't just clone it now,
Chris@297 359 //because it probably hasn't been completed yet -- the transform
Chris@297 360 //runs in the background. Maybe the transform has to handle
Chris@297 361 //cloning and cacheing models itself.
Chris@297 362 //
Chris@297 363 // Once we do clone models here, of course, we'll have to avoid
Chris@297 364 // leaking them too.
Chris@297 365 //
Chris@297 366 // We want the user to be able to add a model to a second layer
Chris@297 367 // _while it's still being calculated in the first_ and have it
Chris@297 368 // work quickly. That means we need to put the same physical
Chris@297 369 // model pointer in both layers, so they can't actually be cloned.
Chris@297 370
Chris@297 371 if (newLayer) {
Chris@329 372 newLayer->setObjectName(names[i]);
Chris@297 373 }
Chris@297 374
Chris@297 375 emit layerAdded(newLayer);
Chris@297 376 layers.push_back(newLayer);
Chris@45 377 }
Chris@45 378
Chris@297 379 return layers;
Chris@45 380 }
Chris@45 381
Chris@45 382 void
Chris@45 383 Document::setMainModel(WaveFileModel *model)
Chris@45 384 {
Chris@45 385 Model *oldMainModel = m_mainModel;
Chris@45 386 m_mainModel = model;
Chris@160 387
Chris@45 388 emit modelAdded(m_mainModel);
Chris@160 389 if (model) {
Chris@160 390 emit activity(tr("Set main model to %1").arg(model->objectName()));
Chris@160 391 } else {
Chris@160 392 emit activity(tr("Clear main model"));
Chris@160 393 }
Chris@45 394
Chris@45 395 std::vector<Layer *> obsoleteLayers;
Chris@53 396 std::set<QString> failedTransformers;
Chris@45 397
Chris@45 398 // We need to ensure that no layer is left using oldMainModel or
Chris@45 399 // any of the old derived models as its model. Either replace the
Chris@45 400 // model, or delete the layer for each layer that is currently
Chris@45 401 // using one of these. Carry out this replacement before we
Chris@45 402 // delete any of the models.
Chris@45 403
Chris@77 404 #ifdef DEBUG_DOCUMENT
Chris@293 405 cerr << "Document::setMainModel: Have "
Chris@293 406 << m_layers.size() << " layers" << endl;
Chris@293 407 cerr << "Models now: ";
Chris@137 408 for (ModelMap::const_iterator i = m_models.begin(); i != m_models.end(); ++i) {
Chris@293 409 cerr << i->first << " ";
Chris@137 410 }
Chris@293 411 cerr << endl;
Chris@293 412 cerr << "Old main model: " << oldMainModel << endl;
Chris@77 413 #endif
Chris@52 414
Chris@45 415 for (LayerSet::iterator i = m_layers.begin(); i != m_layers.end(); ++i) {
Chris@45 416
Chris@45 417 Layer *layer = *i;
Chris@45 418 Model *model = layer->getModel();
Chris@45 419
Chris@77 420 #ifdef DEBUG_DOCUMENT
Chris@293 421 cerr << "Document::setMainModel: inspecting model "
Chris@229 422 << (model ? model->objectName(): "(null)") << " in layer "
Chris@293 423 << layer->objectName() << endl;
Chris@77 424 #endif
Chris@45 425
Chris@70 426 if (model == oldMainModel) {
Chris@77 427 #ifdef DEBUG_DOCUMENT
Chris@293 428 cerr << "... it uses the old main model, replacing" << endl;
Chris@77 429 #endif
Chris@45 430 LayerFactory::getInstance()->setModel(layer, m_mainModel);
Chris@45 431 continue;
Chris@45 432 }
Chris@45 433
Chris@137 434 if (!model) {
Chris@293 435 cerr << "WARNING: Document::setMainModel: Null model in layer "
Chris@293 436 << layer << endl;
Chris@137 437 // get rid of this hideous degenerate
Chris@137 438 obsoleteLayers.push_back(layer);
Chris@137 439 continue;
Chris@137 440 }
Chris@137 441
Chris@137 442 if (m_models.find(model) == m_models.end()) {
Chris@293 443 cerr << "WARNING: Document::setMainModel: Unknown model "
Chris@293 444 << model << " in layer " << layer << endl;
Chris@137 445 // and this one
Chris@45 446 obsoleteLayers.push_back(layer);
Chris@45 447 continue;
Chris@45 448 }
Chris@45 449
Chris@70 450 if (m_models[model].source &&
Chris@70 451 (m_models[model].source == oldMainModel)) {
Chris@45 452
Chris@77 453 #ifdef DEBUG_DOCUMENT
Chris@293 454 cerr << "... it uses a model derived from the old main model, regenerating" << endl;
Chris@77 455 #endif
Chris@45 456
Chris@45 457 // This model was derived from the previous main
Chris@45 458 // model: regenerate it.
Chris@45 459
Chris@72 460 const Transform &transform = m_models[model].transform;
Chris@72 461 QString transformId = transform.getIdentifier();
Chris@45 462
Chris@72 463 //!!! We have a problem here if the number of channels in
Chris@72 464 //the main model has changed.
Chris@72 465
Chris@78 466 QString message;
Chris@45 467 Model *replacementModel =
Chris@45 468 addDerivedModel(transform,
Chris@72 469 ModelTransformer::Input
Chris@78 470 (m_mainModel, m_models[model].channel),
Chris@78 471 message);
Chris@45 472
Chris@45 473 if (!replacementModel) {
Chris@293 474 cerr << "WARNING: Document::setMainModel: Failed to regenerate model for transform \""
Chris@293 475 << transformId << "\"" << " in layer " << layer << endl;
Chris@72 476 if (failedTransformers.find(transformId)
Chris@72 477 == failedTransformers.end()) {
Chris@45 478 emit modelRegenerationFailed(layer->objectName(),
Chris@78 479 transformId,
Chris@78 480 message);
Chris@72 481 failedTransformers.insert(transformId);
Chris@45 482 }
Chris@45 483 obsoleteLayers.push_back(layer);
Chris@45 484 } else {
Chris@78 485 if (message != "") {
Chris@78 486 emit modelRegenerationWarning(layer->objectName(),
Chris@78 487 transformId,
Chris@78 488 message);
Chris@78 489 }
Chris@77 490 #ifdef DEBUG_DOCUMENT
Chris@293 491 cerr << "Replacing model " << model << " (type "
Chris@77 492 << typeid(*model).name() << ") with model "
Chris@77 493 << replacementModel << " (type "
Chris@77 494 << typeid(*replacementModel).name() << ") in layer "
Chris@228 495 << layer << " (name " << layer->objectName() << ")"
Chris@293 496 << endl;
Chris@77 497 #endif
Chris@45 498 RangeSummarisableTimeValueModel *rm =
Chris@45 499 dynamic_cast<RangeSummarisableTimeValueModel *>(replacementModel);
Chris@77 500 #ifdef DEBUG_DOCUMENT
Chris@45 501 if (rm) {
Chris@293 502 cerr << "new model has " << rm->getChannelCount() << " channels " << endl;
Chris@45 503 } else {
Chris@293 504 cerr << "new model " << replacementModel << " is not a RangeSummarisableTimeValueModel!" << endl;
Chris@45 505 }
Chris@77 506 #endif
Chris@45 507 setModel(layer, replacementModel);
Chris@45 508 }
Chris@45 509 }
Chris@45 510 }
Chris@45 511
Chris@45 512 for (size_t k = 0; k < obsoleteLayers.size(); ++k) {
Chris@45 513 deleteLayer(obsoleteLayers[k], true);
Chris@45 514 }
Chris@45 515
Chris@48 516 for (ModelMap::iterator i = m_models.begin(); i != m_models.end(); ++i) {
Chris@329 517 if (i->second.additional) {
Chris@329 518 Model *m = i->first;
Chris@329 519 emit modelAboutToBeDeleted(m);
Chris@329 520 delete m;
Chris@329 521 }
Chris@329 522 }
Chris@329 523
Chris@329 524 for (ModelMap::iterator i = m_models.begin(); i != m_models.end(); ++i) {
Chris@86 525
Chris@137 526 Model *m = i->first;
Chris@137 527
Chris@137 528 #ifdef DEBUG_DOCUMENT
Chris@233 529 SVDEBUG << "considering alignment for model " << m << " (name \""
Chris@229 530 << m->objectName() << "\")" << endl;
Chris@137 531 #endif
Chris@137 532
Chris@86 533 if (m_autoAlignment) {
Chris@86 534
Chris@137 535 alignModel(m);
Chris@86 536
Chris@86 537 } else if (oldMainModel &&
Chris@137 538 (m->getAlignmentReference() == oldMainModel)) {
Chris@86 539
Chris@137 540 alignModel(m);
Chris@48 541 }
Chris@48 542 }
Chris@48 543
Chris@77 544 if (oldMainModel) {
Chris@79 545 oldMainModel->aboutToDelete();
Chris@77 546 emit modelAboutToBeDeleted(oldMainModel);
Chris@77 547 }
Chris@77 548
Chris@86 549 if (m_autoAlignment) {
Chris@86 550 alignModel(m_mainModel);
Chris@86 551 }
Chris@86 552
Chris@45 553 emit mainModelChanged(m_mainModel);
Chris@45 554
Chris@45 555 delete oldMainModel;
Chris@45 556 }
Chris@45 557
Chris@45 558 void
Chris@329 559 Document::addAlreadyDerivedModel(const Transform &transform,
Chris@329 560 const ModelTransformer::Input &input,
Chris@329 561 Model *outputModelToAdd)
Chris@45 562 {
Chris@45 563 if (m_models.find(outputModelToAdd) != m_models.end()) {
Chris@329 564 cerr << "WARNING: Document::addAlreadyDerivedModel: Model already added"
Chris@293 565 << endl;
Chris@45 566 return;
Chris@45 567 }
Chris@45 568
Chris@77 569 #ifdef DEBUG_DOCUMENT
Chris@248 570 if (input.getModel()) {
Chris@329 571 cerr << "Document::addAlreadyDerivedModel: source is " << input.getModel() << " \"" << input.getModel()->objectName() << "\"" << endl;
Chris@248 572 } else {
Chris@329 573 cerr << "Document::addAlreadyDerivedModel: source is " << input.getModel() << endl;
Chris@248 574 }
Chris@77 575 #endif
Chris@45 576
Chris@45 577 ModelRecord rec;
Chris@72 578 rec.source = input.getModel();
Chris@72 579 rec.channel = input.getChannel();
Chris@45 580 rec.transform = transform;
Chris@329 581 rec.additional = false;
Chris@45 582 rec.refcount = 0;
Chris@45 583
Chris@72 584 outputModelToAdd->setSourceModel(input.getModel());
Chris@45 585
Chris@45 586 m_models[outputModelToAdd] = rec;
Chris@45 587
Chris@137 588 #ifdef DEBUG_DOCUMENT
Chris@329 589 cerr << "Document::addAlreadyDerivedModel: Added model " << outputModelToAdd << endl;
Chris@293 590 cerr << "Models now: ";
Chris@137 591 for (ModelMap::const_iterator i = m_models.begin(); i != m_models.end(); ++i) {
Chris@293 592 cerr << i->first << " ";
Chris@137 593 }
Chris@293 594 cerr << endl;
Chris@137 595 #endif
Chris@137 596
Chris@45 597 emit modelAdded(outputModelToAdd);
Chris@45 598 }
Chris@45 599
Chris@45 600
Chris@45 601 void
Chris@45 602 Document::addImportedModel(Model *model)
Chris@45 603 {
Chris@45 604 if (m_models.find(model) != m_models.end()) {
Chris@293 605 cerr << "WARNING: Document::addImportedModel: Model already added"
Chris@293 606 << endl;
Chris@45 607 return;
Chris@45 608 }
Chris@45 609
Chris@45 610 ModelRecord rec;
Chris@45 611 rec.source = 0;
Chris@45 612 rec.refcount = 0;
Chris@329 613 rec.additional = false;
Chris@45 614
Chris@45 615 m_models[model] = rec;
Chris@45 616
Chris@137 617 #ifdef DEBUG_DOCUMENT
Chris@233 618 SVDEBUG << "Document::addImportedModel: Added model " << model << endl;
Chris@293 619 cerr << "Models now: ";
Chris@137 620 for (ModelMap::const_iterator i = m_models.begin(); i != m_models.end(); ++i) {
Chris@293 621 cerr << i->first << " ";
Chris@137 622 }
Chris@293 623 cerr << endl;
Chris@137 624 #endif
Chris@137 625
Chris@47 626 if (m_autoAlignment) alignModel(model);
Chris@47 627
Chris@45 628 emit modelAdded(model);
Chris@45 629 }
Chris@45 630
Chris@329 631 void
Chris@329 632 Document::addAdditionalModel(Model *model)
Chris@329 633 {
Chris@329 634 if (m_models.find(model) != m_models.end()) {
Chris@329 635 cerr << "WARNING: Document::addAdditionalModel: Model already added"
Chris@329 636 << endl;
Chris@329 637 return;
Chris@329 638 }
Chris@329 639
Chris@329 640 ModelRecord rec;
Chris@329 641 rec.source = 0;
Chris@329 642 rec.refcount = 0;
Chris@329 643 rec.additional = true;
Chris@329 644
Chris@329 645 m_models[model] = rec;
Chris@329 646
Chris@329 647 #ifdef DEBUG_DOCUMENT
Chris@329 648 SVDEBUG << "Document::addAdditionalModel: Added model " << model << endl;
Chris@329 649 cerr << "Models now: ";
Chris@329 650 for (ModelMap::const_iterator i = m_models.begin(); i != m_models.end(); ++i) {
Chris@329 651 cerr << i->first << " ";
Chris@329 652 }
Chris@329 653 cerr << endl;
Chris@329 654 #endif
Chris@329 655
Chris@329 656 if (m_autoAlignment) alignModel(model);
Chris@329 657
Chris@329 658 emit modelAdded(model);
Chris@329 659 }
Chris@329 660
Chris@45 661 Model *
Chris@72 662 Document::addDerivedModel(const Transform &transform,
Chris@78 663 const ModelTransformer::Input &input,
Chris@296 664 QString &message)
Chris@45 665 {
Chris@45 666 for (ModelMap::iterator i = m_models.begin(); i != m_models.end(); ++i) {
Chris@297 667 if (i->second.transform == transform &&
Chris@297 668 i->second.source == input.getModel() &&
Chris@72 669 i->second.channel == input.getChannel()) {
Chris@297 670 std::cerr << "derived model taken from map " << std::endl;
Chris@297 671 return i->first;
Chris@297 672 }
Chris@45 673 }
Chris@45 674
Chris@297 675 Transforms tt;
Chris@297 676 tt.push_back(transform);
Chris@329 677 vector<Model *> mm = addDerivedModels(tt, input, message, 0);
Chris@297 678 if (mm.empty()) return 0;
Chris@297 679 else return mm[0];
Chris@297 680 }
Chris@45 681
Chris@297 682 vector<Model *>
Chris@297 683 Document::addDerivedModels(const Transforms &transforms,
Chris@297 684 const ModelTransformer::Input &input,
Chris@329 685 QString &message,
Chris@329 686 AdditionalModelConverter *amc)
Chris@297 687 {
Chris@297 688 vector<Model *> mm =
Chris@297 689 ModelTransformerFactory::getInstance()->transformMultiple
Chris@329 690 (transforms, input, message, amc);
Chris@83 691
Chris@297 692 for (int j = 0; j < (int)mm.size(); ++j) {
Chris@83 693
Chris@297 694 Model *model = mm[j];
Chris@297 695
Chris@297 696 // The transform we actually used was presumably identical to
Chris@297 697 // the one asked for, except that the version of the plugin
Chris@297 698 // may differ. It's possible that the returned message
Chris@297 699 // contains a warning about this; that doesn't concern us
Chris@297 700 // here, but we do need to ensure that the transform we
Chris@297 701 // remember is correct for what was actually applied, with the
Chris@297 702 // current plugin version.
Chris@297 703
Chris@297 704 Transform applied = transforms[j];
Chris@297 705 applied.setPluginVersion
Chris@297 706 (TransformFactory::getInstance()->
Chris@297 707 getDefaultTransformFor(applied.getIdentifier(),
Chris@297 708 lrintf(applied.getSampleRate()))
Chris@297 709 .getPluginVersion());
Chris@297 710
Chris@297 711 if (!model) {
Chris@297 712 cerr << "WARNING: Document::addDerivedModel: no output model for transform " << applied.getIdentifier() << endl;
Chris@297 713 } else {
Chris@329 714 addAlreadyDerivedModel(applied, input, model);
Chris@297 715 }
Chris@45 716 }
gyorgyf@270 717
Chris@297 718 return mm;
Chris@45 719 }
Chris@45 720
Chris@45 721 void
Chris@45 722 Document::releaseModel(Model *model) // Will _not_ release main model!
Chris@45 723 {
Chris@45 724 if (model == 0) {
Chris@45 725 return;
Chris@45 726 }
Chris@45 727
Chris@45 728 if (model == m_mainModel) {
Chris@45 729 return;
Chris@45 730 }
Chris@45 731
Chris@45 732 bool toDelete = false;
Chris@45 733
Chris@45 734 if (m_models.find(model) != m_models.end()) {
Chris@45 735
Chris@45 736 if (m_models[model].refcount == 0) {
Chris@293 737 cerr << "WARNING: Document::releaseModel: model " << model
Chris@293 738 << " reference count is zero already!" << endl;
Chris@45 739 } else {
Chris@45 740 if (--m_models[model].refcount == 0) {
Chris@45 741 toDelete = true;
Chris@45 742 }
Chris@45 743 }
Chris@45 744 } else {
Chris@293 745 cerr << "WARNING: Document::releaseModel: Unfound model "
Chris@293 746 << model << endl;
Chris@45 747 toDelete = true;
Chris@45 748 }
Chris@45 749
Chris@45 750 if (toDelete) {
Chris@45 751
Chris@45 752 int sourceCount = 0;
Chris@45 753
Chris@45 754 for (ModelMap::iterator i = m_models.begin(); i != m_models.end(); ++i) {
Chris@45 755 if (i->second.source == model) {
Chris@45 756 ++sourceCount;
Chris@45 757 i->second.source = 0;
Chris@45 758 }
Chris@45 759 }
Chris@45 760
Chris@45 761 if (sourceCount > 0) {
Chris@233 762 SVDEBUG << "Document::releaseModel: Deleting model "
Chris@45 763 << model << " even though it is source for "
Chris@45 764 << sourceCount << " other derived model(s) -- resetting "
Chris@229 765 << "their source fields appropriately" << endl;
Chris@45 766 }
Chris@45 767
Chris@79 768 model->aboutToDelete();
Chris@45 769 emit modelAboutToBeDeleted(model);
Chris@45 770 m_models.erase(model);
Chris@137 771
Chris@137 772 #ifdef DEBUG_DOCUMENT
Chris@233 773 SVDEBUG << "Document::releaseModel: Deleted model " << model << endl;
Chris@293 774 cerr << "Models now: ";
Chris@137 775 for (ModelMap::const_iterator i = m_models.begin(); i != m_models.end(); ++i) {
Chris@293 776 cerr << i->first << " ";
Chris@137 777 }
Chris@293 778 cerr << endl;
Chris@137 779 #endif
Chris@137 780
Chris@45 781 delete model;
Chris@45 782 }
Chris@45 783 }
Chris@45 784
Chris@45 785 void
Chris@45 786 Document::deleteLayer(Layer *layer, bool force)
Chris@45 787 {
Chris@45 788 if (m_layerViewMap.find(layer) != m_layerViewMap.end() &&
Chris@45 789 m_layerViewMap[layer].size() > 0) {
Chris@45 790
Chris@293 791 cerr << "WARNING: Document::deleteLayer: Layer "
Chris@228 792 << layer << " [" << layer->objectName() << "]"
Chris@45 793 << " is still used in " << m_layerViewMap[layer].size()
Chris@293 794 << " views!" << endl;
Chris@45 795
Chris@45 796 if (force) {
Chris@45 797
Chris@77 798 #ifdef DEBUG_DOCUMENT
Chris@293 799 cerr << "(force flag set -- deleting from all views)" << endl;
Chris@77 800 #endif
Chris@45 801
Chris@45 802 for (std::set<View *>::iterator j = m_layerViewMap[layer].begin();
Chris@45 803 j != m_layerViewMap[layer].end(); ++j) {
Chris@45 804 // don't use removeLayerFromView, as it issues a command
Chris@45 805 layer->setLayerDormant(*j, true);
Chris@45 806 (*j)->removeLayer(layer);
Chris@45 807 }
Chris@45 808
Chris@45 809 m_layerViewMap.erase(layer);
Chris@45 810
Chris@45 811 } else {
Chris@45 812 return;
Chris@45 813 }
Chris@45 814 }
Chris@45 815
Chris@45 816 if (m_layers.find(layer) == m_layers.end()) {
Chris@233 817 SVDEBUG << "Document::deleteLayer: Layer "
Chris@212 818 << layer << " (" << typeid(layer).name() <<
Chris@212 819 ") does not exist, or has already been deleted "
Chris@229 820 << "(this may not be as serious as it sounds)" << endl;
Chris@45 821 return;
Chris@45 822 }
Chris@45 823
Chris@45 824 m_layers.erase(layer);
Chris@45 825
Chris@132 826 #ifdef DEBUG_DOCUMENT
Chris@233 827 SVDEBUG << "Document::deleteLayer: Removing, now have "
Chris@229 828 << m_layers.size() << " layers" << endl;
Chris@132 829 #endif
Chris@52 830
Chris@45 831 releaseModel(layer->getModel());
Chris@45 832 emit layerRemoved(layer);
Chris@45 833 emit layerAboutToBeDeleted(layer);
Chris@45 834 delete layer;
Chris@45 835 }
Chris@45 836
Chris@45 837 void
Chris@45 838 Document::setModel(Layer *layer, Model *model)
Chris@45 839 {
Chris@45 840 if (model &&
Chris@45 841 model != m_mainModel &&
Chris@45 842 m_models.find(model) == m_models.end()) {
Chris@293 843 cerr << "ERROR: Document::setModel: Layer " << layer
Chris@294 844 << " (\"" << layer->objectName()
Chris@45 845 << "\") wants to use unregistered model " << model
Chris@45 846 << ": register the layer's model before setting it!"
Chris@293 847 << endl;
Chris@45 848 return;
Chris@45 849 }
Chris@45 850
Chris@45 851 Model *previousModel = layer->getModel();
Chris@45 852
Chris@45 853 if (previousModel == model) {
Chris@233 854 SVDEBUG << "NOTE: Document::setModel: Layer " << layer << " (\""
Chris@229 855 << layer->objectName() << "\") is already set to model "
Chris@45 856 << model << " (\""
Chris@229 857 << (model ? model->objectName(): "(null)")
Chris@229 858 << "\")" << endl;
Chris@45 859 return;
Chris@45 860 }
Chris@45 861
Chris@45 862 if (model && model != m_mainModel) {
Chris@45 863 m_models[model].refcount ++;
Chris@45 864 }
Chris@45 865
Chris@45 866 if (model && previousModel) {
Chris@45 867 PlayParameterRepository::getInstance()->copyParameters
Chris@45 868 (previousModel, model);
Chris@45 869 }
Chris@45 870
Chris@45 871 LayerFactory::getInstance()->setModel(layer, model);
gyorgyf@272 872 // std::cerr << "layer type: " << LayerFactory::getInstance()->getLayerTypeName(LayerFactory::getInstance()->getLayerType(layer)) << std::endl;
Chris@45 873
Chris@45 874 if (previousModel) {
Chris@45 875 releaseModel(previousModel);
Chris@45 876 }
Chris@45 877 }
Chris@45 878
Chris@45 879 void
Chris@45 880 Document::setChannel(Layer *layer, int channel)
Chris@45 881 {
Chris@45 882 LayerFactory::getInstance()->setChannel(layer, channel);
Chris@45 883 }
Chris@45 884
Chris@45 885 void
Chris@45 886 Document::addLayerToView(View *view, Layer *layer)
Chris@45 887 {
Chris@45 888 Model *model = layer->getModel();
Chris@45 889 if (!model) {
Chris@77 890 #ifdef DEBUG_DOCUMENT
Chris@233 891 SVDEBUG << "Document::addLayerToView: Layer (\""
Chris@229 892 << layer->objectName() << "\") with no model being added to view: "
Chris@229 893 << "normally you want to set the model first" << endl;
Chris@77 894 #endif
Chris@45 895 } else {
Chris@45 896 if (model != m_mainModel &&
Chris@45 897 m_models.find(model) == m_models.end()) {
Chris@293 898 cerr << "ERROR: Document::addLayerToView: Layer " << layer
Chris@45 899 << " has unregistered model " << model
Chris@293 900 << " -- register the layer's model before adding the layer!" << endl;
Chris@45 901 return;
Chris@45 902 }
Chris@45 903 }
Chris@45 904
Chris@45 905 CommandHistory::getInstance()->addCommand
Chris@45 906 (new Document::AddLayerCommand(this, view, layer));
Chris@45 907 }
Chris@45 908
Chris@45 909 void
Chris@45 910 Document::removeLayerFromView(View *view, Layer *layer)
Chris@45 911 {
Chris@45 912 CommandHistory::getInstance()->addCommand
Chris@45 913 (new Document::RemoveLayerCommand(this, view, layer));
Chris@45 914 }
Chris@45 915
Chris@45 916 void
Chris@45 917 Document::addToLayerViewMap(Layer *layer, View *view)
Chris@45 918 {
Chris@45 919 bool firstView = (m_layerViewMap.find(layer) == m_layerViewMap.end() ||
Chris@45 920 m_layerViewMap[layer].empty());
Chris@45 921
Chris@45 922 if (m_layerViewMap[layer].find(view) !=
Chris@45 923 m_layerViewMap[layer].end()) {
Chris@293 924 cerr << "WARNING: Document::addToLayerViewMap:"
Chris@45 925 << " Layer " << layer << " -> view " << view << " already in"
Chris@293 926 << " layer view map -- internal inconsistency" << endl;
Chris@45 927 }
Chris@45 928
Chris@45 929 m_layerViewMap[layer].insert(view);
Chris@45 930
Chris@45 931 if (firstView) emit layerInAView(layer, true);
Chris@45 932 }
Chris@45 933
Chris@45 934 void
Chris@45 935 Document::removeFromLayerViewMap(Layer *layer, View *view)
Chris@45 936 {
Chris@45 937 if (m_layerViewMap[layer].find(view) ==
Chris@45 938 m_layerViewMap[layer].end()) {
Chris@293 939 cerr << "WARNING: Document::removeFromLayerViewMap:"
Chris@45 940 << " Layer " << layer << " -> view " << view << " not in"
Chris@293 941 << " layer view map -- internal inconsistency" << endl;
Chris@45 942 }
Chris@45 943
Chris@45 944 m_layerViewMap[layer].erase(view);
Chris@45 945
Chris@45 946 if (m_layerViewMap[layer].empty()) {
Chris@45 947 m_layerViewMap.erase(layer);
Chris@45 948 emit layerInAView(layer, false);
Chris@45 949 }
Chris@45 950 }
Chris@45 951
Chris@45 952 QString
Chris@45 953 Document::getUniqueLayerName(QString candidate)
Chris@45 954 {
Chris@45 955 for (int count = 1; ; ++count) {
Chris@45 956
Chris@45 957 QString adjusted =
Chris@45 958 (count > 1 ? QString("%1 <%2>").arg(candidate).arg(count) :
Chris@45 959 candidate);
Chris@45 960
Chris@45 961 bool duplicate = false;
Chris@45 962
Chris@45 963 for (LayerSet::iterator i = m_layers.begin(); i != m_layers.end(); ++i) {
Chris@45 964 if ((*i)->objectName() == adjusted) {
Chris@45 965 duplicate = true;
Chris@45 966 break;
Chris@45 967 }
Chris@45 968 }
Chris@45 969
Chris@45 970 if (!duplicate) return adjusted;
Chris@45 971 }
Chris@45 972 }
Chris@45 973
Chris@45 974 std::vector<Model *>
Chris@72 975 Document::getTransformInputModels()
Chris@45 976 {
Chris@45 977 std::vector<Model *> models;
Chris@45 978
Chris@45 979 if (!m_mainModel) return models;
Chris@45 980
Chris@45 981 models.push_back(m_mainModel);
Chris@45 982
Chris@45 983 //!!! This will pick up all models, including those that aren't visible...
Chris@45 984
Chris@45 985 for (ModelMap::iterator i = m_models.begin(); i != m_models.end(); ++i) {
Chris@45 986
Chris@45 987 Model *model = i->first;
Chris@45 988 if (!model || model == m_mainModel) continue;
Chris@45 989 DenseTimeValueModel *dtvm = dynamic_cast<DenseTimeValueModel *>(model);
Chris@45 990
Chris@45 991 if (dtvm) {
Chris@45 992 models.push_back(dtvm);
Chris@45 993 }
Chris@45 994 }
Chris@45 995
Chris@45 996 return models;
Chris@45 997 }
Chris@45 998
Chris@50 999 bool
Chris@77 1000 Document::isKnownModel(const Model *model) const
Chris@77 1001 {
Chris@77 1002 if (model == m_mainModel) return true;
Chris@77 1003 return (m_models.find(const_cast<Model *>(model)) != m_models.end());
Chris@77 1004 }
Chris@77 1005
Chris@90 1006 TransformId
Chris@90 1007 Document::getAlignmentTransformName()
Chris@90 1008 {
Chris@90 1009 QSettings settings;
Chris@90 1010 settings.beginGroup("Alignment");
Chris@90 1011 TransformId id =
Chris@90 1012 settings.value("transform-id",
Chris@90 1013 "vamp:match-vamp-plugin:match:path").toString();
Chris@90 1014 settings.endGroup();
Chris@90 1015 return id;
Chris@90 1016 }
Chris@90 1017
Chris@77 1018 bool
Chris@51 1019 Document::canAlign()
Chris@50 1020 {
Chris@90 1021 TransformId id = getAlignmentTransformName();
Chris@54 1022 TransformFactory *factory = TransformFactory::getInstance();
Chris@54 1023 return factory->haveTransform(id);
Chris@50 1024 }
Chris@50 1025
Chris@45 1026 void
Chris@45 1027 Document::alignModel(Model *model)
Chris@45 1028 {
Chris@86 1029 if (!m_mainModel) return;
Chris@45 1030
Chris@45 1031 RangeSummarisableTimeValueModel *rm =
Chris@45 1032 dynamic_cast<RangeSummarisableTimeValueModel *>(model);
Chris@45 1033 if (!rm) return;
Chris@48 1034
Chris@86 1035 if (rm->getAlignmentReference() == m_mainModel) {
Chris@233 1036 SVDEBUG << "Document::alignModel: model " << rm << " is already aligned to main model " << m_mainModel << endl;
Chris@86 1037 return;
Chris@86 1038 }
Chris@45 1039
Chris@86 1040 if (model == m_mainModel) {
Chris@86 1041 // The reference has an empty alignment to itself. This makes
Chris@86 1042 // it possible to distinguish between the reference and any
Chris@86 1043 // unaligned model just by looking at the model itself,
Chris@86 1044 // without also knowing what the main model is
Chris@233 1045 SVDEBUG << "Document::alignModel(" << model << "): is main model, setting appropriately" << endl;
Chris@86 1046 rm->setAlignment(new AlignmentModel(model, model, 0, 0));
Chris@86 1047 return;
Chris@86 1048 }
Chris@86 1049
Chris@45 1050 // This involves creating three new models:
Chris@45 1051
Chris@45 1052 // 1. an AggregateWaveModel to provide the mixdowns of the main
Chris@45 1053 // model and the new model in its two channels, as input to the
Chris@45 1054 // MATCH plugin
Chris@45 1055
Chris@45 1056 // 2. a SparseTimeValueModel, which is the model automatically
Chris@53 1057 // created by FeatureExtractionPluginTransformer when running the
Chris@45 1058 // MATCH plugin (thus containing the alignment path)
Chris@45 1059
Chris@45 1060 // 3. an AlignmentModel, which stores the path model and carries
Chris@45 1061 // out alignment lookups on it.
Chris@45 1062
Chris@45 1063 // The first two of these are provided as arguments to the
Chris@45 1064 // constructor for the third, which takes responsibility for
Chris@45 1065 // deleting them. The AlignmentModel, meanwhile, is passed to the
Chris@45 1066 // new model we are aligning, which also takes responsibility for
Chris@45 1067 // it. We should not have to delete any of these new models here.
Chris@45 1068
Chris@45 1069 AggregateWaveModel::ChannelSpecList components;
Chris@45 1070
Chris@45 1071 components.push_back(AggregateWaveModel::ModelChannelSpec
Chris@45 1072 (m_mainModel, -1));
Chris@45 1073
Chris@45 1074 components.push_back(AggregateWaveModel::ModelChannelSpec
Chris@45 1075 (rm, -1));
Chris@45 1076
Chris@112 1077 Model *aggregateModel = new AggregateWaveModel(components);
Chris@112 1078 ModelTransformer::Input aggregate(aggregateModel);
Chris@45 1079
Chris@72 1080 TransformId id = "vamp:match-vamp-plugin:match:path"; //!!! configure
Chris@45 1081
Chris@72 1082 TransformFactory *tf = TransformFactory::getInstance();
Chris@45 1083
Chris@72 1084 Transform transform = tf->getDefaultTransformFor
Chris@112 1085 (id, aggregateModel->getSampleRate());
Chris@57 1086
Chris@72 1087 transform.setStepSize(transform.getBlockSize()/2);
Chris@72 1088 transform.setParameter("serialise", 1);
Chris@64 1089
Chris@233 1090 SVDEBUG << "Document::alignModel: Alignment transform step size " << transform.getStepSize() << ", block size " << transform.getBlockSize() << endl;
Chris@81 1091
Chris@72 1092 ModelTransformerFactory *mtf = ModelTransformerFactory::getInstance();
Chris@72 1093
Chris@78 1094 QString message;
Chris@78 1095 Model *transformOutput = mtf->transform(transform, aggregate, message);
Chris@64 1096
Chris@64 1097 if (!transformOutput) {
Chris@72 1098 transform.setStepSize(0);
Chris@78 1099 transformOutput = mtf->transform(transform, aggregate, message);
Chris@64 1100 }
Chris@45 1101
Chris@45 1102 SparseTimeValueModel *path = dynamic_cast<SparseTimeValueModel *>
Chris@45 1103 (transformOutput);
Chris@45 1104
Chris@45 1105 if (!path) {
Chris@293 1106 cerr << "Document::alignModel: ERROR: Failed to create alignment path (no MATCH plugin?)" << endl;
Chris@78 1107 emit alignmentFailed(id, message);
Chris@45 1108 delete transformOutput;
Chris@112 1109 delete aggregateModel;
Chris@45 1110 return;
Chris@45 1111 }
Chris@45 1112
Chris@112 1113 path->setCompletion(0);
Chris@112 1114
Chris@45 1115 AlignmentModel *alignmentModel = new AlignmentModel
Chris@112 1116 (m_mainModel, model, aggregateModel, path);
Chris@45 1117
Chris@45 1118 rm->setAlignment(alignmentModel);
Chris@45 1119 }
Chris@45 1120
Chris@45 1121 void
Chris@45 1122 Document::alignModels()
Chris@45 1123 {
Chris@45 1124 for (ModelMap::iterator i = m_models.begin(); i != m_models.end(); ++i) {
Chris@45 1125 alignModel(i->first);
Chris@45 1126 }
Chris@86 1127 alignModel(m_mainModel);
Chris@45 1128 }
Chris@45 1129
Chris@45 1130 Document::AddLayerCommand::AddLayerCommand(Document *d,
Chris@45 1131 View *view,
Chris@45 1132 Layer *layer) :
Chris@45 1133 m_d(d),
Chris@45 1134 m_view(view),
Chris@45 1135 m_layer(layer),
Chris@45 1136 m_name(qApp->translate("AddLayerCommand", "Add %1 Layer").arg(layer->objectName())),
Chris@45 1137 m_added(false)
Chris@45 1138 {
Chris@45 1139 }
Chris@45 1140
Chris@45 1141 Document::AddLayerCommand::~AddLayerCommand()
Chris@45 1142 {
Chris@77 1143 #ifdef DEBUG_DOCUMENT
Chris@233 1144 SVDEBUG << "Document::AddLayerCommand::~AddLayerCommand" << endl;
Chris@77 1145 #endif
Chris@45 1146 if (!m_added) {
Chris@45 1147 m_d->deleteLayer(m_layer);
Chris@45 1148 }
Chris@45 1149 }
Chris@45 1150
Chris@159 1151 QString
Chris@159 1152 Document::AddLayerCommand::getName() const
Chris@159 1153 {
Chris@165 1154 #ifdef DEBUG_DOCUMENT
Chris@233 1155 SVDEBUG << "Document::AddLayerCommand::getName(): Name is "
Chris@229 1156 << m_name << endl;
Chris@165 1157 #endif
Chris@159 1158 return m_name;
Chris@159 1159 }
Chris@159 1160
Chris@45 1161 void
Chris@45 1162 Document::AddLayerCommand::execute()
Chris@45 1163 {
Chris@45 1164 for (int i = 0; i < m_view->getLayerCount(); ++i) {
Chris@45 1165 if (m_view->getLayer(i) == m_layer) {
Chris@45 1166 // already there
Chris@45 1167 m_layer->setLayerDormant(m_view, false);
Chris@45 1168 m_added = true;
Chris@45 1169 return;
Chris@45 1170 }
Chris@45 1171 }
Chris@45 1172
Chris@45 1173 m_view->addLayer(m_layer);
Chris@45 1174 m_layer->setLayerDormant(m_view, false);
Chris@45 1175
Chris@45 1176 m_d->addToLayerViewMap(m_layer, m_view);
Chris@45 1177 m_added = true;
Chris@45 1178 }
Chris@45 1179
Chris@45 1180 void
Chris@45 1181 Document::AddLayerCommand::unexecute()
Chris@45 1182 {
Chris@45 1183 m_view->removeLayer(m_layer);
Chris@45 1184 m_layer->setLayerDormant(m_view, true);
Chris@45 1185
Chris@45 1186 m_d->removeFromLayerViewMap(m_layer, m_view);
Chris@45 1187 m_added = false;
Chris@45 1188 }
Chris@45 1189
Chris@45 1190 Document::RemoveLayerCommand::RemoveLayerCommand(Document *d,
Chris@45 1191 View *view,
Chris@45 1192 Layer *layer) :
Chris@45 1193 m_d(d),
Chris@45 1194 m_view(view),
Chris@45 1195 m_layer(layer),
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@45 1249 m_layer->setLayerDormant(m_view, false);
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