svapp  1.9
Document.cpp
Go to the documentation of this file.
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
00002 
00003 /*
00004     Sonic Visualiser
00005     An audio file viewer and annotation editor.
00006     Centre for Digital Music, Queen Mary, University of London.
00007     This file copyright 2006 Chris Cannam and QMUL.
00008     
00009     This program is free software; you can redistribute it and/or
00010     modify it under the terms of the GNU General Public License as
00011     published by the Free Software Foundation; either version 2 of the
00012     License, or (at your option) any later version.  See the file
00013     COPYING included with this distribution for more information.
00014 */
00015 
00016 #include "Document.h"
00017 
00018 #include "data/model/WaveFileModel.h"
00019 #include "data/model/WritableWaveFileModel.h"
00020 #include "data/model/DenseThreeDimensionalModel.h"
00021 #include "data/model/DenseTimeValueModel.h"
00022 #include "data/model/FlexiNoteModel.h"
00023 
00024 #include "layer/Layer.h"
00025 #include "widgets/CommandHistory.h"
00026 #include "base/Command.h"
00027 #include "view/View.h"
00028 #include "base/PlayParameterRepository.h"
00029 #include "base/PlayParameters.h"
00030 #include "transform/TransformFactory.h"
00031 #include "transform/ModelTransformerFactory.h"
00032 #include "transform/FeatureExtractionModelTransformer.h"
00033 #include <QApplication>
00034 #include <QTextStream>
00035 #include <QSettings>
00036 #include <iostream>
00037 #include <typeinfo>
00038 
00039 // For alignment:
00040 #include "data/model/AggregateWaveModel.h"
00041 #include "data/model/SparseTimeValueModel.h"
00042 #include "data/model/AlignmentModel.h"
00043 
00044 using std::vector;
00045 
00046 //#define DEBUG_DOCUMENT 1
00047 
00049 
00050 Document::Document() :
00051     m_mainModel(0),
00052     m_autoAlignment(false)
00053 {
00054     connect(this, SIGNAL(modelAboutToBeDeleted(Model *)),
00055             ModelTransformerFactory::getInstance(),
00056             SLOT(modelAboutToBeDeleted(Model *)));
00057 }
00058 
00059 Document::~Document()
00060 {
00062     //still refer to it in various places that don't have access to
00063     //the document, be nice to fix that
00064 
00065 #ifdef DEBUG_DOCUMENT
00066     cerr << "\n\nDocument::~Document: about to clear command history" << endl;
00067 #endif
00068     CommandHistory::getInstance()->clear();
00069     
00070 #ifdef DEBUG_DOCUMENT
00071     SVDEBUG << "Document::~Document: about to delete layers" << endl;
00072 #endif
00073     while (!m_layers.empty()) {
00074         deleteLayer(*m_layers.begin(), true);
00075     }
00076 
00077     if (!m_models.empty()) {
00078         SVDEBUG << "Document::~Document: WARNING: " 
00079                   << m_models.size() << " model(s) still remain -- "
00080                   << "should have been garbage collected when deleting layers"
00081                   << endl;
00082         while (!m_models.empty()) {
00083             Model *model = m_models.begin()->first;
00084             if (model == m_mainModel) {
00085                 // just in case!
00086                 SVDEBUG << "Document::~Document: WARNING: Main model is also"
00087                           << " in models list!" << endl;
00088             } else if (model) {
00089                 model->aboutToDelete();
00090                 emit modelAboutToBeDeleted(model);
00091                 delete model;
00092             }
00093             m_models.erase(m_models.begin());
00094         }
00095     }
00096 
00097 #ifdef DEBUG_DOCUMENT
00098     SVDEBUG << "Document::~Document: About to get rid of main model"
00099               << endl;
00100 #endif
00101     if (m_mainModel) {
00102         m_mainModel->aboutToDelete();
00103         emit modelAboutToBeDeleted(m_mainModel);
00104     }
00105 
00106     emit mainModelChanged(0);
00107     delete m_mainModel;
00108 }
00109 
00110 Layer *
00111 Document::createLayer(LayerFactory::LayerType type)
00112 {
00113     Layer *newLayer = LayerFactory::getInstance()->createLayer(type);
00114     if (!newLayer) return 0;
00115 
00116     newLayer->setObjectName(getUniqueLayerName(newLayer->objectName()));
00117 
00118     m_layers.insert(newLayer);
00119 
00120 #ifdef DEBUG_DOCUMENT
00121     SVDEBUG << "Document::createLayer: Added layer of type " << type
00122               << ", now have " << m_layers.size() << " layers" << endl;
00123 #endif
00124 
00125     emit layerAdded(newLayer);
00126 
00127     return newLayer;
00128 }
00129 
00130 Layer *
00131 Document::createMainModelLayer(LayerFactory::LayerType type)
00132 {
00133     Layer *newLayer = createLayer(type);
00134     if (!newLayer) return 0;
00135     setModel(newLayer, m_mainModel);
00136     return newLayer;
00137 }
00138 
00139 Layer *
00140 Document::createImportedLayer(Model *model)
00141 {
00142     LayerFactory::LayerTypeSet types =
00143         LayerFactory::getInstance()->getValidLayerTypes(model);
00144 
00145     if (types.empty()) {
00146         cerr << "WARNING: Document::importLayer: no valid display layer for model" << endl;
00147         return 0;
00148     }
00149 
00151     LayerFactory::LayerType type = *types.begin();
00152 
00153     Layer *newLayer = LayerFactory::getInstance()->createLayer(type);
00154     if (!newLayer) return 0;
00155 
00156     newLayer->setObjectName(getUniqueLayerName(newLayer->objectName()));
00157 
00158     addImportedModel(model);
00159     setModel(newLayer, model);
00160 
00162     setChannel(newLayer, -1);
00163 
00164     m_layers.insert(newLayer);
00165 
00166 #ifdef DEBUG_DOCUMENT
00167     SVDEBUG << "Document::createImportedLayer: Added layer of type " << type
00168               << ", now have " << m_layers.size() << " layers" << endl;
00169 #endif
00170 
00171     emit layerAdded(newLayer);
00172     return newLayer;
00173 }
00174 
00175 Layer *
00176 Document::createEmptyLayer(LayerFactory::LayerType type)
00177 {
00178     if (!m_mainModel) return 0;
00179 
00180     Model *newModel =
00181         LayerFactory::getInstance()->createEmptyModel(type, m_mainModel);
00182     if (!newModel) return 0;
00183 
00184     Layer *newLayer = createLayer(type);
00185     if (!newLayer) {
00186         delete newModel;
00187         return 0;
00188     }
00189 
00190     addImportedModel(newModel);
00191     setModel(newLayer, newModel);
00192 
00193     return newLayer;
00194 }
00195 
00196 Layer *
00197 Document::createDerivedLayer(LayerFactory::LayerType type,
00198                              TransformId transform)
00199 {
00200     Layer *newLayer = createLayer(type);
00201     if (!newLayer) return 0;
00202 
00203     newLayer->setObjectName(getUniqueLayerName
00204                             (TransformFactory::getInstance()->
00205                              getTransformFriendlyName(transform)));
00206 
00207     return newLayer;
00208 }
00209 
00210 Layer *
00211 Document::createDerivedLayer(const Transform &transform,
00212                              const ModelTransformer::Input &input)
00213 {
00214     Transforms transforms;
00215     transforms.push_back(transform);
00216     vector<Layer *> layers = createDerivedLayers(transforms, input);
00217     if (layers.empty()) return 0;
00218     else return layers[0];
00219 }
00220 
00221 vector<Layer *>
00222 Document::createDerivedLayers(const Transforms &transforms,
00223                               const ModelTransformer::Input &input)
00224 {
00225     QString message;
00226     vector<Model *> newModels = addDerivedModels(transforms, input, message, 0);
00227 
00228     if (newModels.empty()) {
00230         emit modelGenerationFailed(transforms[0].getIdentifier(), message);
00231         return vector<Layer *>();
00232     } else if (message != "") {
00234         emit modelGenerationWarning(transforms[0].getIdentifier(), message);
00235     }
00236 
00237     QStringList names;
00238     for (int i = 0; i < (int)newModels.size(); ++i) {
00239         names.push_back(getUniqueLayerName
00240                         (TransformFactory::getInstance()->
00241                          getTransformFriendlyName
00242                          (transforms[i].getIdentifier())));
00243     }
00244 
00245     vector<Layer *> layers = createLayersForDerivedModels(newModels, names);
00246     return layers;
00247 }
00248 
00249 class AdditionalModelConverter : 
00250     public ModelTransformerFactory::AdditionalModelHandler
00251 {
00252 public:
00253     AdditionalModelConverter(Document *doc, 
00254                              Document::LayerCreationHandler *handler) :
00255         m_doc(doc),
00256         m_handler(handler) {
00257     }
00258 
00259     virtual ~AdditionalModelConverter() { }
00260 
00261     void
00262     setPrimaryLayers(vector<Layer *> layers) {
00263         m_primary = layers;
00264     }
00265 
00266     void
00267     moreModelsAvailable(vector<Model *> models) {
00268         std::cerr << "AdditionalModelConverter::moreModelsAvailable: " << models.size() << " model(s)" << std::endl;
00269         // We can't automatically regenerate the additional models on
00270         // reload -- we should delete them instead
00271         QStringList names;
00272         foreach (Model *model, models) {
00273             m_doc->addAdditionalModel(model);
00274             names.push_back(QString());
00275         }
00276         vector<Layer *> layers = m_doc->createLayersForDerivedModels
00277             (models, names);
00278         m_handler->layersCreated(this, m_primary, layers);
00279         delete this;
00280     }
00281 
00282     void
00283     noMoreModelsAvailable() {
00284         std::cerr << "AdditionalModelConverter::noMoreModelsAvailable" << std::endl;
00285         m_handler->layersCreated(this, m_primary, vector<Layer *>());
00286         delete this;
00287     }
00288 
00289     void cancel() {
00290         foreach (Layer *layer, m_primary) {
00291             Model *model = layer->getModel();
00292             if (model) {
00293                 model->abandon();
00294             }
00295         }
00296     }
00297 
00298 private:
00299     Document *m_doc;
00300     vector<Layer *> m_primary;
00301     Document::LayerCreationHandler *m_handler; 
00302 };
00303 
00304 Document::LayerCreationAsyncHandle
00305 Document::createDerivedLayersAsync(const Transforms &transforms,
00306                                    const ModelTransformer::Input &input,
00307                                    LayerCreationHandler *handler)
00308 {
00309     QString message;
00310 
00311     AdditionalModelConverter *amc = new AdditionalModelConverter(this, handler);
00312     
00313     vector<Model *> newModels = addDerivedModels
00314         (transforms, input, message, amc);
00315 
00316     QStringList names;
00317     for (int i = 0; i < (int)newModels.size(); ++i) {
00318         names.push_back(getUniqueLayerName
00319                         (TransformFactory::getInstance()->
00320                          getTransformFriendlyName
00321                          (transforms[i].getIdentifier())));
00322     }
00323 
00324     vector<Layer *> layers = createLayersForDerivedModels(newModels, names);
00325     amc->setPrimaryLayers(layers);
00326 
00327     if (newModels.empty()) {
00329         emit modelGenerationFailed(transforms[0].getIdentifier(), message);
00331     } else if (message != "") {
00333         emit modelGenerationWarning(transforms[0].getIdentifier(), message);
00335     }
00336 
00337     return amc;
00338 }
00339 
00340 void
00341 Document::cancelAsyncLayerCreation(Document::LayerCreationAsyncHandle h)
00342 {
00343     AdditionalModelConverter *conv = static_cast<AdditionalModelConverter *>(h);
00344     conv->cancel();
00345 }
00346 
00347 vector<Layer *>
00348 Document::createLayersForDerivedModels(vector<Model *> newModels, 
00349                                        QStringList names)
00350 {
00351     vector<Layer *> layers;
00352     
00353     for (int i = 0; i < (int)newModels.size(); ++i) {
00354 
00355         Model *newModel = newModels[i];
00356 
00357         LayerFactory::LayerTypeSet types =
00358             LayerFactory::getInstance()->getValidLayerTypes(newModel);
00359 
00360         if (types.empty()) {
00361             cerr << "WARNING: Document::createLayerForTransformer: no valid display layer for output of transform " << names[i] << endl;
00363             newModel->aboutToDelete();
00364             emit modelAboutToBeDeleted(newModel);
00365             m_models.erase(newModel);
00366             delete newModel;
00367             return vector<Layer *>();
00368         }
00369 
00371 
00372         Layer *newLayer = createLayer(*types.begin());
00373         setModel(newLayer, newModel);
00374 
00376         //can be edited without affecting other layers that are based on
00377         //the same model.  Unfortunately we can't just clone it now,
00378         //because it probably hasn't been completed yet -- the transform
00379         //runs in the background.  Maybe the transform has to handle
00380         //cloning and cacheing models itself.
00381         //
00382         // Once we do clone models here, of course, we'll have to avoid
00383         // leaking them too.
00384         //
00385         // We want the user to be able to add a model to a second layer
00386         // _while it's still being calculated in the first_ and have it
00387         // work quickly.  That means we need to put the same physical
00388         // model pointer in both layers, so they can't actually be cloned.
00389     
00390         if (newLayer) {
00391             newLayer->setObjectName(names[i]);
00392         }
00393 
00394         emit layerAdded(newLayer);
00395         layers.push_back(newLayer);
00396     }
00397 
00398     return layers;
00399 }
00400 
00401 void
00402 Document::setMainModel(WaveFileModel *model)
00403 {
00404     Model *oldMainModel = m_mainModel;
00405     m_mainModel = model;
00406     
00407     emit modelAdded(m_mainModel);
00408     if (model) {
00409         emit activity(tr("Set main model to %1").arg(model->objectName()));
00410     } else {
00411         emit activity(tr("Clear main model"));
00412     }
00413 
00414     std::vector<Layer *> obsoleteLayers;
00415     std::set<QString> failedTransformers;
00416 
00417     // We need to ensure that no layer is left using oldMainModel or
00418     // any of the old derived models as its model.  Either replace the
00419     // model, or delete the layer for each layer that is currently
00420     // using one of these.  Carry out this replacement before we
00421     // delete any of the models.
00422 
00423 #ifdef DEBUG_DOCUMENT
00424     cerr << "Document::setMainModel: Have "
00425               << m_layers.size() << " layers" << endl;
00426     cerr << "Models now: ";
00427     for (ModelMap::const_iterator i = m_models.begin(); i != m_models.end(); ++i) {
00428         cerr << i->first << " ";
00429     } 
00430     cerr << endl;
00431     cerr << "Old main model: " << oldMainModel << endl;
00432 #endif
00433 
00434     for (LayerSet::iterator i = m_layers.begin(); i != m_layers.end(); ++i) {
00435 
00436         Layer *layer = *i;
00437         Model *model = layer->getModel();
00438 
00439 #ifdef DEBUG_DOCUMENT
00440         cerr << "Document::setMainModel: inspecting model "
00441                   << (model ? model->objectName(): "(null)") << " in layer "
00442                   << layer->objectName() << endl;
00443 #endif
00444 
00445         if (model == oldMainModel) {
00446 #ifdef DEBUG_DOCUMENT
00447             cerr << "... it uses the old main model, replacing" << endl;
00448 #endif
00449             LayerFactory::getInstance()->setModel(layer, m_mainModel);
00450             continue;
00451         }
00452 
00453         if (!model) {
00454             cerr << "WARNING: Document::setMainModel: Null model in layer "
00455                       << layer << endl;
00456             // get rid of this hideous degenerate
00457             obsoleteLayers.push_back(layer);
00458             continue;
00459         }
00460 
00461         if (m_models.find(model) == m_models.end()) {
00462             cerr << "WARNING: Document::setMainModel: Unknown model "
00463                       << model << " in layer " << layer << endl;
00464             // and this one
00465             obsoleteLayers.push_back(layer);
00466             continue;
00467         }
00468             
00469         if (m_models[model].source &&
00470             (m_models[model].source == oldMainModel)) {
00471 
00472 #ifdef DEBUG_DOCUMENT
00473             cerr << "... it uses a model derived from the old main model, regenerating" << endl;
00474 #endif
00475 
00476             // This model was derived from the previous main
00477             // model: regenerate it.
00478             
00479             const Transform &transform = m_models[model].transform;
00480             QString transformId = transform.getIdentifier();
00481             
00483             //the main model has changed.
00484 
00485             QString message;
00486             Model *replacementModel =
00487                 addDerivedModel(transform,
00488                                 ModelTransformer::Input
00489                                 (m_mainModel, m_models[model].channel),
00490                                 message);
00491             
00492             if (!replacementModel) {
00493                 cerr << "WARNING: Document::setMainModel: Failed to regenerate model for transform \""
00494                           << transformId << "\"" << " in layer " << layer << endl;
00495                 if (failedTransformers.find(transformId)
00496                     == failedTransformers.end()) {
00497                     emit modelRegenerationFailed(layer->objectName(),
00498                                                  transformId,
00499                                                  message);
00500                     failedTransformers.insert(transformId);
00501                 }
00502                 obsoleteLayers.push_back(layer);
00503             } else {
00504                 if (message != "") {
00505                     emit modelRegenerationWarning(layer->objectName(),
00506                                                   transformId,
00507                                                   message);
00508                 }
00509 #ifdef DEBUG_DOCUMENT
00510                 cerr << "Replacing model " << model << " (type "
00511                           << typeid(*model).name() << ") with model "
00512                           << replacementModel << " (type "
00513                           << typeid(*replacementModel).name() << ") in layer "
00514                           << layer << " (name " << layer->objectName() << ")"
00515                           << endl;
00516 
00517                 RangeSummarisableTimeValueModel *rm =
00518                     dynamic_cast<RangeSummarisableTimeValueModel *>(replacementModel);
00519                 if (rm) {
00520                     cerr << "new model has " << rm->getChannelCount() << " channels " << endl;
00521                 } else {
00522                     cerr << "new model " << replacementModel << " is not a RangeSummarisableTimeValueModel!" << endl;
00523                 }
00524 #endif
00525                 setModel(layer, replacementModel);
00526             }
00527         }           
00528     }
00529 
00530     for (size_t k = 0; k < obsoleteLayers.size(); ++k) {
00531         deleteLayer(obsoleteLayers[k], true);
00532     }
00533 
00534     for (ModelMap::iterator i = m_models.begin(); i != m_models.end(); ++i) {
00535         if (i->second.additional) {
00536             Model *m = i->first;
00537             emit modelAboutToBeDeleted(m);
00538             delete m;
00539         }
00540     }
00541 
00542     for (ModelMap::iterator i = m_models.begin(); i != m_models.end(); ++i) {
00543 
00544         Model *m = i->first;
00545 
00546 #ifdef DEBUG_DOCUMENT
00547         SVDEBUG << "considering alignment for model " << m << " (name \""
00548                   << m->objectName() << "\")" << endl;
00549 #endif
00550 
00551         if (m_autoAlignment) {
00552 
00553             alignModel(m);
00554 
00555         } else if (oldMainModel &&
00556                    (m->getAlignmentReference() == oldMainModel)) {
00557 
00558             alignModel(m);
00559         }
00560     }
00561 
00562     if (oldMainModel) {
00563         oldMainModel->aboutToDelete();
00564         emit modelAboutToBeDeleted(oldMainModel);
00565     }
00566 
00567     if (m_autoAlignment) {
00568         SVDEBUG << "Document::setMainModel: auto-alignment is on, aligning model if possible" << endl;
00569         alignModel(m_mainModel);
00570     }
00571 
00572     emit mainModelChanged(m_mainModel);
00573 
00574     delete oldMainModel;
00575 }
00576 
00577 void
00578 Document::addAlreadyDerivedModel(const Transform &transform,
00579                                  const ModelTransformer::Input &input,
00580                                  Model *outputModelToAdd)
00581 {
00582     if (m_models.find(outputModelToAdd) != m_models.end()) {
00583         cerr << "WARNING: Document::addAlreadyDerivedModel: Model already added"
00584                   << endl;
00585         return;
00586     }
00587 
00588 #ifdef DEBUG_DOCUMENT
00589     if (input.getModel()) {
00590         cerr << "Document::addAlreadyDerivedModel: source is " << input.getModel() << " \"" << input.getModel()->objectName() << "\"" << endl;
00591     } else {
00592         cerr << "Document::addAlreadyDerivedModel: source is " << input.getModel() << endl;
00593     }
00594 #endif
00595 
00596     ModelRecord rec;
00597     rec.source = input.getModel();
00598     rec.channel = input.getChannel();
00599     rec.transform = transform;
00600     rec.additional = false;
00601     rec.refcount = 0;
00602 
00603     outputModelToAdd->setSourceModel(input.getModel());
00604 
00605     m_models[outputModelToAdd] = rec;
00606 
00607 #ifdef DEBUG_DOCUMENT
00608     cerr << "Document::addAlreadyDerivedModel: Added model " << outputModelToAdd << endl;
00609     cerr << "Models now: ";
00610     for (ModelMap::const_iterator i = m_models.begin(); i != m_models.end(); ++i) {
00611         cerr << i->first << " ";
00612     } 
00613     cerr << endl;
00614 #endif
00615 
00616     emit modelAdded(outputModelToAdd);
00617 }
00618 
00619 
00620 void
00621 Document::addImportedModel(Model *model)
00622 {
00623     if (m_models.find(model) != m_models.end()) {
00624         cerr << "WARNING: Document::addImportedModel: Model already added"
00625                   << endl;
00626         return;
00627     }
00628 
00629     ModelRecord rec;
00630     rec.source = 0;
00631     rec.channel = 0;
00632     rec.refcount = 0;
00633     rec.additional = false;
00634 
00635     m_models[model] = rec;
00636 
00637 #ifdef DEBUG_DOCUMENT
00638     SVDEBUG << "Document::addImportedModel: Added model " << model << endl;
00639     cerr << "Models now: ";
00640     for (ModelMap::const_iterator i = m_models.begin(); i != m_models.end(); ++i) {
00641         cerr << i->first << " ";
00642     } 
00643     cerr << endl;
00644 #endif
00645 
00646     if (m_autoAlignment) {
00647         SVDEBUG << "Document::addImportedModel: auto-alignment is on, aligning model if possible" << endl;
00648         alignModel(model);
00649     } else {
00650         SVDEBUG << "Document(" << this << "): addImportedModel: auto-alignment is off" << endl;
00651     }
00652 
00653     emit modelAdded(model);
00654 }
00655 
00656 void
00657 Document::addAdditionalModel(Model *model)
00658 {
00659     if (m_models.find(model) != m_models.end()) {
00660         cerr << "WARNING: Document::addAdditionalModel: Model already added"
00661                   << endl;
00662         return;
00663     }
00664 
00665     ModelRecord rec;
00666     rec.source = 0;
00667     rec.channel = 0;
00668     rec.refcount = 0;
00669     rec.additional = true;
00670 
00671     m_models[model] = rec;
00672 
00673 #ifdef DEBUG_DOCUMENT
00674     SVDEBUG << "Document::addAdditionalModel: Added model " << model << endl;
00675     cerr << "Models now: ";
00676     for (ModelMap::const_iterator i = m_models.begin(); i != m_models.end(); ++i) {
00677         cerr << i->first << " ";
00678     } 
00679     cerr << endl;
00680 #endif
00681 
00682     if (m_autoAlignment) {
00683         SVDEBUG << "Document::addAdditionalModel: auto-alignment is on, aligning model if possible" << endl;
00684         alignModel(model);
00685     }
00686 
00687     emit modelAdded(model);
00688 }
00689 
00690 Model *
00691 Document::addDerivedModel(const Transform &transform,
00692                           const ModelTransformer::Input &input,
00693                           QString &message)
00694 {
00695     for (ModelMap::iterator i = m_models.begin(); i != m_models.end(); ++i) {
00696         if (i->second.transform == transform &&
00697             i->second.source == input.getModel() && 
00698             i->second.channel == input.getChannel()) {
00699             std::cerr << "derived model taken from map " << std::endl;
00700             return i->first;
00701         }
00702     }
00703 
00704     Transforms tt;
00705     tt.push_back(transform);
00706     vector<Model *> mm = addDerivedModels(tt, input, message, 0);
00707     if (mm.empty()) return 0;
00708     else return mm[0];
00709 }
00710 
00711 vector<Model *>
00712 Document::addDerivedModels(const Transforms &transforms,
00713                            const ModelTransformer::Input &input,
00714                            QString &message,
00715                            AdditionalModelConverter *amc)
00716 {
00717     vector<Model *> mm = 
00718         ModelTransformerFactory::getInstance()->transformMultiple
00719         (transforms, input, message, amc);
00720 
00721     for (int j = 0; j < (int)mm.size(); ++j) {
00722 
00723         Model *model = mm[j];
00724 
00725         // The transform we actually used was presumably identical to
00726         // the one asked for, except that the version of the plugin
00727         // may differ.  It's possible that the returned message
00728         // contains a warning about this; that doesn't concern us
00729         // here, but we do need to ensure that the transform we
00730         // remember is correct for what was actually applied, with the
00731         // current plugin version.
00732 
00733         Transform applied = transforms[j];
00734         applied.setPluginVersion
00735             (TransformFactory::getInstance()->
00736              getDefaultTransformFor(applied.getIdentifier(),
00737                                     lrintf(applied.getSampleRate()))
00738              .getPluginVersion());
00739 
00740         if (!model) {
00741             cerr << "WARNING: Document::addDerivedModel: no output model for transform " << applied.getIdentifier() << endl;
00742         } else {
00743             addAlreadyDerivedModel(applied, input, model);
00744         }
00745     }
00746         
00747     return mm;
00748 }
00749 
00750 void
00751 Document::releaseModel(Model *model) // Will _not_ release main model!
00752 {
00753     if (model == 0) {
00754         return;
00755     }
00756 
00757     if (model == m_mainModel) {
00758         return;
00759     }
00760 
00761     bool toDelete = false;
00762 
00763     if (m_models.find(model) != m_models.end()) {
00764         
00765         if (m_models[model].refcount == 0) {
00766             cerr << "WARNING: Document::releaseModel: model " << model
00767                       << " reference count is zero already!" << endl;
00768         } else {
00769             if (--m_models[model].refcount == 0) {
00770                 toDelete = true;
00771             }
00772         }
00773     } else { 
00774         cerr << "WARNING: Document::releaseModel: Unfound model "
00775                   << model << endl;
00776         toDelete = true;
00777     }
00778 
00779     if (toDelete) {
00780 
00781         int sourceCount = 0;
00782 
00783         for (ModelMap::iterator i = m_models.begin(); i != m_models.end(); ++i) {
00784             if (i->second.source == model) {
00785                 ++sourceCount;
00786                 i->second.source = 0;
00787             }
00788         }
00789 
00790         if (sourceCount > 0) {
00791             SVDEBUG << "Document::releaseModel: Deleting model "
00792                       << model << " even though it is source for "
00793                       << sourceCount << " other derived model(s) -- resetting "
00794                       << "their source fields appropriately" << endl;
00795         }
00796 
00797         model->aboutToDelete();
00798         emit modelAboutToBeDeleted(model);
00799         m_models.erase(model);
00800 
00801 #ifdef DEBUG_DOCUMENT
00802         SVDEBUG << "Document::releaseModel: Deleted model " << model << endl;
00803         cerr << "Models now: ";
00804         for (ModelMap::const_iterator i = m_models.begin(); i != m_models.end(); ++i) {
00805             cerr << i->first << " ";
00806         } 
00807         cerr << endl;
00808 #endif
00809 
00810         delete model;
00811     }
00812 }
00813 
00814 void
00815 Document::deleteLayer(Layer *layer, bool force)
00816 {
00817     if (m_layerViewMap.find(layer) != m_layerViewMap.end() &&
00818         m_layerViewMap[layer].size() > 0) {
00819 
00820         cerr << "WARNING: Document::deleteLayer: Layer "
00821                   << layer << " [" << layer->objectName() << "]"
00822                   << " is still used in " << m_layerViewMap[layer].size()
00823                   << " views!" << endl;
00824 
00825         if (force) {
00826 
00827 #ifdef DEBUG_DOCUMENT
00828             cerr << "(force flag set -- deleting from all views)" << endl;
00829 #endif
00830 
00831             for (std::set<View *>::iterator j = m_layerViewMap[layer].begin();
00832                  j != m_layerViewMap[layer].end(); ++j) {
00833                 // don't use removeLayerFromView, as it issues a command
00834                 layer->setLayerDormant(*j, true);
00835                 (*j)->removeLayer(layer);
00836             }
00837             
00838             m_layerViewMap.erase(layer);
00839 
00840         } else {
00841             return;
00842         }
00843     }
00844 
00845     if (m_layers.find(layer) == m_layers.end()) {
00846         SVDEBUG << "Document::deleteLayer: Layer "
00847                   << layer << " (" << typeid(layer).name() <<
00848                   ") does not exist, or has already been deleted "
00849                   << "(this may not be as serious as it sounds)" << endl;
00850         return;
00851     }
00852 
00853     m_layers.erase(layer);
00854 
00855 #ifdef DEBUG_DOCUMENT
00856     SVDEBUG << "Document::deleteLayer: Removing, now have "
00857               << m_layers.size() << " layers" << endl;
00858 #endif
00859 
00860     releaseModel(layer->getModel());
00861     emit layerRemoved(layer);
00862     emit layerAboutToBeDeleted(layer);
00863     delete layer;
00864 }
00865 
00866 void
00867 Document::setModel(Layer *layer, Model *model)
00868 {
00869     if (model && 
00870         model != m_mainModel &&
00871         m_models.find(model) == m_models.end()) {
00872         cerr << "ERROR: Document::setModel: Layer " << layer
00873                   << " (\"" << layer->objectName()
00874                   << "\") wants to use unregistered model " << model
00875                   << ": register the layer's model before setting it!"
00876                   << endl;
00877         return;
00878     }
00879 
00880     Model *previousModel = layer->getModel();
00881 
00882     if (previousModel == model) {
00883         SVDEBUG << "NOTE: Document::setModel: Layer " << layer << " (\""
00884                   << layer->objectName()                  << "\") is already set to model "
00885                   << model << " (\""
00886                   << (model ? model->objectName(): "(null)")
00887                   << "\")" << endl;
00888         return;
00889     }
00890 
00891     if (model && model != m_mainModel) {
00892         m_models[model].refcount ++;
00893     }
00894 
00895     if (model && previousModel) {
00896         PlayParameterRepository::getInstance()->copyParameters
00897             (previousModel, model);
00898     }
00899 
00900     LayerFactory::getInstance()->setModel(layer, model);
00901         // std::cerr << "layer type: " << LayerFactory::getInstance()->getLayerTypeName(LayerFactory::getInstance()->getLayerType(layer)) << std::endl;
00902 
00903     if (previousModel) {
00904         releaseModel(previousModel);
00905     }
00906 }
00907 
00908 void
00909 Document::setChannel(Layer *layer, int channel)
00910 {
00911     LayerFactory::getInstance()->setChannel(layer, channel);
00912 }
00913 
00914 void
00915 Document::addLayerToView(View *view, Layer *layer)
00916 {
00917     Model *model = layer->getModel();
00918     if (!model) {
00919 #ifdef DEBUG_DOCUMENT
00920         SVDEBUG << "Document::addLayerToView: Layer (\""
00921                   << layer->objectName()                  << "\") with no model being added to view: "
00922                   << "normally you want to set the model first" << endl;
00923 #endif
00924     } else {
00925         if (model != m_mainModel &&
00926             m_models.find(model) == m_models.end()) {
00927             cerr << "ERROR: Document::addLayerToView: Layer " << layer
00928                       << " has unregistered model " << model
00929                       << " -- register the layer's model before adding the layer!" << endl;
00930             return;
00931         }
00932     }
00933 
00934     CommandHistory::getInstance()->addCommand
00935         (new Document::AddLayerCommand(this, view, layer));
00936 }
00937 
00938 void
00939 Document::removeLayerFromView(View *view, Layer *layer)
00940 {
00941     CommandHistory::getInstance()->addCommand
00942         (new Document::RemoveLayerCommand(this, view, layer));
00943 }
00944 
00945 void
00946 Document::addToLayerViewMap(Layer *layer, View *view)
00947 {
00948     bool firstView = (m_layerViewMap.find(layer) == m_layerViewMap.end() ||
00949                       m_layerViewMap[layer].empty());
00950 
00951     if (m_layerViewMap[layer].find(view) !=
00952         m_layerViewMap[layer].end()) {
00953         cerr << "WARNING: Document::addToLayerViewMap:"
00954                   << " Layer " << layer << " -> view " << view << " already in"
00955                   << " layer view map -- internal inconsistency" << endl;
00956     }
00957 
00958     m_layerViewMap[layer].insert(view);
00959 
00960     if (firstView) emit layerInAView(layer, true);
00961 }
00962     
00963 void
00964 Document::removeFromLayerViewMap(Layer *layer, View *view)
00965 {
00966     if (m_layerViewMap[layer].find(view) ==
00967         m_layerViewMap[layer].end()) {
00968         cerr << "WARNING: Document::removeFromLayerViewMap:"
00969                   << " Layer " << layer << " -> view " << view << " not in"
00970                   << " layer view map -- internal inconsistency" << endl;
00971     }
00972 
00973     m_layerViewMap[layer].erase(view);
00974 
00975     if (m_layerViewMap[layer].empty()) {
00976         m_layerViewMap.erase(layer);
00977         emit layerInAView(layer, false);
00978     }
00979 }
00980 
00981 QString
00982 Document::getUniqueLayerName(QString candidate)
00983 {
00984     for (int count = 1; ; ++count) {
00985 
00986         QString adjusted =
00987             (count > 1 ? QString("%1 <%2>").arg(candidate).arg(count) :
00988              candidate);
00989         
00990         bool duplicate = false;
00991 
00992         for (LayerSet::iterator i = m_layers.begin(); i != m_layers.end(); ++i) {
00993             if ((*i)->objectName() == adjusted) {
00994                 duplicate = true;
00995                 break;
00996             }
00997         }
00998 
00999         if (!duplicate) return adjusted;
01000     }
01001 }
01002 
01003 std::vector<Model *>
01004 Document::getTransformInputModels()
01005 {
01006     std::vector<Model *> models;
01007 
01008     if (!m_mainModel) return models;
01009 
01010     models.push_back(m_mainModel);
01011 
01013 
01014     for (ModelMap::iterator i = m_models.begin(); i != m_models.end(); ++i) {
01015 
01016         Model *model = i->first;
01017         if (!model || model == m_mainModel) continue;
01018         DenseTimeValueModel *dtvm = dynamic_cast<DenseTimeValueModel *>(model);
01019         
01020         if (dtvm) {
01021             models.push_back(dtvm);
01022         }
01023     }
01024 
01025     return models;
01026 }
01027 
01028 bool
01029 Document::isKnownModel(const Model *model) const
01030 {
01031     if (model == m_mainModel) return true;
01032     return (m_models.find(const_cast<Model *>(model)) != m_models.end());
01033 }
01034 
01035 TransformId
01036 Document::getAlignmentTransformName()
01037 {
01038     QSettings settings;
01039     settings.beginGroup("Alignment");
01040     TransformId id =
01041         settings.value("transform-id",
01042                        "vamp:match-vamp-plugin:match:path").toString();
01043     settings.endGroup();
01044     return id;
01045 }
01046 
01047 bool
01048 Document::canAlign() 
01049 {
01050     TransformId id = getAlignmentTransformName();
01051     TransformFactory *factory = TransformFactory::getInstance();
01052     return factory->haveTransform(id);
01053 }
01054 
01055 void
01056 Document::alignModel(Model *model)
01057 {
01058     SVDEBUG << "Document::alignModel(" << model << ")" << endl;
01059 
01060     if (!m_mainModel) {
01061         SVDEBUG << "(no main model to align to)" << endl;
01062         return;
01063     }
01064 
01065     RangeSummarisableTimeValueModel *rm = 
01066         dynamic_cast<RangeSummarisableTimeValueModel *>(model);
01067     if (!rm) {
01068         SVDEBUG << "(main model is not alignable-to)" << endl;
01069         return;
01070     }
01071 
01072     if (rm->getAlignmentReference() == m_mainModel) {
01073         SVDEBUG << "(model " << rm << " is already aligned to main model " << m_mainModel << ")" << endl;
01074         return;
01075     }
01076     
01077     if (model == m_mainModel) {
01078         // The reference has an empty alignment to itself.  This makes
01079         // it possible to distinguish between the reference and any
01080         // unaligned model just by looking at the model itself,
01081         // without also knowing what the main model is
01082         SVDEBUG << "Document::alignModel(" << model << "): is main model, setting appropriately" << endl;
01083         rm->setAlignment(new AlignmentModel(model, model, 0, 0));
01084         return;
01085     }
01086 
01087     // This involves creating three new models:
01088 
01089     // 1. an AggregateWaveModel to provide the mixdowns of the main
01090     // model and the new model in its two channels, as input to the
01091     // MATCH plugin
01092 
01093     // 2. a SparseTimeValueModel, which is the model automatically
01094     // created by FeatureExtractionPluginTransformer when running the
01095     // MATCH plugin (thus containing the alignment path)
01096 
01097     // 3. an AlignmentModel, which stores the path model and carries
01098     // out alignment lookups on it.
01099 
01100     // The first two of these are provided as arguments to the
01101     // constructor for the third, which takes responsibility for
01102     // deleting them.  The AlignmentModel, meanwhile, is passed to the
01103     // new model we are aligning, which also takes responsibility for
01104     // it.  We should not have to delete any of these new models here.
01105 
01106     AggregateWaveModel::ChannelSpecList components;
01107 
01108     components.push_back(AggregateWaveModel::ModelChannelSpec
01109                          (m_mainModel, -1));
01110 
01111     components.push_back(AggregateWaveModel::ModelChannelSpec
01112                          (rm, -1));
01113 
01114     Model *aggregateModel = new AggregateWaveModel(components);
01115     ModelTransformer::Input aggregate(aggregateModel);
01116 
01117     TransformId id = "vamp:match-vamp-plugin:match:path"; 
01118     
01119     TransformFactory *tf = TransformFactory::getInstance();
01120 
01121     Transform transform = tf->getDefaultTransformFor
01122         (id, aggregateModel->getSampleRate());
01123 
01124     transform.setStepSize(transform.getBlockSize()/2);
01125     transform.setParameter("serialise", 1);
01126 
01127     SVDEBUG << "Document::alignModel: Alignment transform step size " << transform.getStepSize() << ", block size " << transform.getBlockSize() << endl;
01128 
01129     ModelTransformerFactory *mtf = ModelTransformerFactory::getInstance();
01130 
01131     QString message;
01132     Model *transformOutput = mtf->transform(transform, aggregate, message);
01133 
01134     if (!transformOutput) {
01135         transform.setStepSize(0);
01136         transformOutput = mtf->transform(transform, aggregate, message);
01137     }
01138 
01139     SparseTimeValueModel *path = dynamic_cast<SparseTimeValueModel *>
01140         (transformOutput);
01141 
01142     if (!path) {
01143         cerr << "Document::alignModel: ERROR: Failed to create alignment path (no MATCH plugin?)" << endl;
01144         emit alignmentFailed(id, message);
01145         delete transformOutput;
01146         delete aggregateModel;
01147         return;
01148     }
01149 
01150     path->setCompletion(0);
01151 
01152     AlignmentModel *alignmentModel = new AlignmentModel
01153         (m_mainModel, model, aggregateModel, path);
01154 
01155     rm->setAlignment(alignmentModel);
01156 }
01157 
01158 void
01159 Document::alignModels()
01160 {
01161     for (ModelMap::iterator i = m_models.begin(); i != m_models.end(); ++i) {
01162         alignModel(i->first);
01163     }
01164     alignModel(m_mainModel);
01165 }
01166 
01167 Document::AddLayerCommand::AddLayerCommand(Document *d,
01168                                            View *view,
01169                                            Layer *layer) :
01170     m_d(d),
01171     m_view(view),
01172     m_layer(layer),
01173     m_name(qApp->translate("AddLayerCommand", "Add %1 Layer").arg(layer->objectName())),
01174     m_added(false)
01175 {
01176 }
01177 
01178 Document::AddLayerCommand::~AddLayerCommand()
01179 {
01180 #ifdef DEBUG_DOCUMENT
01181     SVDEBUG << "Document::AddLayerCommand::~AddLayerCommand" << endl;
01182 #endif
01183     if (!m_added) {
01184         m_d->deleteLayer(m_layer);
01185     }
01186 }
01187 
01188 QString
01189 Document::AddLayerCommand::getName() const
01190 {
01191 #ifdef DEBUG_DOCUMENT
01192     SVDEBUG << "Document::AddLayerCommand::getName(): Name is "
01193               << m_name << endl;
01194 #endif
01195     return m_name;
01196 }
01197 
01198 void
01199 Document::AddLayerCommand::execute()
01200 {
01201     for (int i = 0; i < m_view->getLayerCount(); ++i) {
01202         if (m_view->getLayer(i) == m_layer) {
01203             // already there
01204             m_layer->setLayerDormant(m_view, false);
01205             m_added = true;
01206             return;
01207         }
01208     }
01209 
01210     m_view->addLayer(m_layer);
01211     m_layer->setLayerDormant(m_view, false);
01212 
01213     m_d->addToLayerViewMap(m_layer, m_view);
01214     m_added = true;
01215 }
01216 
01217 void
01218 Document::AddLayerCommand::unexecute()
01219 {
01220     m_view->removeLayer(m_layer);
01221     m_layer->setLayerDormant(m_view, true);
01222 
01223     m_d->removeFromLayerViewMap(m_layer, m_view);
01224     m_added = false;
01225 }
01226 
01227 Document::RemoveLayerCommand::RemoveLayerCommand(Document *d,
01228                                                  View *view,
01229                                                  Layer *layer) :
01230     m_d(d),
01231     m_view(view),
01232     m_layer(layer),
01233     m_wasDormant(layer->isLayerDormant(view)),
01234     m_name(qApp->translate("RemoveLayerCommand", "Delete %1 Layer").arg(layer->objectName())),
01235     m_added(true)
01236 {
01237 }
01238 
01239 Document::RemoveLayerCommand::~RemoveLayerCommand()
01240 {
01241 #ifdef DEBUG_DOCUMENT
01242     SVDEBUG << "Document::RemoveLayerCommand::~RemoveLayerCommand" << endl;
01243 #endif
01244     if (!m_added) {
01245         m_d->deleteLayer(m_layer);
01246     }
01247 }
01248 
01249 QString
01250 Document::RemoveLayerCommand::getName() const
01251 {
01252 #ifdef DEBUG_DOCUMENT
01253     SVDEBUG << "Document::RemoveLayerCommand::getName(): Name is "
01254               << m_name << endl;
01255 #endif
01256     return m_name;
01257 }
01258 
01259 void
01260 Document::RemoveLayerCommand::execute()
01261 {
01262     bool have = false;
01263     for (int i = 0; i < m_view->getLayerCount(); ++i) {
01264         if (m_view->getLayer(i) == m_layer) {
01265             have = true;
01266             break;
01267         }
01268     }
01269 
01270     if (!have) { // not there!
01271         m_layer->setLayerDormant(m_view, true);
01272         m_added = false;
01273         return;
01274     }
01275 
01276     m_view->removeLayer(m_layer);
01277     m_layer->setLayerDormant(m_view, true);
01278 
01279     m_d->removeFromLayerViewMap(m_layer, m_view);
01280     m_added = false;
01281 }
01282 
01283 void
01284 Document::RemoveLayerCommand::unexecute()
01285 {
01286     m_view->addLayer(m_layer);
01287     m_layer->setLayerDormant(m_view, m_wasDormant);
01288 
01289     m_d->addToLayerViewMap(m_layer, m_view);
01290     m_added = true;
01291 }
01292 
01293 void
01294 Document::toXml(QTextStream &out, QString indent, QString extraAttributes) const
01295 {
01296     toXml(out, indent, extraAttributes, false);
01297 }
01298 
01299 void
01300 Document::toXmlAsTemplate(QTextStream &out, QString indent, QString extraAttributes) const
01301 {
01302     toXml(out, indent, extraAttributes, true);
01303 }
01304 
01305 void
01306 Document::toXml(QTextStream &out, QString indent, QString extraAttributes,
01307                 bool asTemplate) const
01308 {
01309     out << indent + QString("<data%1%2>\n")
01310         .arg(extraAttributes == "" ? "" : " ").arg(extraAttributes);
01311 
01312     if (m_mainModel) {
01313 
01314         if (asTemplate) {
01315             writePlaceholderMainModel(out, indent + "  ");
01316         } else {
01317             m_mainModel->toXml(out, indent + "  ", "mainModel=\"true\"");
01318         }
01319 
01320         PlayParameters *playParameters =
01321             PlayParameterRepository::getInstance()->getPlayParameters(m_mainModel);
01322         if (playParameters) {
01323             playParameters->toXml
01324                 (out, indent + "  ",
01325                  QString("model=\"%1\"")
01326                  .arg(XmlExportable::getObjectExportId(m_mainModel)));
01327         }
01328     }
01329 
01330     // Models that are not used in a layer that is in a view should
01331     // not be written.  Get our list of required models first.
01332 
01333     std::set<const Model *> used;
01334 
01335     for (LayerViewMap::const_iterator i = m_layerViewMap.begin();
01336          i != m_layerViewMap.end(); ++i) {
01337 
01338         if (i->first && !i->second.empty() && i->first->getModel()) {
01339             used.insert(i->first->getModel());
01340         }
01341     }
01342 
01343     std::set<Model *> written;
01344 
01345     for (ModelMap::const_iterator i = m_models.begin();
01346          i != m_models.end(); ++i) {
01347 
01348         Model *model = i->first;
01349         const ModelRecord &rec = i->second;
01350 
01351         if (used.find(model) == used.end()) continue;
01352         
01353         // We need an intelligent way to determine which models need
01354         // to be streamed (i.e. have been edited, or are small) and
01355         // which should not be (i.e. remain as generated by a
01356         // transform, and are large).
01357         //
01358         // At the moment we can get away with deciding not to stream
01359         // dense 3d models or writable wave file models, provided they
01360         // were generated from a transform, because at the moment there
01361         // is no way to edit those model types so it should be safe to
01362         // regenerate them.  That won't always work in future though.
01363         // It would be particularly nice to be able to ask the user,
01364         // as well as making an intelligent guess.
01365 
01366         bool writeModel = true;
01367         bool haveDerivation = false;
01368 
01369         if (rec.source && rec.transform.getIdentifier() != "") {
01370             haveDerivation = true;
01371         } 
01372 
01373         if (haveDerivation) {
01374             if (dynamic_cast<const WritableWaveFileModel *>(model)) {
01375                 writeModel = false;
01376             } else if (dynamic_cast<const DenseThreeDimensionalModel *>(model)) {
01377                 writeModel = false;
01378             }
01379         }
01380 
01381         if (writeModel) {
01382             model->toXml(out, indent + "  ");
01383             written.insert(model);
01384         }
01385 
01386         if (haveDerivation) {
01387             writeBackwardCompatibleDerivation(out, indent + "  ",
01388                                               model, rec);
01389         }
01390 
01392         PlayParameters *playParameters =
01393             PlayParameterRepository::getInstance()->getPlayParameters(model);
01394         if (playParameters) {
01395             playParameters->toXml
01396                 (out, indent + "  ",
01397                  QString("model=\"%1\"")
01398                  .arg(XmlExportable::getObjectExportId(model)));
01399         }
01400     }
01401             
01403 
01404     // We should write out the alignment models here.  AlignmentModel
01405     // needs a toXml that writes out the export IDs of its reference
01406     // and aligned models, and then streams its path model.  Note that
01407     // this will only work when the alignment is complete, so we
01408     // should probably wait for it if it isn't already by this point.
01409 
01410     for (std::set<Model *>::const_iterator i = written.begin();
01411          i != written.end(); ++i) {
01412 
01413         const Model *model = *i;
01414         const AlignmentModel *alignment = model->getAlignment();
01415         if (!alignment) continue;
01416 
01417         alignment->toXml(out, indent + "  ");
01418     }
01419 
01420     for (LayerSet::const_iterator i = m_layers.begin();
01421          i != m_layers.end(); ++i) {
01422 
01423         (*i)->toXml(out, indent + "  ");
01424     }
01425 
01426     out << indent + "</data>\n";
01427 }
01428 
01429 void
01430 Document::writePlaceholderMainModel(QTextStream &out, QString indent) const
01431 {
01432     out << indent;
01433     out << QString("<model id=\"%1\" name=\"placeholder\" sampleRate=\"%2\" type=\"wavefile\" file=\":samples/silent.wav\" mainModel=\"true\"/>\n")
01434         .arg(getObjectExportId(m_mainModel))
01435         .arg(m_mainModel->getSampleRate());
01436 }
01437 
01438 void
01439 Document::writeBackwardCompatibleDerivation(QTextStream &out, QString indent,
01440                                             Model *targetModel,
01441                                             const ModelRecord &rec) const
01442 {
01443     // There is a lot of redundancy in the XML we output here, because
01444     // we want it to work with older SV session file reading code as
01445     // well.
01446     //
01447     // Formerly, a transform was described using a derivation element
01448     // which set out the source and target models, execution context
01449     // (step size, input channel etc) and transform id, containing a
01450     // plugin element which set out the transform parameters and so
01451     // on.  (The plugin element came from a "configurationXml" string
01452     // obtained from PluginXml.)
01453     // 
01454     // This has been replaced by a derivation element setting out the
01455     // source and target models and input channel, containing a
01456     // transform element which sets out everything in the Transform.
01457     //
01458     // In order to retain compatibility with older SV code, however,
01459     // we have to write out the same stuff into the derivation as
01460     // before, and manufacture an appropriate plugin element as well
01461     // as the transform element.  In order that newer code knows it's
01462     // dealing with a newer format, we will also write an attribute
01463     // 'type="transform"' in the derivation element.
01464 
01465     const Transform &transform = rec.transform;
01466 
01467     // Just for reference, this is what we would write if we didn't
01468     // have to be backward compatible:
01469     //
01470     //    out << indent
01471     //        << QString("<derivation type=\"transform\" source=\"%1\" "
01472     //                   "model=\"%2\" channel=\"%3\">\n")
01473     //        .arg(XmlExportable::getObjectExportId(rec.source))
01474     //        .arg(XmlExportable::getObjectExportId(targetModel))
01475     //        .arg(rec.channel);
01476     //
01477     //    transform.toXml(out, indent + "  ");
01478     //
01479     //    out << indent << "</derivation>\n";
01480     // 
01481     // Unfortunately, we can't just do that.  So we do this...
01482 
01483     QString extentsAttributes;
01484     if (transform.getStartTime() != RealTime::zeroTime ||
01485         transform.getDuration() != RealTime::zeroTime) {
01486         extentsAttributes = QString("startFrame=\"%1\" duration=\"%2\" ")
01487             .arg(RealTime::realTime2Frame(transform.getStartTime(),
01488                                           targetModel->getSampleRate()))
01489             .arg(RealTime::realTime2Frame(transform.getDuration(),
01490                                           targetModel->getSampleRate()));
01491     }
01492             
01493     out << indent;
01494     out << QString("<derivation type=\"transform\" source=\"%1\" "
01495                    "model=\"%2\" channel=\"%3\" domain=\"%4\" "
01496                    "stepSize=\"%5\" blockSize=\"%6\" %7windowType=\"%8\" "
01497                    "transform=\"%9\">\n")
01498         .arg(XmlExportable::getObjectExportId(rec.source))
01499         .arg(XmlExportable::getObjectExportId(targetModel))
01500         .arg(rec.channel)
01501         .arg(TransformFactory::getInstance()->getTransformInputDomain
01502              (transform.getIdentifier()))
01503         .arg(transform.getStepSize())
01504         .arg(transform.getBlockSize())
01505         .arg(extentsAttributes)
01506         .arg(int(transform.getWindowType()))
01507         .arg(XmlExportable::encodeEntities(transform.getIdentifier()));
01508 
01509     transform.toXml(out, indent + "  ");
01510     
01511     out << indent << "  "
01512         << TransformFactory::getInstance()->getPluginConfigurationXml(transform);
01513 
01514     out << indent << "</derivation>\n";
01515 }
01516