annotate framework/Document.cpp @ 60:7b71da2d0631

* Some work on correct alignment when moving panes during playback * Overhaul alignment for playback frame values (view manager now always refers to reference-timeline values, only the play source deals in playback model timeline values) * When making a selection, ensure the selection regions shown in other panes (and used for playback constraints if appropriate) are aligned correctly. This may be the coolest feature ever implemented in any program ever.
author Chris Cannam
date Thu, 22 Nov 2007 14:17:19 +0000
parents 621c2edd1693
children 215b8b1b0308 89a689720ee9
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"
Chris@45 22 #include "layer/Layer.h"
Chris@45 23 #include "base/CommandHistory.h"
Chris@45 24 #include "base/Command.h"
Chris@45 25 #include "view/View.h"
Chris@45 26 #include "base/PlayParameterRepository.h"
Chris@45 27 #include "base/PlayParameters.h"
Chris@54 28 #include "plugin/transform/TransformFactory.h"
Chris@54 29 #include "plugin/transform/ModelTransformerFactory.h"
Chris@45 30 #include <QApplication>
Chris@45 31 #include <QTextStream>
Chris@45 32 #include <iostream>
Chris@45 33
Chris@45 34 // For alignment:
Chris@45 35 #include "data/model/AggregateWaveModel.h"
Chris@45 36 #include "data/model/SparseTimeValueModel.h"
Chris@45 37 #include "data/model/AlignmentModel.h"
Chris@45 38
Chris@45 39 //!!! still need to handle command history, documentRestored/documentModified
Chris@45 40
Chris@45 41 Document::Document() :
Chris@47 42 m_mainModel(0),
Chris@47 43 m_autoAlignment(false)
Chris@45 44 {
Chris@45 45 connect(this, SIGNAL(modelAboutToBeDeleted(Model *)),
Chris@54 46 ModelTransformerFactory::getInstance(),
Chris@45 47 SLOT(modelAboutToBeDeleted(Model *)));
Chris@45 48 }
Chris@45 49
Chris@45 50 Document::~Document()
Chris@45 51 {
Chris@45 52 //!!! Document should really own the command history. atm we
Chris@45 53 //still refer to it in various places that don't have access to
Chris@45 54 //the document, be nice to fix that
Chris@45 55
Chris@45 56 // std::cerr << "\n\nDocument::~Document: about to clear command history" << std::endl;
Chris@45 57 CommandHistory::getInstance()->clear();
Chris@45 58
Chris@52 59 std::cerr << "Document::~Document: about to delete layers" << std::endl;
Chris@45 60 while (!m_layers.empty()) {
Chris@45 61 deleteLayer(*m_layers.begin(), true);
Chris@45 62 }
Chris@45 63
Chris@45 64 if (!m_models.empty()) {
Chris@45 65 std::cerr << "Document::~Document: WARNING: "
Chris@45 66 << m_models.size() << " model(s) still remain -- "
Chris@45 67 << "should have been garbage collected when deleting layers"
Chris@45 68 << std::endl;
Chris@45 69 while (!m_models.empty()) {
Chris@45 70 Model *model = m_models.begin()->first;
Chris@45 71 if (model == m_mainModel) {
Chris@45 72 // just in case!
Chris@45 73 std::cerr << "Document::~Document: WARNING: Main model is also"
Chris@45 74 << " in models list!" << std::endl;
Chris@45 75 } else if (model) {
Chris@45 76 emit modelAboutToBeDeleted(model);
Chris@45 77 model->aboutToDelete();
Chris@45 78 delete model;
Chris@45 79 }
Chris@45 80 m_models.erase(m_models.begin());
Chris@45 81 }
Chris@45 82 }
Chris@45 83
Chris@45 84 // std::cerr << "Document::~Document: About to get rid of main model"
Chris@45 85 // << std::endl;
Chris@45 86 if (m_mainModel) {
Chris@45 87 emit modelAboutToBeDeleted(m_mainModel);
Chris@45 88 m_mainModel->aboutToDelete();
Chris@45 89 }
Chris@45 90
Chris@45 91 emit mainModelChanged(0);
Chris@45 92 delete m_mainModel;
Chris@45 93
Chris@45 94 }
Chris@45 95
Chris@45 96 Layer *
Chris@45 97 Document::createLayer(LayerFactory::LayerType type)
Chris@45 98 {
Chris@45 99 Layer *newLayer = LayerFactory::getInstance()->createLayer(type);
Chris@45 100 if (!newLayer) return 0;
Chris@45 101
Chris@45 102 newLayer->setObjectName(getUniqueLayerName(newLayer->objectName()));
Chris@45 103
Chris@45 104 m_layers.insert(newLayer);
Chris@52 105
Chris@52 106 std::cerr << "Document::createLayer: Added layer of type " << type
Chris@52 107 << ", now have " << m_layers.size() << " layers" << std::endl;
Chris@52 108
Chris@45 109 emit layerAdded(newLayer);
Chris@45 110
Chris@45 111 return newLayer;
Chris@45 112 }
Chris@45 113
Chris@45 114 Layer *
Chris@45 115 Document::createMainModelLayer(LayerFactory::LayerType type)
Chris@45 116 {
Chris@45 117 Layer *newLayer = createLayer(type);
Chris@45 118 if (!newLayer) return 0;
Chris@45 119 setModel(newLayer, m_mainModel);
Chris@45 120 return newLayer;
Chris@45 121 }
Chris@45 122
Chris@45 123 Layer *
Chris@45 124 Document::createImportedLayer(Model *model)
Chris@45 125 {
Chris@45 126 LayerFactory::LayerTypeSet types =
Chris@45 127 LayerFactory::getInstance()->getValidLayerTypes(model);
Chris@45 128
Chris@45 129 if (types.empty()) {
Chris@45 130 std::cerr << "WARNING: Document::importLayer: no valid display layer for model" << std::endl;
Chris@45 131 return 0;
Chris@45 132 }
Chris@45 133
Chris@45 134 //!!! for now, just use the first suitable layer type
Chris@45 135 LayerFactory::LayerType type = *types.begin();
Chris@45 136
Chris@45 137 Layer *newLayer = LayerFactory::getInstance()->createLayer(type);
Chris@45 138 if (!newLayer) return 0;
Chris@45 139
Chris@45 140 newLayer->setObjectName(getUniqueLayerName(newLayer->objectName()));
Chris@45 141
Chris@45 142 addImportedModel(model);
Chris@45 143 setModel(newLayer, model);
Chris@45 144
Chris@45 145 //!!! and all channels
Chris@45 146 setChannel(newLayer, -1);
Chris@45 147
Chris@45 148 m_layers.insert(newLayer);
Chris@52 149
Chris@52 150 std::cerr << "Document::createImportedLayer: Added layer of type " << type
Chris@52 151 << ", now have " << m_layers.size() << " layers" << std::endl;
Chris@52 152
Chris@45 153 emit layerAdded(newLayer);
Chris@45 154 return newLayer;
Chris@45 155 }
Chris@45 156
Chris@45 157 Layer *
Chris@45 158 Document::createEmptyLayer(LayerFactory::LayerType type)
Chris@45 159 {
Chris@45 160 Model *newModel =
Chris@45 161 LayerFactory::getInstance()->createEmptyModel(type, m_mainModel);
Chris@45 162 if (!newModel) return 0;
Chris@45 163
Chris@45 164 Layer *newLayer = createLayer(type);
Chris@45 165 if (!newLayer) {
Chris@45 166 delete newModel;
Chris@45 167 return 0;
Chris@45 168 }
Chris@45 169
Chris@45 170 addImportedModel(newModel);
Chris@45 171 setModel(newLayer, newModel);
Chris@45 172
Chris@45 173 return newLayer;
Chris@45 174 }
Chris@45 175
Chris@45 176 Layer *
Chris@45 177 Document::createDerivedLayer(LayerFactory::LayerType type,
Chris@54 178 TransformId transform)
Chris@45 179 {
Chris@45 180 Layer *newLayer = createLayer(type);
Chris@45 181 if (!newLayer) return 0;
Chris@45 182
Chris@45 183 newLayer->setObjectName(getUniqueLayerName
Chris@54 184 (TransformFactory::getInstance()->
Chris@54 185 getTransformFriendlyName(transform)));
Chris@45 186
Chris@45 187 return newLayer;
Chris@45 188 }
Chris@45 189
Chris@45 190 Layer *
Chris@54 191 Document::createDerivedLayer(TransformId transform,
Chris@45 192 Model *inputModel,
Chris@53 193 const PluginTransformer::ExecutionContext &context,
Chris@45 194 QString configurationXml)
Chris@45 195 {
Chris@45 196 Model *newModel = addDerivedModel(transform, inputModel,
Chris@45 197 context, configurationXml);
Chris@45 198 if (!newModel) {
Chris@45 199 // error already printed to stderr by addDerivedModel
Chris@45 200 emit modelGenerationFailed(transform);
Chris@45 201 return 0;
Chris@45 202 }
Chris@45 203
Chris@45 204 LayerFactory::LayerTypeSet types =
Chris@45 205 LayerFactory::getInstance()->getValidLayerTypes(newModel);
Chris@45 206
Chris@45 207 if (types.empty()) {
Chris@53 208 std::cerr << "WARNING: Document::createLayerForTransformer: no valid display layer for output of transform " << transform.toStdString() << std::endl;
Chris@45 209 delete newModel;
Chris@45 210 return 0;
Chris@45 211 }
Chris@45 212
Chris@45 213 //!!! for now, just use the first suitable layer type
Chris@45 214
Chris@45 215 Layer *newLayer = createLayer(*types.begin());
Chris@45 216 setModel(newLayer, newModel);
Chris@45 217
Chris@45 218 //!!! We need to clone the model when adding the layer, so that it
Chris@45 219 //can be edited without affecting other layers that are based on
Chris@45 220 //the same model. Unfortunately we can't just clone it now,
Chris@45 221 //because it probably hasn't been completed yet -- the transform
Chris@45 222 //runs in the background. Maybe the transform has to handle
Chris@45 223 //cloning and cacheing models itself.
Chris@45 224 //
Chris@45 225 // Once we do clone models here, of course, we'll have to avoid
Chris@45 226 // leaking them too.
Chris@45 227 //
Chris@45 228 // We want the user to be able to add a model to a second layer
Chris@45 229 // _while it's still being calculated in the first_ and have it
Chris@45 230 // work quickly. That means we need to put the same physical
Chris@45 231 // model pointer in both layers, so they can't actually be cloned.
Chris@45 232
Chris@45 233 if (newLayer) {
Chris@45 234 newLayer->setObjectName(getUniqueLayerName
Chris@54 235 (TransformFactory::getInstance()->
Chris@54 236 getTransformFriendlyName(transform)));
Chris@45 237 }
Chris@45 238
Chris@45 239 emit layerAdded(newLayer);
Chris@45 240 return newLayer;
Chris@45 241 }
Chris@45 242
Chris@45 243 void
Chris@45 244 Document::setMainModel(WaveFileModel *model)
Chris@45 245 {
Chris@45 246 Model *oldMainModel = m_mainModel;
Chris@45 247 m_mainModel = model;
Chris@45 248
Chris@45 249 emit modelAdded(m_mainModel);
Chris@45 250
Chris@45 251 std::vector<Layer *> obsoleteLayers;
Chris@53 252 std::set<QString> failedTransformers;
Chris@45 253
Chris@45 254 // We need to ensure that no layer is left using oldMainModel or
Chris@45 255 // any of the old derived models as its model. Either replace the
Chris@45 256 // model, or delete the layer for each layer that is currently
Chris@45 257 // using one of these. Carry out this replacement before we
Chris@45 258 // delete any of the models.
Chris@45 259
Chris@52 260 std::cerr << "Document::setMainModel: Have "
Chris@52 261 << m_layers.size() << " layers" << std::endl;
Chris@52 262
Chris@45 263 for (LayerSet::iterator i = m_layers.begin(); i != m_layers.end(); ++i) {
Chris@45 264
Chris@45 265 Layer *layer = *i;
Chris@45 266 Model *model = layer->getModel();
Chris@45 267
Chris@45 268 // std::cerr << "Document::setMainModel: inspecting model "
Chris@45 269 // << (model ? model->objectName().toStdString() : "(null)") << " in layer "
Chris@45 270 // << layer->objectName().toStdString() << std::endl;
Chris@45 271
Chris@45 272 if (model == oldMainModel) {
Chris@45 273 // std::cerr << "... it uses the old main model, replacing" << std::endl;
Chris@45 274 LayerFactory::getInstance()->setModel(layer, m_mainModel);
Chris@45 275 continue;
Chris@45 276 }
Chris@45 277
Chris@45 278 if (m_models.find(model) == m_models.end()) {
Chris@45 279 std::cerr << "WARNING: Document::setMainModel: Unknown model "
Chris@45 280 << model << " in layer " << layer << std::endl;
Chris@45 281 // get rid of this hideous degenerate
Chris@45 282 obsoleteLayers.push_back(layer);
Chris@45 283 continue;
Chris@45 284 }
Chris@45 285
Chris@45 286 if (m_models[model].source == oldMainModel) {
Chris@45 287
Chris@45 288 // std::cerr << "... it uses a model derived from the old main model, regenerating" << std::endl;
Chris@45 289
Chris@45 290 // This model was derived from the previous main
Chris@45 291 // model: regenerate it.
Chris@45 292
Chris@54 293 TransformId transform = m_models[model].transform;
Chris@53 294 PluginTransformer::ExecutionContext context = m_models[model].context;
Chris@45 295
Chris@45 296 Model *replacementModel =
Chris@45 297 addDerivedModel(transform,
Chris@45 298 m_mainModel,
Chris@45 299 context,
Chris@45 300 m_models[model].configurationXml);
Chris@45 301
Chris@45 302 if (!replacementModel) {
Chris@45 303 std::cerr << "WARNING: Document::setMainModel: Failed to regenerate model for transform \""
Chris@45 304 << transform.toStdString() << "\"" << " in layer " << layer << std::endl;
Chris@53 305 if (failedTransformers.find(transform) == failedTransformers.end()) {
Chris@45 306 emit modelRegenerationFailed(layer->objectName(),
Chris@45 307 transform);
Chris@53 308 failedTransformers.insert(transform);
Chris@45 309 }
Chris@45 310 obsoleteLayers.push_back(layer);
Chris@45 311 } else {
Chris@45 312 std::cerr << "Replacing model " << model << " (type "
Chris@45 313 << typeid(*model).name() << ") with model "
Chris@45 314 << replacementModel << " (type "
Chris@45 315 << typeid(*replacementModel).name() << ") in layer "
Chris@45 316 << layer << " (name " << layer->objectName().toStdString() << ")"
Chris@45 317 << std::endl;
Chris@45 318 RangeSummarisableTimeValueModel *rm =
Chris@45 319 dynamic_cast<RangeSummarisableTimeValueModel *>(replacementModel);
Chris@45 320 if (rm) {
Chris@45 321 std::cerr << "new model has " << rm->getChannelCount() << " channels " << std::endl;
Chris@45 322 } else {
Chris@45 323 std::cerr << "new model is not a RangeSummarisableTimeValueModel!" << std::endl;
Chris@45 324 }
Chris@45 325 setModel(layer, replacementModel);
Chris@45 326 }
Chris@45 327 }
Chris@45 328 }
Chris@45 329
Chris@45 330 for (size_t k = 0; k < obsoleteLayers.size(); ++k) {
Chris@45 331 deleteLayer(obsoleteLayers[k], true);
Chris@45 332 }
Chris@45 333
Chris@48 334 for (ModelMap::iterator i = m_models.begin(); i != m_models.end(); ++i) {
Chris@48 335 if (i->first->getAlignmentReference() == oldMainModel) {
Chris@48 336 alignModel(i->first);
Chris@48 337 }
Chris@48 338 }
Chris@48 339
Chris@45 340 emit mainModelChanged(m_mainModel);
Chris@45 341
Chris@45 342 // we already emitted modelAboutToBeDeleted for this
Chris@45 343 delete oldMainModel;
Chris@45 344 }
Chris@45 345
Chris@45 346 void
Chris@54 347 Document::addDerivedModel(TransformId transform,
Chris@45 348 Model *inputModel,
Chris@53 349 const PluginTransformer::ExecutionContext &context,
Chris@45 350 Model *outputModelToAdd,
Chris@45 351 QString configurationXml)
Chris@45 352 {
Chris@45 353 if (m_models.find(outputModelToAdd) != m_models.end()) {
Chris@45 354 std::cerr << "WARNING: Document::addDerivedModel: Model already added"
Chris@45 355 << std::endl;
Chris@45 356 return;
Chris@45 357 }
Chris@45 358
Chris@45 359 // std::cerr << "Document::addDerivedModel: source is " << inputModel << " \"" << inputModel->objectName().toStdString() << "\"" << std::endl;
Chris@45 360
Chris@45 361 ModelRecord rec;
Chris@45 362 rec.source = inputModel;
Chris@45 363 rec.transform = transform;
Chris@45 364 rec.context = context;
Chris@45 365 rec.configurationXml = configurationXml;
Chris@45 366 rec.refcount = 0;
Chris@45 367
Chris@45 368 outputModelToAdd->setSourceModel(inputModel);
Chris@45 369
Chris@45 370 m_models[outputModelToAdd] = rec;
Chris@45 371
Chris@45 372 emit modelAdded(outputModelToAdd);
Chris@45 373 }
Chris@45 374
Chris@45 375
Chris@45 376 void
Chris@45 377 Document::addImportedModel(Model *model)
Chris@45 378 {
Chris@45 379 if (m_models.find(model) != m_models.end()) {
Chris@45 380 std::cerr << "WARNING: Document::addImportedModel: Model already added"
Chris@45 381 << std::endl;
Chris@45 382 return;
Chris@45 383 }
Chris@45 384
Chris@45 385 ModelRecord rec;
Chris@45 386 rec.source = 0;
Chris@45 387 rec.transform = "";
Chris@45 388 rec.refcount = 0;
Chris@45 389
Chris@45 390 m_models[model] = rec;
Chris@45 391
Chris@47 392 if (m_autoAlignment) alignModel(model);
Chris@47 393
Chris@45 394 emit modelAdded(model);
Chris@45 395 }
Chris@45 396
Chris@45 397 Model *
Chris@54 398 Document::addDerivedModel(TransformId transform,
Chris@45 399 Model *inputModel,
Chris@53 400 const PluginTransformer::ExecutionContext &context,
Chris@45 401 QString configurationXml)
Chris@45 402 {
Chris@45 403 Model *model = 0;
Chris@45 404
Chris@45 405 for (ModelMap::iterator i = m_models.begin(); i != m_models.end(); ++i) {
Chris@45 406 if (i->second.transform == transform &&
Chris@45 407 i->second.source == inputModel &&
Chris@45 408 i->second.context == context &&
Chris@45 409 i->second.configurationXml == configurationXml) {
Chris@45 410 return i->first;
Chris@45 411 }
Chris@45 412 }
Chris@45 413
Chris@54 414 model = ModelTransformerFactory::getInstance()->transform
Chris@45 415 (transform, inputModel, context, configurationXml);
Chris@45 416
Chris@45 417 if (!model) {
Chris@45 418 std::cerr << "WARNING: Document::addDerivedModel: no output model for transform " << transform.toStdString() << std::endl;
Chris@45 419 } else {
Chris@45 420 addDerivedModel(transform, inputModel, context, model, configurationXml);
Chris@45 421 }
Chris@45 422
Chris@45 423 return model;
Chris@45 424 }
Chris@45 425
Chris@45 426 void
Chris@45 427 Document::releaseModel(Model *model) // Will _not_ release main model!
Chris@45 428 {
Chris@45 429 if (model == 0) {
Chris@45 430 return;
Chris@45 431 }
Chris@45 432
Chris@45 433 if (model == m_mainModel) {
Chris@45 434 return;
Chris@45 435 }
Chris@45 436
Chris@45 437 bool toDelete = false;
Chris@45 438
Chris@45 439 if (m_models.find(model) != m_models.end()) {
Chris@45 440
Chris@45 441 if (m_models[model].refcount == 0) {
Chris@45 442 std::cerr << "WARNING: Document::releaseModel: model " << model
Chris@45 443 << " reference count is zero already!" << std::endl;
Chris@45 444 } else {
Chris@45 445 if (--m_models[model].refcount == 0) {
Chris@45 446 toDelete = true;
Chris@45 447 }
Chris@45 448 }
Chris@45 449 } else {
Chris@45 450 std::cerr << "WARNING: Document::releaseModel: Unfound model "
Chris@45 451 << model << std::endl;
Chris@45 452 toDelete = true;
Chris@45 453 }
Chris@45 454
Chris@45 455 if (toDelete) {
Chris@45 456
Chris@45 457 int sourceCount = 0;
Chris@45 458
Chris@45 459 for (ModelMap::iterator i = m_models.begin(); i != m_models.end(); ++i) {
Chris@45 460 if (i->second.source == model) {
Chris@45 461 ++sourceCount;
Chris@45 462 i->second.source = 0;
Chris@45 463 }
Chris@45 464 }
Chris@45 465
Chris@45 466 if (sourceCount > 0) {
Chris@45 467 std::cerr << "Document::releaseModel: Deleting model "
Chris@45 468 << model << " even though it is source for "
Chris@45 469 << sourceCount << " other derived model(s) -- resetting "
Chris@45 470 << "their source fields appropriately" << std::endl;
Chris@45 471 }
Chris@45 472
Chris@45 473 emit modelAboutToBeDeleted(model);
Chris@45 474 model->aboutToDelete();
Chris@45 475 m_models.erase(model);
Chris@45 476 delete model;
Chris@45 477 }
Chris@45 478 }
Chris@45 479
Chris@45 480 void
Chris@45 481 Document::deleteLayer(Layer *layer, bool force)
Chris@45 482 {
Chris@45 483 if (m_layerViewMap.find(layer) != m_layerViewMap.end() &&
Chris@45 484 m_layerViewMap[layer].size() > 0) {
Chris@45 485
Chris@45 486 std::cerr << "WARNING: Document::deleteLayer: Layer "
Chris@45 487 << layer << " [" << layer->objectName().toStdString() << "]"
Chris@45 488 << " is still used in " << m_layerViewMap[layer].size()
Chris@45 489 << " views!" << std::endl;
Chris@45 490
Chris@45 491 if (force) {
Chris@45 492
Chris@45 493 std::cerr << "(force flag set -- deleting from all views)" << std::endl;
Chris@45 494
Chris@45 495 for (std::set<View *>::iterator j = m_layerViewMap[layer].begin();
Chris@45 496 j != m_layerViewMap[layer].end(); ++j) {
Chris@45 497 // don't use removeLayerFromView, as it issues a command
Chris@45 498 layer->setLayerDormant(*j, true);
Chris@45 499 (*j)->removeLayer(layer);
Chris@45 500 }
Chris@45 501
Chris@45 502 m_layerViewMap.erase(layer);
Chris@45 503
Chris@45 504 } else {
Chris@45 505 return;
Chris@45 506 }
Chris@45 507 }
Chris@45 508
Chris@45 509 if (m_layers.find(layer) == m_layers.end()) {
Chris@45 510 std::cerr << "Document::deleteLayer: Layer "
Chris@45 511 << layer << " does not exist, or has already been deleted "
Chris@45 512 << "(this may not be as serious as it sounds)" << std::endl;
Chris@45 513 return;
Chris@45 514 }
Chris@45 515
Chris@45 516 m_layers.erase(layer);
Chris@45 517
Chris@52 518 std::cerr << "Document::deleteLayer: Removing, now have "
Chris@52 519 << m_layers.size() << " layers" << std::endl;
Chris@52 520
Chris@45 521 releaseModel(layer->getModel());
Chris@45 522 emit layerRemoved(layer);
Chris@45 523 emit layerAboutToBeDeleted(layer);
Chris@45 524 delete layer;
Chris@45 525 }
Chris@45 526
Chris@45 527 void
Chris@45 528 Document::setModel(Layer *layer, Model *model)
Chris@45 529 {
Chris@45 530 if (model &&
Chris@45 531 model != m_mainModel &&
Chris@45 532 m_models.find(model) == m_models.end()) {
Chris@45 533 std::cerr << "ERROR: Document::setModel: Layer " << layer
Chris@45 534 << " (\"" << layer->objectName().toStdString()
Chris@45 535 << "\") wants to use unregistered model " << model
Chris@45 536 << ": register the layer's model before setting it!"
Chris@45 537 << std::endl;
Chris@45 538 return;
Chris@45 539 }
Chris@45 540
Chris@45 541 Model *previousModel = layer->getModel();
Chris@45 542
Chris@45 543 if (previousModel == model) {
Chris@45 544 std::cerr << "WARNING: Document::setModel: Layer " << layer << " (\""
Chris@45 545 << layer->objectName().toStdString()
Chris@45 546 << "\") is already set to model "
Chris@45 547 << model << " (\""
Chris@45 548 << (model ? model->objectName().toStdString() : "(null)")
Chris@45 549 << "\")" << std::endl;
Chris@45 550 return;
Chris@45 551 }
Chris@45 552
Chris@45 553 if (model && model != m_mainModel) {
Chris@45 554 m_models[model].refcount ++;
Chris@45 555 }
Chris@45 556
Chris@45 557 if (model && previousModel) {
Chris@45 558 PlayParameterRepository::getInstance()->copyParameters
Chris@45 559 (previousModel, model);
Chris@45 560 }
Chris@45 561
Chris@45 562 LayerFactory::getInstance()->setModel(layer, model);
Chris@45 563
Chris@45 564 if (previousModel) {
Chris@45 565 releaseModel(previousModel);
Chris@45 566 }
Chris@45 567 }
Chris@45 568
Chris@45 569 void
Chris@45 570 Document::setChannel(Layer *layer, int channel)
Chris@45 571 {
Chris@45 572 LayerFactory::getInstance()->setChannel(layer, channel);
Chris@45 573 }
Chris@45 574
Chris@45 575 void
Chris@45 576 Document::addLayerToView(View *view, Layer *layer)
Chris@45 577 {
Chris@45 578 Model *model = layer->getModel();
Chris@45 579 if (!model) {
Chris@45 580 // std::cerr << "Document::addLayerToView: Layer (\""
Chris@45 581 // << layer->objectName().toStdString()
Chris@45 582 // << "\") with no model being added to view: "
Chris@45 583 // << "normally you want to set the model first" << std::endl;
Chris@45 584 } else {
Chris@45 585 if (model != m_mainModel &&
Chris@45 586 m_models.find(model) == m_models.end()) {
Chris@45 587 std::cerr << "ERROR: Document::addLayerToView: Layer " << layer
Chris@45 588 << " has unregistered model " << model
Chris@45 589 << " -- register the layer's model before adding the layer!" << std::endl;
Chris@45 590 return;
Chris@45 591 }
Chris@45 592 }
Chris@45 593
Chris@45 594 CommandHistory::getInstance()->addCommand
Chris@45 595 (new Document::AddLayerCommand(this, view, layer));
Chris@45 596 }
Chris@45 597
Chris@45 598 void
Chris@45 599 Document::removeLayerFromView(View *view, Layer *layer)
Chris@45 600 {
Chris@45 601 CommandHistory::getInstance()->addCommand
Chris@45 602 (new Document::RemoveLayerCommand(this, view, layer));
Chris@45 603 }
Chris@45 604
Chris@45 605 void
Chris@45 606 Document::addToLayerViewMap(Layer *layer, View *view)
Chris@45 607 {
Chris@45 608 bool firstView = (m_layerViewMap.find(layer) == m_layerViewMap.end() ||
Chris@45 609 m_layerViewMap[layer].empty());
Chris@45 610
Chris@45 611 if (m_layerViewMap[layer].find(view) !=
Chris@45 612 m_layerViewMap[layer].end()) {
Chris@45 613 std::cerr << "WARNING: Document::addToLayerViewMap:"
Chris@45 614 << " Layer " << layer << " -> view " << view << " already in"
Chris@45 615 << " layer view map -- internal inconsistency" << std::endl;
Chris@45 616 }
Chris@45 617
Chris@45 618 m_layerViewMap[layer].insert(view);
Chris@45 619
Chris@45 620 if (firstView) emit layerInAView(layer, true);
Chris@45 621 }
Chris@45 622
Chris@45 623 void
Chris@45 624 Document::removeFromLayerViewMap(Layer *layer, View *view)
Chris@45 625 {
Chris@45 626 if (m_layerViewMap[layer].find(view) ==
Chris@45 627 m_layerViewMap[layer].end()) {
Chris@45 628 std::cerr << "WARNING: Document::removeFromLayerViewMap:"
Chris@45 629 << " Layer " << layer << " -> view " << view << " not in"
Chris@45 630 << " layer view map -- internal inconsistency" << std::endl;
Chris@45 631 }
Chris@45 632
Chris@45 633 m_layerViewMap[layer].erase(view);
Chris@45 634
Chris@45 635 if (m_layerViewMap[layer].empty()) {
Chris@45 636 m_layerViewMap.erase(layer);
Chris@45 637 emit layerInAView(layer, false);
Chris@45 638 }
Chris@45 639 }
Chris@45 640
Chris@45 641 QString
Chris@45 642 Document::getUniqueLayerName(QString candidate)
Chris@45 643 {
Chris@45 644 for (int count = 1; ; ++count) {
Chris@45 645
Chris@45 646 QString adjusted =
Chris@45 647 (count > 1 ? QString("%1 <%2>").arg(candidate).arg(count) :
Chris@45 648 candidate);
Chris@45 649
Chris@45 650 bool duplicate = false;
Chris@45 651
Chris@45 652 for (LayerSet::iterator i = m_layers.begin(); i != m_layers.end(); ++i) {
Chris@45 653 if ((*i)->objectName() == adjusted) {
Chris@45 654 duplicate = true;
Chris@45 655 break;
Chris@45 656 }
Chris@45 657 }
Chris@45 658
Chris@45 659 if (!duplicate) return adjusted;
Chris@45 660 }
Chris@45 661 }
Chris@45 662
Chris@45 663 std::vector<Model *>
Chris@53 664 Document::getTransformerInputModels()
Chris@45 665 {
Chris@45 666 std::vector<Model *> models;
Chris@45 667
Chris@45 668 if (!m_mainModel) return models;
Chris@45 669
Chris@45 670 models.push_back(m_mainModel);
Chris@45 671
Chris@45 672 //!!! This will pick up all models, including those that aren't visible...
Chris@45 673
Chris@45 674 for (ModelMap::iterator i = m_models.begin(); i != m_models.end(); ++i) {
Chris@45 675
Chris@45 676 Model *model = i->first;
Chris@45 677 if (!model || model == m_mainModel) continue;
Chris@45 678 DenseTimeValueModel *dtvm = dynamic_cast<DenseTimeValueModel *>(model);
Chris@45 679
Chris@45 680 if (dtvm) {
Chris@45 681 models.push_back(dtvm);
Chris@45 682 }
Chris@45 683 }
Chris@45 684
Chris@45 685 return models;
Chris@45 686 }
Chris@45 687
Chris@50 688 bool
Chris@51 689 Document::canAlign()
Chris@50 690 {
Chris@54 691 TransformId id = "vamp:match-vamp-plugin:match:path";
Chris@54 692 TransformFactory *factory = TransformFactory::getInstance();
Chris@54 693 return factory->haveTransform(id);
Chris@50 694 }
Chris@50 695
Chris@45 696 void
Chris@45 697 Document::alignModel(Model *model)
Chris@45 698 {
Chris@45 699 if (!m_mainModel || model == m_mainModel) return;
Chris@45 700
Chris@45 701 RangeSummarisableTimeValueModel *rm =
Chris@45 702 dynamic_cast<RangeSummarisableTimeValueModel *>(model);
Chris@45 703 if (!rm) return;
Chris@48 704
Chris@48 705 if (rm->getAlignmentReference() == m_mainModel) return;
Chris@45 706
Chris@45 707 // This involves creating three new models:
Chris@45 708
Chris@45 709 // 1. an AggregateWaveModel to provide the mixdowns of the main
Chris@45 710 // model and the new model in its two channels, as input to the
Chris@45 711 // MATCH plugin
Chris@45 712
Chris@45 713 // 2. a SparseTimeValueModel, which is the model automatically
Chris@53 714 // created by FeatureExtractionPluginTransformer when running the
Chris@45 715 // MATCH plugin (thus containing the alignment path)
Chris@45 716
Chris@45 717 // 3. an AlignmentModel, which stores the path model and carries
Chris@45 718 // out alignment lookups on it.
Chris@45 719
Chris@45 720 // The first two of these are provided as arguments to the
Chris@45 721 // constructor for the third, which takes responsibility for
Chris@45 722 // deleting them. The AlignmentModel, meanwhile, is passed to the
Chris@45 723 // new model we are aligning, which also takes responsibility for
Chris@45 724 // it. We should not have to delete any of these new models here.
Chris@45 725
Chris@45 726 AggregateWaveModel::ChannelSpecList components;
Chris@45 727
Chris@45 728 components.push_back(AggregateWaveModel::ModelChannelSpec
Chris@45 729 (m_mainModel, -1));
Chris@45 730
Chris@45 731 components.push_back(AggregateWaveModel::ModelChannelSpec
Chris@45 732 (rm, -1));
Chris@45 733
Chris@45 734 Model *aggregate = new AggregateWaveModel(components);
Chris@45 735
Chris@54 736 TransformId id = "vamp:match-vamp-plugin:match:path";
Chris@45 737
Chris@54 738 ModelTransformerFactory *factory = ModelTransformerFactory::getInstance();
Chris@45 739
Chris@57 740 PluginTransformer::ExecutionContext context =
Chris@57 741 factory->getDefaultContextForTransformer(id, aggregate);
Chris@58 742 context.stepSize = context.blockSize/2;
Chris@57 743
Chris@45 744 Model *transformOutput = factory->transform
Chris@57 745 (id, aggregate, context, "<plugin param-serialise=\"1\"/>");
Chris@45 746
Chris@45 747 SparseTimeValueModel *path = dynamic_cast<SparseTimeValueModel *>
Chris@45 748 (transformOutput);
Chris@45 749
Chris@45 750 if (!path) {
Chris@45 751 std::cerr << "Document::alignModel: ERROR: Failed to create alignment path (no MATCH plugin?)" << std::endl;
Chris@45 752 delete transformOutput;
Chris@45 753 delete aggregate;
Chris@45 754 return;
Chris@45 755 }
Chris@45 756
Chris@45 757 AlignmentModel *alignmentModel = new AlignmentModel
Chris@45 758 (m_mainModel, model, aggregate, path);
Chris@45 759
Chris@45 760 rm->setAlignment(alignmentModel);
Chris@45 761 }
Chris@45 762
Chris@45 763 void
Chris@45 764 Document::alignModels()
Chris@45 765 {
Chris@45 766 for (ModelMap::iterator i = m_models.begin(); i != m_models.end(); ++i) {
Chris@45 767 alignModel(i->first);
Chris@45 768 }
Chris@45 769 }
Chris@45 770
Chris@45 771 Document::AddLayerCommand::AddLayerCommand(Document *d,
Chris@45 772 View *view,
Chris@45 773 Layer *layer) :
Chris@45 774 m_d(d),
Chris@45 775 m_view(view),
Chris@45 776 m_layer(layer),
Chris@45 777 m_name(qApp->translate("AddLayerCommand", "Add %1 Layer").arg(layer->objectName())),
Chris@45 778 m_added(false)
Chris@45 779 {
Chris@45 780 }
Chris@45 781
Chris@45 782 Document::AddLayerCommand::~AddLayerCommand()
Chris@45 783 {
Chris@45 784 // std::cerr << "Document::AddLayerCommand::~AddLayerCommand" << std::endl;
Chris@45 785 if (!m_added) {
Chris@45 786 m_d->deleteLayer(m_layer);
Chris@45 787 }
Chris@45 788 }
Chris@45 789
Chris@45 790 void
Chris@45 791 Document::AddLayerCommand::execute()
Chris@45 792 {
Chris@45 793 for (int i = 0; i < m_view->getLayerCount(); ++i) {
Chris@45 794 if (m_view->getLayer(i) == m_layer) {
Chris@45 795 // already there
Chris@45 796 m_layer->setLayerDormant(m_view, false);
Chris@45 797 m_added = true;
Chris@45 798 return;
Chris@45 799 }
Chris@45 800 }
Chris@45 801
Chris@45 802 m_view->addLayer(m_layer);
Chris@45 803 m_layer->setLayerDormant(m_view, false);
Chris@45 804
Chris@45 805 m_d->addToLayerViewMap(m_layer, m_view);
Chris@45 806 m_added = true;
Chris@45 807 }
Chris@45 808
Chris@45 809 void
Chris@45 810 Document::AddLayerCommand::unexecute()
Chris@45 811 {
Chris@45 812 m_view->removeLayer(m_layer);
Chris@45 813 m_layer->setLayerDormant(m_view, true);
Chris@45 814
Chris@45 815 m_d->removeFromLayerViewMap(m_layer, m_view);
Chris@45 816 m_added = false;
Chris@45 817 }
Chris@45 818
Chris@45 819 Document::RemoveLayerCommand::RemoveLayerCommand(Document *d,
Chris@45 820 View *view,
Chris@45 821 Layer *layer) :
Chris@45 822 m_d(d),
Chris@45 823 m_view(view),
Chris@45 824 m_layer(layer),
Chris@45 825 m_name(qApp->translate("RemoveLayerCommand", "Delete %1 Layer").arg(layer->objectName())),
Chris@45 826 m_added(true)
Chris@45 827 {
Chris@45 828 }
Chris@45 829
Chris@45 830 Document::RemoveLayerCommand::~RemoveLayerCommand()
Chris@45 831 {
Chris@45 832 // std::cerr << "Document::RemoveLayerCommand::~RemoveLayerCommand" << std::endl;
Chris@45 833 if (!m_added) {
Chris@45 834 m_d->deleteLayer(m_layer);
Chris@45 835 }
Chris@45 836 }
Chris@45 837
Chris@45 838 void
Chris@45 839 Document::RemoveLayerCommand::execute()
Chris@45 840 {
Chris@45 841 bool have = false;
Chris@45 842 for (int i = 0; i < m_view->getLayerCount(); ++i) {
Chris@45 843 if (m_view->getLayer(i) == m_layer) {
Chris@45 844 have = true;
Chris@45 845 break;
Chris@45 846 }
Chris@45 847 }
Chris@45 848
Chris@45 849 if (!have) { // not there!
Chris@45 850 m_layer->setLayerDormant(m_view, true);
Chris@45 851 m_added = false;
Chris@45 852 return;
Chris@45 853 }
Chris@45 854
Chris@45 855 m_view->removeLayer(m_layer);
Chris@45 856 m_layer->setLayerDormant(m_view, true);
Chris@45 857
Chris@45 858 m_d->removeFromLayerViewMap(m_layer, m_view);
Chris@45 859 m_added = false;
Chris@45 860 }
Chris@45 861
Chris@45 862 void
Chris@45 863 Document::RemoveLayerCommand::unexecute()
Chris@45 864 {
Chris@45 865 m_view->addLayer(m_layer);
Chris@45 866 m_layer->setLayerDormant(m_view, false);
Chris@45 867
Chris@45 868 m_d->addToLayerViewMap(m_layer, m_view);
Chris@45 869 m_added = true;
Chris@45 870 }
Chris@45 871
Chris@45 872 void
Chris@45 873 Document::toXml(QTextStream &out, QString indent, QString extraAttributes) const
Chris@45 874 {
Chris@45 875 out << indent + QString("<data%1%2>\n")
Chris@45 876 .arg(extraAttributes == "" ? "" : " ").arg(extraAttributes);
Chris@45 877
Chris@45 878 if (m_mainModel) {
Chris@45 879 m_mainModel->toXml(out, indent + " ", "mainModel=\"true\"");
Chris@45 880 }
Chris@45 881
Chris@45 882 // Models that are not used in a layer that is in a view should
Chris@45 883 // not be written. Get our list of required models first.
Chris@45 884
Chris@45 885 std::set<const Model *> used;
Chris@45 886
Chris@45 887 for (LayerViewMap::const_iterator i = m_layerViewMap.begin();
Chris@45 888 i != m_layerViewMap.end(); ++i) {
Chris@45 889
Chris@45 890 if (i->first && !i->second.empty() && i->first->getModel()) {
Chris@45 891 used.insert(i->first->getModel());
Chris@45 892 }
Chris@45 893 }
Chris@45 894
Chris@45 895 for (ModelMap::const_iterator i = m_models.begin();
Chris@45 896 i != m_models.end(); ++i) {
Chris@45 897
Chris@45 898 const Model *model = i->first;
Chris@45 899 const ModelRecord &rec = i->second;
Chris@45 900
Chris@45 901 if (used.find(model) == used.end()) continue;
Chris@45 902
Chris@45 903 // We need an intelligent way to determine which models need
Chris@45 904 // to be streamed (i.e. have been edited, or are small) and
Chris@45 905 // which should not be (i.e. remain as generated by a
Chris@45 906 // transform, and are large).
Chris@45 907 //
Chris@45 908 // At the moment we can get away with deciding not to stream
Chris@45 909 // dense 3d models or writable wave file models, provided they
Chris@45 910 // were generated from a transform, because at the moment there
Chris@45 911 // is no way to edit those model types so it should be safe to
Chris@45 912 // regenerate them. That won't always work in future though.
Chris@45 913 // It would be particularly nice to be able to ask the user,
Chris@45 914 // as well as making an intelligent guess.
Chris@45 915
Chris@45 916 bool writeModel = true;
Chris@45 917 bool haveDerivation = false;
Chris@45 918
Chris@45 919 if (rec.source && rec.transform != "") {
Chris@45 920 haveDerivation = true;
Chris@45 921 }
Chris@45 922
Chris@45 923 if (haveDerivation) {
Chris@45 924 if (dynamic_cast<const WritableWaveFileModel *>(model)) {
Chris@45 925 writeModel = false;
Chris@45 926 } else if (dynamic_cast<const DenseThreeDimensionalModel *>(model)) {
Chris@45 927 writeModel = false;
Chris@45 928 }
Chris@45 929 }
Chris@45 930
Chris@45 931 if (writeModel) {
Chris@45 932 i->first->toXml(out, indent + " ");
Chris@45 933 }
Chris@45 934
Chris@45 935 if (haveDerivation) {
Chris@45 936
Chris@45 937 QString extentsAttributes;
Chris@45 938 if (rec.context.startFrame != 0 ||
Chris@45 939 rec.context.duration != 0) {
Chris@45 940 extentsAttributes = QString("startFrame=\"%1\" duration=\"%2\" ")
Chris@45 941 .arg(rec.context.startFrame)
Chris@45 942 .arg(rec.context.duration);
Chris@45 943 }
Chris@45 944
Chris@45 945 out << indent;
Chris@45 946 out << QString(" <derivation source=\"%1\" model=\"%2\" channel=\"%3\" domain=\"%4\" stepSize=\"%5\" blockSize=\"%6\" %7windowType=\"%8\" transform=\"%9\"")
Chris@45 947 .arg(XmlExportable::getObjectExportId(rec.source))
Chris@45 948 .arg(XmlExportable::getObjectExportId(i->first))
Chris@45 949 .arg(rec.context.channel)
Chris@45 950 .arg(rec.context.domain)
Chris@45 951 .arg(rec.context.stepSize)
Chris@45 952 .arg(rec.context.blockSize)
Chris@45 953 .arg(extentsAttributes)
Chris@45 954 .arg(int(rec.context.windowType))
Chris@45 955 .arg(XmlExportable::encodeEntities(rec.transform));
Chris@45 956
Chris@45 957 if (rec.configurationXml != "") {
Chris@45 958 out << ">\n " + indent + rec.configurationXml
Chris@45 959 + "\n" + indent + " </derivation>\n";
Chris@45 960 } else {
Chris@45 961 out << "/>\n";
Chris@45 962 }
Chris@45 963 }
Chris@45 964
Chris@45 965 //!!! We should probably own the PlayParameterRepository
Chris@45 966 PlayParameters *playParameters =
Chris@45 967 PlayParameterRepository::getInstance()->getPlayParameters(i->first);
Chris@45 968 if (playParameters) {
Chris@45 969 playParameters->toXml
Chris@45 970 (out, indent + " ",
Chris@45 971 QString("model=\"%1\"")
Chris@45 972 .arg(XmlExportable::getObjectExportId(i->first)));
Chris@45 973 }
Chris@45 974 }
Chris@45 975
Chris@45 976 for (LayerSet::const_iterator i = m_layers.begin();
Chris@45 977 i != m_layers.end(); ++i) {
Chris@45 978
Chris@45 979 (*i)->toXml(out, indent + " ");
Chris@45 980 }
Chris@45 981
Chris@45 982 out << indent + "</data>\n";
Chris@45 983 }
Chris@45 984
Chris@45 985