annotate framework/Document.h @ 342:4eccff14b4d8 tonioni

Much fiddling toward getting sessions and individual audio files to load cleanly when they need quite different handling after load
author Chris Cannam
date Wed, 02 Apr 2014 21:25:56 +0100
parents dd07d48d7d4f
children f5c914661f6f
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"
gyorgyf@270 22 #include "transform/FeatureExtractionModelTransformer.h"
Chris@45 23 #include "base/Command.h"
Chris@45 24
Chris@45 25 #include <map>
Chris@45 26 #include <set>
Chris@45 27
Chris@45 28 class Model;
Chris@45 29 class Layer;
Chris@45 30 class View;
Chris@45 31 class WaveFileModel;
Chris@45 32
Chris@329 33 class AdditionalModelConverter;
Chris@329 34
Chris@45 35 /**
Chris@45 36 * A Sonic Visualiser document consists of a set of data models, and
Chris@45 37 * also the visualisation layers used to display them. Changes to the
Chris@45 38 * layers and their layout need to be stored and managed in much the
Chris@45 39 * same way as changes to the underlying data.
Chris@45 40 *
Chris@45 41 * The document manages:
Chris@45 42 *
Chris@45 43 * - A main data Model, which provides the underlying sample rate and
Chris@45 44 * such like. This must be a WaveFileModel.
Chris@45 45 *
Chris@45 46 * - Any number of imported Model objects, which contain data without any
Chris@45 47 * requirement to remember where the data came from or how to
Chris@45 48 * regenerate it.
Chris@45 49 *
Chris@53 50 * - Any number of Model objects that were generated by a Transformer
Chris@54 51 * such as FeatureExtractionModelTransformer. For these, we also
Chris@45 52 * record the source model and the name of the transform used to
Chris@45 53 * generate the model so that we can regenerate it (potentially
Chris@45 54 * from a different source) on demand.
Chris@45 55 *
Chris@45 56 * - A flat list of Layer objects. Elsewhere, the GUI may distribute these
Chris@45 57 * across any number of View widgets. A layer may be viewable on more
Chris@45 58 * than one view at once, in principle. A layer refers to one model,
Chris@45 59 * but the same model can be in use in more than one layer.
Chris@45 60 *
Chris@45 61 * The document does *not* manage the existence or structure of Pane
Chris@45 62 * and other view widgets. However, it does provide convenience
Chris@45 63 * methods for reference-counted command-based management of the
Chris@45 64 * association between layers and views (addLayerToView,
Chris@45 65 * removeLayerFromView).
Chris@45 66 */
Chris@45 67
Chris@45 68 class Document : public QObject,
Chris@45 69 public XmlExportable
Chris@45 70 {
Chris@45 71 Q_OBJECT
Chris@45 72
Chris@45 73 public:
Chris@45 74 Document();
Chris@45 75 virtual ~Document();
Chris@45 76
Chris@45 77 /**
Chris@45 78 * Create and return a new layer of the given type, associated
Chris@45 79 * with no model. The caller may set any model on this layer, but
Chris@45 80 * the model must also be registered with the document via the
Chris@45 81 * add-model methods below.
Chris@45 82 */
Chris@45 83 Layer *createLayer(LayerFactory::LayerType);
Chris@45 84
Chris@45 85 /**
Chris@45 86 * Create and return a new layer of the given type, associated
Chris@45 87 * with the current main model (if appropriate to the layer type).
Chris@45 88 */
Chris@45 89 Layer *createMainModelLayer(LayerFactory::LayerType);
Chris@45 90
Chris@45 91 /**
Chris@45 92 * Create and return a new layer associated with the given model,
Chris@45 93 * and register the model as an imported model.
Chris@45 94 */
Chris@45 95 Layer *createImportedLayer(Model *);
Chris@45 96
Chris@45 97 /**
Chris@45 98 * Create and return a new layer of the given type, with an
Chris@45 99 * appropriate empty model. If the given type is not one for
Chris@45 100 * which an empty model can meaningfully be created, return 0.
Chris@45 101 */
Chris@45 102 Layer *createEmptyLayer(LayerFactory::LayerType);
Chris@45 103
Chris@45 104 /**
Chris@45 105 * Create and return a new layer of the given type, associated
Chris@45 106 * with the given transform name. This method does not run the
Chris@45 107 * transform itself, nor create a model. The caller can safely
Chris@45 108 * add a model to the layer later, but note that all models used
Chris@45 109 * by a transform layer _must_ be registered with the document
Chris@45 110 * using addDerivedModel below.
Chris@45 111 */
Chris@54 112 Layer *createDerivedLayer(LayerFactory::LayerType, TransformId);
Chris@45 113
Chris@45 114 /**
Chris@45 115 * Create and return a suitable layer for the given transform,
Chris@45 116 * running the transform and associating the resulting model with
Chris@45 117 * the new layer.
Chris@45 118 */
Chris@72 119 Layer *createDerivedLayer(const Transform &,
Chris@72 120 const ModelTransformer::Input &);
Chris@45 121
Chris@45 122 /**
Chris@297 123 * Create and return suitable layers for the given transforms,
Chris@297 124 * which must be identical apart from the output (i.e. must use
Chris@297 125 * the same plugin and configuration). The layers are returned in
Chris@329 126 * the same order as the transforms are supplied.
matthiasm@269 127 */
Chris@297 128 std::vector<Layer *> createDerivedLayers(const Transforms &,
Chris@297 129 const ModelTransformer::Input &);
matthiasm@269 130
Chris@329 131 class LayerCreationHandler {
Chris@329 132 public:
Chris@329 133 virtual ~LayerCreationHandler() { }
Chris@329 134
Chris@329 135 /**
Chris@329 136 * The primary layers are those corresponding 1-1 to the input
Chris@329 137 * models, listed in the same order as the input models. The
Chris@329 138 * additional layers vector contains any layers (from all
Chris@329 139 * models) that were returned separately at the end of
Chris@329 140 * processing.
Chris@329 141 */
Chris@329 142 virtual void layersCreated(std::vector<Layer *> primary,
Chris@329 143 std::vector<Layer *> additional) = 0;
Chris@329 144 };
Chris@329 145
Chris@329 146 /**
Chris@329 147 * Create suitable layers for the given transforms, which must be
Chris@329 148 * identical apart from the output (i.e. must use the same plugin
Chris@329 149 * and configuration). This method returns after initialising the
Chris@329 150 * transformer process, and the layers are returned through a
Chris@329 151 * subsequent call to the provided handler (which must be non-null).
Chris@329 152 */
Chris@329 153 void createDerivedLayersAsync(const Transforms &,
Chris@329 154 const ModelTransformer::Input &,
Chris@329 155 LayerCreationHandler *handler);
Chris@329 156
matthiasm@269 157 /**
Chris@52 158 * Delete the given layer, and also its associated model if no
Chris@52 159 * longer used by any other layer. In general, this should be the
Chris@52 160 * only method used to delete layers -- doing so directly is a bit
Chris@52 161 * of a social gaffe.
Chris@52 162 */
Chris@52 163 void deleteLayer(Layer *, bool force = false);
Chris@52 164
Chris@52 165 /**
Chris@45 166 * Set the main model (the source for playback sample rate, etc)
Chris@45 167 * to the given wave file model. This will regenerate any derived
Chris@45 168 * models that were based on the previous main model.
Chris@45 169 */
Chris@45 170 void setMainModel(WaveFileModel *);
Chris@45 171
Chris@45 172 /**
Chris@45 173 * Get the main model (the source for playback sample rate, etc).
Chris@45 174 */
Chris@45 175 WaveFileModel *getMainModel() { return m_mainModel; }
Chris@45 176
Chris@45 177 /**
Chris@45 178 * Get the main model (the source for playback sample rate, etc).
Chris@45 179 */
Chris@45 180 const WaveFileModel *getMainModel() const { return m_mainModel; }
Chris@45 181
Chris@72 182 std::vector<Model *> getTransformInputModels();
Chris@45 183
Chris@77 184 bool isKnownModel(const Model *) const;
Chris@77 185
Chris@45 186 /**
Chris@45 187 * Add a derived model associated with the given transform,
Chris@45 188 * running the transform and returning the resulting model.
Chris@45 189 */
Chris@72 190 Model *addDerivedModel(const Transform &transform,
Chris@78 191 const ModelTransformer::Input &input,
Chris@296 192 QString &returnedMessage);
Chris@45 193
Chris@45 194 /**
Chris@297 195 * Add derived models associated with the given set of related
Chris@297 196 * transforms, running the transforms and returning the resulting
Chris@297 197 * models.
Chris@297 198 */
Chris@329 199 friend class AdditionalModelConverter;
Chris@297 200 std::vector<Model *> addDerivedModels(const Transforms &transforms,
Chris@297 201 const ModelTransformer::Input &input,
Chris@329 202 QString &returnedMessage,
Chris@329 203 AdditionalModelConverter *);
Chris@297 204
Chris@297 205 /**
Chris@45 206 * Add a derived model associated with the given transform. This
Chris@45 207 * is necessary to register any derived model that was not created
Chris@45 208 * by the document using createDerivedModel or createDerivedLayer.
Chris@45 209 */
Chris@329 210 void addAlreadyDerivedModel(const Transform &transform,
Chris@329 211 const ModelTransformer::Input &input,
Chris@329 212 Model *outputModelToAdd);
Chris@45 213
Chris@45 214 /**
Chris@45 215 * Add an imported (non-derived, non-main) model. This is
Chris@45 216 * necessary to register any imported model that is associated
Chris@45 217 * with a layer.
Chris@45 218 */
Chris@45 219 void addImportedModel(Model *);
Chris@45 220
Chris@45 221 /**
Chris@45 222 * Associate the given model with the given layer. The model must
Chris@45 223 * have already been registered using one of the addXXModel
Chris@45 224 * methods above.
Chris@45 225 */
Chris@45 226 void setModel(Layer *, Model *);
Chris@45 227
Chris@45 228 /**
Chris@45 229 * Set the given layer to use the given channel of its model (-1
Chris@45 230 * means all available channels).
Chris@45 231 */
Chris@45 232 void setChannel(Layer *, int);
Chris@45 233
Chris@45 234 /**
Chris@45 235 * Add the given layer to the given view. If the layer is
Chris@45 236 * intended to show a particular model, the model should normally
Chris@45 237 * be set using setModel before this method is called.
Chris@45 238 */
Chris@45 239 void addLayerToView(View *, Layer *);
Chris@45 240
Chris@45 241 /**
Chris@333 242 * Remove the given layer from the given view. Ownership of the
Chris@333 243 * layer is transferred to a command object on the undo stack, and
Chris@333 244 * the layer will be deleted when the undo stack is pruned.
Chris@45 245 */
Chris@45 246 void removeLayerFromView(View *, Layer *);
Chris@45 247
Chris@48 248 /**
Chris@50 249 * Return true if alignment is supported (i.e. if the necessary
Chris@50 250 * plugin is found).
Chris@50 251 */
Chris@51 252 static bool canAlign();
Chris@50 253
Chris@50 254 /**
Chris@48 255 * Specify whether models added via addImportedModel should be
Chris@48 256 * automatically aligned against the main model if appropriate.
Chris@48 257 */
Chris@48 258 void setAutoAlignment(bool on) { m_autoAlignment = on; }
Chris@48 259
Chris@48 260 /**
Chris@48 261 * Generate alignments for all appropriate models against the main
Chris@48 262 * model. Existing alignments will not be re-calculated unless
Chris@48 263 * the main model has changed since they were calculated.
Chris@48 264 */
Chris@48 265 void alignModels();
Chris@48 266
Chris@45 267 void toXml(QTextStream &, QString indent, QString extraAttributes) const;
Chris@226 268 void toXmlAsTemplate(QTextStream &, QString indent, QString extraAttributes) const;
Chris@47 269
Chris@45 270 signals:
Chris@45 271 void layerAdded(Layer *);
Chris@45 272 void layerRemoved(Layer *);
Chris@45 273 void layerAboutToBeDeleted(Layer *);
Chris@45 274
Chris@45 275 // Emitted when a layer is first added to a view, or when it is
Chris@45 276 // last removed from a view
Chris@45 277 void layerInAView(Layer *, bool);
Chris@45 278
Chris@45 279 void modelAdded(Model *);
Chris@45 280 void mainModelChanged(WaveFileModel *); // emitted after modelAdded
Chris@45 281 void modelAboutToBeDeleted(Model *);
Chris@45 282
Chris@78 283 void modelGenerationFailed(QString transformName, QString message);
Chris@78 284 void modelGenerationWarning(QString transformName, QString message);
Chris@78 285 void modelRegenerationFailed(QString layerName, QString transformName,
Chris@78 286 QString message);
Chris@78 287 void modelRegenerationWarning(QString layerName, QString transformName,
Chris@78 288 QString message);
Chris@78 289 void alignmentFailed(QString transformName, QString message);
Chris@45 290
Chris@160 291 void activity(QString);
Chris@160 292
Chris@45 293 protected:
Chris@45 294 void releaseModel(Model *model);
Chris@45 295
Chris@45 296 /**
Chris@45 297 * If model is suitable for alignment, align it against the main
Chris@48 298 * model and store the alignment in the model. (If the model has
Chris@48 299 * an alignment already for the current main model, leave it
Chris@48 300 * unchanged.)
Chris@45 301 */
Chris@45 302 void alignModel(Model *);
Chris@45 303
Chris@45 304 /*
Chris@45 305 * Every model that is in use by a layer in the document must be
Chris@45 306 * found in either m_mainModel or m_models. We own and control
Chris@45 307 * the lifespan of all of these models.
Chris@45 308 */
Chris@45 309
Chris@45 310 /**
Chris@45 311 * The model that provides the underlying sample rate, etc. This
Chris@45 312 * model is not reference counted for layers, and is not freed
Chris@45 313 * unless it is replaced or the document is deleted.
Chris@45 314 */
Chris@45 315 WaveFileModel *m_mainModel;
Chris@45 316
Chris@45 317 struct ModelRecord
Chris@45 318 {
Chris@45 319 // Information associated with a non-main model. If this
Chris@45 320 // model is derived from another, then source will be non-NULL
Chris@45 321 // and the transform name will be set appropriately. If the
Chris@45 322 // transform name is set but source is NULL, then there was a
Chris@45 323 // transform involved but the (target) model has been modified
Chris@45 324 // since being generated from it.
Chris@72 325
Chris@72 326 // This does not use ModelTransformer::Input, because it would
Chris@72 327 // be confusing to have Input objects hanging around with NULL
Chris@72 328 // models in them.
Chris@72 329
Chris@45 330 const Model *source;
Chris@72 331 int channel;
Chris@72 332 Transform transform;
Chris@329 333 bool additional;
Chris@45 334
Chris@45 335 // Count of the number of layers using this model.
Chris@45 336 int refcount;
Chris@45 337 };
Chris@45 338
Chris@45 339 typedef std::map<Model *, ModelRecord> ModelMap;
Chris@45 340 ModelMap m_models;
Chris@45 341
Chris@329 342 /**
Chris@329 343 * Add an extra derived model (returned at the end of processing a
Chris@329 344 * transform).
Chris@329 345 */
Chris@329 346 void addAdditionalModel(Model *);
Chris@329 347
Chris@45 348 class AddLayerCommand : public Command
Chris@45 349 {
Chris@45 350 public:
Chris@45 351 AddLayerCommand(Document *d, View *view, Layer *layer);
Chris@45 352 virtual ~AddLayerCommand();
Chris@45 353
Chris@45 354 virtual void execute();
Chris@45 355 virtual void unexecute();
Chris@159 356 virtual QString getName() const;
Chris@45 357
Chris@45 358 protected:
Chris@45 359 Document *m_d;
Chris@45 360 View *m_view; // I don't own this
Chris@83 361 Layer *m_layer; // Document owns this, but I determine its lifespan
Chris@45 362 QString m_name;
Chris@45 363 bool m_added;
Chris@45 364 };
Chris@45 365
Chris@45 366 class RemoveLayerCommand : public Command
Chris@45 367 {
Chris@45 368 public:
Chris@45 369 RemoveLayerCommand(Document *d, View *view, Layer *layer);
Chris@45 370 virtual ~RemoveLayerCommand();
Chris@45 371
Chris@45 372 virtual void execute();
Chris@45 373 virtual void unexecute();
Chris@159 374 virtual QString getName() const;
Chris@45 375
Chris@45 376 protected:
Chris@45 377 Document *m_d;
Chris@45 378 View *m_view; // I don't own this
Chris@45 379 Layer *m_layer; // Document owns this, but I determine its lifespan
Chris@339 380 bool m_wasDormant;
Chris@45 381 QString m_name;
Chris@45 382 bool m_added;
Chris@45 383 };
Chris@45 384
Chris@45 385 typedef std::map<Layer *, std::set<View *> > LayerViewMap;
Chris@45 386 LayerViewMap m_layerViewMap;
Chris@45 387
Chris@45 388 void addToLayerViewMap(Layer *, View *);
Chris@45 389 void removeFromLayerViewMap(Layer *, View *);
Chris@45 390
Chris@45 391 QString getUniqueLayerName(QString candidate);
Chris@72 392 void writeBackwardCompatibleDerivation(QTextStream &, QString, Model *,
Chris@72 393 const ModelRecord &) const;
Chris@90 394
Chris@90 395 static TransformId getAlignmentTransformName();
Chris@45 396
Chris@226 397 void toXml(QTextStream &, QString, QString, bool asTemplate) const;
Chris@226 398 void writePlaceholderMainModel(QTextStream &, QString) const;
Chris@226 399
Chris@329 400 std::vector<Layer *> createLayersForDerivedModels(std::vector<Model *>,
Chris@329 401 QStringList names);
Chris@329 402
Chris@45 403 /**
Chris@45 404 * And these are the layers. We also control the lifespans of
Chris@45 405 * these (usually through the commands used to add and remove them).
Chris@45 406 */
Chris@45 407 typedef std::set<Layer *> LayerSet;
Chris@45 408 LayerSet m_layers;
Chris@47 409
Chris@47 410 bool m_autoAlignment;
Chris@45 411 };
Chris@45 412
Chris@45 413 #endif