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