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