annotate document/Document.h @ 193:4e030ebb6b36

* Make it possible to drop audio files, layer files, session files and images onto SV panes. Need to do a bit more work on where we expect the dropped file to go, particularly in the case of audio files -- at the moment they're always opened in new panes, but it may be better to by default replace whatever is in the target pane.
author Chris Cannam
date Wed, 10 Oct 2007 15:18:02 +0000
parents 98ba77e0d897
children 29c356da4ae4
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 QString toXmlString(QString indent, QString extraAttributes) const;
Chris@0 194
Chris@0 195 signals:
Chris@0 196 void layerAdded(Layer *);
Chris@0 197 void layerRemoved(Layer *);
Chris@0 198 void layerAboutToBeDeleted(Layer *);
Chris@0 199
Chris@0 200 // Emitted when a layer is first added to a view, or when it is
Chris@0 201 // last removed from a view
Chris@0 202 void layerInAView(Layer *, bool);
Chris@0 203
Chris@0 204 void modelAdded(Model *);
Chris@0 205 void mainModelChanged(WaveFileModel *); // emitted after modelAdded
Chris@0 206 void modelAboutToBeDeleted(Model *);
Chris@0 207
Chris@0 208 void modelGenerationFailed(QString transformName);
Chris@0 209 void modelRegenerationFailed(QString layerName, QString transformName);
Chris@0 210
Chris@0 211 protected:
Chris@0 212 void releaseModel(Model *model);
Chris@0 213
Chris@0 214 /**
Chris@0 215 * Delete the given layer, and also its associated model if no
Chris@0 216 * longer used by any other layer. In general, this should be the
Chris@0 217 * only method used to delete layers -- doing so directly is a bit
Chris@0 218 * of a social gaffe.
Chris@0 219 */
Chris@0 220 void deleteLayer(Layer *, bool force = false);
Chris@0 221
Chris@0 222 /*
Chris@0 223 * Every model that is in use by a layer in the document must be
Chris@180 224 * found in either m_mainModel or m_models. We own and control
Chris@180 225 * the lifespan of all of these models.
Chris@0 226 */
Chris@0 227
Chris@0 228 /**
Chris@0 229 * The model that provides the underlying sample rate, etc. This
Chris@0 230 * model is not reference counted for layers, and is not freed
Chris@0 231 * unless it is replaced or the document is deleted.
Chris@0 232 */
Chris@0 233 WaveFileModel *m_mainModel;
Chris@0 234
Chris@0 235 struct ModelRecord
Chris@0 236 {
Chris@0 237 // Information associated with a non-main model. If this
Chris@0 238 // model is derived from another, then source will be non-NULL
Chris@0 239 // and the transform name will be set appropriately. If the
Chris@0 240 // transform name is set but source is NULL, then there was a
Chris@0 241 // transform involved but the (target) model has been modified
Chris@0 242 // since being generated from it.
Chris@0 243 const Model *source;
Chris@107 244 TransformId transform;
Chris@27 245 PluginTransform::ExecutionContext context;
Chris@0 246 QString configurationXml;
Chris@0 247
Chris@0 248 // Count of the number of layers using this model.
Chris@0 249 int refcount;
Chris@0 250 };
Chris@0 251
Chris@0 252 typedef std::map<Model *, ModelRecord> ModelMap;
Chris@0 253 ModelMap m_models;
Chris@0 254
Chris@0 255 class AddLayerCommand : public Command
Chris@0 256 {
Chris@0 257 public:
Chris@0 258 AddLayerCommand(Document *d, View *view, Layer *layer);
Chris@0 259 virtual ~AddLayerCommand();
Chris@0 260
Chris@0 261 virtual void execute();
Chris@0 262 virtual void unexecute();
Chris@0 263 virtual QString getName() const { return m_name; }
Chris@0 264
Chris@0 265 protected:
Chris@0 266 Document *m_d;
Chris@0 267 View *m_view; // I don't own this
Chris@0 268 Layer *m_layer; // Document owns this, but I determine its lifespans
Chris@0 269 QString m_name;
Chris@0 270 bool m_added;
Chris@0 271 };
Chris@0 272
Chris@0 273 class RemoveLayerCommand : public Command
Chris@0 274 {
Chris@0 275 public:
Chris@0 276 RemoveLayerCommand(Document *d, View *view, Layer *layer);
Chris@0 277 virtual ~RemoveLayerCommand();
Chris@0 278
Chris@0 279 virtual void execute();
Chris@0 280 virtual void unexecute();
Chris@0 281 virtual QString getName() const { return m_name; }
Chris@0 282
Chris@0 283 protected:
Chris@0 284 Document *m_d;
Chris@0 285 View *m_view; // I don't own this
Chris@0 286 Layer *m_layer; // Document owns this, but I determine its lifespan
Chris@0 287 QString m_name;
Chris@0 288 bool m_added;
Chris@0 289 };
Chris@0 290
Chris@0 291 typedef std::map<Layer *, std::set<View *> > LayerViewMap;
Chris@0 292 LayerViewMap m_layerViewMap;
Chris@0 293
Chris@0 294 void addToLayerViewMap(Layer *, View *);
Chris@0 295 void removeFromLayerViewMap(Layer *, View *);
Chris@0 296
Chris@0 297 QString getUniqueLayerName(QString candidate);
Chris@0 298
Chris@0 299 /**
Chris@0 300 * And these are the layers. We also control the lifespans of
Chris@0 301 * these (usually through the commands used to add and remove them).
Chris@0 302 */
Chris@0 303 typedef std::set<Layer *> LayerSet;
Chris@0 304 LayerSet m_layers;
Chris@0 305 };
Chris@0 306
Chris@0 307 #endif