1 /*!
2 * @file seqwidget.cpp
3 * @brief Implements the SeqWidget GUI class.
4 *
5 *
6 * Copyright 2009 - 2017 <qmidiarp-devel@lists.sourceforge.net>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21 * MA 02110-1301, USA.
22 */
23
24 #include <vector>
25
26 #include "seqwidget.h"
27
28 #include "pixmaps/seqrecord.xpm"
29
30
31 #ifdef APPBUILD
SeqWidget(MidiSeq * p_midiSeq,GlobStore * p_globStore,int portCount,bool compactStyle,bool mutedAdd,bool inOutVisible,const QString & p_name)32 SeqWidget::SeqWidget(MidiSeq *p_midiSeq, GlobStore *p_globStore,
33 int portCount, bool compactStyle,
34 bool mutedAdd, bool inOutVisible, const QString& p_name):
35 InOutBox(p_midiSeq, p_globStore, portCount, compactStyle, inOutVisible, p_name),
36 midiSeq(p_midiSeq)
37 {
38 #else
39 SeqWidget::SeqWidget(
40 bool compactStyle,
41 bool mutedAdd, bool inOutVisible):
42 InOutBox(compactStyle, inOutVisible, "Seq:"),
43 midiSeq(NULL)
44 {
45 #endif
46
47 // group box for sequence setup
48 QGroupBox *seqBox = new QGroupBox(tr("Sequence"));
49
50 screen = new SeqScreen;
51 screen->setToolTip(
52 tr("Right button to mute points, left button to draw custom wave"));
53 screen->setMinimumHeight(SEQSCR_MIN_H);
54 connect(screen, SIGNAL(mouseEvent(double, double, int, int)), this,
55 SLOT(mouseEvent(double, double, int, int)));
56
57 cursor = new Cursor('S');
58
59 loopBox = new QComboBox;
60 QStringList names;
61 names.clear();
62 names << "->_>" << " <_<-" << "->_<" << " >_<-" << "->_|" << " |_<-" << "RANDM";
63 loopBox->insertItems(0, names);
64 loopBox->setCurrentIndex(0);
65 loopBox->setToolTip(tr("Loop, bounce or play once going forward or backward"));
66 loopBox->setMinimumContentsLength(5);
67 connect(loopBox, SIGNAL(activated(int)), this,
68 SLOT(updateLoop(int)));
69 #ifdef APPBUILD
70 midiControl->addMidiLearnMenu("LoopMode", loopBox, 6);
71 #endif
72 QLabel *recordButtonLabel = new QLabel(tr("Re&cord"));
73 recordAction = new QAction(QPixmap(seqrecord_xpm), tr("Re&cord"), this);
74 recordAction->setToolTip(tr("Record step by step"));
75 recordAction->setCheckable(true);
76 QToolButton *recordButton = new QToolButton;
77 recordButton->setDefaultAction(recordAction);
78 recordButtonLabel->setBuddy(recordButton);
79 connect(recordAction, SIGNAL(toggled(bool)), this, SLOT(setRecord(bool)));
80 #ifdef APPBUILD
81 midiControl->addMidiLearnMenu("RecordToggle", recordButton, 3);
82 #endif
83
84 QLabel *resBoxLabel = new QLabel(tr("&Resolution"));
85 resBox = new QComboBox;
86 resBoxLabel->setBuddy(resBox);
87 names.clear();
88 names << "1" << "2" << "4" << "8" << "16";
89 resBox->insertItems(0, names);
90 resBox->setCurrentIndex(2);
91 resBoxIndex = 2;
92 resBox->setToolTip(
93 tr("Resolution (notes/beat): Number of notes produced every beat"));
94 resBox->setMinimumContentsLength(3);
95 connect(resBox, SIGNAL(activated(int)), this,
96 SLOT(updateRes(int)));
97 #ifdef APPBUILD
98 midiControl->addMidiLearnMenu("Resolution", resBox, 4);
99 #endif
100
101 QLabel *sizeBoxLabel = new QLabel(tr("&Length"));
102 sizeBox = new QComboBox;
103 sizeBoxLabel->setBuddy(sizeBox);
104 names.clear();
105 names << "1" << "2" << "3" << "4" << "5" << "6" << "7" << "8" << "16" << "32";
106 sizeBox->insertItems(0, names);
107 sizeBox->setCurrentIndex(3);
108 sizeBoxIndex = 3;
109 sizeBox->setToolTip(tr("Length of Sequence in beats"));
110 sizeBox->setMinimumContentsLength(3);
111 connect(sizeBox, SIGNAL(activated(int)), this,
112 SLOT(updateSize(int)));
113 #ifdef APPBUILD
114 midiControl->addMidiLearnMenu("Size", sizeBox, 5);
115 #endif
116
117 dispSignalMapper = new QSignalMapper(this);
118 QLabel *dispLabel[4];
119 QString dispText[4] = {tr("&F"), tr("&U"), tr("&M"), tr("&L")};
120 QString dispToolTip[4] = {tr("Full"), tr("Upper"), tr("Mid"), tr("Lower")};
121
122 QHBoxLayout *dispBoxLayout = new QHBoxLayout;
123
124 dispBoxLayout->addWidget(new QLabel(tr("Display")));
125 dispBoxLayout->addStretch(10);
126 for (int l1 = 0; l1 < 4; l1++) {
127 dispLabel[l1] = new QLabel(dispText[l1]);
128 dispVert[l1] = new QCheckBox;
129 connect(dispVert[l1], SIGNAL(toggled(bool)), dispSignalMapper, SLOT(map()));
130 dispSignalMapper->setMapping(dispVert[l1], l1);
131 dispVert[l1]->setAutoExclusive(true);
132 dispLabel[l1]->setBuddy(dispVert[l1]);
133 dispVert[l1]->setToolTip(dispToolTip[l1]);
134 dispBoxLayout->addWidget(dispLabel[l1]);
135 dispBoxLayout->addWidget(dispVert[l1]);
136 }
137 dispBoxLayout->addStretch();
138
139 dispVert[0]->setChecked(true);
140 dispVertIndex = 0;
141 connect(dispSignalMapper, SIGNAL(mapped(int)),
142 this, SLOT(updateDispVert(int)));
143
144 velocity = new Slider(0, 127, 1, 8, 64, Qt::Horizontal,
145 tr("Veloc&ity"), this);
146 connect(velocity, SIGNAL(valueChanged(int)), this,
147 SLOT(updateVelocity(int)));
148 #ifdef APPBUILD
149 midiControl->addMidiLearnMenu("Velocity", velocity, 1);
150 #endif
151
152 notelength = new Slider(0, 127, 1, 16, 60, Qt::Horizontal,
153 tr("N&ote Length"), this);
154 connect(notelength, SIGNAL(valueChanged(int)), this,
155 SLOT(updateNoteLength(int)));
156 #ifdef APPBUILD
157 midiControl->addMidiLearnMenu("NoteLength", notelength, 2);
158 #endif
159
160 transpose = new Slider(-24, 24, 1, 2, 0, Qt::Horizontal,
161 tr("&Transpose"), this);
162 connect(transpose, SIGNAL(valueChanged(int)), this,
163 SLOT(updateTranspose(int)));
164 #ifdef APPBUILD
165 midiControl->addMidiLearnMenu("Transpose", transpose, 8);
166 #endif
167
168 QGridLayout* sliderLayout = new QGridLayout;
169 sliderLayout->addLayout(dispBoxLayout, 1, 0);
170 sliderLayout->addWidget(velocity, 2, 0);
171 sliderLayout->addWidget(notelength, 3, 0);
172 sliderLayout->addWidget(transpose, 4, 0);
173 sliderLayout->setRowStretch(5, 1);
174 if (compactStyle) {
175 sliderLayout->setSpacing(1);
176 sliderLayout->setMargin(2);
177 }
178
179 QGridLayout *paramBoxLayout = new QGridLayout;
180 paramBoxLayout->addWidget(loopBox, 0, 0, 1, 2);
181 paramBoxLayout->addWidget(muteOut, 1, 0, 1, 1);
182 paramBoxLayout->addWidget(deferChangesButton, 1, 1, 1, 2);
183 paramBoxLayout->addWidget(recordButtonLabel, 2, 0);
184 paramBoxLayout->addWidget(recordButton, 2, 1);
185 paramBoxLayout->addWidget(resBoxLabel, 3, 0);
186 paramBoxLayout->addWidget(resBox, 3, 1);
187 paramBoxLayout->addWidget(sizeBoxLabel, 4, 0);
188 paramBoxLayout->addWidget(sizeBox, 4, 1);
189 paramBoxLayout->setRowStretch(5, 1);
190
191 QGridLayout* seqBoxLayout = new QGridLayout;
192 seqBoxLayout->addWidget(screen, 0, 0, 1, 2);
193 seqBoxLayout->addWidget(cursor, 1, 0, 1, 2);
194 seqBoxLayout->addLayout(paramBoxLayout, 2, 0);
195 seqBoxLayout->addLayout(sliderLayout, 2, 1);
196 if (compactStyle) {
197 seqBoxLayout->setMargin(2);
198 seqBoxLayout->setSpacing(0);
199 }
200 seqBox->setLayout(seqBoxLayout);
201
202 QHBoxLayout *widgetLayout = new QHBoxLayout;
203 widgetLayout->addWidget(seqBox, 1);
204 widgetLayout->addWidget(hideInOutBoxButton, 0);
205 widgetLayout->addWidget(inOutBoxWidget, 0);
206
207 muteOutAction->setChecked(mutedAdd);
208 #ifdef APPBUILD
209 midiControl->addMidiLearnMenu("Out Channel", channelOut, 9);
210 #endif
211
212 setLayout(widgetLayout);
213 recordMode = false;
214 updateVelocity(64);
215 updateWaveForm(0);
216 lastMute = false;
217 modified = false;
218 }
219
220 #ifdef APPBUILD
221 MidiSeq *SeqWidget::getMidiWorker()
222 {
223 return (midiSeq);
224 }
225
226 void SeqWidget::writeData(QXmlStreamWriter& xml)
227 {
228 QByteArray tempArray;
229 int l1;
230
231 writeCommonData(xml);
232
233 xml.writeStartElement("display");
234 xml.writeTextElement("vertical", QString::number(
235 dispVertIndex));
236 xml.writeEndElement();
237
238 xml.writeStartElement("seqParams");
239 xml.writeTextElement("loopmode", QString::number(
240 loopBox->currentIndex()));
241 xml.writeTextElement("resolution", QString::number(
242 resBox->currentIndex()));
243 xml.writeTextElement("size", QString::number(
244 sizeBox->currentIndex()));
245 xml.writeTextElement("velocity", QString::number(
246 midiSeq->vel));
247 xml.writeTextElement("noteLength", QString::number(
248 tickLenToSlider(midiSeq->notelength)));
249 xml.writeTextElement("transp", QString::number(
250 midiSeq->transp));
251 xml.writeEndElement();
252
253 tempArray.clear();
254 l1 = 0;
255 while (l1 < midiSeq->maxNPoints) {
256 tempArray.append(midiSeq->muteMask.at(l1));
257 l1++;
258 }
259 xml.writeStartElement("muteMask");
260 xml.writeTextElement("data", tempArray.toHex());
261 xml.writeEndElement();
262
263 tempArray.clear();
264 l1 = 0;
265 while (l1 < midiSeq->maxNPoints) {
266 tempArray.append(midiSeq->customWave.at(l1).value);
267 l1++;
268 }
269 xml.writeStartElement("sequence");
270 xml.writeTextElement("data", tempArray.toHex());
271 xml.writeTextElement("loopmarker", QString::number(
272 getLoopMarker()));
273 xml.writeEndElement();
274
275 xml.writeEndElement();
276 }
277
278 void SeqWidget::readData(QXmlStreamReader& xml)
279 {
280 int tmp;
281 Sample sample;
282
283 while (!xml.atEnd()) {
284 xml.readNext();
285 if (xml.isEndElement())
286 break;
287
288 readCommonData(xml);
289
290 if (xml.isStartElement() && (xml.name() == "display")) {
291 while (!xml.atEnd()) {
292 xml.readNext();
293 if (xml.isEndElement())
294 break;
295 if (xml.name() == "vertical")
296 setDispVert(xml.readElementText().toInt());
297 else skipXmlElement(xml);
298 }
299 }
300
301 else if (xml.isStartElement() && (xml.name() == "seqParams")) {
302 while (!xml.atEnd()) {
303 xml.readNext();
304 if (xml.isEndElement())
305 break;
306 if (xml.name() == "loopmode") {
307 tmp = xml.readElementText().toInt();
308 loopBox->setCurrentIndex(tmp);
309 updateLoop(tmp);
310 }
311 else if (xml.name() == "resolution") {
312 tmp = xml.readElementText().toInt();
313 resBox->setCurrentIndex(tmp);
314 updateRes(tmp);
315 }
316 else if (xml.name() == "size") {
317 tmp = xml.readElementText().toInt();
318 sizeBox->setCurrentIndex(tmp);
319 updateSize(tmp);
320 }
321 else if (xml.name() == "velocity") {
322 tmp = xml.readElementText().toInt();
323 velocity->setValue(tmp);
324 updateVelocity(tmp);
325 }
326 else if (xml.name() == "noteLength") {
327 notelength->setValue(xml.readElementText().toInt());
328 }
329 else if (xml.name() == "transp") {
330 tmp = xml.readElementText().toInt();
331 transpose->setValue(tmp);
332 updateTranspose(tmp);
333 }
334 else skipXmlElement(xml);
335 }
336 }
337 else if (xml.isStartElement() && (xml.name() == "muteMask")) {
338 while (!xml.atEnd()) {
339 xml.readNext();
340 if (xml.isEndElement())
341 break;
342 if (xml.isStartElement() && (xml.name() == "data")) {
343 QByteArray tmpArray =
344 QByteArray::fromHex(xml.readElementText().toLatin1());
345 for (int l1 = 0; l1 < tmpArray.count(); l1++) {
346 midiSeq->muteMask[l1] = tmpArray.at(l1);
347 }
348 midiSeq->maxNPoints = tmpArray.count();
349 }
350 else skipXmlElement(xml);
351 }
352 }
353 else if (xml.isStartElement() && (xml.name() == "sequence")) {
354 while (!xml.atEnd()) {
355 xml.readNext();
356 if (xml.isEndElement())
357 break;
358 if (xml.isStartElement() && (xml.name() == "data")) {
359 QByteArray tmpArray =
360 QByteArray::fromHex(xml.readElementText().toLatin1());
361 int step = TPQN / midiSeq->res;
362 int lt = 0;
363 for (int l1 = 0; l1 < tmpArray.count(); l1++) {
364 sample.value = tmpArray.at(l1);
365 sample.tick = lt;
366 sample.muted = midiSeq->muteMask[l1];
367 midiSeq->customWave[l1] = sample;
368 lt+=step;
369 }
370 updateWaveForm(0);
371 }
372 else if (xml.name() == "loopmarker") {
373 tmp = xml.readElementText().toInt();
374 midiSeq->setLoopMarker(tmp);
375 screen->setLoopMarker(tmp);
376 }
377 else skipXmlElement(xml);
378 }
379 }
380 else skipXmlElement(xml);
381 }
382
383 updateChIn(chIn->currentIndex());
384 updateChannelOut(channelOut->currentIndex());
385 updatePortOut(portOut->currentIndex());
386 midiSeq->needsGUIUpdate = false;
387 modified = false;
388 }
389 #endif
390
391 void SeqWidget::updateNoteLength(int val)
392 {
393 if (midiSeq) midiSeq->updateNoteLength(sliderToTickLen(val));
394 modified = true;
395 }
396
397 void SeqWidget::updateWaveForm(int val)
398 {
399 (void)val;
400 modified = true;
401 if (!midiSeq) return;
402 std::vector<Sample> sdata;
403 midiSeq->getData(&sdata);
404 data=QVector<Sample>::fromStdVector(sdata);
405 screen->updateData(data);
406 }
407
408 void SeqWidget::setRecord(bool on)
409 {
410 recordMode = on;
411 screen->setRecordMode(on);
412 if (!midiSeq) return;
413 midiSeq->setRecordMode(on);
414 screen->setCurrentRecStep(midiSeq->currentRecStep);
415 }
416
417 void SeqWidget::updateRes(int val)
418 {
419 if (val > 4) return;
420 resBoxIndex = val;
421 modified = true;
422 if (!midiSeq) return;
423 midiSeq->res = seqResValues[val];
424 midiSeq->resizeAll();
425 std::vector<Sample> sdata;
426 midiSeq->getData(&sdata);
427 data=QVector<Sample>::fromStdVector(sdata);
428 screen->setCurrentRecStep(midiSeq->currentRecStep);
429 screen->updateData(data);
430 }
431
432 void SeqWidget::updateSize(int val)
433 {
434 if (val > 9) return;
435 sizeBoxIndex = val;
436 modified = true;
437 if (!midiSeq) return;
438 midiSeq->size = sizeBox->currentText().toInt();
439 midiSeq->resizeAll();
440 std::vector<Sample> sdata;
441 midiSeq->getData(&sdata);
442 data=QVector<Sample>::fromStdVector(sdata);
443 screen->setCurrentRecStep(midiSeq->currentRecStep);
444 screen->updateData(data);
445 }
446
447 void SeqWidget::updateLoop(int val)
448 {
449 if (val > 6) return;
450 if (midiSeq) midiSeq->updateLoop(val);
451 modified = true;
452 }
453
454 void SeqWidget::updateVelocity(int val)
455 {
456 if (midiSeq) midiSeq->updateVelocity(val);
457 modified = true;
458 }
459
460 void SeqWidget::updateTranspose(int val)
461 {
462 if (midiSeq) midiSeq->updateTranspose(val);
463 modified = true;
464 }
465
466 void SeqWidget::mouseEvent(double mouseX, double mouseY, int buttons, int pressed)
467 {
468 if (!midiSeq) {
469 emit mouseSig(mouseX, mouseY, buttons, pressed);
470 }
471 else {
472 midiSeq->mouseEvent(mouseX, mouseY, buttons, pressed);
473 }
474
475 if ((mouseY < 0) && (pressed != 2)) { // we have to recalculate loopMarker for screen update
476 if (mouseX < 0) mouseX = 0;
477 if (buttons == 2) mouseX = - mouseX;
478 const int npoints = data.count() - 1;
479 int lm;
480 if (mouseX > 0) lm = mouseX * (double)npoints + .5;
481 else lm = mouseX * (double)npoints - .5;
482 if (abs(lm) >= npoints) lm = 0;
483 screen->setLoopMarker(lm);
484 screen->updateDraw();
485 }
486 modified = true;
487 }
488
489 void SeqWidget::setDispVert(int mode)
490 {
491 dispVert[mode]->setChecked(true);
492 }
493
494 void SeqWidget::updateDispVert(int mode)
495 {
496 dispVertIndex = mode;
497 if (midiSeq) midiSeq->updateDispVert(mode);
498 screen->updateDispVert(mode);
499 modified = true;
500 }
501
502 #ifdef APPBUILD
503
504 void SeqWidget::doStoreParams(int ix)
505 {
506 parStore->temp.res = resBox->currentIndex();
507 parStore->temp.size = sizeBox->currentIndex();
508 parStore->temp.loopMode = loopBox->currentIndex();
509 parStore->temp.notelen = notelength->value();
510 parStore->temp.transp = transpose->value();
511 parStore->temp.vel = velocity->value();
512 parStore->temp.dispVertIndex = dispVertIndex;
513 parStore->temp.loopMode = loopBox->currentIndex();
514 parStore->temp.wave = getCustomWave().mid(0, midiSeq->maxNPoints);
515 parStore->temp.muteMask = getMuteMask().mid(0, midiSeq->maxNPoints);
516 parStore->temp.loopMarker = getLoopMarker();
517
518 parStore->tempToList(ix);
519 }
520
521 void SeqWidget::doRestoreParams(int ix)
522 {
523 midiSeq->applyPendingParChanges();
524 if (parStore->list.at(ix).empty) return;
525 for (int l1 = 0; l1 < parStore->list.at(ix).wave.count(); l1++) {
526 midiSeq->customWave[l1] = parStore->list.at(ix).wave.at(l1);
527 midiSeq->muteMask[l1] = parStore->list.at(ix).muteMask.at(l1);
528 }
529 sizeBoxIndex = parStore->list.at(ix).size;
530 sizeBox->setCurrentIndex(sizeBoxIndex);
531 midiSeq->size = sizeBox->currentText().toInt();
532 resBoxIndex = parStore->list.at(ix).res;
533 midiSeq->res = seqResValues[resBoxIndex];
534 midiSeq->resizeAll();
535 midiSeq->setLoopMarker(parStore->list.at(ix).loopMarker);
536 screen->setLoopMarker(parStore->list.at(ix).loopMarker);
537
538 resBox->setCurrentIndex(parStore->list.at(ix).res);
539 loopBox->setCurrentIndex(parStore->list.at(ix).loopMode);
540 if (!parStore->onlyPatternList.at(ix)) {
541 midiSeq->notelength = sliderToTickLen(parStore->list.at(ix).notelen);
542 midiSeq->transp = parStore->list.at(ix).transp;
543 midiSeq->vel = parStore->list.at(ix).vel;
544 setDispVert(parStore->list.at(ix).dispVertIndex);
545 }
546 updateLoop(parStore->list.at(ix).loopMode);
547 updateWaveForm(parStore->list.at(ix).waveForm);
548 midiSeq->setFramePtr(0);
549
550 needsGUIUpdate = true;
551 }
552
553 void SeqWidget::copyParamsFrom(SeqWidget *fromWidget)
554 {
555 int tmp;
556 setDispVert(fromWidget->dispVertIndex);
557 enableNoteIn->setChecked(fromWidget->enableNoteIn->isChecked());
558 enableNoteOff->setChecked(fromWidget->enableNoteOff->isChecked());
559 enableVelIn->setChecked(fromWidget->enableVelIn->isChecked());
560 enableRestartByKbd->setChecked(fromWidget->enableRestartByKbd->isChecked());
561 enableTrigByKbd->setChecked(fromWidget->enableTrigByKbd->isChecked());
562 enableTrigLegato->setChecked(fromWidget->enableTrigLegato->isChecked());
563
564 for (int l1 = 0; l1 < 1; l1++) {
565 tmp = fromWidget->indexIn[l1]->value();
566 indexIn[l1]->setValue(tmp);
567 }
568 for (int l1 = 0; l1 < 1; l1++) {
569 tmp = fromWidget->rangeIn[l1]->value();
570 rangeIn[l1]->setValue(tmp);
571 }
572 tmp = fromWidget->chIn->currentIndex();
573 chIn->setCurrentIndex(tmp);
574 updateChIn(tmp);
575 tmp = fromWidget->channelOut->currentIndex();
576 channelOut->setCurrentIndex(tmp);
577 updateChannelOut(tmp);
578 tmp = fromWidget->portOut->currentIndex();
579 portOut->setCurrentIndex(tmp);
580 updatePortOut(tmp);
581
582 tmp = fromWidget->resBox->currentIndex();
583 resBox->setCurrentIndex(tmp);
584 updateRes(tmp);
585 tmp = fromWidget->sizeBox->currentIndex();
586 sizeBox->setCurrentIndex(tmp);
587 updateSize(tmp);
588 tmp = fromWidget->loopBox->currentIndex();
589 loopBox->setCurrentIndex(tmp);
590 updateLoop(tmp);
591
592 tmp = fromWidget->velocity->value();
593 updateVelocity(tmp);
594 velocity->setValue(tmp);
595 tmp = fromWidget->transpose->value();
596 updateTranspose(tmp);
597 transpose->setValue(tmp);
598
599 notelength->setValue(fromWidget->notelength->value());
600 for (int l1 = 0; l1 < fromWidget->getMidiWorker()->maxNPoints; l1++) {
601 midiSeq->customWave[l1] = fromWidget->getCustomWave().at(l1);
602 midiSeq->muteMask[l1] = midiSeq->customWave.at(l1).muted;
603 }
604 tmp = fromWidget->getLoopMarker();
605 midiSeq->setLoopMarker(tmp);
606 screen->setLoopMarker(tmp);
607 midiControl->setCcList(fromWidget->midiControl->ccList);
608 muteOutAction->setChecked(true);
609 updateWaveForm(0);
610 }
611
612 QVector<Sample> SeqWidget::getCustomWave()
613 {
614 return QVector<Sample>::fromStdVector(midiSeq->customWave);
615 }
616
617 QVector<bool> SeqWidget::getMuteMask()
618 {
619 return QVector<bool>::fromStdVector(midiSeq->muteMask);
620 }
621
622 void SeqWidget::handleController(int ccnumber, int channel, int value)
623 {
624 QVector<MidiCC> cclist= midiControl->ccList;
625
626 for (int l2 = 0; l2 < cclist.count(); l2++) {
627 int min = cclist.at(l2).min;
628 int max = cclist.at(l2).max;
629 if ((ccnumber == cclist.at(l2).ccnumber) &&
630 (channel == cclist.at(l2).channel)) {
631 int sval = 0;
632 bool m = false;
633 switch (cclist.at(l2).ID) {
634 case 0: if (min == max) {
635 if (value == max) {
636 m = midiSeq->isMuted;
637 midiSeq->setMuted(!m);
638 }
639 }
640 else {
641 if (value == max) {
642 midiSeq->setMuted(false);
643 }
644 if (value == min) {
645 midiSeq->setMuted(true);
646 }
647 }
648 break;
649
650 case 1:
651 sval = min + ((double)value * (max - min) / 127);
652 midiSeq->updateVelocity(sval);
653 break;
654
655 case 2:
656 sval = min + ((double)value * (max - min) / 127);
657 midiSeq->updateNoteLength(sliderToTickLen(sval));
658 break;
659
660 case 3: if (min == max) {
661 if (value == max) {
662 m = midiSeq->recordMode;
663 midiSeq->setRecordMode(!m);
664 return;
665 }
666 }
667 else {
668 if (value == max) {
669 midiSeq->setRecordMode(true);
670 }
671 if (value == min) {
672 midiSeq->setRecordMode(false);
673 }
674 }
675 break;
676 case 4:
677 sval = min + ((double)value * (max - min) / 127);
678 if (sval < 5) resBoxIndex = sval;
679 break;
680 case 5:
681 sval = min + ((double)value * (max - min) / 127);
682 if (sval < 8) sizeBoxIndex = sval;
683 break;
684 case 6:
685 sval = min + ((double)value * (max - min) / 127);
686 if (sval < 6) midiSeq->curLoopMode = sval;
687 break;
688 case 7:
689 sval = min + ((double)value * (max - min) / 127);
690 if ((sval < parStore->list.count())
691 && (sval != parStore->activeStore)
692 && (sval != parStore->currentRequest)) {
693 parStore->requestDispState(sval, 2);
694 parStore->restoreRequest = sval;
695 parStore->restoreRunOnce = (parStore->jumpToList.at(sval) > -2);
696 }
697 else return;
698 break;
699
700 case 8:
701 sval = min + ((double)value * (max - min) / 127);
702 midiSeq->updateTranspose(sval - 24);
703 break;
704
705 case 9:
706 sval = min + ((double)value * (max - min) / 127);
707 if (sval < 16) midiSeq->channelOut = sval;
708 break;
709
710 default:
711 break;
712 }
713 needsGUIUpdate = true;
714 }
715 }
716 }
717
718 void SeqWidget::updateDisplay()
719 {
720 QVector<Sample> data;
721 std::vector<Sample> sdata;
722
723 parStore->updateDisplay(getFramePtr(), midiSeq->reverse);
724
725 if (dataChanged || midiSeq->dataChanged) {
726 dataChanged=false;
727 midiSeq->dataChanged=false;
728 midiSeq->getData(&sdata);
729 data = QVector<Sample>::fromStdVector(sdata);
730 screen->updateData(data);
731 if (recordMode) screen->setCurrentRecStep(midiSeq->currentRecStep);
732 cursor->updateNumbers(midiSeq->res, midiSeq->size);
733 }
734 screen->updateDraw();
735 cursor->updateDraw();
736 midiControl->update();
737
738 if (!(needsGUIUpdate || midiSeq->needsGUIUpdate)) return;
739
740 transpose->setValue(midiSeq->transp);
741 notelength->setValue(tickLenToSlider(midiSeq->notelength));
742 velocity->setValue(midiSeq->vel);
743 muteOut->setChecked(midiSeq->isMuted);
744 screen->newGrooveValues(midiSeq->newGrooveTick, midiSeq->grooveVelocity,
745 midiSeq->grooveLength);
746 screen->setMuted(midiSeq->isMuted);
747 parStore->ndc->setMuted(midiSeq->isMuted);
748 recordAction->setChecked(midiSeq->recordMode);
749 resBox->setCurrentIndex(resBoxIndex);
750 updateRes(resBoxIndex);
751 sizeBox->setCurrentIndex(sizeBoxIndex);
752 updateSize(sizeBoxIndex);
753 loopBox->setCurrentIndex(midiSeq->curLoopMode);
754 channelOut->setCurrentIndex(midiSeq->channelOut);
755 needsGUIUpdate = false;
756 midiSeq->needsGUIUpdate = false;
757 }
758
759 #endif
760