comparison framework/Document.cpp @ 101:89a689720ee9 spectrogram-cache-rejig

* Merge from trunk
author Chris Cannam
date Wed, 27 Feb 2008 11:59:42 +0000
parents 621c2edd1693
children
comparison
equal deleted inserted replaced
59:bf1a53489ccc 101:89a689720ee9
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
115 #ifdef DEBUG_DOCUMENT
106 std::cerr << "Document::createLayer: Added layer of type " << type 116 std::cerr << "Document::createLayer: Added layer of type " << type
107 << ", now have " << m_layers.size() << " layers" << std::endl; 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
157 Layer * 170 Layer *
158 Document::createEmptyLayer(LayerFactory::LayerType type) 171 Document::createEmptyLayer(LayerFactory::LayerType type)
159 { 172 {
173 if (!m_mainModel) return 0;
174
160 Model *newModel = 175 Model *newModel =
161 LayerFactory::getInstance()->createEmptyModel(type, m_mainModel); 176 LayerFactory::getInstance()->createEmptyModel(type, m_mainModel);
162 if (!newModel) return 0; 177 if (!newModel) return 0;
163 178
164 Layer *newLayer = createLayer(type); 179 Layer *newLayer = createLayer(type);
186 201
187 return newLayer; 202 return newLayer;
188 } 203 }
189 204
190 Layer * 205 Layer *
191 Document::createDerivedLayer(TransformId transform, 206 Document::createDerivedLayer(const Transform &transform,
192 Model *inputModel, 207 const ModelTransformer::Input &input)
193 const PluginTransformer::ExecutionContext &context, 208 {
194 QString configurationXml) 209 QString message;
195 { 210 Model *newModel = addDerivedModel(transform, input, message);
196 Model *newModel = addDerivedModel(transform, inputModel,
197 context, configurationXml);
198 if (!newModel) { 211 if (!newModel) {
199 // error already printed to stderr by addDerivedModel 212 emit modelGenerationFailed(transform.getIdentifier(), message);
200 emit modelGenerationFailed(transform);
201 return 0; 213 return 0;
214 } else if (message != "") {
215 emit modelGenerationWarning(transform.getIdentifier(), message);
202 } 216 }
203 217
204 LayerFactory::LayerTypeSet types = 218 LayerFactory::LayerTypeSet types =
205 LayerFactory::getInstance()->getValidLayerTypes(newModel); 219 LayerFactory::getInstance()->getValidLayerTypes(newModel);
206 220
207 if (types.empty()) { 221 if (types.empty()) {
208 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;
209 delete newModel; 223 delete newModel;
210 return 0; 224 return 0;
211 } 225 }
212 226
213 //!!! for now, just use the first suitable layer type 227 //!!! for now, just use the first suitable layer type
231 // 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.
232 246
233 if (newLayer) { 247 if (newLayer) {
234 newLayer->setObjectName(getUniqueLayerName 248 newLayer->setObjectName(getUniqueLayerName
235 (TransformFactory::getInstance()-> 249 (TransformFactory::getInstance()->
236 getTransformFriendlyName(transform))); 250 getTransformFriendlyName
251 (transform.getIdentifier())));
237 } 252 }
238 253
239 emit layerAdded(newLayer); 254 emit layerAdded(newLayer);
240 return newLayer; 255 return newLayer;
241 } 256 }
255 // 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
256 // model, or delete the layer for each layer that is currently 271 // model, or delete the layer for each layer that is currently
257 // using one of these. Carry out this replacement before we 272 // using one of these. Carry out this replacement before we
258 // delete any of the models. 273 // delete any of the models.
259 274
275 #ifdef DEBUG_DOCUMENT
260 std::cerr << "Document::setMainModel: Have " 276 std::cerr << "Document::setMainModel: Have "
261 << m_layers.size() << " layers" << std::endl; 277 << m_layers.size() << " layers" << std::endl;
278 #endif
262 279
263 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) {
264 281
265 Layer *layer = *i; 282 Layer *layer = *i;
266 Model *model = layer->getModel(); 283 Model *model = layer->getModel();
267 284
268 // std::cerr << "Document::setMainModel: inspecting model " 285 #ifdef DEBUG_DOCUMENT
269 // << (model ? model->objectName().toStdString() : "(null)") << " in layer " 286 std::cerr << "Document::setMainModel: inspecting model "
270 // << layer->objectName().toStdString() << std::endl; 287 << (model ? model->objectName().toStdString() : "(null)") << " in layer "
288 << layer->objectName().toStdString() << std::endl;
289 #endif
271 290
272 if (model == oldMainModel) { 291 if (model == oldMainModel) {
273 // 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
274 LayerFactory::getInstance()->setModel(layer, m_mainModel); 295 LayerFactory::getInstance()->setModel(layer, m_mainModel);
275 continue; 296 continue;
276 } 297 }
277 298
278 if (m_models.find(model) == m_models.end()) { 299 if (model && (m_models.find(model) == m_models.end())) {
279 std::cerr << "WARNING: Document::setMainModel: Unknown model " 300 std::cerr << "WARNING: Document::setMainModel: Unknown model "
280 << model << " in layer " << layer << std::endl; 301 << model << " in layer " << layer << std::endl;
281 // get rid of this hideous degenerate 302 // get rid of this hideous degenerate
282 obsoleteLayers.push_back(layer); 303 obsoleteLayers.push_back(layer);
283 continue; 304 continue;
284 } 305 }
285 306
286 if (m_models[model].source == oldMainModel) { 307 if (m_models[model].source &&
287 308 (m_models[model].source == oldMainModel)) {
288 // std::cerr << "... it uses a model derived from the old main model, regenerating" << std::endl; 309
310 #ifdef DEBUG_DOCUMENT
311 std::cerr << "... it uses a model derived from the old main model, regenerating" << std::endl;
312 #endif
289 313
290 // This model was derived from the previous main 314 // This model was derived from the previous main
291 // model: regenerate it. 315 // model: regenerate it.
292 316
293 TransformId transform = m_models[model].transform; 317 const Transform &transform = m_models[model].transform;
294 PluginTransformer::ExecutionContext context = m_models[model].context; 318 QString transformId = transform.getIdentifier();
295 319
320 //!!! We have a problem here if the number of channels in
321 //the main model has changed.
322
323 QString message;
296 Model *replacementModel = 324 Model *replacementModel =
297 addDerivedModel(transform, 325 addDerivedModel(transform,
298 m_mainModel, 326 ModelTransformer::Input
299 context, 327 (m_mainModel, m_models[model].channel),
300 m_models[model].configurationXml); 328 message);
301 329
302 if (!replacementModel) { 330 if (!replacementModel) {
303 std::cerr << "WARNING: Document::setMainModel: Failed to regenerate model for transform \"" 331 std::cerr << "WARNING: Document::setMainModel: Failed to regenerate model for transform \""
304 << transform.toStdString() << "\"" << " in layer " << layer << std::endl; 332 << transformId.toStdString() << "\"" << " in layer " << layer << std::endl;
305 if (failedTransformers.find(transform) == failedTransformers.end()) { 333 if (failedTransformers.find(transformId)
334 == failedTransformers.end()) {
306 emit modelRegenerationFailed(layer->objectName(), 335 emit modelRegenerationFailed(layer->objectName(),
307 transform); 336 transformId,
308 failedTransformers.insert(transform); 337 message);
338 failedTransformers.insert(transformId);
309 } 339 }
310 obsoleteLayers.push_back(layer); 340 obsoleteLayers.push_back(layer);
311 } else { 341 } else {
342 if (message != "") {
343 emit modelRegenerationWarning(layer->objectName(),
344 transformId,
345 message);
346 }
347 #ifdef DEBUG_DOCUMENT
312 std::cerr << "Replacing model " << model << " (type " 348 std::cerr << "Replacing model " << model << " (type "
313 << typeid(*model).name() << ") with model " 349 << typeid(*model).name() << ") with model "
314 << replacementModel << " (type " 350 << replacementModel << " (type "
315 << typeid(*replacementModel).name() << ") in layer " 351 << typeid(*replacementModel).name() << ") in layer "
316 << layer << " (name " << layer->objectName().toStdString() << ")" 352 << layer << " (name " << layer->objectName().toStdString() << ")"
317 << std::endl; 353 << std::endl;
354 #endif
318 RangeSummarisableTimeValueModel *rm = 355 RangeSummarisableTimeValueModel *rm =
319 dynamic_cast<RangeSummarisableTimeValueModel *>(replacementModel); 356 dynamic_cast<RangeSummarisableTimeValueModel *>(replacementModel);
357 #ifdef DEBUG_DOCUMENT
320 if (rm) { 358 if (rm) {
321 std::cerr << "new model has " << rm->getChannelCount() << " channels " << std::endl; 359 std::cerr << "new model has " << rm->getChannelCount() << " channels " << std::endl;
322 } else { 360 } else {
323 std::cerr << "new model is not a RangeSummarisableTimeValueModel!" << std::endl; 361 std::cerr << "new model is not a RangeSummarisableTimeValueModel!" << std::endl;
324 } 362 }
363 #endif
325 setModel(layer, replacementModel); 364 setModel(layer, replacementModel);
326 } 365 }
327 } 366 }
328 } 367 }
329 368
330 for (size_t k = 0; k < obsoleteLayers.size(); ++k) { 369 for (size_t k = 0; k < obsoleteLayers.size(); ++k) {
331 deleteLayer(obsoleteLayers[k], true); 370 deleteLayer(obsoleteLayers[k], true);
332 } 371 }
333 372
334 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) {
335 if (i->first->getAlignmentReference() == oldMainModel) { 374
375 if (m_autoAlignment) {
376
377 alignModel(i->first);
378
379 } else if (oldMainModel &&
380 (i->first->getAlignmentReference() == oldMainModel)) {
381
336 alignModel(i->first); 382 alignModel(i->first);
337 } 383 }
338 } 384 }
339 385
386 if (oldMainModel) {
387 oldMainModel->aboutToDelete();
388 emit modelAboutToBeDeleted(oldMainModel);
389 }
390
391 if (m_autoAlignment) {
392 alignModel(m_mainModel);
393 }
394
340 emit mainModelChanged(m_mainModel); 395 emit mainModelChanged(m_mainModel);
341 396
342 // we already emitted modelAboutToBeDeleted for this
343 delete oldMainModel; 397 delete oldMainModel;
344 } 398 }
345 399
346 void 400 void
347 Document::addDerivedModel(TransformId transform, 401 Document::addDerivedModel(const Transform &transform,
348 Model *inputModel, 402 const ModelTransformer::Input &input,
349 const PluginTransformer::ExecutionContext &context, 403 Model *outputModelToAdd)
350 Model *outputModelToAdd,
351 QString configurationXml)
352 { 404 {
353 if (m_models.find(outputModelToAdd) != m_models.end()) { 405 if (m_models.find(outputModelToAdd) != m_models.end()) {
354 std::cerr << "WARNING: Document::addDerivedModel: Model already added" 406 std::cerr << "WARNING: Document::addDerivedModel: Model already added"
355 << std::endl; 407 << std::endl;
356 return; 408 return;
357 } 409 }
358 410
359 // 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
360 414
361 ModelRecord rec; 415 ModelRecord rec;
362 rec.source = inputModel; 416 rec.source = input.getModel();
417 rec.channel = input.getChannel();
363 rec.transform = transform; 418 rec.transform = transform;
364 rec.context = context;
365 rec.configurationXml = configurationXml;
366 rec.refcount = 0; 419 rec.refcount = 0;
367 420
368 outputModelToAdd->setSourceModel(inputModel); 421 outputModelToAdd->setSourceModel(input.getModel());
369 422
370 m_models[outputModelToAdd] = rec; 423 m_models[outputModelToAdd] = rec;
371 424
372 emit modelAdded(outputModelToAdd); 425 emit modelAdded(outputModelToAdd);
373 } 426 }
382 return; 435 return;
383 } 436 }
384 437
385 ModelRecord rec; 438 ModelRecord rec;
386 rec.source = 0; 439 rec.source = 0;
387 rec.transform = "";
388 rec.refcount = 0; 440 rec.refcount = 0;
389 441
390 m_models[model] = rec; 442 m_models[model] = rec;
391 443
392 if (m_autoAlignment) alignModel(model); 444 if (m_autoAlignment) alignModel(model);
393 445
394 emit modelAdded(model); 446 emit modelAdded(model);
395 } 447 }
396 448
397 Model * 449 Model *
398 Document::addDerivedModel(TransformId transform, 450 Document::addDerivedModel(const Transform &transform,
399 Model *inputModel, 451 const ModelTransformer::Input &input,
400 const PluginTransformer::ExecutionContext &context, 452 QString &message)
401 QString configurationXml)
402 { 453 {
403 Model *model = 0; 454 Model *model = 0;
404 455
405 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) {
406 if (i->second.transform == transform && 457 if (i->second.transform == transform &&
407 i->second.source == inputModel && 458 i->second.source == input.getModel() &&
408 i->second.context == context && 459 i->second.channel == input.getChannel()) {
409 i->second.configurationXml == configurationXml) {
410 return i->first; 460 return i->first;
411 } 461 }
412 } 462 }
413 463
414 model = ModelTransformerFactory::getInstance()->transform 464 model = ModelTransformerFactory::getInstance()->transform
415 (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());
416 480
417 if (!model) { 481 if (!model) {
418 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;
419 } else { 483 } else {
420 addDerivedModel(transform, inputModel, context, model, configurationXml); 484 addDerivedModel(applied, input, model);
421 } 485 }
422 486
423 return model; 487 return model;
424 } 488 }
425 489
468 << model << " even though it is source for " 532 << model << " even though it is source for "
469 << sourceCount << " other derived model(s) -- resetting " 533 << sourceCount << " other derived model(s) -- resetting "
470 << "their source fields appropriately" << std::endl; 534 << "their source fields appropriately" << std::endl;
471 } 535 }
472 536
537 model->aboutToDelete();
473 emit modelAboutToBeDeleted(model); 538 emit modelAboutToBeDeleted(model);
474 model->aboutToDelete();
475 m_models.erase(model); 539 m_models.erase(model);
476 delete model; 540 delete model;
477 } 541 }
478 } 542 }
479 543
488 << " is still used in " << m_layerViewMap[layer].size() 552 << " is still used in " << m_layerViewMap[layer].size()
489 << " views!" << std::endl; 553 << " views!" << std::endl;
490 554
491 if (force) { 555 if (force) {
492 556
557 #ifdef DEBUG_DOCUMENT
493 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
494 560
495 for (std::set<View *>::iterator j = m_layerViewMap[layer].begin(); 561 for (std::set<View *>::iterator j = m_layerViewMap[layer].begin();
496 j != m_layerViewMap[layer].end(); ++j) { 562 j != m_layerViewMap[layer].end(); ++j) {
497 // don't use removeLayerFromView, as it issues a command 563 // don't use removeLayerFromView, as it issues a command
498 layer->setLayerDormant(*j, true); 564 layer->setLayerDormant(*j, true);
575 void 641 void
576 Document::addLayerToView(View *view, Layer *layer) 642 Document::addLayerToView(View *view, Layer *layer)
577 { 643 {
578 Model *model = layer->getModel(); 644 Model *model = layer->getModel();
579 if (!model) { 645 if (!model) {
580 // std::cerr << "Document::addLayerToView: Layer (\"" 646 #ifdef DEBUG_DOCUMENT
581 // << layer->objectName().toStdString() 647 std::cerr << "Document::addLayerToView: Layer (\""
582 // << "\") with no model being added to view: " 648 << layer->objectName().toStdString()
583 // << "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
584 } else { 652 } else {
585 if (model != m_mainModel && 653 if (model != m_mainModel &&
586 m_models.find(model) == m_models.end()) { 654 m_models.find(model) == m_models.end()) {
587 std::cerr << "ERROR: Document::addLayerToView: Layer " << layer 655 std::cerr << "ERROR: Document::addLayerToView: Layer " << layer
588 << " has unregistered model " << model 656 << " has unregistered model " << model
659 if (!duplicate) return adjusted; 727 if (!duplicate) return adjusted;
660 } 728 }
661 } 729 }
662 730
663 std::vector<Model *> 731 std::vector<Model *>
664 Document::getTransformerInputModels() 732 Document::getTransformInputModels()
665 { 733 {
666 std::vector<Model *> models; 734 std::vector<Model *> models;
667 735
668 if (!m_mainModel) return models; 736 if (!m_mainModel) return models;
669 737
684 752
685 return models; 753 return models;
686 } 754 }
687 755
688 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
689 Document::canAlign() 776 Document::canAlign()
690 { 777 {
691 TransformId id = "vamp:match-vamp-plugin:match:path"; 778 TransformId id = getAlignmentTransformName();
692 TransformFactory *factory = TransformFactory::getInstance(); 779 TransformFactory *factory = TransformFactory::getInstance();
693 return factory->haveTransform(id); 780 return factory->haveTransform(id);
694 } 781 }
695 782
696 void 783 void
697 Document::alignModel(Model *model) 784 Document::alignModel(Model *model)
698 { 785 {
699 if (!m_mainModel || model == m_mainModel) return; 786 if (!m_mainModel) return;
700 787
701 RangeSummarisableTimeValueModel *rm = 788 RangeSummarisableTimeValueModel *rm =
702 dynamic_cast<RangeSummarisableTimeValueModel *>(model); 789 dynamic_cast<RangeSummarisableTimeValueModel *>(model);
703 if (!rm) return; 790 if (!rm) return;
704 791
705 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 }
706 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
707 // This involves creating three new models: 807 // This involves creating three new models:
708 808
709 // 1. an AggregateWaveModel to provide the mixdowns of the main 809 // 1. an AggregateWaveModel to provide the mixdowns of the main
710 // 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
711 // MATCH plugin 811 // MATCH plugin
731 components.push_back(AggregateWaveModel::ModelChannelSpec 831 components.push_back(AggregateWaveModel::ModelChannelSpec
732 (rm, -1)); 832 (rm, -1));
733 833
734 Model *aggregate = new AggregateWaveModel(components); 834 Model *aggregate = new AggregateWaveModel(components);
735 835
736 TransformId id = "vamp:match-vamp-plugin:match:path"; 836 TransformId id = "vamp:match-vamp-plugin:match:path"; //!!! configure
737 837
738 ModelTransformerFactory *factory = ModelTransformerFactory::getInstance(); 838 TransformFactory *tf = TransformFactory::getInstance();
739 839
740 PluginTransformer::ExecutionContext context = 840 Transform transform = tf->getDefaultTransformFor
741 factory->getDefaultContextForTransformer(id, aggregate); 841 (id, aggregate->getSampleRate());
742 context.stepSize = context.blockSize/2; 842
743 843 transform.setStepSize(transform.getBlockSize()/2);
744 Model *transformOutput = factory->transform 844 transform.setParameter("serialise", 1);
745 (id, aggregate, context, "<plugin param-serialise=\"1\"/>"); 845
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);
852
853 if (!transformOutput) {
854 transform.setStepSize(0);
855 transformOutput = mtf->transform(transform, aggregate, message);
856 }
746 857
747 SparseTimeValueModel *path = dynamic_cast<SparseTimeValueModel *> 858 SparseTimeValueModel *path = dynamic_cast<SparseTimeValueModel *>
748 (transformOutput); 859 (transformOutput);
749 860
750 if (!path) { 861 if (!path) {
751 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);
752 delete transformOutput; 864 delete transformOutput;
753 delete aggregate; 865 delete aggregate;
754 return; 866 return;
755 } 867 }
756 868
764 Document::alignModels() 876 Document::alignModels()
765 { 877 {
766 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) {
767 alignModel(i->first); 879 alignModel(i->first);
768 } 880 }
881 alignModel(m_mainModel);
769 } 882 }
770 883
771 Document::AddLayerCommand::AddLayerCommand(Document *d, 884 Document::AddLayerCommand::AddLayerCommand(Document *d,
772 View *view, 885 View *view,
773 Layer *layer) : 886 Layer *layer) :
779 { 892 {
780 } 893 }
781 894
782 Document::AddLayerCommand::~AddLayerCommand() 895 Document::AddLayerCommand::~AddLayerCommand()
783 { 896 {
784 // std::cerr << "Document::AddLayerCommand::~AddLayerCommand" << std::endl; 897 #ifdef DEBUG_DOCUMENT
898 std::cerr << "Document::AddLayerCommand::~AddLayerCommand" << std::endl;
899 #endif
785 if (!m_added) { 900 if (!m_added) {
786 m_d->deleteLayer(m_layer); 901 m_d->deleteLayer(m_layer);
787 } 902 }
788 } 903 }
789 904
827 { 942 {
828 } 943 }
829 944
830 Document::RemoveLayerCommand::~RemoveLayerCommand() 945 Document::RemoveLayerCommand::~RemoveLayerCommand()
831 { 946 {
832 // std::cerr << "Document::RemoveLayerCommand::~RemoveLayerCommand" << std::endl; 947 #ifdef DEBUG_DOCUMENT
948 std::cerr << "Document::RemoveLayerCommand::~RemoveLayerCommand" << std::endl;
949 #endif
833 if (!m_added) { 950 if (!m_added) {
834 m_d->deleteLayer(m_layer); 951 m_d->deleteLayer(m_layer);
835 } 952 }
836 } 953 }
837 954
914 // as well as making an intelligent guess. 1031 // as well as making an intelligent guess.
915 1032
916 bool writeModel = true; 1033 bool writeModel = true;
917 bool haveDerivation = false; 1034 bool haveDerivation = false;
918 1035
919 if (rec.source && rec.transform != "") { 1036 if (rec.source && rec.transform.getIdentifier() != "") {
920 haveDerivation = true; 1037 haveDerivation = true;
921 } 1038 }
922 1039
923 if (haveDerivation) { 1040 if (haveDerivation) {
924 if (dynamic_cast<const WritableWaveFileModel *>(model)) { 1041 if (dynamic_cast<const WritableWaveFileModel *>(model)) {
931 if (writeModel) { 1048 if (writeModel) {
932 i->first->toXml(out, indent + " "); 1049 i->first->toXml(out, indent + " ");
933 } 1050 }
934 1051
935 if (haveDerivation) { 1052 if (haveDerivation) {
936 1053 writeBackwardCompatibleDerivation(out, indent + " ",
937 QString extentsAttributes; 1054 i->first, rec);
938 if (rec.context.startFrame != 0 ||
939 rec.context.duration != 0) {
940 extentsAttributes = QString("startFrame=\"%1\" duration=\"%2\" ")
941 .arg(rec.context.startFrame)
942 .arg(rec.context.duration);
943 }
944
945 out << indent;
946 out << QString(" <derivation source=\"%1\" model=\"%2\" channel=\"%3\" domain=\"%4\" stepSize=\"%5\" blockSize=\"%6\" %7windowType=\"%8\" transform=\"%9\"")
947 .arg(XmlExportable::getObjectExportId(rec.source))
948 .arg(XmlExportable::getObjectExportId(i->first))
949 .arg(rec.context.channel)
950 .arg(rec.context.domain)
951 .arg(rec.context.stepSize)
952 .arg(rec.context.blockSize)
953 .arg(extentsAttributes)
954 .arg(int(rec.context.windowType))
955 .arg(XmlExportable::encodeEntities(rec.transform));
956
957 if (rec.configurationXml != "") {
958 out << ">\n " + indent + rec.configurationXml
959 + "\n" + indent + " </derivation>\n";
960 } else {
961 out << "/>\n";
962 }
963 } 1055 }
964 1056
965 //!!! We should probably own the PlayParameterRepository 1057 //!!! We should probably own the PlayParameterRepository
966 PlayParameters *playParameters = 1058 PlayParameters *playParameters =
967 PlayParameterRepository::getInstance()->getPlayParameters(i->first); 1059 PlayParameterRepository::getInstance()->getPlayParameters(i->first);
980 } 1072 }
981 1073
982 out << indent + "</data>\n"; 1074 out << indent + "</data>\n";
983 } 1075 }
984 1076
985 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