annotate data/model/IntervalModel.h @ 455:3e0f1f7bec85

* Fix a nasty and long-standing race condition in MatrixFile's use of FileReadThread that was causing crashes sometimes
author Chris Cannam
date Thu, 09 Oct 2008 20:10:28 +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