| 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@150 | 16 #ifndef _MODEL_H_ | 
| Chris@150 | 17 #define _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@290 | 27 typedef std::vector<float> SampleBlock; | 
| Chris@290 | 28 | 
| Chris@179 | 29 class ZoomConstraint; | 
| Chris@319 | 30 class AlignmentModel; | 
| Chris@179 | 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@391 | 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@150 | 58      * Return the last audio frame spanned by the model. | 
| Chris@150 | 59      */ | 
| Chris@1038 | 60     virtual sv_frame_t getEndFrame() const = 0; | 
| Chris@150 | 61 | 
| Chris@150 | 62     /** | 
| Chris@150 | 63      * Return the frame rate in frames per second. | 
| Chris@150 | 64      */ | 
| Chris@1040 | 65     virtual sv_samplerate_t getSampleRate() const = 0; | 
| Chris@150 | 66 | 
| Chris@150 | 67     /** | 
| Chris@297 | 68      * Return the frame rate of the underlying material, if the model | 
| Chris@297 | 69      * itself has already been resampled. | 
| Chris@297 | 70      */ | 
| Chris@1040 | 71     virtual sv_samplerate_t getNativeRate() const { return getSampleRate(); } | 
| Chris@297 | 72 | 
| Chris@297 | 73     /** | 
| Chris@333 | 74      * Return the "work title" of the model, if known. | 
| Chris@333 | 75      */ | 
| Chris@333 | 76     virtual QString getTitle() const; | 
| Chris@333 | 77 | 
| Chris@333 | 78     /** | 
| Chris@333 | 79      * Return the "artist" or "maker" of the model, if known. | 
| Chris@333 | 80      */ | 
| Chris@333 | 81     virtual QString getMaker() const; | 
| Chris@333 | 82 | 
| Chris@333 | 83     /** | 
| Chris@345 | 84      * Return the location of the data in this model (e.g. source | 
| Chris@345 | 85      * URL).  This should not normally be returned for editable models | 
| Chris@345 | 86      * that have been edited. | 
| Chris@345 | 87      */ | 
| Chris@345 | 88     virtual QString getLocation() const; | 
| Chris@345 | 89 | 
| Chris@345 | 90     /** | 
| Chris@345 | 91      * Return the type of the model.  For display purposes only. | 
| Chris@345 | 92      */ | 
| Chris@345 | 93     virtual QString getTypeName() const = 0; | 
| Chris@345 | 94 | 
| Chris@345 | 95     /** | 
| Chris@923 | 96      * Mark the model as abandoning. This means that the application | 
| Chris@923 | 97      * no longer needs it, so it can stop doing any background | 
| Chris@923 | 98      * calculations it may be involved in. Note that as far as the | 
| Chris@923 | 99      * model API is concerned, this does nothing more than tell the | 
| Chris@923 | 100      * model to return true from isAbandoning().  The actual response | 
| Chris@923 | 101      * to this will depend on the model's context -- it's possible | 
| Chris@923 | 102      * nothing at all will change. | 
| Chris@923 | 103      */ | 
| Chris@923 | 104     virtual void abandon() { | 
| Chris@923 | 105         m_abandoning = true; | 
| Chris@923 | 106     } | 
| Chris@923 | 107 | 
| Chris@923 | 108     /** | 
| Chris@923 | 109      * Query whether the model has been marked as abandoning. | 
| Chris@923 | 110      */ | 
| Chris@923 | 111     virtual bool isAbandoning() const { | 
| Chris@923 | 112         return m_abandoning; | 
| Chris@923 | 113     } | 
| Chris@923 | 114 | 
| Chris@150 | 115     /** | 
| Chris@150 | 116      * Return true if the model has finished loading or calculating | 
| Chris@150 | 117      * all its data, for a model that is capable of calculating in a | 
| Chris@150 | 118      * background thread.  The default implementation is appropriate | 
| Chris@150 | 119      * for a thread that does not background any work but carries out | 
| Chris@150 | 120      * all its calculation from the constructor or accessors. | 
| Chris@150 | 121      * | 
| Chris@150 | 122      * If "completion" is non-NULL, this function should return | 
| Chris@150 | 123      * through it an estimated percentage value showing how far | 
| Chris@150 | 124      * through the background operation it thinks it is (for progress | 
| Chris@150 | 125      * reporting).  If it has no way to calculate progress, it may | 
| Chris@150 | 126      * return the special value COMPLETION_UNKNOWN. | 
| Chris@150 | 127      */ | 
| Chris@150 | 128     virtual bool isReady(int *completion = 0) const { | 
| Chris@150 | 129 	bool ok = isOK(); | 
| Chris@150 | 130 	if (completion) *completion = (ok ? 100 : 0); | 
| Chris@150 | 131 	return ok; | 
| Chris@150 | 132     } | 
| Chris@150 | 133     static const int COMPLETION_UNKNOWN; | 
| Chris@150 | 134 | 
| Chris@179 | 135     /** | 
| Chris@179 | 136      * If this model imposes a zoom constraint, i.e. some limit to the | 
| Chris@179 | 137      * set of resolutions at which its data can meaningfully be | 
| Chris@179 | 138      * displayed, then return it. | 
| Chris@179 | 139      */ | 
| Chris@179 | 140     virtual const ZoomConstraint *getZoomConstraint() const { | 
| Chris@179 | 141         return 0; | 
| Chris@179 | 142     } | 
| Chris@179 | 143 | 
| Chris@297 | 144     /** | 
| Chris@297 | 145      * If this model was derived from another, return the model it was | 
| Chris@297 | 146      * derived from.  The assumption is that the source model's | 
| Chris@297 | 147      * alignment will also apply to this model, unless some other | 
| Chris@319 | 148      * property (such as a specific alignment model set on this model) | 
| Chris@319 | 149      * indicates otherwise. | 
| Chris@297 | 150      */ | 
| Chris@297 | 151     virtual Model *getSourceModel() const { | 
| Chris@297 | 152         return m_sourceModel; | 
| Chris@297 | 153     } | 
| Chris@297 | 154 | 
| Chris@297 | 155     /** | 
| Chris@297 | 156      * Set the source model for this model. | 
| Chris@297 | 157      */ | 
| Chris@319 | 158     virtual void setSourceModel(Model *model); | 
| Chris@319 | 159 | 
| Chris@319 | 160     /** | 
| Chris@319 | 161      * Specify an aligment between this model's timeline and that of a | 
| Chris@319 | 162      * reference model.  The alignment model records both the | 
| Chris@319 | 163      * reference and the alignment.  This model takes ownership of the | 
| Chris@319 | 164      * alignment model. | 
| Chris@319 | 165      */ | 
| Chris@319 | 166     virtual void setAlignment(AlignmentModel *alignment); | 
| Chris@319 | 167 | 
| Chris@319 | 168     /** | 
| Chris@407 | 169      * Retrieve the alignment model for this model.  This is not a | 
| Chris@407 | 170      * generally useful function, as the alignment you really want may | 
| Chris@407 | 171      * be performed by the source model instead.  You should normally | 
| Chris@407 | 172      * use getAlignmentReference, alignToReference and | 
| Chris@407 | 173      * alignFromReference instead of this.  The main intended | 
| Chris@407 | 174      * application for this function is in streaming out alignments to | 
| Chris@407 | 175      * the session file. | 
| Chris@407 | 176      */ | 
| Chris@407 | 177     virtual const AlignmentModel *getAlignment() const; | 
| Chris@407 | 178 | 
| Chris@407 | 179     /** | 
| Chris@319 | 180      * Return the reference model for the current alignment timeline, | 
| Chris@319 | 181      * if any. | 
| Chris@319 | 182      */ | 
| Chris@319 | 183     virtual const Model *getAlignmentReference() const; | 
| Chris@319 | 184 | 
| Chris@319 | 185     /** | 
| Chris@319 | 186      * Return the frame number of the reference model that corresponds | 
| Chris@319 | 187      * to the given frame number in this model. | 
| Chris@319 | 188      */ | 
| Chris@1038 | 189     virtual sv_frame_t alignToReference(sv_frame_t frame) const; | 
| Chris@319 | 190 | 
| Chris@319 | 191     /** | 
| Chris@319 | 192      * Return the frame number in this model that corresponds to the | 
| Chris@319 | 193      * given frame number of the reference model. | 
| Chris@319 | 194      */ | 
| Chris@1038 | 195     virtual sv_frame_t alignFromReference(sv_frame_t referenceFrame) const; | 
| Chris@319 | 196 | 
| Chris@319 | 197     /** | 
| Chris@319 | 198      * Return the completion percentage for the alignment model: 100 | 
| Chris@319 | 199      * if there is no alignment model or it has been entirely | 
| Chris@319 | 200      * calculated, or less than 100 if it is still being calculated. | 
| Chris@319 | 201      */ | 
| Chris@319 | 202     virtual int getAlignmentCompletion() const; | 
| Chris@297 | 203 | 
| Chris@558 | 204     /** | 
| Chris@558 | 205      * Set the event, feature, or signal type URI for the features | 
| Chris@558 | 206      * contained in this model, according to the Audio Features RDF | 
| Chris@558 | 207      * ontology. | 
| Chris@558 | 208      */ | 
| Chris@558 | 209     void setRDFTypeURI(QString uri) { m_typeUri = uri; } | 
| Chris@558 | 210 | 
| Chris@558 | 211     /** | 
| Chris@558 | 212      * Retrieve the event, feature, or signal type URI for the | 
| Chris@558 | 213      * features contained in this model, if previously set with | 
| Chris@558 | 214      * setRDFTypeURI. | 
| Chris@558 | 215      */ | 
| Chris@558 | 216     QString getRDFTypeURI() const { return m_typeUri; } | 
| Chris@558 | 217 | 
| Chris@150 | 218     virtual void toXml(QTextStream &stream, | 
| Chris@150 | 219                        QString indent = "", | 
| Chris@150 | 220                        QString extraAttributes = "") const; | 
| Chris@150 | 221 | 
| Chris@838 | 222     virtual QString toDelimitedDataString(QString delimiter) const { | 
| Chris@1072 | 223         return toDelimitedDataStringSubset | 
| Chris@1072 | 224             (delimiter, getStartFrame(), getEndFrame() + 1); | 
| Chris@838 | 225     } | 
| Chris@1060 | 226     virtual QString toDelimitedDataStringWithOptions(QString delimiter, DataExportOptions opts) const { | 
| Chris@1072 | 227         return toDelimitedDataStringSubsetWithOptions | 
| Chris@1072 | 228             (delimiter, opts, getStartFrame(), getEndFrame() + 1); | 
| Chris@1060 | 229     } | 
| Chris@1038 | 230     virtual QString toDelimitedDataStringSubset(QString, sv_frame_t /* f0 */, sv_frame_t /* f1 */) const { | 
| Chris@838 | 231         return ""; | 
| Chris@838 | 232     } | 
| Chris@1060 | 233     virtual QString toDelimitedDataStringSubsetWithOptions(QString delimiter, DataExportOptions, sv_frame_t f0, sv_frame_t f1) const { | 
| Chris@1060 | 234         // Default implementation supports no options | 
| Chris@1060 | 235         return toDelimitedDataStringSubset(delimiter, f0, f1); | 
| Chris@1060 | 236     } | 
| Chris@150 | 237 | 
| Chris@319 | 238 public slots: | 
| Chris@319 | 239     void aboutToDelete(); | 
| Chris@319 | 240     void sourceModelAboutToBeDeleted(); | 
| Chris@319 | 241 | 
| Chris@150 | 242 signals: | 
| Chris@150 | 243     /** | 
| Chris@150 | 244      * Emitted when a model has been edited (or more data retrieved | 
| Chris@150 | 245      * from cache, in the case of a cached model that generates slowly) | 
| Chris@150 | 246      */ | 
| Chris@150 | 247     void modelChanged(); | 
| Chris@150 | 248 | 
| Chris@150 | 249     /** | 
| Chris@150 | 250      * Emitted when a model has been edited (or more data retrieved | 
| Chris@150 | 251      * from cache, in the case of a cached model that generates slowly) | 
| Chris@150 | 252      */ | 
| Chris@1038 | 253     void modelChangedWithin(sv_frame_t startFrame, sv_frame_t endFrame); | 
| Chris@150 | 254 | 
| Chris@150 | 255     /** | 
| Chris@150 | 256      * Emitted when some internal processing has advanced a stage, but | 
| Chris@150 | 257      * the model has not changed externally.  Views should respond by | 
| Chris@150 | 258      * updating any progress meters or other monitoring, but not | 
| Chris@150 | 259      * refreshing the actual view. | 
| Chris@150 | 260      */ | 
| Chris@150 | 261     void completionChanged(); | 
| Chris@150 | 262 | 
| Chris@319 | 263     /** | 
| Chris@411 | 264      * Emitted when internal processing is complete (i.e. when | 
| Chris@411 | 265      * isReady() would return true, with completion at 100). | 
| Chris@411 | 266      */ | 
| Chris@411 | 267     void ready(); | 
| Chris@411 | 268 | 
| Chris@411 | 269     /** | 
| Chris@319 | 270      * Emitted when the completion percentage changes for the | 
| Chris@319 | 271      * calculation of this model's alignment model. | 
| Chris@319 | 272      */ | 
| Chris@319 | 273     void alignmentCompletionChanged(); | 
| Chris@319 | 274 | 
| Chris@319 | 275     /** | 
| Chris@319 | 276      * Emitted when something notifies this model (through calling | 
| Chris@319 | 277      * aboutToDelete() that it is about to delete it.  Note that this | 
| Chris@319 | 278      * depends on an external agent such as a Document object or | 
| Chris@319 | 279      * owning model telling the model that it is about to delete it; | 
| Chris@319 | 280      * there is nothing in the model to guarantee that this signal | 
| Chris@319 | 281      * will be emitted before the actual deletion. | 
| Chris@319 | 282      */ | 
| Chris@319 | 283     void aboutToBeDeleted(); | 
| Chris@319 | 284 | 
| Chris@150 | 285 protected: | 
| Chris@923 | 286     Model() : | 
| Chris@923 | 287         m_sourceModel(0), | 
| Chris@923 | 288         m_alignment(0), | 
| Chris@923 | 289         m_abandoning(false), | 
| Chris@923 | 290         m_aboutToDelete(false) { } | 
| Chris@150 | 291 | 
| Chris@150 | 292     // Not provided. | 
| Chris@150 | 293     Model(const Model &); | 
| Chris@150 | 294     Model &operator=(const Model &); | 
| Chris@297 | 295 | 
| Chris@297 | 296     Model *m_sourceModel; | 
| Chris@319 | 297     AlignmentModel *m_alignment; | 
| Chris@558 | 298     QString m_typeUri; | 
| Chris@923 | 299     bool m_abandoning; | 
| Chris@319 | 300     bool m_aboutToDelete; | 
| Chris@150 | 301 }; | 
| Chris@150 | 302 | 
| Chris@150 | 303 #endif |