svgui  1.9
LayerFactory.cpp
Go to the documentation of this file.
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
00002 
00003 /*
00004     Sonic Visualiser
00005     An audio file viewer and annotation editor.
00006     Centre for Digital Music, Queen Mary, University of London.
00007     This file copyright 2006 Chris Cannam.
00008     
00009     This program is free software; you can redistribute it and/or
00010     modify it under the terms of the GNU General Public License as
00011     published by the Free Software Foundation; either version 2 of the
00012     License, or (at your option) any later version.  See the file
00013     COPYING included with this distribution for more information.
00014 */
00015 
00016 #include "LayerFactory.h"
00017 
00018 #include "WaveformLayer.h"
00019 #include "SpectrogramLayer.h"
00020 #include "TimeRulerLayer.h"
00021 #include "TimeInstantLayer.h"
00022 #include "TimeValueLayer.h"
00023 #include "NoteLayer.h"
00024 #include "FlexiNoteLayer.h"
00025 #include "RegionLayer.h"
00026 #include "TextLayer.h"
00027 #include "ImageLayer.h"
00028 #include "Colour3DPlotLayer.h"
00029 #include "SpectrumLayer.h"
00030 #include "SliceLayer.h"
00031 #include "SliceableLayer.h"
00032 
00033 #include "base/Clipboard.h"
00034 
00035 #include "data/model/RangeSummarisableTimeValueModel.h"
00036 #include "data/model/DenseTimeValueModel.h"
00037 #include "data/model/SparseOneDimensionalModel.h"
00038 #include "data/model/SparseTimeValueModel.h"
00039 #include "data/model/NoteModel.h"
00040 #include "data/model/FlexiNoteModel.h"
00041 #include "data/model/RegionModel.h"
00042 #include "data/model/TextModel.h"
00043 #include "data/model/ImageModel.h"
00044 #include "data/model/DenseThreeDimensionalModel.h"
00045 #include "data/model/WaveFileModel.h"
00046 #include "data/model/WritableWaveFileModel.h"
00047 
00048 #include <QDomDocument>
00049 #include <QDomElement>
00050 #include <QDomNamedNodeMap>
00051 #include <QDomAttr>
00052 
00053 #include <QSettings>
00054 
00055 LayerFactory *
00056 LayerFactory::m_instance = new LayerFactory;
00057 
00058 LayerFactory *
00059 LayerFactory::getInstance()
00060 {
00061     return m_instance;
00062 }
00063 
00064 LayerFactory::~LayerFactory()
00065 {
00066 }
00067 
00068 QString
00069 LayerFactory::getLayerPresentationName(LayerType type)
00070 {
00071     switch (type) {
00072     case Waveform:     return Layer::tr("Waveform");
00073     case Spectrogram:  return Layer::tr("Spectrogram");
00074     case TimeRuler:    return Layer::tr("Ruler");
00075     case TimeInstants: return Layer::tr("Time Instants");
00076     case TimeValues:   return Layer::tr("Time Values");
00077     case Notes:        return Layer::tr("Notes");
00078     case FlexiNotes:   return Layer::tr("Flexible Notes");
00079     case Regions:      return Layer::tr("Regions");
00080     case Text:         return Layer::tr("Text");
00081     case Image:        return Layer::tr("Images");
00082     case Colour3DPlot: return Layer::tr("Colour 3D Plot");
00083     case Spectrum:     return Layer::tr("Spectrum");
00084     case Slice:        return Layer::tr("Time Slice");
00085 
00086     case MelodicRangeSpectrogram:
00087         // The user can change all the parameters of this after the
00088         // fact -- there's nothing permanently melodic-range about it
00089         // that should be encoded in its name
00090         return Layer::tr("Spectrogram");
00091 
00092     case PeakFrequencySpectrogram:
00093         // likewise
00094         return Layer::tr("Spectrogram");
00095 
00096     case UnknownLayer:
00097     default:
00098         cerr << "WARNING: LayerFactory::getLayerPresentationName passed unknown layer" << endl;
00099         return Layer::tr("Unknown Layer");
00100     }
00101 }
00102 
00103 bool
00104 LayerFactory::isLayerSliceable(const Layer *layer)
00105 {
00106     if (dynamic_cast<const SliceableLayer *>(layer)) {
00107         if (dynamic_cast<const SpectrogramLayer *>(layer)) {
00108 
00110             // problem managing the models.  The source model for the
00111             // slice layer has to be one of the spectrogram's FFT
00112             // models -- that's fine, except that we can't store &
00113             // recall the slice layer with a reference to that model
00114             // because the model is internal to the spectrogram layer
00115             // and the document has no record of it.  We would need
00116             // some other way of managing models that are used in this
00117             // way.  For the moment we just don't allow slices of
00118             // spectrograms -- and provide a spectrum layer for this
00119             // instead.
00120             //
00121             // This business needs a bit more thought -- either come
00122             // up with a sensible way to deal with that stuff, or
00123             // simplify the existing slice layer logic so that it
00124             // doesn't have to deal with models disappearing on it at
00125             // all (and use the normal Document setModel mechanism to
00126             // set its sliceable model instead of the fancy pants
00127             // nonsense it's doing at the moment).
00128 
00129             return false;
00130         }
00131         return true;
00132     }
00133     return false;
00134 }
00135 
00136 LayerFactory::LayerTypeSet
00137 LayerFactory::getValidLayerTypes(Model *model)
00138 {
00139     LayerTypeSet types;
00140 
00141     if (dynamic_cast<DenseThreeDimensionalModel *>(model)) {
00142         types.insert(Colour3DPlot);
00143         types.insert(Slice);
00144     }
00145 
00146     if (dynamic_cast<RangeSummarisableTimeValueModel *>(model)) {
00147         types.insert(Waveform);
00148     }
00149 
00150     if (dynamic_cast<DenseTimeValueModel *>(model)) {
00151         types.insert(Spectrogram);
00152         types.insert(MelodicRangeSpectrogram);
00153         types.insert(PeakFrequencySpectrogram);
00154     }
00155 
00156     if (dynamic_cast<SparseOneDimensionalModel *>(model)) {
00157         types.insert(TimeInstants);
00158     }
00159 
00160     if (dynamic_cast<SparseTimeValueModel *>(model)) {
00161         types.insert(TimeValues);
00162     }
00163 
00164     if (dynamic_cast<NoteModel *>(model)) {
00165         types.insert(Notes);
00166     }
00167 
00168     // NOTE: GF: types is a set, so order of insertion does not matter
00169     if (dynamic_cast<FlexiNoteModel *>(model)) {
00170         types.insert(FlexiNotes);
00171     }
00172 
00173     if (dynamic_cast<RegionModel *>(model)) {
00174         types.insert(Regions);
00175     }
00176 
00177     if (dynamic_cast<TextModel *>(model)) {
00178         types.insert(Text);
00179     }
00180 
00181     if (dynamic_cast<ImageModel *>(model)) {
00182         types.insert(Image);
00183     }
00184 
00185     if (dynamic_cast<DenseTimeValueModel *>(model)) {
00186         types.insert(Spectrum);
00187     }
00188 
00189     // We don't count TimeRuler here as it doesn't actually display
00190     // the data, although it can be backed by any model
00191 
00192     return types;
00193 }
00194 
00195 LayerFactory::LayerTypeSet
00196 LayerFactory::getValidEmptyLayerTypes()
00197 {
00198     LayerTypeSet types;
00199     types.insert(TimeInstants);
00200     types.insert(TimeValues);
00201     types.insert(FlexiNotes);
00202     types.insert(Notes);
00203     types.insert(Regions);
00204     types.insert(Text);
00205     types.insert(Image);
00207     return types;
00208 }
00209 
00210 LayerFactory::LayerType
00211 LayerFactory::getLayerType(const Layer *layer)
00212 {
00213     if (dynamic_cast<const WaveformLayer *>(layer)) return Waveform;
00214     if (dynamic_cast<const SpectrogramLayer *>(layer)) return Spectrogram;
00215     if (dynamic_cast<const TimeRulerLayer *>(layer)) return TimeRuler;
00216     if (dynamic_cast<const TimeInstantLayer *>(layer)) return TimeInstants;
00217     if (dynamic_cast<const TimeValueLayer *>(layer)) return TimeValues;
00218     if (dynamic_cast<const FlexiNoteLayer *>(layer)) return FlexiNotes;
00219     if (dynamic_cast<const NoteLayer *>(layer)) return Notes;
00220     if (dynamic_cast<const RegionLayer *>(layer)) return Regions;
00221     if (dynamic_cast<const TextLayer *>(layer)) return Text;
00222     if (dynamic_cast<const ImageLayer *>(layer)) return Image;
00223     if (dynamic_cast<const Colour3DPlotLayer *>(layer)) return Colour3DPlot;
00224     if (dynamic_cast<const SpectrumLayer *>(layer)) return Spectrum;
00225     if (dynamic_cast<const SliceLayer *>(layer)) return Slice;
00226     return UnknownLayer;
00227 }
00228 
00229 QString
00230 LayerFactory::getLayerIconName(LayerType type)
00231 {
00232     switch (type) {
00233     case Waveform: return "waveform";
00234     case Spectrogram: return "spectrogram";
00235     case TimeRuler: return "timeruler";
00236     case TimeInstants: return "instants";
00237     case TimeValues: return "values";
00238     case Notes: return "notes";
00239     case FlexiNotes: return "flexinotes";
00240     case Regions: return "regions";
00241     case Text: return "text";
00242     case Image: return "image";
00243     case Colour3DPlot: return "colour3d";
00244     case Spectrum: return "spectrum";
00245     case Slice: return "spectrum";
00246     case MelodicRangeSpectrogram: return "spectrogram";
00247     case PeakFrequencySpectrogram: return "spectrogram";
00248     case UnknownLayer:
00249     default:
00250         cerr << "WARNING: LayerFactory::getLayerIconName passed unknown layer" << endl;
00251         return "unknown";
00252     }
00253 }
00254 
00255 QString
00256 LayerFactory::getLayerTypeName(LayerType type)
00257 {
00258     switch (type) {
00259     case Waveform: return "waveform";
00260     case Spectrogram: return "spectrogram";
00261     case TimeRuler: return "timeruler";
00262     case TimeInstants: return "timeinstants";
00263     case TimeValues: return "timevalues";
00264     case Notes: return "notes";
00265     case FlexiNotes: return "flexinotes";
00266     case Regions: return "regions";
00267     case Text: return "text";
00268     case Image: return "image";
00269     case Colour3DPlot: return "colour3dplot";
00270     case Spectrum: return "spectrum";
00271     case Slice: return "slice";
00272     case MelodicRangeSpectrogram: return "melodicrange";
00273     case PeakFrequencySpectrogram: return "peakfrequency";
00274     case UnknownLayer:
00275     default:
00276         cerr << "WARNING: LayerFactory::getLayerTypeName passed unknown layer" << endl;
00277         return "unknown";
00278     }
00279 }
00280 
00281 LayerFactory::LayerType
00282 LayerFactory::getLayerTypeForName(QString name)
00283 {
00284     if (name == "waveform") return Waveform;
00285     if (name == "spectrogram") return Spectrogram;
00286     if (name == "timeruler") return TimeRuler;
00287     if (name == "timeinstants") return TimeInstants;
00288     if (name == "timevalues") return TimeValues;
00289     if (name == "flexinotes") return FlexiNotes;
00290     if (name == "regions") return Regions;
00291     if (name == "text") return Text;
00292     if (name == "image") return Image;
00293     if (name == "colour3dplot") return Colour3DPlot;
00294     if (name == "spectrum") return Spectrum;
00295     if (name == "slice") return Slice;
00296     return UnknownLayer;
00297 }
00298 
00299 void
00300 LayerFactory::setModel(Layer *layer, Model *model)
00301 {
00302 //    if (trySetModel<WaveformLayer, RangeSummarisableTimeValueModel>(layer, model))
00303 //      return;
00304         
00305     if (trySetModel<WaveformLayer, WaveFileModel>(layer, model))
00306         return;
00307 
00308     if (trySetModel<WaveformLayer, WritableWaveFileModel>(layer, model))
00309         return;
00310 
00311     if (trySetModel<SpectrogramLayer, DenseTimeValueModel>(layer, model))
00312         return;
00313 
00314     if (trySetModel<TimeRulerLayer, Model>(layer, model))
00315         return;
00316 
00317     if (trySetModel<TimeInstantLayer, SparseOneDimensionalModel>(layer, model))
00318         return;
00319 
00320     if (trySetModel<TimeValueLayer, SparseTimeValueModel>(layer, model))
00321         return;
00322 
00323     if (trySetModel<NoteLayer, NoteModel>(layer, model)) 
00324         return; 
00325 
00326     // GF: added FlexiNoteLayer
00327     if (trySetModel<FlexiNoteLayer, FlexiNoteModel>(layer, model)) 
00328         return; 
00329         
00330     if (trySetModel<RegionLayer, RegionModel>(layer, model))
00331         return;
00332 
00333     if (trySetModel<TextLayer, TextModel>(layer, model))
00334         return;
00335 
00336     if (trySetModel<ImageLayer, ImageModel>(layer, model))
00337         return;
00338 
00339     if (trySetModel<Colour3DPlotLayer, DenseThreeDimensionalModel>(layer, model))
00340         return;
00341 
00342     if (trySetModel<SpectrogramLayer, DenseTimeValueModel>(layer, model))
00343         return;
00344 
00345     if (trySetModel<SpectrumLayer, DenseTimeValueModel>(layer, model)) 
00346         return;
00347 
00348 //    if (trySetModel<SliceLayer, DenseThreeDimensionalModel>(layer, model)) 
00349 //        return;
00350 }
00351 
00352 Model *
00353 LayerFactory::createEmptyModel(LayerType layerType, Model *baseModel)
00354 {
00355     if (layerType == TimeInstants) {
00356         return new SparseOneDimensionalModel(baseModel->getSampleRate(), 1);
00357     } else if (layerType == TimeValues) {
00358         return new SparseTimeValueModel(baseModel->getSampleRate(), 1, true);
00359     } else if (layerType == FlexiNotes) {
00360         return new FlexiNoteModel(baseModel->getSampleRate(), 1, true);
00361     } else if (layerType == Notes) {
00362         return new NoteModel(baseModel->getSampleRate(), 1, true);
00363     } else if (layerType == Regions) {
00364         return new RegionModel(baseModel->getSampleRate(), 1, true);
00365     } else if (layerType == Text) {
00366         return new TextModel(baseModel->getSampleRate(), 1, true);
00367     } else if (layerType == Image) {
00368         return new ImageModel(baseModel->getSampleRate(), 1, true);
00369     } else {
00370         return 0;
00371     }
00372 }
00373 
00374 int
00375 LayerFactory::getChannel(Layer *layer)
00376 {
00377     if (dynamic_cast<WaveformLayer *>(layer)) {
00378         return dynamic_cast<WaveformLayer *>(layer)->getChannel();
00379     } 
00380     if (dynamic_cast<SpectrogramLayer *>(layer)) {
00381         return dynamic_cast<SpectrogramLayer *>(layer)->getChannel();
00382     }
00383     return -1;
00384 }
00385 
00386 void
00387 LayerFactory::setChannel(Layer *layer, int channel)
00388 {
00389     if (dynamic_cast<WaveformLayer *>(layer)) {
00390         dynamic_cast<WaveformLayer *>(layer)->setChannel(channel);
00391         return;
00392     } 
00393     if (dynamic_cast<SpectrogramLayer *>(layer)) {
00394         dynamic_cast<SpectrogramLayer *>(layer)->setChannel(channel);
00395         return;
00396     }
00397     if (dynamic_cast<SpectrumLayer *>(layer)) {
00398         dynamic_cast<SpectrumLayer *>(layer)->setChannel(channel);
00399         return;
00400     }
00401 }
00402 
00403 Layer *
00404 LayerFactory::createLayer(LayerType type)
00405 {
00406     Layer *layer = 0;
00407 
00408     switch (type) {
00409 
00410     case Waveform:
00411         layer = new WaveformLayer;
00412         break;
00413 
00414     case Spectrogram:
00415         layer = new SpectrogramLayer;
00416         break;
00417 
00418     case TimeRuler:
00419         layer = new TimeRulerLayer;
00420         break;
00421 
00422     case TimeInstants:
00423         layer = new TimeInstantLayer;
00424         break;
00425 
00426     case TimeValues:
00427         layer = new TimeValueLayer;
00428         break;
00429 
00430     case FlexiNotes:
00431         layer = new FlexiNoteLayer;
00432         break;
00433 
00434     case Notes:
00435         layer = new NoteLayer;
00436         break;
00437 
00438     case Regions:
00439         layer = new RegionLayer;
00440         break;
00441 
00442     case Text:
00443         layer = new TextLayer;
00444         break;
00445 
00446     case Image:
00447         layer = new ImageLayer;
00448         break;
00449 
00450     case Colour3DPlot:
00451         layer = new Colour3DPlotLayer;
00452         break;
00453 
00454     case Spectrum:
00455         layer = new SpectrumLayer;
00456         break;
00457 
00458     case Slice:
00459         layer = new SliceLayer;
00460         break;
00461 
00462     case MelodicRangeSpectrogram: 
00463         layer = new SpectrogramLayer(SpectrogramLayer::MelodicRange);
00464         break;
00465 
00466     case PeakFrequencySpectrogram: 
00467         layer = new SpectrogramLayer(SpectrogramLayer::MelodicPeaks);
00468         break;
00469 
00470     case UnknownLayer:
00471     default:
00472         cerr << "WARNING: LayerFactory::createLayer passed unknown layer" << endl;
00473         break;
00474     }
00475 
00476     if (!layer) {
00477         cerr << "LayerFactory::createLayer: Unknown layer type " 
00478                   << type << endl;
00479     } else {
00480 //      SVDEBUG << "LayerFactory::createLayer: Setting object name "
00481 //                << getLayerPresentationName(type) << " on " << layer << endl;
00482         layer->setObjectName(getLayerPresentationName(type));
00483         setLayerDefaultProperties(type, layer);
00484     }
00485 
00486     return layer;
00487 }
00488 
00489 void
00490 LayerFactory::setLayerDefaultProperties(LayerType type, Layer *layer)
00491 {
00492 //    SVDEBUG << "LayerFactory::setLayerDefaultProperties: type " << type << " (name \"" << getLayerTypeName(type) << "\")" << endl;
00493 
00494     QSettings settings;
00495     settings.beginGroup("LayerDefaults");
00496     QString defaults = settings.value(getLayerTypeName(type), "").toString();
00497     if (defaults == "") return;
00498 
00499 //    cerr << "defaults=\"" << defaults << "\"" << endl;
00500 
00501     QString xml = layer->toXmlString();
00502     QDomDocument docOld, docNew;
00503     
00504     if (docOld.setContent(xml, false) &&
00505         docNew.setContent(defaults, false)) {
00506         
00507         QXmlAttributes attrs;
00508         
00509         QDomElement layerElt = docNew.firstChildElement("layer");
00510         QDomNamedNodeMap attrNodes = layerElt.attributes();
00511         
00512         for (int i = 0; i < attrNodes.length(); ++i) {
00513             QDomAttr attr = attrNodes.item(i).toAttr();
00514             if (attr.isNull()) continue;
00515 //            cerr << "append \"" << attr.name()
00516 //                      << "\" -> \"" << attr.value() << "\""
00517 //                      << endl;
00518             attrs.append(attr.name(), "", "", attr.value());
00519         }
00520         
00521         layerElt = docOld.firstChildElement("layer");
00522         attrNodes = layerElt.attributes();
00523         for (int i = 0; i < attrNodes.length(); ++i) {
00524             QDomAttr attr = attrNodes.item(i).toAttr();
00525             if (attr.isNull()) continue;
00526             if (attrs.value(attr.name()) == "") {
00527 //                cerr << "append \"" << attr.name()
00528 //                          << "\" -> \"" << attr.value() << "\""
00529 //                          << endl;
00530                 attrs.append(attr.name(), "", "", attr.value());
00531             }
00532         }
00533         
00534         layer->setProperties(attrs);
00535     }
00536 
00537     settings.endGroup();
00538 }
00539 
00540 LayerFactory::LayerType
00541 LayerFactory::getLayerTypeForClipboardContents(const Clipboard &clip)
00542 {
00543     const Clipboard::PointList &contents = clip.getPoints();
00544 
00545     bool haveFrame = false;
00546     bool haveValue = false;
00547     bool haveDuration = false;
00548     bool haveLevel = false;
00549 
00550     for (Clipboard::PointList::const_iterator i = contents.begin();
00551          i != contents.end(); ++i) {
00552         if (i->haveFrame()) haveFrame = true;
00553         if (i->haveValue()) haveValue = true;
00554         if (i->haveDuration()) haveDuration = true;
00555         if (i->haveLevel()) haveLevel = true;
00556     }
00557 
00558     if (haveFrame && haveValue && haveDuration && haveLevel) return Notes;
00559     if (haveFrame && haveValue && haveDuration) return Regions;
00560     if (haveFrame && haveValue) return TimeValues;
00561     return TimeInstants;
00562 }
00563