1
//=========================================================
4
// $Id: editevent.cpp,v 1.12.2.6 2009/02/02 21:38:00 terminator356 Exp $
5
// (C) Copyright 1999-2004 Werner Schweer (ws@seh.de)
7
// This program is free software; you can redistribute it and/or
8
// modify it under the terms of the GNU General Public License
9
// as published by the Free Software Foundation; version 2 of
10
// the License, or (at your option) any later version.
12
// This program is distributed in the hope that it will be useful,
13
// but WITHOUT ANY WARRANTY; without even the implied warranty of
14
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
// GNU General Public License for more details.
17
// You should have received a copy of the GNU General Public License
18
// along with this program; if not, write to the Free Software
19
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21
//=========================================================
26
#include <QHBoxLayout>
27
#include <QGridLayout>
29
#include <QListWidget>
31
#include <QMessageBox>
32
#include <QPushButton>
33
#include <QRadioButton>
37
#include <QVBoxLayout>
39
#include "awl/posedit.h"
44
#include "editevent.h"
45
#include "pitchedit.h"
48
///#include "posedit.h"
51
#include "midiedit/drummap.h"
52
#include "instruments/minstrument.h"
54
#include "popupmenu.h"
58
//---------------------------------------------------------
60
//---------------------------------------------------------
62
QString string2hex(const unsigned char* data, int len)
66
for (int i = 0; i < len; ++i) {
67
if ((i > 0) && ((i % 8)==0)) {
72
d += s.sprintf("%02x", data[i]);
77
//---------------------------------------------------------
79
//---------------------------------------------------------
81
char* hex2string(QWidget* parent, const char* src, int& len)
87
while (*src == ' ' || *src == '\n')
90
long val = strtol(src, &ep, 16);
92
QMessageBox::information(parent,
94
QWidget::tr("Cannot convert sysex string"));
99
if (dst - buffer >= 2048) {
100
QMessageBox::information(parent,
102
QWidget::tr("Hex String too long (2048 bytes limit)"));
109
char* b = new char[len+1];
110
memcpy(b, buffer, len);
115
//---------------------------------------------------------
117
//---------------------------------------------------------
119
MusECore::Event EditNoteDialog::getEvent(int tick, const MusECore::Event& event, QWidget* parent)
121
EditNoteDialog* dlg = new EditNoteDialog(tick, event, parent);
122
MusECore::Event nevent;
123
if (dlg->exec() == QDialog::Accepted) {
124
nevent = dlg->event();
130
MusECore::Event EditSysexDialog::getEvent(int tick, const MusECore::Event& event, QWidget* parent)
132
EditSysexDialog* dlg = new EditSysexDialog(tick, event, parent);
133
MusECore::Event nevent;
134
if (dlg->exec() == QDialog::Accepted) {
135
nevent = dlg->event();
141
MusECore::Event EditMetaDialog::getEvent(int tick, const MusECore::Event& event, QWidget* parent)
143
EditEventDialog* dlg = new EditMetaDialog(tick, event, parent);
144
MusECore::Event nevent;
145
if (dlg->exec() == QDialog::Accepted) {
146
nevent = dlg->event();
152
MusECore::Event EditCAfterDialog::getEvent(int tick, const MusECore::Event& event, QWidget* parent)
154
EditEventDialog* dlg = new EditCAfterDialog(tick, event, parent);
155
MusECore::Event nevent;
156
if (dlg->exec() == QDialog::Accepted) {
157
nevent = dlg->event();
163
MusECore::Event EditPAfterDialog::getEvent(int tick, const MusECore::Event& event, QWidget* parent)
165
EditEventDialog* dlg = new EditPAfterDialog(tick, event, parent);
166
MusECore::Event nevent;
167
if (dlg->exec() == QDialog::Accepted) {
168
nevent = dlg->event();
174
//---------------------------------------------------------
176
//---------------------------------------------------------
178
EditEventDialog::EditEventDialog(QWidget* parent)
181
QVBoxLayout* xlayout = new QVBoxLayout;
182
layout1 = new QGridLayout; // ddskrjo this
183
xlayout->addLayout(layout1);
185
//---------------------------------------------------
187
//---------------------------------------------------
189
QBoxLayout* w5 = new QHBoxLayout; // ddskrjo this
190
QPushButton* okB = new QPushButton(tr("Ok"));
191
okB->setDefault(true);
192
QPushButton* cancelB = new QPushButton(tr("Cancel"));
193
okB->setFixedWidth(80);
194
cancelB->setFixedWidth(80);
197
w5->addWidget(cancelB);
199
xlayout->addLayout(w5);
201
connect(cancelB, SIGNAL(clicked()), SLOT(reject()));
202
connect(okB, SIGNAL(clicked()), SLOT(accept()));
205
//---------------------------------------------------------
207
//---------------------------------------------------------
209
EditNoteDialog::EditNoteDialog(int tick, const MusECore::Event& event,
214
if (!event.empty()) {
215
epos->setValue(tick);
216
il1->setValue(event.lenTick());
217
pl->setValue(event.pitch());
218
il2->setValue(event.velo());
219
il3->setValue(event.veloOff());
222
epos->setValue(tick);
230
//---------------------------------------------------------
231
// EditNoteDialog::event
232
//---------------------------------------------------------
234
MusECore::Event EditNoteDialog::event()
236
MusECore::Event event(MusECore::Note);
237
event.setTick(epos->pos().tick());
238
event.setA(pl->value());
239
event.setB(il2->value());
240
event.setC(il3->value());
241
event.setLenTick(il1->value());
245
//---------------------------------------------------------
247
//---------------------------------------------------------
249
EditSysexDialog::EditSysexDialog(int tick, const MusECore::Event& event,
255
if (!event.empty()) {
256
epos->setValue(tick);
257
edit->setText(string2hex(event.data(), event.dataLen()));
260
epos->setValue(tick);
264
//---------------------------------------------------------
266
//---------------------------------------------------------
268
EditSysexDialog::~EditSysexDialog()
274
//---------------------------------------------------------
275
// EditSysExDialog::event
276
//---------------------------------------------------------
278
MusECore::Event EditSysexDialog::event()
280
MusECore::Event event(MusECore::Sysex);
281
event.setTick(epos->pos().tick());
282
event.setData(sysex, len);
286
//---------------------------------------------------------
288
//---------------------------------------------------------
290
void EditSysexDialog::accept()
292
QString qsrc = edit->toPlainText();
293
QByteArray ba = qsrc.toLatin1();
294
const char* src = ba.constData();
296
sysex = (unsigned char*)hex2string(this, src, len);
301
//---------------------------------------------------------
303
//---------------------------------------------------------
305
EditMetaDialog::EditMetaDialog(int tick, const MusECore::Event& ev,
307
: EditEventDialog(parent)
310
setWindowTitle(tr("MusE: Enter Meta Event"));
312
QLabel* l1 = new QLabel(tr("Time Position"));
313
///epos = new PosEdit;
314
epos = new Awl::PosEdit;
316
QLabel* l2 = new QLabel(tr("Meta Type"));
317
il2 = new MusEGui::IntLabel(-1, 0, 127, this, -1);
318
il2->setFixedWidth(100);
321
typeLabel = new QLabel;
322
typeLabel->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
323
QHBoxLayout* typeLayout = new QHBoxLayout;
324
typeLayout->addWidget(il2);
325
typeLayout->addWidget(typeLabel);
326
typeLayout->addStretch();
328
hexButton = new QRadioButton(tr("Enter Hex"));
329
hexButton->setChecked(true);
330
connect(hexButton, SIGNAL(toggled(bool)), SLOT(toggled(bool)));
332
edit = new QTextEdit;
333
edit->setFont(MusEGlobal::config.fonts[0]);
336
epos->setValue(tick);
337
il2->setValue(ev.dataA());
339
edit->setText(string2hex(ev.data(), ev.dataLen()));
342
epos->setValue(tick);
346
typeChanged(il2->value());
347
connect(il2, SIGNAL(valueChanged(int)), SLOT(typeChanged(int)));
349
layout1->addWidget(l1, 0, 0);
350
layout1->addWidget(epos, 0, 1, Qt::AlignLeft);
351
layout1->addWidget(l2, 1, 0);
353
//layout1->addWidget(il2, 1, 1, AlignLeft);
354
layout1->addLayout(typeLayout, 1, 1);
356
//layout1->addMultiCellWidget(hexButton, 2, 2, 0, 1);
357
//layout1->addMultiCellWidget(edit, 3, 3, 0, 1);
358
layout1->addWidget(hexButton, 2, 0, 1, 2);
359
layout1->addWidget(edit, 3, 0, 1, 2);
362
//---------------------------------------------------------
364
//---------------------------------------------------------
366
void EditMetaDialog::typeChanged(int val)
368
typeLabel->setText(MusECore::midiMetaName(val));
371
//---------------------------------------------------------
373
//---------------------------------------------------------
375
void EditMetaDialog::toggled(bool flag)
377
QString qsrc = edit->toPlainText();
378
QByteArray ba = qsrc.toLatin1();
379
const char* src = ba.constData();
383
if (flag) { // convert to hex
384
dst = string2hex((unsigned char*)src, strlen(src));
386
else { // convert to string
388
dst = hex2string(this, src, len);
393
//---------------------------------------------------------
395
//---------------------------------------------------------
397
EditMetaDialog::~EditMetaDialog()
403
//---------------------------------------------------------
404
// EditMetaDialog::event
405
//---------------------------------------------------------
407
MusECore::Event EditMetaDialog::event()
409
MusECore::Event event(MusECore::Meta);
410
event.setTick(epos->pos().tick());
411
event.setA(il2->value());
412
event.setData(meta, len); // TODO ??
416
//---------------------------------------------------------
418
//---------------------------------------------------------
420
void EditMetaDialog::accept()
422
QString qsrc = edit->toPlainText();
423
QByteArray ba = qsrc.toLatin1();
424
const char* src = ba.constData();
425
if (!hexButton->isChecked()) {
426
meta = (unsigned char*)strdup(src);
432
meta = (unsigned char*)hex2string(this, src, len);
437
//---------------------------------------------------------
439
//---------------------------------------------------------
441
EditCAfterDialog::EditCAfterDialog(int tick, const MusECore::Event& event,
443
: EditEventDialog(parent)
445
setWindowTitle(tr("MusE: Enter Channel Aftertouch"));
447
QLabel* l1 = new QLabel(tr("Time Position"));
448
///epos = new PosEdit;
449
epos = new Awl::PosEdit;
451
QLabel* l2 = new QLabel(tr("Pressure"));
452
il2 = new MusEGui::IntLabel(-1, 0, 127, this, -1);
456
QSlider* slider = new QSlider(Qt::Horizontal);
457
slider->setMinimum(0);
458
slider->setMaximum(127);
459
slider->setPageStep(1);
462
connect(slider, SIGNAL(valueChanged(int)), il2, SLOT(setValue(int)));
463
connect(il2, SIGNAL(valueChanged(int)), slider, SLOT(setValue(int)));
465
if (!event.empty()) {
466
epos->setValue(tick);
467
il2->setValue(event.dataA());
468
slider->setValue(event.dataA());
471
epos->setValue(tick);
473
slider->setValue(64);
476
layout1->addWidget(l1, 0, 0);
477
layout1->addWidget(epos, 0, 1, Qt::AlignLeft);
478
layout1->addWidget(l2, 1, 0);
479
layout1->addWidget(il2, 1, 1, Qt::AlignLeft);
480
//layout1->addMultiCellWidget(slider, 2, 2, 0, 1);
481
layout1->addWidget(slider, 2, 0, 1, 2);
484
//---------------------------------------------------------
485
// EditCAfterDialog::event
486
//---------------------------------------------------------
488
MusECore::Event EditCAfterDialog::event()
490
MusECore::Event event(MusECore::CAfter);
491
event.setTick(epos->pos().tick());
492
event.setA(il2->value());
496
//---------------------------------------------------------
498
//---------------------------------------------------------
500
EditPAfterDialog::EditPAfterDialog(int tick, const MusECore::Event& event,
502
: EditEventDialog(parent)
504
setWindowTitle(tr("MusE: Enter Poly Aftertouch"));
506
QLabel* l1 = new QLabel(tr("Time Position"));
507
///epos = new PosEdit;
508
epos = new Awl::PosEdit;
510
QLabel* l2 = new QLabel(tr("Pitch"));
511
pl = new MusEGui::PitchEdit;
512
QLabel* l3 = new QLabel(tr("Pressure"));
513
il2 = new MusEGui::IntLabel(-1, 0, 127, this, -1);
517
QSlider* slider = new QSlider(Qt::Horizontal);
518
slider->setMinimum(0);
519
slider->setMaximum(127);
520
slider->setPageStep(1);
523
connect(slider, SIGNAL(valueChanged(int)), il2, SLOT(setValue(int)));
524
connect(il2, SIGNAL(valueChanged(int)), slider, SLOT(setValue(int)));
526
if (!event.empty()) {
527
epos->setValue(tick);
528
pl->setValue(event.pitch());
529
il2->setValue(event.dataB());
530
slider->setValue(event.dataB());
533
epos->setValue(tick);
536
slider->setValue(64);
539
layout1->addWidget(l1, 0, 0);
540
layout1->addWidget(epos, 0, 1, Qt::AlignLeft);
541
layout1->addWidget(l2, 1, 0);
542
layout1->addWidget(pl, 1, 1, Qt::AlignLeft);
543
layout1->addWidget(l3, 2, 0);
544
layout1->addWidget(il2, 2, 1, Qt::AlignLeft);
545
//layout1->addMultiCellWidget(slider, 3, 3, 0, 1);
546
layout1->addWidget(slider, 3, 0, 1, 2);
549
//---------------------------------------------------------
550
// EditPAfterDialog::event
551
//---------------------------------------------------------
553
MusECore::Event EditPAfterDialog::event()
555
MusECore::Event event(MusECore::PAfter);
556
event.setTick(epos->pos().tick());
557
event.setA(pl->value());
558
event.setB(il2->value());
561
//---------------------------------------------------------
563
//---------------------------------------------------------
565
MusECore::Event EditCtrlDialog::getEvent(int tick, const MusECore::Event& event,
566
const MusECore::MidiPart* part, QWidget* parent)
568
EditCtrlDialog* dlg = new EditCtrlDialog(tick, event, part, parent);
569
MusECore::Event nevent;
570
if (dlg->exec() == QDialog::Accepted) {
571
nevent = dlg->event();
577
//---------------------------------------------------------
578
// EditCtrlDialog::event
579
//---------------------------------------------------------
581
MusECore::Event EditCtrlDialog::event()
583
MusECore::Event event(MusECore::Controller);
584
event.setTick(timePos->pos().tick());
586
if (num == MusECore::CTRL_PROGRAM)
589
event.setB(valSlider->value() + MusEGlobal::midiPorts[part->track()->outPort()].midiController(num)->bias());
593
//---------------------------------------------------------
596
// QSlider* valSlider;
597
// QSpinBox* valSpinBox;
598
// QLabel* controllerName;
599
// QListWidget* ctrlList;
600
// QPushButton* buttonNewController;
601
//---------------------------------------------------------
603
EditCtrlDialog::EditCtrlDialog(int tick, const MusECore::Event& event,
604
const MusECore::MidiPart* p, QWidget* parent)
605
: QDialog(parent), part(p)
608
widgetStack->setAutoFillBackground(true);
611
if (!event.empty()) {
616
///pop = new QMenu(this);
617
//pop->setCheckable(false);//not necessary in Qt4
619
MusECore::MidiTrack* track = part->track();
620
int portn = track->outPort();
621
MusECore::MidiPort* port = &MusEGlobal::midiPorts[portn];
622
bool isDrum = track->type() == MusECore::Track::DRUM;
623
MusECore::MidiCtrlValListList* cll = port->controller();
626
ctrlList->setSelectionMode(QAbstractItemView::SingleSelection);
629
// populate list of available controller
632
std::list<QString> sList;
633
typedef std::list<QString>::iterator isList;
635
for (MusECore::iMidiCtrlValList i = cll->begin(); i != cll->end(); ++i) {
636
MusECore::MidiCtrlValList* cl = i->second;
639
// dont show drum specific controller if not a drum track
640
if ((num & 0xff) == 0xff) {
644
MusECore::MidiController* c = port->midiController(num);
645
isList i = sList.begin();
646
for (; i != sList.end(); ++i) {
650
if (i == sList.end())
651
sList.push_back(c->name());
653
MusECore::MidiController* mc = port->midiController(num);
655
int selectionIndex = 0;
656
for (isList i = sList.begin(); i != sList.end(); ++i, ++idx) {
657
ctrlList->addItem(*i);
658
if (mc->name() == *i)
659
selectionIndex = idx;
661
ctrlList->item(selectionIndex)->setSelected(true);
663
valSlider->setRange(mc->minVal(), mc->maxVal());
664
valSpinBox->setRange(mc->minVal(), mc->maxVal());
666
controllerName->setText(mc->name());
670
if(num == MusECore::CTRL_PROGRAM)
672
widgetStack->setCurrentIndex(1);
677
widgetStack->setCurrentIndex(0);
678
valSlider->setValue(val - mc->bias());
682
ctrlListClicked(ctrlList->selectedItems()[0]);
683
connect(ctrlList, SIGNAL(itemClicked(QListWidgetItem*)), SLOT(ctrlListClicked(QListWidgetItem*)));
684
connect(buttonNewController, SIGNAL(clicked()), SLOT(newController()));
685
connect(hbank, SIGNAL(valueChanged(int)), SLOT(programChanged()));
686
connect(lbank, SIGNAL(valueChanged(int)), SLOT(programChanged()));
687
connect(program, SIGNAL(valueChanged(int)), SLOT(programChanged()));
688
connect(patchName, SIGNAL(released()), SLOT(instrPopup()));
689
connect(buttonCancel, SIGNAL(clicked()), SLOT(reject()));
690
connect(buttonOk, SIGNAL(clicked()), SLOT(accept()));
691
timePos->setValue(tick);
694
//---------------------------------------------------------
696
//---------------------------------------------------------
698
void EditCtrlDialog::newController()
700
//QMenu* pup = new QMenu(this);
701
MusEGui::PopupMenu* pup = new MusEGui::PopupMenu(this);
702
//pup->setCheckable(this);//not necessary in Qt4
704
// populate popup with all controllers available for
705
// current instrument
707
MusECore::MidiTrack* track = part->track();
708
int portn = track->outPort();
709
MusECore::MidiPort* port = &MusEGlobal::midiPorts[portn];
710
MusECore::MidiInstrument* instr = port->instrument();
711
MusECore::MidiControllerList* mcl = instr->controller();
713
MusECore::MidiCtrlValListList* cll = port->controller();
714
int channel = track->outChannel();
716
for (MusECore::iMidiController ci = mcl->begin(); ci != mcl->end(); ++ci)
718
if(cll->find(channel, ci->second->num()) == cll->end())
720
QAction* act = pup->addAction(ci->second->name());
725
QAction* rv = pup->exec(buttonNewController->mapToGlobal(QPoint(0,0)));
727
QString s = rv->text();
728
for (MusECore::iMidiController ci = mcl->begin(); ci != mcl->end(); ++ci) {
729
MusECore::MidiController* mc = ci->second;
730
if (mc->name() == s) {
731
if(cll->find(channel, mc->num()) == cll->end())
733
MusECore::MidiCtrlValList* vl = new MusECore::MidiCtrlValList(mc->num());
734
cll->add(channel, vl);
735
//MusEGlobal::song->update(SC_MIDI_CONTROLLER_ADD);
737
//for (int idx = 0; ;++idx) {
739
for (; idx < ctrlList->count() ;++idx) { // p4.0.25 Fix segfault
740
QString str = ctrlList->item(idx)->text();
743
ctrlList->item(idx)->setSelected(true);
744
ctrlListClicked(ctrlList->item(idx));
747
//if (str.isNull()) {
748
// ctrlList->addItem(s);
749
// ctrlList->item(idx)->setSelected(true);
750
// ctrlListClicked(ctrlList->item(idx));
754
if (idx >= ctrlList->count()) { // p4.0.25 Fix segfault
755
ctrlList->addItem(s);
756
ctrlList->item(idx)->setSelected(true);
757
ctrlListClicked(ctrlList->item(idx));
768
//---------------------------------------------------------
770
//---------------------------------------------------------
772
void EditCtrlDialog::ctrlListClicked(QListWidgetItem* item)
776
QString s(item->text());
778
MusECore::MidiTrack* track = part->track();
779
int portn = track->outPort();
780
MusECore::MidiPort* port = &MusEGlobal::midiPorts[portn];
781
MusECore::MidiCtrlValListList* cll = port->controller();
783
MusECore::iMidiCtrlValList i;
784
for (i = cll->begin(); i != cll->end(); ++i) {
785
MusECore::MidiCtrlValList* cl = i->second;
787
MusECore::MidiController* c = port->midiController(num);
788
if (s == c->name()) {
789
if (num == MusECore::CTRL_PROGRAM) {
790
widgetStack->setCurrentIndex(1);
793
if(val == MusECore::CTRL_VAL_UNKNOWN)
798
widgetStack->setCurrentIndex(0);
799
valSlider->setRange(c->minVal(), c->maxVal());
800
valSpinBox->setRange(c->minVal(), c->maxVal());
801
controllerName->setText(s);
804
if(val == MusECore::CTRL_VAL_UNKNOWN || val == 0)
808
case MusECore::CTRL_PANPOT:
809
val = 64 - c->bias();
811
case MusECore::CTRL_VOLUME:
819
valSlider->setValue(val);
825
printf("controller %s not found!\n", s.toLatin1().constData());
828
//---------------------------------------------------------
830
//---------------------------------------------------------
832
void EditCtrlDialog::updatePatch()
834
MusECore::MidiTrack* track = part->track();
835
int port = track->outPort();
836
int channel = track->outChannel();
837
MusECore::MidiInstrument* instr = MusEGlobal::midiPorts[port].instrument();
838
patchName->setText(instr->getPatchName(channel, val, MusEGlobal::song->mtype(), track->type() == MusECore::Track::DRUM));
840
int hb = ((val >> 16) & 0xff) + 1;
843
int lb = ((val >> 8) & 0xff) + 1;
846
int pr = (val & 0xff) + 1;
850
hbank->blockSignals(true);
851
lbank->blockSignals(true);
852
program->blockSignals(true);
856
program->setValue(pr);
858
hbank->blockSignals(false);
859
lbank->blockSignals(false);
860
program->blockSignals(false);
863
//---------------------------------------------------------
865
//---------------------------------------------------------
867
void EditCtrlDialog::instrPopup()
869
MusECore::MidiTrack* track = part->track();
870
int channel = track->outChannel();
871
int port = track->outPort();
872
MusECore::MidiInstrument* instr = MusEGlobal::midiPorts[port].instrument();
874
//QMenu* pup = new QMenu(this);
875
MusEGui::PopupMenu* pup = new MusEGui::PopupMenu(this);
876
//populatePatchPopup(instr, pup, channel, MusEGlobal::song->mtype(), track->type() == MusECore::Track::DRUM);
877
instr->populatePatchPopup(pup, channel, MusEGlobal::song->mtype(), track->type() == MusECore::Track::DRUM);
879
if(pup->actions().count() == 0)
885
QAction* rv = pup->exec(patchName->mapToGlobal(QPoint(10,5)));
887
val = rv->data().toInt();
894
//---------------------------------------------------------
896
//---------------------------------------------------------
898
void EditCtrlDialog::programChanged()
900
// MusECore::MidiTrack* track = part->track();
901
// int channel = track->outChannel();
902
// int port = track->outPort();
903
int hb = hbank->value();
904
int lb = lbank->value();
905
int prog = program->value();
907
if (hb > 0 && hb < 129)
911
if (lb > 0 && lb < 129)
915
if (prog > 0 && prog < 129)
920
val = (hb << 16) + (lb << 8) + prog;
924
} // namespace MusEGui