diff data/model/NoteModel.h @ 1651:7a56bb85030f single-point

Introduce deferred notifier, + start converting sparse time-value model (perhaps we should rename it too)
author Chris Cannam
date Mon, 18 Mar 2019 14:17:20 +0000
parents 1cc9a0d4b1b6
children 0cfb882155a6
line wrap: on
line diff
--- a/data/model/NoteModel.h	Mon Mar 18 09:37:46 2019 +0000
+++ b/data/model/NoteModel.h	Mon Mar 18 14:17:20 2019 +0000
@@ -4,7 +4,6 @@
     Sonic Visualiser
     An audio file viewer and annotation editor.
     Centre for Digital Music, Queen Mary, University of London.
-    This file copyright 2006 Chris Cannam.
     
     This program is free software; you can redistribute it and/or
     modify it under the terms of the GNU General Public License as
@@ -19,6 +18,7 @@
 #include "Model.h"
 #include "TabularModel.h"
 #include "EventCommands.h"
+#include "DeferredNotifier.h"
 #include "base/UnitDatabase.h"
 #include "base/EventSeries.h"
 #include "base/NoteData.h"
@@ -57,9 +57,10 @@
         m_valueQuantization(0),
         m_units(""),
         m_extendTo(0),
-        m_notifyOnAdd(notifyOnAdd),
-        m_sinceLastNotifyMin(-1),
-        m_sinceLastNotifyMax(-1),
+        m_notifier(this,
+                   notifyOnAdd ?
+                   DeferredNotifier::NOTIFY_ALWAYS :
+                   DeferredNotifier::NOTIFY_DEFERRED),
         m_completion(0) {
         if (subtype == FLEXI_NOTE) {
             m_valueMinimum = 33.f;
@@ -81,9 +82,10 @@
         m_valueQuantization(0),
         m_units(""),
         m_extendTo(0),
-        m_notifyOnAdd(notifyOnAdd),
-        m_sinceLastNotifyMin(-1),
-        m_sinceLastNotifyMax(-1),
+        m_notifier(this,
+                   notifyOnAdd ?
+                   DeferredNotifier::NOTIFY_ALWAYS :
+                   DeferredNotifier::NOTIFY_DEFERRED),
         m_completion(0) {
         PlayParameterRepository::getInstance()->addPlayable(this);
     }
@@ -122,46 +124,22 @@
 
     void setCompletion(int completion, bool update = true) {
 
-        bool emitCompletionChanged = true;
-        bool emitGeneralModelChanged = false;
-        bool emitRegionChanged = false;
-
-        {
-            QMutexLocker locker(&m_mutex);
-
-            if (m_completion != completion) {
-                m_completion = completion;
-
-                if (completion == 100) {
-
-                    if (m_notifyOnAdd) {
-                        emitCompletionChanged = false;
-                    }
-
-                    m_notifyOnAdd = true; // henceforth
-                    emitGeneralModelChanged = true;
-
-                } else if (!m_notifyOnAdd) {
-
-                    if (update &&
-                        m_sinceLastNotifyMin >= 0 &&
-                        m_sinceLastNotifyMax >= 0) {
-                        emitRegionChanged = true;
-                    }
-                }
-            }
+        {   QMutexLocker locker(&m_mutex);
+            if (m_completion == completion) return;
+            m_completion = completion;
         }
 
-        if (emitCompletionChanged) {
-            emit completionChanged();
+        if (update) {
+            m_notifier.makeDeferredNotifications();
         }
-        if (emitGeneralModelChanged) {
+        
+        emit completionChanged();
+
+        if (completion == 100) {
+            // henceforth:
+            m_notifier.switchMode(DeferredNotifier::NOTIFY_ALWAYS);
             emit modelChanged();
         }
-        if (emitRegionChanged) {
-            emit modelChangedWithin(m_sinceLastNotifyMin, m_sinceLastNotifyMax);
-            m_sinceLastNotifyMin = m_sinceLastNotifyMax = -1;
-        }        
     }
 
     /**
@@ -203,7 +181,6 @@
         {
             QMutexLocker locker(&m_mutex);
             m_events.add(e);
-//!!!???        if (point.getLabel() != "") m_hasTextLabels = true;
 
             float v = e.getValue();
             if (!ISNAN(v) && !ISINF(v)) {
@@ -215,23 +192,10 @@
                 }
                 m_haveExtents = true;
             }
-            
-            sv_frame_t f = e.getFrame();
-
-            if (!m_notifyOnAdd) {
-                if (m_sinceLastNotifyMin == -1 || f < m_sinceLastNotifyMin) {
-                    m_sinceLastNotifyMin = f;
-                }
-                if (m_sinceLastNotifyMax == -1 || f > m_sinceLastNotifyMax) {
-                    m_sinceLastNotifyMax = f;
-                }
-            }
         }
         
-        if (m_notifyOnAdd) {
-            emit modelChangedWithin(e.getFrame(),
-                                    e.getFrame() + e.getDuration() + m_resolution);
-        }
+        m_notifier.update(e.getFrame(), e.getDuration() + m_resolution);
+
         if (allChange) {
             emit modelChanged();
         }
@@ -388,13 +352,14 @@
                      "valueQuantization=\"%5\" minimum=\"%6\" maximum=\"%7\" "
                      "units=\"%8\" %9")
              .arg(m_resolution)
-             .arg(m_notifyOnAdd ? "true" : "false")
+             .arg("true") // always true after model reaches 100% -
+                          // subsequent events are always notified
              .arg(getObjectExportId(&m_events))
              .arg(m_subtype == FLEXI_NOTE ? "flexinote" : "note")
              .arg(m_valueQuantization)
              .arg(m_valueMinimum)
              .arg(m_valueMaximum)
-             .arg(m_units)
+             .arg(encodeEntities(m_units))
              .arg(extraAttributes));
         
         m_events.toXml(out, indent, QString("dimensions=\"3\""));
@@ -410,17 +375,12 @@
     bool m_haveExtents;
     float m_valueQuantization;
     QString m_units;
-    
     sv_frame_t m_extendTo;
-
-    bool m_notifyOnAdd;
-    sv_frame_t m_sinceLastNotifyMin;
-    sv_frame_t m_sinceLastNotifyMax;
+    DeferredNotifier m_notifier;
+    int m_completion;
 
     EventSeries m_events;
 
-    int m_completion;
-
     mutable QMutex m_mutex;
 
     //!!! do we have general docs for ownership and synchronisation of models?