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 |