annotate data/model/PathModel.h @ 1725:78fe29adfd16

Re-implement extendEndFrame behaviour, used by Tony application
author Chris Cannam
date Wed, 19 Jun 2019 13:32:52 +0100
parents cd6be949a16a
children d91ff235e69d
rev   line source
Chris@407 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@407 2
Chris@407 3 /*
Chris@407 4 Sonic Visualiser
Chris@407 5 An audio file viewer and annotation editor.
Chris@407 6 Centre for Digital Music, Queen Mary, University of London.
Chris@407 7 This file copyright 2007 QMUL.
Chris@407 8
Chris@407 9 This program is free software; you can redistribute it and/or
Chris@407 10 modify it under the terms of the GNU General Public License as
Chris@407 11 published by the Free Software Foundation; either version 2 of the
Chris@407 12 License, or (at your option) any later version. See the file
Chris@407 13 COPYING included with this distribution for more information.
Chris@407 14 */
Chris@407 15
Chris@1581 16 #ifndef SV_PATH_MODEL_H
Chris@1581 17 #define SV_PATH_MODEL_H
Chris@407 18
Chris@407 19 #include "Model.h"
Chris@1662 20 #include "DeferredNotifier.h"
Chris@407 21 #include "base/RealTime.h"
Chris@1040 22 #include "base/BaseTypes.h"
Chris@407 23
Chris@1662 24 #include "base/XmlExportable.h"
Chris@1662 25 #include "base/RealTime.h"
Chris@1662 26
Chris@407 27 #include <QStringList>
Chris@1662 28 #include <set>
Chris@407 29
Chris@407 30 struct PathPoint
Chris@407 31 {
Chris@1662 32 PathPoint(sv_frame_t _frame) :
Chris@1662 33 frame(_frame), mapframe(_frame) { }
Chris@1040 34 PathPoint(sv_frame_t _frame, sv_frame_t _mapframe) :
Chris@407 35 frame(_frame), mapframe(_mapframe) { }
Chris@407 36
Chris@1040 37 sv_frame_t frame;
Chris@1040 38 sv_frame_t mapframe;
Chris@407 39
Chris@407 40 void toXml(QTextStream &stream, QString indent = "",
Chris@407 41 QString extraAttributes = "") const {
Chris@407 42 stream << QString("%1<point frame=\"%2\" mapframe=\"%3\" %4/>\n")
Chris@407 43 .arg(indent).arg(frame).arg(mapframe).arg(extraAttributes);
Chris@407 44 }
Chris@407 45
Chris@1060 46 QString toDelimitedDataString(QString delimiter, DataExportOptions,
Chris@1040 47 sv_samplerate_t sampleRate) const {
Chris@407 48 QStringList list;
Chris@407 49 list << RealTime::frame2RealTime(frame, sampleRate).toString().c_str();
Chris@407 50 list << QString("%1").arg(mapframe);
Chris@407 51 return list.join(delimiter);
Chris@407 52 }
Chris@407 53
Chris@1662 54 bool operator<(const PathPoint &p2) const {
Chris@1662 55 if (frame != p2.frame) return frame < p2.frame;
Chris@1662 56 return mapframe < p2.mapframe;
Chris@1662 57 }
Chris@407 58 };
Chris@407 59
Chris@1662 60 class PathModel : public Model
Chris@407 61 {
Chris@407 62 public:
Chris@1662 63 typedef std::set<PathPoint> PointList;
Chris@407 64
Chris@1662 65 PathModel(sv_samplerate_t sampleRate,
Chris@1662 66 int resolution,
Chris@1662 67 bool notifyOnAdd = true) :
Chris@1662 68 m_sampleRate(sampleRate),
Chris@1662 69 m_resolution(resolution),
Chris@1662 70 m_notifier(this,
Chris@1662 71 notifyOnAdd ?
Chris@1662 72 DeferredNotifier::NOTIFY_ALWAYS :
Chris@1662 73 DeferredNotifier::NOTIFY_DEFERRED),
Chris@1662 74 m_completion(100),
Chris@1662 75 m_start(0),
Chris@1662 76 m_end(0) {
Chris@1662 77 }
Chris@1662 78
Chris@1667 79 QString getTypeName() const override { return tr("Path"); }
cannam@1695 80 bool isSparse() const override { return true; }
Chris@1662 81 bool isOK() const override { return true; }
Chris@1662 82
Chris@1662 83 sv_frame_t getStartFrame() const override {
Chris@1662 84 return m_start;
Chris@1662 85 }
Chris@1725 86 sv_frame_t getTrueEndFrame() const override {
Chris@1662 87 return m_end;
Chris@1662 88 }
Chris@1662 89
Chris@1662 90 sv_samplerate_t getSampleRate() const override { return m_sampleRate; }
Chris@1662 91 int getResolution() const { return m_resolution; }
Chris@1662 92
cannam@1695 93 int getCompletion() const override { return m_completion; }
Chris@1662 94
Chris@1662 95 void setCompletion(int completion, bool update = true) {
Chris@1662 96
Chris@1662 97 { QMutexLocker locker(&m_mutex);
Chris@1662 98 if (m_completion == completion) return;
Chris@1662 99 m_completion = completion;
Chris@1662 100 }
Chris@1662 101
Chris@1662 102 if (update) {
Chris@1662 103 m_notifier.makeDeferredNotifications();
Chris@1662 104 }
Chris@1662 105
Chris@1662 106 emit completionChanged();
Chris@1662 107
Chris@1662 108 if (completion == 100) {
Chris@1662 109 // henceforth:
Chris@1662 110 m_notifier.switchMode(DeferredNotifier::NOTIFY_ALWAYS);
Chris@1662 111 emit modelChanged();
Chris@1662 112 }
Chris@407 113 }
Chris@425 114
Chris@425 115 /**
Chris@1662 116 * Query methods.
Chris@425 117 */
Chris@1670 118 int getPointCount() const {
Chris@1670 119 return int(m_points.size());
Chris@1670 120 }
Chris@1662 121 const PointList &getPoints() const {
Chris@1662 122 return m_points;
Chris@1662 123 }
Chris@425 124
Chris@1662 125 /**
Chris@1662 126 * Editing methods.
Chris@1662 127 */
Chris@1662 128 void add(PathPoint p) {
Chris@1662 129
Chris@1662 130 { QMutexLocker locker(&m_mutex);
Chris@1662 131 m_points.insert(p);
Chris@1662 132
Chris@1662 133 if (m_start == m_end) {
Chris@1662 134 m_start = p.frame;
Chris@1662 135 m_end = m_start + m_resolution;
Chris@1662 136 } else {
Chris@1662 137 if (p.frame < m_start) {
Chris@1662 138 m_start = p.frame;
Chris@1662 139 }
Chris@1662 140 if (p.frame + m_resolution > m_end) {
Chris@1662 141 m_end = p.frame + m_resolution;
Chris@1662 142 }
Chris@1662 143 }
Chris@1662 144 }
Chris@1662 145
Chris@1662 146 m_notifier.update(p.frame, m_resolution);
Chris@1662 147 }
Chris@1662 148
Chris@1662 149 void remove(PathPoint p) {
Chris@1662 150 { QMutexLocker locker(&m_mutex);
Chris@1662 151 m_points.erase(p);
Chris@1662 152 }
Chris@1662 153
Chris@1662 154 emit modelChangedWithin(p.frame, p.frame + m_resolution);
Chris@1662 155 }
Chris@1662 156
Chris@1662 157 void clear() {
Chris@1662 158 { QMutexLocker locker(&m_mutex);
Chris@1662 159 m_start = m_end = 0;
Chris@1662 160 m_points.clear();
Chris@1662 161 }
Chris@1662 162 }
Chris@1662 163
Chris@1662 164 /**
Chris@1662 165 * XmlExportable methods.
Chris@1662 166 */
Chris@1662 167 void toXml(QTextStream &out,
Chris@1662 168 QString indent = "",
Chris@1662 169 QString extraAttributes = "") const override {
Chris@1677 170
Chris@1677 171 // Our dataset doesn't have its own export ID, we just use
Chris@1677 172 // ours. Actually any model could do that, since datasets
Chris@1677 173 // aren't in the same id-space as models when re-read
Chris@1662 174
Chris@1662 175 Model::toXml
Chris@1662 176 (out,
Chris@1662 177 indent,
Chris@1662 178 QString("type=\"sparse\" dimensions=\"2\" resolution=\"%1\" "
Chris@1662 179 "notifyOnAdd=\"%2\" dataset=\"%3\" subtype=\"path\" %4")
Chris@1662 180 .arg(m_resolution)
Chris@1662 181 .arg("true") // always true after model reaches 100% -
Chris@1662 182 // subsequent points are always notified
Chris@1677 183 .arg(getExportId())
Chris@1662 184 .arg(extraAttributes));
Chris@1662 185
Chris@1675 186 out << indent << QString("<dataset id=\"%1\" dimensions=\"2\">\n")
Chris@1677 187 .arg(getExportId());
Chris@1662 188
Chris@1675 189 for (PathPoint p: m_points) {
Chris@1675 190 p.toXml(out, indent + " ", "");
Chris@1675 191 }
Chris@1675 192
Chris@1675 193 out << indent << "</dataset>\n";
Chris@1662 194 }
Chris@1679 195
Chris@1679 196 QString toDelimitedDataString(QString delimiter,
Chris@1679 197 DataExportOptions,
Chris@1679 198 sv_frame_t startFrame,
Chris@1679 199 sv_frame_t duration) const override {
Chris@1679 200
Chris@1679 201 QString s;
Chris@1679 202 for (PathPoint p: m_points) {
Chris@1679 203 if (p.frame < startFrame) continue;
Chris@1679 204 if (p.frame >= startFrame + duration) break;
Chris@1679 205 s += QString("%1%2%3\n")
Chris@1679 206 .arg(p.frame)
Chris@1679 207 .arg(delimiter)
Chris@1679 208 .arg(p.mapframe);
Chris@1679 209 }
Chris@1679 210
Chris@1679 211 return s;
Chris@1679 212 }
Chris@1662 213
Chris@1662 214 protected:
Chris@1662 215 sv_samplerate_t m_sampleRate;
Chris@1662 216 int m_resolution;
Chris@1662 217
Chris@1662 218 DeferredNotifier m_notifier;
Chris@1662 219 int m_completion;
Chris@1662 220
Chris@1662 221 sv_frame_t m_start;
Chris@1662 222 sv_frame_t m_end;
Chris@1662 223 PointList m_points;
Chris@1662 224
Chris@1662 225 mutable QMutex m_mutex;
Chris@407 226 };
Chris@407 227
Chris@407 228
Chris@407 229 #endif