1 //
2 // C++ Implementation: testogui
3 //
4 // Description:
5 //
6 //
7 // Author: Mathias Lundgren <lunar_shuttle@users.sf.net>, (C) 2004
8 //  Contributer: (C) Copyright 2011 Tim E. Real (terminator356 at users.sourceforge.net)
9 //  Multi-channel support and metering - Andrew Deryabin, 2015
10 //
11 //  This program is free software; you can redistribute it and/or
12 //  modify it under the terms of the GNU General Public License
13 //  as published by the Free Software Foundation; version 2 of
14 //  the License, or (at your option) any later version.
15 //
16 //  This program is distributed in the hope that it will be useful,
17 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
18 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 //  GNU General Public License for more details.
20 //
21 //  You should have received a copy of the GNU General Public License
22 //  along with this program; if not, write to the Free Software
23 //  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
24 //
25 //
26 //
27 
28 #include <QButtonGroup>
29 #include <QLabel>
30 #include <QFileDialog>
31 #include <QLayout>
32 #include <QToolTip>
33 #include <QLineEdit>
34 #include <QMessageBox>
35 
36 #include "common_defs.h"
37 #include "simpledrumsgui.h"
38 #include "mpevent.h"
39 #include "midi_consts.h"
40 #include "ssplugingui.h"
41 #include "wavepreview.h"
42 
43 #define SS_VOLUME_MIN_VALUE                     0
44 #define SS_VOLUME_MAX_VALUE                   127
45 #define SS_VOLUME_DEFAULT_VALUE               100
46 #define SS_MASTERVOL_MAX_VALUE                127
47 #define SS_MASTERVOL_DEFAULT_VALUE    100.0/127.0
48 #define SS_SENDFX_MIN_VALUE                     0
49 #define SS_SENDFX_MAX_VALUE                   127
50 
51 //Gui constants:
52 #define SS_BTNGRP_WIDTH                        50
53 #define SS_BTNGRP_HEIGHT                       80
54 #define SS_ONOFF_WIDTH                         16
55 #define SS_ONOFF_HEIGHT                        21
56 #define SS_VOLSLDR_WIDTH                       (SS_BTNGRP_WIDTH - 8)
57 #define SS_VOLSLDR_LENGTH                     120
58 #define SS_PANSLDR_WIDTH                       (SS_BTNGRP_WIDTH - 8)
59 #define SS_PANSLDR_LENGTH                      20
60 #define SS_PANSLDR_DEFAULT_VALUE               63
61 #define SS_NONOFF_LABEL_WIDTH                  30
62 #define SS_NONOFF_LABEL_HEIGHT                 16
63 #define SS_NONOFF_WIDTH                        SS_ONOFF_WIDTH
64 #define SS_NONOFF_HEIGHT                       SS_ONOFF_HEIGHT
65 #define SS_SENDFX_WIDTH                        ((SS_BTNGRP_WIDTH/2) - 4)
66 //#define SS_SENDFX_WIDTH                        28
67 #define SS_SENDFX_HEIGHT                       SS_SENDFX_WIDTH
68 #define SS_MASTERSLDR_WIDTH                    (SS_BTNGRP_WIDTH - 8)
69 #define SS_MASTERSLDR_HEIGHT                   (SS_BTNGRP_HEIGHT - 4)
70 
71 
72 // Sample groupbox
73 
74 #define SS_SAMPLENAME_LABEL_WIDTH              30
75 #define SS_SAMPLENAME_LABEL_HEIGHT             21
76 #define SS_SAMPLENAME_LABEL_XOFF                4
77 
78 #define SS_SAMPLE_LOAD_WIDTH                   15
79 #define SS_SAMPLE_LOAD_HEIGHT                  19
80 
81 #define SS_SAMPLE_CLEAR_WIDTH                   SS_SAMPLE_LOAD_WIDTH
82 #define SS_SAMPLE_CLEAR_HEIGHT                  SS_SAMPLE_LOAD_HEIGHT
83 
84 #define SS_SAMPLENAME_LINEEDIT_WIDTH           90
85 #define SS_SAMPLENAME_LINEEDIT_HEIGHT          21
86 
87 #define SS_SAMPLE_INFO_LINE_HEIGHT             22
88 #define SS_SAMPLE_INFO_LINE_WIDTH               (SS_SAMPLENAME_LINEEDIT_XOFF + SS_SAMPLENAME_LINEEDIT_WIDTH)
89 
90 #define SS_GUI_WINDOW_WIDTH                     ((SS_NR_OF_CHANNELS +1) * SS_BTNGRP_XOFF)
91 #define SS_MAIN_GROUPBOX_HEIGHT                 200
92 #define SS_GUI_WINDOW_HEIGHT                    (SS_BTNGRP_HEIGHT + SS_MAIN_GROUPBOX_HEIGHT)
93 #define SS_MAIN_GROUPBOX_WIDTH                  SS_GUI_WINDOW_WIDTH
94 
95 
96 QString labelStrings[] = {
97    "C 1 Bass drum 1",
98    "C#1 Side stick",
99    "D 1 Acoustic snare",
100    "D#1 Hand clap",
101    "E 1 Electric snare",
102    "F 1 Low floor tom",
103    "F#1 Closed hi-hat",
104    "G 1 High floor tom",
105 
106    "G#1 Pedal hi-hat",
107    "A 1 Low tom",
108    "A#1 Open hi-hat",
109    "B 1 Low-mid tom",
110    "C 2 Hi-mid tom",
111    "C#2 Crash cymbal",
112    "D 2 High tom",
113    "D#2 Ride cymbal 1",
114 };
115 
116 
117 /*!
118     \fn QChannelSlider::QChannelSlider(Qt::Orientation orientation, int ch, QWidget* parent, const char* name)
119  */
QChannelSlider(Qt::Orientation orientation,int ch,QWidget * parent)120 QChannelSlider::QChannelSlider(Qt::Orientation orientation, int ch, QWidget* parent)
121    : QSlider(orientation, parent)
122 {
123    channel = ch;
124    setMinimumHeight(50);
125    setMouseTracking(true);
126    setTracking(true);
127    connect(this, SIGNAL(valueChanged(int)), SLOT(updateStatusField()));
128 }
129 
sliderChange(SliderChange change)130 void QChannelSlider::sliderChange(SliderChange change)
131 {
132    QSlider::sliderChange(change);
133    if(change == QAbstractSlider::SliderValueChange)
134       emit valueChanged(channel, value());
135 }
136 
updateStatusField()137 void QChannelSlider::updateStatusField()
138 {
139     auto infoString = QString("%1 : %2").arg(toolTip()).arg(value());
140     emit updateInformationField(infoString);
141 }
142 
mouseMoveEvent(QMouseEvent * e)143 void QChannelSlider::mouseMoveEvent(QMouseEvent *e)
144 {
145     QSlider::mouseMoveEvent(e);
146     updateStatusField();
147 }
148 
149 /*!
150     \fn QChannelSlider::getChannel()
151  */
getChannel()152 int QChannelSlider::getChannel()
153 {
154    return channel;
155 }
156 
157 
158 /*!
159     \fn QChannelSlider::setChannel(int ch)
160  */
setChannel(int ch)161 void QChannelSlider::setChannel(int ch)
162 {
163    channel = ch;
164 }
165 
166 /*!
167     \fn QChannelCheckbox::QChannelCheckbox(QWidget* parent, int ch)
168  */
QChannelCheckbox(QWidget * parent,int ch)169 QChannelCheckbox::QChannelCheckbox(QWidget* parent, int ch)
170    : QCheckBox(parent)
171 {
172    channel = ch;
173    connect(this, SIGNAL(clicked()), SLOT(isClicked()));
174 }
175 
176 
177 /*!
178     \fn QChannelCheckbox::isClicked()
179  */
isClicked()180 void QChannelCheckbox::isClicked()
181 {
182    emit channelState(channel, this->isChecked());
183 }
184 
185 /*!
186     \fn QChannelButton::QChannelButton(QWidget* parent, const char* text, int ch, const char* name)
187  */
QChannelButton(QWidget * parent,const char * text,int ch)188 QChannelButton::QChannelButton(QWidget* parent, const char* text, int ch)
189    : QPushButton(parent), channel (ch)
190 {
191    connect(this, SIGNAL(clicked()), SLOT(isClicked()));
192    setText(text);
193 }
194 
195 /*!
196     \fn QChannelButton::isClicked()
197  */
isClicked()198 void QChannelButton::isClicked()
199 {
200    emit channelState(channel, this->isChecked());
201 }
202 
203 /*!
204     \fn QChannelDial()
205  */
QChannelDial(QWidget * parent,int ch,int fxid)206 QChannelDial::QChannelDial(QWidget* parent, int ch, int fxid)
207    : QDial(parent)
208 {
209    setTracking(true);
210    setMouseTracking(true);
211    channel = ch;
212    sendfxid = fxid;
213    connect(this, SIGNAL(sliderReleased()), SLOT(forwardSliderMoved()));
214    connect(this, SIGNAL(valueChanged(int)), SLOT(updateStatusField()));
215 }
updateStatusField()216 void QChannelDial::updateStatusField()
217 {
218     auto infoString = QString("%1 : %2").arg(toolTip()).arg(value());
219     emit updateInformationField(infoString);
220 }
221 
sliderChange(SliderChange change)222 void QChannelDial::sliderChange(SliderChange change)
223 {
224    QDial::sliderChange(change);
225    if(change == QAbstractSlider::SliderValueChange)
226       emit valueChanged(channel, sendfxid, value());
227 }
228 
mouseMoveEvent(QMouseEvent * e)229 void QChannelDial::mouseMoveEvent(QMouseEvent *e)
230 {
231     QDial::mouseMoveEvent(e);
232     updateStatusField();
233 }
234 
235 
forwardSliderMoved()236 void QChannelDial::forwardSliderMoved()
237 {
238    emit sliderMoved(channel, value());
239 }
240 
241 /*!
242     \fn SimpleSynthGui::SimpleSynthGui()
243  */
SimpleSynthGui(int sampleRate)244 SimpleSynthGui::SimpleSynthGui(int sampleRate)
245 {
246    SS_TRACE_IN
247          setupUi(this);
248 
249    setSampleRate(sampleRate);
250 
251    pluginGui = new SS_PluginGui(this);
252    pluginGui->hide();
253 
254    for (int i=0; i<SS_NR_OF_CHANNELS; i++) {
255       channelButtonGroups[i] = new QGroupBox(this);
256       //            channelButtonGroups[i]->setMinimumSize(SS_BTNGRP_WIDTH, SS_BTNGRP_HEIGHT);
257       channelButtonGroups[i]->setTitle(QString::number(i + 1));
258 
259       QString name = QString("volumeSlider");
260       name.append(i + 1);
261 
262       channelLayout->addWidget(channelButtonGroups[i]);
263 
264       QVBoxLayout* inchnlLayout = new QVBoxLayout(channelButtonGroups[i]); //, 2, 0, "channelinternallayout");
265       inchnlLayout->setAlignment(Qt::AlignHCenter);
266       inchnlLayout->setSpacing(1);
267       inchnlLayout->setMargin(0);
268 
269 
270       onOff[i] = new QChannelCheckbox(channelButtonGroups[i], i);
271       //            onOff[i]->setMinimumSize(SS_ONOFF_WIDTH, SS_ONOFF_HEIGHT);
272       onOff[i]->setToolTip("Channel " + QString::number(i + 1) + " on/off");
273       inchnlLayout->addWidget(onOff[i]);
274       connect(onOff[i], SIGNAL(channelState(int, bool)), SLOT(channelOnOff(int, bool)));
275 
276       QHBoxLayout *volLayout = new QHBoxLayout(channelButtonGroups[i]);
277 
278       volumeSliders[i] = new QChannelSlider(Qt::Vertical, i, channelButtonGroups[i]);
279 
280       volumeSliders[i]->setMinimum(SS_VOLUME_MIN_VALUE);
281       volumeSliders[i]->setMaximum(SS_VOLUME_MAX_VALUE);
282 
283       ///volumeSliders[i]->setValue(SS_VOLUME_MAX_VALUE - SS_VOLUME_DEFAULT_VALUE);
284       volumeSliders[i]->setValue(SS_VOLUME_DEFAULT_VALUE);  // p4.0.27
285 
286       //            volumeSliders[i]->setMinimumSize(SS_VOLSLDR_WIDTH, SS_VOLSLDR_LENGTH);
287       volumeSliders[i]->setToolTip("Volume, channel " + QString::number(i + 1));
288       //            setMinimumSize(SS_VOLSLDR_WIDTH, SS_VOLSLDR_LENGTH);
289       volLayout->addWidget(volumeSliders[i]);
290 
291       chnMeter[i] = new MusEGui::Meter(channelButtonGroups[i]);
292       chnMeter[i]->setFixedWidth(9);
293       chnMeter[i]->setVal(0.0, 0.0, false);
294       meterVal[i] = peakVal[i] = 0.0;
295       chnMeter[i]->setRange(SS_minMeterVal, 10.0);
296       chnMeter[i]->show();
297       volLayout->addWidget(chnMeter[i]);
298 
299       inchnlLayout->addLayout(volLayout);
300 
301       connect(volumeSliders[i], SIGNAL(updateInformationField(QString)), widgetStatusInfo, SLOT(setText(QString)));
302       connect(volumeSliders[i], SIGNAL(valueChanged(int, int)), SLOT(volumeChanged(int, int)));
303 
304       pitchKnobs[i] = new QChannelDial(channelButtonGroups[i], i, 0);
305       pitchKnobs[i]->setRange(-63,63);
306       pitchKnobs[i]->setValue(0);
307       pitchKnobs[i]->setToolTip("Pitch, channel " + QString::number(i + 1));
308       pitchKnobs[i]->setFixedSize(30,30);
309       inchnlLayout->addWidget(pitchKnobs[i]);
310       connect(pitchKnobs[i], SIGNAL(updateInformationField(QString)), widgetStatusInfo, SLOT(setText(QString)));
311       connect(pitchKnobs[i], SIGNAL(valueChanged(int,int,int)), SLOT(pitchChanged(int,int, int)));
312 
313 
314       nOffLabel[i] = new QLabel(channelButtonGroups[i]);
315       nOffLabel[i]->setText("nOff");
316       inchnlLayout->addWidget(nOffLabel[i]);
317 
318       nOffIgnore[i] = new QChannelCheckbox(channelButtonGroups[i], i);
319       nOffIgnore[i]->setToolTip("Note off ignore, channel " + QString::number(i + 1));
320       inchnlLayout->addWidget(nOffIgnore[i]);
321       connect(nOffIgnore[i], SIGNAL(channelState(int, bool)),SLOT(channelNoteOffIgnore(int, bool)));
322 
323       panSliders[i] = new QChannelSlider(Qt::Horizontal, i, channelButtonGroups[i]);
324       panSliders[i]->setRange(0, 127);
325       panSliders[i]->setValue(SS_PANSLDR_DEFAULT_VALUE);
326       panSliders[i]->setToolTip("Pan, channel " + QString::number(i + 1));
327       inchnlLayout->addWidget(panSliders[i]);
328       connect(panSliders[i], SIGNAL(updateInformationField(QString)), widgetStatusInfo, SLOT(setText(QString)));
329       connect(panSliders[i], SIGNAL(valueChanged(int, int)), SLOT(panChanged(int, int)));
330 
331       QGridLayout* dialGrid = new QGridLayout;
332       inchnlLayout->addLayout(dialGrid);
333       sendFxDial[i][0] = new QChannelDial(channelButtonGroups[i], i, 0);
334       sendFxDial[i][0]->setRange(0, 127);
335       sendFxDial[i][0]->setMaximumSize(SS_SENDFX_WIDTH, SS_SENDFX_HEIGHT);
336       sendFxDial[i][0]->setToolTip("Fx 1 send amount");
337 
338       dialGrid->addWidget(sendFxDial[i][0], 0, 0, Qt::AlignCenter | Qt::AlignTop);
339 
340       connect(sendFxDial[i][0], SIGNAL(updateInformationField(QString)), widgetStatusInfo, SLOT(setText(QString)));
341       connect(sendFxDial[i][0], SIGNAL(valueChanged(int, int, int)), SLOT(sendFxChanged(int, int, int)));
342 
343       sendFxDial[i][1] = new QChannelDial(channelButtonGroups[i], i, 1);
344       sendFxDial[i][1]->setRange(0, 127);
345       dialGrid->addWidget(sendFxDial[i][1], 0, 1, Qt::AlignCenter | Qt::AlignTop);
346       sendFxDial[i][1]->setMaximumSize(SS_SENDFX_WIDTH, SS_SENDFX_HEIGHT);
347       sendFxDial[i][1]->setToolTip("Fx 2 send amount");
348 
349       connect(sendFxDial[i][1], SIGNAL(updateInformationField(QString)), widgetStatusInfo, SLOT(setText(QString)));
350       connect(sendFxDial[i][1], SIGNAL(valueChanged(int, int, int)), SLOT(sendFxChanged(int, int, int)));
351 
352       sendFxDial[i][2] = new QChannelDial(channelButtonGroups[i], i, 2);
353       sendFxDial[i][2]->setRange(0, 127);
354       sendFxDial[i][2]->setMaximumSize(SS_SENDFX_WIDTH, SS_SENDFX_HEIGHT);
355       dialGrid->addWidget(sendFxDial[i][2], 1, 0, Qt::AlignCenter | Qt::AlignTop);
356       sendFxDial[i][2]->setToolTip("Fx 3 send amount");
357 
358       connect(sendFxDial[i][2], SIGNAL(updateInformationField(QString)), widgetStatusInfo, SLOT(setText(QString)));
359       connect(sendFxDial[i][2], SIGNAL(valueChanged(int, int, int)), SLOT(sendFxChanged(int, int, int)));
360 
361       sendFxDial[i][3] = new QChannelDial(channelButtonGroups[i], i, 3);
362       sendFxDial[i][3]->setRange(0, 127);
363       sendFxDial[i][3]->setMaximumSize(SS_SENDFX_WIDTH, SS_SENDFX_HEIGHT);
364       sendFxDial[i][3]->setToolTip("Fx 4 send amount");
365       dialGrid->addWidget(sendFxDial[i][3], 1, 1, Qt::AlignCenter | Qt::AlignTop);
366 
367       connect(sendFxDial[i][3], SIGNAL(updateInformationField(QString)), widgetStatusInfo, SLOT(setText(QString)));
368       connect(sendFxDial[i][3], SIGNAL(valueChanged(int, int, int)), SLOT(sendFxChanged(int, int, int)));
369 
370       chnRoutingCb[i] = new QComboBox(channelButtonGroups[i]);
371       chnRoutingCb[i]->addItem(tr("Mix"), QVariant(0));
372       chnRoutingCb[i]->addItem(tr("Chn"), QVariant(1));
373       chnRoutingCb[i]->setMaximumSize(SS_PANSLDR_WIDTH, SS_PANSLDR_LENGTH);
374       chnRoutingCb[i]->setToolTip(tr("Channel routing"));
375       QFont chnRFont;
376       chnRFont.setPointSize(6);
377       chnRoutingCb[i]->setFont(chnRFont);
378       connect(chnRoutingCb[i], SIGNAL(currentIndexChanged(int)), this, SLOT(routeChanged(int)));
379       inchnlLayout->addWidget(chnRoutingCb[i]);
380 
381       inchnlLayout->activate();
382    }
383 
384    masterSlider = new QSlider(Qt::Vertical, this);
385    masterSlider->setToolTip("Master volume");
386    channelLayout->addWidget(masterSlider);
387    masterSlider->setRange(0, 127);
388    masterSlider->setValue((int)(SS_MASTERVOL_DEFAULT_VALUE*SS_VOLUME_MAX_VALUE)); // p4.0.27
389 
390    connect(masterSlider, SIGNAL(valueChanged(int)), SLOT(masterVolChanged(int)));  // p4.0.27
391 
392 
393    int i=0;
394 
395    for (int c=0; c<2; c++) {
396       for (int r=0; r<SS_NR_OF_CHANNELS/2; r++) {
397          QHBoxLayout* strip = new QHBoxLayout;
398          mgbLayout->addLayout(strip, r, c);
399 
400          QLabel* channelLabel = new QLabel(QString::number(i + 1) + ": (" +labelStrings[i] + ")");
401          strip->addWidget(channelLabel);
402 
403          sampleNameLineEdit[i] = new QLineEdit();
404          sampleNameLineEdit[i]->setReadOnly(true);
405          sampleNameLineEdit[i]->setFixedWidth(180);
406          strip->addWidget(sampleNameLineEdit[i]);
407 
408          loadSampleButton[i] = new QChannelButton(0, "L", i);
409          loadSampleButton[i]->setToolTip("Load sample on channel " + QString::number(i + 1));
410          loadSampleButton[i]->setFixedSize(23,23);
411          strip->addWidget(loadSampleButton[i]);
412          connect(loadSampleButton[i], SIGNAL(channelState(int, bool)), SLOT(loadSampleDialogue(int)));
413 
414          clearSampleButton[i] = new QChannelButton(0, "C", i);
415          clearSampleButton[i]->setToolTip("Clear sample on channel " + QString::number(i + 1));
416          clearSampleButton[i]->setFixedSize(23,23);
417          strip->addWidget(clearSampleButton[i]);
418          connect(clearSampleButton[i], SIGNAL(channelState(int, bool)), SLOT(clearSample(int)));
419          i++;
420       }
421    }
422 
423    // Right bottom panel:
424    QGroupBox* rbPanel= new QGroupBox();
425    mgbLayout->addWidget(rbPanel, 1, 3, 7, 1, Qt::AlignCenter);
426    QGridLayout* rbLayout = new QGridLayout(rbPanel);
427 
428    openPluginsButton = new QPushButton("&Send Effects");
429    openPluginsButton->setToolTip("Configure LADSPA send effects");
430    connect(openPluginsButton, SIGNAL(clicked()), SLOT(openPluginButtonClicked()));
431    rbLayout->addWidget(openPluginsButton, 2, 1, Qt::AlignCenter | Qt::AlignVCenter);
432    rbLayout->setSpacing(0);
433    rbLayout->setMargin(0);
434    aboutButton = new QPushButton("About SimpleDrums");
435    connect(aboutButton, SIGNAL(clicked()), SLOT(aboutButtonClicked()));
436    rbLayout->addWidget(aboutButton, 4, 1, Qt::AlignLeft | Qt::AlignVCenter);
437 
438 
439    loadButton = new QPushButton(tr("&Load setup"), rbPanel);
440    connect(loadButton, SIGNAL(clicked()), SLOT(loadSetup()));
441    saveButton = new QPushButton(tr("&Save setup"), rbPanel);
442    connect(saveButton, SIGNAL(clicked()), SLOT(saveSetup()));
443    rbLayout->addWidget(loadButton,  3, 1, Qt::AlignCenter | Qt::AlignVCenter);
444    rbLayout->addWidget(saveButton,  4, 1, Qt::AlignCenter | Qt::AlignVCenter);
445    rbLayout->addWidget(aboutButton, 6, 1, Qt::AlignCenter | Qt::AlignVCenter);
446 
447    lastDir = "";
448    connect(this->getGuiSignal(),SIGNAL(wakeup()),this,SLOT(readMessage()));
449 
450    SS_TRACE_OUT
451 }
452 
453 /*!
454     \fn SimpleSynthGui::~SimpleSynthGui()
455  */
~SimpleSynthGui()456 SimpleSynthGui::~SimpleSynthGui()
457 {
458    SS_TRACE_IN
459    delete pluginGui;
460    SS_TRACE_OUT
461 }
462 
463 /*!
464     \fn SimpleSynthGui::readMessage()
465  */
readMessage()466 void SimpleSynthGui::readMessage()
467 {
468    MessGui::readMessage();
469 }
470 
471 /*!
472     \fn SimpleSynthGui::processEvent(const MusECore::MidiPlayEvent& ev)
473  */
processEvent(const MusECore::MidiPlayEvent & ev)474 void SimpleSynthGui::processEvent(const MusECore::MidiPlayEvent& ev)
475 {
476    SS_TRACE_IN
477          if (SS_DEBUG_MIDI) {
478       printf("GUI received midi event\n");
479    }
480    if (ev.type() == MusECore::ME_CONTROLLER) {
481       int id  = ev.dataA();
482       int val = ev.dataB();
483 
484       // Channel controllers:
485       if (id >= SS_FIRST_CHANNEL_CONTROLLER && id <= SS_LAST_CHANNEL_CONTROLLER ) {
486          // Find out which channel we're dealing with:
487          id-= SS_FIRST_CHANNEL_CONTROLLER;
488          int ch = (id / SS_NR_OF_CHANNEL_CONTROLLERS);
489          id = (id % SS_NR_OF_CHANNEL_CONTROLLERS);
490 
491          int fxid = -1;
492 
493          if (SS_DEBUG_MIDI) {
494             printf("GUI received midi controller - id: %d val %d channel %d\n", id, val, ch);
495          }
496 
497          switch(id) {
498          case SS_CHANNEL_CTRL_VOLUME:
499             volumeSliders[ch]->blockSignals(true);
500             volumeSliders[ch]->setValue(val);
501             volumeSliders[ch]->blockSignals(false);
502             break;
503          case SS_CHANNEL_CTRL_PITCH:
504             pitchKnobs[ch]->blockSignals(true);
505             pitchKnobs[ch]->setValue(-(val-63));
506             pitchKnobs[ch]->blockSignals(false);
507             break;
508 
509          case SS_CHANNEL_CTRL_PAN:
510             panSliders[ch]->blockSignals(true);
511             panSliders[ch]->setValue(val);
512             panSliders[ch]->blockSignals(false);
513             break;
514 
515          case SS_CHANNEL_CTRL_NOFF:
516             nOffIgnore[ch]->blockSignals(true);
517             nOffIgnore[ch]->setChecked(val);
518             nOffIgnore[ch]->blockSignals(false);
519             break;
520 
521          case SS_CHANNEL_CTRL_ONOFF:
522             onOff[ch]->blockSignals(true);
523             onOff[ch]->setChecked(val);
524             onOff[ch]->blockSignals(false);
525             break;
526 
527          case SS_CHANNEL_CTRL_ROUTE:
528             chnRoutingCb[ch]->setCurrentIndex(val);
529             break;
530 
531          case SS_CHANNEL_SENDFX1:
532          case SS_CHANNEL_SENDFX2:
533          case SS_CHANNEL_SENDFX3:
534          case SS_CHANNEL_SENDFX4:
535             fxid = id - SS_CHANNEL_SENDFX1;
536             if (SS_DEBUG_MIDI) {
537                printf("SimpleSynthGui::processEvent - Channel sendfx, fxid: %d, val: %d\n", fxid, val);
538             }
539             sendFxDial[ch][fxid]->blockSignals(true);
540             sendFxDial[ch][fxid]->setValue(val);
541             sendFxDial[ch][fxid]->blockSignals(false);
542             break;
543 
544          default:
545             if (SS_DEBUG_MIDI)
546                printf("SimpleSynthGui::processEvent - unknown controller received: %d\n", id);
547          }
548       }
549       // Master controllers:
550       else if (id >= SS_FIRST_MASTER_CONTROLLER && id <= SS_LAST_MASTER_CONTROLLER) {
551          if (id == SS_MASTER_CTRL_VOLUME) {
552             masterSlider->blockSignals(true);
553 
554             ///masterSlider->setValue(SS_MASTERVOL_MAX_VALUE - val);
555             masterSlider->setValue(val);   // p4.0.27
556 
557             masterSlider->blockSignals(false);
558          }
559       }
560       else if (id>= SS_FIRST_PLUGIN_CONTROLLER && id <= SS_LAST_PLUGIN_CONTROLLER) {
561          int fxid = (id - SS_FIRST_PLUGIN_CONTROLLER) / SS_NR_OF_PLUGIN_CONTROLLERS;
562          int cmd = (id - SS_FIRST_PLUGIN_CONTROLLER) % SS_NR_OF_PLUGIN_CONTROLLERS;
563 
564          // Plugin return-gain:
565          if (cmd == SS_PLUGIN_RETURN) {
566             if (SS_DEBUG_MIDI)
567                printf("SimpleSynthGui::processEvent - fx retgain received: fxid: %d val: %d\n", fxid, val);
568 
569             SS_PluginFront* pf = pluginGui->getPluginFront((unsigned)fxid);
570             pf->setRetGain(val);
571          }
572          // Plugin on/off:
573          else if (cmd == SS_PLUGIN_ONOFF) {      // p4.0.27
574             if (SS_DEBUG_MIDI)
575                printf("SimpleSynthGui::processEvent - fx onoff received: fxid: %d val: %d\n", fxid, val);
576             SS_PluginFront* pf = pluginGui->getPluginFront((unsigned)fxid);
577             pf->setOnOff(val);
578          }
579       }
580    }
581    //
582    // Sysexes:
583    //
584    else if (ev.type() == MusECore::ME_SYSEX) {
585       const byte* data = ev.constData();
586       //byte* data = d + 2;
587       const int cmd = *data;
588       switch (cmd) {
589       case SS_SYSEX_LOAD_SAMPLE_OK: {
590          const int ch = *(data+1);
591          QString filename = (const char*) (data+2);
592          sampleNameLineEdit[ch]->setText(filename.section('/',-1,-1));
593          if (SS_DEBUG_MIDI) {
594             printf("SimpleSynthGui - sample %s loaded OK on channel: %d\n", filename.toLatin1().constData(), ch);
595          }
596          if (!onOff[ch]->isChecked()) {
597             onOff[ch]->blockSignals(true);
598             onOff[ch]->setChecked(true);
599             onOff[ch]->blockSignals(false);
600             channelOnOff(ch, true);
601          }
602          break;
603       }
604 
605       case SS_SYSEX_LOAD_SAMPLE_ERROR: {
606          const char* filename = (const char*) (data+2);
607          printf("Error: Sample %s not found! TODO: Fix this\n", filename);
608          break;
609       }
610 
611       case SS_SYSEX_LOAD_SENDEFFECT_OK: {
612          if (SS_DEBUG_MIDI) {
613             printf("SimpleSynthGui - sysex load sendeffect OK on fxid: %d\n", *(data+1));
614          }
615          const int fxid = *(data+1);
616          SS_PluginFront* pf = pluginGui->getPluginFront((unsigned)fxid);
617          ///pf->updatePluginValue(*(data+2));
618          pf->updatePluginValue(  *((MusESimplePlugin::PluginI**)(data+2)) );
619          break;
620       }
621 
622       case SS_SYSEX_CLEAR_SENDEFFECT_OK: {
623          if (SS_DEBUG_MIDI) {
624             printf("SimpleSynthGui - sysex clear sendeffect OK on fxid: %d\n", *(data+1));
625          }
626          SS_PluginFront* pf = pluginGui->getPluginFront((unsigned)*(data+1));
627          pf->clearPluginDisplay();
628          break;
629       }
630 
631       case SS_SYSEX_CLEAR_SAMPLE_OK: {
632          if (SS_DEBUG_MIDI) {
633             printf("SimpleSynthGui - sysex clear samle OK on channel: %d\n", *(data+1));
634          }
635          const byte ch = *(data+1);
636          sampleNameLineEdit[ch]->setText("");
637          break;
638       }
639 
640       case SS_SYSEX_SET_PLUGIN_PARAMETER_OK: {
641          if (SS_DEBUG_MIDI) {
642             printf("SimpleSynthGui - plugin parameter OK on fxid: %d\n", *(data+1));
643          }
644          SS_PluginFront* pf = pluginGui->getPluginFront((unsigned)*(data+1));
645          const int param = *(data+2);
646          const int val   = *(data+3);
647          pf->blockSignals(true);
648          pf->setParameterValue(param, val);
649          pf->blockSignals(false);
650          break;
651       }
652 
653       case SS_SYSEX_SEND_INIT_DATA: {
654          // FN: TODO
655 #if 1
656          const unsigned initdata_len = ev.len() - 1;
657          const byte* init_data = (data + 1);
658          QFileInfo fileInfo = QFileInfo(lastSavedProject);
659 
660          lastProjectDir = fileInfo.path();
661          if (fileInfo.suffix() != "sds" && fileInfo.suffix() != "SDS") {
662             lastSavedProject += ".sds";
663             fileInfo = QFileInfo(lastSavedProject);
664          }
665          QFile theFile(fileInfo.filePath());
666 
667          // Write data
668          if (theFile.open(QIODevice::WriteOnly)) {
669             theFile.write((const char*)&initdata_len, sizeof(initdata_len)); // First write length
670             if (theFile.write((const char*)init_data, initdata_len) == -1) {
671                // Fatal error writing
672                QMessageBox* msgBox = new QMessageBox(QMessageBox::Warning, "SimpleDrums error Dialog", "Fatal error when writing to file. Setup not saved.",
673                                                      QMessageBox::Ok, this);
674                msgBox->exec();
675                delete msgBox;
676             }
677             theFile.close();
678          }
679          else {
680             // An error occurred when opening
681             QMessageBox* msgBox = new QMessageBox(QMessageBox::Warning, "SimpleDrums error Dialog", "Error opening file. Setup was not saved.",
682                                                   QMessageBox::Ok, this);
683             msgBox->exec();
684             delete msgBox;
685          }
686 #endif
687 
688          break;
689       }
690 
691 
692       default:
693          if (SS_DEBUG_MIDI) {
694             printf("SimpleSynthGui::processEvent - unknown sysex cmd received: %d\n", cmd);
695          }
696          break;
697       }
698    }
699    SS_TRACE_OUT
700 }
701 
702 
703 /*!
704     \fn SimpleSynthGui::volumeChanged(int val)
705  */
volumeChanged(int channel,int val)706 void SimpleSynthGui::volumeChanged(int channel, int val)
707 {
708    setChannelVolume(channel, val);
709 }
710 
711 /*!
712     \fn SimpleSynthGui::pitchChanged(int val)
713  */
pitchChanged(int channel,int,int val)714 void SimpleSynthGui::pitchChanged(int channel, int, int val)
715 {
716    setChannelPitch(channel, -val+63);
717 }
718 
719 /*!
720     \fn SimpleSynthGui::panChanged(int channel, int value)
721  */
panChanged(int channel,int value)722 void SimpleSynthGui::panChanged(int channel, int value)
723 {
724    sendController(0, SS_CHANNEL_PAN_CONTROLLER(channel), value);
725 }
726 
727 /*!
728     \fn SimpleSynthGui::channelOnOff(int channel, bool state)
729  */
channelOnOff(int channel,bool state)730 void SimpleSynthGui::channelOnOff(int channel, bool state)
731 {
732    sendController(0, SS_CHANNEL_ONOFF_CONTROLLER(channel), state);
733 }
734 
735 /*!
736     \fn SimpleSynthGui::channelNoteOffIgnore(bool state)
737  */
channelNoteOffIgnore(int channel,bool state)738 void SimpleSynthGui::channelNoteOffIgnore(int channel, bool state)
739 {
740    sendController(0, SS_CHANNEL_NOFF_CONTROLLER(channel), (int) state);
741 }
742 
743 /*!
744     \fn SimpleSynthGui::sendFxChanged(int ch, int fxid, int val)
745  */
sendFxChanged(int ch,int fxid,int val)746 void SimpleSynthGui::sendFxChanged(int ch, int fxid, int val)
747 {
748    sendController(0, SS_CHANNEL_SENDFX_CONTROLLER(ch, fxid), (int) val);
749 }
750 
751 /*!
752     \fn SimpleSynthGui::masterVolChanged(int val)
753  */
masterVolChanged(int val)754 void SimpleSynthGui::masterVolChanged(int val)
755 {
756    sendController(0, SS_MASTER_CTRL_VOLUME, val);
757 }
758 
759 /*!
760     \fn SimpleSynthGui::setChannelVolume(int channel, byte volume)
761  */
setChannelVolume(int channel,int volume)762 void SimpleSynthGui::setChannelVolume(int channel, int volume)
763 {
764    //volumeSliders[channel]->setValue(SS_VOLUME_MAX_VALUE - volume);
765    sendController(0, SS_CHANNEL_VOLUME_CONTROLLER(channel), (int)volume);
766 }
767 
768 /*!
769     \fn SimpleSynthGui::setChannelPitch(int channel, byte pitch)
770  */
setChannelPitch(int channel,int pitch)771 void SimpleSynthGui::setChannelPitch(int channel, int pitch)
772 {
773    sendController(0, SS_CHANNEL_PITCH_CONTROLLER(channel), (int)pitch);
774 }
775 
setChannelRoute(int channel,int route)776 void SimpleSynthGui::setChannelRoute(int channel, int route)
777 {
778    sendController(0, SS_CHANNEL_ROUTE_CONTROLLER(channel), (int)route);
779 }
780 
781 
782 /*!
783     \fn SimpleSynthGui::loadSampleDialogue(int channel)
784  */
loadSampleDialogue(int channel)785 void SimpleSynthGui::loadSampleDialogue(int channel)
786 {
787    MusECore::AudioPreviewDialog dlg(this, sampleRate());
788    dlg.setWindowTitle(tr("Load sample dialog"));
789    dlg.setDirectory(lastDir);
790    if(dlg.exec() == QFileDialog::Rejected)
791    {
792       return;
793    }
794 
795    QStringList filenames = dlg.selectedFiles();
796    if(filenames.size() < 1)
797    {
798       return;
799    }
800    QString filename = filenames [0];
801    /*dlg.getOpenFileName(this,
802                        tr("Load sample dialog"),
803                        lastDir,
804                        QString("Samples *.wav *.ogg *.flac (*.wav *.WAV *.ogg *.flac);;All files (*)"));
805 
806    QString filename =
807          QFileDialog::getOpenFileName(
808             this,
809             tr("Load sample dialog"),
810             lastDir,
811             QString("Samples *.wav *.ogg *.flac (*.wav *.WAV *.ogg *.flac);;All files (*)"));
812 */
813    if (!filename.isEmpty()) {
814       QFileInfo fi(filename);
815       lastDir = fi.path();
816 
817       if (SS_DEBUG)
818          printf("lastDir = %s\n", lastDir.toLatin1().constData());
819 
820       //int l = filename.length() + 4;
821       int l = filename.length() + 6;
822       byte d[l];
823 
824       //d[0] = SS_SYSEX_LOAD_SAMPLE;
825       //d[1] = (byte) channel;
826       //d[2] = (byte) filename.length();
827       d[0] = MUSE_SYNTH_SYSEX_MFG_ID;
828       d[1] = SIMPLEDRUMS_UNIQUE_ID;
829       d[2] = SS_SYSEX_LOAD_SAMPLE;
830       d[3] = (byte) channel;
831       d[4] = (byte) filename.length();
832       memcpy(d+5, filename.toLatin1().constData(), filename.length()+1);
833       sendSysex(d, l);
834    }
835 }
836 
837 
838 
839 /*!
840     \fn SimpleSynthGui::clearSample(int ch)
841  */
clearSample(int ch)842 void SimpleSynthGui::clearSample(int ch)
843 {
844    if (sampleNameLineEdit[ch]->text().length() > 0) { //OK, we've got a live one here
845       //byte d[2];
846       byte d[4];
847       //d[0] = SS_SYSEX_CLEAR_SAMPLE;
848       //d[1] = (byte) ch;
849       d[0] = MUSE_SYNTH_SYSEX_MFG_ID;
850       d[1] = SIMPLEDRUMS_UNIQUE_ID;
851       d[2] = SS_SYSEX_CLEAR_SAMPLE;
852       d[3] = (byte) ch;
853       //sendSysex(d, 2);
854       sendSysex(d, 4);
855       sampleNameLineEdit[ch]->setText("");
856    }
857 }
858 
859 /*!
860     \fn SimpleSynthGui::displayPluginGui()
861  */
displayPluginGui()862 void SimpleSynthGui::displayPluginGui()
863 {
864    pluginGui->show();
865 }
866 
867 /*!
868     \fn SimpleSynthGui::loadEffectInvoked(int fxid, QString lib, QString label)
869  */
loadEffectInvoked(int fxid,QString lib,QString label)870 void SimpleSynthGui::loadEffectInvoked(int fxid, QString lib, QString label)
871 {
872    //int l = 4 + lib.length() + label.length();
873    int l = 6 + lib.length() + label.length();
874    byte d[l];
875    //d[0] = SS_SYSEX_LOAD_SENDEFFECT;
876    //d[1] = (byte) fxid;
877    d[0] = MUSE_SYNTH_SYSEX_MFG_ID;
878    d[1] = SIMPLEDRUMS_UNIQUE_ID;
879    d[2] = SS_SYSEX_LOAD_SENDEFFECT;
880    d[3] = (byte) fxid;
881    memcpy (d+4, lib.toLatin1().constData(), lib.length()+1);
882    memcpy (d+5+lib.length(), label.toLatin1().constData(), label.length()+1);
883    sendSysex(d, l);
884 }
885 
886 
887 /*!
888     \fn SimpleSynthGui::returnLevelChanged(int fxid, int val)
889  */
returnLevelChanged(int fxid,int val)890 void SimpleSynthGui::returnLevelChanged(int fxid, int val)
891 {
892    sendController(0, SS_PLUGIN_RETURNLEVEL_CONTROLLER(fxid), val);
893 }
894 
895 
896 /*!
897     \fn SimpleSynthGui::toggleEffectOnOff(int fxid, int state)
898  */
toggleEffectOnOff(int fxid,int state)899 void SimpleSynthGui::toggleEffectOnOff(int fxid, int state)
900 {
901    sendController(0, SS_PLUGIN_ONOFF_CONTROLLER(fxid), state);
902 }
903 
904 
905 /*!
906     \fn SimpleSynthGui::clearPlugin(int fxid)
907  */
clearPlugin(int fxid)908 void SimpleSynthGui::clearPlugin(int fxid)
909 {
910    //byte d[2];
911    byte d[4];
912    //d[0] = SS_SYSEX_CLEAR_SENDEFFECT;
913    //d[1] = fxid;
914    d[0] = MUSE_SYNTH_SYSEX_MFG_ID;
915    d[1] = SIMPLEDRUMS_UNIQUE_ID;
916    d[2] = SS_SYSEX_CLEAR_SENDEFFECT;
917    d[3] = fxid;
918    //sendSysex(d, 2);
919    sendSysex(d, 4);
920 }
921 
922 
923 /*!
924     \fn SimpleSynthGui::effectParameterChanged(int fxid, int parameter, int val)
925  */
effectParameterChanged(int fxid,int parameter,int val)926 void SimpleSynthGui::effectParameterChanged(int fxid, int parameter, int val)
927 {
928    //int len = 4;
929    int len = 6;
930    byte d[len];
931    //d[0] = SS_SYSEX_SET_PLUGIN_PARAMETER;
932    //d[1] = (byte) fxid;
933    //d[2] = (byte) parameter;
934    //d[3] = (byte) val;
935    d[0] = MUSE_SYNTH_SYSEX_MFG_ID;
936    d[1] = SIMPLEDRUMS_UNIQUE_ID;
937    d[2] = SS_SYSEX_SET_PLUGIN_PARAMETER;
938    d[3] = (byte) fxid;
939    d[4] = (byte) parameter;
940    d[5] = (byte) val;
941    sendSysex(d, len);
942 }
943 
944 
945 /*!
946     \fn SimpleSynthGui::openPluginButtonClicked()
947  */
openPluginButtonClicked()948 void SimpleSynthGui::openPluginButtonClicked()
949 {
950    if (pluginGui->isVisible())
951       pluginGui->raise();
952    else
953       displayPluginGui();
954 }
955 
956 
957 /*!
958     \fn SimpleSynthGui::aboutButtonClicked()
959  */
aboutButtonClicked()960 void SimpleSynthGui::aboutButtonClicked()
961 {
962    QString caption = "SimpleDrums ver";
963    caption+= SS_VERSIONSTRING;
964    ///QString text = caption + "\n\n(C) Copyright 2000-2004 Mathias Lundgren (lunar_shuttle@users.sf.net), Werner Schweer\nPublished under the GNU Public License";
965    QString text = caption + "\n\n(C) Copyright 2000-2004 Mathias Lundgren (lunar_shuttle@users.sf.net), Werner Schweer\n"
966                             "Fixes/mods: (C) Copyright 2011 Tim E. Real (terminator356@users.sf.net)\nPublished under the GNU Public License";
967    QMessageBox* msgBox = new QMessageBox(caption, text, QMessageBox::NoIcon,
968                                          QMessageBox::Ok, Qt::NoButton, Qt::NoButton, this);
969    msgBox->exec();
970 }
971 
972 
973 /*!
974     \fn SimpleSynthGui::loadSetup()
975     \brief Load setup from file
976  */
loadSetup()977 void SimpleSynthGui::loadSetup()
978 {
979    bool success = true;
980    QString filename =
981          QFileDialog::getOpenFileName(this, "Load setup dialog", lastProjectDir,
982                                       QString("*.sds *.SDS"));
983 
984    if (!filename.isEmpty()) {
985       QFile theFile(filename);
986       if (theFile.open(QIODevice::ReadOnly)) {
987          unsigned initdata_len = 0;
988          if (theFile.read((char*)&initdata_len, sizeof(initdata_len)) == -1)
989             success = false;
990 
991          ///byte* init_data = new byte[initdata_len];
992          byte* init_data = new byte[initdata_len + 2];   // 2 for MFG ID and synth ID.
993          init_data[0] = MUSE_SYNTH_SYSEX_MFG_ID;
994          init_data[1] = SIMPLEDRUMS_UNIQUE_ID;
995          //if (theFile.read((char*)(init_data), initdata_len) == -1)
996          if (theFile.read((char*)(init_data + 2), initdata_len) == -1)
997             success = false;
998 
999          if (!success) {
1000             QMessageBox* msgBox = new QMessageBox(QMessageBox::Warning, "SimpleDrums Error Dialog", "Error opening/reading from file. Setup not loaded.",
1001                                                   QMessageBox::Ok, this);
1002             msgBox->exec();
1003             delete msgBox;
1004          }
1005          else {
1006             ///sendSysex(init_data, initdata_len);
1007             sendSysex(init_data, initdata_len + 2);
1008          }
1009 
1010          delete[] init_data;
1011       }
1012    }
1013 }
1014 
1015 
1016 /*!
1017     \fn SimpleSynthGui::saveSetup()
1018     \brief Save setup to file
1019  */
saveSetup()1020 void SimpleSynthGui::saveSetup()
1021 {
1022    QString filename =
1023          QFileDialog::getSaveFileName(this, "Save setup dialog", lastProjectDir,
1024                                       QString("*.sds *.SDS"));
1025 
1026    if (!filename.isEmpty()) {
1027       lastSavedProject = filename;
1028       //byte d[1];
1029       byte d[3];
1030       //d[0] = SS_SYSEX_GET_INIT_DATA;
1031       d[0] = MUSE_SYNTH_SYSEX_MFG_ID;
1032       d[1] = SIMPLEDRUMS_UNIQUE_ID;
1033       d[2] = SS_SYSEX_GET_INIT_DATA;
1034       //sendSysex(d, 1); // Makes synth send gui initdata, where rest of the saving takes place
1035       sendSysex(d, 3); // Makes synth send gui initdata, where rest of the saving takes place
1036    }
1037 }
1038 
routeChanged(int index)1039 void SimpleSynthGui::routeChanged(int index)
1040 {
1041    QObject *obj = sender();
1042    int ch = -1;
1043    for(int i = 0; i < SS_NR_OF_CHANNELS; i++)
1044    {
1045       if(chnRoutingCb [i] == obj)
1046       {
1047          ch = i;
1048          break;
1049       }
1050    }
1051    if(ch == -1)
1052    {
1053       return;
1054    }
1055 
1056    fprintf(stderr, "SS: change routing: chn %d -> %d\n", ch, index);
1057 
1058    setChannelRoute(ch, index);
1059 
1060 }
1061 
heartBeat()1062 void SimpleSynthGui::heartBeat()
1063 {
1064    for(int i = 0; i < SS_NR_OF_CHANNELS; i++){
1065       chnMeter[i]->setVal(meterVal[i], peakVal[i], false);
1066       //chnMeter[i]->update();
1067    }
1068 }
1069 
1070