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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1706 - (hide annotations) (download)
Tue Feb 19 22:15:18 2008 UTC (16 years, 2 months ago) by capela
File size: 11582 byte(s)
* Selection rectangle get visible only where it stands legal,
  that is for Qt >= 4.3, right on the channel sends fx dialog.

1 schoenebeck 1667 // 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 schoenebeck 1668 // let's not reinvent the wheel for audio routing
27     #include "qsamplerChannel.h"
28    
29     #include <math.h>
30    
31 schoenebeck 1667 #include <QAbstractButton>
32 schoenebeck 1668 #include <QLineEdit>
33     #include <QHeaderView>
34     #include <QMap>
35 schoenebeck 1667
36 schoenebeck 1668 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 schoenebeck 1667 namespace QSampler {
106    
107     ChannelFxForm::ChannelFxForm (
108 schoenebeck 1668 Channel* pSamplerChannel, QWidget* pParent, Qt::WindowFlags wflags )
109 schoenebeck 1667 : QDialog(pParent, wflags)
110     {
111     m_ui.setupUi(this);
112    
113 schoenebeck 1668 m_pSamplerChannel = pSamplerChannel;
114 schoenebeck 1667
115 schoenebeck 1668 m_pAudioDevice = NULL;
116    
117 schoenebeck 1667 FxSendsModel* pModel =
118 schoenebeck 1668 new FxSendsModel(m_pSamplerChannel->channelID(), m_ui.SendsListView);
119 schoenebeck 1667 m_ui.SendsListView->setModel(pModel);
120 capela 1706 #ifdef QT_VERSION >= 0x040300
121     m_ui.SendsListView->setSelectionRectVisible(true);
122     #endif
123 schoenebeck 1667
124 schoenebeck 1668 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 schoenebeck 1667 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 schoenebeck 1668 pResetButton->setToolTip("Revert all changes.");
153 schoenebeck 1667
154     m_ui.destroyPushButton->setEnabled(false);
155    
156 schoenebeck 1668 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 schoenebeck 1667 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 schoenebeck 1668 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 schoenebeck 1667 }
210    
211     ChannelFxForm::~ChannelFxForm() {
212 schoenebeck 1668 if (m_pAudioDevice) delete m_pAudioDevice;
213 schoenebeck 1667 }
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 schoenebeck 1668 // force a refresh of the parameter control elements
222     onFxSendSelection(m_ui.SendsListView->currentIndex());
223 schoenebeck 1667 break;
224     case QDialogButtonBox::ResetRole:
225     pModel->cleanRefresh();
226 schoenebeck 1668 // force a refresh of the parameter control elements
227     onFxSendSelection(m_ui.SendsListView->currentIndex());
228 schoenebeck 1667 break;
229     default: // to avoid gcc warnings
230     break;
231     }
232     }
233    
234     void ChannelFxForm::onFxSendSelection(const QModelIndex& index) {
235 schoenebeck 1668 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 capela 1671 int(::round(pFxSend->currentDepth() * 100.0))
265 schoenebeck 1668 );
266 schoenebeck 1667 }
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 schoenebeck 1668 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 schoenebeck 1667 } // namespace QSampler
351    
352     // end of qsamplerChannelFxForm.cpp

  ViewVC Help
Powered by ViewVC