annotate data/model/EditableDenseThreeDimensionalModel.cpp @ 360:ac300d385ab2

* Various fixes to object lifetime management, particularly in the spectrum layer and for notification of main model deletion. The main purpose of this is to improve the behaviour of the spectrum, but I think it may also help with #1840922 Various crashes in Layer Summary window.
author Chris Cannam
date Wed, 23 Jan 2008 15:43:27 +0000
parents 1afaf98dbf11
children 7aa1de571880
rev   line source
Chris@152 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@152 2
Chris@152 3 /*
Chris@152 4 Sonic Visualiser
Chris@152 5 An audio file viewer and annotation editor.
Chris@152 6 Centre for Digital Music, Queen Mary, University of London.
Chris@202 7 This file copyright 2006 Chris Cannam and QMUL.
Chris@152 8
Chris@152 9 This program is free software; you can redistribute it and/or
Chris@152 10 modify it under the terms of the GNU General Public License as
Chris@152 11 published by the Free Software Foundation; either version 2 of the
Chris@152 12 License, or (at your option) any later version. See the file
Chris@152 13 COPYING included with this distribution for more information.
Chris@152 14 */
Chris@152 15
Chris@152 16 #include "EditableDenseThreeDimensionalModel.h"
Chris@152 17
Chris@152 18 #include <QTextStream>
Chris@152 19
Chris@181 20 #include <iostream>
Chris@181 21
Chris@256 22 #include <cmath>
Chris@256 23
Chris@152 24 EditableDenseThreeDimensionalModel::EditableDenseThreeDimensionalModel(size_t sampleRate,
Chris@152 25 size_t resolution,
Chris@152 26 size_t yBinCount,
Chris@152 27 bool notifyOnAdd) :
Chris@152 28 m_sampleRate(sampleRate),
Chris@152 29 m_resolution(resolution),
Chris@152 30 m_yBinCount(yBinCount),
Chris@152 31 m_minimum(0.0),
Chris@152 32 m_maximum(0.0),
Chris@256 33 m_haveExtents(false),
Chris@152 34 m_notifyOnAdd(notifyOnAdd),
Chris@152 35 m_sinceLastNotifyMin(-1),
Chris@152 36 m_sinceLastNotifyMax(-1),
Chris@152 37 m_completion(100)
Chris@152 38 {
Chris@152 39 }
Chris@152 40
Chris@152 41 bool
Chris@152 42 EditableDenseThreeDimensionalModel::isOK() const
Chris@152 43 {
Chris@152 44 return true;
Chris@152 45 }
Chris@152 46
Chris@152 47 size_t
Chris@152 48 EditableDenseThreeDimensionalModel::getSampleRate() const
Chris@152 49 {
Chris@152 50 return m_sampleRate;
Chris@152 51 }
Chris@152 52
Chris@152 53 size_t
Chris@152 54 EditableDenseThreeDimensionalModel::getStartFrame() const
Chris@152 55 {
Chris@152 56 return 0;
Chris@152 57 }
Chris@152 58
Chris@152 59 size_t
Chris@152 60 EditableDenseThreeDimensionalModel::getEndFrame() const
Chris@152 61 {
Chris@152 62 return m_resolution * m_data.size() + (m_resolution - 1);
Chris@152 63 }
Chris@152 64
Chris@152 65 Model *
Chris@152 66 EditableDenseThreeDimensionalModel::clone() const
Chris@152 67 {
Chris@152 68 EditableDenseThreeDimensionalModel *model =
Chris@152 69 new EditableDenseThreeDimensionalModel
Chris@152 70 (m_sampleRate, m_resolution, m_yBinCount);
Chris@152 71
Chris@152 72 model->m_minimum = m_minimum;
Chris@152 73 model->m_maximum = m_maximum;
Chris@256 74 model->m_haveExtents = m_haveExtents;
Chris@152 75
Chris@152 76 for (size_t i = 0; i < m_data.size(); ++i) {
Chris@182 77 model->setColumn(i, m_data[i]);
Chris@152 78 }
Chris@152 79
Chris@152 80 return model;
Chris@152 81 }
Chris@152 82
Chris@152 83 size_t
Chris@152 84 EditableDenseThreeDimensionalModel::getResolution() const
Chris@152 85 {
Chris@152 86 return m_resolution;
Chris@152 87 }
Chris@152 88
Chris@152 89 void
Chris@152 90 EditableDenseThreeDimensionalModel::setResolution(size_t sz)
Chris@152 91 {
Chris@152 92 m_resolution = sz;
Chris@152 93 }
Chris@152 94
Chris@152 95 size_t
Chris@182 96 EditableDenseThreeDimensionalModel::getWidth() const
Chris@182 97 {
Chris@182 98 return m_data.size();
Chris@182 99 }
Chris@182 100
Chris@182 101 size_t
Chris@182 102 EditableDenseThreeDimensionalModel::getHeight() const
Chris@152 103 {
Chris@152 104 return m_yBinCount;
Chris@152 105 }
Chris@152 106
Chris@152 107 void
Chris@182 108 EditableDenseThreeDimensionalModel::setHeight(size_t sz)
Chris@152 109 {
Chris@152 110 m_yBinCount = sz;
Chris@152 111 }
Chris@152 112
Chris@152 113 float
Chris@152 114 EditableDenseThreeDimensionalModel::getMinimumLevel() const
Chris@152 115 {
Chris@152 116 return m_minimum;
Chris@152 117 }
Chris@152 118
Chris@152 119 void
Chris@152 120 EditableDenseThreeDimensionalModel::setMinimumLevel(float level)
Chris@152 121 {
Chris@152 122 m_minimum = level;
Chris@152 123 }
Chris@152 124
Chris@152 125 float
Chris@152 126 EditableDenseThreeDimensionalModel::getMaximumLevel() const
Chris@152 127 {
Chris@152 128 return m_maximum;
Chris@152 129 }
Chris@152 130
Chris@152 131 void
Chris@152 132 EditableDenseThreeDimensionalModel::setMaximumLevel(float level)
Chris@152 133 {
Chris@152 134 m_maximum = level;
Chris@152 135 }
Chris@152 136
Chris@152 137 void
Chris@182 138 EditableDenseThreeDimensionalModel::getColumn(size_t index,
Chris@182 139 Column &result) const
Chris@152 140 {
Chris@152 141 QMutexLocker locker(&m_mutex);
Chris@152 142
Chris@182 143 if (index < m_data.size()) {
Chris@152 144 result = m_data[index];
Chris@152 145 } else {
Chris@152 146 result.clear();
Chris@152 147 }
Chris@152 148
Chris@152 149 while (result.size() < m_yBinCount) result.push_back(m_minimum);
Chris@152 150 }
Chris@152 151
Chris@152 152 float
Chris@182 153 EditableDenseThreeDimensionalModel::getValueAt(size_t index, size_t n) const
Chris@152 154 {
Chris@152 155 QMutexLocker locker(&m_mutex);
Chris@152 156
Chris@182 157 if (index < m_data.size()) {
Chris@182 158 const Column &s = m_data[index];
Chris@256 159 // std::cerr << "index " << index << ", n " << n << ", res " << m_resolution << ", size " << s.size()
Chris@256 160 // << std::endl;
Chris@152 161 if (n < s.size()) return s[n];
Chris@152 162 }
Chris@152 163
Chris@152 164 return m_minimum;
Chris@152 165 }
Chris@152 166
Chris@152 167 void
Chris@182 168 EditableDenseThreeDimensionalModel::setColumn(size_t index,
Chris@182 169 const Column &values)
Chris@152 170 {
Chris@152 171 QMutexLocker locker(&m_mutex);
Chris@152 172
Chris@182 173 while (index >= m_data.size()) {
Chris@182 174 m_data.push_back(Column());
Chris@152 175 }
Chris@152 176
Chris@152 177 bool allChange = false;
Chris@152 178
Chris@152 179 for (size_t i = 0; i < values.size(); ++i) {
Chris@256 180 float value = values[i];
Chris@257 181 if (std::isnan(value) || std::isinf(value)) {
Chris@256 182 continue;
Chris@256 183 }
Chris@256 184 if (!m_haveExtents || value < m_minimum) {
Chris@256 185 m_minimum = value;
Chris@152 186 allChange = true;
Chris@152 187 }
Chris@256 188 if (!m_haveExtents || value > m_maximum) {
Chris@256 189 m_maximum = value;
Chris@152 190 allChange = true;
Chris@152 191 }
Chris@256 192 m_haveExtents = true;
Chris@152 193 }
Chris@152 194
Chris@152 195 m_data[index] = values;
Chris@152 196
Chris@182 197 long windowStart = index;
Chris@182 198 windowStart *= m_resolution;
Chris@182 199
Chris@152 200 if (m_notifyOnAdd) {
Chris@152 201 if (allChange) {
Chris@152 202 emit modelChanged();
Chris@152 203 } else {
Chris@152 204 emit modelChanged(windowStart, windowStart + m_resolution);
Chris@152 205 }
Chris@152 206 } else {
Chris@152 207 if (allChange) {
Chris@152 208 m_sinceLastNotifyMin = -1;
Chris@152 209 m_sinceLastNotifyMax = -1;
Chris@152 210 emit modelChanged();
Chris@152 211 } else {
Chris@152 212 if (m_sinceLastNotifyMin == -1 ||
Chris@152 213 windowStart < m_sinceLastNotifyMin) {
Chris@152 214 m_sinceLastNotifyMin = windowStart;
Chris@152 215 }
Chris@152 216 if (m_sinceLastNotifyMax == -1 ||
Chris@152 217 windowStart > m_sinceLastNotifyMax) {
Chris@152 218 m_sinceLastNotifyMax = windowStart;
Chris@152 219 }
Chris@152 220 }
Chris@152 221 }
Chris@152 222 }
Chris@152 223
Chris@152 224 QString
Chris@152 225 EditableDenseThreeDimensionalModel::getBinName(size_t n) const
Chris@152 226 {
Chris@152 227 if (m_binNames.size() > n) return m_binNames[n];
Chris@152 228 else return "";
Chris@152 229 }
Chris@152 230
Chris@152 231 void
Chris@152 232 EditableDenseThreeDimensionalModel::setBinName(size_t n, QString name)
Chris@152 233 {
Chris@152 234 while (m_binNames.size() <= n) m_binNames.push_back("");
Chris@152 235 m_binNames[n] = name;
Chris@152 236 emit modelChanged();
Chris@152 237 }
Chris@152 238
Chris@152 239 void
Chris@152 240 EditableDenseThreeDimensionalModel::setBinNames(std::vector<QString> names)
Chris@152 241 {
Chris@152 242 m_binNames = names;
Chris@152 243 emit modelChanged();
Chris@152 244 }
Chris@152 245
Chris@152 246 void
Chris@333 247 EditableDenseThreeDimensionalModel::setCompletion(int completion, bool update)
Chris@152 248 {
Chris@152 249 if (m_completion != completion) {
Chris@152 250 m_completion = completion;
Chris@152 251
Chris@152 252 if (completion == 100) {
Chris@152 253
Chris@152 254 m_notifyOnAdd = true; // henceforth
Chris@152 255 emit modelChanged();
Chris@152 256
Chris@152 257 } else if (!m_notifyOnAdd) {
Chris@152 258
Chris@333 259 if (update &&
Chris@333 260 m_sinceLastNotifyMin >= 0 &&
Chris@152 261 m_sinceLastNotifyMax >= 0) {
Chris@152 262 emit modelChanged(m_sinceLastNotifyMin,
Chris@152 263 m_sinceLastNotifyMax + m_resolution);
Chris@152 264 m_sinceLastNotifyMin = m_sinceLastNotifyMax = -1;
Chris@152 265 } else {
Chris@152 266 emit completionChanged();
Chris@152 267 }
Chris@152 268 } else {
Chris@152 269 emit completionChanged();
Chris@152 270 }
Chris@152 271 }
Chris@152 272 }
Chris@152 273
Chris@318 274 QString
Chris@318 275 EditableDenseThreeDimensionalModel::toDelimitedDataString(QString delimiter) const
Chris@318 276 {
Chris@318 277 QString s;
Chris@318 278 for (size_t i = 0; i < m_data.size(); ++i) {
Chris@318 279 QStringList list;
Chris@318 280 for (size_t j = 0; j < m_data[i].size(); ++j) {
Chris@318 281 list << QString("%1").arg(m_data[i][j]);
Chris@318 282 }
Chris@318 283 s += list.join(delimiter) + "\n";
Chris@318 284 }
Chris@318 285 return s;
Chris@318 286 }
Chris@318 287
Chris@152 288 void
Chris@152 289 EditableDenseThreeDimensionalModel::toXml(QTextStream &out,
Chris@314 290 QString indent,
Chris@314 291 QString extraAttributes) const
Chris@152 292 {
Chris@152 293 // For historical reasons we read and write "resolution" as "windowSize"
Chris@152 294
Chris@318 295 std::cerr << "EditableDenseThreeDimensionalModel::toXml" << std::endl;
Chris@318 296
Chris@314 297 Model::toXml
Chris@314 298 (out, indent,
Chris@314 299 QString("type=\"dense\" dimensions=\"3\" windowSize=\"%1\" yBinCount=\"%2\" minimum=\"%3\" maximum=\"%4\" dataset=\"%5\" %6")
Chris@152 300 .arg(m_resolution)
Chris@152 301 .arg(m_yBinCount)
Chris@152 302 .arg(m_minimum)
Chris@152 303 .arg(m_maximum)
Chris@152 304 .arg(getObjectExportId(&m_data))
Chris@152 305 .arg(extraAttributes));
Chris@152 306
Chris@152 307 out << indent;
Chris@152 308 out << QString("<dataset id=\"%1\" dimensions=\"3\" separator=\" \">\n")
Chris@152 309 .arg(getObjectExportId(&m_data));
Chris@152 310
Chris@152 311 for (size_t i = 0; i < m_binNames.size(); ++i) {
Chris@152 312 if (m_binNames[i] != "") {
Chris@152 313 out << indent + " ";
Chris@152 314 out << QString("<bin number=\"%1\" name=\"%2\"/>\n")
Chris@152 315 .arg(i).arg(m_binNames[i]);
Chris@152 316 }
Chris@152 317 }
Chris@152 318
Chris@152 319 for (size_t i = 0; i < m_data.size(); ++i) {
Chris@152 320 out << indent + " ";
Chris@152 321 out << QString("<row n=\"%1\">").arg(i);
Chris@152 322 for (size_t j = 0; j < m_data[i].size(); ++j) {
Chris@152 323 if (j > 0) out << " ";
Chris@152 324 out << m_data[i][j];
Chris@152 325 }
Chris@152 326 out << QString("</row>\n");
Chris@318 327 out.flush();
Chris@152 328 }
Chris@152 329
Chris@152 330 out << indent + "</dataset>\n";
Chris@152 331 }
Chris@152 332
Chris@152 333