annotate framework/Document.h @ 256:f3f9e3d647c1

Give a dedicated key to toggling the centre line, and move it out of the overlay level setting -- reducing number of overlay levels to 3. Introduce two distinct vertical scale types (so that we can hide the spectrogram colour scale part easily)
author Chris Cannam
date Mon, 30 Jan 2012 16:02:14 +0000
parents 2c827ac7c8e7
children 40a0fa9af6b4
rev   line source
Chris@45 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@45 2
Chris@45 3 /*
Chris@45 4 Sonic Visualiser
Chris@45 5 An audio file viewer and annotation editor.
Chris@45 6 Centre for Digital Music, Queen Mary, University of London.
Chris@45 7 This file copyright 2006 Chris Cannam and QMUL.
Chris@45 8
Chris@45 9 This program is free software; you can redistribute it and/or
Chris@45 10 modify it under the terms of the GNU General Public License as
Chris@45 11 published by the Free Software Foundation; either version 2 of the
Chris@45 12 License, or (at your option) any later version. See the file
Chris@45 13 COPYING included with this distribution for more information.
Chris@45 14 */
Chris@45 15
Chris@45 16 #ifndef _DOCUMENT_H_
Chris@45 17 #define _DOCUMENT_H_
Chris@45 18
Chris@45 19 #include "layer/LayerFactory.h"
Chris@106 20 #include "transform/Transform.h"
Chris@106 21 #include "transform/ModelTransformer.h"
Chris@45 22 #include "base/Command.h"
Chris@45 23
Chris@45 24 #include <map>
Chris@45 25 #include <set>
Chris@45 26
Chris@45 27 class Model;
Chris@45 28 class Layer;
Chris@45 29 class View;
Chris@45 30 class WaveFileModel;
Chris@45 31
Chris@45 32 /**
Chris@45 33 * A Sonic Visualiser document consists of a set of data models, and
Chris@45 34 * also the visualisation layers used to display them. Changes to the
Chris@45 35 * layers and their layout need to be stored and managed in much the
Chris@45 36 * same way as changes to the underlying data.
Chris@45 37 *
Chris@45 38 * The document manages:
Chris@45 39 *
Chris@45 40 * - A main data Model, which provides the underlying sample rate and
Chris@45 41 * such like. This must be a WaveFileModel.
Chris@45 42 *
Chris@45 43 * - Any number of imported Model objects, which contain data without any
Chris@45 44 * requirement to remember where the data came from or how to
Chris@45 45 * regenerate it.
Chris@45 46 *
Chris@53 47 * - Any number of Model objects that were generated by a Transformer
Chris@54 48 * such as FeatureExtractionModelTransformer. For these, we also
Chris@45 49 * record the source model and the name of the transform used to
Chris@45 50 * generate the model so that we can regenerate it (potentially
Chris@45 51 * from a different source) on demand.
Chris@45 52 *
Chris@45 53 * - A flat list of Layer objects. Elsewhere, the GUI may distribute these
Chris@45 54 * across any number of View widgets. A layer may be viewable on more
Chris@45 55 * than one view at once, in principle. A layer refers to one model,
Chris@45 56 * but the same model can be in use in more than one layer.
Chris@45 57 *
Chris@45 58 * The document does *not* manage the existence or structure of Pane
Chris@45 59 * and other view widgets. However, it does provide convenience
Chris@45 60 * methods for reference-counted command-based management of the
Chris@45 61 * association between layers and views (addLayerToView,
Chris@45 62 * removeLayerFromView).
Chris@45 63 */
Chris@45 64
Chris@45 65 class Document : public QObject,
Chris@45 66 public XmlExportable
Chris@45 67 {
Chris@45 68 Q_OBJECT
Chris@45 69
Chris@45 70 public:
Chris@45 71 Document();
Chris@45 72 virtual ~Document();
Chris@45 73
Chris@45 74 /**
Chris@45 75 * Create and return a new layer of the given type, associated
Chris@45 76 * with no model. The caller may set any model on this layer, but
Chris@45 77 * the model must also be registered with the document via the
Chris@45 78 * add-model methods below.
Chris@45 79 */
Chris@45 80 Layer *createLayer(LayerFactory::LayerType);
Chris@45 81
Chris@45 82 /**
Chris@45 83 * Create and return a new layer of the given type, associated
Chris@45 84 * with the current main model (if appropriate to the layer type).
Chris@45 85 */
Chris@45 86 Layer *createMainModelLayer(LayerFactory::LayerType);
Chris@45 87
Chris@45 88 /**
Chris@45 89 * Create and return a new layer associated with the given model,
Chris@45 90 * and register the model as an imported model.
Chris@45 91 */
Chris@45 92 Layer *createImportedLayer(Model *);
Chris@45 93
Chris@45 94 /**
Chris@45 95 * Create and return a new layer of the given type, with an
Chris@45 96 * appropriate empty model. If the given type is not one for
Chris@45 97 * which an empty model can meaningfully be created, return 0.
Chris@45 98 */
Chris@45 99 Layer *createEmptyLayer(LayerFactory::LayerType);
Chris@45 100
Chris@45 101 /**
Chris@45 102 * Create and return a new layer of the given type, associated
Chris@45 103 * with the given transform name. This method does not run the
Chris@45 104 * transform itself, nor create a model. The caller can safely
Chris@45 105 * add a model to the layer later, but note that all models used
Chris@45 106 * by a transform layer _must_ be registered with the document
Chris@45 107 * using addDerivedModel below.
Chris@45 108 */
Chris@54 109 Layer *createDerivedLayer(LayerFactory::LayerType, TransformId);
Chris@45 110
Chris@45 111 /**
Chris@45 112 * Create and return a suitable layer for the given transform,
Chris@45 113 * running the transform and associating the resulting model with
Chris@45 114 * the new layer.
Chris@45 115 */
Chris@72 116 Layer *createDerivedLayer(const Transform &,
Chris@72 117 const ModelTransformer::Input &);
Chris@45 118
Chris@45 119 /**
Chris@52 120 * Delete the given layer, and also its associated model if no
Chris@52 121 * longer used by any other layer. In general, this should be the
Chris@52 122 * only method used to delete layers -- doing so directly is a bit
Chris@52 123 * of a social gaffe.
Chris@52 124 */
Chris@52 125 void deleteLayer(Layer *, bool force = false);
Chris@52 126
Chris@52 127 /**
Chris@45 128 * Set the main model (the source for playback sample rate, etc)
Chris@45 129 * to the given wave file model. This will regenerate any derived
Chris@45 130 * models that were based on the previous main model.
Chris@45 131 */
Chris@45 132 void setMainModel(WaveFileModel *);
Chris@45 133
Chris@45 134 /**
Chris@45 135 * Get the main model (the source for playback sample rate, etc).
Chris@45 136 */
Chris@45 137 WaveFileModel *getMainModel() { return m_mainModel; }
Chris@45 138
Chris@45 139 /**
Chris@45 140 * Get the main model (the source for playback sample rate, etc).
Chris@45 141 */
Chris@45 142 const WaveFileModel *getMainModel() const { return m_mainModel; }
Chris@45 143
Chris@72 144 std::vector<Model *> getTransformInputModels();
Chris@45 145
Chris@77 146 bool isKnownModel(const Model *) const;
Chris@77 147
Chris@45 148 /**
Chris@45 149 * Add a derived model associated with the given transform,
Chris@45 150 * running the transform and returning the resulting model.
Chris@45 151 */
Chris@72 152 Model *addDerivedModel(const Transform &transform,
Chris@78 153 const ModelTransformer::Input &input,
Chris@78 154 QString &returnedMessage);
Chris@45 155
Chris@45 156 /**
Chris@45 157 * Add a derived model associated with the given transform. This
Chris@45 158 * is necessary to register any derived model that was not created
Chris@45 159 * by the document using createDerivedModel or createDerivedLayer.
Chris@45 160 */
Chris@72 161 void addDerivedModel(const Transform &transform,
Chris@72 162 const ModelTransformer::Input &input,
Chris@72 163 Model *outputModelToAdd);
Chris@45 164
Chris@45 165 /**
Chris@45 166 * Add an imported (non-derived, non-main) model. This is
Chris@45 167 * necessary to register any imported model that is associated
Chris@45 168 * with a layer.
Chris@45 169 */
Chris@45 170 void addImportedModel(Model *);
Chris@45 171
Chris@45 172 /**
Chris@45 173 * Associate the given model with the given layer. The model must
Chris@45 174 * have already been registered using one of the addXXModel
Chris@45 175 * methods above.
Chris@45 176 */
Chris@45 177 void setModel(Layer *, Model *);
Chris@45 178
Chris@45 179 /**
Chris@45 180 * Set the given layer to use the given channel of its model (-1
Chris@45 181 * means all available channels).
Chris@45 182 */
Chris@45 183 void setChannel(Layer *, int);
Chris@45 184
Chris@45 185 /**
Chris@45 186 * Add the given layer to the given view. If the layer is
Chris@45 187 * intended to show a particular model, the model should normally
Chris@45 188 * be set using setModel before this method is called.
Chris@45 189 */
Chris@45 190 void addLayerToView(View *, Layer *);
Chris@45 191
Chris@45 192 /**
Chris@45 193 * Remove the given layer from the given view.
Chris@45 194 */
Chris@45 195 void removeLayerFromView(View *, Layer *);
Chris@45 196
Chris@48 197 /**
Chris@50 198 * Return true if alignment is supported (i.e. if the necessary
Chris@50 199 * plugin is found).
Chris@50 200 */
Chris@51 201 static bool canAlign();
Chris@50 202
Chris@50 203 /**
Chris@48 204 * Specify whether models added via addImportedModel should be
Chris@48 205 * automatically aligned against the main model if appropriate.
Chris@48 206 */
Chris@48 207 void setAutoAlignment(bool on) { m_autoAlignment = on; }
Chris@48 208
Chris@48 209 /**
Chris@48 210 * Generate alignments for all appropriate models against the main
Chris@48 211 * model. Existing alignments will not be re-calculated unless
Chris@48 212 * the main model has changed since they were calculated.
Chris@48 213 */
Chris@48 214 void alignModels();
Chris@48 215
Chris@45 216 void toXml(QTextStream &, QString indent, QString extraAttributes) const;
Chris@226 217 void toXmlAsTemplate(QTextStream &, QString indent, QString extraAttributes) const;
Chris@47 218
Chris@45 219 signals:
Chris@45 220 void layerAdded(Layer *);
Chris@45 221 void layerRemoved(Layer *);
Chris@45 222 void layerAboutToBeDeleted(Layer *);
Chris@45 223
Chris@45 224 // Emitted when a layer is first added to a view, or when it is
Chris@45 225 // last removed from a view
Chris@45 226 void layerInAView(Layer *, bool);
Chris@45 227
Chris@45 228 void modelAdded(Model *);
Chris@45 229 void mainModelChanged(WaveFileModel *); // emitted after modelAdded
Chris@45 230 void modelAboutToBeDeleted(Model *);
Chris@45 231
Chris@78 232 void modelGenerationFailed(QString transformName, QString message);
Chris@78 233 void modelGenerationWarning(QString transformName, QString message);
Chris@78 234 void modelRegenerationFailed(QString layerName, QString transformName,
Chris@78 235 QString message);
Chris@78 236 void modelRegenerationWarning(QString layerName, QString transformName,
Chris@78 237 QString message);
Chris@78 238 void alignmentFailed(QString transformName, QString message);
Chris@45 239
Chris@160 240 void activity(QString);
Chris@160 241
Chris@45 242 protected:
Chris@45 243 void releaseModel(Model *model);
Chris@45 244
Chris@45 245 /**
Chris@45 246 * If model is suitable for alignment, align it against the main
Chris@48 247 * model and store the alignment in the model. (If the model has
Chris@48 248 * an alignment already for the current main model, leave it
Chris@48 249 * unchanged.)
Chris@45 250 */
Chris@45 251 void alignModel(Model *);
Chris@45 252
Chris@45 253 /*
Chris@45 254 * Every model that is in use by a layer in the document must be
Chris@45 255 * found in either m_mainModel or m_models. We own and control
Chris@45 256 * the lifespan of all of these models.
Chris@45 257 */
Chris@45 258
Chris@45 259 /**
Chris@45 260 * The model that provides the underlying sample rate, etc. This
Chris@45 261 * model is not reference counted for layers, and is not freed
Chris@45 262 * unless it is replaced or the document is deleted.
Chris@45 263 */
Chris@45 264 WaveFileModel *m_mainModel;
Chris@45 265
Chris@45 266 struct ModelRecord
Chris@45 267 {
Chris@45 268 // Information associated with a non-main model. If this
Chris@45 269 // model is derived from another, then source will be non-NULL
Chris@45 270 // and the transform name will be set appropriately. If the
Chris@45 271 // transform name is set but source is NULL, then there was a
Chris@45 272 // transform involved but the (target) model has been modified
Chris@45 273 // since being generated from it.
Chris@72 274
Chris@72 275 // This does not use ModelTransformer::Input, because it would
Chris@72 276 // be confusing to have Input objects hanging around with NULL
Chris@72 277 // models in them.
Chris@72 278
Chris@45 279 const Model *source;
Chris@72 280 int channel;
Chris@72 281 Transform transform;
Chris@45 282
Chris@45 283 // Count of the number of layers using this model.
Chris@45 284 int refcount;
Chris@45 285 };
Chris@45 286
Chris@45 287 typedef std::map<Model *, ModelRecord> ModelMap;
Chris@45 288 ModelMap m_models;
Chris@45 289
Chris@45 290 class AddLayerCommand : public Command
Chris@45 291 {
Chris@45 292 public:
Chris@45 293 AddLayerCommand(Document *d, View *view, Layer *layer);
Chris@45 294 virtual ~AddLayerCommand();
Chris@45 295
Chris@45 296 virtual void execute();
Chris@45 297 virtual void unexecute();
Chris@159 298 virtual QString getName() const;
Chris@45 299
Chris@45 300 protected:
Chris@45 301 Document *m_d;
Chris@45 302 View *m_view; // I don't own this
Chris@83 303 Layer *m_layer; // Document owns this, but I determine its lifespan
Chris@45 304 QString m_name;
Chris@45 305 bool m_added;
Chris@45 306 };
Chris@45 307
Chris@45 308 class RemoveLayerCommand : public Command
Chris@45 309 {
Chris@45 310 public:
Chris@45 311 RemoveLayerCommand(Document *d, View *view, Layer *layer);
Chris@45 312 virtual ~RemoveLayerCommand();
Chris@45 313
Chris@45 314 virtual void execute();
Chris@45 315 virtual void unexecute();
Chris@159 316 virtual QString getName() const;
Chris@45 317
Chris@45 318 protected:
Chris@45 319 Document *m_d;
Chris@45 320 View *m_view; // I don't own this
Chris@45 321 Layer *m_layer; // Document owns this, but I determine its lifespan
Chris@45 322 QString m_name;
Chris@45 323 bool m_added;
Chris@45 324 };
Chris@45 325
Chris@45 326 typedef std::map<Layer *, std::set<View *> > LayerViewMap;
Chris@45 327 LayerViewMap m_layerViewMap;
Chris@45 328
Chris@45 329 void addToLayerViewMap(Layer *, View *);
Chris@45 330 void removeFromLayerViewMap(Layer *, View *);
Chris@45 331
Chris@45 332 QString getUniqueLayerName(QString candidate);
Chris@72 333 void writeBackwardCompatibleDerivation(QTextStream &, QString, Model *,
Chris@72 334 const ModelRecord &) const;
Chris@90 335
Chris@90 336 static TransformId getAlignmentTransformName();
Chris@45 337
Chris@226 338 void toXml(QTextStream &, QString, QString, bool asTemplate) const;
Chris@226 339 void writePlaceholderMainModel(QTextStream &, QString) const;
Chris@226 340
Chris@45 341 /**
Chris@45 342 * And these are the layers. We also control the lifespans of
Chris@45 343 * these (usually through the commands used to add and remove them).
Chris@45 344 */
Chris@45 345 typedef std::set<Layer *> LayerSet;
Chris@45 346 LayerSet m_layers;
Chris@47 347
Chris@47 348 bool m_autoAlignment;
Chris@45 349 };
Chris@45 350
Chris@45 351 #endif