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