1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
2 
3 /*
4     Sonic Visualiser
5     An audio file viewer and annotation editor.
6     Centre for Digital Music, Queen Mary, University of London.
7     This file copyright 2006 Chris Cannam and QMUL.
8 
9     This program is free software; you can redistribute it and/or
10     modify it under the terms of the GNU General Public License as
11     published by the Free Software Foundation; either version 2 of the
12     License, or (at your option) any later version.  See the file
13     COPYING included with this distribution for more information.
14 */
15 
16 #ifndef SV_DOCUMENT_H
17 #define SV_DOCUMENT_H
18 
19 #include "layer/LayerFactory.h"
20 #include "transform/Transform.h"
21 #include "transform/ModelTransformer.h"
22 #include "transform/FeatureExtractionModelTransformer.h"
23 #include "base/Command.h"
24 
25 #include <map>
26 #include <set>
27 
28 class Model;
29 class Layer;
30 class View;
31 class WaveFileModel;
32 class AggregateWaveModel;
33 
34 class AdditionalModelConverter;
35 
36 class Align;
37 
38 /**
39  * A Sonic Visualiser document consists of a set of data models, and
40  * also the visualisation layers used to display them.  Changes to the
41  * layers and their layout need to be stored and managed in much the
42  * same way as changes to the underlying data.
43  *
44  * The document manages:
45  *
46  *  - A main data Model, which provides the underlying sample rate and
47  * such like.  This must be a WaveFileModel.
48  *
49  *  - Any number of imported Model objects, which contain data without any
50  * requirement to remember where the data came from or how to
51  * regenerate it.
52  *
53  *  - Any number of Model objects that were generated by a Transformer
54  * such as FeatureExtractionModelTransformer.  For these, we also
55  * record the source model and the name of the transform used to
56  * generate the model so that we can regenerate it (potentially
57  * from a different source) on demand.
58  *
59  *  - A flat list of Layer objects.  Elsewhere, the GUI may distribute these
60  * across any number of View widgets.  A layer may be viewable on more
61  * than one view at once, in principle.  A layer refers to one model,
62  * but the same model can be in use in more than one layer.
63  *
64  * The document does *not* manage the existence or structure of Pane
65  * and other view widgets.  However, it does provide convenience
66  * methods for reference-counted command-based management of the
67  * association between layers and views (addLayerToView,
68  * removeLayerFromView).
69  */
70 
71 class Document : public QObject,
72                  public XmlExportable
73 {
74     Q_OBJECT
75 
76 public:
77     Document();
78     virtual ~Document();
79 
80     /**
81      * Create and return a new layer of the given type, associated
82      * with no model.  The caller may set any model on this layer, but
83      * the model must also be registered with the document via the
84      * add-model methods below.
85      */
86     Layer *createLayer(LayerFactory::LayerType);
87 
88     /**
89      * Create and return a new layer of the given type, associated
90      * with the current main model (if appropriate to the layer type).
91      */
92     Layer *createMainModelLayer(LayerFactory::LayerType);
93 
94     /**
95      * Create and return a new layer associated with the given model,
96      * and register the model as an imported model.
97      */
98     Layer *createImportedLayer(ModelId);
99 
100     /**
101      * Create and return a new layer of the given type, with an
102      * appropriate empty model.  If the given type is not one for
103      * which an empty model can meaningfully be created, return 0.
104      */
105     Layer *createEmptyLayer(LayerFactory::LayerType);
106 
107     /**
108      * Create and return a new layer of the given type, associated
109      * with the given transform name.  This method does not run the
110      * transform itself, nor create a model.  The caller can safely
111      * add a model to the layer later, but note that all models used
112      * by a transform layer _must_ be registered with the document
113      * using addDerivedModel below.
114      */
115     Layer *createDerivedLayer(LayerFactory::LayerType, TransformId);
116 
117     /**
118      * Create and return a suitable layer for the given transform,
119      * running the transform and associating the resulting model with
120      * the new layer.
121      */
122     Layer *createDerivedLayer(const Transform &,
123                               const ModelTransformer::Input &);
124 
125     /**
126      * Create and return suitable layers for the given transforms,
127      * which must be identical apart from the output (i.e. must use
128      * the same plugin and configuration). The layers are returned in
129      * the same order as the transforms are supplied.
130      */
131     std::vector<Layer *> createDerivedLayers(const Transforms &,
132                                              const ModelTransformer::Input &);
133 
134     typedef void *LayerCreationAsyncHandle;
135 
136     class LayerCreationHandler {
137     public:
~LayerCreationHandler()138         virtual ~LayerCreationHandler() { }
139 
140         /**
141          * The primary layers are those corresponding 1-1 to the input
142          * models, listed in the same order as the input models. The
143          * additional layers vector contains any layers (from all
144          * models) that were returned separately at the end of
145          * processing. The handle indicates which async process this
146          * callback was initiated by. It must not be used again after
147          * this function returns.
148          */
149         virtual void layersCreated(LayerCreationAsyncHandle handle,
150                                    std::vector<Layer *> primary,
151                                    std::vector<Layer *> additional) = 0;
152     };
153 
154     /**
155      * Create suitable layers for the given transforms, which must be
156      * identical apart from the output (i.e. must use the same plugin
157      * and configuration). This method returns after initialising the
158      * transformer process, and the layers are returned through a
159      * subsequent call to the provided handler (which must be
160      * non-null). The handle returned will be passed through to the
161      * handler callback.
162      */
163     LayerCreationAsyncHandle createDerivedLayersAsync(const Transforms &,
164                                                       const ModelTransformer::Input &,
165                                                       LayerCreationHandler *handler);
166 
167     /**
168      * Indicate that the async layer creation task associated with the
169      * given handle should be cancelled. There is no guarantee about
170      * what this will mean, and the handler callback may still be
171      * called.
172      */
173     void cancelAsyncLayerCreation(LayerCreationAsyncHandle handle);
174 
175     /**
176      * Delete the given layer, and also its associated model if no
177      * longer used by any other layer.  In general, this should be the
178      * only method used to delete layers -- doing so directly is a bit
179      * of a social gaffe.
180      */
181     void deleteLayer(Layer *, bool force = false);
182 
183     /**
184      * Set the main model (the source for playback sample rate, etc)
185      * to the given wave file model.  This will regenerate any derived
186      * models that were based on the previous main model. The model
187      * must have been added to ModelById already, and Document will
188      * take responsibility for releasing it later.
189      */
190     void setMainModel(ModelId); // a WaveFileModel
191 
192     /**
193      * Get the main model (the source for playback sample rate, etc).
194      */
getMainModel()195     ModelId getMainModel() { return m_mainModel; }
196 
197     std::vector<ModelId> getTransformInputModels();
198 
199     /**
200      * Return true if the model id is known to be the main model or
201      * one of the other existing models that can be shown in a new
202      * layer.
203      */
204     bool isKnownModel(ModelId) const;
205 
206     /**
207      * Add a derived model associated with the given transform,
208      * running the transform and returning the resulting model.
209      * The model is added to ModelById before returning.
210      */
211     ModelId addDerivedModel(const Transform &transform,
212                             const ModelTransformer::Input &input,
213                             QString &returnedMessage);
214 
215     /**
216      * Add derived models associated with the given set of related
217      * transforms, running the transforms and returning the resulting
218      * models.  The models are added to ModelById before returning.
219      */
220     friend class AdditionalModelConverter;
221     std::vector<ModelId> addDerivedModels(const Transforms &transforms,
222                                           const ModelTransformer::Input &input,
223                                           QString &returnedMessage,
224                                           AdditionalModelConverter *);
225 
226     /**
227      * Add a derived model associated with the given transform.  This
228      * is necessary to register any derived model that was not created
229      * by the document using createDerivedModel or
230      * createDerivedLayer. Document will take responsibility for
231      * releasing the model later.
232      */
233     void addAlreadyDerivedModel(const Transform &transform,
234                                 const ModelTransformer::Input &input,
235                                 ModelId outputModelToAdd);
236 
237     /**
238      * Add an imported model, i.e. any model (other than the main
239      * model) that has been created by any means other than as the
240      * output of a transform.  This is necessary to register any
241      * imported model that is to be associated with a layer, and also
242      * to make sure that the model is released by the Document
243      * later. Aggregate models, alignment models, and miscellaneous
244      * temporary models should also be added in this way, unless the
245      * temporary models are large enough to need managing in a way
246      * that guarantees the shortest possible lifespan.
247      */
248     void addNonDerivedModel(ModelId);
249 
250     /**
251      * Associate the given model with the given layer.  The model must
252      * have already been registered using one of the addXXModel
253      * methods above.
254      */
255     void setModel(Layer *, ModelId);
256 
257     /**
258      * Set the given layer to use the given channel of its model (-1
259      * means all available channels).
260      */
261     void setChannel(Layer *, int);
262 
263     /**
264      * Add the given layer to the given view.  If the layer is
265      * intended to show a particular model, the model should normally
266      * be set using setModel before this method is called.
267      */
268     void addLayerToView(View *, Layer *);
269 
270     /**
271      * Remove the given layer from the given view. Ownership of the
272      * layer is transferred to a command object on the undo stack, and
273      * the layer will be deleted when the undo stack is pruned.
274      */
275     void removeLayerFromView(View *, Layer *);
276 
277     /**
278      * Return true if alignment is supported (i.e. if the necessary
279      * plugin is found).
280      */
281     static bool canAlign();
282 
283     /**
284      * Specify whether models added via addImportedModel should be
285      * automatically aligned against the main model if appropriate.
286      */
setAutoAlignment(bool on)287     void setAutoAlignment(bool on) { m_autoAlignment = on; }
288 
289     /**
290      * Generate alignments for all appropriate models against the main
291      * model.  Existing alignments will not be re-calculated unless
292      * the main model has changed since they were calculated.
293      */
294     void alignModels();
295 
296     /**
297      * Re-generate alignments for all appropriate models against the
298      * main model.  Existing alignments will be re-calculated.
299      */
300     void realignModels();
301 
302     /**
303      * Return true if any external files (most obviously audio) failed
304      * to be found on load, so that the document is incomplete
305      * compared to its saved description.
306      */
isIncomplete()307     bool isIncomplete() const { return m_isIncomplete; }
308 
setIncomplete(bool i)309     void setIncomplete(bool i) { m_isIncomplete = i; }
310 
311     void toXml(QTextStream &, QString indent, QString extraAttributes) const override;
312     void toXmlAsTemplate(QTextStream &, QString indent, QString extraAttributes) const;
313 
314 signals:
315     void layerAdded(Layer *);
316     void layerRemoved(Layer *);
317     void layerAboutToBeDeleted(Layer *);
318 
319     // Emitted when a layer is first added to a view, or when it is
320     // last removed from a view
321     void layerInAView(Layer *, bool);
322 
323     void modelAdded(ModelId);
324     void mainModelChanged(ModelId); // a WaveFileModel; emitted after modelAdded
325 
326     void modelGenerationFailed(QString transformName, QString message);
327     void modelGenerationWarning(QString transformName, QString message);
328     void modelRegenerationFailed(QString layerName, QString transformName,
329                                  QString message);
330     void modelRegenerationWarning(QString layerName, QString transformName,
331                                   QString message);
332 
333     void alignmentComplete(ModelId); // an AlignmentModel
334     void alignmentFailed(QString message);
335 
336     void activity(QString);
337 
338 protected slots:
339     void performDeferredAlignment(ModelId);
340 
341 protected:
342     void releaseModel(ModelId model);
343 
344     /**
345      * If model is suitable for alignment, align it against the main
346      * model and store the alignment in the model. If the model has an
347      * alignment already for the current main model, leave it
348      * unchanged unless forceRecalculate is true.
349      */
350     void alignModel(ModelId, bool forceRecalculate = false);
351 
352     /*
353      * Every model that is in use by a layer in the document must be
354      * found in either m_mainModel or m_models.  We own and control
355      * the lifespan of all of these models.
356      */
357 
358     /**
359      * The model that provides the underlying sample rate, etc.  This
360      * model is not reference counted for layers, and is not freed
361      * unless it is replaced or the document is deleted.
362      */
363     ModelId m_mainModel; // a WaveFileModel
364 
365     struct ModelRecord
366     {
367         // Information associated with a non-main model.  If this
368         // model is derived from another, then source will be
369         // something other than None and the transform name will be
370         // set appropriately.  If the transform is set but source is
371         // None, then there was a transform involved but the (target)
372         // model has been modified since being generated from it.
373 
374         // This does not use ModelTransformer::Input, because it would
375         // be confusing to have Input objects hanging around with None
376         // models in them.
377 
378         ModelId source; // may be None
379         int channel;
380         Transform transform;
381         bool additional;
382     };
383 
384     // These must be stored in increasing order of id (as in the
385     // ordered std::map), to ensure repeatability for automated tests
386     std::map<ModelId, ModelRecord> m_models;
387 
388     std::set<ModelId> m_aggregateModels;
389     std::set<ModelId> m_alignmentModels;
390 
391     /**
392      * Add an extra derived model (returned at the end of processing a
393      * transform).
394      */
395     void addAdditionalModel(ModelId);
396 
397     class AddLayerCommand : public Command
398     {
399     public:
400         AddLayerCommand(Document *d, View *view, Layer *layer);
401         virtual ~AddLayerCommand();
402 
403         void execute() override;
404         void unexecute() override;
405         QString getName() const override;
406 
407     protected:
408         Document *m_d;
409         View *m_view; // I don't own this
410         Layer *m_layer; // Document owns this, but I determine its lifespan
411         QString m_name;
412         bool m_added;
413     };
414 
415     class RemoveLayerCommand : public Command
416     {
417     public:
418         RemoveLayerCommand(Document *d, View *view, Layer *layer);
419         virtual ~RemoveLayerCommand();
420 
421         void execute() override;
422         void unexecute() override;
423         QString getName() const override;
424 
425     protected:
426         Document *m_d;
427         View *m_view; // I don't own this
428         Layer *m_layer; // Document owns this, but I determine its lifespan
429         bool m_wasDormant;
430         QString m_name;
431         bool m_added;
432     };
433 
434     typedef std::map<Layer *, std::set<View *> > LayerViewMap;
435     LayerViewMap m_layerViewMap;
436 
437     void addToLayerViewMap(Layer *, View *);
438     void removeFromLayerViewMap(Layer *, View *);
439 
440     QString getUniqueLayerName(QString candidate);
441     void writeBackwardCompatibleDerivation(QTextStream &, QString, ModelId,
442                                            const ModelRecord &) const;
443 
444     void toXml(QTextStream &, QString, QString, bool asTemplate) const;
445     void writePlaceholderMainModel(QTextStream &, QString) const;
446 
447     std::vector<Layer *> createLayersForDerivedModels(std::vector<ModelId>,
448                                                       QStringList names);
449 
450     /**
451      * And these are the layers.  We also control the lifespans of
452      * these (usually through the commands used to add and remove them).
453      */
454     typedef std::vector<Layer *> LayerList;
455     LayerList m_layers;
456 
457     bool m_autoAlignment;
458     Align *m_align;
459 
460     bool m_isIncomplete;
461 };
462 
463 #endif
464