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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1707 - (show annotations) (download)
Tue Feb 19 22:26:33 2008 UTC (16 years, 1 month ago) by schoenebeck
File size: 11579 byte(s)
* fixed minor macro typo bug (causing compiler error on Qt < 4.3)

1 // qsamplerChannelFxForm.cpp
2 //
3 /****************************************************************************
4 Copyright (C) 2008, Christian Schoenebeck
5
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; either version 2
9 of the License, or (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
20 *****************************************************************************/
21
22 #include "qsamplerAbout.h"
23 #include "qsamplerChannelFxForm.h"
24 #include "qsamplerFxSendsModel.h"
25
26 // let's not reinvent the wheel for audio routing
27 #include "qsamplerChannel.h"
28
29 #include <math.h>
30
31 #include <QAbstractButton>
32 #include <QLineEdit>
33 #include <QHeaderView>
34 #include <QMap>
35
36 namespace { // private namespace
37
38 static const char* _midiControllerName(int iMidiCtrl) {
39 switch (iMidiCtrl) {
40 case 0: return "Bank select MSB";
41 case 1: return "Modulation MSB";
42 case 2: return "Breath Controller";
43 case 4: return "Foot Controller MSB";
44 case 5: return "Portamento Time MSB";
45 case 6: return "(N)RPN Data Byte";
46 case 7: return "Main Volume";
47 case 8: return "Balance";
48 case 10: return "Panorama";
49 case 11: return "Expression";
50 case 12: return "Effect Control 1";
51 case 13: return "Effect Control 2";
52 case 16: return "General Purpose Controller 1";
53 case 17: return "General Purpose Controller 2";
54 case 18: return "General Purpose Controller 3";
55 case 19: return "General Purpose Controller 4";
56 case 32: return "Bank select LSB";
57 case 63: return "LSB for Controllers 0?31";
58 case 64: return "Hold 1";
59 case 65: return "Portamento";
60 case 66: return "Sostenuto";
61 case 67: return "Soft Pedal";
62 case 68: return "Legato Footswitch";
63 case 69: return "Hold 2";
64 case 70: return "Sound Controller 1 (Sound Variation)";
65 case 71: return "Sound Controller 2 (Harmonic Content)";
66 case 72: return "Sound Controller 3 (Release Time)";
67 case 73: return "Sound Controller 4 (Attack Time)";
68 case 74: return "Sound Controller 5 (Brightness)";
69 case 75: return "Sound Controller 6";
70 case 76: return "Sound Controller 7";
71 case 77: return "Sound Controller 8";
72 case 78: return "Sound Controller 9";
73 case 79: return "Sound Controller 10";
74 case 80: return "General Purpose 5";
75 case 81: return "General Purpose 6";
76 case 82: return "General Purpose 7";
77 case 83: return "General Purpose 8";
78 case 84: return "Portamento Control";
79 case 91: return "Effects 1 Depth";
80 case 92: return "Effects 2 Depth";
81 case 93: return "Effects 3 Depth";
82 case 94: return "Effects 4 Depth";
83 case 95: return "Effects 5 Depth";
84 case 96: return "Data Increment (N)RPN";
85 case 97: return "Data Decrement (N)RPN";
86 case 98: return "NRPN LSB";
87 case 99: return "NRPN MSB";
88 case 100: return "RPN LSB";
89 case 101: return "RPN MSB";
90 case 120: return "All Sounds Off";
91 case 121: return "Controller Reset";
92 case 122: return "Local Control on/off";
93 case 123: return "All Notes Off";
94 case 124: return "Omni Off";
95 case 125: return "Omni On";
96 case 126: return "Mono On / Poly Off";
97 case 127: return "Poly On / Mono Off";
98 default: return "";
99 }
100 }
101
102 } // private namespace
103
104
105 namespace QSampler {
106
107 ChannelFxForm::ChannelFxForm (
108 Channel* pSamplerChannel, QWidget* pParent, Qt::WindowFlags wflags )
109 : QDialog(pParent, wflags)
110 {
111 m_ui.setupUi(this);
112
113 m_pSamplerChannel = pSamplerChannel;
114
115 m_pAudioDevice = NULL;
116
117 FxSendsModel* pModel =
118 new FxSendsModel(m_pSamplerChannel->channelID(), m_ui.SendsListView);
119 m_ui.SendsListView->setModel(pModel);
120 #if QT_VERSION >= 0x040300
121 m_ui.SendsListView->setSelectionRectVisible(true);
122 #endif
123
124 const int iRowHeight = m_ui.audioRoutingTable->fontMetrics().height() + 4;
125 m_ui.audioRoutingTable->verticalHeader()->setDefaultSectionSize(iRowHeight);
126 m_ui.audioRoutingTable->horizontalHeader()->setDefaultAlignment(Qt::AlignLeft);
127 ChannelRoutingModel* pRoutingModel =
128 new ChannelRoutingModel(m_ui.audioRoutingTable);
129 m_ui.audioRoutingTable->setModel(pRoutingModel);
130 ChannelRoutingDelegate* pRoutingDelegate =
131 new ChannelRoutingDelegate(m_ui.audioRoutingTable);
132 m_ui.audioRoutingTable->setItemDelegate(pRoutingDelegate);
133 m_ui.audioRoutingTable->horizontalHeader()->setResizeMode(0, QHeaderView::Stretch);
134 // m_ui.audioRoutingTable->verticalHeader()->hide();
135
136 QAbstractButton* pApplyButton =
137 m_ui.buttonBox->button(QDialogButtonBox::Apply);
138 pApplyButton->setEnabled(false);
139 pApplyButton->setIcon(QIcon(":/icons/formEdit.png"));
140
141 QAbstractButton* pCancelButton =
142 m_ui.buttonBox->button(QDialogButtonBox::Cancel);
143 pCancelButton->setIcon(QIcon(":/icons/formRemove.png"));
144
145 QAbstractButton* pOkButton =
146 m_ui.buttonBox->button(QDialogButtonBox::Ok);
147 pOkButton->setIcon(QIcon(":/icons/formAccept.png"));
148
149 QAbstractButton* pResetButton =
150 m_ui.buttonBox->button(QDialogButtonBox::Reset);
151 pResetButton->setEnabled(false);
152 pResetButton->setToolTip("Revert all changes.");
153
154 m_ui.destroyPushButton->setEnabled(false);
155
156 m_ui.mainParametersGroupBox->setEnabled(false);
157 m_ui.audioRoutingGroupBox->setEnabled(false);
158
159 for (int i = 0; i < 128; ++i) {
160 m_ui.depthCtrlComboBox->addItem(
161 QString("[") + QString::number(i) + "] " + _midiControllerName(i)
162 );
163 }
164
165 connect(
166 m_ui.buttonBox, SIGNAL(clicked(QAbstractButton*)),
167 this, SLOT(onButtonClicked(QAbstractButton*))
168 );
169 connect(
170 m_ui.createPushButton, SIGNAL(clicked()),
171 this, SLOT(onCreateFxSend())
172 );
173 connect(
174 m_ui.destroyPushButton, SIGNAL(clicked()),
175 this, SLOT(onDestroyFxSend())
176 );
177 connect(
178 pModel, SIGNAL(fxSendsDirtyChanged(bool)),
179 pApplyButton, SLOT(setEnabled(bool))
180 );
181 connect(
182 pModel, SIGNAL(fxSendsDirtyChanged(bool)),
183 pResetButton, SLOT(setEnabled(bool))
184 );
185 connect(
186 m_ui.SendsListView, SIGNAL(clicked(const QModelIndex&)),
187 this, SLOT(onFxSendSelection(const QModelIndex&))
188 );
189 connect(
190 m_ui.depthCtrlComboBox, SIGNAL(activated(int)),
191 this, SLOT(onDepthCtrlChanged(int))
192 );
193 connect(
194 m_ui.depthSpinBox, SIGNAL(valueChanged(int)),
195 this, SLOT(onCurrentSendDepthChanged(int))
196 );
197 connect(
198 pRoutingModel, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&)),
199 this, SLOT(updateTableCellRenderers(const QModelIndex&, const QModelIndex&))
200 );
201 connect(
202 pRoutingModel, SIGNAL(modelReset()),
203 this, SLOT(updateTableCellRenderers())
204 );
205 connect(
206 pRoutingModel, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&)),
207 this, SLOT(onRoutingTableChanged())
208 );
209 }
210
211 ChannelFxForm::~ChannelFxForm() {
212 if (m_pAudioDevice) delete m_pAudioDevice;
213 }
214
215 void ChannelFxForm::onButtonClicked(QAbstractButton* button) {
216 FxSendsModel* pModel = (FxSendsModel*) m_ui.SendsListView->model();
217 switch (m_ui.buttonBox->buttonRole(button)) {
218 case QDialogButtonBox::AcceptRole:
219 case QDialogButtonBox::ApplyRole:
220 pModel->applyToSampler();
221 // force a refresh of the parameter control elements
222 onFxSendSelection(m_ui.SendsListView->currentIndex());
223 break;
224 case QDialogButtonBox::ResetRole:
225 pModel->cleanRefresh();
226 // force a refresh of the parameter control elements
227 onFxSendSelection(m_ui.SendsListView->currentIndex());
228 break;
229 default: // to avoid gcc warnings
230 break;
231 }
232 }
233
234 void ChannelFxForm::onFxSendSelection(const QModelIndex& index) {
235 const bool bValid = index.isValid();
236 m_ui.destroyPushButton->setEnabled(bValid);
237 m_ui.mainParametersGroupBox->setEnabled(bValid);
238 m_ui.audioRoutingGroupBox->setEnabled(bValid);
239
240 FxSendsModel* pModel = (FxSendsModel*) m_ui.SendsListView->model();
241 FxSend* pFxSend = pModel->fxSend(index);
242
243 // clear routing model
244 ChannelRoutingModel* pRoutingModel =
245 (ChannelRoutingModel*) m_ui.audioRoutingTable->model();
246 pRoutingModel->refresh(NULL, ChannelRoutingMap());
247 pRoutingModel->routingMap().clear(); // Reset routing change map.
248 if (m_pAudioDevice) {
249 delete m_pAudioDevice;
250 m_pAudioDevice = NULL;
251 }
252
253 if (!pFxSend) return;
254
255 // update routing model
256 if (m_pSamplerChannel->audioDevice() >= 0) {
257 m_pAudioDevice =
258 new Device(Device::Audio, m_pSamplerChannel->audioDevice());
259 pRoutingModel->refresh(m_pAudioDevice, pFxSend->audioRouting());
260 }
261
262 m_ui.depthCtrlComboBox->setCurrentIndex(pFxSend->sendDepthMidiCtrl());
263 m_ui.depthSpinBox->setValue(
264 int(::round(pFxSend->currentDepth() * 100.0))
265 );
266 }
267
268 void ChannelFxForm::onCreateFxSend() {
269 FxSendsModel* pModel = (FxSendsModel*) m_ui.SendsListView->model();
270 pModel->addFxSend();
271 }
272
273 void ChannelFxForm::onDestroyFxSend() {
274 FxSendsModel* pModel = (FxSendsModel*) m_ui.SendsListView->model();
275 pModel->removeFxSend(m_ui.SendsListView->currentIndex());
276 }
277
278 void ChannelFxForm::onDepthCtrlChanged(int iMidiCtrl) {
279 FxSendsModel* pModel = (FxSendsModel*) m_ui.SendsListView->model();
280 const QModelIndex index = m_ui.SendsListView->currentIndex();
281 FxSend* pFxSend = pModel->fxSend(index);
282 if (!pFxSend) return;
283
284 pFxSend->setSendDepthMidiCtrl(iMidiCtrl);
285 pModel->onExternalModifiication(index);
286 }
287
288 void ChannelFxForm::onCurrentSendDepthChanged(int depthPercent) {
289 FxSendsModel* pModel = (FxSendsModel*) m_ui.SendsListView->model();
290 const QModelIndex index = m_ui.SendsListView->currentIndex();
291 FxSend* pFxSend = pModel->fxSend(index);
292 if (!pFxSend) return;
293
294 if (depthPercent == int( ::round(pFxSend->currentDepth() * 100.0) ))
295 return; // nothing changed actually
296
297 pFxSend->setCurrentDepth(double(depthPercent) / 100.0);
298 pModel->onExternalModifiication(index);
299 }
300
301 void ChannelFxForm::onRoutingTableChanged() {
302 ChannelRoutingModel* pRoutingModel =
303 (ChannelRoutingModel*) m_ui.audioRoutingTable->model();
304 if (pRoutingModel->routingMap().size() <= 0)
305 return; // no changes
306
307 FxSendsModel* pModel = (FxSendsModel*) m_ui.SendsListView->model();
308 const QModelIndex index = m_ui.SendsListView->currentIndex();
309 FxSend* pFxSend = pModel->fxSend(index);
310 if (!pFxSend) {
311 pRoutingModel->routingMap().clear(); // reset routing change map
312 return;
313 }
314
315 ChannelRoutingMap routingMap = pRoutingModel->routingMap();
316 for (
317 ChannelRoutingMap::iterator iter = routingMap.begin();
318 iter != routingMap.end(); ++iter
319 ) pFxSend->setAudioChannel(iter.key(), iter.value());
320
321 pRoutingModel->routingMap().clear(); // reset routing change map
322
323 pModel->onExternalModifiication(index);
324 }
325
326 void ChannelFxForm::updateTableCellRenderers() {
327 ChannelRoutingModel* pRoutingModel =
328 (ChannelRoutingModel*) m_ui.audioRoutingTable->model();
329 const int rows = pRoutingModel->rowCount();
330 const int cols = pRoutingModel->columnCount();
331 updateTableCellRenderers(
332 pRoutingModel->index(0, 0),
333 pRoutingModel->index(rows - 1, cols - 1)
334 );
335 }
336
337 void ChannelFxForm::updateTableCellRenderers (
338 const QModelIndex& topLeft, const QModelIndex& bottomRight )
339 {
340 ChannelRoutingModel* pRoutingModel =
341 (ChannelRoutingModel*) m_ui.audioRoutingTable->model();
342 for (int r = topLeft.row(); r <= bottomRight.row(); r++) {
343 for (int c = topLeft.column(); c <= bottomRight.column(); c++) {
344 const QModelIndex index = pRoutingModel->index(r, c);
345 m_ui.audioRoutingTable->openPersistentEditor(index);
346 }
347 }
348 }
349
350 } // namespace QSampler
351
352 // end of qsamplerChannelFxForm.cpp

  ViewVC Help
Powered by ViewVC