annotate data/model/IntervalModel.h @ 458:f60360209e5c

* Fix race condition in FFTFileCache when reading from the same FFT model from multiple threads (e.g. when applying more than one plugin at once)
author Chris Cannam
date Wed, 15 Oct 2008 12:08:02 +0000
parents 32c399d06374
children 6441b31b37ac
rev   line source
Chris@437 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@437 2
Chris@437 3 /*
Chris@437 4 Sonic Visualiser
Chris@437 5 An audio file viewer and annotation editor.
Chris@437 6 Centre for Digital Music, Queen Mary, University of London.
Chris@437 7 This file copyright 2006-2008 Chris Cannam and QMUL.
Chris@437 8
Chris@437 9 This program is free software; you can redistribute it and/or
Chris@437 10 modify it under the terms of the GNU General Public License as
Chris@437 11 published by the Free Software Foundation; either version 2 of the
Chris@437 12 License, or (at your option) any later version. See the file
Chris@437 13 COPYING included with this distribution for more information.
Chris@437 14 */
Chris@437 15
Chris@437 16 #ifndef _INTERVAL_MODEL_H_
Chris@437 17 #define _INTERVAL_MODEL_H_
Chris@437 18
Chris@437 19 #include "SparseValueModel.h"
Chris@437 20 #include "base/RealTime.h"
Chris@437 21
Chris@437 22 /**
Chris@437 23 * Model containing sparse data (points with some properties) of which
Chris@437 24 * the properties include a duration and an arbitrary float value.
Chris@437 25 * The other properties depend on the point type.
Chris@437 26 */
Chris@437 27
Chris@437 28 template <typename PointType>
Chris@437 29 class IntervalModel : public SparseValueModel<PointType>
Chris@437 30 {
Chris@437 31 public:
Chris@437 32 IntervalModel(size_t sampleRate, size_t resolution,
Chris@437 33 bool notifyOnAdd = true) :
Chris@437 34 SparseValueModel<PointType>(sampleRate, resolution, notifyOnAdd)
Chris@437 35 { }
Chris@437 36
Chris@437 37 IntervalModel(size_t sampleRate, size_t resolution,
Chris@437 38 float valueMinimum, float valueMaximum,
Chris@437 39 bool notifyOnAdd = true) :
Chris@437 40 SparseValueModel<PointType>(sampleRate, resolution,
Chris@437 41 valueMinimum, valueMaximum,
Chris@437 42 notifyOnAdd)
Chris@437 43 { }
Chris@437 44
Chris@437 45 /**
Chris@437 46 * PointTypes have a duration, so this returns all points that span any
Chris@437 47 * of the given range (as well as the usual additional few before
Chris@437 48 * and after). Consequently this can be very slow (optimised data
Chris@437 49 * structures still to be done!).
Chris@437 50 */
Chris@437 51 virtual typename SparseValueModel<PointType>::PointList getPoints(long start, long end) const;
Chris@437 52
Chris@437 53 /**
Chris@437 54 * PointTypes have a duration, so this returns all points that span the
Chris@437 55 * given frame. Consequently this can be very slow (optimised
Chris@437 56 * data structures still to be done!).
Chris@437 57 */
Chris@437 58 virtual typename SparseValueModel<PointType>::PointList getPoints(long frame) const;
Chris@437 59
Chris@437 60 /**
Chris@437 61 * TabularModel methods.
Chris@437 62 */
Chris@437 63
Chris@437 64 virtual QVariant getData(int row, int column, int role) const
Chris@437 65 {
Chris@437 66 if (column < 2) {
Chris@437 67 return SparseValueModel<PointType>::getData
Chris@437 68 (row, column, role);
Chris@437 69 }
Chris@437 70
Chris@437 71 typename SparseModel<PointType>::PointList::const_iterator i
Chris@437 72 = SparseModel<PointType>::getPointListIteratorForRow(row);
Chris@437 73 if (i == SparseModel<PointType>::m_points.end()) return QVariant();
Chris@437 74
Chris@437 75 switch (column) {
Chris@437 76 case 2:
Chris@437 77 if (role == Qt::EditRole || role == TabularModel::SortRole) return i->value;
Chris@437 78 else return QString("%1 %2").arg(i->value).arg
Chris@437 79 (IntervalModel<PointType>::getScaleUnits());
Chris@437 80 case 3: return int(i->duration); //!!! could be better presented
Chris@437 81 default: return QVariant();
Chris@437 82 }
Chris@437 83 }
Chris@437 84
Chris@437 85 virtual Command *getSetDataCommand(int row, int column, const QVariant &value, int role)
Chris@437 86 {
Chris@438 87 typedef IntervalModel<PointType> I;
Chris@438 88
Chris@437 89 if (column < 2) {
Chris@437 90 return SparseValueModel<PointType>::getSetDataCommand
Chris@437 91 (row, column, value, role);
Chris@437 92 }
Chris@437 93
Chris@437 94 if (role != Qt::EditRole) return false;
Chris@438 95 typename I::PointList::const_iterator i
Chris@438 96 = I::getPointListIteratorForRow(row);
Chris@438 97 if (i == I::m_points.end()) return false;
Chris@438 98 typename I::EditCommand *command = new typename I::EditCommand
Chris@438 99 (this, I::tr("Edit Data"));
Chris@437 100
Chris@437 101 PointType point(*i);
Chris@437 102 command->deletePoint(point);
Chris@437 103
Chris@437 104 switch (column) {
Chris@437 105 case 0: case 1: point.frame = value.toInt(); break;
Chris@437 106 case 2: point.value = value.toDouble(); break;
Chris@437 107 case 3: point.duration = value.toInt(); break;
Chris@437 108 }
Chris@437 109
Chris@437 110 command->addPoint(point);
Chris@437 111 return command->finish();
Chris@437 112 }
Chris@437 113
Chris@437 114 virtual bool isColumnTimeValue(int column) const
Chris@437 115 {
Chris@437 116 return (column < 2 || column == 3);
Chris@437 117 }
Chris@437 118 };
Chris@437 119
Chris@437 120 template <typename PointType>
Chris@437 121 typename SparseValueModel<PointType>::PointList
Chris@437 122 IntervalModel<PointType>::getPoints(long start, long end) const
Chris@437 123 {
Chris@437 124 typedef IntervalModel<PointType> I;
Chris@437 125
Chris@437 126 if (start > end) return typename I::PointList();
Chris@437 127
Chris@437 128 QMutex &mutex(I::m_mutex);
Chris@437 129 QMutexLocker locker(&mutex);
Chris@437 130
Chris@437 131 PointType endPoint(end);
Chris@437 132
Chris@437 133 typename I::PointListIterator endItr = I::m_points.upper_bound(endPoint);
Chris@437 134
Chris@437 135 if (endItr != I::m_points.end()) ++endItr;
Chris@437 136 if (endItr != I::m_points.end()) ++endItr;
Chris@437 137
Chris@437 138 typename I::PointList rv;
Chris@437 139
Chris@437 140 for (typename I::PointListIterator i = endItr; i != I::m_points.begin(); ) {
Chris@437 141 --i;
Chris@437 142 if (i->frame < start) {
Chris@437 143 if (i->frame + long(i->duration) >= start) {
Chris@437 144 rv.insert(*i);
Chris@437 145 }
Chris@437 146 } else if (i->frame <= end) {
Chris@437 147 rv.insert(*i);
Chris@437 148 }
Chris@437 149 }
Chris@437 150
Chris@437 151 return rv;
Chris@437 152 }
Chris@437 153
Chris@437 154 template <typename PointType>
Chris@437 155 typename SparseValueModel<PointType>::PointList
Chris@437 156 IntervalModel<PointType>::getPoints(long frame) const
Chris@437 157 {
Chris@437 158 typedef IntervalModel<PointType> I;
Chris@437 159
Chris@437 160 QMutex &mutex(I::m_mutex);
Chris@437 161 QMutexLocker locker(&mutex);
Chris@437 162
Chris@437 163 if (I::m_resolution == 0) return typename I::PointList();
Chris@437 164
Chris@437 165 long start = (frame / I::m_resolution) * I::m_resolution;
Chris@437 166 long end = start + I::m_resolution;
Chris@437 167
Chris@437 168 PointType endPoint(end);
Chris@437 169
Chris@437 170 typename I::PointListIterator endItr = I::m_points.upper_bound(endPoint);
Chris@437 171
Chris@437 172 typename I::PointList rv;
Chris@437 173
Chris@437 174 for (typename I::PointListIterator i = endItr; i != I::m_points.begin(); ) {
Chris@437 175 --i;
Chris@437 176 if (i->frame < start) {
Chris@437 177 if (i->frame + long(i->duration) >= start) {
Chris@437 178 rv.insert(*i);
Chris@437 179 }
Chris@437 180 } else if (i->frame <= end) {
Chris@437 181 rv.insert(*i);
Chris@437 182 }
Chris@437 183 }
Chris@437 184
Chris@437 185 return rv;
Chris@437 186 }
Chris@437 187
Chris@437 188 #endif