Mercurial > hg > svcore
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 |