From 036482a3fea264fdc7a4c9404466be9f49904100 Mon Sep 17 00:00:00 2001 From: Werner Schweer Date: Wed, 6 Dec 2006 16:01:13 +0000 Subject: instrument editor updates --- muse/muse/conf.cpp | 1 + muse/muse/ctrl.cpp | 4 + muse/muse/ctrl.h | 4 + muse/muse/gconfig.cpp | 1 + muse/muse/gconfig.h | 1 + muse/muse/instruments/editinstrument.cpp | 634 ++++++++++++++++++++---- muse/muse/instruments/editinstrument.h | 20 +- muse/muse/instruments/editinstrument.ui | 812 +++++++++++++++++++------------ muse/muse/instruments/minstrument.cpp | 61 ++- muse/muse/instruments/minstrument.h | 14 +- muse/muse/midictrl.h | 6 +- muse/muse/muse.cpp | 71 +-- muse/muse/preferences.cpp | 2 + muse/muse/preferences.ui | 86 +++- 14 files changed, 1247 insertions(+), 470 deletions(-) diff --git a/muse/muse/conf.cpp b/muse/muse/conf.cpp index 87b6fcb7..b926ddb5 100644 --- a/muse/muse/conf.cpp +++ b/muse/muse/conf.cpp @@ -483,6 +483,7 @@ void MusE::writeGlobalConfiguration(Xml& xml) const xml.tag("createDefaultMidiInput", config.createDefaultMidiInput); xml.tag("projectPath", config.projectPath); xml.tag("templatePath", config.templatePath); + xml.tag("instrumentPath", config.instrumentPath); xml.tag("importMidiPath", config.importMidiPath); xml.tag("importWavePath", config.importWavePath); diff --git a/muse/muse/ctrl.cpp b/muse/muse/ctrl.cpp index e4d58247..e6f6540b 100644 --- a/muse/muse/ctrl.cpp +++ b/muse/muse/ctrl.cpp @@ -36,6 +36,7 @@ Ctrl::Ctrl(int id, const QString& s, int t) _curVal.f = 0.0f; _touched = false; _changed = false; + _moveWithPart = false; } Ctrl::Ctrl(int id, const QString& s, int t, float a, float b) @@ -49,6 +50,7 @@ Ctrl::Ctrl(int id, const QString& s, int t, float a, float b) _curVal.f = 0.0f; _touched = false; _changed = false; + _moveWithPart = false; } Ctrl::Ctrl() @@ -60,6 +62,7 @@ Ctrl::Ctrl() _curVal.f = 0.0f; _touched = false; _changed = false; + _moveWithPart = false; } Ctrl::Ctrl(const MidiController* mc) @@ -72,6 +75,7 @@ Ctrl::Ctrl(const MidiController* mc) _name = mc->name(); _touched = false; _changed = false; + _moveWithPart = false; } //--------------------------------------------------------- diff --git a/muse/muse/ctrl.h b/muse/muse/ctrl.h index f4f0922a..929a11d3 100644 --- a/muse/muse/ctrl.h +++ b/muse/muse/ctrl.h @@ -165,6 +165,7 @@ class Ctrl : public CTRL { CVal min, max; bool _changed; bool _touched; + bool _moveWithPart; public: Ctrl(); @@ -200,6 +201,9 @@ class Ctrl : public CTRL { void setRange(CVal, CVal); CVal minVal() const { return min; } CVal maxVal() const { return max; } + bool moveWithPart() const { return _moveWithPart; } + void setMoveWithPart(bool v) { _moveWithPart = v; } + void read(QDomNode node, bool midi); void write(Xml&); int val2pixelR(CVal, int maxpixel); diff --git a/muse/muse/gconfig.cpp b/muse/muse/gconfig.cpp index 231238ad..840e75f7 100644 --- a/muse/muse/gconfig.cpp +++ b/muse/muse/gconfig.cpp @@ -123,6 +123,7 @@ GlobalConfigValues config = { true, // createDefaultMidiInput QString("MusE/projects"), // projectPath QString("MusE/templates"), // templatePath + QString("MusE/instruments"), // instrumentPath QString("MusE/"), // midi import path QString("MusE/"), // wave import path }; diff --git a/muse/muse/gconfig.h b/muse/muse/gconfig.h index 00ef43d5..1356fb22 100644 --- a/muse/muse/gconfig.h +++ b/muse/muse/gconfig.h @@ -123,6 +123,7 @@ struct GlobalConfigValues { bool createDefaultMidiInput; QString projectPath; QString templatePath; + QString instrumentPath; QString importMidiPath; QString importWavePath; }; diff --git a/muse/muse/instruments/editinstrument.cpp b/muse/muse/instruments/editinstrument.cpp index 25fdac10..4736f918 100644 --- a/muse/muse/instruments/editinstrument.cpp +++ b/muse/muse/instruments/editinstrument.cpp @@ -23,6 +23,7 @@ #include "ctrl.h" #include "midictrl.h" #include "al/xml.h" +#include "gconfig.h" //--------------------------------------------------------- // EditInstrument @@ -41,31 +42,453 @@ EditInstrument::EditInstrument(QWidget* parent) } instrumentList->setItemSelected(instrumentList->item(0), true); connect(instrumentList, SIGNAL(currentItemChanged(QListWidgetItem*,QListWidgetItem*)), - SLOT(instrumentChanged(QListWidgetItem*))); + SLOT(instrumentChanged(QListWidgetItem*,QListWidgetItem*))); connect(patchView, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), - SLOT(patchChanged(QTreeWidgetItem*))); - instrumentChanged(instrumentList->item(0)); + SLOT(patchChanged(QTreeWidgetItem*, QTreeWidgetItem*))); + instrumentChanged(instrumentList->item(0), instrumentList->item(0)); connect(listController, SIGNAL(currentItemChanged(QListWidgetItem*,QListWidgetItem*)), SLOT(controllerChanged(QListWidgetItem*))); + connect(sysexList, SIGNAL(currentItemChanged(QListWidgetItem*,QListWidgetItem*)), + SLOT(sysexChanged(QListWidgetItem*))); connect(instrumentName, SIGNAL(textChanged(const QString&)), SLOT(instrumentNameChanged(const QString&))); connect(fileSaveAsAction, SIGNAL(triggered()), SLOT(fileSaveAs())); connect(fileSaveAction, SIGNAL(triggered()), SLOT(fileSave())); + connect(fileNewAction, SIGNAL(triggered()), SLOT(fileNew())); + + connect(deletePatch, SIGNAL(clicked()), SLOT(deletePatchClicked())); + connect(newPatch, SIGNAL(clicked()), SLOT(newPatchClicked())); + connect(newGroup, SIGNAL(clicked()), SLOT(newGroupClicked())); + connect(newCategory, SIGNAL(clicked()), SLOT(newCategoryClicked())); + connect(deleteController, SIGNAL(clicked()), SLOT(deleteControllerClicked())); + connect(newController, SIGNAL(clicked()), SLOT(newControllerClicked())); + connect(deleteSysex, SIGNAL(clicked()), SLOT(deleteSysexClicked())); + connect(newSysex, SIGNAL(clicked()), SLOT(newSysexClicked())); + } + +//--------------------------------------------------------- +// fileNew +//--------------------------------------------------------- + +void EditInstrument::fileNew() + { + for (int i = 1;; ++i) { + QString s = QString("Instrument-%1").arg(i); + bool found = false; + for (iMidiInstrument i = midiInstruments.begin(); i != midiInstruments.end(); ++i) { + if (s == (*i)->iname()) { + found = true; + break; + } + } + if (!found) { + MidiInstrument* ni = new MidiInstrument(s); + midiInstruments.append(ni); + QListWidgetItem* item = new QListWidgetItem(ni->iname()); + QVariant v = qVariantFromValue((void*)(ni)); + item->setData(Qt::UserRole, v); + instrumentList->addItem(item); + instrumentList->setCurrentItem(item); + break; + } + } + } + +//--------------------------------------------------------- +// fileSave +//--------------------------------------------------------- + +void EditInstrument::fileSave() + { + QListWidgetItem* item = instrumentList->currentItem(); + if (item == 0) + return; + MidiInstrument* instrument = (MidiInstrument*)item->data(Qt::UserRole).value(); + if (instrument->filePath().isEmpty()) + fileSaveAs(); + else { + QFile f(instrument->filePath()); + if (!f.open(QIODevice::WriteOnly)) + fileSaveAs(); + else { + f.close(); + if (fileSave(instrument, instrument->filePath())) + instrument->setDirty(false); + } + } + } + +//--------------------------------------------------------- +// fileSave +//--------------------------------------------------------- + +bool EditInstrument::fileSave(MidiInstrument* instrument, const QString& name) + { + QFile f(name); + if (!f.open(QIODevice::WriteOnly)) { + QString s("Creating file failed: "); + s += strerror(errno); + QMessageBox::critical(this, + tr("MusE: Create file failed"), s); + return false; + } + Xml xml(&f); + instrument->write(xml); + f.close(); + if (f.error()) { + QString s = QString("Write File\n") + f.fileName() + QString("\nfailed: ") + + f.errorString(); + QMessageBox::critical(this, tr("MusE: Write File failed"), s); + return false; + } + return true; + } + +//--------------------------------------------------------- +// fileSaveAs +//--------------------------------------------------------- + +void EditInstrument::fileSaveAs() + { + QListWidgetItem* item = instrumentList->currentItem(); + if (item == 0) + return; + MidiInstrument* instrument = (MidiInstrument*)item->data(Qt::UserRole).value(); + QString path = QDir::homePath() + "/" + config.instrumentPath; + path += QString("/%1.idf").arg(instrument->iname()); + QString s = QFileDialog::getSaveFileName(this, + tr("MusE: Save Instrument Definition"), + path, + tr("Instrument Definition (*.idf)")); + if (s.isEmpty()) + return; + instrument->setFilePath(s); + if (fileSave(instrument, s)) + instrument->setDirty(false); + } + +//--------------------------------------------------------- +// closeEvent +//--------------------------------------------------------- + +void EditInstrument::closeEvent(QCloseEvent* ev) + { + QListWidgetItem* item = instrumentList->currentItem(); + if (item) { + MidiInstrument* instrument = (MidiInstrument*)item->data(Qt::UserRole).value(); + if (checkDirty(instrument)) { + ev->ignore(); + return; + } + } + QMainWindow::closeEvent(ev); + } + +//--------------------------------------------------------- +// instrumentNameChanged +//--------------------------------------------------------- + +void EditInstrument::instrumentNameChanged(const QString& s) + { + QListWidgetItem* item = instrumentList->currentItem(); + if (item == 0) + return; + if (s != item->text()) { + item->setText(s); + MidiInstrument* instrument = (MidiInstrument*)item->data(Qt::UserRole).value(); + instrument->setDirty(true); + } + } + +//--------------------------------------------------------- +// deletePatchClicked +//--------------------------------------------------------- + +void EditInstrument::deletePatchClicked() + { + QListWidgetItem* item = instrumentList->currentItem(); + if (item == 0) + return; + MidiInstrument* instrument = (MidiInstrument*)item->data(Qt::UserRole).value(); + QTreeWidgetItem* pi = patchView->currentItem(); + if (pi == 0) + return; + void* p = pi->data(0, Qt::UserRole).value(); + if (p == 0) + return; + Patch* patch = (Patch*)p; + std::vector* pg = instrument->groups(); + for (std::vector::iterator g = pg->begin(); g != pg->end(); ++g) { + for (iPatch p = g->patches.begin(); p != g->patches.end(); ++p) { + if (patch == *p) { + g->patches.erase(p); + delete pi; + instrument->setDirty(true); + return; + } + } + } + printf("fatal: patch not found\n"); + } + +//--------------------------------------------------------- +// newPatchClicked +//--------------------------------------------------------- + +void EditInstrument::newPatchClicked() + { + QListWidgetItem* item = instrumentList->currentItem(); + if (item == 0) + return; + MidiInstrument* instrument = (MidiInstrument*)item->data(Qt::UserRole).value(); + std::vector* pg = instrument->groups(); + QString patchName; + for (int i = 1;; ++i) { + patchName = QString("Patch-%1").arg(i); + bool found = false; + + for (std::vector::iterator g = pg->begin(); g != pg->end(); ++g) { + for (iPatch p = g->patches.begin(); p != g->patches.end(); ++p) { + if ((*p)->name == patchName) { + found = true; + break; + } + } + if (found) + break; + } + if (!found) + break; + } + + // + // search current patch group + // + PatchGroup* pGroup = 0; + QTreeWidgetItem* pi = patchView->currentItem(); + if (pi == 0) + return; + if (pi->data(0, Qt::UserRole).value()) + pi = pi->parent(); + for (std::vector::iterator g = pg->begin(); g != pg->end(); ++g) { + if (g->name == pi->text(0)) { + pGroup = &*g; + break; + } + } + if (pGroup == 0) { + printf("group not found\n"); + return; + } + Patch* patch = new Patch; + patch->name = patchName; + pGroup->patches.push_back(patch); + QTreeWidgetItem* sitem = new QTreeWidgetItem; + sitem->setText(0, patch->name); + QVariant v = QVariant::fromValue((void*)(patch)); + sitem->setData(0, Qt::UserRole, v); + + pi->addChild(sitem); + patchView->setCurrentItem(sitem); + instrument->setDirty(true); + } + +//--------------------------------------------------------- +// newGroupClicked +//--------------------------------------------------------- + +void EditInstrument::newGroupClicked() + { + QListWidgetItem* item = instrumentList->currentItem(); + if (item == 0) + return; + MidiInstrument* instrument = (MidiInstrument*)item->data(Qt::UserRole).value(); + std::vector* pg = instrument->groups(); + QString groupName; + for (int i = 1;; ++i) { + groupName = QString("Group-%1").arg(i); + bool found = false; + + for (std::vector::iterator g = pg->begin(); g != pg->end(); ++g) { + if (g->name == groupName) { + found = true; + break; + } + } + if (!found) + break; + } + + PatchGroup pGroup; + pGroup.name = groupName; + pg->push_back(pGroup); + + QTreeWidgetItem* sitem = new QTreeWidgetItem; + sitem->setText(0, groupName); + QVariant v = QVariant::fromValue((void*)0); + sitem->setData(0, Qt::UserRole, v); + patchView->addTopLevelItem(sitem); + patchView->setCurrentItem(sitem); + instrument->setDirty(true); + } + +//--------------------------------------------------------- +// newCategoryClicked +//--------------------------------------------------------- + +void EditInstrument::newCategoryClicked() + { + QListWidgetItem* item = instrumentList->currentItem(); + if (item == 0) + return; + MidiInstrument* instrument = (MidiInstrument*)item->data(Qt::UserRole).value(); + bool ok; + QString cat = QInputDialog::getText(this, + tr("MusE: Enter new Category"), + tr("Enter new Category:"), + QLineEdit::Normal, "", &ok + ); + if (ok && !cat.isEmpty()) { + category->addItem(cat); + instrument->addCategory(cat); + instrument->setDirty(true); + } + } + +//--------------------------------------------------------- +// deleteControllerClicked +//--------------------------------------------------------- + +void EditInstrument::deleteControllerClicked() + { + QListWidgetItem* item = instrumentList->currentItem(); + QListWidgetItem* item2 = listController->currentItem(); + if (item == 0 || item2 == 0) + return; + MidiInstrument* instrument = (MidiInstrument*)item->data(Qt::UserRole).value(); + MidiController* ctrl = (MidiController*)item2->data(Qt::UserRole).value(); + MidiControllerList* cl = instrument->controller(); + cl->removeAll(ctrl); + delete item2; + instrument->setDirty(true); + } + +//--------------------------------------------------------- +// newControllerClicked +//--------------------------------------------------------- + +void EditInstrument::newControllerClicked() + { + QListWidgetItem* item = instrumentList->currentItem(); + if (item == 0) + return; + MidiInstrument* instrument = (MidiInstrument*)item->data(Qt::UserRole).value(); + + QString ctrlName; + MidiControllerList* cl = instrument->controller(); + for (int i = 1;; ++i) { + ctrlName = QString("Controller-%d").arg(i); + + bool found = false; + for (iMidiController ic = cl->begin(); ic != cl->end(); ++ic) { + MidiController* c = *ic; + if (c->name() == ctrlName) { + found = true; + break; + } + } + if (!found) + break; + } + + MidiController* ctrl = new MidiController(); + ctrl->setName(ctrlName); + item = new QListWidgetItem(ctrlName); + QVariant v = qVariantFromValue((void*)(ctrl)); + item->setData(Qt::UserRole, v); + listController->addItem(item); + listController->setCurrentItem(item); + instrument->setDirty(true); + } + +//--------------------------------------------------------- +// deleteSysexClicked +//--------------------------------------------------------- + +void EditInstrument::deleteSysexClicked() + { + QListWidgetItem* item = instrumentList->currentItem(); + QListWidgetItem* item2 = sysexList->currentItem(); + if (item == 0 || item2 == 0) + return; + MidiInstrument* instrument = (MidiInstrument*)item->data(Qt::UserRole).value(); + SysEx* sysex = (SysEx*)item2->data(Qt::UserRole).value(); + QList sl = instrument->sysex(); + instrument->removeSysex(sysex); + delete item2; + instrument->setDirty(true); + } + +//--------------------------------------------------------- +// newSysexClicked +//--------------------------------------------------------- + +void EditInstrument::newSysexClicked() + { + QListWidgetItem* item = instrumentList->currentItem(); + if (item == 0) + return; + MidiInstrument* instrument = (MidiInstrument*)item->data(Qt::UserRole).value(); + + QString sysexName; + for (int i = 1;; ++i) { + sysexName = QString("Sysex-%d").arg(i); + + bool found = false; + foreach(const SysEx* s, instrument->sysex()) { + if (s->name == sysexName) { + found = true; + break; + } + } + if (!found) + break; + } + SysEx* nsysex = new SysEx; + nsysex->name = sysexName; + instrument->addSysex(nsysex); + + item = new QListWidgetItem(sysexName); + QVariant v = QVariant::fromValue((void*)item); + item->setData(Qt::UserRole, v); + sysexList->addItem(item); + sysexList->setCurrentItem(item); + instrument->setDirty(true); } //--------------------------------------------------------- // instrumentChanged //--------------------------------------------------------- -void EditInstrument::instrumentChanged(QListWidgetItem* sel) +void EditInstrument::instrumentChanged(QListWidgetItem* sel, QListWidgetItem* old) { patchView->clear(); listController->clear(); + category->clear(); + sysexList->clear(); if (sel == 0) return; + if (old) { + MidiInstrument* oi = (MidiInstrument*)old->data(Qt::UserRole).value(); + checkDirty(oi); + oi->setDirty(false); + } + // populate patch list MidiInstrument* instrument = (MidiInstrument*)sel->data(Qt::UserRole).value(); + instrument->setDirty(false); + instrumentName->setText(instrument->iname()); std::vector* pg = instrument->groups(); for (std::vector::iterator g = pg->begin(); g != pg->end(); ++g) { @@ -78,7 +501,7 @@ void EditInstrument::instrumentChanged(QListWidgetItem* sel) Patch* patch = *p; QTreeWidgetItem* sitem = new QTreeWidgetItem; sitem->setText(0, patch->name); - QVariant v = QVariant::fromValue((void*)(patch)); + QVariant v = QVariant::fromValue((void*)patch); sitem->setData(0, Qt::UserRole, v); item->addChild(sitem); } @@ -87,12 +510,94 @@ void EditInstrument::instrumentChanged(QListWidgetItem* sel) for (iMidiController ic = cl->begin(); ic != cl->end(); ++ic) { MidiController* c = *ic; QListWidgetItem* item = new QListWidgetItem(c->name()); - QVariant v = qVariantFromValue((void*)(c)); + QVariant v = QVariant::fromValue((void*)c); item->setData(Qt::UserRole, v); listController->addItem(item); } - listController->setItemSelected(listController->item(0), true); - controllerChanged(listController->item(0)); + + category->addItems(instrument->categories()); + + foreach(const SysEx* s, instrument->sysex()) { + QListWidgetItem* item = new QListWidgetItem(s->name); + QVariant v = QVariant::fromValue((void*)item); + item->setData(Qt::UserRole, v); + sysexList->addItem(item); + } + if (!instrument->sysex().isEmpty()) { + sysexList->setItemSelected(sysexList->item(0), true); + sysexChanged(sysexList->item(0)); + } + if (!cl->empty()) { + listController->setItemSelected(listController->item(0), true); + controllerChanged(listController->item(0)); + } + } + +//--------------------------------------------------------- +// patchChanged +//--------------------------------------------------------- + +void EditInstrument::patchChanged(QTreeWidgetItem* sel, QTreeWidgetItem* old) + { + if (old && old->data(0, Qt::UserRole).value()) { + QListWidgetItem* item = instrumentList->currentItem(); + if (item == 0) + 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); + } + 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); + } + } + if (sel == 0 || sel->data(0, Qt::UserRole).value() == 0) { + patchNameEdit->setText(""); + return; + } + Patch* p = (Patch*)sel->data(0, Qt::UserRole).value(); + patchNameEdit->setText(p->name); + spinBoxHBank->setValue(p->hbank); + spinBoxLBank->setValue(p->lbank); + spinBoxProgram->setValue(p->prog); + checkBoxDrum->setChecked(p->drumMap); + checkBoxGM->setChecked(p->typ & 1); + checkBoxGS->setChecked(p->typ & 2); + checkBoxXG->setChecked(p->typ & 4); + category->setCurrentIndex(p->categorie); } //--------------------------------------------------------- @@ -136,101 +641,42 @@ void EditInstrument::controllerChanged(QListWidgetItem* sel) } //--------------------------------------------------------- -// patchChanged -//--------------------------------------------------------- - -void EditInstrument::patchChanged(QTreeWidgetItem* sel) - { - if (sel == 0 || sel->data(0, Qt::UserRole).value() == 0) { - patchNameEdit->setText(""); - return; - } - Patch* p = (Patch*)sel->data(0, Qt::UserRole).value(); - patchNameEdit->setText(p->name); - spinBoxHBank->setValue(p->hbank); - spinBoxLBank->setValue(p->lbank); - spinBoxProgram->setValue(p->prog); - checkBoxDrum->setChecked(p->drumMap); - checkBoxGM->setChecked(p->typ & 1); - checkBoxGS->setChecked(p->typ & 2); - checkBoxXG->setChecked(p->typ & 4); - } - -//--------------------------------------------------------- -// fileNew -//--------------------------------------------------------- - -void EditInstrument::fileNew() - { - - } - -//--------------------------------------------------------- -// fileSave -//--------------------------------------------------------- - -void EditInstrument::fileSave() - { - - } - -//--------------------------------------------------------- -// fileSaveAs -//--------------------------------------------------------- - -void EditInstrument::fileSaveAs() - { - QListWidgetItem* item = instrumentList->currentItem(); - if (item == 0) - return; - MidiInstrument* instrument = (MidiInstrument*)item->data(Qt::UserRole).value(); - QString path = QDir::homePath() + "/MusE/instruments"; - path += QString("/%1.idf").arg(instrument->iname()); - QString s = QFileDialog::getSaveFileName(this, - tr("MusE: Save Instrument Definition"), - path, - tr("Instrument Definition (*.idf)")); - if (s.isEmpty()) - return; - QFile f(s); - if (!f.open(QIODevice::WriteOnly)) { - QString s("Creating file failed: "); - s += strerror(errno); - QMessageBox::critical(this, - tr("MusE: Create file failed"), s); - return; - } - Xml xml(&f); - instrument->write(xml); - f.close(); - if (f.error()) { - QString s = QString("Write File\n") + f.fileName() + QString("\nfailed: ") - + f.errorString(); - QMessageBox::critical(this, tr("MusE: Write File failed"), s); - } - } - -//--------------------------------------------------------- -// fileExit +// sysexChanged //--------------------------------------------------------- -void EditInstrument::fileExit() +void EditInstrument::sysexChanged(QListWidgetItem*) { + printf("sysexChanged\n"); } //--------------------------------------------------------- -// instrumentNameChanged +// checkDirty +// return true on Abort //--------------------------------------------------------- -void EditInstrument::instrumentNameChanged(const QString& s) +bool EditInstrument::checkDirty(MidiInstrument* i) { - QListWidgetItem* item = instrumentList->currentItem(); - if (item == 0) - return; - if (s != item->text()) { - item->setText(s); - MidiInstrument* instrument = (MidiInstrument*)item->data(Qt::UserRole).value(); - instrument->setDirty(true); + if (!i->dirty()) + return false; + int n = QMessageBox::warning(this, tr("MusE"), + tr("The current Instrument contains unsaved data\n" + "Save Current Instrument?"), + tr("&Save"), tr("&Nosave"), tr("&Abort"), 0, 2); + if (n == 0) { + if (i->filePath().isEmpty()) + fileSaveAs(); + else { + QFile f(i->filePath()); + if (!f.open(QIODevice::WriteOnly)) + fileSaveAs(); + else { + f.close(); + if (fileSave(i, i->filePath())) + i->setDirty(false); + } + } + return false; } + return n == 2; } diff --git a/muse/muse/instruments/editinstrument.h b/muse/muse/instruments/editinstrument.h index 2714814a..660ba3cc 100644 --- a/muse/muse/instruments/editinstrument.h +++ b/muse/muse/instruments/editinstrument.h @@ -23,6 +23,8 @@ #include "ui_editinstrument.h" +class MidiInstrument; + //--------------------------------------------------------- // EditInstrument //--------------------------------------------------------- @@ -30,15 +32,27 @@ class EditInstrument : public QMainWindow, public Ui::EditInstrumentBase { Q_OBJECT + bool fileSave(MidiInstrument*, const QString& name); + void closeEvent(QCloseEvent*); + bool checkDirty(MidiInstrument*); + private slots: virtual void fileNew(); virtual void fileSave(); virtual void fileSaveAs(); - virtual void fileExit(); - void instrumentChanged(QListWidgetItem*); - void patchChanged(QTreeWidgetItem*); + void instrumentChanged(QListWidgetItem*, QListWidgetItem*); + void patchChanged(QTreeWidgetItem*, QTreeWidgetItem*); void controllerChanged(QListWidgetItem* sel); + void sysexChanged(QListWidgetItem* sel); void instrumentNameChanged(const QString&); + void deletePatchClicked(); + void newPatchClicked(); + void newGroupClicked(); + void newCategoryClicked(); + void deleteControllerClicked(); + void newControllerClicked(); + void deleteSysexClicked(); + void newSysexClicked(); public: EditInstrument(QWidget* parent = 0); diff --git a/muse/muse/instruments/editinstrument.ui b/muse/muse/instruments/editinstrument.ui index c8f1916b..2a7b525a 100644 --- a/muse/muse/instruments/editinstrument.ui +++ b/muse/muse/instruments/editinstrument.ui @@ -5,8 +5,8 @@ 0 0 - 819 - 505 + 821 + 551 @@ -21,7 +21,7 @@ 6 - + Qt::Horizontal @@ -57,7 +57,7 @@ - 1 + 0 @@ -111,23 +111,23 @@ - + Program: - + - 5 + 0 6 - + 5 @@ -145,7 +145,7 @@ - + 5 @@ -163,7 +163,7 @@ - + New Group @@ -185,9 +185,16 @@ + + + + New Category + + + - + Qt::Horizontal @@ -203,7 +210,7 @@ - + Qt::Horizontal @@ -219,7 +226,7 @@ - + Qt::Horizontal @@ -235,7 +242,7 @@ - + d.c. @@ -251,21 +258,21 @@ - + High Bank: - + Low Bank: - + Qt::Vertical @@ -281,7 +288,7 @@ - + d.c. @@ -297,13 +304,13 @@ - + - + - 6 + 0 6 @@ -338,6 +345,20 @@ + + + + true + + + + + + + Category: + + + @@ -348,264 +369,332 @@ Controller - + 9 6 - - - - - 5 - 0 - 0 - 0 - - - - Controller List: - - - - - + + - Qt::Vertical - - - - 20 - 111 - + Qt::Horizontal - - - - - - This is a list of commonly used midi controllers. + + + + 0 + + + 6 + + + + + + 5 + 0 + 0 + 0 + + + + Controller List: + + + + + + + This is a list of commonly used midi controllers. Note that in MusE pitch and program changes are handled like normal controllers. - - - - - - - - 1 - 5 - 0 - 0 - - - - Properties - - - - 10 - - - 6 - - - - - Name - - - - - - - Type - - - - - - - 2 - - - 6 - - - - - - Controller-7Bit - + + + + + + + + + 0 + + + 6 + + + + + + 1 + 5 + 0 + 0 + + + + Properties + + + + 9 + + + 6 + + + + + Name + + - - - Controller-14Bit - + + - - - RPN-7Bit - + + + + Comment + + - - - NRPN-7Bit - + + - - - RPN-14Bit - + + + + Type + + - - - NRPN-14Bit - + + + + 2 + + + 6 + + + + + + Controller-7Bit + + + + + Controller-14Bit + + + + + RPN-7Bit + + + + + NRPN-7Bit + + + + + RPN-14Bit + + + + + NRPN-14Bit + + + + + Pitch + + + + + Program + + + + + + + + H-Ctrl + + + 10 + + + + + + + Midi Controller Number High Byte + + + 127 + + + 0 + + + 1 + + + + + + + L-Ctrl + + + 10 + + + + + + + Midi Controller Number Low Byte + + + 127 + + + 0 + + + 1 + + + + + + + + + Range + + + + + + + 0 + + + 6 + + + + + Min + + + 10 + + + + + + + 16384 + + + -16385 + + + + + + + Max + + + 10 + + + + + + + 16384 + + + -16385 + + + 127 + + + + + + + Default + + + + + + + + + + + + Move Controller Values with Part + + - + + + + + + + 0 + + + 6 + + + - Pitch + Delete - - + + + + - Program + New Controller - - - - - - - H-Ctrl - - - 10 - - - - - - - Midi Controller Number High Byte - - - 127 - - - 0 - - - 1 - - - - - - - L-Ctrl - - - 10 - - - - - - - Midi Controller Number Low Byte - - - 127 - - - 0 - - - 1 - - - - - - - - - - - - Range - - - - - - - 0 - - - 6 - - - - - Min - - - 10 - - - - - - - 16384 - - - -16385 - - - - - - - Max - - - 10 - - - - - - - 16384 - - - -16385 - - - 127 - - - - - - - Default - - - - - - - - - + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + @@ -614,49 +703,139 @@ handled like normal controllers. SysEx - + - 0 + 9 6 - - + + - Qt::Vertical - - - QSizePolicy::Expanding - - - - 20 - 130 - - - - - - - - - 1 - 7 - 0 - 0 - - - - - - - - - - - Hex Entry: + Qt::Horizontal + + + + 0 + + + 6 + + + + + SYSEX-List: + + + + + + + + 1 + 7 + 0 + 0 + + + + + + + + + + 0 + + + 6 + + + + + Properties + + + + 9 + + + 6 + + + + + Name: + + + + + + + + + + Comment: + + + + + + + + + + Data: + + + + + + + + + + + + + 0 + + + 6 + + + + + Delete + + + + + + + New Sysex + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + @@ -674,7 +853,7 @@ handled like normal controllers. 0 0 - 819 + 821 32 @@ -687,7 +866,7 @@ handled like normal controllers. 434 167 146 - 166 + 168 @@ -701,9 +880,20 @@ handled like normal controllers. + + + Qt::Horizontal + + + 4 + + + + + - image0 + :/xpm/filenew.png &New @@ -717,7 +907,7 @@ handled like normal controllers. - image1 + :/xpm/fileopen.png &Open... @@ -731,7 +921,7 @@ handled like normal controllers. - image2 + :/xpm/filesave.png &Save @@ -758,6 +948,9 @@ handled like normal controllers. + + :/xpm/off.svg + E&xit @@ -773,5 +966,22 @@ 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 ae02dd3c..3e353a13 100644 --- a/muse/muse/instruments/minstrument.cpp +++ b/muse/muse/instruments/minstrument.cpp @@ -30,6 +30,25 @@ MidiInstrumentList midiInstruments; MidiInstrument* genericMidiInstrument; +//--------------------------------------------------------- +// string2sysex +//--------------------------------------------------------- + +int string2sysex(const QString&, unsigned char** data) + { + *data = 0; + return 0; + } + +//--------------------------------------------------------- +// sysex2string +//--------------------------------------------------------- + +QString sysex2string(int, unsigned char*) + { + return QString(""); + } + //--------------------------------------------------------- // Patch //--------------------------------------------------------- @@ -57,6 +76,8 @@ static void loadIDF(QFileInfo* fi) printf("cannot open file %s\n", fi->fileName().toLatin1().data()); return; } + if (debugMsg) + printf(" load instrument definition <%s>\n", fi->filePath().toLocal8Bit().data()); QDomDocument doc; int line, column; QString err; @@ -82,7 +103,19 @@ static void loadIDF(QFileInfo* fi) MidiInstrument* i = new MidiInstrument(); i->read(n); i->setFilePath(fi->filePath()); - midiInstruments.push_back(i); + bool replaced = false; + for (int idx = 0; idx < midiInstruments.size(); ++idx) { + if (midiInstruments[idx]->iname() == i->iname()) { + midiInstruments.replace(idx, i); + replaced = true; + if (debugMsg) + printf("Midi Instrument Definition <%s> overwritten\n", + i->iname().toLocal8Bit().data()); + break; + } + } + if (!replaced) + midiInstruments += i; } } } @@ -116,6 +149,19 @@ void initMidiInstruments() loadIDF(&fi); } } + QString path2 = QDir::homePath() + "/" + config.instrumentPath; + if (debugMsg) + printf("load instrument definitions from <%s>\n", path2.toLatin1().data()); + QDir instrumentsDir2(path2, QString("*.idf"), + QDir::SortFlags(QDir::Name | QDir::IgnoreCase), QDir::Files); + if (instrumentsDir2.exists()) { + QFileInfoList list = instrumentsDir2.entryInfoList(); + int n = list.size(); + for (int i = 0; i < n; ++i) { + QFileInfo fi = list.at(i); + loadIDF(&fi); + } + } } //--------------------------------------------------------- @@ -353,19 +399,20 @@ void MidiInstrument::read(QDomNode node) else if (tag == "Init") _midiInit->read(node.firstChild(), true); else if (tag == "SysEx") { - SysEx se; - se.name = e.attribute("name"); + SysEx* se = new SysEx; + se->name = e.attribute("name"); for (QDomNode nnode = node.firstChild(); !nnode.isNull(); nnode = nnode.nextSibling()) { e = nnode.toElement(); QString tag(e.tagName()); if (tag == "comment") - se.comment = e.text(); - else if (tag == "data") - se.data = e.text(); + se->comment = e.text(); + else if (tag == "data") { + se->dataLen = string2sysex(e.text(), &(se->data)); + } else printf("MidiInstrument::read():SysEx: unknown tag %s\n", tag.toLatin1().data()); } - sysex.push_back(se); + _sysex.append(se); } else if (!tag.isEmpty()) { printf("MidiInstrument::read(): unknown tag %s\n", tag.toLatin1().data()); diff --git a/muse/muse/instruments/minstrument.h b/muse/muse/instruments/minstrument.h index 5c7b081e..5bcf2616 100644 --- a/muse/muse/instruments/minstrument.h +++ b/muse/muse/instruments/minstrument.h @@ -71,7 +71,8 @@ struct PatchGroup { struct SysEx { QString name; QString comment; - QString data; + int dataLen; + unsigned char* data; }; //--------------------------------------------------------- @@ -81,7 +82,7 @@ struct SysEx { class MidiInstrument { std::vector pg; MidiControllerList* _controller; - std::vector sysex; + QList _sysex; bool _dirty; bool _readonly; @@ -127,11 +128,15 @@ class MidiInstrument { virtual void populatePatchPopup(QMenu*, int); void read(QDomNode); void write(Xml& xml); - std::vector* sysexList() { return &sysex; } + const QList& sysex() const { return _sysex; } + void removeSysex(SysEx* sysex) { _sysex.removeAll(sysex); } + void addSysex(SysEx* sysex) { _sysex.append(sysex); } + MidiController* midiController(int num) const; - std::vector* groups() { return &pg; } + std::vector* groups() { return &pg; } const QList& categories() const { return _categories; } + void addCategory(const QString& s) { _categories.append(s); } }; //--------------------------------------------------------- @@ -144,6 +149,7 @@ class MidiInstrumentList : public QList { typedef MidiInstrumentList::iterator iMidiInstrument; extern MidiInstrumentList midiInstruments; + extern MidiInstrument* genericMidiInstrument; extern void initMidiInstruments(); extern MidiInstrument* registerMidiInstrument(const QString&); diff --git a/muse/muse/midictrl.h b/muse/muse/midictrl.h index 895695e0..067aad6a 100644 --- a/muse/muse/midictrl.h +++ b/muse/muse/midictrl.h @@ -141,14 +141,10 @@ class MidiController { // - implicit during import of a midi file //--------------------------------------------------------- -class MidiControllerList : public std::list { - public: - MidiControllerList() {} - }; +class MidiControllerList : public QList {}; typedef MidiControllerList::iterator iMidiController; typedef MidiControllerList::const_iterator ciMidiController; -typedef MidiControllerList MidiControllerList; extern MidiControllerList defaultMidiController; extern void initMidiController(); diff --git a/muse/muse/muse.cpp b/muse/muse/muse.cpp index 156683ce..fa37cec5 100644 --- a/muse/muse/muse.cpp +++ b/muse/muse/muse.cpp @@ -2763,6 +2763,42 @@ void MusE::setGlobalTempo(int val) int main(int argc, char* argv[]) { + char c; + QString opts("mvdDiosP:p"); + +#ifdef VST_SUPPORT + opts += "V"; +#endif +#ifdef DSSI_SUPPORT + opts += "I"; +#endif + while ((c = getopt(argc, argv, opts.toLatin1().data())) != EOF) { + switch (c) { + case 'v': printVersion(argv[0]); return 0; + case 'd': + debugMode = true; + realTimePriority = false; + break; + case 'm': midiOnly = true; break; + case 'D': debugMsg = true; break; + case 'i': midiInputTrace = true; break; + case 'o': midiOutputTrace = true; break; + case 's': debugSync = true; break; + case 'p': loadPlugins = false; break; + case 'V': loadVST = false; break; + case 'I': loadDSSI = false; break; + default: usage(argv[0], "bad argument"); return -1; + } + } + if (midiOnly) { + loadDSSI = false; + loadPlugins = false; + loadVST = false; + } + + + + museUser = QString(getenv("MUSEHOME")); if (museUser.isEmpty()) museUser = QDir::homePath(); @@ -2810,39 +2846,6 @@ int main(int argc, char* argv[]) } } - char c; - QString opts("mvdDiosP:p"); - -#ifdef VST_SUPPORT - opts += "V"; -#endif -#ifdef DSSI_SUPPORT - opts += "I"; -#endif - while ((c = getopt(argc, argv, opts.toLatin1().data())) != EOF) { - switch (c) { - case 'v': printVersion(argv[0]); return 0; - case 'd': - debugMode = true; - realTimePriority = false; - break; - case 'm': midiOnly = true; break; - case 'D': debugMsg = true; break; - case 'i': midiInputTrace = true; break; - case 'o': midiOutputTrace = true; break; - case 's': debugSync = true; break; - case 'p': loadPlugins = false; break; - case 'V': loadVST = false; break; - case 'I': loadDSSI = false; break; - default: usage(argv[0], "bad argument"); return -1; - } - } - if (midiOnly) { - loadDSSI = false; - loadPlugins = false; - loadVST = false; - } - bool useJACK = !(debugMode || midiOnly); if (useJACK) { if (initJackAudio()) { @@ -2988,7 +2991,7 @@ int main(int argc, char* argv[]) // check for instruments directory: - pd.setPath(QDir::homePath() + "/MusE/instruments"); + pd.setPath(QDir::homePath() + "/" + config.instrumentPath); if (!pd.exists()) { // ask user to create a new instruments directory QString title(QT_TR_NOOP("MusE: create instruments directory")); diff --git a/muse/muse/preferences.cpp b/muse/muse/preferences.cpp index e0b9b4be..bcd1aa02 100644 --- a/muse/muse/preferences.cpp +++ b/muse/muse/preferences.cpp @@ -328,6 +328,7 @@ PreferencesDialog::PreferencesDialog(Arranger* a, QWidget* parent) showSplash->setChecked(config->showSplashScreen); projectPath->setText(config->projectPath); templatePath->setText(config->templatePath); + instrumentPath->setText(config->instrumentPath); midiImportPath->setText(config->importMidiPath); waveImportPath->setText(config->importWavePath); @@ -590,6 +591,7 @@ void PreferencesDialog::apply() ::config.projectPath = projectPath->text(); ::config.templatePath = templatePath->text(); + ::config.instrumentPath = instrumentPath->text(); ::config.importMidiPath = midiImportPath->text(); ::config.importWavePath = waveImportPath->text(); diff --git a/muse/muse/preferences.ui b/muse/muse/preferences.ui index c7adf58f..1c3d5ca5 100644 --- a/muse/muse/preferences.ui +++ b/muse/muse/preferences.ui @@ -139,46 +139,88 @@ 6 - - - - - - - - + + + + + 0 + 0 + 0 + 0 + + + + Projects + + + + + 0 + 0 + 0 + 0 + + Midi Import - - + + + + + + + + 0 + 0 + 0 + 0 + + - Wave Import + Templates - - + + + + + - Projects + Wave Import - - + + + + + + + + 0 + 0 + 0 + 0 + + - Templates + Instruments + + + @@ -2242,6 +2284,11 @@ + + RasterCombo + QComboBox +
rastercombo.h
+
QuantCombo QComboBox @@ -2257,11 +2304,6 @@ QToolButton
recordbutton.h
- - RasterCombo - QComboBox -
rastercombo.h
-
-- cgit v1.2.3