/[svn]/qsampler/trunk/src/qsamplerInstrumentList.cpp
ViewVC logotype

Contents of /qsampler/trunk/src/qsamplerInstrumentList.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1526 - (show annotations) (download)
Mon Nov 26 10:58:23 2007 UTC (12 years, 10 months ago) by capela
File size: 8798 byte(s)
* Fixed crash on (All) instrument map list; instrument program number
  list display fix (off by one); header section
  widths are now arranged as in the Qt3 version.

1 // qsamplerInstrumentList.cpp
2 //
3 /****************************************************************************
4 Copyright (C) 2003-2007, rncbc aka Rui Nuno Capela. All rights reserved.
5 Copyright (C) 2007, Christian Schoenebeck
6
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License
9 as published by the Free Software Foundation; either version 2
10 of the License, or (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20
21 *****************************************************************************/
22
23 #include "qsamplerAbout.h"
24 #include "qsamplerInstrumentList.h"
25
26 #include "qsamplerInstrument.h"
27 #include "qsamplerInstrumentForm.h"
28
29 #include "qsamplerOptions.h"
30 #include "qsamplerMainForm.h"
31
32 #include <QApplication>
33 #include <QMessageBox>
34 #include <QMenu>
35 #include <QAction>
36 #include <QCursor>
37 #include <QFileInfo>
38
39 // Needed for lroundf()
40 #include <math.h>
41
42 #ifndef CONFIG_ROUND
43 static inline long lroundf ( float x )
44 {
45 if (x >= 0.0f)
46 return long(x + 0.5f);
47 else
48 return long(x - 0.5f);
49 }
50 #endif
51
52 using namespace QSampler;
53
54
55 //-------------------------------------------------------------------------
56 // MidiInstrumentsModel - data model for MIDI prog mappings (used for QTableView)
57 //
58
59 MidiInstrumentsModel::MidiInstrumentsModel ( QObject* pParent)
60 : QAbstractTableModel(pParent)
61 {
62 m_iMidiMap = LSCP_MIDI_MAP_ALL;
63 }
64
65
66 int MidiInstrumentsModel::rowCount ( const QModelIndex& /*parent*/) const
67 {
68 if (m_iMidiMap == LSCP_MIDI_MAP_ALL) {
69 int n = 0;
70 for (InstrumentsMap::const_iterator itMap = m_instruments.begin();
71 itMap != m_instruments.end(); ++itMap)
72 n += (*itMap).size();
73 return n;
74 }
75 InstrumentsMap::const_iterator itMap = m_instruments.find(m_iMidiMap);
76 if (itMap == m_instruments.end()) return 0;
77 return (*itMap).size();
78 }
79
80
81 int MidiInstrumentsModel::columnCount ( const QModelIndex& /*parent*/) const
82 {
83 return 9;
84 }
85
86
87 QVariant MidiInstrumentsModel::data ( const QModelIndex &index, int role ) const
88 {
89 if (!index.isValid())
90 return QVariant();
91
92 const qsamplerInstrument* pInstr = NULL;
93
94 if (m_iMidiMap == LSCP_MIDI_MAP_ALL) {
95 int n = 0;
96 for (InstrumentsMap::const_iterator itMap = m_instruments.begin();
97 itMap != m_instruments.end(); ++itMap) {
98 n += (*itMap).size();
99 if (index.row() < n) {
100 pInstr = &(*itMap)[index.row() + (*itMap).size() - n];
101 break;
102 }
103 }
104 } else {
105 // resolve MIDI instrument map
106 InstrumentsMap::const_iterator itMap = m_instruments.find(m_iMidiMap);
107 if (itMap == m_instruments.end()) return QVariant();
108 // resolve instrument in that map
109 if (index.row() >= (*itMap).size()) return QVariant();
110 pInstr = &(*itMap)[index.row()];
111 }
112
113 if (!pInstr)
114 return QVariant();
115
116 if (role == Qt::UserRole)
117 return QVariant::fromValue((void *) pInstr);
118
119 if (role == Qt::DisplayRole) {
120 switch (index.column()) {
121 case 0: return pInstr->name();
122 case 1: return QVariant::fromValue(pInstr->map());
123 case 2: return QVariant::fromValue(pInstr->bank());
124 case 3: return QVariant::fromValue(pInstr->prog() + 1);
125 case 4: return pInstr->engineName();
126 case 5: return pInstr->instrumentFile();
127 case 6: return QVariant::fromValue(pInstr->instrumentNr());
128 case 7: return QString::number(pInstr->volume() * 100.0) + " %";
129 case 8: {
130 switch (pInstr->loadMode()) {
131 case 3: return QObject::tr("Persistent");
132 case 2: return QObject::tr("On Demand Hold");
133 case 1: return QObject::tr("On Demand");
134 }
135 }
136 default: return QVariant();
137 }
138 }
139
140 return QVariant();
141 }
142
143
144 QVariant MidiInstrumentsModel::headerData (
145 int section, Qt::Orientation orientation, int role ) const
146 {
147 if (orientation != Qt::Horizontal || role != Qt::DisplayRole)
148 return QVariant();
149
150 switch (section) {
151 case 0: return tr("Name");
152 case 1: return tr("Map");
153 case 2: return tr("Bank");
154 case 3: return tr("Prog");
155 case 4: return tr("Engine");
156 case 5: return tr("File");
157 case 6: return tr("Nr");
158 case 7: return tr("Vol");
159 case 8: return tr("Mode");
160 default: return QVariant();
161 }
162 }
163
164
165 qsamplerInstrument* MidiInstrumentsModel::addInstrument (
166 int iMap, int iBank, int iProg )
167 {
168 // Check it there's already one instrument item
169 // with the very same key (bank, program);
170 // if yes, just remove it without prejudice...
171 for (int i = 0; i < m_instruments[iMap].size(); i++) {
172 if (m_instruments[iMap][i].bank() == iBank &&
173 m_instruments[iMap][i].prog() == iProg) {
174 m_instruments[iMap].removeAt(i);
175 break;
176 }
177 }
178
179 // Resolve the appropriate place, we keep the list sorted that way ...
180 int i = 0;
181 for (; i < m_instruments[iMap].size(); ++i) {
182 if (iBank < m_instruments[iMap][i].bank()
183 || (iBank == m_instruments[iMap][i].bank() &&
184 iProg < m_instruments[iMap][i].prog())) {
185 break;
186 }
187 }
188
189 m_instruments[iMap].insert(i, qsamplerInstrument(iMap, iBank, iProg));
190 qsamplerInstrument& instr = m_instruments[iMap][i];
191 if (!instr.getInstrument())
192 m_instruments[iMap].removeAt(i);
193
194 return &instr;
195 }
196
197
198 void MidiInstrumentsModel::removeInstrument (
199 const qsamplerInstrument& instrument )
200 {
201 const int iMap = instrument.map();
202 const int iBank = instrument.bank();
203 const int iProg = instrument.prog();
204 for (int i = 0; i < m_instruments[iMap].size(); i++) {
205 if (m_instruments[iMap][i].bank() == iBank &&
206 m_instruments[iMap][i].prog() == iProg) {
207 m_instruments[iMap].removeAt(i);
208 break;
209 }
210 }
211 }
212
213
214 // Reposition the instrument in the model (called when map/bank/prg changed)
215 void MidiInstrumentsModel::resort ( const qsamplerInstrument& instrument )
216 {
217 const int iMap = instrument.map();
218 const int iBank = instrument.bank();
219 const int iProg = instrument.prog();
220 // Remove given instrument from its current list
221 removeInstrument(instrument);
222 // Re-add the instrument
223 addInstrument(iMap, iBank, iProg);
224 }
225
226
227 void MidiInstrumentsModel::setMidiMap ( int iMidiMap )
228 {
229 if (iMidiMap < 0)
230 iMidiMap = LSCP_MIDI_MAP_ALL;
231
232 m_iMidiMap = iMidiMap;
233 }
234
235
236 int MidiInstrumentsModel::midiMap (void) const
237 {
238 return m_iMidiMap;
239 }
240
241 void MidiInstrumentsModel::refresh (void)
242 {
243 m_instruments.clear();
244
245 MainForm* pMainForm = MainForm::getInstance();
246 if (pMainForm == NULL)
247 return;
248 if (pMainForm->client() == NULL)
249 return;
250
251 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
252
253 // Load the whole bunch of instrument items...
254 lscp_midi_instrument_t* pInstrs
255 = ::lscp_list_midi_instruments(pMainForm->client(), m_iMidiMap);
256 for (int iInstr = 0; pInstrs && pInstrs[iInstr].map >= 0; ++iInstr) {
257 const int iMap = pInstrs[iInstr].map;
258 const int iBank = pInstrs[iInstr].bank;
259 const int iProg = pInstrs[iInstr].prog;
260 addInstrument(iMap, iBank, iProg);
261 // Try to keep it snappy :)
262 QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
263 }
264
265 QApplication::restoreOverrideCursor();
266
267 if (pInstrs == NULL && ::lscp_client_get_errno(pMainForm->client())) {
268 pMainForm->appendMessagesClient("lscp_list_midi_instruments");
269 pMainForm->appendMessagesError(
270 tr("Could not get current list of MIDI instrument mappings.\n\nSorry."));
271 }
272
273 // inform the outer world (QTableView) that our data changed
274 QAbstractTableModel::reset();
275 }
276
277
278 //-------------------------------------------------------------------------
279 // MidiInstrumentsDelegate - table cell renderer for MIDI prog mappings
280 // (doesn't actually do anything ATM, but is already there for a future
281 // cell editor widget implementation)
282
283 MidiInstrumentsDelegate::MidiInstrumentsDelegate ( QObject* pParent )
284 : QItemDelegate(pParent)
285 {
286 }
287
288
289 QWidget* MidiInstrumentsDelegate::createEditor ( QWidget* pParent,
290 const QStyleOptionViewItem& option, const QModelIndex& index ) const
291 {
292 return QItemDelegate::createEditor(pParent, option, index);
293 // return new QLabel(index.model()->data(index, Qt::DisplayRole).toString(), parent);
294 }
295
296
297 void MidiInstrumentsDelegate::setEditorData ( QWidget */*pEditor*/,
298 const QModelIndex& /*index*/) const
299 {
300 }
301
302
303 void MidiInstrumentsDelegate::setModelData ( QWidget */*pEditor*/,
304 QAbstractItemModel* /*model*/, const QModelIndex& /*index*/) const
305 {
306 }
307
308
309 void MidiInstrumentsDelegate::updateEditorGeometry ( QWidget *pEditor,
310 const QStyleOptionViewItem& option, const QModelIndex& index) const
311 {
312 QItemDelegate::updateEditorGeometry(pEditor, option, index);
313 // if (pEditor) pEditor->setGeometry(option.rect);
314 }
315
316
317 // end of qsamplerInstrumentList.cpp

  ViewVC Help
Powered by ViewVC