Chris@58: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@0: Chris@0: /* Chris@59: Sonic Visualiser Chris@59: An audio file viewer and annotation editor. Chris@59: Centre for Digital Music, Queen Mary, University of London. Chris@59: This file copyright 2006 Chris Cannam. Chris@0: Chris@59: This program is free software; you can redistribute it and/or Chris@59: modify it under the terms of the GNU General Public License as Chris@59: published by the Free Software Foundation; either version 2 of the Chris@59: License, or (at your option) any later version. See the file Chris@59: COPYING included with this distribution for more information. Chris@0: */ Chris@0: Chris@0: #include "LayerFactory.h" Chris@0: Chris@0: #include "WaveformLayer.h" Chris@0: #include "SpectrogramLayer.h" Chris@0: #include "TimeRulerLayer.h" Chris@0: #include "TimeInstantLayer.h" Chris@0: #include "TimeValueLayer.h" Chris@30: #include "NoteLayer.h" Chris@35: #include "TextLayer.h" Chris@303: #include "ImageLayer.h" Chris@0: #include "Colour3DPlotLayer.h" Chris@133: #include "SpectrumLayer.h" Chris@193: #include "SliceLayer.h" Chris@193: #include "SliceableLayer.h" Chris@0: Chris@128: #include "data/model/RangeSummarisableTimeValueModel.h" Chris@128: #include "data/model/DenseTimeValueModel.h" Chris@128: #include "data/model/SparseOneDimensionalModel.h" Chris@128: #include "data/model/SparseTimeValueModel.h" Chris@128: #include "data/model/NoteModel.h" Chris@128: #include "data/model/TextModel.h" Chris@303: #include "data/model/ImageModel.h" Chris@128: #include "data/model/DenseThreeDimensionalModel.h" Chris@156: #include "data/model/WaveFileModel.h" Chris@156: #include "data/model/WritableWaveFileModel.h" Chris@0: Chris@0: LayerFactory * Chris@0: LayerFactory::m_instance = new LayerFactory; Chris@0: Chris@0: LayerFactory * Chris@125: LayerFactory::getInstance() Chris@0: { Chris@0: return m_instance; Chris@0: } Chris@0: Chris@0: LayerFactory::~LayerFactory() Chris@0: { Chris@0: } Chris@0: Chris@0: QString Chris@0: LayerFactory::getLayerPresentationName(LayerType type) Chris@0: { Chris@0: switch (type) { Chris@0: case Waveform: return Layer::tr("Waveform"); Chris@0: case Spectrogram: return Layer::tr("Spectrogram"); Chris@0: case TimeRuler: return Layer::tr("Ruler"); Chris@0: case TimeInstants: return Layer::tr("Time Instants"); Chris@0: case TimeValues: return Layer::tr("Time Values"); Chris@30: case Notes: return Layer::tr("Notes"); Chris@35: case Text: return Layer::tr("Text"); Chris@303: case Image: return Layer::tr("Images"); Chris@0: case Colour3DPlot: return Layer::tr("Colour 3D Plot"); Chris@133: case Spectrum: return Layer::tr("Spectrum"); Chris@193: case Slice: return Layer::tr("Time Slice"); Chris@0: Chris@0: case MelodicRangeSpectrogram: Chris@0: // The user can change all the parameters of this after the Chris@0: // fact -- there's nothing permanently melodic-range about it Chris@0: // that should be encoded in its name Chris@0: return Layer::tr("Spectrogram"); Chris@11: Chris@37: case PeakFrequencySpectrogram: Chris@37: // likewise Chris@37: return Layer::tr("Spectrogram"); Chris@37: Chris@11: default: break; Chris@0: } Chris@0: Chris@0: return Layer::tr("Layer"); Chris@0: } Chris@0: Chris@193: bool Chris@193: LayerFactory::isLayerSliceable(const Layer *layer) Chris@193: { Chris@193: if (dynamic_cast(layer)) { Chris@193: if (dynamic_cast(layer)) { Chris@193: Chris@193: //!!! We can create slices of spectrograms, but there's a Chris@193: // problem managing the models. The source model for the Chris@193: // slice layer has to be one of the spectrogram's FFT Chris@193: // models -- that's fine, except that we can't store & Chris@193: // recall the slice layer with a reference to that model Chris@193: // because the model is internal to the spectrogram layer Chris@193: // and the document has no record of it. We would need Chris@193: // some other way of managing models that are used in this Chris@193: // way. For the moment we just don't allow slices of Chris@193: // spectrograms -- and provide a spectrum layer for this Chris@193: // instead. Chris@193: // Chris@193: // This business needs a bit more thought -- either come Chris@193: // up with a sensible way to deal with that stuff, or Chris@193: // simplify the existing slice layer logic so that it Chris@193: // doesn't have to deal with models disappearing on it at Chris@193: // all (and use the normal Document setModel mechanism to Chris@193: // set its sliceable model instead of the fancy pants Chris@193: // nonsense it's doing at the moment). Chris@193: Chris@193: return false; Chris@193: } Chris@193: return true; Chris@193: } Chris@193: return false; Chris@193: } Chris@193: Chris@0: LayerFactory::LayerTypeSet Chris@0: LayerFactory::getValidLayerTypes(Model *model) Chris@0: { Chris@0: LayerTypeSet types; Chris@0: Chris@0: if (dynamic_cast(model)) { Chris@0: types.insert(Colour3DPlot); Chris@193: types.insert(Slice); Chris@193: } Chris@193: Chris@193: if (dynamic_cast(model)) { Chris@193: types.insert(Waveform); Chris@0: } Chris@0: Chris@0: if (dynamic_cast(model)) { Chris@0: types.insert(Spectrogram); Chris@0: types.insert(MelodicRangeSpectrogram); Chris@37: types.insert(PeakFrequencySpectrogram); Chris@0: } Chris@0: Chris@0: if (dynamic_cast(model)) { Chris@0: types.insert(TimeInstants); Chris@0: } Chris@0: Chris@0: if (dynamic_cast(model)) { Chris@0: types.insert(TimeValues); Chris@35: Chris@35: } Chris@35: if (dynamic_cast(model)) { Chris@35: types.insert(Notes); Chris@0: } Chris@0: Chris@35: if (dynamic_cast(model)) { Chris@35: types.insert(Text); Chris@30: } Chris@30: Chris@303: if (dynamic_cast(model)) { Chris@303: types.insert(Image); Chris@303: } Chris@303: Chris@133: if (dynamic_cast(model)) { Chris@133: types.insert(Spectrum); Chris@133: } Chris@133: Chris@0: // We don't count TimeRuler here as it doesn't actually display Chris@0: // the data, although it can be backed by any model Chris@0: Chris@0: return types; Chris@0: } Chris@0: Chris@17: LayerFactory::LayerTypeSet Chris@17: LayerFactory::getValidEmptyLayerTypes() Chris@17: { Chris@17: LayerTypeSet types; Chris@17: types.insert(TimeInstants); Chris@17: types.insert(TimeValues); Chris@30: types.insert(Notes); Chris@35: types.insert(Text); Chris@303: types.insert(Image); Chris@17: //!!! and in principle Colour3DPlot -- now that's a challenge Chris@17: return types; Chris@17: } Chris@17: Chris@0: LayerFactory::LayerType Chris@6: LayerFactory::getLayerType(const Layer *layer) Chris@0: { Chris@6: if (dynamic_cast(layer)) return Waveform; Chris@6: if (dynamic_cast(layer)) return Spectrogram; Chris@6: if (dynamic_cast(layer)) return TimeRuler; Chris@6: if (dynamic_cast(layer)) return TimeInstants; Chris@6: if (dynamic_cast(layer)) return TimeValues; Chris@30: if (dynamic_cast(layer)) return Notes; Chris@35: if (dynamic_cast(layer)) return Text; Chris@303: if (dynamic_cast(layer)) return Image; Chris@6: if (dynamic_cast(layer)) return Colour3DPlot; Chris@133: if (dynamic_cast(layer)) return Spectrum; Chris@193: if (dynamic_cast(layer)) return Slice; Chris@6: return UnknownLayer; Chris@6: } Chris@6: Chris@6: QString Chris@17: LayerFactory::getLayerIconName(LayerType type) Chris@17: { Chris@17: switch (type) { Chris@17: case Waveform: return "waveform"; Chris@17: case Spectrogram: return "spectrogram"; Chris@17: case TimeRuler: return "timeruler"; Chris@17: case TimeInstants: return "instants"; Chris@17: case TimeValues: return "values"; Chris@30: case Notes: return "notes"; Chris@35: case Text: return "text"; Chris@303: case Image: return "image"; Chris@17: case Colour3DPlot: return "colour3d"; Chris@133: case Spectrum: return "spectrum"; Chris@193: case Slice: return "spectrum"; Chris@17: default: return "unknown"; Chris@17: } Chris@17: } Chris@17: Chris@17: QString Chris@6: LayerFactory::getLayerTypeName(LayerType type) Chris@6: { Chris@6: switch (type) { Chris@6: case Waveform: return "waveform"; Chris@6: case Spectrogram: return "spectrogram"; Chris@6: case TimeRuler: return "timeruler"; Chris@6: case TimeInstants: return "timeinstants"; Chris@6: case TimeValues: return "timevalues"; Chris@30: case Notes: return "notes"; Chris@35: case Text: return "text"; Chris@303: case Image: return "image"; Chris@6: case Colour3DPlot: return "colour3dplot"; Chris@133: case Spectrum: return "spectrum"; Chris@193: case Slice: return "slice"; Chris@6: default: return "unknown"; Chris@6: } Chris@6: } Chris@6: Chris@6: LayerFactory::LayerType Chris@6: LayerFactory::getLayerTypeForName(QString name) Chris@6: { Chris@6: if (name == "waveform") return Waveform; Chris@6: if (name == "spectrogram") return Spectrogram; Chris@6: if (name == "timeruler") return TimeRuler; Chris@6: if (name == "timeinstants") return TimeInstants; Chris@6: if (name == "timevalues") return TimeValues; Chris@30: if (name == "notes") return Notes; Chris@35: if (name == "text") return Text; Chris@303: if (name == "image") return Image; Chris@6: if (name == "colour3dplot") return Colour3DPlot; Chris@133: if (name == "spectrum") return Spectrum; Chris@193: if (name == "slice") return Slice; Chris@0: return UnknownLayer; Chris@0: } Chris@0: Chris@0: void Chris@0: LayerFactory::setModel(Layer *layer, Model *model) Chris@0: { Chris@156: // if (trySetModel(layer, model)) Chris@156: // return; Chris@156: Chris@156: if (trySetModel(layer, model)) Chris@156: return; Chris@156: Chris@156: if (trySetModel(layer, model)) Chris@0: return; Chris@0: Chris@0: if (trySetModel(layer, model)) Chris@0: return; Chris@0: Chris@0: if (trySetModel(layer, model)) Chris@0: return; Chris@0: Chris@0: if (trySetModel(layer, model)) Chris@0: return; Chris@0: Chris@0: if (trySetModel(layer, model)) Chris@0: return; Chris@0: Chris@30: if (trySetModel(layer, model)) Chris@30: return; Chris@30: Chris@35: if (trySetModel(layer, model)) Chris@35: return; Chris@35: Chris@303: if (trySetModel(layer, model)) Chris@303: return; Chris@303: Chris@0: if (trySetModel(layer, model)) Chris@0: return; Chris@0: Chris@0: if (trySetModel(layer, model)) Chris@0: return; Chris@133: Chris@133: if (trySetModel(layer, model)) Chris@133: return; Chris@193: Chris@193: // if (trySetModel(layer, model)) Chris@193: // return; Chris@0: } Chris@0: Chris@17: Model * Chris@17: LayerFactory::createEmptyModel(LayerType layerType, Model *baseModel) Chris@17: { Chris@17: if (layerType == TimeInstants) { Chris@17: return new SparseOneDimensionalModel(baseModel->getSampleRate(), 1); Chris@17: } else if (layerType == TimeValues) { Chris@245: return new SparseTimeValueModel(baseModel->getSampleRate(), 1, true); Chris@30: } else if (layerType == Notes) { Chris@245: return new NoteModel(baseModel->getSampleRate(), 1, true); Chris@35: } else if (layerType == Text) { Chris@35: return new TextModel(baseModel->getSampleRate(), 1, true); Chris@303: } else if (layerType == Image) { Chris@303: return new ImageModel(baseModel->getSampleRate(), 1, true); Chris@17: } else { Chris@17: return 0; Chris@17: } Chris@17: } Chris@17: Chris@53: int Chris@53: LayerFactory::getChannel(Layer *layer) Chris@53: { Chris@53: if (dynamic_cast(layer)) { Chris@53: return dynamic_cast(layer)->getChannel(); Chris@53: } Chris@53: if (dynamic_cast(layer)) { Chris@53: return dynamic_cast(layer)->getChannel(); Chris@53: } Chris@53: return -1; Chris@53: } Chris@53: Chris@53: void Chris@53: LayerFactory::setChannel(Layer *layer, int channel) Chris@53: { Chris@53: if (dynamic_cast(layer)) { Chris@53: dynamic_cast(layer)->setChannel(channel); Chris@53: return; Chris@53: } Chris@53: if (dynamic_cast(layer)) { Chris@53: dynamic_cast(layer)->setChannel(channel); Chris@53: return; Chris@53: } Chris@53: } Chris@53: Chris@0: Layer * Chris@53: LayerFactory::createLayer(LayerType type) Chris@0: { Chris@0: Layer *layer = 0; Chris@0: Chris@0: switch (type) { Chris@0: Chris@0: case Waveform: Chris@44: layer = new WaveformLayer; Chris@0: break; Chris@0: Chris@0: case Spectrogram: Chris@44: layer = new SpectrogramLayer; Chris@0: break; Chris@0: Chris@0: case TimeRuler: Chris@44: layer = new TimeRulerLayer; Chris@0: break; Chris@0: Chris@0: case TimeInstants: Chris@44: layer = new TimeInstantLayer; Chris@0: break; Chris@0: Chris@0: case TimeValues: Chris@44: layer = new TimeValueLayer; Chris@0: break; Chris@0: Chris@30: case Notes: Chris@44: layer = new NoteLayer; Chris@30: break; Chris@30: Chris@35: case Text: Chris@44: layer = new TextLayer; Chris@35: break; Chris@35: Chris@303: case Image: Chris@303: layer = new ImageLayer; Chris@303: break; Chris@303: Chris@0: case Colour3DPlot: Chris@44: layer = new Colour3DPlotLayer; Chris@0: break; Chris@0: Chris@133: case Spectrum: Chris@133: layer = new SpectrumLayer; Chris@133: break; Chris@133: Chris@193: case Slice: Chris@193: layer = new SliceLayer; Chris@193: break; Chris@193: Chris@0: case MelodicRangeSpectrogram: Chris@44: layer = new SpectrogramLayer(SpectrogramLayer::MelodicRange); Chris@0: break; Chris@11: Chris@37: case PeakFrequencySpectrogram: Chris@44: layer = new SpectrogramLayer(SpectrogramLayer::MelodicPeaks); Chris@37: break; Chris@37: Chris@11: default: break; Chris@0: } Chris@0: Chris@0: if (!layer) { Chris@0: std::cerr << "LayerFactory::createLayer: Unknown layer type " Chris@0: << type << std::endl; Chris@0: } else { Chris@101: // std::cerr << "LayerFactory::createLayer: Setting object name " Chris@101: // << getLayerPresentationName(type).toStdString() << " on " << layer << std::endl; Chris@0: layer->setObjectName(getLayerPresentationName(type)); Chris@0: } Chris@0: Chris@0: return layer; Chris@0: } Chris@0: