1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351
|
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
/*
Sonic Visualiser
An audio file viewer and annotation editor.
Centre for Digital Music, Queen Mary, University of London.
This file copyright 2006 Chris Cannam.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version. See the file
COPYING included with this distribution for more information.
*/
#ifndef SV_MODEL_H
#define SV_MODEL_H
#include <vector>
#include <atomic>
#include <QObject>
#include <QMutex>
#include "base/ById.h"
#include "base/XmlExportable.h"
#include "base/Playable.h"
#include "base/BaseTypes.h"
#include "base/DataExportOptions.h"
namespace sv {
class ZoomConstraint;
class AlignmentModel;
/**
* Model is the base class for all data models that represent any sort
* of data on a time scale based on an audio frame rate.
*
* Model classes are expected to be thread-safe, particularly with
* regard to content rather than metadata (e.g. populating a model
* from a transform running in a background thread while displaying it
* in a UI layer).
*
* Never store a pointer to a model unless it is completely private to
* the code owning it. Models should be referred to using their
* ModelId id and looked up from the ById pool when needed. This
* returns a shared pointer, which ensures a sufficient lifespan for a
* transient operation locally. See notes in ById.h. The document
* unregisters models when it is closed, and then they are deleted
* when the last shared pointer instance expires.
*/
class Model : public QObject,
public WithTypedId<Model>,
public XmlExportable,
public Playable
{
Q_OBJECT
public:
typedef Id ModelId;
virtual ~Model();
/**
* Return true if the model was constructed successfully. Classes
* that refer to the model should always test this before use.
*/
virtual bool isOK() const = 0;
/**
* Return the first audio frame spanned by the model.
*/
virtual sv_frame_t getStartFrame() const = 0;
/**
* Return the audio frame at the end of the model, i.e. the final
* frame contained within the model plus 1 (rounded up to the
* model's "resolution" granularity, if more than 1). The end
* frame minus the start frame should yield the total duration in
* frames (as a multiple of the resolution) spanned by the
* model. This is broadly consistent with the definition of the
* end frame of a Selection object.
*
* If the end has been extended by extendEndFrame() beyond the
* true end frame, return the extended end instead. This is
* usually the behaviour you want.
*/
sv_frame_t getEndFrame() const {
sv_frame_t trueEnd = getTrueEndFrame();
if (m_extendTo > trueEnd) {
return m_extendTo;
} else {
return trueEnd;
}
}
/**
* Return the audio frame at the end of the model. This is
* identical to getEndFrame(), except that it ignores any extended
* duration set with extendEndFrame().
*/
virtual sv_frame_t getTrueEndFrame() const = 0;
/**
* Extend the end of the model. If this is set to something beyond
* the true end of the data within the model, then getEndFrame()
* will return this value instead of the true end. (This is used
* by the Tony application.)
*/
void extendEndFrame(sv_frame_t to) {
m_extendTo = to;
}
/**
* Return the frame rate in frames per second.
*/
virtual sv_samplerate_t getSampleRate() const = 0;
/**
* Return the frame rate of the underlying material, if the model
* itself has already been resampled.
*/
virtual sv_samplerate_t getNativeRate() const { return getSampleRate(); }
/**
* Return the "work title" of the model, if known.
*/
virtual QString getTitle() const;
/**
* Return the "artist" or "maker" of the model, if known.
*/
virtual QString getMaker() const;
/**
* Return the location of the data in this model (e.g. source
* URL). This should not normally be returned for editable models
* that have been edited.
*/
virtual QString getLocation() const;
/**
* Return the type of the model. For display purposes only.
*/
virtual QString getTypeName() const = 0;
/**
* Return true if this is a sparse model.
*/
virtual bool isSparse() const { return false; }
/**
* Return true if the model has finished loading or calculating
* all its data, for a model that is capable of calculating in a
* background thread.
*
* If "completion" is non-NULL, return through it an estimated
* percentage value showing how far through the background
* operation it thinks it is (for progress reporting). This should
* be identical to the value returned by getCompletion().
*
* A model that carries out all its calculation from the
* constructor or accessor functions would typically return true
* (and completion == 100) as long as isOK() is true. Other models
* may make the return value here depend on the internal
* completion status.
*
* See also getCompletion().
*/
virtual bool isReady(int *cp = nullptr) const {
int c = getCompletion();
if (cp) *cp = c;
if (!isOK()) return false;
else return (c == 100);
}
/**
* Return an estimated percentage value showing how far through
* any background operation used to calculate or load the model
* data the model thinks it is. Must return 100 when the model is
* complete.
*
* A model that carries out all its calculation from the
* constructor or accessor functions might return 0 if isOK() is
* false and 100 if isOK() is true. Other models may make the
* return value here depend on the internal completion status.
*
* See also isReady().
*/
virtual int getCompletion() const = 0;
/**
* If this model imposes a zoom constraint, i.e. some limit to the
* set of resolutions at which its data can meaningfully be
* displayed, then return it.
*/
virtual const ZoomConstraint *getZoomConstraint() const {
return 0;
}
/**
* If this model was derived from another, return the id of the
* model it was derived from. The assumption is that the source
* model's alignment will also apply to this model, unless some
* other property (such as a specific alignment model set on this
* model) indicates otherwise.
*/
virtual ModelId getSourceModel() const {
return m_sourceModel;
}
/**
* Set the source model for this model.
*/
virtual void setSourceModel(ModelId model);
/**
* Specify an alignment between this model's timeline and that of
* a reference model. The alignment model, of type AlignmentModel,
* records both the reference and the alignment.
*/
virtual void setAlignment(ModelId alignmentModel);
/**
* Retrieve the alignment model for this model. This is not a
* generally useful function, as the alignment you really want may
* be performed by the source model instead. You should normally
* use getAlignmentReference, alignToReference and
* alignFromReference instead of this. The main intended
* application for this function is in streaming out alignments to
* the session file.
*/
virtual const ModelId getAlignment() const;
/**
* Return the reference model for the current alignment timeline,
* if any.
*/
virtual const ModelId getAlignmentReference() const;
/**
* Return the frame number of the reference model that corresponds
* to the given frame number in this model.
*/
virtual sv_frame_t alignToReference(sv_frame_t frame) const;
/**
* Return the frame number in this model that corresponds to the
* given frame number of the reference model.
*/
virtual sv_frame_t alignFromReference(sv_frame_t referenceFrame) const;
/**
* Return the completion percentage for the alignment model: 100
* if there is no alignment model or it has been entirely
* calculated, or less than 100 if it is still being calculated.
*/
virtual int getAlignmentCompletion() const;
/**
* Set the event, feature, or signal type URI for the features
* contained in this model, according to the Audio Features RDF
* ontology.
*/
void setRDFTypeURI(QString uri) { m_typeUri = uri; }
/**
* Retrieve the event, feature, or signal type URI for the
* features contained in this model, if previously set with
* setRDFTypeURI.
*/
QString getRDFTypeURI() const { return m_typeUri; }
void toXml(QTextStream &stream,
QString indent = "",
QString extraAttributes = "") const override;
/**
* Return a label for each column that would be written by
* toStringExportRows.
*/
virtual QVector<QString>
getStringExportHeaders(DataExportOptions options) const = 0;
/**
* Emit events starting within the given range as string rows
* ready for conversion to an e.g. comma-separated data format.
*/
virtual QVector<QVector<QString>>
toStringExportRows(DataExportOptions options,
sv_frame_t startFrame,
sv_frame_t duration) const = 0;
signals:
/**
* Emitted when a model has been edited (or more data retrieved
* from cache, in the case of a cached model that generates slowly)
*/
void modelChanged(ModelId myId);
/**
* Emitted when a model has been edited (or more data retrieved
* from cache, in the case of a cached model that generates slowly)
*/
void modelChangedWithin(ModelId myId, sv_frame_t startFrame, sv_frame_t endFrame);
/**
* Emitted when some internal processing has advanced a stage, but
* the model has not changed externally. Views should respond by
* updating any progress meters or other monitoring, but not
* refreshing the actual view.
*/
void completionChanged(ModelId myId);
/**
* Emitted when internal processing is complete (i.e. when
* isReady() would return true, with completion at 100).
*/
void ready(ModelId myId);
/**
* Emitted when the completion percentage changes for the
* calculation of this model's alignment model. (The ModelId
* provided is that of this model, not the alignment model.)
*/
void alignmentCompletionChanged(ModelId myId);
private slots:
void alignmentModelCompletionChanged(ModelId);
protected:
Model() : m_extendTo(0) { }
// Not provided.
Model(const Model &) =delete;
Model &operator=(const Model &) =delete;
mutable QMutex m_mutex;
ModelId m_sourceModel;
ModelId m_alignmentModel;
QString m_typeUri;
std::atomic<sv_frame_t> m_extendTo;
};
typedef Model::Id ModelId;
typedef TypedById<Model, Model::Id> ModelById;
} // end namespace sv
#endif
|