annotate document/Document.cpp @ 201:de783e8ee5f0

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