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