svcore  1.9
SparseOneDimensionalModel.h
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 #ifndef _SPARSE_ONE_DIMENSIONAL_MODEL_H_
00017 #define _SPARSE_ONE_DIMENSIONAL_MODEL_H_
00018 
00019 #include "SparseModel.h"
00020 #include "NoteData.h"
00021 #include "base/PlayParameterRepository.h"
00022 #include "base/RealTime.h"
00023 
00024 #include <QStringList>
00025 
00026 struct OneDimensionalPoint
00027 {
00028 public:
00029     OneDimensionalPoint(int _frame) : frame(_frame) { }
00030     OneDimensionalPoint(int _frame, QString _label) : frame(_frame), label(_label) { }
00031 
00032     int getDimensions() const { return 1; }
00033     
00034     int frame;
00035     QString label;
00036 
00037     QString getLabel() const { return label; }
00038 
00039     void toXml(QTextStream &stream,
00040                QString indent = "",
00041                QString extraAttributes = "") const
00042     {
00043         stream << QString("%1<point frame=\"%2\" label=\"%3\" %4/>\n")
00044             .arg(indent).arg(frame).arg(XmlExportable::encodeEntities(label))
00045             .arg(extraAttributes);
00046     }
00047 
00048     QString toDelimitedDataString(QString delimiter, int sampleRate) const
00049     {
00050         QStringList list;
00051         list << RealTime::frame2RealTime(frame, sampleRate).toString().c_str();
00052         if (label != "") list << label;
00053         return list.join(delimiter);
00054     }
00055 
00056     struct Comparator {
00057         bool operator()(const OneDimensionalPoint &p1,
00058                         const OneDimensionalPoint &p2) const {
00059             if (p1.frame != p2.frame) return p1.frame < p2.frame;
00060             return p1.label < p2.label;
00061         }
00062     };
00063     
00064     struct OrderComparator {
00065         bool operator()(const OneDimensionalPoint &p1,
00066                         const OneDimensionalPoint &p2) const {
00067             return p1.frame < p2.frame;
00068         }
00069     };
00070 };
00071 
00072 
00073 class SparseOneDimensionalModel : public SparseModel<OneDimensionalPoint>,
00074                                   public NoteExportable
00075 {
00076     Q_OBJECT
00077     
00078 public:
00079     SparseOneDimensionalModel(int sampleRate, int resolution,
00080                               bool notifyOnAdd = true) :
00081         SparseModel<OneDimensionalPoint>(sampleRate, resolution, notifyOnAdd)
00082     {
00083         PlayParameterRepository::getInstance()->addPlayable(this);
00084     }
00085 
00086     virtual ~SparseOneDimensionalModel()
00087     {
00088         PlayParameterRepository::getInstance()->removePlayable(this);
00089     }
00090 
00091     virtual bool canPlay() const { return true; }
00092 
00093     virtual QString getDefaultPlayClipId() const
00094     {
00095         return "tap";
00096     }
00097 
00098     int getIndexOf(const Point &point)
00099     {
00100         // slow
00101         int i = 0;
00102         Point::Comparator comparator;
00103         for (PointList::const_iterator j = m_points.begin();
00104              j != m_points.end(); ++j, ++i) {
00105             if (!comparator(*j, point) && !comparator(point, *j)) return i;
00106         }
00107         return -1;
00108     }
00109 
00110     QString getTypeName() const { return tr("Sparse 1-D"); }
00111 
00116     virtual int getColumnCount() const
00117     {
00118         return 3;
00119     }
00120 
00121     virtual QString getHeading(int column) const
00122     {
00123         switch (column) {
00124         case 0: return tr("Time");
00125         case 1: return tr("Frame");
00126         case 2: return tr("Label");
00127         default: return tr("Unknown");
00128         }
00129     }
00130 
00131     virtual QVariant getData(int row, int column, int role) const
00132     {
00133         if (column < 2) {
00134             return SparseModel<OneDimensionalPoint>::getData
00135                 (row, column, role);
00136         }
00137 
00138         PointListConstIterator i = getPointListIteratorForRow(row);
00139         if (i == m_points.end()) return QVariant();
00140 
00141         switch (column) {
00142         case 2: return i->label;
00143         default: return QVariant();
00144         }
00145     }
00146 
00147     virtual Command *getSetDataCommand(int row, int column, const QVariant &value, int role)
00148     {
00149         if (column < 2) {
00150             return SparseModel<OneDimensionalPoint>::getSetDataCommand
00151                 (row, column, value, role);
00152         }
00153 
00154         if (role != Qt::EditRole) return 0;
00155         PointListConstIterator i = getPointListIteratorForRow(row);
00156         if (i == m_points.end()) return 0;
00157         EditCommand *command = new EditCommand(this, tr("Edit Data"));
00158 
00159         Point point(*i);
00160         command->deletePoint(point);
00161 
00162         switch (column) {
00163         case 2: point.label = value.toString(); break;
00164         }
00165 
00166         command->addPoint(point);
00167         return command->finish();
00168     }
00169 
00170 
00171     virtual bool isColumnTimeValue(int column) const
00172     {
00173         return (column < 2); 
00174     }
00175 
00176     virtual SortType getSortType(int column) const
00177     {
00178         if (column == 2) return SortAlphabetical;
00179         return SortNumeric;
00180     }
00181 
00186     NoteList getNotes() const {
00187         return getNotesWithin(getStartFrame(), getEndFrame());
00188     }
00189 
00190     NoteList getNotesWithin(int startFrame, int endFrame) const {
00191         
00192         PointList points = getPoints(startFrame, endFrame);
00193         NoteList notes;
00194 
00195         for (PointList::iterator pli =
00196                  points.begin(); pli != points.end(); ++pli) {
00197 
00198             notes.push_back
00199                 (NoteData(pli->frame,
00200                           getSampleRate() / 6, // arbitrary short duration
00201                           64,   // default pitch
00202                           100)); // default velocity
00203         }
00204 
00205         return notes;
00206     }
00207 };
00208 
00209 #endif
00210 
00211 
00212