annotate document/Document.h @ 201:de783e8ee5f0

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