Mercurial > hg > svapp
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 |