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