From 9af73b3a26a39bce5a95ee0945b7df68df2e2ac4 Mon Sep 17 00:00:00 2001 From: Werner Schweer Date: Fri, 8 Dec 2006 14:37:14 +0000 Subject: instrument editor updates --- muse/ChangeLog | 4 +- muse/muse/instruments/editinstrument.cpp | 250 ++++++++++++++++++++----------- muse/muse/instruments/editinstrument.h | 7 + muse/muse/instruments/editinstrument.ui | 25 +--- muse/muse/instruments/minstrument.cpp | 12 ++ muse/muse/midictrl.cpp | 20 ++- muse/muse/midictrl.h | 17 ++- 7 files changed, 213 insertions(+), 122 deletions(-) diff --git a/muse/ChangeLog b/muse/ChangeLog index 5db277da..709a80a6 100644 --- a/muse/ChangeLog +++ b/muse/ChangeLog @@ -1,4 +1,6 @@ -08.12 (ng) deicsonze +08.12 (ws) + - first version of midi instrument editor (*.idf files) + (ng) deicsonze - fix LFO and Ctrl modulation 07.12 (ws) - xml lib cleanups diff --git a/muse/muse/instruments/editinstrument.cpp b/muse/muse/instruments/editinstrument.cpp index 90400587..823a20e3 100644 --- a/muse/muse/instruments/editinstrument.cpp +++ b/muse/muse/instruments/editinstrument.cpp @@ -57,6 +57,7 @@ EditInstrument::EditInstrument(QWidget* parent) connect(fileSaveAsAction, SIGNAL(triggered()), SLOT(fileSaveAs())); connect(fileSaveAction, SIGNAL(triggered()), SLOT(fileSave())); connect(fileNewAction, SIGNAL(triggered()), SLOT(fileNew())); + connect(fileExitAction, SIGNAL(triggered()), SLOT(close())); connect(deletePatch, SIGNAL(clicked()), SLOT(deletePatchClicked())); connect(newPatch, SIGNAL(clicked()), SLOT(newPatchClicked())); @@ -112,8 +113,9 @@ void EditInstrument::fileSave() fileSaveAs(); else { QFile f(instrument->filePath()); - if (!f.open(QIODevice::WriteOnly)) + if (!f.open(QIODevice::WriteOnly)) { fileSaveAs(); + } else { f.close(); if (fileSave(instrument, instrument->filePath())) @@ -137,6 +139,7 @@ bool EditInstrument::fileSave(MidiInstrument* instrument, const QString& name) return false; } Xml xml(&f); + updateInstrument(instrument); instrument->write(xml); f.close(); if (f.error()) { @@ -159,7 +162,12 @@ void EditInstrument::fileSaveAs() return; MidiInstrument* instrument = (MidiInstrument*)item->data(Qt::UserRole).value(); QString path = QDir::homePath() + "/" + config.instrumentPath; - path += QString("/%1.idf").arg(instrument->iname()); + if (instrument->filePath().isEmpty()) + path += QString("/%1.idf").arg(instrument->iname()); + else { + QFileInfo fi(instrument->filePath()); + path += QString("/%1.idf").arg(fi.baseName()); + } QString s = QFileDialog::getSaveFileName(this, tr("MusE: Save Instrument Definition"), path, @@ -476,11 +484,6 @@ void EditInstrument::newSysexClicked() void EditInstrument::instrumentChanged(QListWidgetItem* sel, QListWidgetItem* old) { - patchView->clear(); - listController->clear(); - category->clear(); - sysexList->clear(); - if (sel == 0) return; if (old) { @@ -489,6 +492,11 @@ void EditInstrument::instrumentChanged(QListWidgetItem* sel, QListWidgetItem* ol oi->setDirty(false); } + patchView->clear(); + listController->clear(); + category->clear(); + sysexList->clear(); + // populate patch list MidiInstrument* instrument = (MidiInstrument*)sel->data(Qt::UserRole).value(); @@ -519,6 +527,8 @@ void EditInstrument::instrumentChanged(QListWidgetItem* sel, QListWidgetItem* ol item->setData(Qt::UserRole, v); listController->addItem(item); } + listController->setItemSelected(listController->item(0), true); + controllerChanged(listController->item(0), 0); category->addItems(instrument->categories()); @@ -538,6 +548,52 @@ void EditInstrument::instrumentChanged(QListWidgetItem* sel, QListWidgetItem* ol } } +//--------------------------------------------------------- +// updatePatch +//--------------------------------------------------------- + +void EditInstrument::updatePatch(MidiInstrument* instrument, Patch* p) + { + if (p->name != patchNameEdit->text()) { + p->name = patchNameEdit->text(); + instrument->setDirty(true); + } + if (p->hbank != spinBoxHBank->value()) { + p->hbank = spinBoxHBank->value(); + instrument->setDirty(true); + } + if (p->lbank != spinBoxLBank->value()) { + p->hbank = spinBoxHBank->value(); + instrument->setDirty(true); + } + if (p->prog != spinBoxProgram->value()) { + p->prog = spinBoxProgram->value(); + instrument->setDirty(true); + } + // there is no logical xor in c++ + bool a = p->typ & 1; + bool b = p->typ & 2; + bool c = p->typ & 4; + bool aa = checkBoxGM->isChecked(); + bool bb = checkBoxGS->isChecked(); + bool cc = checkBoxXG->isChecked(); + if ((a ^ aa) || (b ^ bb) || (c ^ cc)) { + int value = 0; + if (checkBoxGM->isChecked()) + value |= 1; + if (checkBoxGS->isChecked()) + value |= 2; + if (checkBoxXG->isChecked()) + value |= 4; + p->typ = value; + instrument->setDirty(true); + } + if (p->categorie != category->currentIndex()) { + p->categorie = category->currentIndex(); + instrument->setDirty(true); + } + } + //--------------------------------------------------------- // patchChanged //--------------------------------------------------------- @@ -550,48 +606,7 @@ void EditInstrument::patchChanged(QTreeWidgetItem* sel, QTreeWidgetItem* old) return; MidiInstrument* instrument = (MidiInstrument*)item->data(Qt::UserRole).value(); Patch* p = (Patch*)old->data(0, Qt::UserRole).value(); - if (p->name != patchNameEdit->text()) { - p->name = patchNameEdit->text(); - instrument->setDirty(true); -printf("patch mod 1\n"); - } - if (p->hbank != spinBoxHBank->value()) { - p->hbank = spinBoxHBank->value(); - instrument->setDirty(true); -printf("patch mod 2\n"); - } - if (p->lbank != spinBoxLBank->value()) { - p->hbank = spinBoxHBank->value(); - instrument->setDirty(true); -printf("patch mod 3\n"); - } - if (p->prog != spinBoxProgram->value()) { - p->prog = spinBoxProgram->value(); - instrument->setDirty(true); -printf("patch mod 4\n"); - } - // there is no logical xor in c++ - bool a = p->typ & 1; - bool b = p->typ & 2; - bool c = p->typ & 4; - bool aa = checkBoxGM->isChecked(); - bool bb = checkBoxGS->isChecked(); - bool cc = checkBoxXG->isChecked(); - if ((a ^ aa) || (b ^ bb) || (c ^ cc)) { - int value = 0; - if (checkBoxGM->isChecked()) - value |= 1; - if (checkBoxGS->isChecked()) - value |= 2; - if (checkBoxXG->isChecked()) - value |= 4; - p->typ = value; - instrument->setDirty(true); - } - if (p->categorie != category->currentIndex()) { - p->categorie = category->currentIndex(); - instrument->setDirty(true); - } + updatePatch(instrument, p); } if (sel == 0 || sel->data(0, Qt::UserRole).value() == 0) { patchNameEdit->setText(""); @@ -609,6 +624,47 @@ printf("patch mod 4\n"); category->setCurrentIndex(p->categorie); } +//--------------------------------------------------------- +// updateController +//--------------------------------------------------------- + +void EditInstrument::updateController(MidiInstrument* instrument, MidiController* oc) + { + int ctrlH = spinBoxHCtrlNo->value(); + int ctrlL = spinBoxLCtrlNo->value(); + MidiController::ControllerType type = (MidiController::ControllerType)ctrlType->currentIndex(); + int num = MidiController::genNum(type, ctrlH, ctrlL); + + if (num != oc->num()) { + oc->setNum(num); + instrument->setDirty(true); + } + if (spinBoxMin->value() != oc->minVal()) { + oc->setMinVal(spinBoxMin->value()); + instrument->setDirty(true); + } + if (spinBoxMax->value() != oc->maxVal()) { + oc->setMaxVal(spinBoxMax->value()); + instrument->setDirty(true); + } + if (spinBoxDefault->value() != oc->initVal()) { + oc->setInitVal(spinBoxDefault->value()); + instrument->setDirty(true); + } + if (moveWithPart->isChecked() ^ oc->moveWithPart()) { + oc->setMoveWithPart(moveWithPart->isChecked()); + instrument->setDirty(true); + } + if (ctrlName->text() != oc->name()) { + oc->setName(ctrlName->text()); + instrument->setDirty(true); + } + if (ctrlComment->toPlainText() != oc->comment()) { + oc->setComment(ctrlComment->toPlainText()); + instrument->setDirty(true); + } + } + //--------------------------------------------------------- // controllerChanged //--------------------------------------------------------- @@ -621,34 +677,16 @@ void EditInstrument::controllerChanged(QListWidgetItem* sel, QListWidgetItem* ol return; MidiInstrument* instrument = (MidiInstrument*)item->data(Qt::UserRole).value(); MidiController* oc = (MidiController*)old->data(Qt::UserRole).value(); - int ctrlH = spinBoxHCtrlNo->value(); - int ctrlL = spinBoxLCtrlNo->value(); - MidiController::ControllerType type = (MidiController::ControllerType)ctrlType->currentIndex(); - int num = MidiController::genNum(type, ctrlH, ctrlL); - - if (num != oc->num()) { - oc->setNum(num); - instrument->setDirty(true); - } - if (spinBoxMin->value() != oc->minVal()) { - oc->setMinVal(spinBoxMin->value()); - instrument->setDirty(true); - } - if (spinBoxMax->value() != oc->maxVal()) { - oc->setMaxVal(spinBoxMax->value()); - instrument->setDirty(true); - } - if (spinBoxDefault->value() != oc->initVal()) { - oc->setInitVal(spinBoxDefault->value()); - instrument->setDirty(true); - } + updateController(instrument, oc); } if (sel == 0 || sel->data(Qt::UserRole).value() == 0) { - // patchNameEdit->setText(""); + ctrlName->setText(""); + ctrlComment->setText(""); return; } MidiController* c = (MidiController*)sel->data(Qt::UserRole).value(); - entryName->setText(c->name()); + ctrlName->setText(c->name()); + ctrlComment->setText(c->comment()); int ctrlH = (c->num() >> 8) & 0x7f; int ctrlL = c->num() & 0x7f; int type = int(c->type()); @@ -660,6 +698,30 @@ void EditInstrument::controllerChanged(QListWidgetItem* sel, QListWidgetItem* ol spinBoxMax->setValue(c->maxVal()); spinBoxDefault->setRange(c->minVal()-1, c->maxVal()); spinBoxDefault->setValue(c->initVal()); + moveWithPart->setChecked(c->moveWithPart()); + } + +//--------------------------------------------------------- +// updateSysex +//--------------------------------------------------------- + +void EditInstrument::updateSysex(MidiInstrument* instrument, SysEx* so) + { + if (sysexName->text() != so->name) { + so->name = sysexName->text(); + instrument->setDirty(true); + } + if (sysexComment->toPlainText() != so->comment) { + so->comment = sysexComment->toPlainText(); + instrument->setDirty(true); + } + unsigned char* data; + int len = string2sysex(sysexData->toPlainText(), &data); + if (so->dataLen != len || !memcmp(data, so->data, len)) { + delete so->data; + so->data = data; + so->dataLen = len; + } } //--------------------------------------------------------- @@ -673,24 +735,8 @@ void EditInstrument::sysexChanged(QListWidgetItem* sel, QListWidgetItem* old) if (item == 0) return; MidiInstrument* instrument = (MidiInstrument*)item->data(Qt::UserRole).value(); - SysEx* so = (SysEx*)old->data(Qt::UserRole).value(); - if (sysexName->text() != so->name) { - so->name = sysexName->text(); - instrument->setDirty(true); -printf("sysex mod 1\n"); - } - if (sysexComment->toPlainText() != so->comment) { - so->comment = sysexComment->toPlainText(); - instrument->setDirty(true); -printf("sysex mod 2\n"); - } - unsigned char* data; - int len = string2sysex(sysexData->toPlainText(), &data); - if (so->dataLen != len || !memcmp(data, so->data, len)) { - delete so->data; - so->data = data; - so->dataLen = len; - } + SysEx* so = (SysEx*)item->data(Qt::UserRole).value(); + updateSysex(instrument, so); } if (sel == 0) { sysexName->setText(""); @@ -718,6 +764,7 @@ printf("sysex mod 2\n"); bool EditInstrument::checkDirty(MidiInstrument* i) { + updateInstrument(i); if (!i->dirty()) return false; int n = QMessageBox::warning(this, tr("MusE"), @@ -772,3 +819,26 @@ void EditInstrument::ctrlTypeChanged(int idx) } } +//--------------------------------------------------------- +// updateInstrument +//--------------------------------------------------------- + +void EditInstrument::updateInstrument(MidiInstrument* instrument) + { + QListWidgetItem* sysexItem = sysexList->currentItem(); + if (sysexItem) { + SysEx* so = (SysEx*)sysexItem->data(Qt::UserRole).value(); + updateSysex(instrument, so); + } + QListWidgetItem* ctrlItem = listController->currentItem(); + if (ctrlItem) { + MidiController* ctrl = (MidiController*)ctrlItem->data(Qt::UserRole).value(); + updateController(instrument, ctrl); + } + QTreeWidgetItem* patchItem = patchView->currentItem(); + if (patchItem) { + Patch* p = (Patch*)patchItem->data(0, Qt::UserRole).value(); + updatePatch(instrument, p); + } + } + diff --git a/muse/muse/instruments/editinstrument.h b/muse/muse/instruments/editinstrument.h index 1b38fb26..cefafe74 100644 --- a/muse/muse/instruments/editinstrument.h +++ b/muse/muse/instruments/editinstrument.h @@ -24,6 +24,9 @@ #include "ui_editinstrument.h" class MidiInstrument; +class SysEx; +class MidiController; +struct Patch; //--------------------------------------------------------- // EditInstrument @@ -35,6 +38,10 @@ class EditInstrument : public QMainWindow, public Ui::EditInstrumentBase { bool fileSave(MidiInstrument*, const QString& name); void closeEvent(QCloseEvent*); bool checkDirty(MidiInstrument*); + void updateInstrument(MidiInstrument*); + void updateSysex(MidiInstrument*, SysEx*); + void updateController(MidiInstrument*, MidiController*); + void updatePatch(MidiInstrument* instrument, Patch* p); private slots: virtual void fileNew(); diff --git a/muse/muse/instruments/editinstrument.ui b/muse/muse/instruments/editinstrument.ui index 7c071290..f58d9d28 100644 --- a/muse/muse/instruments/editinstrument.ui +++ b/muse/muse/instruments/editinstrument.ui @@ -72,7 +72,7 @@ - 1 + 0 @@ -466,7 +466,7 @@ handled like normal controllers. - + @@ -476,7 +476,7 @@ handled like normal controllers. - + @@ -994,22 +994,5 @@ handled like normal controllers. - - - toolBar - actionTriggered(QAction*) - EditInstrumentBase - close() - - - 34 - 58 - - - 161 - 546 - - - - + diff --git a/muse/muse/instruments/minstrument.cpp b/muse/muse/instruments/minstrument.cpp index e4044056..66705211 100644 --- a/muse/muse/instruments/minstrument.cpp +++ b/muse/muse/instruments/minstrument.cpp @@ -432,6 +432,17 @@ void MidiInstrument::read(QDomNode node) else if (tag == "Controller") { MidiController* mc = new MidiController(); mc->read(node); + // + // HACK: make predefined "Program" controller overloadable + // + if (mc->name() == "Program") { + for (iMidiController i = _controller->begin(); i != _controller->end(); ++i) { + if ((*i)->name() == mc->name()) { + _controller->erase(i); + break; + } + } + } _controller->push_back(mc); } else if (tag == "Init") @@ -612,5 +623,6 @@ void MidiInstrument::write(Xml& xml) for (iMidiController ic = _controller->begin(); ic != _controller->end(); ++ic) (*ic)->write(xml); xml.etag("MidiInstrument"); + xml.etag("muse"); } diff --git a/muse/muse/midictrl.cpp b/muse/muse/midictrl.cpp index 409316d9..89e40ec1 100644 --- a/muse/muse/midictrl.cpp +++ b/muse/muse/midictrl.cpp @@ -193,10 +193,13 @@ MidiController::MidiController() _minVal = 0; _maxVal = 127; _initVal = 0; + _moveWithPart = true; } -MidiController::MidiController(const QString& s, int n, int min, int max, int init) - : _name(s), _num(n), _minVal(min), _maxVal(max), _initVal(init) +MidiController::MidiController(const QString& s, int n, int min, int max, int init, + bool mwp) + : _name(s), _num(n), _minVal(min), _maxVal(max), _initVal(init), + _moveWithPart(mwp) { } @@ -245,8 +248,14 @@ void MidiController::write(Xml& xml) const else sl.setNum(l); - xml.tagE(QString("Controller name=\"%1\" type=\"%2\" h=\"%3\" l=\"%4\" min=\"%5\" max\"%6\" init=\"%7\"") - .arg(Xml::xmlString(_name)).arg(type).arg(h).arg(sl).arg(_minVal).arg(_maxVal).arg(_initVal)); + QString s = QString("Controller name=\"%1\" type=\"%2\" h=\"%3\" l=\"%4\" min=\"%5\" max=\"%6\" init=\"%7\"") + .arg(Xml::xmlString(_name)).arg(type).arg(h).arg(sl).arg(_minVal).arg(_maxVal).arg(_initVal); + if (_comment.isEmpty()) + xml.tagE(s); + else { + xml.putLevel(); + xml << '<' << s << '>' << Xml::xmlString(_comment) << "\n"; + } } //--------------------------------------------------------- @@ -260,7 +269,8 @@ void MidiController::read(QDomNode node) int l = 0; QDomElement e = node.toElement(); - _name = e.attribute("name"); + _name = e.attribute("name"); + _comment = e.text(); t = ctrlType2Int(e.attribute("type")); int h = e.attribute("h","0").toInt(0,0); QString s = e.attribute("l"); diff --git a/muse/muse/midictrl.h b/muse/muse/midictrl.h index 4ffaa017..9d20fdcc 100644 --- a/muse/muse/midictrl.h +++ b/muse/muse/midictrl.h @@ -111,18 +111,23 @@ class MidiController { }; private: QString _name; + QString _comment; int _num; // Controller Number int _minVal; // controller value range (used in gui) int _maxVal; int _initVal; + bool _moveWithPart; public: MidiController(); - MidiController(const QString& n, int num, int min, int max, int init); - const QString& name() const { return _name; } - int num() const { return _num; } - void setName(const QString& s) { _name = s; } - void setNum(int v) { _num = v; } + MidiController(const QString& n, int num, int min, int max, int init, + bool mwp = true); + const QString& name() const { return _name; } + void setName(const QString& s) { _name = s; } + const QString& comment() const { return _comment; } + void setComment(const QString& s) { _comment = s; } + int num() const { return _num; } + void setNum(int v) { _num = v; } void write(Xml& xml) const; void read(QDomNode); int minVal() const { return _minVal; } @@ -131,6 +136,8 @@ class MidiController { void setInitVal(int val) { _initVal = val; } void setMinVal(int val) { _minVal = val; } void setMaxVal(int val) { _maxVal = val; } + bool moveWithPart() const { return _moveWithPart; } + void setMoveWithPart(bool v) { _moveWithPart = v; } ControllerType type() const; static int genNum(ControllerType, int, int); }; -- cgit v1.2.3