changeset 407:88ad01799040

* Save alignments to session file. Needs much testing.
author Chris Cannam
date Tue, 29 Apr 2008 15:34:17 +0000
parents d095214ffbaf
children 115f60df1e4d
files data/data.pro data/model/AlignmentModel.cpp data/model/AlignmentModel.h data/model/Model.cpp data/model/Model.h data/model/PathModel.h data/model/SparseModel.h
diffstat 7 files changed, 186 insertions(+), 54 deletions(-) [+]
line wrap: on
line diff
--- a/data/data.pro	Tue Apr 29 10:59:19 2008 +0000
+++ b/data/data.pro	Tue Apr 29 15:34:17 2008 +0000
@@ -53,6 +53,7 @@
            model/Labeller.h \
            model/Model.h \
            model/NoteModel.h \
+           model/PathModel.h \
            model/PowerOfSqrtTwoZoomConstraint.h \
            model/PowerOfTwoZoomConstraint.h \
            model/RangeSummarisableTimeValueModel.h \
--- a/data/model/AlignmentModel.cpp	Tue Apr 29 10:59:19 2008 +0000
+++ b/data/model/AlignmentModel.cpp	Tue Apr 29 15:34:17 2008 +0000
@@ -42,17 +42,28 @@
         
         connect(m_rawPath, SIGNAL(completionChanged()),
                 this, SLOT(pathCompletionChanged()));
+
+        constructPath();
+        constructReversePath();
     }
 
-    constructPath();
-    constructReversePath();
+    if (m_rawPath && m_rawPath->isReady()) {
+        pathCompletionChanged();
+    }
 }
 
 AlignmentModel::~AlignmentModel()
 {
+    if (m_inputModel) m_inputModel->aboutToDelete();
     delete m_inputModel;
+
+    if (m_rawPath) m_rawPath->aboutToDelete();
     delete m_rawPath;
+
+    if (m_path) m_path->aboutToDelete();
     delete m_path;
+
+    if (m_reversePath) m_reversePath->aboutToDelete();
     delete m_reversePath;
 }
 
@@ -157,6 +168,7 @@
 {
     if (m_pathComplete) {
         std::cerr << "AlignmentModel: deleting raw path model" << std::endl;
+        if (m_rawPath) m_rawPath->aboutToDelete();
         delete m_rawPath;
         m_rawPath = 0;
     }
@@ -192,7 +204,8 @@
 
             constructPath();
             constructReversePath();
-
+            
+            if (m_inputModel) m_inputModel->aboutToDelete();
             delete m_inputModel;
             m_inputModel = 0;
         }
@@ -237,6 +250,7 @@
 AlignmentModel::constructReversePath() const
 {
     if (!m_reversePath) {
+/*!!!
         if (!m_rawPath) {
             std::cerr << "ERROR: AlignmentModel::constructReversePath: "
                       << "No raw path available" << std::endl;
@@ -244,12 +258,23 @@
         }
         m_reversePath = new PathModel
             (m_rawPath->getSampleRate(), m_rawPath->getResolution(), false);
+*/
+        if (!m_path) {
+            std::cerr << "ERROR: AlignmentModel::constructReversePath: "
+                      << "No forward path available" << std::endl;
+            return;
+        }
+        m_reversePath = new PathModel
+            (m_path->getSampleRate(), m_path->getResolution(), false);
     } else {
+/*!!!
         if (!m_rawPath) return;
+*/
+        if (!m_path) return;
     }
         
     m_reversePath->clear();
-
+/*!!!
     SparseTimeValueModel::PointList points = m_rawPath->getPoints();
         
     for (SparseTimeValueModel::PointList::const_iterator i = points.begin();
@@ -259,6 +284,16 @@
         long rframe = lrintf(value * m_aligned->getSampleRate());
         m_reversePath->addPoint(PathPoint(rframe, frame));
     }
+*/
+
+    PathModel::PointList points = m_path->getPoints();
+        
+    for (PathModel::PointList::const_iterator i = points.begin();
+         i != points.end(); ++i) {
+        long frame = i->frame;
+        long rframe = i->mapframe;
+        m_reversePath->addPoint(PathPoint(rframe, frame));
+    }
 
 #ifdef DEBUG_ALIGNMENT_MODEL
     std::cerr << "AlignmentModel::constructReversePath: " << m_reversePath->getPointCount() << " points, at least " << (2 * m_reversePath->getPointCount() * (3 * sizeof(void *) + sizeof(int) + sizeof(PathPoint))) << " bytes" << std::endl;
@@ -333,4 +368,34 @@
 
     return resultFrame;
 }
+
+void
+AlignmentModel::setPath(PathModel *path)
+{
+    if (m_path) m_path->aboutToDelete();
+    delete m_path;
+    m_path = path;
+    constructReversePath();
+}
     
+void
+AlignmentModel::toXml(QTextStream &stream,
+                      QString indent,
+                      QString extraAttributes) const
+{
+    if (!m_path) {
+        std::cerr << "AlignmentModel::toXml: no path" << std::endl;
+        return;
+    }
+
+    m_path->toXml(stream, indent, "");
+
+    Model::toXml(stream, indent,
+                 QString("type=\"alignment\" reference=\"%1\" aligned=\"%2\" path=\"%3\" %4")
+                 .arg(getObjectExportId(m_reference))
+                 .arg(getObjectExportId(m_aligned))
+                 .arg(getObjectExportId(m_path))
+                 .arg(extraAttributes));
+}
+
+
--- a/data/model/AlignmentModel.h	Tue Apr 29 10:59:19 2008 +0000
+++ b/data/model/AlignmentModel.h	Tue Apr 29 15:34:17 2008 +0000
@@ -17,7 +17,7 @@
 #define _ALIGNMENT_MODEL_H_
 
 #include "Model.h"
-#include "SparseModel.h"
+#include "PathModel.h"
 #include "base/RealTime.h"
 
 #include <QString>
@@ -52,6 +52,12 @@
     size_t toReference(size_t frame) const;
     size_t fromReference(size_t frame) const;
 
+    void setPath(PathModel *path);
+
+    virtual void toXml(QTextStream &stream,
+                       QString indent = "",
+                       QString extraAttributes = "") const;
+
 signals:
     void modelChanged();
     void modelChanged(size_t startFrame, size_t endFrame);
@@ -68,54 +74,6 @@
 
     Model *m_inputModel; // I own this
 
-    struct PathPoint
-    {
-        PathPoint(long _frame) : frame(_frame), mapframe(_frame) { }
-        PathPoint(long _frame, long _mapframe) :
-            frame(_frame), mapframe(_mapframe) { }
-
-        int getDimensions() const { return 2; }
-
-        long frame;
-        long mapframe;
-
-        QString getLabel() const { return ""; }
-
-        void toXml(QTextStream &stream, QString indent = "",
-                   QString extraAttributes = "") const {
-            stream << QString("%1<point frame=\"%2\" mapframe=\"%3\" %4/>\n")
-                .arg(indent).arg(frame).arg(mapframe).arg(extraAttributes);
-        }
-        
-        QString toDelimitedDataString(QString delimiter,
-                                      size_t sampleRate) const {
-            QStringList list;
-            list << RealTime::frame2RealTime(frame, sampleRate).toString().c_str();
-            list << QString("%1").arg(mapframe);
-            return list.join(delimiter);
-        }
-
-        struct Comparator {
-            bool operator()(const PathPoint &p1, const PathPoint &p2) const {
-                if (p1.frame != p2.frame) return p1.frame < p2.frame;
-                return p1.mapframe < p2.mapframe;
-            }
-        };
-    
-        struct OrderComparator {
-            bool operator()(const PathPoint &p1, const PathPoint &p2) const {
-                return p1.frame < p2.frame;
-            }
-        };
-    };
-
-    class PathModel : public SparseModel<PathPoint>
-    {
-    public:
-        PathModel(size_t sampleRate, size_t resolution, bool notify = true) :
-            SparseModel<PathPoint>(sampleRate, resolution, notify) { }
-    };
-
     SparseTimeValueModel *m_rawPath; // I own this
     mutable PathModel *m_path; // I own this
     mutable PathModel *m_reversePath; // I own this
--- a/data/model/Model.cpp	Tue Apr 29 10:59:19 2008 +0000
+++ b/data/model/Model.cpp	Tue Apr 29 15:34:17 2008 +0000
@@ -90,6 +90,12 @@
             this, SIGNAL(alignmentCompletionChanged()));
 }
 
+const AlignmentModel *
+Model::getAlignment() const
+{
+    return m_alignment;
+}
+
 const Model *
 Model::getAlignmentReference() const
 {
--- a/data/model/Model.h	Tue Apr 29 10:59:19 2008 +0000
+++ b/data/model/Model.h	Tue Apr 29 15:34:17 2008 +0000
@@ -160,6 +160,17 @@
     virtual void setAlignment(AlignmentModel *alignment);
 
     /**
+     * Retrieve the alignment model for this model.  This is not a
+     * generally useful function, as the alignment you really want may
+     * be performed by the source model instead.  You should normally
+     * use getAlignmentReference, alignToReference and
+     * alignFromReference instead of this.  The main intended
+     * application for this function is in streaming out alignments to
+     * the session file.
+     */
+    virtual const AlignmentModel *getAlignment() const;
+
+    /**
      * Return the reference model for the current alignment timeline,
      * if any.
      */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/data/model/PathModel.h	Tue Apr 29 15:34:17 2008 +0000
@@ -0,0 +1,86 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    Sonic Visualiser
+    An audio file viewer and annotation editor.
+    Centre for Digital Music, Queen Mary, University of London.
+    This file copyright 2007 QMUL.
+    
+    This program is free software; you can redistribute it and/or
+    modify it under the terms of the GNU General Public License as
+    published by the Free Software Foundation; either version 2 of the
+    License, or (at your option) any later version.  See the file
+    COPYING included with this distribution for more information.
+*/
+
+#ifndef _PATH_MODEL_H_
+#define _PATH_MODEL_H_
+
+#include "Model.h"
+#include "SparseModel.h"
+#include "base/RealTime.h"
+
+#include <QStringList>
+
+
+struct PathPoint
+{
+    PathPoint(long _frame) : frame(_frame), mapframe(_frame) { }
+    PathPoint(long _frame, long _mapframe) :
+        frame(_frame), mapframe(_mapframe) { }
+
+    int getDimensions() const { return 2; }
+
+    long frame;
+    long mapframe;
+
+    QString getLabel() const { return ""; }
+
+    void toXml(QTextStream &stream, QString indent = "",
+               QString extraAttributes = "") const {
+        stream << QString("%1<point frame=\"%2\" mapframe=\"%3\" %4/>\n")
+            .arg(indent).arg(frame).arg(mapframe).arg(extraAttributes);
+    }
+        
+    QString toDelimitedDataString(QString delimiter,
+                                  size_t sampleRate) const {
+        QStringList list;
+        list << RealTime::frame2RealTime(frame, sampleRate).toString().c_str();
+        list << QString("%1").arg(mapframe);
+        return list.join(delimiter);
+    }
+
+    struct Comparator {
+        bool operator()(const PathPoint &p1, const PathPoint &p2) const {
+            if (p1.frame != p2.frame) return p1.frame < p2.frame;
+            return p1.mapframe < p2.mapframe;
+        }
+    };
+    
+    struct OrderComparator {
+        bool operator()(const PathPoint &p1, const PathPoint &p2) const {
+            return p1.frame < p2.frame;
+        }
+    };
+};
+
+class PathModel : public SparseModel<PathPoint>
+{
+public:
+    PathModel(size_t sampleRate, size_t resolution, bool notify = true) :
+        SparseModel<PathPoint>(sampleRate, resolution, notify) { }
+
+    virtual void toXml(QTextStream &out,
+                       QString indent = "",
+                       QString extraAttributes = "") const
+    {
+        SparseModel<PathPoint>::toXml
+            (out, 
+             indent,
+             QString("%1 subtype=\"path\"")
+             .arg(extraAttributes));
+    }
+};
+
+
+#endif
--- a/data/model/SparseModel.h	Tue Apr 29 10:59:19 2008 +0000
+++ b/data/model/SparseModel.h	Tue Apr 29 15:34:17 2008 +0000
@@ -133,6 +133,8 @@
 
     QString getTypeName() const { return tr("Sparse"); }
 
+    virtual QString getXmlOutputType() const { return "sparse"; }
+
     virtual void toXml(QTextStream &out,
                        QString indent = "",
                        QString extraAttributes = "") const;
@@ -554,10 +556,13 @@
     std::cerr << "SparseModel::toXml: extraAttributes = \"" 
               << extraAttributes.toStdString() << std::endl;
 
+    QString type = getXmlOutputType();
+
     Model::toXml
 	(out,
          indent,
-	 QString("type=\"sparse\" dimensions=\"%1\" resolution=\"%2\" notifyOnAdd=\"%3\" dataset=\"%4\" %5")
+	 QString("type=\"%1\" dimensions=\"%2\" resolution=\"%3\" notifyOnAdd=\"%4\" dataset=\"%5\" %6")
+         .arg(type)
 	 .arg(PointType(0).getDimensions())
 	 .arg(m_resolution)
 	 .arg(m_notifyOnAdd ? "true" : "false")