LayerFactory.cpp
Go to the documentation of this file.
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.
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 #include "LayerFactory.h"
17 
18 #include "WaveformLayer.h"
19 #include "SpectrogramLayer.h"
20 #include "TimeRulerLayer.h"
21 #include "TimeInstantLayer.h"
22 #include "TimeValueLayer.h"
23 #include "NoteLayer.h"
24 #include "FlexiNoteLayer.h"
25 #include "RegionLayer.h"
26 #include "BoxLayer.h"
27 #include "TextLayer.h"
28 #include "ImageLayer.h"
29 #include "Colour3DPlotLayer.h"
30 #include "SpectrumLayer.h"
31 #include "SliceLayer.h"
32 #include "SliceableLayer.h"
33 
34 #include "base/Clipboard.h"
35 
36 #include "data/model/RangeSummarisableTimeValueModel.h"
37 #include "data/model/DenseTimeValueModel.h"
38 #include "data/model/SparseOneDimensionalModel.h"
39 #include "data/model/SparseTimeValueModel.h"
40 #include "data/model/NoteModel.h"
41 #include "data/model/RegionModel.h"
42 #include "data/model/BoxModel.h"
43 #include "data/model/TextModel.h"
44 #include "data/model/ImageModel.h"
45 #include "data/model/DenseThreeDimensionalModel.h"
46 #include "data/model/WaveFileModel.h"
47 #include "data/model/WritableWaveFileModel.h"
48 
49 #include <QDomDocument>
50 #include <QDomElement>
51 #include <QDomNamedNodeMap>
52 #include <QDomAttr>
53 
54 #include <QSettings>
55 
58 
61 {
62  return m_instance;
63 }
64 
66 {
67 }
68 
69 QString
71 {
72  switch (type) {
73  case Waveform: return Layer::tr("Waveform");
74  case Spectrogram: return Layer::tr("Spectrogram");
75  case TimeRuler: return Layer::tr("Ruler");
76  case TimeInstants: return Layer::tr("Time Instants");
77  case TimeValues: return Layer::tr("Time Values");
78  case Notes: return Layer::tr("Notes");
79  case FlexiNotes: return Layer::tr("Flexible Notes");
80  case Regions: return Layer::tr("Regions");
81  case Boxes: return Layer::tr("Boxes");
82  case Text: return Layer::tr("Text");
83  case Image: return Layer::tr("Images");
84  case Colour3DPlot: return Layer::tr("Colour 3D Plot");
85  case Spectrum: return Layer::tr("Spectrum");
86  case Slice: return Layer::tr("Time Slice");
87 
89  // The user can change all the parameters of this after the
90  // fact -- there's nothing permanently melodic-range about it
91  // that should be encoded in its name
92  return Layer::tr("Spectrogram");
93 
95  // likewise
96  return Layer::tr("Spectrogram");
97 
98  case UnknownLayer:
99  default:
100  cerr << "WARNING: LayerFactory::getLayerPresentationName passed unknown layer" << endl;
101  return Layer::tr("Unknown Layer");
102  }
103 }
104 
105 bool
107 {
108  if (dynamic_cast<const SliceableLayer *>(layer)) {
109  if (dynamic_cast<const SpectrogramLayer *>(layer)) {
110 
112  // problem managing the models. The source model for the
113  // slice layer has to be one of the spectrogram's FFT
114  // models -- that's fine, except that we can't store &
115  // recall the slice layer with a reference to that model
116  // because the model is internal to the spectrogram layer
117  // and the document has no record of it. We would need
118  // some other way of managing models that are used in this
119  // way. For the moment we just don't allow slices of
120  // spectrograms -- and provide a spectrum layer for this
121  // instead.
122  //
123  // This business needs a bit more thought -- either come
124  // up with a sensible way to deal with that stuff, or
125  // simplify the existing slice layer logic so that it
126  // doesn't have to deal with models disappearing on it at
127  // all (and use the normal Document setModel mechanism to
128  // set its sliceable model instead of the fancy pants
129  // nonsense it's doing at the moment).
130 
131  return false;
132  }
133  return true;
134  }
135  return false;
136 }
137 
140 {
141  LayerTypeSet types;
142 
143  if (ModelById::getAs<DenseThreeDimensionalModel>(modelId)) {
144  types.insert(Colour3DPlot);
145  types.insert(Slice);
146  }
147 
148  if (ModelById::getAs<RangeSummarisableTimeValueModel>(modelId)) {
149  types.insert(Waveform);
150  }
151 
152  if (ModelById::getAs<DenseTimeValueModel>(modelId)) {
153  types.insert(Spectrogram);
154  types.insert(MelodicRangeSpectrogram);
155  types.insert(PeakFrequencySpectrogram);
156  }
157 
158  if (ModelById::getAs<SparseOneDimensionalModel>(modelId)) {
159  types.insert(TimeInstants);
160  }
161 
162  if (ModelById::getAs<SparseTimeValueModel>(modelId)) {
163  types.insert(TimeValues);
164  }
165 
166  if (ModelById::getAs<NoteModel>(modelId)) {
167  auto nm = ModelById::getAs<NoteModel>(modelId);
168  if (nm && nm->getSubtype() == NoteModel::FLEXI_NOTE) {
169  types.insert(FlexiNotes);
170  } else {
171  types.insert(Notes);
172  }
173  }
174 
175  if (ModelById::getAs<RegionModel>(modelId)) {
176  types.insert(Regions);
177  }
178 
179  if (ModelById::getAs<BoxModel>(modelId)) {
180  types.insert(Boxes);
181  }
182 
183  if (ModelById::getAs<TextModel>(modelId)) {
184  types.insert(Text);
185  }
186 
187  if (ModelById::getAs<ImageModel>(modelId)) {
188  types.insert(Image);
189  }
190 
191  if (ModelById::getAs<DenseTimeValueModel>(modelId)) {
192  types.insert(Spectrum);
193  }
194 
195  // We don't count TimeRuler here as it doesn't actually display
196  // the data, although it can be backed by any model
197 
198  return types;
199 }
200 
203 {
204  LayerTypeSet types;
205  types.insert(TimeInstants);
206  types.insert(TimeValues);
207  // Because this is strictly a UI function -- list the layer types
208  // to show in a menu -- it should not contain FlexiNotes; the
209  // layer isn't meaningfully editable in SV
210 // types.insert(FlexiNotes);
211  types.insert(Notes);
212  types.insert(Regions);
213  types.insert(Boxes);
214  types.insert(Text);
215  types.insert(Image);
217  return types;
218 }
219 
222 {
223  if (dynamic_cast<const WaveformLayer *>(layer)) return Waveform;
224  if (dynamic_cast<const SpectrogramLayer *>(layer)) return Spectrogram;
225  if (dynamic_cast<const TimeRulerLayer *>(layer)) return TimeRuler;
226  if (dynamic_cast<const TimeInstantLayer *>(layer)) return TimeInstants;
227  if (dynamic_cast<const TimeValueLayer *>(layer)) return TimeValues;
228  if (dynamic_cast<const FlexiNoteLayer *>(layer)) return FlexiNotes;
229  if (dynamic_cast<const NoteLayer *>(layer)) return Notes;
230  if (dynamic_cast<const RegionLayer *>(layer)) return Regions;
231  if (dynamic_cast<const BoxLayer *>(layer)) return Boxes;
232  if (dynamic_cast<const TextLayer *>(layer)) return Text;
233  if (dynamic_cast<const ImageLayer *>(layer)) return Image;
234  if (dynamic_cast<const Colour3DPlotLayer *>(layer)) return Colour3DPlot;
235  if (dynamic_cast<const SpectrumLayer *>(layer)) return Spectrum;
236  if (dynamic_cast<const SliceLayer *>(layer)) return Slice;
237  return UnknownLayer;
238 }
239 
240 QString
242 {
243  switch (type) {
244  case Waveform: return "waveform";
245  case Spectrogram: return "spectrogram";
246  case TimeRuler: return "timeruler";
247  case TimeInstants: return "instants";
248  case TimeValues: return "values";
249  case Notes: return "notes";
250  case FlexiNotes: return "flexinotes";
251  case Regions: return "regions";
252  case Boxes: return "boxes";
253  case Text: return "text";
254  case Image: return "image";
255  case Colour3DPlot: return "colour3d";
256  case Spectrum: return "spectrum";
257  case Slice: return "spectrum";
258  case MelodicRangeSpectrogram: return "spectrogram";
259  case PeakFrequencySpectrogram: return "spectrogram";
260  case UnknownLayer:
261  default:
262  cerr << "WARNING: LayerFactory::getLayerIconName passed unknown layer" << endl;
263  return "unknown";
264  }
265 }
266 
267 QString
269 {
270  switch (type) {
271  case Waveform: return "waveform";
272  case Spectrogram: return "spectrogram";
273  case TimeRuler: return "timeruler";
274  case TimeInstants: return "timeinstants";
275  case TimeValues: return "timevalues";
276  case Notes: return "notes";
277  case FlexiNotes: return "flexinotes";
278  case Regions: return "regions";
279  case Boxes: return "boxes";
280  case Text: return "text";
281  case Image: return "image";
282  case Colour3DPlot: return "colour3dplot";
283  case Spectrum: return "spectrum";
284  case Slice: return "slice";
285  case MelodicRangeSpectrogram: return "melodicrange";
286  case PeakFrequencySpectrogram: return "peakfrequency";
287  case UnknownLayer:
288  default:
289  cerr << "WARNING: LayerFactory::getLayerTypeName passed unknown layer" << endl;
290  return "unknown";
291  }
292 }
293 
296 {
297  if (name == "waveform") return Waveform;
298  if (name == "spectrogram") return Spectrogram;
299  if (name == "timeruler") return TimeRuler;
300  if (name == "timeinstants") return TimeInstants;
301  if (name == "timevalues") return TimeValues;
302  if (name == "notes") return Notes;
303  if (name == "flexinotes") return FlexiNotes;
304  if (name == "regions") return Regions;
305  if (name == "boxes" || name == "timefrequencybox") return Boxes;
306  if (name == "text") return Text;
307  if (name == "image") return Image;
308  if (name == "colour3dplot") return Colour3DPlot;
309  if (name == "spectrum") return Spectrum;
310  if (name == "slice") return Slice;
311  if (name == "melodicrange") return MelodicRangeSpectrogram;
312  if (name == "peakfrequency") return PeakFrequencySpectrogram;
313  return UnknownLayer;
314 }
315 
316 void
317 LayerFactory::setModel(Layer *layer, ModelId model)
318 {
319  if (trySetModel<WaveformLayer, WaveFileModel>(layer, model))
320  return;
321 
322  if (trySetModel<WaveformLayer, WritableWaveFileModel>(layer, model))
323  return;
324 
325  if (trySetModel<SpectrogramLayer, DenseTimeValueModel>(layer, model))
326  return;
327 
328  if (trySetModel<TimeRulerLayer, Model>(layer, model))
329  return;
330 
331  if (trySetModel<TimeInstantLayer, SparseOneDimensionalModel>(layer, model))
332  return;
333 
334  if (trySetModel<TimeValueLayer, SparseTimeValueModel>(layer, model))
335  return;
336 
337  if (trySetModel<NoteLayer, NoteModel>(layer, model))
338  return;
339 
340  if (trySetModel<FlexiNoteLayer, NoteModel>(layer, model))
341  return;
342 
343  if (trySetModel<RegionLayer, RegionModel>(layer, model))
344  return;
345 
346  if (trySetModel<BoxLayer, BoxModel>(layer, model))
347  return;
348 
349  if (trySetModel<TextLayer, TextModel>(layer, model))
350  return;
351 
352  if (trySetModel<ImageLayer, ImageModel>(layer, model))
353  return;
354 
355  if (trySetModel<Colour3DPlotLayer, DenseThreeDimensionalModel>(layer, model))
356  return;
357 
358  if (trySetModel<SpectrumLayer, DenseTimeValueModel>(layer, model))
359  return;
360 }
361 
362 std::shared_ptr<Model>
363 LayerFactory::createEmptyModel(LayerType layerType, ModelId baseModelId)
364 {
365  auto baseModel = ModelById::get(baseModelId);
366  if (!baseModel) return {};
367 
368  sv_samplerate_t rate = baseModel->getSampleRate();
369 
370  if (layerType == TimeInstants) {
371  return std::make_shared<SparseOneDimensionalModel>(rate, 1);
372  } else if (layerType == TimeValues) {
373  return std::make_shared<SparseTimeValueModel>(rate, 1, true);
374  } else if (layerType == FlexiNotes) {
375  return std::make_shared<NoteModel>(rate, 1, true);
376  } else if (layerType == Notes) {
377  return std::make_shared<NoteModel>(rate, 1, true);
378  } else if (layerType == Regions) {
379  return std::make_shared<RegionModel>(rate, 1, true);
380  } else if (layerType == Boxes) {
381  return std::make_shared<BoxModel>(rate, 1, true);
382  } else if (layerType == Text) {
383  return std::make_shared<TextModel>(rate, 1, true);
384  } else if (layerType == Image) {
385  return std::make_shared<ImageModel>(rate, 1, true);
386  } else {
387  return {};
388  }
389 }
390 
391 int
393 {
394  if (dynamic_cast<WaveformLayer *>(layer)) {
395  return dynamic_cast<WaveformLayer *>(layer)->getChannel();
396  }
397  if (dynamic_cast<SpectrogramLayer *>(layer)) {
398  return dynamic_cast<SpectrogramLayer *>(layer)->getChannel();
399  }
400  return -1;
401 }
402 
403 void
404 LayerFactory::setChannel(Layer *layer, int channel)
405 {
406  if (dynamic_cast<WaveformLayer *>(layer)) {
407  dynamic_cast<WaveformLayer *>(layer)->setChannel(channel);
408  return;
409  }
410  if (dynamic_cast<SpectrogramLayer *>(layer)) {
411  dynamic_cast<SpectrogramLayer *>(layer)->setChannel(channel);
412  return;
413  }
414  if (dynamic_cast<SpectrumLayer *>(layer)) {
415  dynamic_cast<SpectrumLayer *>(layer)->setChannel(channel);
416  return;
417  }
418 }
419 
420 Layer *
422 {
423  Layer *layer = nullptr;
424 
425  switch (type) {
426 
427  case Waveform:
428  layer = new WaveformLayer;
429  break;
430 
431  case Spectrogram:
432  layer = new SpectrogramLayer;
433  break;
434 
435  case TimeRuler:
436  layer = new TimeRulerLayer;
437  break;
438 
439  case TimeInstants:
440  layer = new TimeInstantLayer;
441  break;
442 
443  case TimeValues:
444  layer = new TimeValueLayer;
445  break;
446 
447  case FlexiNotes:
448  layer = new FlexiNoteLayer;
449  break;
450 
451  case Notes:
452  layer = new NoteLayer;
453  break;
454 
455  case Regions:
456  layer = new RegionLayer;
457  break;
458 
459  case Boxes:
460  layer = new BoxLayer;
461  break;
462 
463  case Text:
464  layer = new TextLayer;
465  break;
466 
467  case Image:
468  layer = new ImageLayer;
469  break;
470 
471  case Colour3DPlot:
472  layer = new Colour3DPlotLayer;
473  break;
474 
475  case Spectrum:
476  layer = new SpectrumLayer;
477  break;
478 
479  case Slice:
480  layer = new SliceLayer;
481  break;
482 
485  break;
486 
489  break;
490 
491  case UnknownLayer:
492  default:
493  cerr << "WARNING: LayerFactory::createLayer passed unknown layer" << endl;
494  break;
495  }
496 
497  if (!layer) {
498  cerr << "LayerFactory::createLayer: Unknown layer type "
499  << type << endl;
500  } else {
501 // SVDEBUG << "LayerFactory::createLayer: Setting object name "
502 // << getLayerPresentationName(type) << " on " << layer << endl;
504  setLayerDefaultProperties(type, layer);
505  }
506 
507  return layer;
508 }
509 
510 void
512 {
513 // SVDEBUG << "LayerFactory::setLayerDefaultProperties: type " << type << " (name \"" << getLayerTypeName(type) << "\")" << endl;
514 
515  QSettings settings;
516  settings.beginGroup("LayerDefaults");
517  QString defaults = settings.value(getLayerTypeName(type), "").toString();
518  if (defaults == "") return;
519  setLayerProperties(layer, defaults);
520  settings.endGroup();
521 }
522 
523 void
525 {
526  QDomDocument docOld, docNew;
527  QString oldXml = layer->toXmlString();
528 
529  if (!docOld.setContent(oldXml, false)) {
530  SVCERR << "LayerFactory::setLayerProperties: Failed to parse XML for existing layer properties! XML string is: " << oldXml << endl;
531  return;
532  }
533 
534  if (!docNew.setContent(newXml, false)) {
535  SVCERR << "LayerFactory::setLayerProperties: Failed to parse XML: " << newXml << endl;
536  return;
537  }
538 
539  QXmlAttributes attrs;
540 
541  QDomElement layerElt = docNew.firstChildElement("layer");
542  QDomNamedNodeMap attrNodes = layerElt.attributes();
543 
544  for (int i = 0; i < attrNodes.length(); ++i) {
545  QDomAttr attr = attrNodes.item(i).toAttr();
546  if (attr.isNull()) continue;
547 // cerr << "append \"" << attr.name()
548 // << "\" -> \"" << attr.value() << "\""
549 // << endl;
550  attrs.append(attr.name(), "", "", attr.value());
551  }
552 
553  layerElt = docOld.firstChildElement("layer");
554  attrNodes = layerElt.attributes();
555  for (int i = 0; i < attrNodes.length(); ++i) {
556  QDomAttr attr = attrNodes.item(i).toAttr();
557  if (attr.isNull()) continue;
558  if (attrs.value(attr.name()) == "") {
559 // cerr << "append \"" << attr.name()
560 // << "\" -> \"" << attr.value() << "\""
561 // << endl;
562  attrs.append(attr.name(), "", "", attr.value());
563  }
564  }
565 
566  layer->setProperties(attrs);
567 }
568 
571 {
572  const EventVector &contents = clip.getPoints();
573 
574  bool haveValue = false;
575  bool haveDuration = false;
576  bool haveLevel = false;
577 
578  for (EventVector::const_iterator i = contents.begin();
579  i != contents.end(); ++i) {
580  if (i->hasValue()) haveValue = true;
581  if (i->hasDuration()) haveDuration = true;
582  if (i->hasLevel()) haveLevel = true;
583  }
584 
585  if (haveValue && haveDuration && haveLevel) return Notes;
586  if (haveValue && haveDuration) return Regions;
587  if (haveValue) return TimeValues;
588  return TimeInstants;
589 }
590 
static LayerFactory * getInstance()
QString getLayerIconName(LayerType)
The base class for visual representations of the data found in a Model.
Definition: Layer.h:54
virtual void setProperties(const QXmlAttributes &)=0
Set the particular properties of a layer (those specific to the subclass) from a set of XML attribute...
LayerTypeSet getValidLayerTypes(ModelId modelId)
SpectrogramLayer represents waveform data (obtained from a DenseTimeValueModel) in spectrogram form...
bool isLayerSliceable(const Layer *)
LayerType getLayerTypeForName(QString)
void setModel(Layer *layer, ModelId model)
This is a view that displays dense 3-D data (time, some sort of binned y-axis range, value) as a colour plot with value mapped to colour range.
LayerTypeSet getValidEmptyLayerTypes()
Return the set of layer types that an end user should be allowed to create, empty, for subsequent editing.
int getChannel(Layer *layer)
virtual void setObjectName(const QString &name)
Definition: Layer.cpp:122
QString getLayerPresentationName(LayerType type)
static LayerFactory * m_instance
Definition: LayerFactory.h:116
void setChannel(Layer *layer, int channel)
Layer for displaying and editing notes, i.e.
Definition: NoteLayer.h:41
Layer * createLayer(LayerType type)
void setLayerProperties(Layer *layer, QString xmlString)
Set the properties of a layer, from the XML string provided.
std::set< LayerType > LayerTypeSet
Definition: LayerFactory.h:60
LayerType getLayerType(const Layer *)
LayerType getLayerTypeForClipboardContents(const Clipboard &)
QString getLayerTypeName(LayerType)
virtual ~LayerFactory()
std::shared_ptr< Model > createEmptyModel(LayerType type, ModelId baseModel)
void setLayerDefaultProperties(LayerType type, Layer *layer)
Set the default properties of a layer, from the XML string contained in the LayerDefaults settings gr...