Mercurial > hg > svapp
comparison framework/Document.cpp @ 100:22bf057ea151 1.2-stable
* merge from trunk (1.2 ended up being tracked from trunk, but we may want
  this branch for fixes later)
| author | Chris Cannam | 
|---|---|
| date | Wed, 27 Feb 2008 10:32:45 +0000 | 
| parents | a8acc7841d70 | 
| children | 
   comparison
  equal
  deleted
  inserted
  replaced
| 71:a8acc7841d70 | 100:22bf057ea151 | 
|---|---|
| 27 #include "base/PlayParameters.h" | 27 #include "base/PlayParameters.h" | 
| 28 #include "plugin/transform/TransformFactory.h" | 28 #include "plugin/transform/TransformFactory.h" | 
| 29 #include "plugin/transform/ModelTransformerFactory.h" | 29 #include "plugin/transform/ModelTransformerFactory.h" | 
| 30 #include <QApplication> | 30 #include <QApplication> | 
| 31 #include <QTextStream> | 31 #include <QTextStream> | 
| 32 #include <QSettings> | |
| 32 #include <iostream> | 33 #include <iostream> | 
| 33 | 34 | 
| 34 // For alignment: | 35 // For alignment: | 
| 35 #include "data/model/AggregateWaveModel.h" | 36 #include "data/model/AggregateWaveModel.h" | 
| 36 #include "data/model/SparseTimeValueModel.h" | 37 #include "data/model/SparseTimeValueModel.h" | 
| 37 #include "data/model/AlignmentModel.h" | 38 #include "data/model/AlignmentModel.h" | 
| 38 | 39 | 
| 40 //#define DEBUG_DOCUMENT 1 | |
| 41 | |
| 39 //!!! still need to handle command history, documentRestored/documentModified | 42 //!!! still need to handle command history, documentRestored/documentModified | 
| 40 | 43 | 
| 41 Document::Document() : | 44 Document::Document() : | 
| 42 m_mainModel(0), | 45 m_mainModel(0), | 
| 43 m_autoAlignment(false) | 46 m_autoAlignment(false) | 
| 51 { | 54 { | 
| 52 //!!! Document should really own the command history. atm we | 55 //!!! Document should really own the command history. atm we | 
| 53 //still refer to it in various places that don't have access to | 56 //still refer to it in various places that don't have access to | 
| 54 //the document, be nice to fix that | 57 //the document, be nice to fix that | 
| 55 | 58 | 
| 56 // std::cerr << "\n\nDocument::~Document: about to clear command history" << std::endl; | 59 #ifdef DEBUG_DOCUMENT | 
| 60 std::cerr << "\n\nDocument::~Document: about to clear command history" << std::endl; | |
| 61 #endif | |
| 57 CommandHistory::getInstance()->clear(); | 62 CommandHistory::getInstance()->clear(); | 
| 58 | 63 | 
| 64 #ifdef DEBUG_DOCUMENT | |
| 59 std::cerr << "Document::~Document: about to delete layers" << std::endl; | 65 std::cerr << "Document::~Document: about to delete layers" << std::endl; | 
| 66 #endif | |
| 60 while (!m_layers.empty()) { | 67 while (!m_layers.empty()) { | 
| 61 deleteLayer(*m_layers.begin(), true); | 68 deleteLayer(*m_layers.begin(), true); | 
| 62 } | 69 } | 
| 63 | 70 | 
| 64 if (!m_models.empty()) { | 71 if (!m_models.empty()) { | 
| 71 if (model == m_mainModel) { | 78 if (model == m_mainModel) { | 
| 72 // just in case! | 79 // just in case! | 
| 73 std::cerr << "Document::~Document: WARNING: Main model is also" | 80 std::cerr << "Document::~Document: WARNING: Main model is also" | 
| 74 << " in models list!" << std::endl; | 81 << " in models list!" << std::endl; | 
| 75 } else if (model) { | 82 } else if (model) { | 
| 83 model->aboutToDelete(); | |
| 76 emit modelAboutToBeDeleted(model); | 84 emit modelAboutToBeDeleted(model); | 
| 77 model->aboutToDelete(); | |
| 78 delete model; | 85 delete model; | 
| 79 } | 86 } | 
| 80 m_models.erase(m_models.begin()); | 87 m_models.erase(m_models.begin()); | 
| 81 } | 88 } | 
| 82 } | 89 } | 
| 83 | 90 | 
| 84 // std::cerr << "Document::~Document: About to get rid of main model" | 91 #ifdef DEBUG_DOCUMENT | 
| 85 // << std::endl; | 92 std::cerr << "Document::~Document: About to get rid of main model" | 
| 93 << std::endl; | |
| 94 #endif | |
| 86 if (m_mainModel) { | 95 if (m_mainModel) { | 
| 96 m_mainModel->aboutToDelete(); | |
| 87 emit modelAboutToBeDeleted(m_mainModel); | 97 emit modelAboutToBeDeleted(m_mainModel); | 
| 88 m_mainModel->aboutToDelete(); | |
| 89 } | 98 } | 
| 90 | 99 | 
| 91 emit mainModelChanged(0); | 100 emit mainModelChanged(0); | 
| 92 delete m_mainModel; | 101 delete m_mainModel; | 
| 93 | 102 | 
| 101 | 110 | 
| 102 newLayer->setObjectName(getUniqueLayerName(newLayer->objectName())); | 111 newLayer->setObjectName(getUniqueLayerName(newLayer->objectName())); | 
| 103 | 112 | 
| 104 m_layers.insert(newLayer); | 113 m_layers.insert(newLayer); | 
| 105 | 114 | 
| 106 // std::cerr << "Document::createLayer: Added layer of type " << type | 115 #ifdef DEBUG_DOCUMENT | 
| 107 // << ", now have " << m_layers.size() << " layers" << std::endl; | 116 std::cerr << "Document::createLayer: Added layer of type " << type | 
| 117 << ", now have " << m_layers.size() << " layers" << std::endl; | |
| 118 #endif | |
| 108 | 119 | 
| 109 emit layerAdded(newLayer); | 120 emit layerAdded(newLayer); | 
| 110 | 121 | 
| 111 return newLayer; | 122 return newLayer; | 
| 112 } | 123 } | 
| 145 //!!! and all channels | 156 //!!! and all channels | 
| 146 setChannel(newLayer, -1); | 157 setChannel(newLayer, -1); | 
| 147 | 158 | 
| 148 m_layers.insert(newLayer); | 159 m_layers.insert(newLayer); | 
| 149 | 160 | 
| 161 #ifdef DEBUG_DOCUMENT | |
| 150 std::cerr << "Document::createImportedLayer: Added layer of type " << type | 162 std::cerr << "Document::createImportedLayer: Added layer of type " << type | 
| 151 << ", now have " << m_layers.size() << " layers" << std::endl; | 163 << ", now have " << m_layers.size() << " layers" << std::endl; | 
| 164 #endif | |
| 152 | 165 | 
| 153 emit layerAdded(newLayer); | 166 emit layerAdded(newLayer); | 
| 154 return newLayer; | 167 return newLayer; | 
| 155 } | 168 } | 
| 156 | 169 | 
| 188 | 201 | 
| 189 return newLayer; | 202 return newLayer; | 
| 190 } | 203 } | 
| 191 | 204 | 
| 192 Layer * | 205 Layer * | 
| 193 Document::createDerivedLayer(TransformId transform, | 206 Document::createDerivedLayer(const Transform &transform, | 
| 194 Model *inputModel, | 207 const ModelTransformer::Input &input) | 
| 195 const PluginTransformer::ExecutionContext &context, | 208 { | 
| 196 QString configurationXml) | 209 QString message; | 
| 197 { | 210 Model *newModel = addDerivedModel(transform, input, message); | 
| 198 Model *newModel = addDerivedModel(transform, inputModel, | |
| 199 context, configurationXml); | |
| 200 if (!newModel) { | 211 if (!newModel) { | 
| 201 // error already printed to stderr by addDerivedModel | 212 emit modelGenerationFailed(transform.getIdentifier(), message); | 
| 202 emit modelGenerationFailed(transform); | |
| 203 return 0; | 213 return 0; | 
| 214 } else if (message != "") { | |
| 215 emit modelGenerationWarning(transform.getIdentifier(), message); | |
| 204 } | 216 } | 
| 205 | 217 | 
| 206 LayerFactory::LayerTypeSet types = | 218 LayerFactory::LayerTypeSet types = | 
| 207 LayerFactory::getInstance()->getValidLayerTypes(newModel); | 219 LayerFactory::getInstance()->getValidLayerTypes(newModel); | 
| 208 | 220 | 
| 209 if (types.empty()) { | 221 if (types.empty()) { | 
| 210 std::cerr << "WARNING: Document::createLayerForTransformer: no valid display layer for output of transform " << transform.toStdString() << std::endl; | 222 std::cerr << "WARNING: Document::createLayerForTransformer: no valid display layer for output of transform " << transform.getIdentifier().toStdString() << std::endl; | 
| 211 delete newModel; | 223 delete newModel; | 
| 212 return 0; | 224 return 0; | 
| 213 } | 225 } | 
| 214 | 226 | 
| 215 //!!! for now, just use the first suitable layer type | 227 //!!! for now, just use the first suitable layer type | 
| 233 // model pointer in both layers, so they can't actually be cloned. | 245 // model pointer in both layers, so they can't actually be cloned. | 
| 234 | 246 | 
| 235 if (newLayer) { | 247 if (newLayer) { | 
| 236 newLayer->setObjectName(getUniqueLayerName | 248 newLayer->setObjectName(getUniqueLayerName | 
| 237 (TransformFactory::getInstance()-> | 249 (TransformFactory::getInstance()-> | 
| 238 getTransformFriendlyName(transform))); | 250 getTransformFriendlyName | 
| 251 (transform.getIdentifier()))); | |
| 239 } | 252 } | 
| 240 | 253 | 
| 241 emit layerAdded(newLayer); | 254 emit layerAdded(newLayer); | 
| 242 return newLayer; | 255 return newLayer; | 
| 243 } | 256 } | 
| 257 // any of the old derived models as its model. Either replace the | 270 // any of the old derived models as its model. Either replace the | 
| 258 // model, or delete the layer for each layer that is currently | 271 // model, or delete the layer for each layer that is currently | 
| 259 // using one of these. Carry out this replacement before we | 272 // using one of these. Carry out this replacement before we | 
| 260 // delete any of the models. | 273 // delete any of the models. | 
| 261 | 274 | 
| 262 // std::cerr << "Document::setMainModel: Have " | 275 #ifdef DEBUG_DOCUMENT | 
| 263 // << m_layers.size() << " layers" << std::endl; | 276 std::cerr << "Document::setMainModel: Have " | 
| 277 << m_layers.size() << " layers" << std::endl; | |
| 278 #endif | |
| 264 | 279 | 
| 265 for (LayerSet::iterator i = m_layers.begin(); i != m_layers.end(); ++i) { | 280 for (LayerSet::iterator i = m_layers.begin(); i != m_layers.end(); ++i) { | 
| 266 | 281 | 
| 267 Layer *layer = *i; | 282 Layer *layer = *i; | 
| 268 Model *model = layer->getModel(); | 283 Model *model = layer->getModel(); | 
| 269 | 284 | 
| 270 // std::cerr << "Document::setMainModel: inspecting model " | 285 #ifdef DEBUG_DOCUMENT | 
| 271 // << (model ? model->objectName().toStdString() : "(null)") << " in layer " | 286 std::cerr << "Document::setMainModel: inspecting model " | 
| 272 // << layer->objectName().toStdString() << std::endl; | 287 << (model ? model->objectName().toStdString() : "(null)") << " in layer " | 
| 288 << layer->objectName().toStdString() << std::endl; | |
| 289 #endif | |
| 273 | 290 | 
| 274 if (model == oldMainModel) { | 291 if (model == oldMainModel) { | 
| 275 // std::cerr << "... it uses the old main model, replacing" << std::endl; | 292 #ifdef DEBUG_DOCUMENT | 
| 293 std::cerr << "... it uses the old main model, replacing" << std::endl; | |
| 294 #endif | |
| 276 LayerFactory::getInstance()->setModel(layer, m_mainModel); | 295 LayerFactory::getInstance()->setModel(layer, m_mainModel); | 
| 277 continue; | 296 continue; | 
| 278 } | 297 } | 
| 279 | 298 | 
| 280 if (model && (m_models.find(model) == m_models.end())) { | 299 if (model && (m_models.find(model) == m_models.end())) { | 
| 286 } | 305 } | 
| 287 | 306 | 
| 288 if (m_models[model].source && | 307 if (m_models[model].source && | 
| 289 (m_models[model].source == oldMainModel)) { | 308 (m_models[model].source == oldMainModel)) { | 
| 290 | 309 | 
| 291 // std::cerr << "... it uses a model derived from the old main model, regenerating" << std::endl; | 310 #ifdef DEBUG_DOCUMENT | 
| 311 std::cerr << "... it uses a model derived from the old main model, regenerating" << std::endl; | |
| 312 #endif | |
| 292 | 313 | 
| 293 // This model was derived from the previous main | 314 // This model was derived from the previous main | 
| 294 // model: regenerate it. | 315 // model: regenerate it. | 
| 295 | 316 | 
| 296 TransformId transform = m_models[model].transform; | 317 const Transform &transform = m_models[model].transform; | 
| 297 PluginTransformer::ExecutionContext context = m_models[model].context; | 318 QString transformId = transform.getIdentifier(); | 
| 298 | 319 | 
| 320 //!!! We have a problem here if the number of channels in | |
| 321 //the main model has changed. | |
| 322 | |
| 323 QString message; | |
| 299 Model *replacementModel = | 324 Model *replacementModel = | 
| 300 addDerivedModel(transform, | 325 addDerivedModel(transform, | 
| 301 m_mainModel, | 326 ModelTransformer::Input | 
| 302 context, | 327 (m_mainModel, m_models[model].channel), | 
| 303 m_models[model].configurationXml); | 328 message); | 
| 304 | 329 | 
| 305 if (!replacementModel) { | 330 if (!replacementModel) { | 
| 306 std::cerr << "WARNING: Document::setMainModel: Failed to regenerate model for transform \"" | 331 std::cerr << "WARNING: Document::setMainModel: Failed to regenerate model for transform \"" | 
| 307 << transform.toStdString() << "\"" << " in layer " << layer << std::endl; | 332 << transformId.toStdString() << "\"" << " in layer " << layer << std::endl; | 
| 308 if (failedTransformers.find(transform) == failedTransformers.end()) { | 333 if (failedTransformers.find(transformId) | 
| 334 == failedTransformers.end()) { | |
| 309 emit modelRegenerationFailed(layer->objectName(), | 335 emit modelRegenerationFailed(layer->objectName(), | 
| 310 transform); | 336 transformId, | 
| 311 failedTransformers.insert(transform); | 337 message); | 
| 338 failedTransformers.insert(transformId); | |
| 312 } | 339 } | 
| 313 obsoleteLayers.push_back(layer); | 340 obsoleteLayers.push_back(layer); | 
| 314 } else { | 341 } else { | 
| 315 // std::cerr << "Replacing model " << model << " (type " | 342 if (message != "") { | 
| 316 // << typeid(*model).name() << ") with model " | 343 emit modelRegenerationWarning(layer->objectName(), | 
| 317 // << replacementModel << " (type " | 344 transformId, | 
| 318 // << typeid(*replacementModel).name() << ") in layer " | 345 message); | 
| 319 // << layer << " (name " << layer->objectName().toStdString() << ")" | 346 } | 
| 320 // << std::endl; | 347 #ifdef DEBUG_DOCUMENT | 
| 348 std::cerr << "Replacing model " << model << " (type " | |
| 349 << typeid(*model).name() << ") with model " | |
| 350 << replacementModel << " (type " | |
| 351 << typeid(*replacementModel).name() << ") in layer " | |
| 352 << layer << " (name " << layer->objectName().toStdString() << ")" | |
| 353 << std::endl; | |
| 354 #endif | |
| 321 RangeSummarisableTimeValueModel *rm = | 355 RangeSummarisableTimeValueModel *rm = | 
| 322 dynamic_cast<RangeSummarisableTimeValueModel *>(replacementModel); | 356 dynamic_cast<RangeSummarisableTimeValueModel *>(replacementModel); | 
| 357 #ifdef DEBUG_DOCUMENT | |
| 323 if (rm) { | 358 if (rm) { | 
| 324 std::cerr << "new model has " << rm->getChannelCount() << " channels " << std::endl; | 359 std::cerr << "new model has " << rm->getChannelCount() << " channels " << std::endl; | 
| 325 } else { | 360 } else { | 
| 326 std::cerr << "new model is not a RangeSummarisableTimeValueModel!" << std::endl; | 361 std::cerr << "new model is not a RangeSummarisableTimeValueModel!" << std::endl; | 
| 327 } | 362 } | 
| 363 #endif | |
| 328 setModel(layer, replacementModel); | 364 setModel(layer, replacementModel); | 
| 329 } | 365 } | 
| 330 } | 366 } | 
| 331 } | 367 } | 
| 332 | 368 | 
| 333 for (size_t k = 0; k < obsoleteLayers.size(); ++k) { | 369 for (size_t k = 0; k < obsoleteLayers.size(); ++k) { | 
| 334 deleteLayer(obsoleteLayers[k], true); | 370 deleteLayer(obsoleteLayers[k], true); | 
| 335 } | 371 } | 
| 336 | 372 | 
| 337 for (ModelMap::iterator i = m_models.begin(); i != m_models.end(); ++i) { | 373 for (ModelMap::iterator i = m_models.begin(); i != m_models.end(); ++i) { | 
| 338 if (oldMainModel && | 374 | 
| 339 (i->first->getAlignmentReference() == oldMainModel)) { | 375 if (m_autoAlignment) { | 
| 376 | |
| 377 alignModel(i->first); | |
| 378 | |
| 379 } else if (oldMainModel && | |
| 380 (i->first->getAlignmentReference() == oldMainModel)) { | |
| 381 | |
| 340 alignModel(i->first); | 382 alignModel(i->first); | 
| 341 } | 383 } | 
| 342 } | 384 } | 
| 343 | 385 | 
| 386 if (oldMainModel) { | |
| 387 oldMainModel->aboutToDelete(); | |
| 388 emit modelAboutToBeDeleted(oldMainModel); | |
| 389 } | |
| 390 | |
| 391 if (m_autoAlignment) { | |
| 392 alignModel(m_mainModel); | |
| 393 } | |
| 394 | |
| 344 emit mainModelChanged(m_mainModel); | 395 emit mainModelChanged(m_mainModel); | 
| 345 | 396 | 
| 346 // we already emitted modelAboutToBeDeleted for this | |
| 347 delete oldMainModel; | 397 delete oldMainModel; | 
| 348 } | 398 } | 
| 349 | 399 | 
| 350 void | 400 void | 
| 351 Document::addDerivedModel(TransformId transform, | 401 Document::addDerivedModel(const Transform &transform, | 
| 352 Model *inputModel, | 402 const ModelTransformer::Input &input, | 
| 353 const PluginTransformer::ExecutionContext &context, | 403 Model *outputModelToAdd) | 
| 354 Model *outputModelToAdd, | |
| 355 QString configurationXml) | |
| 356 { | 404 { | 
| 357 if (m_models.find(outputModelToAdd) != m_models.end()) { | 405 if (m_models.find(outputModelToAdd) != m_models.end()) { | 
| 358 std::cerr << "WARNING: Document::addDerivedModel: Model already added" | 406 std::cerr << "WARNING: Document::addDerivedModel: Model already added" | 
| 359 << std::endl; | 407 << std::endl; | 
| 360 return; | 408 return; | 
| 361 } | 409 } | 
| 362 | 410 | 
| 363 // std::cerr << "Document::addDerivedModel: source is " << inputModel << " \"" << inputModel->objectName().toStdString() << "\"" << std::endl; | 411 #ifdef DEBUG_DOCUMENT | 
| 412 std::cerr << "Document::addDerivedModel: source is " << input.getModel() << " \"" << input.getModel()->objectName().toStdString() << "\"" << std::endl; | |
| 413 #endif | |
| 364 | 414 | 
| 365 ModelRecord rec; | 415 ModelRecord rec; | 
| 366 rec.source = inputModel; | 416 rec.source = input.getModel(); | 
| 417 rec.channel = input.getChannel(); | |
| 367 rec.transform = transform; | 418 rec.transform = transform; | 
| 368 rec.context = context; | |
| 369 rec.configurationXml = configurationXml; | |
| 370 rec.refcount = 0; | 419 rec.refcount = 0; | 
| 371 | 420 | 
| 372 outputModelToAdd->setSourceModel(inputModel); | 421 outputModelToAdd->setSourceModel(input.getModel()); | 
| 373 | 422 | 
| 374 m_models[outputModelToAdd] = rec; | 423 m_models[outputModelToAdd] = rec; | 
| 375 | 424 | 
| 376 emit modelAdded(outputModelToAdd); | 425 emit modelAdded(outputModelToAdd); | 
| 377 } | 426 } | 
| 386 return; | 435 return; | 
| 387 } | 436 } | 
| 388 | 437 | 
| 389 ModelRecord rec; | 438 ModelRecord rec; | 
| 390 rec.source = 0; | 439 rec.source = 0; | 
| 391 rec.transform = ""; | |
| 392 rec.refcount = 0; | 440 rec.refcount = 0; | 
| 393 | 441 | 
| 394 m_models[model] = rec; | 442 m_models[model] = rec; | 
| 395 | 443 | 
| 396 if (m_autoAlignment) alignModel(model); | 444 if (m_autoAlignment) alignModel(model); | 
| 397 | 445 | 
| 398 emit modelAdded(model); | 446 emit modelAdded(model); | 
| 399 } | 447 } | 
| 400 | 448 | 
| 401 Model * | 449 Model * | 
| 402 Document::addDerivedModel(TransformId transform, | 450 Document::addDerivedModel(const Transform &transform, | 
| 403 Model *inputModel, | 451 const ModelTransformer::Input &input, | 
| 404 const PluginTransformer::ExecutionContext &context, | 452 QString &message) | 
| 405 QString configurationXml) | |
| 406 { | 453 { | 
| 407 Model *model = 0; | 454 Model *model = 0; | 
| 408 | 455 | 
| 409 for (ModelMap::iterator i = m_models.begin(); i != m_models.end(); ++i) { | 456 for (ModelMap::iterator i = m_models.begin(); i != m_models.end(); ++i) { | 
| 410 if (i->second.transform == transform && | 457 if (i->second.transform == transform && | 
| 411 i->second.source == inputModel && | 458 i->second.source == input.getModel() && | 
| 412 i->second.context == context && | 459 i->second.channel == input.getChannel()) { | 
| 413 i->second.configurationXml == configurationXml) { | |
| 414 return i->first; | 460 return i->first; | 
| 415 } | 461 } | 
| 416 } | 462 } | 
| 417 | 463 | 
| 418 model = ModelTransformerFactory::getInstance()->transform | 464 model = ModelTransformerFactory::getInstance()->transform | 
| 419 (transform, inputModel, context, configurationXml); | 465 (transform, input, message); | 
| 466 | |
| 467 // The transform we actually used was presumably identical to the | |
| 468 // one asked for, except that the version of the plugin may | |
| 469 // differ. It's possible that the returned message contains a | |
| 470 // warning about this; that doesn't concern us here, but we do | |
| 471 // need to ensure that the transform we remember is correct for | |
| 472 // what was actually applied, with the current plugin version. | |
| 473 | |
| 474 Transform applied = transform; | |
| 475 applied.setPluginVersion | |
| 476 (TransformFactory::getInstance()-> | |
| 477 getDefaultTransformFor(transform.getIdentifier(), | |
| 478 lrintf(transform.getSampleRate())) | |
| 479 .getPluginVersion()); | |
| 420 | 480 | 
| 421 if (!model) { | 481 if (!model) { | 
| 422 std::cerr << "WARNING: Document::addDerivedModel: no output model for transform " << transform.toStdString() << std::endl; | 482 std::cerr << "WARNING: Document::addDerivedModel: no output model for transform " << transform.getIdentifier().toStdString() << std::endl; | 
| 423 } else { | 483 } else { | 
| 424 addDerivedModel(transform, inputModel, context, model, configurationXml); | 484 addDerivedModel(applied, input, model); | 
| 425 } | 485 } | 
| 426 | 486 | 
| 427 return model; | 487 return model; | 
| 428 } | 488 } | 
| 429 | 489 | 
| 472 << model << " even though it is source for " | 532 << model << " even though it is source for " | 
| 473 << sourceCount << " other derived model(s) -- resetting " | 533 << sourceCount << " other derived model(s) -- resetting " | 
| 474 << "their source fields appropriately" << std::endl; | 534 << "their source fields appropriately" << std::endl; | 
| 475 } | 535 } | 
| 476 | 536 | 
| 537 model->aboutToDelete(); | |
| 477 emit modelAboutToBeDeleted(model); | 538 emit modelAboutToBeDeleted(model); | 
| 478 model->aboutToDelete(); | |
| 479 m_models.erase(model); | 539 m_models.erase(model); | 
| 480 delete model; | 540 delete model; | 
| 481 } | 541 } | 
| 482 } | 542 } | 
| 483 | 543 | 
| 492 << " is still used in " << m_layerViewMap[layer].size() | 552 << " is still used in " << m_layerViewMap[layer].size() | 
| 493 << " views!" << std::endl; | 553 << " views!" << std::endl; | 
| 494 | 554 | 
| 495 if (force) { | 555 if (force) { | 
| 496 | 556 | 
| 557 #ifdef DEBUG_DOCUMENT | |
| 497 std::cerr << "(force flag set -- deleting from all views)" << std::endl; | 558 std::cerr << "(force flag set -- deleting from all views)" << std::endl; | 
| 559 #endif | |
| 498 | 560 | 
| 499 for (std::set<View *>::iterator j = m_layerViewMap[layer].begin(); | 561 for (std::set<View *>::iterator j = m_layerViewMap[layer].begin(); | 
| 500 j != m_layerViewMap[layer].end(); ++j) { | 562 j != m_layerViewMap[layer].end(); ++j) { | 
| 501 // don't use removeLayerFromView, as it issues a command | 563 // don't use removeLayerFromView, as it issues a command | 
| 502 layer->setLayerDormant(*j, true); | 564 layer->setLayerDormant(*j, true); | 
| 579 void | 641 void | 
| 580 Document::addLayerToView(View *view, Layer *layer) | 642 Document::addLayerToView(View *view, Layer *layer) | 
| 581 { | 643 { | 
| 582 Model *model = layer->getModel(); | 644 Model *model = layer->getModel(); | 
| 583 if (!model) { | 645 if (!model) { | 
| 584 // std::cerr << "Document::addLayerToView: Layer (\"" | 646 #ifdef DEBUG_DOCUMENT | 
| 585 // << layer->objectName().toStdString() | 647 std::cerr << "Document::addLayerToView: Layer (\"" | 
| 586 // << "\") with no model being added to view: " | 648 << layer->objectName().toStdString() | 
| 587 // << "normally you want to set the model first" << std::endl; | 649 << "\") with no model being added to view: " | 
| 650 << "normally you want to set the model first" << std::endl; | |
| 651 #endif | |
| 588 } else { | 652 } else { | 
| 589 if (model != m_mainModel && | 653 if (model != m_mainModel && | 
| 590 m_models.find(model) == m_models.end()) { | 654 m_models.find(model) == m_models.end()) { | 
| 591 std::cerr << "ERROR: Document::addLayerToView: Layer " << layer | 655 std::cerr << "ERROR: Document::addLayerToView: Layer " << layer | 
| 592 << " has unregistered model " << model | 656 << " has unregistered model " << model | 
| 663 if (!duplicate) return adjusted; | 727 if (!duplicate) return adjusted; | 
| 664 } | 728 } | 
| 665 } | 729 } | 
| 666 | 730 | 
| 667 std::vector<Model *> | 731 std::vector<Model *> | 
| 668 Document::getTransformerInputModels() | 732 Document::getTransformInputModels() | 
| 669 { | 733 { | 
| 670 std::vector<Model *> models; | 734 std::vector<Model *> models; | 
| 671 | 735 | 
| 672 if (!m_mainModel) return models; | 736 if (!m_mainModel) return models; | 
| 673 | 737 | 
| 688 | 752 | 
| 689 return models; | 753 return models; | 
| 690 } | 754 } | 
| 691 | 755 | 
| 692 bool | 756 bool | 
| 757 Document::isKnownModel(const Model *model) const | |
| 758 { | |
| 759 if (model == m_mainModel) return true; | |
| 760 return (m_models.find(const_cast<Model *>(model)) != m_models.end()); | |
| 761 } | |
| 762 | |
| 763 TransformId | |
| 764 Document::getAlignmentTransformName() | |
| 765 { | |
| 766 QSettings settings; | |
| 767 settings.beginGroup("Alignment"); | |
| 768 TransformId id = | |
| 769 settings.value("transform-id", | |
| 770 "vamp:match-vamp-plugin:match:path").toString(); | |
| 771 settings.endGroup(); | |
| 772 return id; | |
| 773 } | |
| 774 | |
| 775 bool | |
| 693 Document::canAlign() | 776 Document::canAlign() | 
| 694 { | 777 { | 
| 695 TransformId id = "vamp:match-vamp-plugin:match:path"; | 778 TransformId id = getAlignmentTransformName(); | 
| 696 TransformFactory *factory = TransformFactory::getInstance(); | 779 TransformFactory *factory = TransformFactory::getInstance(); | 
| 697 return factory->haveTransform(id); | 780 return factory->haveTransform(id); | 
| 698 } | 781 } | 
| 699 | 782 | 
| 700 void | 783 void | 
| 701 Document::alignModel(Model *model) | 784 Document::alignModel(Model *model) | 
| 702 { | 785 { | 
| 703 if (!m_mainModel || model == m_mainModel) return; | 786 if (!m_mainModel) return; | 
| 704 | 787 | 
| 705 RangeSummarisableTimeValueModel *rm = | 788 RangeSummarisableTimeValueModel *rm = | 
| 706 dynamic_cast<RangeSummarisableTimeValueModel *>(model); | 789 dynamic_cast<RangeSummarisableTimeValueModel *>(model); | 
| 707 if (!rm) return; | 790 if (!rm) return; | 
| 708 | 791 | 
| 709 if (rm->getAlignmentReference() == m_mainModel) return; | 792 if (rm->getAlignmentReference() == m_mainModel) { | 
| 793 std::cerr << "Document::alignModel: model " << rm << " is already aligned to main model " << m_mainModel << std::endl; | |
| 794 return; | |
| 795 } | |
| 710 | 796 | 
| 797 if (model == m_mainModel) { | |
| 798 // The reference has an empty alignment to itself. This makes | |
| 799 // it possible to distinguish between the reference and any | |
| 800 // unaligned model just by looking at the model itself, | |
| 801 // without also knowing what the main model is | |
| 802 std::cerr << "Document::alignModel(" << model << "): is main model, setting appropriately" << std::endl; | |
| 803 rm->setAlignment(new AlignmentModel(model, model, 0, 0)); | |
| 804 return; | |
| 805 } | |
| 806 | |
| 711 // This involves creating three new models: | 807 // This involves creating three new models: | 
| 712 | 808 | 
| 713 // 1. an AggregateWaveModel to provide the mixdowns of the main | 809 // 1. an AggregateWaveModel to provide the mixdowns of the main | 
| 714 // model and the new model in its two channels, as input to the | 810 // model and the new model in its two channels, as input to the | 
| 715 // MATCH plugin | 811 // MATCH plugin | 
| 735 components.push_back(AggregateWaveModel::ModelChannelSpec | 831 components.push_back(AggregateWaveModel::ModelChannelSpec | 
| 736 (rm, -1)); | 832 (rm, -1)); | 
| 737 | 833 | 
| 738 Model *aggregate = new AggregateWaveModel(components); | 834 Model *aggregate = new AggregateWaveModel(components); | 
| 739 | 835 | 
| 740 TransformId id = "vamp:match-vamp-plugin:match:path"; | 836 TransformId id = "vamp:match-vamp-plugin:match:path"; //!!! configure | 
| 741 | 837 | 
| 742 ModelTransformerFactory *factory = ModelTransformerFactory::getInstance(); | 838 TransformFactory *tf = TransformFactory::getInstance(); | 
| 743 | 839 | 
| 744 PluginTransformer::ExecutionContext context = | 840 Transform transform = tf->getDefaultTransformFor | 
| 745 factory->getDefaultContextForTransformer(id, aggregate); | 841 (id, aggregate->getSampleRate()); | 
| 746 context.stepSize = context.blockSize/2; | 842 | 
| 747 | 843 transform.setStepSize(transform.getBlockSize()/2); | 
| 748 QString args = "<plugin param-serialise=\"1\"/>"; | 844 transform.setParameter("serialise", 1); | 
| 749 | 845 | 
| 750 Model *transformOutput = factory->transform(id, aggregate, context, args); | 846 std::cerr << "Document::alignModel: Alignment transform step size " << transform.getStepSize() << ", block size " << transform.getBlockSize() << std::endl; | 
| 847 | |
| 848 ModelTransformerFactory *mtf = ModelTransformerFactory::getInstance(); | |
| 849 | |
| 850 QString message; | |
| 851 Model *transformOutput = mtf->transform(transform, aggregate, message); | |
| 751 | 852 | 
| 752 if (!transformOutput) { | 853 if (!transformOutput) { | 
| 753 context.stepSize = 0; | 854 transform.setStepSize(0); | 
| 754 transformOutput = factory->transform(id, aggregate, context, args); | 855 transformOutput = mtf->transform(transform, aggregate, message); | 
| 755 } | 856 } | 
| 756 | 857 | 
| 757 SparseTimeValueModel *path = dynamic_cast<SparseTimeValueModel *> | 858 SparseTimeValueModel *path = dynamic_cast<SparseTimeValueModel *> | 
| 758 (transformOutput); | 859 (transformOutput); | 
| 759 | 860 | 
| 760 if (!path) { | 861 if (!path) { | 
| 761 std::cerr << "Document::alignModel: ERROR: Failed to create alignment path (no MATCH plugin?)" << std::endl; | 862 std::cerr << "Document::alignModel: ERROR: Failed to create alignment path (no MATCH plugin?)" << std::endl; | 
| 863 emit alignmentFailed(id, message); | |
| 762 delete transformOutput; | 864 delete transformOutput; | 
| 763 delete aggregate; | 865 delete aggregate; | 
| 764 return; | 866 return; | 
| 765 } | 867 } | 
| 766 | 868 | 
| 774 Document::alignModels() | 876 Document::alignModels() | 
| 775 { | 877 { | 
| 776 for (ModelMap::iterator i = m_models.begin(); i != m_models.end(); ++i) { | 878 for (ModelMap::iterator i = m_models.begin(); i != m_models.end(); ++i) { | 
| 777 alignModel(i->first); | 879 alignModel(i->first); | 
| 778 } | 880 } | 
| 881 alignModel(m_mainModel); | |
| 779 } | 882 } | 
| 780 | 883 | 
| 781 Document::AddLayerCommand::AddLayerCommand(Document *d, | 884 Document::AddLayerCommand::AddLayerCommand(Document *d, | 
| 782 View *view, | 885 View *view, | 
| 783 Layer *layer) : | 886 Layer *layer) : | 
| 789 { | 892 { | 
| 790 } | 893 } | 
| 791 | 894 | 
| 792 Document::AddLayerCommand::~AddLayerCommand() | 895 Document::AddLayerCommand::~AddLayerCommand() | 
| 793 { | 896 { | 
| 794 // std::cerr << "Document::AddLayerCommand::~AddLayerCommand" << std::endl; | 897 #ifdef DEBUG_DOCUMENT | 
| 898 std::cerr << "Document::AddLayerCommand::~AddLayerCommand" << std::endl; | |
| 899 #endif | |
| 795 if (!m_added) { | 900 if (!m_added) { | 
| 796 m_d->deleteLayer(m_layer); | 901 m_d->deleteLayer(m_layer); | 
| 797 } | 902 } | 
| 798 } | 903 } | 
| 799 | 904 | 
| 837 { | 942 { | 
| 838 } | 943 } | 
| 839 | 944 | 
| 840 Document::RemoveLayerCommand::~RemoveLayerCommand() | 945 Document::RemoveLayerCommand::~RemoveLayerCommand() | 
| 841 { | 946 { | 
| 842 // std::cerr << "Document::RemoveLayerCommand::~RemoveLayerCommand" << std::endl; | 947 #ifdef DEBUG_DOCUMENT | 
| 948 std::cerr << "Document::RemoveLayerCommand::~RemoveLayerCommand" << std::endl; | |
| 949 #endif | |
| 843 if (!m_added) { | 950 if (!m_added) { | 
| 844 m_d->deleteLayer(m_layer); | 951 m_d->deleteLayer(m_layer); | 
| 845 } | 952 } | 
| 846 } | 953 } | 
| 847 | 954 | 
| 924 // as well as making an intelligent guess. | 1031 // as well as making an intelligent guess. | 
| 925 | 1032 | 
| 926 bool writeModel = true; | 1033 bool writeModel = true; | 
| 927 bool haveDerivation = false; | 1034 bool haveDerivation = false; | 
| 928 | 1035 | 
| 929 if (rec.source && rec.transform != "") { | 1036 if (rec.source && rec.transform.getIdentifier() != "") { | 
| 930 haveDerivation = true; | 1037 haveDerivation = true; | 
| 931 } | 1038 } | 
| 932 | 1039 | 
| 933 if (haveDerivation) { | 1040 if (haveDerivation) { | 
| 934 if (dynamic_cast<const WritableWaveFileModel *>(model)) { | 1041 if (dynamic_cast<const WritableWaveFileModel *>(model)) { | 
| 941 if (writeModel) { | 1048 if (writeModel) { | 
| 942 i->first->toXml(out, indent + " "); | 1049 i->first->toXml(out, indent + " "); | 
| 943 } | 1050 } | 
| 944 | 1051 | 
| 945 if (haveDerivation) { | 1052 if (haveDerivation) { | 
| 946 | 1053 writeBackwardCompatibleDerivation(out, indent + " ", | 
| 947 QString extentsAttributes; | 1054 i->first, rec); | 
| 948 if (rec.context.startFrame != 0 || | |
| 949 rec.context.duration != 0) { | |
| 950 extentsAttributes = QString("startFrame=\"%1\" duration=\"%2\" ") | |
| 951 .arg(rec.context.startFrame) | |
| 952 .arg(rec.context.duration); | |
| 953 } | |
| 954 | |
| 955 out << indent; | |
| 956 out << QString(" <derivation source=\"%1\" model=\"%2\" channel=\"%3\" domain=\"%4\" stepSize=\"%5\" blockSize=\"%6\" %7windowType=\"%8\" transform=\"%9\"") | |
| 957 .arg(XmlExportable::getObjectExportId(rec.source)) | |
| 958 .arg(XmlExportable::getObjectExportId(i->first)) | |
| 959 .arg(rec.context.channel) | |
| 960 .arg(rec.context.domain) | |
| 961 .arg(rec.context.stepSize) | |
| 962 .arg(rec.context.blockSize) | |
| 963 .arg(extentsAttributes) | |
| 964 .arg(int(rec.context.windowType)) | |
| 965 .arg(XmlExportable::encodeEntities(rec.transform)); | |
| 966 | |
| 967 if (rec.configurationXml != "") { | |
| 968 out << ">\n " + indent + rec.configurationXml | |
| 969 + "\n" + indent + " </derivation>\n"; | |
| 970 } else { | |
| 971 out << "/>\n"; | |
| 972 } | |
| 973 } | 1055 } | 
| 974 | 1056 | 
| 975 //!!! We should probably own the PlayParameterRepository | 1057 //!!! We should probably own the PlayParameterRepository | 
| 976 PlayParameters *playParameters = | 1058 PlayParameters *playParameters = | 
| 977 PlayParameterRepository::getInstance()->getPlayParameters(i->first); | 1059 PlayParameterRepository::getInstance()->getPlayParameters(i->first); | 
| 990 } | 1072 } | 
| 991 | 1073 | 
| 992 out << indent + "</data>\n"; | 1074 out << indent + "</data>\n"; | 
| 993 } | 1075 } | 
| 994 | 1076 | 
| 995 | 1077 void | 
| 1078 Document::writeBackwardCompatibleDerivation(QTextStream &out, QString indent, | |
| 1079 Model *targetModel, | |
| 1080 const ModelRecord &rec) const | |
| 1081 { | |
| 1082 // There is a lot of redundancy in the XML we output here, because | |
| 1083 // we want it to work with older SV session file reading code as | |
| 1084 // well. | |
| 1085 // | |
| 1086 // Formerly, a transform was described using a derivation element | |
| 1087 // which set out the source and target models, execution context | |
| 1088 // (step size, input channel etc) and transform id, containing a | |
| 1089 // plugin element which set out the transform parameters and so | |
| 1090 // on. (The plugin element came from a "configurationXml" string | |
| 1091 // obtained from PluginXml.) | |
| 1092 // | |
| 1093 // This has been replaced by a derivation element setting out the | |
| 1094 // source and target models and input channel, containing a | |
| 1095 // transform element which sets out everything in the Transform. | |
| 1096 // | |
| 1097 // In order to retain compatibility with older SV code, however, | |
| 1098 // we have to write out the same stuff into the derivation as | |
| 1099 // before, and manufacture an appropriate plugin element as well | |
| 1100 // as the transform element. In order that newer code knows it's | |
| 1101 // dealing with a newer format, we will also write an attribute | |
| 1102 // 'type="transform"' in the derivation element. | |
| 1103 | |
| 1104 const Transform &transform = rec.transform; | |
| 1105 | |
| 1106 // Just for reference, this is what we would write if we didn't | |
| 1107 // have to be backward compatible: | |
| 1108 // | |
| 1109 // out << indent | |
| 1110 // << QString("<derivation type=\"transform\" source=\"%1\" " | |
| 1111 // "model=\"%2\" channel=\"%3\">\n") | |
| 1112 // .arg(XmlExportable::getObjectExportId(rec.source)) | |
| 1113 // .arg(XmlExportable::getObjectExportId(targetModel)) | |
| 1114 // .arg(rec.channel); | |
| 1115 // | |
| 1116 // transform.toXml(out, indent + " "); | |
| 1117 // | |
| 1118 // out << indent << "</derivation>\n"; | |
| 1119 // | |
| 1120 // Unfortunately, we can't just do that. So we do this... | |
| 1121 | |
| 1122 QString extentsAttributes; | |
| 1123 if (transform.getStartTime() != RealTime::zeroTime || | |
| 1124 transform.getDuration() != RealTime::zeroTime) { | |
| 1125 extentsAttributes = QString("startFrame=\"%1\" duration=\"%2\" ") | |
| 1126 .arg(RealTime::realTime2Frame(transform.getStartTime(), | |
| 1127 targetModel->getSampleRate())) | |
| 1128 .arg(RealTime::realTime2Frame(transform.getDuration(), | |
| 1129 targetModel->getSampleRate())); | |
| 1130 } | |
| 1131 | |
| 1132 out << indent; | |
| 1133 out << QString("<derivation type=\"transform\" source=\"%1\" " | |
| 1134 "model=\"%2\" channel=\"%3\" domain=\"%4\" " | |
| 1135 "stepSize=\"%5\" blockSize=\"%6\" %7windowType=\"%8\" " | |
| 1136 "transform=\"%9\">\n") | |
| 1137 .arg(XmlExportable::getObjectExportId(rec.source)) | |
| 1138 .arg(XmlExportable::getObjectExportId(targetModel)) | |
| 1139 .arg(rec.channel) | |
| 1140 .arg(TransformFactory::getInstance()->getTransformInputDomain | |
| 1141 (transform.getIdentifier())) | |
| 1142 .arg(transform.getStepSize()) | |
| 1143 .arg(transform.getBlockSize()) | |
| 1144 .arg(extentsAttributes) | |
| 1145 .arg(int(transform.getWindowType())) | |
| 1146 .arg(XmlExportable::encodeEntities(transform.getIdentifier())); | |
| 1147 | |
| 1148 transform.toXml(out, indent + " "); | |
| 1149 | |
| 1150 out << indent << " " | |
| 1151 << TransformFactory::getInstance()->getPluginConfigurationXml(transform); | |
| 1152 | |
| 1153 out << indent << "</derivation>\n"; | |
| 1154 } | |
| 1155 | 
