changeset 329:f72d58d1ccb0 tonioni

Adapt additional models created during a transform so they can be returned through a callback in an async method
author Chris Cannam
date Wed, 29 Jan 2014 17:32:47 +0000
parents d2c13ec0f148
children 350a410e0555
files framework/Document.cpp framework/Document.h framework/SVFileReader.cpp
diffstat 3 files changed, 195 insertions(+), 24 deletions(-) [+]
line wrap: on
line diff
--- a/framework/Document.cpp	Fri Jan 17 11:59:49 2014 -0500
+++ b/framework/Document.cpp	Wed Jan 29 17:32:47 2014 +0000
@@ -224,7 +224,7 @@
                               const ModelTransformer::Input &input)
 {
     QString message;
-    vector<Model *> newModels = addDerivedModels(transforms, input, message);
+    vector<Model *> newModels = addDerivedModels(transforms, input, message, 0);
 
     if (newModels.empty()) {
         //!!! This identifier may be wrong!
@@ -235,8 +235,101 @@
         emit modelGenerationWarning(transforms[0].getIdentifier(), message);
     }
 
+    QStringList names;
+    for (int i = 0; i < newModels.size(); ++i) {
+        names.push_back(getUniqueLayerName
+                        (TransformFactory::getInstance()->
+                         getTransformFriendlyName
+                         (transforms[i].getIdentifier())));
+    }
+
+    vector<Layer *> layers = createLayersForDerivedModels(newModels, names);
+    return layers;
+}
+
+class AdditionalModelConverter : 
+    public ModelTransformerFactory::AdditionalModelHandler
+{
+public:
+    AdditionalModelConverter(Document *doc, 
+                             Document::LayerCreationHandler *handler) :
+        m_doc(doc),
+        m_handler(handler) {
+    }
+
+    virtual ~AdditionalModelConverter() { }
+
+    void
+    setPrimaryLayers(vector<Layer *> layers) {
+        m_primary = layers;
+    }
+
+    void
+    moreModelsAvailable(vector<Model *> models) {
+        std::cerr << "AdditionalModelConverter::moreModelsAvailable: " << models.size() << " model(s)" << std::endl;
+        // We can't automatically regenerate the additional models on
+        // reload -- we should delete them instead
+        QStringList names;
+        foreach (Model *model, models) {
+            m_doc->addAdditionalModel(model);
+            names.push_back(QString());
+        }
+        vector<Layer *> layers = m_doc->createLayersForDerivedModels
+            (models, names);
+        m_handler->layersCreated(m_primary, layers);
+        delete this;
+    }
+
+    void
+    noMoreModelsAvailable() {
+        std::cerr << "AdditionalModelConverter::noMoreModelsAvailable" << std::endl;
+        delete this;
+    }
+
+private:
+    Document *m_doc;
+    vector<Layer *> m_primary;
+    Document::LayerCreationHandler *m_handler; //!!! how to handle destruction of this?
+};
+
+void
+Document::createDerivedLayersAsync(const Transforms &transforms,
+                                   const ModelTransformer::Input &input,
+                                   LayerCreationHandler *handler)
+{
+    QString message;
+
+    AdditionalModelConverter *amc = new AdditionalModelConverter(this, handler);
+    
+    vector<Model *> newModels = addDerivedModels
+        (transforms, input, message, amc);
+
+    QStringList names;
+    for (int i = 0; i < newModels.size(); ++i) {
+        names.push_back(getUniqueLayerName
+                        (TransformFactory::getInstance()->
+                         getTransformFriendlyName
+                         (transforms[i].getIdentifier())));
+    }
+
+    vector<Layer *> layers = createLayersForDerivedModels(newModels, names);
+    amc->setPrimaryLayers(layers);
+
+    if (newModels.empty()) {
+        //!!! This identifier may be wrong!
+        emit modelGenerationFailed(transforms[0].getIdentifier(), message);
+    } else if (message != "") {
+        //!!! This identifier may be wrong!
+        emit modelGenerationWarning(transforms[0].getIdentifier(), message);
+    }
+}
+
+vector<Layer *>
+Document::createLayersForDerivedModels(vector<Model *> newModels, 
+                                       QStringList names)
+{
     vector<Layer *> layers;
-
+    
     for (int i = 0; i < (int)newModels.size(); ++i) {
 
         Model *newModel = newModels[i];
@@ -245,7 +338,7 @@
             LayerFactory::getInstance()->getValidLayerTypes(newModel);
 
         if (types.empty()) {
-            cerr << "WARNING: Document::createLayerForTransformer: no valid display layer for output of transform " << transforms[i].getIdentifier() << endl;
+            cerr << "WARNING: Document::createLayerForTransformer: no valid display layer for output of transform " << names[i] << endl;
             //!!! inadequate cleanup:
             newModel->aboutToDelete();
             emit modelAboutToBeDeleted(newModel);
@@ -275,10 +368,7 @@
         // model pointer in both layers, so they can't actually be cloned.
     
         if (newLayer) {
-            newLayer->setObjectName(getUniqueLayerName
-                                    (TransformFactory::getInstance()->
-                                     getTransformFriendlyName
-                                     (transforms[i].getIdentifier())));
+            newLayer->setObjectName(names[i]);
         }
 
         emit layerAdded(newLayer);
@@ -423,6 +513,14 @@
     }
 
     for (ModelMap::iterator i = m_models.begin(); i != m_models.end(); ++i) {
+        if (i->second.additional) {
+            Model *m = i->first;
+            emit modelAboutToBeDeleted(m);
+            delete m;
+        }
+    }
+
+    for (ModelMap::iterator i = m_models.begin(); i != m_models.end(); ++i) {
 
         Model *m = i->first;
 
@@ -457,21 +555,21 @@
 }
 
 void
-Document::addDerivedModel(const Transform &transform,
-                          const ModelTransformer::Input &input,
-                          Model *outputModelToAdd)
+Document::addAlreadyDerivedModel(const Transform &transform,
+                                 const ModelTransformer::Input &input,
+                                 Model *outputModelToAdd)
 {
     if (m_models.find(outputModelToAdd) != m_models.end()) {
-	cerr << "WARNING: Document::addDerivedModel: Model already added"
+	cerr << "WARNING: Document::addAlreadyDerivedModel: Model already added"
 		  << endl;
 	return;
     }
 
 #ifdef DEBUG_DOCUMENT
     if (input.getModel()) {
-        cerr << "Document::addDerivedModel: source is " << input.getModel() << " \"" << input.getModel()->objectName() << "\"" << endl;
+        cerr << "Document::addAlreadyDerivedModel: source is " << input.getModel() << " \"" << input.getModel()->objectName() << "\"" << endl;
     } else {
-        cerr << "Document::addDerivedModel: source is " << input.getModel() << endl;
+        cerr << "Document::addAlreadyDerivedModel: source is " << input.getModel() << endl;
     }
 #endif
 
@@ -479,6 +577,7 @@
     rec.source = input.getModel();
     rec.channel = input.getChannel();
     rec.transform = transform;
+    rec.additional = false;
     rec.refcount = 0;
 
     outputModelToAdd->setSourceModel(input.getModel());
@@ -486,7 +585,7 @@
     m_models[outputModelToAdd] = rec;
 
 #ifdef DEBUG_DOCUMENT
-    SVDEBUG << "Document::addDerivedModel: Added model " << outputModelToAdd << endl;
+    cerr << "Document::addAlreadyDerivedModel: Added model " << outputModelToAdd << endl;
     cerr << "Models now: ";
     for (ModelMap::const_iterator i = m_models.begin(); i != m_models.end(); ++i) {
         cerr << i->first << " ";
@@ -510,6 +609,7 @@
     ModelRecord rec;
     rec.source = 0;
     rec.refcount = 0;
+    rec.additional = false;
 
     m_models[model] = rec;
 
@@ -527,6 +627,36 @@
     emit modelAdded(model);
 }
 
+void
+Document::addAdditionalModel(Model *model)
+{
+    if (m_models.find(model) != m_models.end()) {
+	cerr << "WARNING: Document::addAdditionalModel: Model already added"
+		  << endl;
+	return;
+    }
+
+    ModelRecord rec;
+    rec.source = 0;
+    rec.refcount = 0;
+    rec.additional = true;
+
+    m_models[model] = rec;
+
+#ifdef DEBUG_DOCUMENT
+    SVDEBUG << "Document::addAdditionalModel: Added model " << model << endl;
+    cerr << "Models now: ";
+    for (ModelMap::const_iterator i = m_models.begin(); i != m_models.end(); ++i) {
+        cerr << i->first << " ";
+    } 
+    cerr << endl;
+#endif
+
+    if (m_autoAlignment) alignModel(model);
+
+    emit modelAdded(model);
+}
+
 Model *
 Document::addDerivedModel(const Transform &transform,
                           const ModelTransformer::Input &input,
@@ -543,7 +673,7 @@
 
     Transforms tt;
     tt.push_back(transform);
-    vector<Model *> mm = addDerivedModels(tt, input, message);
+    vector<Model *> mm = addDerivedModels(tt, input, message, 0);
     if (mm.empty()) return 0;
     else return mm[0];
 }
@@ -551,11 +681,12 @@
 vector<Model *>
 Document::addDerivedModels(const Transforms &transforms,
                            const ModelTransformer::Input &input,
-                           QString &message)
+                           QString &message,
+                           AdditionalModelConverter *amc)
 {
     vector<Model *> mm = 
         ModelTransformerFactory::getInstance()->transformMultiple
-        (transforms, input, message);
+        (transforms, input, message, amc);
 
     for (int j = 0; j < (int)mm.size(); ++j) {
 
@@ -579,7 +710,7 @@
         if (!model) {
             cerr << "WARNING: Document::addDerivedModel: no output model for transform " << applied.getIdentifier() << endl;
         } else {
-            addDerivedModel(applied, input, model);
+            addAlreadyDerivedModel(applied, input, model);
         }
     }
 	
--- a/framework/Document.h	Fri Jan 17 11:59:49 2014 -0500
+++ b/framework/Document.h	Wed Jan 29 17:32:47 2014 +0000
@@ -30,6 +30,8 @@
 class View;
 class WaveFileModel;
 
+class AdditionalModelConverter;
+
 /**
  * A Sonic Visualiser document consists of a set of data models, and
  * also the visualisation layers used to display them.  Changes to the
@@ -121,11 +123,37 @@
      * Create and return suitable layers for the given transforms,
      * which must be identical apart from the output (i.e. must use
      * the same plugin and configuration). The layers are returned in
-     * the same order as the transformed are supplied.
+     * the same order as the transforms are supplied.
      */
     std::vector<Layer *> createDerivedLayers(const Transforms &,
                                              const ModelTransformer::Input &);
 
+    class LayerCreationHandler {
+    public:
+        virtual ~LayerCreationHandler() { }
+
+        /**
+         * The primary layers are those corresponding 1-1 to the input
+         * models, listed in the same order as the input models. The
+         * additional layers vector contains any layers (from all
+         * models) that were returned separately at the end of
+         * processing.
+         */
+        virtual void layersCreated(std::vector<Layer *> primary,
+                                   std::vector<Layer *> additional) = 0;
+    };
+
+    /**
+     * Create suitable layers for the given transforms, which must be
+     * identical apart from the output (i.e. must use the same plugin
+     * and configuration). This method returns after initialising the
+     * transformer process, and the layers are returned through a
+     * subsequent call to the provided handler (which must be non-null).
+     */
+    void createDerivedLayersAsync(const Transforms &,
+                                  const ModelTransformer::Input &,
+                                  LayerCreationHandler *handler);
+
     /**
      * Delete the given layer, and also its associated model if no
      * longer used by any other layer.  In general, this should be the
@@ -168,18 +196,20 @@
      * transforms, running the transforms and returning the resulting
      * models.
      */
+    friend class AdditionalModelConverter;
     std::vector<Model *> addDerivedModels(const Transforms &transforms,
                                           const ModelTransformer::Input &input,
-                                          QString &returnedMessage);
+                                          QString &returnedMessage,
+                                          AdditionalModelConverter *);
 
     /**
      * Add a derived model associated with the given transform.  This
      * is necessary to register any derived model that was not created
      * by the document using createDerivedModel or createDerivedLayer.
      */
-    void addDerivedModel(const Transform &transform,
-                         const ModelTransformer::Input &input,
-                         Model *outputModelToAdd);
+    void addAlreadyDerivedModel(const Transform &transform,
+                                const ModelTransformer::Input &input,
+                                Model *outputModelToAdd);
 
     /**
      * Add an imported (non-derived, non-main) model.  This is
@@ -298,6 +328,7 @@
 	const Model *source;
         int channel;
         Transform transform;
+        bool additional;
 
 	// Count of the number of layers using this model.
 	int refcount;
@@ -306,6 +337,12 @@
     typedef std::map<Model *, ModelRecord> ModelMap;
     ModelMap m_models;
 
+    /**
+     * Add an extra derived model (returned at the end of processing a
+     * transform).
+     */
+    void addAdditionalModel(Model *);
+
     class AddLayerCommand : public Command
     {
     public:
@@ -357,6 +394,9 @@
     void toXml(QTextStream &, QString, QString, bool asTemplate) const;
     void writePlaceholderMainModel(QTextStream &, QString) const;
 
+    std::vector<Layer *> createLayersForDerivedModels(std::vector<Model *>,
+                                                      QStringList names);
+
     /**
      * And these are the layers.  We also control the lifespans of
      * these (usually through the commands used to add and remove them).
--- a/framework/SVFileReader.cpp	Fri Jan 17 11:59:49 2014 -0500
+++ b/framework/SVFileReader.cpp	Wed Jan 29 17:32:47 2014 +0000
@@ -325,7 +325,7 @@
                 }                    
             }
         } else {
-            m_document->addDerivedModel
+            m_document->addAlreadyDerivedModel
                 (m_currentTransform,
                  ModelTransformer::Input(m_currentTransformSource,
                                          m_currentTransformChannel),