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