annotate data/model/Model.h @ 1671:82d03c9661f9 single-point

Rework isReady()/getCompletion() on models. Previously the new overhauled models were implementing getCompletion() but inheriting a version of isReady() (from the Model base) that didn't call it, referring only to isOK(). So they were reporting completion as soon as they had begun. Instead hoist getCompletion() to abstract base and call it from Model::isReady().
author Chris Cannam
date Wed, 27 Mar 2019 13:15:16 +0000
parents f9b6e99e0520
children 0d89abd631ac
rev   line source
Chris@150 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@150 2
Chris@150 3 /*
Chris@150 4 Sonic Visualiser
Chris@150 5 An audio file viewer and annotation editor.
Chris@150 6 Centre for Digital Music, Queen Mary, University of London.
Chris@150 7 This file copyright 2006 Chris Cannam.
Chris@150 8
Chris@150 9 This program is free software; you can redistribute it and/or
Chris@150 10 modify it under the terms of the GNU General Public License as
Chris@150 11 published by the Free Software Foundation; either version 2 of the
Chris@150 12 License, or (at your option) any later version. See the file
Chris@150 13 COPYING included with this distribution for more information.
Chris@150 14 */
Chris@150 15
Chris@1500 16 #ifndef SV_MODEL_H
Chris@1500 17 #define SV_MODEL_H
Chris@150 18
Chris@150 19 #include <vector>
Chris@150 20 #include <QObject>
Chris@150 21
Chris@150 22 #include "base/XmlExportable.h"
Chris@391 23 #include "base/Playable.h"
Chris@1038 24 #include "base/BaseTypes.h"
Chris@1060 25 #include "base/DataExportOptions.h"
Chris@150 26
Chris@179 27 class ZoomConstraint;
Chris@319 28 class AlignmentModel;
Chris@179 29
Chris@1500 30 typedef int ModelId;
Chris@1500 31
Chris@150 32 /**
Chris@150 33 * Model is the base class for all data models that represent any sort
Chris@150 34 * of data on a time scale based on an audio frame rate.
Chris@150 35 */
Chris@150 36
Chris@179 37 class Model : public QObject,
Chris@1429 38 public XmlExportable,
Chris@391 39 public Playable
Chris@150 40 {
Chris@150 41 Q_OBJECT
Chris@150 42
Chris@150 43 public:
Chris@150 44 virtual ~Model();
Chris@150 45
Chris@150 46 /**
Chris@150 47 * Return true if the model was constructed successfully. Classes
Chris@150 48 * that refer to the model should always test this before use.
Chris@150 49 */
Chris@150 50 virtual bool isOK() const = 0;
Chris@150 51
Chris@150 52 /**
Chris@150 53 * Return the first audio frame spanned by the model.
Chris@150 54 */
Chris@1038 55 virtual sv_frame_t getStartFrame() const = 0;
Chris@150 56
Chris@150 57 /**
Chris@1611 58 * Return the audio frame at the end of the model, i.e. the final
Chris@1659 59 * frame contained within the model plus 1 (rounded up to the
Chris@1659 60 * model's "resolution" granularity, if more than 1). The end
Chris@1659 61 * frame minus the start frame should yield the total duration in
Chris@1659 62 * frames (as a multiple of the resolution) spanned by the
Chris@1659 63 * model. This is broadly consistent with the definition of the
Chris@1659 64 * end frame of a Selection object.
Chris@150 65 */
Chris@1038 66 virtual sv_frame_t getEndFrame() const = 0;
Chris@150 67
Chris@150 68 /**
Chris@150 69 * Return the frame rate in frames per second.
Chris@150 70 */
Chris@1040 71 virtual sv_samplerate_t getSampleRate() const = 0;
Chris@150 72
Chris@150 73 /**
Chris@297 74 * Return the frame rate of the underlying material, if the model
Chris@297 75 * itself has already been resampled.
Chris@297 76 */
Chris@1040 77 virtual sv_samplerate_t getNativeRate() const { return getSampleRate(); }
Chris@297 78
Chris@297 79 /**
Chris@333 80 * Return the "work title" of the model, if known.
Chris@333 81 */
Chris@333 82 virtual QString getTitle() const;
Chris@333 83
Chris@333 84 /**
Chris@333 85 * Return the "artist" or "maker" of the model, if known.
Chris@333 86 */
Chris@333 87 virtual QString getMaker() const;
Chris@333 88
Chris@333 89 /**
Chris@345 90 * Return the location of the data in this model (e.g. source
Chris@345 91 * URL). This should not normally be returned for editable models
Chris@345 92 * that have been edited.
Chris@345 93 */
Chris@345 94 virtual QString getLocation() const;
Chris@345 95
Chris@345 96 /**
Chris@345 97 * Return the type of the model. For display purposes only.
Chris@345 98 */
Chris@345 99 virtual QString getTypeName() const = 0;
Chris@345 100
Chris@345 101 /**
cannam@1452 102 * Return true if this is a sparse model.
cannam@1452 103 */
cannam@1452 104 virtual bool isSparse() const { return false; }
Chris@1500 105
Chris@1500 106 /**
Chris@1500 107 * Return an id for this model. The id is guaranteed to be a
Chris@1500 108 * unique identifier for this model among all models that may ever
Chris@1500 109 * exist within this single run of the application.
Chris@1500 110 */
Chris@1500 111 ModelId getId() const { return m_id; }
cannam@1452 112
cannam@1452 113 /**
Chris@923 114 * Mark the model as abandoning. This means that the application
Chris@923 115 * no longer needs it, so it can stop doing any background
Chris@923 116 * calculations it may be involved in. Note that as far as the
Chris@923 117 * model API is concerned, this does nothing more than tell the
Chris@923 118 * model to return true from isAbandoning(). The actual response
Chris@923 119 * to this will depend on the model's context -- it's possible
Chris@923 120 * nothing at all will change.
Chris@923 121 */
Chris@923 122 virtual void abandon() {
Chris@923 123 m_abandoning = true;
Chris@923 124 }
Chris@923 125
Chris@923 126 /**
Chris@923 127 * Query whether the model has been marked as abandoning.
Chris@923 128 */
Chris@923 129 virtual bool isAbandoning() const {
Chris@923 130 return m_abandoning;
Chris@923 131 }
Chris@923 132
Chris@150 133 /**
Chris@150 134 * Return true if the model has finished loading or calculating
Chris@150 135 * all its data, for a model that is capable of calculating in a
Chris@1671 136 * background thread.
Chris@150 137 *
Chris@1671 138 * If "completion" is non-NULL, return through it an estimated
Chris@1671 139 * percentage value showing how far through the background
Chris@1671 140 * operation it thinks it is (for progress reporting). This should
Chris@1671 141 * be identical to the value returned by getCompletion().
Chris@1671 142 *
Chris@1671 143 * A model that carries out all its calculation from the
Chris@1671 144 * constructor or accessor functions would typically return true
Chris@1671 145 * (and completion == 100) as long as isOK() is true. Other models
Chris@1671 146 * may make the return value here depend on the internal
Chris@1671 147 * completion status.
Chris@1669 148 *
Chris@1669 149 * See also getCompletion().
Chris@150 150 */
Chris@1671 151 virtual bool isReady(int *cp = nullptr) const {
Chris@1671 152 int c = getCompletion();
Chris@1671 153 if (cp) *cp = c;
Chris@1671 154 if (!isOK()) return false;
Chris@1671 155 else return (c == 100);
Chris@150 156 }
Chris@1671 157
Chris@1671 158 /**
Chris@1671 159 * Return an estimated percentage value showing how far through
Chris@1671 160 * any background operation used to calculate or load the model
Chris@1671 161 * data the model thinks it is. Must return 100 when the model is
Chris@1671 162 * complete.
Chris@1671 163 *
Chris@1671 164 * A model that carries out all its calculation from the
Chris@1671 165 * constructor or accessor functions might return 0 if isOK() is
Chris@1671 166 * false and 100 if isOK() is true. Other models may make the
Chris@1671 167 * return value here depend on the internal completion status.
Chris@1671 168 *
Chris@1671 169 * See also isReady().
Chris@1671 170 */
Chris@1671 171 virtual int getCompletion() const = 0;
Chris@150 172
Chris@179 173 /**
Chris@179 174 * If this model imposes a zoom constraint, i.e. some limit to the
Chris@179 175 * set of resolutions at which its data can meaningfully be
Chris@179 176 * displayed, then return it.
Chris@179 177 */
Chris@179 178 virtual const ZoomConstraint *getZoomConstraint() const {
Chris@179 179 return 0;
Chris@179 180 }
Chris@179 181
Chris@297 182 /**
Chris@297 183 * If this model was derived from another, return the model it was
Chris@297 184 * derived from. The assumption is that the source model's
Chris@297 185 * alignment will also apply to this model, unless some other
Chris@319 186 * property (such as a specific alignment model set on this model)
Chris@319 187 * indicates otherwise.
Chris@297 188 */
Chris@297 189 virtual Model *getSourceModel() const {
Chris@297 190 return m_sourceModel;
Chris@297 191 }
Chris@297 192
Chris@297 193 /**
Chris@297 194 * Set the source model for this model.
Chris@297 195 */
Chris@319 196 virtual void setSourceModel(Model *model);
Chris@319 197
Chris@319 198 /**
Chris@319 199 * Specify an aligment between this model's timeline and that of a
Chris@319 200 * reference model. The alignment model records both the
Chris@319 201 * reference and the alignment. This model takes ownership of the
Chris@319 202 * alignment model.
Chris@319 203 */
Chris@319 204 virtual void setAlignment(AlignmentModel *alignment);
Chris@319 205
Chris@319 206 /**
Chris@407 207 * Retrieve the alignment model for this model. This is not a
Chris@407 208 * generally useful function, as the alignment you really want may
Chris@407 209 * be performed by the source model instead. You should normally
Chris@407 210 * use getAlignmentReference, alignToReference and
Chris@407 211 * alignFromReference instead of this. The main intended
Chris@407 212 * application for this function is in streaming out alignments to
Chris@407 213 * the session file.
Chris@407 214 */
Chris@407 215 virtual const AlignmentModel *getAlignment() const;
Chris@407 216
Chris@407 217 /**
Chris@319 218 * Return the reference model for the current alignment timeline,
Chris@319 219 * if any.
Chris@319 220 */
Chris@319 221 virtual const Model *getAlignmentReference() const;
Chris@319 222
Chris@319 223 /**
Chris@319 224 * Return the frame number of the reference model that corresponds
Chris@319 225 * to the given frame number in this model.
Chris@319 226 */
Chris@1038 227 virtual sv_frame_t alignToReference(sv_frame_t frame) const;
Chris@319 228
Chris@319 229 /**
Chris@319 230 * Return the frame number in this model that corresponds to the
Chris@319 231 * given frame number of the reference model.
Chris@319 232 */
Chris@1038 233 virtual sv_frame_t alignFromReference(sv_frame_t referenceFrame) const;
Chris@319 234
Chris@319 235 /**
Chris@319 236 * Return the completion percentage for the alignment model: 100
Chris@319 237 * if there is no alignment model or it has been entirely
Chris@319 238 * calculated, or less than 100 if it is still being calculated.
Chris@319 239 */
Chris@319 240 virtual int getAlignmentCompletion() const;
Chris@297 241
Chris@558 242 /**
Chris@558 243 * Set the event, feature, or signal type URI for the features
Chris@558 244 * contained in this model, according to the Audio Features RDF
Chris@558 245 * ontology.
Chris@558 246 */
Chris@558 247 void setRDFTypeURI(QString uri) { m_typeUri = uri; }
Chris@558 248
Chris@558 249 /**
Chris@558 250 * Retrieve the event, feature, or signal type URI for the
Chris@558 251 * features contained in this model, if previously set with
Chris@558 252 * setRDFTypeURI.
Chris@558 253 */
Chris@558 254 QString getRDFTypeURI() const { return m_typeUri; }
Chris@558 255
Chris@1580 256 void toXml(QTextStream &stream,
Chris@1608 257 QString indent = "",
Chris@1608 258 QString extraAttributes = "") const override;
Chris@150 259
Chris@838 260 virtual QString toDelimitedDataString(QString delimiter) const {
Chris@1072 261 return toDelimitedDataStringSubset
Chris@1451 262 (delimiter, getStartFrame(), getEndFrame());
Chris@838 263 }
Chris@1060 264 virtual QString toDelimitedDataStringWithOptions(QString delimiter, DataExportOptions opts) const {
Chris@1072 265 return toDelimitedDataStringSubsetWithOptions
Chris@1451 266 (delimiter, opts, getStartFrame(), getEndFrame());
Chris@1060 267 }
Chris@1038 268 virtual QString toDelimitedDataStringSubset(QString, sv_frame_t /* f0 */, sv_frame_t /* f1 */) const {
Chris@838 269 return "";
Chris@838 270 }
Chris@1060 271 virtual QString toDelimitedDataStringSubsetWithOptions(QString delimiter, DataExportOptions, sv_frame_t f0, sv_frame_t f1) const {
Chris@1060 272 // Default implementation supports no options
Chris@1060 273 return toDelimitedDataStringSubset(delimiter, f0, f1);
Chris@1060 274 }
Chris@150 275
Chris@319 276 public slots:
Chris@319 277 void aboutToDelete();
Chris@319 278 void sourceModelAboutToBeDeleted();
Chris@319 279
Chris@150 280 signals:
Chris@150 281 /**
Chris@150 282 * Emitted when a model has been edited (or more data retrieved
Chris@150 283 * from cache, in the case of a cached model that generates slowly)
Chris@150 284 */
Chris@150 285 void modelChanged();
Chris@150 286
Chris@150 287 /**
Chris@150 288 * Emitted when a model has been edited (or more data retrieved
Chris@150 289 * from cache, in the case of a cached model that generates slowly)
Chris@150 290 */
Chris@1038 291 void modelChangedWithin(sv_frame_t startFrame, sv_frame_t endFrame);
Chris@150 292
Chris@150 293 /**
Chris@150 294 * Emitted when some internal processing has advanced a stage, but
Chris@150 295 * the model has not changed externally. Views should respond by
Chris@150 296 * updating any progress meters or other monitoring, but not
Chris@150 297 * refreshing the actual view.
Chris@150 298 */
Chris@150 299 void completionChanged();
Chris@150 300
Chris@319 301 /**
Chris@411 302 * Emitted when internal processing is complete (i.e. when
Chris@411 303 * isReady() would return true, with completion at 100).
Chris@411 304 */
Chris@411 305 void ready();
Chris@411 306
Chris@411 307 /**
Chris@319 308 * Emitted when the completion percentage changes for the
Chris@319 309 * calculation of this model's alignment model.
Chris@319 310 */
Chris@319 311 void alignmentCompletionChanged();
Chris@319 312
Chris@319 313 /**
Chris@319 314 * Emitted when something notifies this model (through calling
Chris@319 315 * aboutToDelete() that it is about to delete it. Note that this
Chris@319 316 * depends on an external agent such as a Document object or
Chris@319 317 * owning model telling the model that it is about to delete it;
Chris@319 318 * there is nothing in the model to guarantee that this signal
Chris@319 319 * will be emitted before the actual deletion.
Chris@319 320 */
Chris@319 321 void aboutToBeDeleted();
Chris@319 322
Chris@150 323 protected:
Chris@1500 324 Model() :
Chris@1500 325 m_id(getNextId()),
Chris@923 326 m_sourceModel(0),
Chris@923 327 m_alignment(0),
Chris@923 328 m_abandoning(false),
Chris@923 329 m_aboutToDelete(false) { }
Chris@150 330
Chris@150 331 // Not provided.
Chris@150 332 Model(const Model &);
Chris@150 333 Model &operator=(const Model &);
Chris@297 334
Chris@1500 335 const ModelId m_id;
Chris@297 336 Model *m_sourceModel;
Chris@319 337 AlignmentModel *m_alignment;
Chris@558 338 QString m_typeUri;
Chris@923 339 bool m_abandoning;
Chris@319 340 bool m_aboutToDelete;
Chris@1500 341
Chris@1500 342 int getNextId();
Chris@150 343 };
Chris@150 344
Chris@150 345 #endif