Mercurial > hg > svapp
comparison framework/Document.cpp @ 72:4aa40182321f
* Merge from transforms branch -- switch over to using Transform object
properly
author | Chris Cannam |
---|---|
date | Fri, 07 Dec 2007 16:47:31 +0000 |
parents | 716e9d2f91c7 |
children | 0535c49069ba |
comparison
equal
deleted
inserted
replaced
70:716e9d2f91c7 | 72:4aa40182321f |
---|---|
188 | 188 |
189 return newLayer; | 189 return newLayer; |
190 } | 190 } |
191 | 191 |
192 Layer * | 192 Layer * |
193 Document::createDerivedLayer(TransformId transform, | 193 Document::createDerivedLayer(const Transform &transform, |
194 Model *inputModel, | 194 const ModelTransformer::Input &input) |
195 const PluginTransformer::ExecutionContext &context, | 195 { |
196 QString configurationXml) | 196 Model *newModel = addDerivedModel(transform, input); |
197 { | |
198 Model *newModel = addDerivedModel(transform, inputModel, | |
199 context, configurationXml); | |
200 if (!newModel) { | 197 if (!newModel) { |
201 // error already printed to stderr by addDerivedModel | 198 // error already printed to stderr by addDerivedModel |
202 emit modelGenerationFailed(transform); | 199 emit modelGenerationFailed(transform.getIdentifier()); |
203 return 0; | 200 return 0; |
204 } | 201 } |
205 | 202 |
206 LayerFactory::LayerTypeSet types = | 203 LayerFactory::LayerTypeSet types = |
207 LayerFactory::getInstance()->getValidLayerTypes(newModel); | 204 LayerFactory::getInstance()->getValidLayerTypes(newModel); |
208 | 205 |
209 if (types.empty()) { | 206 if (types.empty()) { |
210 std::cerr << "WARNING: Document::createLayerForTransformer: no valid display layer for output of transform " << transform.toStdString() << std::endl; | 207 std::cerr << "WARNING: Document::createLayerForTransformer: no valid display layer for output of transform " << transform.getIdentifier().toStdString() << std::endl; |
211 delete newModel; | 208 delete newModel; |
212 return 0; | 209 return 0; |
213 } | 210 } |
214 | 211 |
215 //!!! for now, just use the first suitable layer type | 212 //!!! for now, just use the first suitable layer type |
233 // model pointer in both layers, so they can't actually be cloned. | 230 // model pointer in both layers, so they can't actually be cloned. |
234 | 231 |
235 if (newLayer) { | 232 if (newLayer) { |
236 newLayer->setObjectName(getUniqueLayerName | 233 newLayer->setObjectName(getUniqueLayerName |
237 (TransformFactory::getInstance()-> | 234 (TransformFactory::getInstance()-> |
238 getTransformFriendlyName(transform))); | 235 getTransformFriendlyName |
236 (transform.getIdentifier()))); | |
239 } | 237 } |
240 | 238 |
241 emit layerAdded(newLayer); | 239 emit layerAdded(newLayer); |
242 return newLayer; | 240 return newLayer; |
243 } | 241 } |
291 // std::cerr << "... it uses a model derived from the old main model, regenerating" << std::endl; | 289 // std::cerr << "... it uses a model derived from the old main model, regenerating" << std::endl; |
292 | 290 |
293 // This model was derived from the previous main | 291 // This model was derived from the previous main |
294 // model: regenerate it. | 292 // model: regenerate it. |
295 | 293 |
296 TransformId transform = m_models[model].transform; | 294 const Transform &transform = m_models[model].transform; |
297 PluginTransformer::ExecutionContext context = m_models[model].context; | 295 QString transformId = transform.getIdentifier(); |
298 | 296 |
297 //!!! We have a problem here if the number of channels in | |
298 //the main model has changed. | |
299 | |
299 Model *replacementModel = | 300 Model *replacementModel = |
300 addDerivedModel(transform, | 301 addDerivedModel(transform, |
301 m_mainModel, | 302 ModelTransformer::Input |
302 context, | 303 (m_mainModel, |
303 m_models[model].configurationXml); | 304 m_models[model].channel)); |
304 | 305 |
305 if (!replacementModel) { | 306 if (!replacementModel) { |
306 std::cerr << "WARNING: Document::setMainModel: Failed to regenerate model for transform \"" | 307 std::cerr << "WARNING: Document::setMainModel: Failed to regenerate model for transform \"" |
307 << transform.toStdString() << "\"" << " in layer " << layer << std::endl; | 308 << transformId.toStdString() << "\"" << " in layer " << layer << std::endl; |
308 if (failedTransformers.find(transform) == failedTransformers.end()) { | 309 if (failedTransformers.find(transformId) |
310 == failedTransformers.end()) { | |
309 emit modelRegenerationFailed(layer->objectName(), | 311 emit modelRegenerationFailed(layer->objectName(), |
310 transform); | 312 transformId); |
311 failedTransformers.insert(transform); | 313 failedTransformers.insert(transformId); |
312 } | 314 } |
313 obsoleteLayers.push_back(layer); | 315 obsoleteLayers.push_back(layer); |
314 } else { | 316 } else { |
315 // std::cerr << "Replacing model " << model << " (type " | 317 // std::cerr << "Replacing model " << model << " (type " |
316 // << typeid(*model).name() << ") with model " | 318 // << typeid(*model).name() << ") with model " |
346 // we already emitted modelAboutToBeDeleted for this | 348 // we already emitted modelAboutToBeDeleted for this |
347 delete oldMainModel; | 349 delete oldMainModel; |
348 } | 350 } |
349 | 351 |
350 void | 352 void |
351 Document::addDerivedModel(TransformId transform, | 353 Document::addDerivedModel(const Transform &transform, |
352 Model *inputModel, | 354 const ModelTransformer::Input &input, |
353 const PluginTransformer::ExecutionContext &context, | 355 Model *outputModelToAdd) |
354 Model *outputModelToAdd, | |
355 QString configurationXml) | |
356 { | 356 { |
357 if (m_models.find(outputModelToAdd) != m_models.end()) { | 357 if (m_models.find(outputModelToAdd) != m_models.end()) { |
358 std::cerr << "WARNING: Document::addDerivedModel: Model already added" | 358 std::cerr << "WARNING: Document::addDerivedModel: Model already added" |
359 << std::endl; | 359 << std::endl; |
360 return; | 360 return; |
361 } | 361 } |
362 | 362 |
363 // std::cerr << "Document::addDerivedModel: source is " << inputModel << " \"" << inputModel->objectName().toStdString() << "\"" << std::endl; | 363 // std::cerr << "Document::addDerivedModel: source is " << inputModel << " \"" << inputModel->objectName().toStdString() << "\"" << std::endl; |
364 | 364 |
365 ModelRecord rec; | 365 ModelRecord rec; |
366 rec.source = inputModel; | 366 rec.source = input.getModel(); |
367 rec.channel = input.getChannel(); | |
367 rec.transform = transform; | 368 rec.transform = transform; |
368 rec.context = context; | |
369 rec.configurationXml = configurationXml; | |
370 rec.refcount = 0; | 369 rec.refcount = 0; |
371 | 370 |
372 outputModelToAdd->setSourceModel(inputModel); | 371 outputModelToAdd->setSourceModel(input.getModel()); |
373 | 372 |
374 m_models[outputModelToAdd] = rec; | 373 m_models[outputModelToAdd] = rec; |
375 | 374 |
376 emit modelAdded(outputModelToAdd); | 375 emit modelAdded(outputModelToAdd); |
377 } | 376 } |
386 return; | 385 return; |
387 } | 386 } |
388 | 387 |
389 ModelRecord rec; | 388 ModelRecord rec; |
390 rec.source = 0; | 389 rec.source = 0; |
391 rec.transform = ""; | |
392 rec.refcount = 0; | 390 rec.refcount = 0; |
393 | 391 |
394 m_models[model] = rec; | 392 m_models[model] = rec; |
395 | 393 |
396 if (m_autoAlignment) alignModel(model); | 394 if (m_autoAlignment) alignModel(model); |
397 | 395 |
398 emit modelAdded(model); | 396 emit modelAdded(model); |
399 } | 397 } |
400 | 398 |
401 Model * | 399 Model * |
402 Document::addDerivedModel(TransformId transform, | 400 Document::addDerivedModel(const Transform &transform, |
403 Model *inputModel, | 401 const ModelTransformer::Input &input) |
404 const PluginTransformer::ExecutionContext &context, | |
405 QString configurationXml) | |
406 { | 402 { |
407 Model *model = 0; | 403 Model *model = 0; |
408 | 404 |
409 for (ModelMap::iterator i = m_models.begin(); i != m_models.end(); ++i) { | 405 for (ModelMap::iterator i = m_models.begin(); i != m_models.end(); ++i) { |
410 if (i->second.transform == transform && | 406 if (i->second.transform == transform && |
411 i->second.source == inputModel && | 407 i->second.source == input.getModel() && |
412 i->second.context == context && | 408 i->second.channel == input.getChannel()) { |
413 i->second.configurationXml == configurationXml) { | |
414 return i->first; | 409 return i->first; |
415 } | 410 } |
416 } | 411 } |
417 | 412 |
418 model = ModelTransformerFactory::getInstance()->transform | 413 model = ModelTransformerFactory::getInstance()->transform(transform, input); |
419 (transform, inputModel, context, configurationXml); | |
420 | 414 |
421 if (!model) { | 415 if (!model) { |
422 std::cerr << "WARNING: Document::addDerivedModel: no output model for transform " << transform.toStdString() << std::endl; | 416 std::cerr << "WARNING: Document::addDerivedModel: no output model for transform " << transform.getIdentifier().toStdString() << std::endl; |
423 } else { | 417 } else { |
424 addDerivedModel(transform, inputModel, context, model, configurationXml); | 418 addDerivedModel(transform, input, model); |
425 } | 419 } |
426 | 420 |
427 return model; | 421 return model; |
428 } | 422 } |
429 | 423 |
663 if (!duplicate) return adjusted; | 657 if (!duplicate) return adjusted; |
664 } | 658 } |
665 } | 659 } |
666 | 660 |
667 std::vector<Model *> | 661 std::vector<Model *> |
668 Document::getTransformerInputModels() | 662 Document::getTransformInputModels() |
669 { | 663 { |
670 std::vector<Model *> models; | 664 std::vector<Model *> models; |
671 | 665 |
672 if (!m_mainModel) return models; | 666 if (!m_mainModel) return models; |
673 | 667 |
735 components.push_back(AggregateWaveModel::ModelChannelSpec | 729 components.push_back(AggregateWaveModel::ModelChannelSpec |
736 (rm, -1)); | 730 (rm, -1)); |
737 | 731 |
738 Model *aggregate = new AggregateWaveModel(components); | 732 Model *aggregate = new AggregateWaveModel(components); |
739 | 733 |
740 TransformId id = "vamp:match-vamp-plugin:match:path"; | 734 TransformId id = "vamp:match-vamp-plugin:match:path"; //!!! configure |
741 | 735 |
742 ModelTransformerFactory *factory = ModelTransformerFactory::getInstance(); | 736 TransformFactory *tf = TransformFactory::getInstance(); |
743 | 737 |
744 PluginTransformer::ExecutionContext context = | 738 Transform transform = tf->getDefaultTransformFor |
745 factory->getDefaultContextForTransformer(id, aggregate); | 739 (id, aggregate->getSampleRate()); |
746 context.stepSize = context.blockSize/2; | 740 |
747 | 741 transform.setStepSize(transform.getBlockSize()/2); |
748 QString args = "<plugin param-serialise=\"1\"/>"; | 742 transform.setParameter("serialise", 1); |
749 | 743 |
750 Model *transformOutput = factory->transform(id, aggregate, context, args); | 744 //!!! QString args = "<plugin param-serialise=\"1\"/>"; |
745 // Model *transformOutput = factory->transform(id, aggregate, context, args); | |
746 | |
747 ModelTransformerFactory *mtf = ModelTransformerFactory::getInstance(); | |
748 | |
749 Model *transformOutput = mtf->transform(transform, aggregate); | |
751 | 750 |
752 if (!transformOutput) { | 751 if (!transformOutput) { |
753 context.stepSize = 0; | 752 transform.setStepSize(0); |
754 transformOutput = factory->transform(id, aggregate, context, args); | 753 transformOutput = mtf->transform(transform, aggregate); |
755 } | 754 } |
756 | 755 |
757 SparseTimeValueModel *path = dynamic_cast<SparseTimeValueModel *> | 756 SparseTimeValueModel *path = dynamic_cast<SparseTimeValueModel *> |
758 (transformOutput); | 757 (transformOutput); |
759 | 758 |
924 // as well as making an intelligent guess. | 923 // as well as making an intelligent guess. |
925 | 924 |
926 bool writeModel = true; | 925 bool writeModel = true; |
927 bool haveDerivation = false; | 926 bool haveDerivation = false; |
928 | 927 |
929 if (rec.source && rec.transform != "") { | 928 if (rec.source && rec.transform.getIdentifier() != "") { |
930 haveDerivation = true; | 929 haveDerivation = true; |
931 } | 930 } |
932 | 931 |
933 if (haveDerivation) { | 932 if (haveDerivation) { |
934 if (dynamic_cast<const WritableWaveFileModel *>(model)) { | 933 if (dynamic_cast<const WritableWaveFileModel *>(model)) { |
941 if (writeModel) { | 940 if (writeModel) { |
942 i->first->toXml(out, indent + " "); | 941 i->first->toXml(out, indent + " "); |
943 } | 942 } |
944 | 943 |
945 if (haveDerivation) { | 944 if (haveDerivation) { |
946 | 945 writeBackwardCompatibleDerivation(out, indent + " ", |
947 QString extentsAttributes; | 946 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 } | 947 } |
974 | 948 |
975 //!!! We should probably own the PlayParameterRepository | 949 //!!! We should probably own the PlayParameterRepository |
976 PlayParameters *playParameters = | 950 PlayParameters *playParameters = |
977 PlayParameterRepository::getInstance()->getPlayParameters(i->first); | 951 PlayParameterRepository::getInstance()->getPlayParameters(i->first); |
990 } | 964 } |
991 | 965 |
992 out << indent + "</data>\n"; | 966 out << indent + "</data>\n"; |
993 } | 967 } |
994 | 968 |
995 | 969 void |
970 Document::writeBackwardCompatibleDerivation(QTextStream &out, QString indent, | |
971 Model *targetModel, | |
972 const ModelRecord &rec) const | |
973 { | |
974 // There is a lot of redundancy in the XML we output here, because | |
975 // we want it to work with older SV session file reading code as | |
976 // well. | |
977 // | |
978 // Formerly, a transform was described using a derivation element | |
979 // which set out the source and target models, execution context | |
980 // (step size, input channel etc) and transform id, containing a | |
981 // plugin element which set out the transform parameters and so | |
982 // on. (The plugin element came from a "configurationXml" string | |
983 // obtained from PluginXml.) | |
984 // | |
985 // This has been replaced by a derivation element setting out the | |
986 // source and target models and input channel, containing a | |
987 // transform element which sets out everything in the Transform. | |
988 // | |
989 // In order to retain compatibility with older SV code, however, | |
990 // we have to write out the same stuff into the derivation as | |
991 // before, and manufacture an appropriate plugin element as well | |
992 // as the transform element. In order that newer code knows it's | |
993 // dealing with a newer format, we will also write an attribute | |
994 // 'type="transform"' in the derivation element. | |
995 | |
996 const Transform &transform = rec.transform; | |
997 | |
998 // Just for reference, this is what we would write if we didn't | |
999 // have to be backward compatible: | |
1000 // | |
1001 // out << indent | |
1002 // << QString("<derivation type=\"transform\" source=\"%1\" " | |
1003 // "model=\"%2\" channel=\"%3\">\n") | |
1004 // .arg(XmlExportable::getObjectExportId(rec.source)) | |
1005 // .arg(XmlExportable::getObjectExportId(targetModel)) | |
1006 // .arg(rec.channel); | |
1007 // | |
1008 // transform.toXml(out, indent + " "); | |
1009 // | |
1010 // out << indent << "</derivation>\n"; | |
1011 // | |
1012 // Unfortunately, we can't just do that. So we do this... | |
1013 | |
1014 QString extentsAttributes; | |
1015 if (transform.getStartTime() != RealTime::zeroTime || | |
1016 transform.getDuration() != RealTime::zeroTime) { | |
1017 extentsAttributes = QString("startFrame=\"%1\" duration=\"%2\" ") | |
1018 .arg(RealTime::realTime2Frame(transform.getStartTime(), | |
1019 targetModel->getSampleRate())) | |
1020 .arg(RealTime::realTime2Frame(transform.getDuration(), | |
1021 targetModel->getSampleRate())); | |
1022 } | |
1023 | |
1024 out << indent; | |
1025 out << QString("<derivation type=\"transform\" source=\"%1\" " | |
1026 "model=\"%2\" channel=\"%3\" domain=\"%4\" " | |
1027 "stepSize=\"%5\" blockSize=\"%6\" %7windowType=\"%8\" " | |
1028 "transform=\"%9\">\n") | |
1029 .arg(XmlExportable::getObjectExportId(rec.source)) | |
1030 .arg(XmlExportable::getObjectExportId(targetModel)) | |
1031 .arg(rec.channel) | |
1032 .arg(TransformFactory::getInstance()->getTransformInputDomain | |
1033 (transform.getIdentifier())) | |
1034 .arg(transform.getStepSize()) | |
1035 .arg(transform.getBlockSize()) | |
1036 .arg(extentsAttributes) | |
1037 .arg(int(transform.getWindowType())) | |
1038 .arg(XmlExportable::encodeEntities(transform.getIdentifier())); | |
1039 | |
1040 transform.toXml(out, indent + " "); | |
1041 | |
1042 out << indent << " " | |
1043 << TransformFactory::getInstance()->getPluginConfigurationXml(transform); | |
1044 | |
1045 out << indent << "</derivation>\n"; | |
1046 } | |
1047 |