comparison 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
comparison
equal deleted inserted replaced
1650:bbfb5a1e4b84 1651:7a56bb85030f
2 2
3 /* 3 /*
4 Sonic Visualiser 4 Sonic Visualiser
5 An audio file viewer and annotation editor. 5 An audio file viewer and annotation editor.
6 Centre for Digital Music, Queen Mary, University of London. 6 Centre for Digital Music, Queen Mary, University of London.
7 This file copyright 2006 Chris Cannam.
8 7
9 This program is free software; you can redistribute it and/or 8 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License as 9 modify it under the terms of the GNU General Public License as
11 published by the Free Software Foundation; either version 2 of the 10 published by the Free Software Foundation; either version 2 of the
12 License, or (at your option) any later version. See the file 11 License, or (at your option) any later version. See the file
17 #define SV_NOTE_MODEL_H 16 #define SV_NOTE_MODEL_H
18 17
19 #include "Model.h" 18 #include "Model.h"
20 #include "TabularModel.h" 19 #include "TabularModel.h"
21 #include "EventCommands.h" 20 #include "EventCommands.h"
21 #include "DeferredNotifier.h"
22 #include "base/UnitDatabase.h" 22 #include "base/UnitDatabase.h"
23 #include "base/EventSeries.h" 23 #include "base/EventSeries.h"
24 #include "base/NoteData.h" 24 #include "base/NoteData.h"
25 #include "base/NoteExportable.h" 25 #include "base/NoteExportable.h"
26 #include "base/RealTime.h" 26 #include "base/RealTime.h"
55 m_valueMaximum(0.f), 55 m_valueMaximum(0.f),
56 m_haveExtents(false), 56 m_haveExtents(false),
57 m_valueQuantization(0), 57 m_valueQuantization(0),
58 m_units(""), 58 m_units(""),
59 m_extendTo(0), 59 m_extendTo(0),
60 m_notifyOnAdd(notifyOnAdd), 60 m_notifier(this,
61 m_sinceLastNotifyMin(-1), 61 notifyOnAdd ?
62 m_sinceLastNotifyMax(-1), 62 DeferredNotifier::NOTIFY_ALWAYS :
63 DeferredNotifier::NOTIFY_DEFERRED),
63 m_completion(0) { 64 m_completion(0) {
64 if (subtype == FLEXI_NOTE) { 65 if (subtype == FLEXI_NOTE) {
65 m_valueMinimum = 33.f; 66 m_valueMinimum = 33.f;
66 m_valueMaximum = 88.f; 67 m_valueMaximum = 88.f;
67 } 68 }
79 m_valueMaximum(valueMaximum), 80 m_valueMaximum(valueMaximum),
80 m_haveExtents(true), 81 m_haveExtents(true),
81 m_valueQuantization(0), 82 m_valueQuantization(0),
82 m_units(""), 83 m_units(""),
83 m_extendTo(0), 84 m_extendTo(0),
84 m_notifyOnAdd(notifyOnAdd), 85 m_notifier(this,
85 m_sinceLastNotifyMin(-1), 86 notifyOnAdd ?
86 m_sinceLastNotifyMax(-1), 87 DeferredNotifier::NOTIFY_ALWAYS :
88 DeferredNotifier::NOTIFY_DEFERRED),
87 m_completion(0) { 89 m_completion(0) {
88 PlayParameterRepository::getInstance()->addPlayable(this); 90 PlayParameterRepository::getInstance()->addPlayable(this);
89 } 91 }
90 92
91 virtual ~NoteModel() { 93 virtual ~NoteModel() {
120 122
121 int getCompletion() const { return m_completion; } 123 int getCompletion() const { return m_completion; }
122 124
123 void setCompletion(int completion, bool update = true) { 125 void setCompletion(int completion, bool update = true) {
124 126
125 bool emitCompletionChanged = true; 127 { QMutexLocker locker(&m_mutex);
126 bool emitGeneralModelChanged = false; 128 if (m_completion == completion) return;
127 bool emitRegionChanged = false; 129 m_completion = completion;
128 130 }
129 { 131
130 QMutexLocker locker(&m_mutex); 132 if (update) {
131 133 m_notifier.makeDeferredNotifications();
132 if (m_completion != completion) { 134 }
133 m_completion = completion; 135
134 136 emit completionChanged();
135 if (completion == 100) { 137
136 138 if (completion == 100) {
137 if (m_notifyOnAdd) { 139 // henceforth:
138 emitCompletionChanged = false; 140 m_notifier.switchMode(DeferredNotifier::NOTIFY_ALWAYS);
139 }
140
141 m_notifyOnAdd = true; // henceforth
142 emitGeneralModelChanged = true;
143
144 } else if (!m_notifyOnAdd) {
145
146 if (update &&
147 m_sinceLastNotifyMin >= 0 &&
148 m_sinceLastNotifyMax >= 0) {
149 emitRegionChanged = true;
150 }
151 }
152 }
153 }
154
155 if (emitCompletionChanged) {
156 emit completionChanged();
157 }
158 if (emitGeneralModelChanged) {
159 emit modelChanged(); 141 emit modelChanged();
160 } 142 }
161 if (emitRegionChanged) {
162 emit modelChangedWithin(m_sinceLastNotifyMin, m_sinceLastNotifyMax);
163 m_sinceLastNotifyMin = m_sinceLastNotifyMax = -1;
164 }
165 } 143 }
166 144
167 /** 145 /**
168 * Query methods. 146 * Query methods.
169 */ 147 */
201 bool allChange = false; 179 bool allChange = false;
202 180
203 { 181 {
204 QMutexLocker locker(&m_mutex); 182 QMutexLocker locker(&m_mutex);
205 m_events.add(e); 183 m_events.add(e);
206 //!!!??? if (point.getLabel() != "") m_hasTextLabels = true;
207 184
208 float v = e.getValue(); 185 float v = e.getValue();
209 if (!ISNAN(v) && !ISINF(v)) { 186 if (!ISNAN(v) && !ISINF(v)) {
210 if (!m_haveExtents || v < m_valueMinimum) { 187 if (!m_haveExtents || v < m_valueMinimum) {
211 m_valueMinimum = v; allChange = true; 188 m_valueMinimum = v; allChange = true;
213 if (!m_haveExtents || v > m_valueMaximum) { 190 if (!m_haveExtents || v > m_valueMaximum) {
214 m_valueMaximum = v; allChange = true; 191 m_valueMaximum = v; allChange = true;
215 } 192 }
216 m_haveExtents = true; 193 m_haveExtents = true;
217 } 194 }
218 195 }
219 sv_frame_t f = e.getFrame(); 196
220 197 m_notifier.update(e.getFrame(), e.getDuration() + m_resolution);
221 if (!m_notifyOnAdd) { 198
222 if (m_sinceLastNotifyMin == -1 || f < m_sinceLastNotifyMin) {
223 m_sinceLastNotifyMin = f;
224 }
225 if (m_sinceLastNotifyMax == -1 || f > m_sinceLastNotifyMax) {
226 m_sinceLastNotifyMax = f;
227 }
228 }
229 }
230
231 if (m_notifyOnAdd) {
232 emit modelChangedWithin(e.getFrame(),
233 e.getFrame() + e.getDuration() + m_resolution);
234 }
235 if (allChange) { 199 if (allChange) {
236 emit modelChanged(); 200 emit modelChanged();
237 } 201 }
238 } 202 }
239 203
386 QString("type=\"sparse\" dimensions=\"3\" resolution=\"%1\" " 350 QString("type=\"sparse\" dimensions=\"3\" resolution=\"%1\" "
387 "notifyOnAdd=\"%2\" dataset=\"%3\" subtype=\"%4\" " 351 "notifyOnAdd=\"%2\" dataset=\"%3\" subtype=\"%4\" "
388 "valueQuantization=\"%5\" minimum=\"%6\" maximum=\"%7\" " 352 "valueQuantization=\"%5\" minimum=\"%6\" maximum=\"%7\" "
389 "units=\"%8\" %9") 353 "units=\"%8\" %9")
390 .arg(m_resolution) 354 .arg(m_resolution)
391 .arg(m_notifyOnAdd ? "true" : "false") 355 .arg("true") // always true after model reaches 100% -
356 // subsequent events are always notified
392 .arg(getObjectExportId(&m_events)) 357 .arg(getObjectExportId(&m_events))
393 .arg(m_subtype == FLEXI_NOTE ? "flexinote" : "note") 358 .arg(m_subtype == FLEXI_NOTE ? "flexinote" : "note")
394 .arg(m_valueQuantization) 359 .arg(m_valueQuantization)
395 .arg(m_valueMinimum) 360 .arg(m_valueMinimum)
396 .arg(m_valueMaximum) 361 .arg(m_valueMaximum)
397 .arg(m_units) 362 .arg(encodeEntities(m_units))
398 .arg(extraAttributes)); 363 .arg(extraAttributes));
399 364
400 m_events.toXml(out, indent, QString("dimensions=\"3\"")); 365 m_events.toXml(out, indent, QString("dimensions=\"3\""));
401 } 366 }
402 367
408 float m_valueMinimum; 373 float m_valueMinimum;
409 float m_valueMaximum; 374 float m_valueMaximum;
410 bool m_haveExtents; 375 bool m_haveExtents;
411 float m_valueQuantization; 376 float m_valueQuantization;
412 QString m_units; 377 QString m_units;
413
414 sv_frame_t m_extendTo; 378 sv_frame_t m_extendTo;
415 379 DeferredNotifier m_notifier;
416 bool m_notifyOnAdd; 380 int m_completion;
417 sv_frame_t m_sinceLastNotifyMin;
418 sv_frame_t m_sinceLastNotifyMax;
419 381
420 EventSeries m_events; 382 EventSeries m_events;
421
422 int m_completion;
423 383
424 mutable QMutex m_mutex; 384 mutable QMutex m_mutex;
425 385
426 //!!! do we have general docs for ownership and synchronisation of models? 386 //!!! do we have general docs for ownership and synchronisation of models?
427 // this might be a good opportunity to stop using bare pointers to them 387 // this might be a good opportunity to stop using bare pointers to them