svcore
1.9
|
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