diff options
Diffstat (limited to 'attic/muse2-oom/muse2/muse/instruments')
-rw-r--r-- | attic/muse2-oom/muse2/muse/instruments/CMakeLists.txt | 89 | ||||
-rw-r--r-- | attic/muse2-oom/muse2/muse/instruments/ccontrolbase.ui | 525 | ||||
-rw-r--r-- | attic/muse2-oom/muse2/muse/instruments/editinstrument.cpp | 3588 | ||||
-rw-r--r-- | attic/muse2-oom/muse2/muse/instruments/editinstrument.h | 91 | ||||
-rw-r--r-- | attic/muse2-oom/muse2/muse/instruments/editinstrumentbase.ui | 1649 | ||||
-rw-r--r-- | attic/muse2-oom/muse2/muse/instruments/midictrledit.cpp | 725 | ||||
-rw-r--r-- | attic/muse2-oom/muse2/muse/instruments/midictrledit.h | 56 | ||||
-rw-r--r-- | attic/muse2-oom/muse2/muse/instruments/minstrument.cpp | 927 | ||||
-rw-r--r-- | attic/muse2-oom/muse2/muse/instruments/minstrument.h | 145 |
9 files changed, 7795 insertions, 0 deletions
diff --git a/attic/muse2-oom/muse2/muse/instruments/CMakeLists.txt b/attic/muse2-oom/muse2/muse/instruments/CMakeLists.txt new file mode 100644 index 00000000..b068798a --- /dev/null +++ b/attic/muse2-oom/muse2/muse/instruments/CMakeLists.txt @@ -0,0 +1,89 @@ +#============================================================================= +# MusE +# Linux Music Editor +# $Id:$ +# +# Copyright (C) 2002-2006 by Werner Schweer and others +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +#============================================================================= + +## +## Expand Qt macros in source files +## +QT4_WRAP_CPP ( instruments_mocs + editinstrument.h + # minstrument.h + ) + +## +## UI files +## +file (GLOB instruments_ui_files + # ccontrollerbase.ui # not built. It needs to be converted to Qt4 for revival. + editinstrumentbase.ui + ) +QT4_WRAP_UI ( instruments_uis ${instruments_ui_files} ) + +## +## List of source files to compile +## +file (GLOB instruments_source_files + editinstrument.cpp + editinstrument.h + minstrument.cpp + minstrument.h + ) + +## +## Define target +## +add_library ( instruments SHARED + ${instruments_source_files} + ${instruments_mocs} + ${instruments_uis} + ) + +## +## Append to the list of translations +## +set (FILES_TO_TRANSLATE + ${FILES_TO_TRANSLATE} + ${instruments_source_files} + ${instruments_ui_files} + CACHE INTERNAL "" + ) + +## +## Compilation flags and target name +## +set_target_properties( instruments + PROPERTIES COMPILE_FLAGS "-include ${PROJECT_BINARY_DIR}/all.h -fPIC" + OUTPUT_NAME muse_instruments + ) + +## +## Linkage +## +target_link_libraries ( instruments + ${QT_LIBRARIES} + icons + ) + +## +## Install location +## +install(TARGETS instruments + DESTINATION ${MusE_MODULES_DIR} + ) + diff --git a/attic/muse2-oom/muse2/muse/instruments/ccontrolbase.ui b/attic/muse2-oom/muse2/muse/instruments/ccontrolbase.ui new file mode 100644 index 00000000..3094776f --- /dev/null +++ b/attic/muse2-oom/muse2/muse/instruments/ccontrolbase.ui @@ -0,0 +1,525 @@ +<!DOCTYPE UI><UI version="3.1" stdsetdef="1"> +<class>MidiControllerEditDialogBase</class> +<widget class="QDialog"> + <property name="name"> + <cstring>MidiControllerEditDialogBase</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>698</width> + <height>457</height> + </rect> + </property> + <property name="caption"> + <string>MusE: Define Midi Controller</string> + </property> + <property name="sizeGripEnabled"> + <bool>true</bool> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QLayoutWidget" row="3" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>Layout2</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QPushButton"> + <property name="name"> + <cstring>buttonNew</cstring> + </property> + <property name="text"> + <string>&Add</string> + </property> + <property name="accel"> + <string>Alt+A</string> + </property> + <property name="autoDefault"> + <bool>false</bool> + </property> + <property name="toolTip" stdset="0"> + <string>create new entry</string> + </property> + <property name="whatsThis" stdset="0"> + <string>pressing the New button you create a new entry +in the MusE list of defined controllers</string> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>buttonDelete</cstring> + </property> + <property name="text"> + <string>&Delete</string> + </property> + <property name="autoDefault"> + <bool>false</bool> + </property> + <property name="toolTip" stdset="0"> + <string>delete selected entry</string> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>Spacer1</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>0</height> + </size> + </property> + </spacer> + <widget class="QPushButton"> + <property name="name"> + <cstring>buttonOk</cstring> + </property> + <property name="text"> + <string>&OK</string> + </property> + <property name="autoDefault"> + <bool>false</bool> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>buttonApply</cstring> + </property> + <property name="text"> + <string>A&pply</string> + </property> + <property name="autoDefault"> + <bool>false</bool> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>buttonCancel</cstring> + </property> + <property name="text"> + <string>&Cancel</string> + </property> + <property name="autoDefault"> + <bool>false</bool> + </property> + </widget> + </hbox> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>Predefined Controller:</string> + </property> + </widget> + <widget class="QListView" row="1" column="1"> + <column> + <property name="text"> + <string>Name </string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <column> + <property name="text"> + <string>Type </string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <column> + <property name="text"> + <string>H-Ctrl</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>false</bool> + </property> + </column> + <column> + <property name="text"> + <string>L-Ctrl</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>false</bool> + </property> + </column> + <column> + <property name="text"> + <string>Min Val</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>false</bool> + </property> + </column> + <column> + <property name="text"> + <string>Max Val</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>false</bool> + </property> + </column> + <property name="name"> + <cstring>viewController</cstring> + </property> + <property name="frameShape"> + <enum>StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>Sunken</enum> + </property> + <property name="allColumnsShowFocus"> + <bool>true</bool> + </property> + <property name="toolTip" stdset="0"> + <string>list of defined controllers</string> + </property> + <property name="whatsThis" stdset="0"> + <string>This is the MusE list of defined controllers.</string> + </property> + </widget> + <widget class="QLayoutWidget" row="0" column="1"> + <property name="name"> + <cstring>layout2</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel2</cstring> + </property> + <property name="text"> + <string>Managed Controller for Port</string> + </property> + </widget> + <widget class="QComboBox"> + <property name="name"> + <cstring>midiPortsList</cstring> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel3</cstring> + </property> + <property name="text"> + <string>Channel</string> + </property> + </widget> + <widget class="QSpinBox"> + <property name="name"> + <cstring>midiChannel</cstring> + </property> + <property name="maxValue"> + <number>16</number> + </property> + <property name="minValue"> + <number>1</number> + </property> + </widget> + </hbox> + </widget> + <widget class="QListBox" row="1" column="0" rowspan="2" colspan="1"> + <property name="name"> + <cstring>listController</cstring> + </property> + <property name="whatsThis" stdset="0"> + <string>This is a list of commonly used midi controllers. +Note that in MusE pitch and program changes are +handled like normal controllers.</string> + </property> + </widget> + <widget class="QGroupBox" row="2" column="1"> + <property name="name"> + <cstring>GroupBox1</cstring> + </property> + <property name="title"> + <string>Properties</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>TextLabel1</cstring> + </property> + <property name="text"> + <string>Name</string> + </property> + </widget> + <widget class="QLayoutWidget" row="2" column="1"> + <property name="name"> + <cstring>layout3</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>TextLabel1_2</cstring> + </property> + <property name="text"> + <string>Min Value</string> + </property> + <property name="indent"> + <number>10</number> + </property> + </widget> + <widget class="QSpinBox"> + <property name="name"> + <cstring>spinboxMin</cstring> + </property> + <property name="maxValue"> + <number>16384</number> + </property> + <property name="minValue"> + <number>-16385</number> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>TextLabel2_2</cstring> + </property> + <property name="text"> + <string>Max Value</string> + </property> + <property name="indent"> + <number>10</number> + </property> + </widget> + <widget class="QSpinBox"> + <property name="name"> + <cstring>spinboxMax</cstring> + </property> + <property name="maxValue"> + <number>16384</number> + </property> + <property name="minValue"> + <number>-16385</number> + </property> + <property name="value"> + <number>127</number> + </property> + </widget> + </hbox> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>TextLabel2</cstring> + </property> + <property name="text"> + <string>Type</string> + </property> + </widget> + <widget class="QLineEdit" row="0" column="1"> + <property name="name"> + <cstring>entryName</cstring> + </property> + </widget> + <widget class="QLayoutWidget" row="1" column="1"> + <property name="name"> + <cstring>layout5</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QComboBox"> + <item> + <property name="text"> + <string>Control7</string> + </property> + </item> + <item> + <property name="text"> + <string>Control14</string> + </property> + </item> + <item> + <property name="text"> + <string>RPN</string> + </property> + </item> + <item> + <property name="text"> + <string>NRPN</string> + </property> + </item> + <item> + <property name="text"> + <string>RPN14</string> + </property> + </item> + <item> + <property name="text"> + <string>NRPN14</string> + </property> + </item> + <item> + <property name="text"> + <string>Pitch</string> + </property> + </item> + <item> + <property name="text"> + <string>Program</string> + </property> + </item> + <property name="name"> + <cstring>comboType</cstring> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>TextLabel3</cstring> + </property> + <property name="text"> + <string>H-Ctrl</string> + </property> + <property name="indent"> + <number>10</number> + </property> + </widget> + <widget class="QSpinBox"> + <property name="name"> + <cstring>spinboxHCtrlNo</cstring> + </property> + <property name="maxValue"> + <number>127</number> + </property> + <property name="minValue"> + <number>0</number> + </property> + <property name="value"> + <number>1</number> + </property> + <property name="toolTip" stdset="0"> + <string>Midi Controller Number High Byte</string> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>TextLabel2_3</cstring> + </property> + <property name="text"> + <string>L-Ctrl</string> + </property> + <property name="indent"> + <number>10</number> + </property> + </widget> + <widget class="QSpinBox"> + <property name="name"> + <cstring>spinboxLCtrlNo</cstring> + </property> + <property name="maxValue"> + <number>127</number> + </property> + <property name="minValue"> + <number>0</number> + </property> + <property name="value"> + <number>1</number> + </property> + <property name="toolTip" stdset="0"> + <string>Midi Controller Number Low Byte</string> + </property> + </widget> + </hbox> + </widget> + <widget class="QLabel" row="2" column="0"> + <property name="name"> + <cstring>textLabel4</cstring> + </property> + <property name="text"> + <string>Range</string> + </property> + </widget> + </grid> + </widget> + </grid> +</widget> +<connections> + <connection> + <sender>buttonCancel</sender> + <signal>clicked()</signal> + <receiver>MidiControllerEditDialogBase</receiver> + <slot>reject()</slot> + </connection> + <connection> + <sender>buttonOk</sender> + <signal>clicked()</signal> + <receiver>MidiControllerEditDialogBase</receiver> + <slot>accept()</slot> + </connection> +</connections> +<tabstops> + <tabstop>viewController</tabstop> + <tabstop>entryName</tabstop> + <tabstop>comboType</tabstop> + <tabstop>spinboxHCtrlNo</tabstop> + <tabstop>spinboxLCtrlNo</tabstop> + <tabstop>spinboxMin</tabstop> + <tabstop>spinboxMax</tabstop> + <tabstop>buttonNew</tabstop> + <tabstop>buttonDelete</tabstop> + <tabstop>buttonOk</tabstop> + <tabstop>buttonApply</tabstop> + <tabstop>buttonCancel</tabstop> +</tabstops> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/attic/muse2-oom/muse2/muse/instruments/editinstrument.cpp b/attic/muse2-oom/muse2/muse/instruments/editinstrument.cpp new file mode 100644 index 00000000..c45ac97a --- /dev/null +++ b/attic/muse2-oom/muse2/muse/instruments/editinstrument.cpp @@ -0,0 +1,3588 @@ +//========================================================= +// MusE +// Linux Music Editor +// $Id: editinstrument.cpp,v 1.2.2.6 2009/05/31 05:12:12 terminator356 Exp $ +// +// (C) Copyright 2003 Werner Schweer (ws@seh.de) +//========================================================= + +#include <stdio.h> +#include <errno.h> + +#include <QCloseEvent> +#include <QDir> +#include <QFileDialog> +#include <QFileInfo> +#include <QInputDialog> +#include <QMessageBox> +#include <QLineEdit> +#include <QWhatsThis> + +#include "editinstrument.h" +#include "minstrument.h" +#include "globals.h" +#include "song.h" +#include "xml.h" +#include "midictrl.h" +#include "gconfig.h" +#include "icons.h" + + +enum { + COL_NAME = 0, COL_TYPE, + COL_HNUM, COL_LNUM, COL_MIN, COL_MAX, COL_DEF + }; + +//--------------------------------------------------------- +// EditInstrument +//--------------------------------------------------------- + +EditInstrument::EditInstrument(QWidget* parent, Qt::WFlags fl) + : QMainWindow(parent, fl) + { + setupUi(this); + fileNewAction->setIcon(QIcon(*filenewIcon)); + fileOpenAction->setIcon(QIcon(*openIcon)); + fileSaveAction->setIcon(QIcon(*saveIcon)); + fileSaveAsAction->setIcon(QIcon(*saveasIcon)); + fileExitAction->setIcon(QIcon(*exitIcon)); + viewController->setSelectionMode(QAbstractItemView::SingleSelection); + toolBar->addAction(QWhatsThis::createAction(this)); + Help->addAction(QWhatsThis::createAction(this)); + + ///patchpopup = new QMenu(patchButton); + //patchpopup->setCheckable(false);// Qt4 doc says this is unnecessary. + + // populate instrument list + // Populate common controller list. + for(int i = 0; i < 128; ++i) + { + QListWidgetItem *lci = new QListWidgetItem(midiCtrlName(i)); + listController->addItem(lci); + } + oldMidiInstrument = 0; + oldPatchItem = 0; + for (iMidiInstrument i = midiInstruments.begin(); i != midiInstruments.end(); ++i) { + // Imperfect, crude way of ignoring internal instruments, soft synths etc. If it has a gui, + // it must be an internal instrument. But this will still allow some vst instruments (without a gui) + // to show up in the list. + // Hmm, try file path instead... + //if((*i)->hasGui()) + if((*i)->filePath().isEmpty()) + continue; + + QListWidgetItem* item = new QListWidgetItem((*i)->iname()); + QVariant v = qVariantFromValue((void*)(*i)); + item->setData(Qt::UserRole, v); + instrumentList->addItem(item); + } + instrumentList->setSelectionMode(QAbstractItemView::SingleSelection); + if(instrumentList->item(0)) + instrumentList->setCurrentItem(instrumentList->item(0)); + //oldMidiInstrument = (MidiInstrument*)((ListBoxData*)instrumentList->item(0))->data(); + //oldMidiInstrument = (ListBoxData*)instrumentList->item(0); + //oldMidiInstrument = (ListBoxData*)instrumentList->selectedItem(); + +// MidiInstrument* wip = (MidiInstrument*)((ListBoxData*)instrumentList->item(0))->data(); +// if(wip) + // Assignment +// workingInstrument.assign( *wip ); + + + connect(instrumentList, SIGNAL(itemSelectionChanged()), SLOT(instrumentChanged())); + connect(patchView, SIGNAL(itemSelectionChanged()), SLOT(patchChanged())); + + //instrumentChanged(); + changeInstrument(); + + //connect(listController, SIGNAL(selectionChanged()), SLOT(controllerChanged())); + connect(viewController, SIGNAL(itemSelectionChanged()), SLOT(controllerChanged())); + + //connect(instrumentName, SIGNAL(textChanged(const QString&)), SLOT(instrumentNameChanged(const QString&))); + connect(instrumentName, SIGNAL(returnPressed()), SLOT(instrumentNameReturn())); + connect(instrumentName, SIGNAL(lostFocus()), SLOT(instrumentNameReturn())); + + connect(patchNameEdit, SIGNAL(returnPressed()), SLOT(patchNameReturn())); + connect(patchNameEdit, SIGNAL(lostFocus()), SLOT(patchNameReturn())); + connect(patchDelete, SIGNAL(clicked()), SLOT(deletePatchClicked())); + connect(patchNew, SIGNAL(clicked()), SLOT(newPatchClicked())); + connect(patchNewGroup, SIGNAL(clicked()), SLOT(newGroupClicked())); + //connect(newCategory, SIGNAL(clicked()), SLOT(newCategoryClicked())); + + connect(patchButton, SIGNAL(clicked()), SLOT(patchButtonClicked())); + connect(defPatchH, SIGNAL(valueChanged(int)), SLOT(defPatchChanged(int))); + connect(defPatchL, SIGNAL(valueChanged(int)), SLOT(defPatchChanged(int))); + connect(defPatchProg, SIGNAL(valueChanged(int)), SLOT(defPatchChanged(int))); + connect(deleteController, SIGNAL(clicked()), SLOT(deleteControllerClicked())); + connect(newController, SIGNAL(clicked()), SLOT(newControllerClicked())); + connect(addController, SIGNAL(clicked()), SLOT(addControllerClicked())); + connect(listController, SIGNAL(itemDoubleClicked(QListWidgetItem*)), SLOT(addControllerClicked())); + connect(ctrlType,SIGNAL(activated(int)), SLOT(ctrlTypeChanged(int))); + connect(ctrlName, SIGNAL(returnPressed()), SLOT(ctrlNameReturn())); + connect(ctrlName, SIGNAL(lostFocus()), SLOT(ctrlNameReturn())); + //connect(ctrlName, SIGNAL(textChanged(const QString&)), SLOT(ctrlNameChanged(const QString&))); + connect(spinBoxHCtrlNo, SIGNAL(valueChanged(int)), SLOT(ctrlHNumChanged(int))); + connect(spinBoxLCtrlNo, SIGNAL(valueChanged(int)), SLOT(ctrlLNumChanged(int))); + connect(spinBoxMin, SIGNAL(valueChanged(int)), SLOT(ctrlMinChanged(int))); + connect(spinBoxMax, SIGNAL(valueChanged(int)), SLOT(ctrlMaxChanged(int))); + connect(spinBoxDefault, SIGNAL(valueChanged(int)), SLOT(ctrlDefaultChanged(int))); + connect(nullParamSpinBoxH, SIGNAL(valueChanged(int)), SLOT(ctrlNullParamHChanged(int))); + connect(nullParamSpinBoxL, SIGNAL(valueChanged(int)), SLOT(ctrlNullParamLChanged(int))); + + connect(tabWidget3, SIGNAL(currentChanged(QWidget*)), SLOT(tabChanged(QWidget*))); + //connect(sysexList, SIGNAL(selectionChanged()), SLOT(sysexChanged())); + //connect(deleteSysex, SIGNAL(clicked()), SLOT(deleteSysexClicked())); + //connect(newSysex, SIGNAL(clicked()), SLOT(newSysexClicked())); + } + +//--------------------------------------------------------- +// helpWhatsThis +//--------------------------------------------------------- + +void EditInstrument::helpWhatsThis() +{ + whatsThis(); +} + +//--------------------------------------------------------- +// fileNew +//--------------------------------------------------------- + +void EditInstrument::fileNew() + { + // Allow these to update... + instrumentNameReturn(); + patchNameReturn(); + ctrlNameReturn(); + + 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) { + //if(oldMidiInstrument) + //{ + MidiInstrument* oi = 0; + if(oldMidiInstrument) + oi = (MidiInstrument*)oldMidiInstrument->data(Qt::UserRole).value<void*>(); + MidiInstrument* wip = &workingInstrument; + //checkDirty(oi); + //if(checkDirty(oi)) + if(checkDirty(wip)) + // No save was chosen. Restore the actual instrument name. + { + if(oi) + { + oldMidiInstrument->setText(oi->iname()); + //workingInstrument.setIName(oi->iname()); + + // No file path? Only a new unsaved instrument can do that. So delete it. + if(oi->filePath().isEmpty()) + // Delete the list item and the instrument. + deleteInstrument(oldMidiInstrument); + + } + } + //else + //{ + // if(oi) + // Save was chosen. Assign the working instrument to the actual instrument. + // oi->assign(workingInstrument); + //} + + //oi->setDirty(false); + workingInstrument.setDirty(false); + //} + + MidiInstrument* ni = new MidiInstrument(s); + //midiInstruments.append(ni); + midiInstruments.push_back(ni); + //QListWidgetItem* item = new QListWidgetItem(ni->iname()); + //InstrumentListItem* item = new InstrumentListItem(ni->iname()); + QListWidgetItem* item = new QListWidgetItem(ni->iname()); + + //oldMidiInstrument = item; + workingInstrument.assign( *ni ); + //workingInstrument.setDirty(false); + + //item->setText(ni->iname()); + QVariant v = qVariantFromValue((void*)(ni)); + item->setData(Qt::UserRole, v); + instrumentList->addItem(item); + + oldMidiInstrument = 0; + + instrumentList->blockSignals(true); + instrumentList->setCurrentItem(item); + instrumentList->blockSignals(false); + + changeInstrument(); + + // We have our new instrument! So set dirty to true. + workingInstrument.setDirty(true); + + break; + } + } + + } + +//--------------------------------------------------------- +// fileOpen +//--------------------------------------------------------- + +void EditInstrument::fileOpen() + { + // Allow these to update... + //instrumentNameReturn(); + //patchNameReturn(); + //ctrlNameReturn(); + + + } + +//--------------------------------------------------------- +// fileSave +//--------------------------------------------------------- + +void EditInstrument::fileSave() +{ + //if (instrument->filePath().isEmpty()) + if (workingInstrument.filePath().isEmpty()) + { + //fileSaveAs(); + saveAs(); + return; + } + + // Do not allow a direct overwrite of a 'built-in' muse instrument. + QFileInfo qfi(workingInstrument.filePath()); + if(qfi.absolutePath() == museInstruments) + { + //fileSaveAs(); + saveAs(); + return; + } + + //QFile f(instrument->filePath()); + //if (!f.open(QIODevice::WriteOnly)) { + //FILE* f = fopen(instrument->filePath().toLatin1().constData(), "w"); + FILE* f = fopen(workingInstrument.filePath().toLatin1().constData(), "w"); + if(f == 0) + { + //fileSaveAs(); + saveAs(); + return; + } + + // Allow these to update... + instrumentNameReturn(); + patchNameReturn(); + ctrlNameReturn(); + + //f.close(); + if(fclose(f) != 0) + { + //QString s = QString("Creating file:\n") + instrument->filePath() + QString("\nfailed: ") + QString s = QString("Creating file:\n") + workingInstrument.filePath() + QString("\nfailed: ") + //+ f.errorString(); + + QString(strerror(errno) ); + //fprintf(stderr, "poll failed: %s\n", strerror(errno)); + QMessageBox::critical(this, tr("MusE: Create file failed"), s); + return; + } + + //if(fileSave(instrument, instrument->filePath())) + // instrument->setDirty(false); + if(fileSave(&workingInstrument, workingInstrument.filePath())) + workingInstrument.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); + + FILE* f = fopen(name.toAscii().constData(), "w"); + if(f == 0) + { + //if(debugMsg) + // printf("READ IDF %s\n", fi->filePath().toLatin1().constData()); + QString s("Creating file failed: "); + s += QString(strerror(errno)); + QMessageBox::critical(this, + tr("MusE: Create file failed"), s); + return false; + } + + Xml xml(f); + + updateInstrument(instrument); + + //instrument->write(xml); + instrument->write(0, xml); + + // Assign the working instrument values to the actual current selected instrument... + if(oldMidiInstrument) + { + MidiInstrument* oi = (MidiInstrument*)oldMidiInstrument->data(Qt::UserRole).value<void*>(); + if(oi) + { + oi->assign(workingInstrument); + + // Now signal the rest of the app so stuff can change... + song->update(SC_CONFIG | SC_MIDI_CONTROLLER); + //song->update(SC_CONFIG | SC_MIDI_CONTROLLER | SC_MIDI_CONTROLLER_ADD); + } + } + + //f.close(); + //if (f.error()) { + if(fclose(f) != 0) + { + QString s = QString("Write File\n") + name + QString("\nfailed: ") + //+ f.errorString(); + + QString(strerror(errno)); + //fprintf(stderr, "poll failed: %s\n", strerror(errno)); + QMessageBox::critical(this, tr("MusE: Write File failed"), s); + return false; + } + return true; + } + +//--------------------------------------------------------- +// saveAs +//--------------------------------------------------------- + +void EditInstrument::saveAs() + { + // Allow these to update... + instrumentNameReturn(); + patchNameReturn(); + ctrlNameReturn(); + + //QListWidgetItem* item = instrumentList->currentItem(); +// ListBoxData* item = (ListBoxData*)instrumentList->selectedItem(); +// if (item == 0) +// return; + //MidiInstrument* instrument = (MidiInstrument*)item->data(Qt::UserRole).value<void*>(); +// MidiInstrument* instrument = (MidiInstrument*)item->data(); + + //QString path = QDir::homePath() + "/" + config.instrumentPath; + //QString path = QDir::homeDirPath() + "/" + museGlobalShare; + //QString path = museInstruments; + QString path = museUserInstruments; + + if(!QDir(museUserInstruments).exists()) + { + if(QMessageBox::question(this, + tr("MusE:"), + tr("The user instrument directory\n") + museUserInstruments + tr("\ndoes not exist yet. Create it now?\n") + + tr("(You can change the user instruments directory at Settings->Global Settings->Midi)"), + QMessageBox::Ok | QMessageBox::Default, + QMessageBox::Cancel | QMessageBox::Escape, + Qt::NoButton) == QMessageBox::Ok) + { + if(QDir().mkdir(museUserInstruments)) + printf("Created user instrument directory: %s\n", museUserInstruments.toLatin1().constData()); + else + { + printf("Unable to create user instrument directory: %s\n", museUserInstruments.toLatin1().constData()); + QMessageBox::critical(this, tr("MusE:"), tr("Unable to create user instrument directory\n") + museUserInstruments); + //return; + path = museUser; + } + } + else + // return; + path = museUser; + } + + //if (instrument->filePath().isEmpty()) + if (workingInstrument.filePath().isEmpty()) + path += QString("/%1.idf").arg(workingInstrument.iname()); + else { + //QFileInfo fi(instrument->filePath()); + QFileInfo fi(workingInstrument.filePath()); + + // Prompt for a new instrument name if the name has not been changed, to avoid duplicates. + if(oldMidiInstrument) + { + MidiInstrument* oi = (MidiInstrument*)oldMidiInstrument->data(Qt::UserRole).value<void*>(); + if(oi) + { + if(oi->iname() == workingInstrument.iname()) + { + // Prompt only if it's a user instrument, to avoid duplicates in the user instrument dir. + // This will still allow a user instrument to override a built-in instrument with the same name. + if(fi.absolutePath() != museInstruments) + { + //QMessageBox::critical(this, + // tr("MusE: Bad instrument name"), + // tr("Please change the instrument name to a new unique name before saving, to avoid duplicates"), + // QMessageBox::Ok, + // QMessageBox::NoButton, + // QMessageBox::NoButton); + printf("EditInstrument::saveAs Error: Instrument name %s already used!\n", workingInstrument.iname().toLatin1().constData()); + return; + } + } + } + } + path += QString("/%1.idf").arg(fi.baseName()); + } + //QString s = QFileDialog::getSaveFileName(this, + // tr("MusE: Save Instrument Definition"), + // path, + // tr("Instrument Definition (*.idf)")); + + QString s = QFileDialog::getSaveFileName(this, tr("MusE: Save Instrument Definition").toLatin1().constData(), + path, tr("Instrument Definition (*.idf)")); + if (s.isEmpty()) + return; + //instrument->setFilePath(s); + workingInstrument.setFilePath(s); + + //if (fileSave(instrument, s)) + // instrument->setDirty(false); + if(fileSave(&workingInstrument, s)) + workingInstrument.setDirty(false); + } + +//--------------------------------------------------------- +// fileSaveAs +//--------------------------------------------------------- + +void EditInstrument::fileSaveAs() + { + // Is this a new unsaved instrument? Just do a normal save. + if(workingInstrument.filePath().isEmpty()) + { + saveAs(); + return; + } + + // Allow these to update... + instrumentNameReturn(); + patchNameReturn(); + ctrlNameReturn(); + + MidiInstrument* oi = 0; + if(oldMidiInstrument) + oi = (MidiInstrument*)oldMidiInstrument->data(Qt::UserRole).value<void*>(); + + int res = checkDirty(&workingInstrument, true); + switch(res) + { + // No save: + case 1: + //item->setText(instrument->iname()); + //instrumentList->triggerUpdate(true); + //instrument->setDirty(false); + workingInstrument.setDirty(false); + if(oi) + { + oldMidiInstrument->setText(oi->iname()); + //workingInstrument.setIName(oi->iname()); + + //workingInstrument.assign(*oi); + + // No file path? Only a new unsaved instrument can do that. So delete it. + if(oi->filePath().isEmpty()) + { + // Delete the list item and the instrument. + deleteInstrument(oldMidiInstrument); + oldMidiInstrument = 0; + } + + changeInstrument(); + + } + return; + break; + + // Abort: + case 2: + return; + break; + + // Save: + case 0: + //if(oi) + // oi->assign(workingInstrument); + workingInstrument.setDirty(false); + break; + } + + //QListWidgetItem* item = instrumentList->currentItem(); +// ListBoxData* item = (ListBoxData*)instrumentList->selectedItem(); +// if (item == 0) +// return; + //MidiInstrument* instrument = (MidiInstrument*)item->data(Qt::UserRole).value<void*>(); +// MidiInstrument* instrument = (MidiInstrument*)item->data(); + + bool isuser = false; + QString so; + if(workingInstrument.iname().isEmpty()) + so = QString("Instrument"); + else + so = workingInstrument.iname(); + + for(int i = 1;; ++i) + { + QString s = so + QString("-%1").arg(i); + + bool found = false; + for(iMidiInstrument imi = midiInstruments.begin(); imi != midiInstruments.end(); ++imi) + { + if(s == (*imi)->iname()) + { + // Allow override of built-in instrument names. + QFileInfo fi((*imi)->filePath()); + if(fi.absolutePath() == museInstruments) + break; + found = true; + break; + } + } + if(found) + continue; + + bool ok; + s = QInputDialog::getText(this, tr("MusE: Save instrument as"), tr("Enter a new unique instrument name:"), + QLineEdit::Normal, s, &ok); + if(!ok) + return; + if(s.isEmpty()) + { + --i; + continue; + } + + isuser = false; + bool builtin = false; + found = false; + for(iMidiInstrument imi = midiInstruments.begin(); imi != midiInstruments.end(); ++imi) + { + // If an instrument with the same name is found... + if((*imi)->iname() == s) + { + // If it's not the same name as the working instrument, and it's not an internal instrument (soft synth etc.)... + if(s != workingInstrument.iname() && !(*imi)->filePath().isEmpty()) + { + QFileInfo fi((*imi)->filePath()); + // Allow override of built-in and user instruments: + // If it's a user instrument, not a built-in instrument... + if(fi.absolutePath() == museUserInstruments) + { + // No choice really but to overwrite the destination instrument file! + // Can not have two user files containing the same instrument name. + if(QMessageBox::question(this, + tr("MusE: Save instrument as"), + tr("The user instrument:\n") + s + tr("\nalready exists. This will overwrite its .idf instrument file.\nAre you sure?"), + QMessageBox::Ok | QMessageBox::Default, + QMessageBox::Cancel | QMessageBox::Escape, + Qt::NoButton) == QMessageBox::Ok) + { + // Set the working instrument's file path to the found instrument's path. + workingInstrument.setFilePath((*imi)->filePath()); + // Mark as overwriting a user instrument. + isuser = true; + } + else + { + found = true; + break; + } + } + // Assign the found instrument to the working instrument. + //workingInstrument.assign(*(*imi)); + // Assign the found instrument name to the working instrument name. + workingInstrument.setIName(s); + + // Find the instrument in the list and set the old instrument to the item. + oldMidiInstrument = instrumentList->findItems(s, Qt::MatchExactly)[0]; + + // Mark as a built-in instrument. + builtin = true; + break; + } + found = true; + break; + } + } + if(found) + { + so = s; + i = 0; + continue; + } + + so = s; + + // If the name does not belong to a built-in instrument... + if(!builtin) + { + MidiInstrument* ni = new MidiInstrument(); + ni->assign(workingInstrument); + ni->setIName(so); + ni->setFilePath(QString()); + //midiInstruments.append(ni); + midiInstruments.push_back(ni); + //QListWidgetItem* item = new QListWidgetItem(ni->iname()); + //InstrumentListItem* item = new InstrumentListItem(ni->iname()); + //ListBoxData* item = new ListBoxData(ni->iname()); + QListWidgetItem* item = new QListWidgetItem(so); + + //oldMidiInstrument = item; + workingInstrument.assign( *ni ); + //workingInstrument.setDirty(false); + + //item->setText(ni->iname()); + //item->setData((void*)ni); + QVariant v = qVariantFromValue((void*)(ni)); + item->setData(Qt::UserRole, v); + //instrumentList->addItem(item); + instrumentList->addItem(item); + + oldMidiInstrument = 0; + + instrumentList->blockSignals(true); + instrumentList->setCurrentItem(item); + instrumentList->blockSignals(false); + + changeInstrument(); + + // We have our new instrument! So set dirty to true. + workingInstrument.setDirty(true); + } + + break; + } + + //QString path = QDir::homePath() + "/" + config.instrumentPath; + //QString path = QDir::homeDirPath() + "/" + museGlobalShare; + //QString path = museInstruments; + QString path = museUserInstruments; + + if(!QDir(museUserInstruments).exists()) + { + if(QMessageBox::question(this, + tr("MusE:"), + tr("The user instrument directory\n") + museUserInstruments + tr("\ndoes not exist yet. Create it now?\n") + + tr("(You can change the user instruments directory at Settings->Global Settings->Midi)"), + QMessageBox::Ok | QMessageBox::Default, + QMessageBox::Cancel | QMessageBox::Escape, + Qt::NoButton) == QMessageBox::Ok) + { + if(QDir().mkdir(museUserInstruments)) + printf("Created user instrument directory: %s\n", museUserInstruments.toLatin1().constData()); + else + { + printf("Unable to create user instrument directory: %s\n", museUserInstruments.toLatin1().constData()); + QMessageBox::critical(this, tr("MusE:"), tr("Unable to create user instrument directory\n") + museUserInstruments); + //return; + path = museUser; + } + } + else + // return; + path = museUser; + } + path += QString("/%1.idf").arg(so); + + //QString s = QFileDialog::getSaveFileName(this, + // tr("MusE: Save Instrument Definition"), + // path, + // tr("Instrument Definition (*.idf)")); + + QString sfn; + // If we are overwriting a user instrument just force the path. + if(isuser) + sfn = path; + else + { + sfn = QFileDialog::getSaveFileName(this, tr("MusE: Save Instrument Definition").toLatin1().constData(), + path, tr("Instrument Definition (*.idf)")); + if (sfn.isEmpty()) + return; + //instrument->setFilePath(s); + workingInstrument.setFilePath(sfn); + } + + //if (fileSave(instrument, s)) + // instrument->setDirty(false); + if(fileSave(&workingInstrument, sfn)) + workingInstrument.setDirty(false); + } + +//--------------------------------------------------------- +// fileExit +//--------------------------------------------------------- + +void EditInstrument::fileExit() + { + + } + +//--------------------------------------------------------- +// closeEvent +//--------------------------------------------------------- + +void EditInstrument::closeEvent(QCloseEvent* ev) + { + // Allow these to update... + instrumentNameReturn(); + patchNameReturn(); + ctrlNameReturn(); + + //QListWidgetItem* item = instrumentList->currentItem(); + +// ListBoxData* item = (ListBoxData*)instrumentList->selectedItem(); + +// if(item) +// { + //MidiInstrument* instrument = (MidiInstrument*)item->data(Qt::UserRole).value<void*>(); +// MidiInstrument* instrument = (MidiInstrument*)item->data(); +// int res = checkDirty(instrument, true); + MidiInstrument* oi = 0; + if(oldMidiInstrument) + oi = (MidiInstrument*)oldMidiInstrument->data(Qt::UserRole).value<void*>(); + + int res = checkDirty(&workingInstrument, true); + switch(res) + { + // No save: + case 1: + //item->setText(instrument->iname()); + //instrumentList->triggerUpdate(true); + //instrument->setDirty(false); + workingInstrument.setDirty(false); + if(oi) + { + oldMidiInstrument->setText(oi->iname()); + //workingInstrument.setIName(oi->iname()); + + //workingInstrument.assign(*oi); + + // No file path? Only a new unsaved instrument can do that. So delete it. + if(oi->filePath().isEmpty()) + { + // Delete the list item and the instrument. + deleteInstrument(oldMidiInstrument); + oldMidiInstrument = 0; + } + + changeInstrument(); + + } + break; + + // Abort: + case 2: + ev->ignore(); + return; + break; + + // Save: + case 0: + //if(oi) + // oi->assign(workingInstrument); + workingInstrument.setDirty(false); + break; + + } + +// } + + QMainWindow::closeEvent(ev); + } + +//--------------------------------------------------------- +// changeInstrument +//--------------------------------------------------------- + +void EditInstrument::changeInstrument() +{ + QListWidgetItem* sel = instrumentList->currentItem(); + + if(!sel) + return; + + //oldMidiInstrument = (MidiInstrument*)sel->data(); + oldMidiInstrument = sel; + // Assignment + //workingInstrument = *((MidiInstrument*)sel->data()); + + // Assign will 'delete' any existing patches, groups, or controllers. + workingInstrument.assign( *((MidiInstrument*)sel->data(Qt::UserRole).value<void*>()) ); + + workingInstrument.setDirty(false); + + // populate patch list + patchView->blockSignals(true); + for (int i = 0; i < patchView->topLevelItemCount(); ++i) + qDeleteAll(patchView->topLevelItem(i)->takeChildren()); + patchView->clear(); + patchView->blockSignals(false); + + //viewController->blockSignals(true); + for (int i = 0; i < viewController->topLevelItemCount(); ++i) + qDeleteAll(viewController->topLevelItem(i)->takeChildren()); + viewController->clear(); + //viewController->blockSignals(false); + + //listController->clear(); + //category->clear(); + //sysexList->clear(); + + + //MidiInstrument* instrument = (MidiInstrument*)sel->data(Qt::UserRole).value<void*>(); + //MidiInstrument* instrument = (MidiInstrument*)sel->data(); + //instrument->setDirty(false); + + instrumentName->blockSignals(true); + //instrumentName->setText(instrument->iname()); + instrumentName->setText(workingInstrument.iname()); + instrumentName->blockSignals(false); + + nullParamSpinBoxH->blockSignals(true); + nullParamSpinBoxL->blockSignals(true); + int nv = workingInstrument.nullSendValue(); + if(nv == -1) + { + nullParamSpinBoxH->setValue(-1); + nullParamSpinBoxL->setValue(-1); + } + else + { + int nvh = (nv >> 8) & 0xff; + int nvl = nv & 0xff; + if(nvh == 0xff) + nullParamSpinBoxH->setValue(-1); + else + nullParamSpinBoxH->setValue(nvh & 0x7f); + if(nvl == 0xff) + nullParamSpinBoxL->setValue(-1); + else + nullParamSpinBoxL->setValue(nvl & 0x7f); + } + nullParamSpinBoxH->blockSignals(false); + nullParamSpinBoxL->blockSignals(false); + + //std::vector<PatchGroup>* pg = instrument->groups(); + //PatchGroupList* pg = instrument->groups(); + PatchGroupList* pg = workingInstrument.groups(); + //for (std::vector<PatchGroup>::iterator g = pg->begin(); g != pg->end(); ++g) { + for (ciPatchGroup g = pg->begin(); g != pg->end(); ++g) { + PatchGroup* pgp = *g; + if(pgp) + { + //QTreeWidgetItem* item = new QTreeWidgetItem; + QTreeWidgetItem* item = new QTreeWidgetItem(patchView); + + //item->setText(0, g->name); + item->setText(0, pgp->name); + //QVariant v = QVariant::fromValue((void*)0); + //item->setData(0, Qt::UserRole, v); + //item->setData((void*)*g); + //item->setData((void*)0); + //item->setData((void*)&*g); + //item->setData((void*)pgp); + QVariant v = qVariantFromValue((void*)(pgp)); + item->setData(0, Qt::UserRole, v); + //patchView->addTopLevelItem(item); + + //for (ciPatch p = g->patches.begin(); p != g->patches.end(); ++p) + for (ciPatch p = pgp->patches.begin(); p != pgp->patches.end(); ++p) + { + //const Patch& patch = *p; + Patch* patch = *p; + if(patch) + { + //QTreeWidgetItem* sitem = new QTreeWidgetItem; + QTreeWidgetItem* sitem = new QTreeWidgetItem(item); + //printf("%s \n", qPrintable(patch->name)); + + //sitem->setText(0, patch.name); + //sitem->setText(0, p->name); + sitem->setText(0, patch->name); + //QVariant v = QVariant::fromValue((void*)patch); + //sitem->setData(0, Qt::UserRole, v); + //sitem->setData((void*)&*p); + //sitem->setData((void*)patch); + QVariant v = QVariant::fromValue((void*)patch); + sitem->setData(0, Qt::UserRole, v); + //item->addChild(sitem); + } + } + } + } + //patchView->setSelected(patchView->item(0), true); + + oldPatchItem = 0; + + QTreeWidgetItem* fc = patchView->topLevelItem(0); + if(fc) + { + // This may cause a patchChanged call. + //if(patchView->selectedItem() != fc) + patchView->blockSignals(true); + fc->setSelected(true); + patchView->blockSignals(false); + //else + // patchChanged(); + + //patchView->firstChild()->setSelected(true); + //patchView->triggerUpdate(true); + } + + patchChanged(); + +// oldPatchItem = (ListViewData*)patchView->selectedItem(); + //patchChanged(); +// if(oldPatchItem) +// { +// if(oldPatchItem->parent()) +// patchNameEdit->setText( ((Patch*)oldPatchItem->data())->name ); +// else +// patchNameEdit->setText( ((PatchGroup*)oldPatchItem->data())->name ); +// } + + //MidiControllerList* cl = instrument->controller(); + MidiControllerList* cl = workingInstrument.controller(); + for (ciMidiController ic = cl->begin(); ic != cl->end(); ++ic) { + MidiController* c = ic->second; + //QListWidgetItem* item = new QListWidgetItem(c->name()); + // ListBoxData* item = new ListBoxData(c->name()); + //QVariant v = QVariant::fromValue((void*)c); + //item->setData(Qt::UserRole, v); + // item->setData((void*)c); + // listController->insertItem(item); + + addControllerToView(c); + } + + + //listController->setItemSelected(listController->item(0), true); + +// oldController = 0; + + //ListBoxData* ci = (ListBoxData*)listController->item(0); + + QTreeWidgetItem *ci = viewController->topLevelItem(0); + + if(ci) + { + // This may cause a controllerChanged call. + //if(listController->selectedItem != ci) + // listController->blockSignals(true); + // listController->setSelected(ci, true); + // listController->blockSignals(false); + //else + // controllerChanged(); + + viewController->blockSignals(true); + ci->setSelected(true); + viewController->blockSignals(false); + } + + controllerChanged(); + + //oldController = (ListBoxData*)listController->selectedItem(); + + + //controllerChanged(listController->item(0), 0); + //controllerChanged(); + +/* + category->addItems(instrument->categories()); + + foreach(const SysEx* s, instrument->sysex()) { + QListWidgetItem* item = new QListWidgetItem(s->name); + QVariant v = QVariant::fromValue((void*)s); + item->setData(Qt::UserRole, v); + sysexList->addItem(item); + } + + sysexList->setItemSelected(sysexList->item(0), true); + sysexChanged(sysexList->item(0), 0); + + if (!cl->empty()) { + listController->setItemSelected(listController->item(0), true); + controllerChanged(listController->item(0), 0); + } +*/ + + +} + +//--------------------------------------------------------- +// instrumentChanged +//--------------------------------------------------------- + +void EditInstrument::instrumentChanged() + { + QListWidgetItem* sel = instrumentList->currentItem(); + + if(!sel) + return; + + //printf("instrument changed: %s\n", sel->text().toLatin1().constData()); + + //if (old) { + //if(oldMidiInstrument) + //{ + MidiInstrument* oi = 0; + if(oldMidiInstrument) + oi = (MidiInstrument*)oldMidiInstrument->data(Qt::UserRole).value<void*>(); + MidiInstrument* wip = &workingInstrument; + // Returns true if aborted. + //checkDirty(oi); + //if(checkDirty(oi)) + if(checkDirty(wip)) + { + // No save was chosen. Abandon changes, or delete if it is new... + if(oi) + { + oldMidiInstrument->setText(oi->iname()); + //wip->setText(oi->iname()); + + // No file path? Only a new unsaved instrument can do that. So delete it. + if(oi->filePath().isEmpty()) + { + // Delete the list item and the instrument. + deleteInstrument(oldMidiInstrument); + oldMidiInstrument = 0; + } + + } + } + //else + //{ + // Save was chosen. + // if(oi) + // oi->assign(workingInstrument); + //} + + //oi->setDirty(false); + //wip->setDirty(false); + workingInstrument.setDirty(false); + //} + + changeInstrument(); + + } + +//--------------------------------------------------------- +// instrumentNameReturn +//--------------------------------------------------------- + +void EditInstrument::instrumentNameReturn() +//void EditInstrument::instrumentNameChanged(const QString& s) +{ + //instrumentNameChanged(instrumentName->text()); + QListWidgetItem* item = instrumentList->currentItem(); + + if (item == 0) + return; + QString s = instrumentName->text(); + + if(s == item->text()) + return; + + MidiInstrument* curins = (MidiInstrument*)item->data(Qt::UserRole).value<void*>(); + + for(iMidiInstrument i = midiInstruments.begin(); i != midiInstruments.end(); ++i) + { + if((*i) != curins && s == (*i)->iname()) + { + instrumentName->blockSignals(true); + // Grab the last valid name from the item text, since the instrument has not been updated yet. + //instrumentName->setText(curins->iname()); + instrumentName->setText(item->text()); + instrumentName->blockSignals(false); + + QMessageBox::critical(this, + tr("MusE: Bad instrument name"), + tr("Please choose a unique instrument name.\n(The name might be used by a hidden instrument.)"), + QMessageBox::Ok, + Qt::NoButton, + Qt::NoButton); + + return; + } + } + + //if (s != workingInstrument.iname()) { + item->setText(s); + //MidiInstrument* instrument = (MidiInstrument*)item->data(Qt::UserRole).value<void*>(); + //MidiInstrument* instrument = (MidiInstrument*)item->data(); + //instrument->setDirty(true); + workingInstrument.setIName(s); + workingInstrument.setDirty(true); + //instrumentList->updateItem(item); + //instrumentList->update(); + // } +} + +//--------------------------------------------------------- +// deleteInstrument +//--------------------------------------------------------- + +void EditInstrument::deleteInstrument(QListWidgetItem* item) +{ + if(!item) + return; + + //ListBoxData* curritem = (ListBoxData*)instrumentList->selectedItem(); + + MidiInstrument* ins = (MidiInstrument*)item->data(Qt::UserRole).value<void*>(); + + // Be kind to the list item, just in case we install a delete handler or something. + //item->setData(0); + + // Delete the list item. + // Test this: Is this going to change the current selection? + instrumentList->blockSignals(true); + delete item; + instrumentList->blockSignals(false); + + // Test this: Neccessary? + // if(curritem) + // instrumentList->setCurrentItem(curritem); + + if(!ins) + return; + + // Remove the instrument from the list. + midiInstruments.remove(ins); + + // Delete the instrument. + delete ins; +} + +//--------------------------------------------------------- +// tabChanged +// Added so that patch list is updated when switching tabs, +// so that 'Program' default values and text are current in controller tab. +//--------------------------------------------------------- + +void EditInstrument::tabChanged(QWidget* w) +{ + if(!w) + return; + + // If we're switching to the Patches tab, just ignore. + if(QString(w->objectName()) == QString("patchesTab")) + return; + + if(oldPatchItem) + { + // Don't bother calling patchChanged, just update the patch or group. + if(oldPatchItem->QTreeWidgetItem::parent()) + updatePatch(&workingInstrument, (Patch*)oldPatchItem->data(0, Qt::UserRole).value<void*>()); + else + updatePatchGroup(&workingInstrument, (PatchGroup*)oldPatchItem->data(0, Qt::UserRole).value<void*>()); + } + + // We're still on the same item. No need to set oldPatchItem as in patchChanged... + + // If we're switching to the Controller tab, update the default patch button text in case a patch changed... + if(QString(w->objectName()) == QString("controllerTab")) + { + QTreeWidgetItem* sel = viewController->currentItem(); + + if(!sel || !sel->data(0, Qt::UserRole).value<void*>()) + return; + + MidiController* c = (MidiController*)sel->data(0, Qt::UserRole).value<void*>(); + MidiController::ControllerType type = midiControllerType(c->num()); + + // Grab the controller number from the actual values showing + // and set the patch button text. + if(type == MidiController::Program) + setDefaultPatchName(getDefaultPatchNumber()); + } +} + +//--------------------------------------------------------- +// patchNameReturn +//--------------------------------------------------------- + +void EditInstrument::patchNameReturn() +{ + QTreeWidgetItem* item = patchView->currentItem(); + + if (item == 0) + return; + + QString s = patchNameEdit->text(); + + if(item->text(0) == s) + return; + + PatchGroupList* pg = workingInstrument.groups(); + for(iPatchGroup g = pg->begin(); g != pg->end(); ++g) + { + PatchGroup* pgp = *g; + // If the item has a parent, it's a patch item. + if(item->QTreeWidgetItem::parent()) + { + Patch* curp = (Patch*)item->data(0, Qt::UserRole).value<void*>(); + for(iPatch p = pgp->patches.begin(); p != pgp->patches.end(); ++p) + { + if((*p) != curp && (*p)->name == s) + { + patchNameEdit->blockSignals(true); + // Grab the last valid name from the item text, since the patch has not been updated yet. + //patchNameEdit->setText(curp->name); + patchNameEdit->setText(item->text(0)); + patchNameEdit->blockSignals(false); + + QMessageBox::critical(this, + tr("MusE: Bad patch name"), + tr("Please choose a unique patch name"), + QMessageBox::Ok, + Qt::NoButton, + Qt::NoButton); + + return; + } + } + } + else + // The item has no parent. It's a patch group item. + { + PatchGroup* curpg = (PatchGroup*)item->data(0, Qt::UserRole).value<void*>(); + if(pgp != curpg && pgp->name == s) + { + patchNameEdit->blockSignals(true); + // Grab the last valid name from the item text, since the patch group has not been updated yet. + //patchNameEdit->setText(curpg->name); + patchNameEdit->setText(item->text(0)); + patchNameEdit->blockSignals(false); + + QMessageBox::critical(this, + tr("MusE: Bad patchgroup name"), + tr("Please choose a unique patchgroup name"), + QMessageBox::Ok, + Qt::NoButton, + Qt::NoButton); + + return; + } + } + } + + item->setText(0, s); + workingInstrument.setDirty(true); + + // Since the name of the patch/group in the working instrument will be updated later, + // there's no need to do manually set the name here now. + /* + // If the item has a parent, it's a patch item. + if(item->parent()) + { + Patch* p = item->data(); + if(s != p->name) + { + item->setText(s); + p->name = s; + workingInstrument.setDirty(true); + //patchView->triggerUpdate(true); + } + } + else + // The item has no parent. It's a patch group item. + { + PatchGroup* pg = (PatchGroup*)item->data(); + if(s != pg->name) + { + item->setText(s); + pg->name = s; + workingInstrument.setDirty(true); + //patchView->triggerUpdate(true); + } + } + */ +} + +//--------------------------------------------------------- +// patchChanged +//--------------------------------------------------------- +void EditInstrument::patchChanged() + { + //if (old && old->data(0, Qt::UserRole).value<void*>()) { + if(oldPatchItem) + { + //QListWidgetItem* item = instrumentList->currentItem(); + //if (item == 0) + // return; + //MidiInstrument* instrument = (MidiInstrument*)item->data(Qt::UserRole).value<void*>(); + //Patch* p = (Patch*)old->data(0, Qt::UserRole).value<void*>(); + //updatePatch(instrument, p); + if(oldPatchItem->parent()) + updatePatch(&workingInstrument, (Patch*)oldPatchItem->data(0, Qt::UserRole).value<void*>()); + else + updatePatchGroup(&workingInstrument, (PatchGroup*)oldPatchItem->data(0, Qt::UserRole).value<void*>()); + } + + QTreeWidgetItem* sel = patchView->selectedItems().size() ? patchView->selectedItems()[0] : 0; + oldPatchItem = sel; + + if(!sel || !sel->data(0, Qt::UserRole).value<void*>()) + { + patchNameEdit->setText(""); + spinBoxHBank->setEnabled(false); + spinBoxLBank->setEnabled(false); + spinBoxProgram->setEnabled(false); + checkBoxDrum->setEnabled(false); + checkBoxGM->setEnabled(false); + checkBoxGS->setEnabled(false); + checkBoxXG->setEnabled(false); + return; + } + + // If the item has a parent, it's a patch item. + if(sel->parent()) + { + Patch* p = (Patch*)sel->data(0, Qt::UserRole).value<void*>(); + patchNameEdit->setText(p->name); + spinBoxHBank->setEnabled(true); + spinBoxLBank->setEnabled(true); + spinBoxProgram->setEnabled(true); + checkBoxDrum->setEnabled(true); + checkBoxGM->setEnabled(true); + checkBoxGS->setEnabled(true); + checkBoxXG->setEnabled(true); + + int hb = ((p->hbank + 1) & 0xff); + int lb = ((p->lbank + 1) & 0xff); + int pr = ((p->prog + 1) & 0xff); + spinBoxHBank->setValue(hb); + spinBoxLBank->setValue(lb); + spinBoxProgram->setValue(pr); + //checkBoxDrum->setChecked(p->drumMap); + checkBoxDrum->setChecked(p->drum); + checkBoxGM->setChecked(p->typ & 1); + checkBoxGS->setChecked(p->typ & 2); + checkBoxXG->setChecked(p->typ & 4); + //category->setCurrentIndex(p->categorie); + } + else + // The item is a patch group item. + { + patchNameEdit->setText( ((PatchGroup*)sel->data(0, Qt::UserRole).value<void*>())->name ); + spinBoxHBank->setEnabled(false); + spinBoxLBank->setEnabled(false); + spinBoxProgram->setEnabled(false); + checkBoxDrum->setEnabled(false); + checkBoxGM->setEnabled(false); + checkBoxGS->setEnabled(false); + checkBoxXG->setEnabled(false); + } + } + +//--------------------------------------------------------- +// defPatchChanged +//--------------------------------------------------------- + +void EditInstrument::defPatchChanged(int) +{ + QTreeWidgetItem* item = viewController->currentItem(); + + if (!item) + return; + + MidiController* c = (MidiController*)item->data(0, Qt::UserRole).value<void*>(); + + int val = getDefaultPatchNumber(); + + //if(val == c->minVal() - 1) + // c->setInitVal(CTRL_VAL_UNKNOWN); + //else + c->setInitVal(val); + + setDefaultPatchName(val); + + item->setText(COL_DEF, getPatchItemText(val)); + workingInstrument.setDirty(true); +} + +//--------------------------------------------------------- +// patchButtonClicked +//--------------------------------------------------------- + +void EditInstrument::patchButtonClicked() +{ + //MidiTrack* track = (MidiTrack*)selected; + //int channel = track->outChannel(); + //int port = track->outPort(); + //MidiInstrument* instr = midiPorts[port].instrument(); + + //patchpopup->clear(); + + QMenu* patchpopup = new QMenu; + + PatchGroupList* pg = workingInstrument.groups(); + + if (pg->size() > 1) { + for (ciPatchGroup i = pg->begin(); i != pg->end(); ++i) { + PatchGroup* pgp = *i; + QMenu* pm = patchpopup->addMenu(pgp->name); + //pm->setCheckable(false);//Qt4 doc says this is unnecessary + pm->setFont(config.fonts[0]); + const PatchList& pl = pgp->patches; + for (ciPatch ipl = pl.begin(); ipl != pl.end(); ++ipl) { + const Patch* mp = *ipl; + //if ((mp->typ & mask) && + // ((drum && songType != MT_GM) || + // (mp->drum == drumchan)) ) + + // { + int id = ((mp->hbank & 0xff) << 16) + + ((mp->lbank & 0xff) << 8) + (mp->prog & 0xff); + QAction *ac1 = pm->addAction(mp->name); + ac1->setData(id); + // } + + } + } + } + else if (pg->size() == 1 ){ + // no groups + const PatchList& pl = pg->front()->patches; + for (ciPatch ipl = pl.begin(); ipl != pl.end(); ++ipl) { + const Patch* mp = *ipl; + //if (mp->typ & mask) { + int id = ((mp->hbank & 0xff) << 16) + + ((mp->lbank & 0xff) << 8) + (mp->prog & 0xff); + QAction *ac2 = patchpopup->addAction(mp->name); + ac2->setData(id); + // } + } + } + + if(patchpopup->actions().count() == 0) + { + delete patchpopup; + return; + } + + QAction* act = patchpopup->exec(patchButton->mapToGlobal(QPoint(10,5))); + if(!act) + { + delete patchpopup; + return; + } + + int rv = act->data().toInt(); + delete patchpopup; + + if (rv != -1) + { + //if(rv != workingInstrument. + + setDefaultPatchControls(rv); + + QTreeWidgetItem* item = viewController->currentItem(); + + if(item) + { + MidiController* c = (MidiController*)item->data(0, Qt::UserRole).value<void*>(); + c->setInitVal(rv); + + item->setText(COL_DEF, getPatchItemText(rv)); + } + workingInstrument.setDirty(true); + } + +} + +//--------------------------------------------------------- +// addControllerToView +//--------------------------------------------------------- + +QTreeWidgetItem* EditInstrument::addControllerToView(MidiController* mctrl) +{ + QString hnum; + QString lnum; + QString min; + QString max; + QString def; + int defval = mctrl->initVal(); + int n = mctrl->num(); + //int h = (n >> 7) & 0x7f; + int h = (n >> 8) & 0x7f; + int l = n & 0x7f; + if((n & 0xff) == 0xff) + l = -1; + + MidiController::ControllerType t = midiControllerType(n); + switch(t) + { + case MidiController::Controller7: + //case MidiController::RPN: + //case MidiController::NRPN: + hnum = "---"; + if(l == -1) + lnum = "*"; + else + lnum.setNum(l); + min.setNum(mctrl->minVal()); + max.setNum(mctrl->maxVal()); + if(defval == CTRL_VAL_UNKNOWN) + def = "---"; + else + def.setNum(defval); + break; + case MidiController::RPN: + case MidiController::NRPN: + case MidiController::RPN14: + case MidiController::NRPN14: + case MidiController::Controller14: + hnum.setNum(h); + if(l == -1) + lnum = "*"; + else + lnum.setNum(l); + min.setNum(mctrl->minVal()); + max.setNum(mctrl->maxVal()); + if(defval == CTRL_VAL_UNKNOWN) + def = "---"; + else + def.setNum(defval); + break; + case MidiController::Pitch: + hnum = "---"; + lnum = "---"; + min.setNum(mctrl->minVal()); + max.setNum(mctrl->maxVal()); + if(defval == CTRL_VAL_UNKNOWN) + def = "---"; + else + def.setNum(defval); + break; + case MidiController::Program: + hnum = "---"; + lnum = "---"; + min = "---"; + max = "---"; + def = getPatchItemText(defval); + break; + + default: + hnum = "---"; + lnum = "---"; + //min.setNum(0); + //max.setNum(0); + min = "---"; + max = "---"; + def = "---"; + break; + } + + QTreeWidgetItem* ci = new QTreeWidgetItem(viewController, QStringList() << mctrl->name() << int2ctrlType(t) << hnum << lnum << min << max << def); + //ListViewData* ci = new ListViewData(viewController, mctrl->name(), int2ctrlType(t), + // hnum, lnum, min, max, def); + //ci->setData((void*)mctrl); + QVariant v = qVariantFromValue((void*)(mctrl)); + ci->setData(0, Qt::UserRole, v); + //setModified(true); + + return ci; +} + +//--------------------------------------------------------- +// controllerChanged +//--------------------------------------------------------- + +void EditInstrument::controllerChanged() + { + //if (old) { +// if(oldController) +// { + //QListWidgetItem* item = instrumentList->currentItem(); + //if (item == 0) + // return; + //MidiInstrument* instrument = (MidiInstrument*)item->data(Qt::UserRole).value<void*>(); + //MidiController* oc = (MidiController*)old->data(Qt::UserRole).value<void*>(); + //updateController(instrument, oc); +// updateController(&workingInstrument, (MidiController*)oldController->data()); +// } + + // ListBoxData* sel = (ListBoxData*)listController->selectedItem(); + + QTreeWidgetItem* sel = viewController->selectedItems().size() ? viewController->selectedItems()[0] : 0; +// oldController = sel; + + if(!sel || !sel->data(0, Qt::UserRole).value<void*>()) + { + ctrlName->blockSignals(true); + ctrlName->setText(""); + ctrlName->blockSignals(false); + //ctrlComment->setText(""); + return; + } + + MidiController* c = (MidiController*)sel->data(0, Qt::UserRole).value<void*>(); + + ctrlName->blockSignals(true); + ctrlName->setText(c->name()); + ctrlName->blockSignals(false); + + //ctrlComment->setText(c->comment()); + int ctrlH = (c->num() >> 8) & 0x7f; + int ctrlL = c->num() & 0x7f; + if((c->num() & 0xff) == 0xff) + ctrlL = -1; + + //int type = int(c->type()); + MidiController::ControllerType type = midiControllerType(c->num()); + + //ctrlType->setCurrentIndex(type); + ctrlType->blockSignals(true); + ctrlType->setCurrentIndex(type); + ctrlType->blockSignals(false); + + //ctrlTypeChanged(type); + + spinBoxHCtrlNo->blockSignals(true); + spinBoxLCtrlNo->blockSignals(true); + spinBoxMin->blockSignals(true); + spinBoxMax->blockSignals(true); + spinBoxDefault->blockSignals(true); + + //ctrlTypeChanged(type); + + switch (type) { + //case MidiController::RPN: + //case MidiController::NRPN: + case MidiController::Controller7: + spinBoxHCtrlNo->setEnabled(false); + spinBoxLCtrlNo->setEnabled(true); + spinBoxHCtrlNo->setValue(0); + spinBoxLCtrlNo->setValue(ctrlL); + spinBoxMin->setEnabled(true); + spinBoxMax->setEnabled(true); + spinBoxMin->setRange(-128, 127); + spinBoxMax->setRange(-128, 127); + spinBoxMin->setValue(c->minVal()); + spinBoxMax->setValue(c->maxVal()); + enableDefaultControls(true, false); + break; + case MidiController::RPN: + case MidiController::NRPN: + spinBoxHCtrlNo->setEnabled(true); + spinBoxLCtrlNo->setEnabled(true); + spinBoxHCtrlNo->setValue(ctrlH); + spinBoxLCtrlNo->setValue(ctrlL); + spinBoxMin->setEnabled(true); + spinBoxMax->setEnabled(true); + spinBoxMin->setRange(-128, 127); + spinBoxMax->setRange(-128, 127); + spinBoxMin->setValue(c->minVal()); + spinBoxMax->setValue(c->maxVal()); + enableDefaultControls(true, false); + break; + case MidiController::Controller14: + case MidiController::RPN14: + case MidiController::NRPN14: + spinBoxHCtrlNo->setEnabled(true); + spinBoxLCtrlNo->setEnabled(true); + spinBoxHCtrlNo->setValue(ctrlH); + spinBoxLCtrlNo->setValue(ctrlL); + spinBoxMin->setEnabled(true); + spinBoxMax->setEnabled(true); + spinBoxMin->setRange(-16384, 16383); + spinBoxMax->setRange(-16384, 16383); + spinBoxMin->setValue(c->minVal()); + spinBoxMax->setValue(c->maxVal()); + enableDefaultControls(true, false); + break; + case MidiController::Pitch: + spinBoxHCtrlNo->setEnabled(false); + spinBoxLCtrlNo->setEnabled(false); + spinBoxHCtrlNo->setValue(0); + spinBoxLCtrlNo->setValue(0); + spinBoxMin->setEnabled(true); + spinBoxMax->setEnabled(true); + spinBoxMin->setRange(-8192, 8191); + spinBoxMax->setRange(-8192, 8191); + spinBoxMin->setValue(c->minVal()); + spinBoxMax->setValue(c->maxVal()); + enableDefaultControls(true, false); + break; + case MidiController::Program: + spinBoxHCtrlNo->setEnabled(false); + spinBoxLCtrlNo->setEnabled(false); + spinBoxHCtrlNo->setValue(0); + spinBoxLCtrlNo->setValue(0); + spinBoxMin->setEnabled(false); + spinBoxMax->setEnabled(false); + spinBoxMin->setRange(0, 0); + spinBoxMax->setRange(0, 0); + spinBoxMin->setValue(0); + spinBoxMax->setValue(0); + enableDefaultControls(false, true); + break; + default: + spinBoxHCtrlNo->setEnabled(false); + spinBoxLCtrlNo->setEnabled(false); + spinBoxMin->setEnabled(false); + spinBoxMax->setEnabled(false); + enableDefaultControls(false, false); + break; + } + + if(type == MidiController::Program) + { + spinBoxDefault->setRange(0, 0); + spinBoxDefault->setValue(0); + setDefaultPatchControls(c->initVal()); + } + else + { + spinBoxDefault->setRange(c->minVal() - 1, c->maxVal()); + if(c->initVal() == CTRL_VAL_UNKNOWN) + //spinBoxDefault->setValue(c->minVal() - 1); + spinBoxDefault->setValue(spinBoxDefault->minimum()); + else + spinBoxDefault->setValue(c->initVal()); + } + + //moveWithPart->setChecked(c->moveWithPart()); + + spinBoxHCtrlNo->blockSignals(false); + spinBoxLCtrlNo->blockSignals(false); + spinBoxMin->blockSignals(false); + spinBoxMax->blockSignals(false); + spinBoxDefault->blockSignals(false); + } + +//--------------------------------------------------------- +// ctrlNameReturn +//--------------------------------------------------------- + +void EditInstrument::ctrlNameReturn() +//void EditInstrument::ctrlNameChanged(const QString& s) +{ + QTreeWidgetItem* item = viewController->currentItem(); + + if (item == 0) + return; + MidiController* c = (MidiController*)item->data(0, Qt::UserRole).value<void*>(); + + QString cName = ctrlName->text(); + + if(c->name() == cName) + return; + + //MidiControllerList* cl = instrument->controller(); + MidiControllerList* cl = workingInstrument.controller(); + for(ciMidiController ic = cl->begin(); ic != cl->end(); ++ic) + { + MidiController* mc = ic->second; + if(mc != c && mc->name() == cName) + { + ctrlName->blockSignals(true); + ctrlName->setText(c->name()); + ctrlName->blockSignals(false); + + QMessageBox::critical(this, + tr("MusE: Bad controller name"), + tr("Please choose a unique controller name"), + QMessageBox::Ok, + Qt::NoButton, + Qt::NoButton); + + return; + } + } + + c->setName(ctrlName->text()); + item->setText(COL_NAME, ctrlName->text()); + //c->setName(s); + //item->setText(COL_NAME, s); + workingInstrument.setDirty(true); +} + +//--------------------------------------------------------- +// ctrlTypeChanged +//--------------------------------------------------------- + +void EditInstrument::ctrlTypeChanged(int idx) + { + QTreeWidgetItem* item = viewController->currentItem(); + + if (item == 0) + return; + + MidiController::ControllerType t = (MidiController::ControllerType)idx; + MidiController* c = (MidiController*)item->data(0, Qt::UserRole).value<void*>(); + if(t == midiControllerType(c->num())) + return; + + //if(item) + item->setText(COL_TYPE, ctrlType->currentText()); + + int hnum = 0, lnum = 0; + //int rng = 0; + //int min = 0, max = 0; + + spinBoxMin->blockSignals(true); + spinBoxMax->blockSignals(true); + spinBoxDefault->blockSignals(true); + + switch (t) { + //case MidiController::RPN: + //case MidiController::NRPN: + case MidiController::Controller7: + spinBoxHCtrlNo->setEnabled(false); + spinBoxLCtrlNo->setEnabled(true); + spinBoxMin->setEnabled(true); + spinBoxMax->setEnabled(true); + enableDefaultControls(true, false); + spinBoxMin->setRange(-128, 127); + spinBoxMax->setRange(-128, 127); + + spinBoxMin->setValue(0); + spinBoxMax->setValue(127); + spinBoxDefault->setRange(spinBoxMin->value() - 1, spinBoxMax->value()); + + spinBoxDefault->setValue(spinBoxDefault->minimum()); + lnum = spinBoxLCtrlNo->value(); + //rng = 127; + //min = -128; + //max = 127; + //if(item) + //{ + //item->setText(COL_LNUM, QString().setNum(spinBoxLCtrlNo->value())); + if(lnum == -1) + item->setText(COL_LNUM, QString("*")); + else + item->setText(COL_LNUM, QString().setNum(lnum)); + item->setText(COL_HNUM, QString("---")); + item->setText(COL_MIN, QString().setNum(spinBoxMin->value())); + item->setText(COL_MAX, QString().setNum(spinBoxMax->value())); + item->setText(COL_DEF, QString("---")); + //} + break; + case MidiController::RPN: + case MidiController::NRPN: + spinBoxHCtrlNo->setEnabled(true); + spinBoxLCtrlNo->setEnabled(true); + spinBoxMin->setEnabled(true); + spinBoxMax->setEnabled(true); + enableDefaultControls(true, false); + spinBoxMin->setRange(-128, 127); + spinBoxMax->setRange(-128, 127); + + spinBoxMin->setValue(0); + spinBoxMax->setValue(127); + spinBoxDefault->setRange(spinBoxMin->value() - 1, spinBoxMax->value()); + spinBoxDefault->setValue(spinBoxDefault->minimum()); + + hnum = spinBoxHCtrlNo->value(); + lnum = spinBoxLCtrlNo->value(); + //rng = 127; + //min = -128; + //max = 127; + //if(item) + //{ + //item->setText(COL_LNUM, QString().setNum(spinBoxLCtrlNo->value())); + //item->setText(COL_HNUM, QString().setNum(spinBoxHCtrlNo->value())); + if(lnum == -1) + item->setText(COL_LNUM, QString("*")); + else + item->setText(COL_LNUM, QString().setNum(lnum)); + item->setText(COL_HNUM, QString().setNum(hnum)); + item->setText(COL_MIN, QString().setNum(spinBoxMin->value())); + item->setText(COL_MAX, QString().setNum(spinBoxMax->value())); + item->setText(COL_DEF, QString("---")); + //} + break; + case MidiController::Controller14: + case MidiController::RPN14: + case MidiController::NRPN14: + spinBoxHCtrlNo->setEnabled(true); + spinBoxLCtrlNo->setEnabled(true); + spinBoxMin->setEnabled(true); + spinBoxMax->setEnabled(true); + enableDefaultControls(true, false); + spinBoxMin->setRange(-16384, 16383); + spinBoxMax->setRange(-16384, 16383); + + spinBoxMin->setValue(0); + spinBoxMax->setValue(16383); + spinBoxDefault->setRange(spinBoxMin->value() - 1, spinBoxMax->value()); + spinBoxDefault->setValue(spinBoxDefault->minimum()); + + hnum = spinBoxHCtrlNo->value(); + lnum = spinBoxLCtrlNo->value(); + //rng = 16383; + //min = -16384; + //max = 16383; + //if(item) + //{ + //item->setText(COL_LNUM, QString().setNum(spinBoxLCtrlNo->value())); + //item->setText(COL_HNUM, QString().setNum(spinBoxHCtrlNo->value())); + if(lnum == -1) + item->setText(COL_LNUM, QString("*")); + else + item->setText(COL_LNUM, QString().setNum(lnum)); + item->setText(COL_HNUM, QString().setNum(hnum)); + item->setText(COL_MIN, QString().setNum(spinBoxMin->value())); + item->setText(COL_MAX, QString().setNum(spinBoxMax->value())); + item->setText(COL_DEF, QString("---")); + //} + break; + case MidiController::Pitch: + spinBoxHCtrlNo->setEnabled(false); + spinBoxLCtrlNo->setEnabled(false); + spinBoxMin->setEnabled(true); + spinBoxMax->setEnabled(true); + enableDefaultControls(true, false); + spinBoxMin->setRange(-8192, 8191); + spinBoxMax->setRange(-8192, 8191); + + spinBoxMin->setValue(-8192); + spinBoxMax->setValue(8191); + spinBoxDefault->setRange(spinBoxMin->value() - 1, spinBoxMax->value()); + spinBoxDefault->setValue(spinBoxDefault->minimum()); + + //rng = 8191; + //min = -8192; + //max = 8191; + //if(item) + //{ + item->setText(COL_LNUM, QString("---")); + item->setText(COL_HNUM, QString("---")); + item->setText(COL_MIN, QString().setNum(spinBoxMin->value())); + item->setText(COL_MAX, QString().setNum(spinBoxMax->value())); + item->setText(COL_DEF, QString("---")); + //} + break; + case MidiController::Program: + spinBoxHCtrlNo->setEnabled(false); + spinBoxLCtrlNo->setEnabled(false); + spinBoxMin->setEnabled(false); + spinBoxMax->setEnabled(false); + enableDefaultControls(false, true); + spinBoxMin->setRange(0, 0); + spinBoxMax->setRange(0, 0); + + spinBoxMin->setValue(0); + spinBoxMax->setValue(0); + spinBoxDefault->setRange(0, 0); + spinBoxDefault->setValue(0); + + //if(item) + //{ + item->setText(COL_LNUM, QString("---")); + item->setText(COL_HNUM, QString("---")); + item->setText(COL_MIN, QString("---")); + item->setText(COL_MAX, QString("---")); + + //item->setText(COL_DEF, QString("0-0-0")); + item->setText(COL_DEF, QString("---")); + //} + break; + // Shouldn't happen... + default: + spinBoxHCtrlNo->setEnabled(false); + spinBoxLCtrlNo->setEnabled(false); + spinBoxMin->setEnabled(false); + spinBoxMax->setEnabled(false); + enableDefaultControls(false, false); + + spinBoxMin->blockSignals(false); + spinBoxMax->blockSignals(false); + return; + + break; + } + + spinBoxMin->blockSignals(false); + spinBoxMax->blockSignals(false); + spinBoxDefault->blockSignals(false); + + c->setNum(MidiController::genNum(t, hnum, lnum)); + + setDefaultPatchControls(0xffffff); + if(t == MidiController::Program) + { + c->setMinVal(0); + c->setMaxVal(0xffffff); + c->setInitVal(0xffffff); + } + else + { + c->setMinVal(spinBoxMin->value()); + c->setMaxVal(spinBoxMax->value()); + if(spinBoxDefault->value() == spinBoxDefault->minimum()) + c->setInitVal(CTRL_VAL_UNKNOWN); + else + c->setInitVal(spinBoxDefault->value()); + } + + + /* + + if(rng != 0) + { + int mn = c->minVal(); + int mx = c->maxVal(); + //if(val > item->text(COL_MAX).toInt()) + if(mx > max) + { + c->setMaxVal(max); + spinBoxMax->blockSignals(true); + spinBoxMax->setValue(max); + spinBoxMax->blockSignals(false); + if(item) + item->setText(COL_MAX, QString().setNum(max)); + } + //else + if(mn < min) + { + c->setMinVal(min); + spinBoxMin->blockSignals(true); + spinBoxMin->setValue(min); + spinBoxMin->blockSignals(false); + if(item) + item->setText(COL_MIN, QString().setNum(min)); + } + //else + if(mx - mn > rng) + { + //mx = val + rng; + c->setMinVal(0); + c->setMaxVal(rng); + spinBoxMin->blockSignals(true); + spinBoxMax->blockSignals(true); + spinBoxMin->setValue(0); + spinBoxMax->setValue(rng); + spinBoxMin->blockSignals(false); + spinBoxMax->blockSignals(false); + if(item) + { + item->setText(COL_MIN, QString().setNum(0)); + item->setText(COL_MAX, QString().setNum(rng)); + } + } + + spinBoxDefault->blockSignals(true); + + spinBoxDefault->setRange(spinBoxMin->value() - 1, spinBoxMax->value()); + int inval = c->initVal(); + if(inval == CTRL_VAL_UNKNOWN) + spinBoxDefault->setValue(spinBoxDefault->minimum()); + else + { + if(inval < c->minVal()) + { + c->setInitVal(c->minVal()); + spinBoxDefault->setValue(c->minVal()); + } + else + if(inval > c->maxVal()) + { + c->setInitVal(c->maxVal()); + spinBoxDefault->setValue(c->maxVal()); + } + } + + //spinBoxDefault->setRange(c->minVal() - 1, c->maxVal()); + spinBoxDefault->blockSignals(false); + + } + + */ + + workingInstrument.setDirty(true); + } + +//--------------------------------------------------------- +// ctrlHNumChanged +//--------------------------------------------------------- + +void EditInstrument::ctrlHNumChanged(int val) + { + QTreeWidgetItem* item = viewController->currentItem(); + + if (item == 0) + return; + QString s; + s.setNum(val); + MidiController* c = (MidiController*)item->data(0, Qt::UserRole).value<void*>(); + //int n = c->num() & 0xff; + int n = c->num() & 0x7fff00ff; + c->setNum(n | ((val & 0xff) << 8)); + item->setText(COL_HNUM, s); + workingInstrument.setDirty(true); + } + +//--------------------------------------------------------- +// ctrlLNumChanged +//--------------------------------------------------------- + +void EditInstrument::ctrlLNumChanged(int val) + { + QTreeWidgetItem* item = viewController->currentItem(); + + if (item == 0) + return; + MidiController* c = (MidiController*)item->data(0, Qt::UserRole).value<void*>(); + //int n = c->num() & 0xff00; + int n = c->num() & ~0xff; + c->setNum(n | (val & 0xff)); + if(val == -1) + item->setText(COL_LNUM, QString("*")); + else + { + QString s; + s.setNum(val); + item->setText(COL_LNUM, s); + } + workingInstrument.setDirty(true); + } + +//--------------------------------------------------------- +// ctrlMinChanged +//--------------------------------------------------------- + +void EditInstrument::ctrlMinChanged(int val) +{ + QTreeWidgetItem* item = viewController->currentItem(); + + if (item == 0) + return; + + QString s; + s.setNum(val); + item->setText(COL_MIN, s); + + MidiController* c = (MidiController*)item->data(0, Qt::UserRole).value<void*>(); + c->setMinVal(val); + + int rng = 0; + //switch((MidiController::ControllerType)ctrlType->currentItem()) + switch(midiControllerType(c->num())) + { + case MidiController::Controller7: + case MidiController::RPN: + case MidiController::NRPN: + rng = 127; + break; + case MidiController::Controller14: + case MidiController::RPN14: + case MidiController::NRPN14: + case MidiController::Pitch: + rng = 16383; + break; + default: + break; + } + + int mx = c->maxVal(); + + //if(val > item->text(COL_MAX).toInt()) + if(val > mx) + { + c->setMaxVal(val); + spinBoxMax->blockSignals(true); + spinBoxMax->setValue(val); + spinBoxMax->blockSignals(false); + item->setText(COL_MAX, s); + } + else + if(mx - val > rng) + { + mx = val + rng; + c->setMaxVal(mx); + spinBoxMax->blockSignals(true); + spinBoxMax->setValue(mx); + spinBoxMax->blockSignals(false); + item->setText(COL_MAX, QString().setNum(mx)); + } + + spinBoxDefault->blockSignals(true); + + spinBoxDefault->setRange(spinBoxMin->value() - 1, spinBoxMax->value()); + + int inval = c->initVal(); + if(inval == CTRL_VAL_UNKNOWN) + spinBoxDefault->setValue(spinBoxDefault->minimum()); + else + { + if(inval < c->minVal()) + { + c->setInitVal(c->minVal()); + spinBoxDefault->setValue(c->minVal()); + } + else + if(inval > c->maxVal()) + { + c->setInitVal(c->maxVal()); + spinBoxDefault->setValue(c->maxVal()); + } + } + + spinBoxDefault->blockSignals(false); + + workingInstrument.setDirty(true); +} + +//--------------------------------------------------------- +// ctrlMaxChanged +//--------------------------------------------------------- + +void EditInstrument::ctrlMaxChanged(int val) +{ + QTreeWidgetItem* item = viewController->currentItem(); + + if (item == 0) + return; + + QString s; + s.setNum(val); + item->setText(COL_MAX, s); + + MidiController* c = (MidiController*)item->data(0, Qt::UserRole).value<void*>(); + c->setMaxVal(val); + + int rng = 0; + //switch((MidiController::ControllerType)ctrlType->currentItem()) + switch(midiControllerType(c->num())) + { + case MidiController::Controller7: + case MidiController::RPN: + case MidiController::NRPN: + rng = 127; + break; + case MidiController::Controller14: + case MidiController::RPN14: + case MidiController::NRPN14: + case MidiController::Pitch: + rng = 16383; + break; + default: + break; + } + + int mn = c->minVal(); + + //if(val < item->text(COL_MIN).toInt()) + if(val < mn) + { + c->setMinVal(val); + spinBoxMin->blockSignals(true); + spinBoxMin->setValue(val); + spinBoxMin->blockSignals(false); + item->setText(COL_MIN, s); + } + else + if(val - mn > rng) + { + mn = val - rng; + c->setMinVal(mn); + spinBoxMin->blockSignals(true); + spinBoxMin->setValue(mn); + spinBoxMin->blockSignals(false); + item->setText(COL_MIN, QString().setNum(mn)); + } + + spinBoxDefault->blockSignals(true); + + spinBoxDefault->setRange(spinBoxMin->value() - 1, spinBoxMax->value()); + + int inval = c->initVal(); + if(inval == CTRL_VAL_UNKNOWN) + spinBoxDefault->setValue(spinBoxDefault->minimum()); + else + { + if(inval < c->minVal()) + { + c->setInitVal(c->minVal()); + spinBoxDefault->setValue(c->minVal()); + } + else + if(inval > c->maxVal()) + { + c->setInitVal(c->maxVal()); + spinBoxDefault->setValue(c->maxVal()); + } + } + + spinBoxDefault->blockSignals(false); + + workingInstrument.setDirty(true); +} + +//--------------------------------------------------------- +// ctrlDefaultChanged +//--------------------------------------------------------- + +void EditInstrument::ctrlDefaultChanged(int val) +{ + QTreeWidgetItem* item = viewController->currentItem(); + + if (item == 0) + return; + + MidiController* c = (MidiController*)item->data(0, Qt::UserRole).value<void*>(); + + if(val == c->minVal() - 1) + { + c->setInitVal(CTRL_VAL_UNKNOWN); + item->setText(COL_DEF, QString("---")); + } + else + { + c->setInitVal(val); + item->setText(COL_DEF, QString().setNum(val)); + } + workingInstrument.setDirty(true); +} + +//--------------------------------------------------------- +// ctrlNullParamHChanged +//--------------------------------------------------------- + +void EditInstrument::ctrlNullParamHChanged(int nvh) +{ + int nvl = nullParamSpinBoxL->value(); + if(nvh == -1) + { + nullParamSpinBoxL->blockSignals(true); + nullParamSpinBoxL->setValue(-1); + nullParamSpinBoxL->blockSignals(false); + nvl = -1; + } + else + { + if(nvl == -1) + { + nullParamSpinBoxL->blockSignals(true); + nullParamSpinBoxL->setValue(0); + nullParamSpinBoxL->blockSignals(false); + nvl = 0; + } + } + if(nvh == -1 && nvl == -1) + workingInstrument.setNullSendValue(-1); + else + workingInstrument.setNullSendValue((nvh << 8) | nvl); + workingInstrument.setDirty(true); +} + +//--------------------------------------------------------- +// ctrlNullParamLChanged +//--------------------------------------------------------- + +void EditInstrument::ctrlNullParamLChanged(int nvl) +{ + int nvh = nullParamSpinBoxH->value(); + if(nvl == -1) + { + nullParamSpinBoxH->blockSignals(true); + nullParamSpinBoxH->setValue(-1); + nullParamSpinBoxH->blockSignals(false); + nvh = -1; + } + else + { + if(nvh == -1) + { + nullParamSpinBoxH->blockSignals(true); + nullParamSpinBoxH->setValue(0); + nullParamSpinBoxH->blockSignals(false); + nvh = 0; + } + } + if(nvh == -1 && nvl == -1) + workingInstrument.setNullSendValue(-1); + else + workingInstrument.setNullSendValue((nvh << 8) | nvl); + workingInstrument.setDirty(true); +} + +//--------------------------------------------------------- +// deletePatchClicked +//--------------------------------------------------------- + +void EditInstrument::deletePatchClicked() + { + //QListWidgetItem* item = instrumentList->currentItem(); +// ListBoxData* item = (ListBoxData*)instrumentList->selectedItem(); +// if (item == 0) +// return; + //MidiInstrument* instrument = (MidiInstrument*)item->data(Qt::UserRole).value<void*>(); +// MidiInstrument* instrument = (MidiInstrument*)item->data(); + //QTreeWidgetItem* pi = patchView->currentItem(); + QTreeWidgetItem* pi = patchView->currentItem(); + + if (pi == 0) + return; + + //void* p = pi->data(0, Qt::UserRole).value<void*>(); +// Patch* patch = (Patch*)pi->data(); + //if (p == 0) + // If patch is zero it's a patch group. +// if(patch == 0) + + // If the item has a parent item, it's a patch item... + if(pi->parent()) + { + PatchGroup* group = (PatchGroup*)(pi->parent())->data(0, Qt::UserRole).value<void*>(); + + // If there is an allocated patch in the data, delete it. + //Patch* patch = (Patch*)pi->auxData(); + Patch* patch = (Patch*)pi->data(0, Qt::UserRole).value<void*>(); + if(patch) + { + if(group) + { + //for(iPatch ip = group->patches.begin(); ip != group->patches.end(); ++ip) + // if(&*ip == patch) + // if(*ip == patch) + // { + // + // printf("deletePatchClicked: erasing patch\n"); + // + // group->patches.erase(ip); + // break; + // } + //group->patches.remove( (const Patch&)(*patch) ); + group->patches.remove(patch); + } + delete patch; + } + } + else + // The item has no parent item, it's a patch group item... + { + // Is there an allocated patch group in the data? + //PatchGroup* group = (PatchGroup*)pi->auxData(); + PatchGroup* group = (PatchGroup*)pi->data(0, Qt::UserRole).value<void*>(); + if(group) + { + + PatchGroupList* pg = workingInstrument.groups(); + //for(ciPatchGroup ipg = pg->begin(); ipg != pg->end(); ++ipg) + for(iPatchGroup ipg = pg->begin(); ipg != pg->end(); ++ipg) + { + + //printf("deletePatchClicked: working patch group name:%s ad:%X group name:%s ad:%X\n", (*ipg)->name.toLatin1().constData(), (unsigned int)(*ipg), group->name.toLatin1().constData(), (unsigned int) group); + + //if(&*ipg == group) + if(*ipg == group) + { + pg->erase(ipg); + break; + } + } + + // Iterate all child list view (patch) items. Find and delete any allocated patches in the items' data. +// for(ListViewData* i = (ListViewData*)pi->firstChild(); i; i = (ListViewData*)i->nextSibling()) +// { + //Patch* patch = (Patch*)i->auxData(); +// Patch* patch = (Patch*)i->data(); +// if(patch) +// { + //delete patch; + //group->patches.remove(*patch); + const PatchList& pl = group->patches; + for(ciPatch ip = pl.begin(); ip != pl.end(); ++ip) + { +// if(&*ip == patch) +// { +// group->patches.erase(ip); +// break; +// } + + // Delete the patch. + if(*ip) + delete *ip; + } + + //group->patches.clear(); + +// } +// } + + // Now delete the group. + delete group; + + } + } + + //oldPatchItem = (ListViewData*)patchView->selectedItem(); + //oldPatchItem = 0; + + // Now delete the patch or group item (and any child patch items) from the list view tree. + // !!! This will trigger a patchChanged call. + patchView->blockSignals(true); + delete pi; + if(patchView->currentItem()) + patchView->currentItem()->setSelected(true); + patchView->blockSignals(false); + + oldPatchItem = 0; + patchChanged(); + + //Patch* patch = (Patch*)p; + + //std::vector<PatchGroup>* pg = instrument->groups(); + //for (std::vector<PatchGroup>::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"); + //delete patch; + //delete pi; + + + workingInstrument.setDirty(true); + } + +//--------------------------------------------------------- +// newPatchClicked +//--------------------------------------------------------- + +void EditInstrument::newPatchClicked() + { + //QListWidgetItem* item = instrumentList->currentItem(); +// ListBoxData* item = (ListBoxData*)instrumentList->selectedItem(); +// if (item == 0) +// return; + + if(oldPatchItem) + { + if(oldPatchItem->parent()) + updatePatch(&workingInstrument, (Patch*)oldPatchItem->data(0, Qt::UserRole).value<void*>()); + else + updatePatchGroup(&workingInstrument, (PatchGroup*)oldPatchItem->data(0, Qt::UserRole).value<void*>()); + } + + //MidiInstrument* instrument = (MidiInstrument*)item->data(Qt::UserRole).value<void*>(); +// MidiInstrument* instrument = (MidiInstrument*)item->data(); + //std::vector<PatchGroup>* pg = instrument->groups(); +// PatchGroupList* pg = instrument->groups(); + PatchGroupList* pg = workingInstrument.groups(); + QString patchName; + for (int i = 1;; ++i) { + patchName = QString("Patch-%1").arg(i); + bool found = false; + + //for (std::vector<PatchGroup>::iterator g = pg->begin(); g != pg->end(); ++g) { + for (iPatchGroup g = pg->begin(); g != pg->end(); ++g) { + PatchGroup* pgp = *g; + //for (iPatch p = g->patches.begin(); p != g->patches.end(); ++p) { + for (iPatch p = pgp->patches.begin(); p != pgp->patches.end(); ++p) { + //if (p->name == patchName) { + if ((*p)->name == patchName) { + found = true; + break; + } + } + if (found) + break; + } + if (!found) + break; + } + + // + // search current patch group + // + //PatchGroup* pGroup = 0; + //QTreeWidgetItem* pi = patchView->currentItem(); + QTreeWidgetItem* pi = patchView->currentItem(); + + if (pi == 0) + return; + + // If there is data then pi is a patch item, and there must be a parent patch group item (with null data). + //if (pi->data(0, Qt::UserRole).value<void*>()) + //if (pi->data()) + + Patch* selpatch = 0; + + // If there is a parent item then pi is a patch item, and there must be a parent patch group item. + if(pi->parent()) + { + // Remember the current selected patch. + selpatch = (Patch*)pi->data(0, Qt::UserRole).value<void*>(); + + pi = pi->parent(); + } + + PatchGroup* group = (PatchGroup*)pi->data(0, Qt::UserRole).value<void*>(); + if(!group) + return; + + //for (std::vector<PatchGroup>::iterator g = pg->begin(); g != pg->end(); ++g) { +// for (ciPatchGroup 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; +// } + + // Create a new Patch, then store its pointer in a new patch item, + // to be added later to the patch group only upon save... + //Patch patch; + //patch.name = patchName; + Patch* patch = new Patch; + int hb = -1; + int lb = -1; + int prg = 0; + patch->hbank = hb; + patch->lbank = lb; + patch->prog = prg; + patch->typ = -1; + patch->drum = false; + + if(selpatch) + { + hb = selpatch->hbank; + lb = selpatch->lbank; + prg = selpatch->prog; + patch->typ = selpatch->typ; + patch->drum = selpatch->drum; + } + + bool found = false; + + // The 129 is to accommodate -1 values. Yes, it may cause one extra redundant loop but hey, + // if it hasn't found an available patch number by then, another loop won't matter. + for(int k = 0; k < 129; ++k) + { + for(int j = 0; j < 129; ++j) + { + for(int i = 0; i < 128; ++i) + { + found = false; + + for(iPatchGroup g = pg->begin(); g != pg->end(); ++g) + { + PatchGroup* pgp = *g; + for(iPatch ip = pgp->patches.begin(); ip != pgp->patches.end(); ++ip) + { + Patch* p = *ip; + if((p->prog == ((prg + i) & 0x7f)) && + ((p->lbank == -1 && lb == -1) || (p->lbank == ((lb + j) & 0x7f))) && + ((p->hbank == -1 && hb == -1) || (p->hbank == ((hb + k) & 0x7f)))) + { + found = true; + break; + } + } + if(found) + break; + } + + if(!found) + { + patch->prog = (prg + i) & 0x7f; + if(lb == -1) + patch->lbank = -1; + else + patch->lbank = (lb + j) & 0x7f; + + if(hb == -1) + patch->hbank = -1; + else + patch->hbank = (hb + k) & 0x7f; + + //patch->typ = selpatch->typ; + //patch->drum = selpatch->drum; + break; + } + + } + if(!found) + break; + } + if(!found) + break; + } + + patch->name = patchName; + + group->patches.push_back(patch); + //Patch* pp = &(group->patches.back()); + + //QTreeWidgetItem* sitem = new QTreeWidgetItem; + QTreeWidgetItem* sitem = new QTreeWidgetItem(pi); + //sitem->setText(0, patch->name); + sitem->setText(0, patchName); + + patchNameEdit->setText(patchName); + + //QVariant v = QVariant::fromValue((void*)(patch)); + //sitem->setData(0, Qt::UserRole, v); + + // Set the list view item's data. + //sitem->setData((void*)patch); + QVariant v = qVariantFromValue((void*)(patch)); + sitem->setData(0, Qt::UserRole, v); + //sitem->setAuxData((void*)patch); + //sitem->setData((void*)pp); + + //pi->addChild(sitem); + + //printf("newPatchClicked: before patchView->setCurrentItem\n"); + + //patchView->setCurrentItem(sitem); + + //printf("newPatchClicked: after patchView->setCurrentItem\n"); + + //oldPatchItem = 0; + + // May cause patchChanged call. + patchView->blockSignals(true); + sitem->setSelected(true); + patchView->scrollToItem((QTreeWidgetItem*)sitem, QAbstractItemView::EnsureVisible); + patchView->blockSignals(false); + + //oldPatchItem = (ListViewData*)patchView->selectedItem(); + //oldPatchItem = sitem; + //oldPatchItem = 0; + + spinBoxHBank->setEnabled(true); + spinBoxLBank->setEnabled(true); + spinBoxProgram->setEnabled(true); + checkBoxDrum->setEnabled(true); + checkBoxGM->setEnabled(true); + checkBoxGS->setEnabled(true); + checkBoxXG->setEnabled(true); + + oldPatchItem = 0; + patchChanged(); + + //instrument->setDirty(true); + workingInstrument.setDirty(true); + } + +//--------------------------------------------------------- +// newGroupClicked +//--------------------------------------------------------- + +void EditInstrument::newGroupClicked() + { + //QListWidgetItem* item = instrumentList->currentItem(); +// ListBoxData* item = (ListBoxData*)instrumentList->selectedItem(); +// if (item == 0) +// return; + + if(oldPatchItem) + { + if(oldPatchItem->parent()) + updatePatch(&workingInstrument, (Patch*)oldPatchItem->data(0, Qt::UserRole).value<void*>()); + else + updatePatchGroup(&workingInstrument, (PatchGroup*)oldPatchItem->data(0, Qt::UserRole).value<void*>()); + } + + //MidiInstrument* instrument = (MidiInstrument*)item->data(Qt::UserRole).value<void*>(); +// MidiInstrument* instrument = (MidiInstrument*)item->data(); + //std::vector<PatchGroup>* pg = instrument->groups(); +// PatchGroupList* pg = instrument->groups(); + PatchGroupList* pg = workingInstrument.groups(); + QString groupName; + for (int i = 1;; ++i) { + groupName = QString("Group-%1").arg(i); + bool found = false; + + //for (std::vector<PatchGroup>::iterator g = pg->begin(); g != pg->end(); ++g) { + for (ciPatchGroup g = pg->begin(); g != pg->end(); ++g) { + //if (g->name == groupName) { + if ((*g)->name == groupName) { + found = true; + break; + } + } + if (!found) + break; + } + + // Create a new PatchGroup, then store its pointer in a new patch group item, + // to be added later to the instrument only upon save... + PatchGroup* group = new PatchGroup; + group->name = groupName; + //PatchGroup group; + //group.name = groupName; + + pg->push_back(group); + //PatchGroup* pgp = &(pg->back()); + + QTreeWidgetItem* sitem = new QTreeWidgetItem(patchView); + sitem->setText(0, groupName); + + patchNameEdit->setText(groupName); + + //QVariant v = QVariant::fromValue((void*)0); + //sitem->setData(0, Qt::UserRole, v); + //sitem->setData((void*)0); + + // Set the list view item's data. + QVariant v = qVariantFromValue((void*)(group)); + sitem->setData(0, Qt::UserRole, v); + //sitem->setAuxData((void*)pgp); + + //patchView->addTopLevelItem(sitem); + //patchView->setCurrentItem(sitem); + + //oldPatchItem = 0; + + // May cause patchChanged call. + patchView->blockSignals(true); + sitem->setSelected(true); + patchView->blockSignals(false); + + //oldPatchItem = (ListViewData*)patchView->selectedItem(); + oldPatchItem = sitem; + //oldPatchItem = 0; + //patchChanged(); + + spinBoxHBank->setEnabled(false); + spinBoxLBank->setEnabled(false); + spinBoxProgram->setEnabled(false); + checkBoxDrum->setEnabled(false); + checkBoxGM->setEnabled(false); + checkBoxGS->setEnabled(false); + checkBoxXG->setEnabled(false); + + //instrument->setDirty(true); + workingInstrument.setDirty(true); + } + +//--------------------------------------------------------- +// deleteControllerClicked +//--------------------------------------------------------- + +void EditInstrument::deleteControllerClicked() + { + //QListWidgetItem* item = instrumentList->currentItem(); + //ListBoxData* item = (ListBoxData*)instrumentList->selectedItem(); + //QListWidgetItem* item2 = listController->currentItem(); +// ListBoxData* item = (ListBoxData*)listController->selectedItem(); + QTreeWidgetItem* item = viewController->currentItem(); + + //if (item == 0 || item2 == 0) + if(!item) + return; + //MidiInstrument* instrument = (MidiInstrument*)item->data(Qt::UserRole).value<void*>(); +// MidiInstrument* instrument = (MidiInstrument*)item->data(); + //MidiController* ctrl = (MidiController*)item2->data(Qt::UserRole).value<void*>(); + //MidiController* ctrl = (MidiController*)item2->data(); + //MidiControllerList* cl = instrument->controller(); + //cl->removeAll(ctrl); + + MidiController* ctrl = (MidiController*)item->data(0, Qt::UserRole).value<void*>(); + if(!ctrl) + return; + + workingInstrument.controller()->erase(ctrl->num()); + // Now delete the controller. + delete ctrl; + + // Now remove the controller item from the list. + // This may cause a controllerChanged call. +// listController->blockSignals(true); + viewController->blockSignals(true); + delete item; + if(viewController->currentItem()) + viewController->currentItem()->setSelected(true); +// listController->blockSignals(false); + viewController->blockSignals(false); + + //oldController = (ListBoxData*)listController->selectedItem(); +// oldController = 0; + + controllerChanged(); + + //instrument->setDirty(true); + workingInstrument.setDirty(true); + } + +//--------------------------------------------------------- +// newControllerClicked +//--------------------------------------------------------- + +void EditInstrument::newControllerClicked() + { + //QListWidgetItem* item = instrumentList->currentItem(); + //if (item == 0) + // return; + //MidiInstrument* instrument = (MidiInstrument*)item->data(Qt::UserRole).value<void*>(); + +// if(oldController) +// updateController(&workingInstrument, (MidiController*)oldController->data()); + + QString cName; + //MidiControllerList* cl = instrument->controller(); + MidiControllerList* cl = workingInstrument.controller(); + for (int i = 1;; ++i) { + //ctrlName = QString("Controller-%d").arg(i); + cName = QString("Controller-%1").arg(i); + bool found = false; + for (iMidiController ic = cl->begin(); ic != cl->end(); ++ic) { + MidiController* c = ic->second; + if (c->name() == cName) { + found = true; + break; + } + } + if (!found) + break; + } + + MidiController* ctrl = new MidiController(); + ctrl->setNum(CTRL_MODULATION); + ctrl->setMinVal(0); + ctrl->setMaxVal(127); + ctrl->setInitVal(CTRL_VAL_UNKNOWN); + + QTreeWidgetItem* ci = viewController->currentItem(); + + // To allow for quick multiple successive controller creation. + // If there's a current controller item selected, copy initial values from it. + bool found = false; + if(ci) + { + MidiController* selctl = (MidiController*)ci->data(0, Qt::UserRole).value<void*>(); + // Assign. + // *ctrl = *selctl; + + // Auto increment controller number. + //int l = ctrl->num() & 0x7f; + //int h = ctrl->num() & 0xffffff00; + int l = selctl->num() & 0x7f; + int h = selctl->num() & 0xffffff00; + + // Ignore internal controllers and wild cards. + //if(((h & 0xff0000) != 0x40000) && ((ctrl->num() & 0xff) != 0xff)) + if(((h & 0xff0000) != 0x40000) && ((selctl->num() & 0xff) != 0xff)) + { + // Assign. + *ctrl = *selctl; + + for (int i = 1; i < 128; ++i) + { + //ctrlName = QString("Controller-%d").arg(i); + //cName = QString("Controller-%1").arg(i); + int j = ((i + l) & 0x7f) | h; + found = false; + for (iMidiController ic = cl->begin(); ic != cl->end(); ++ic) + { + MidiController* c = ic->second; + if(c->num() == j) + { + found = true; + break; + } + } + if(!found) + { + ctrl->setNum(j); + break; + } + } + } + } + + ctrl->setName(cName); + + //item = new QListWidgetItem(ctrlName); +// ListBoxData* item = new ListBoxData(ctrlName); + + //QVariant v = qVariantFromValue((void*)(ctrl)); + //item->setData(Qt::UserRole, v); +// item->setData((void*)ctrl); + //listController->addItem(item); +// listController->insertItem(item); + //listController->setCurrentItem(item); + + workingInstrument.controller()->add(ctrl); + QTreeWidgetItem* item = addControllerToView(ctrl); + +// listController->blockSignals(true); +// listController->setSelected(item, true); +// listController->blockSignals(false); + viewController->blockSignals(true); + item->setSelected(true); + viewController->blockSignals(false); + + //oldController = (ListBoxData*)listController->selectedItem(); +// oldController = item; + //oldController = 0; + // MidiController is a class, with itialized values. We have to call this to show the values. + // To make multiple entries easier, don't bother calling this. + controllerChanged(); + + //instrument->setDirty(true); + workingInstrument.setDirty(true); + } + +//--------------------------------------------------------- +// addControllerClicked +//--------------------------------------------------------- + +void EditInstrument::addControllerClicked() +{ + //int lnum = listController->currentItem(); + //if(lnum == -1) + // return; + + //QString name = midiCtrlName(lnum); + + QListWidgetItem* idx = listController->currentItem(); + if(idx == 0) + return; + + int lnum = -1; + QString name = listController->currentItem()->text(); + for(int i = 0; i < 128; i++) + { + if(midiCtrlName(i) == name) + { + lnum = i; + break; + } + } + if(lnum == -1) + { + printf("Add controller: Controller not found: %s\n", name.toLatin1().constData()); + return; + } + + int num = MidiController::genNum(MidiController::Controller7, 0, lnum); + + MidiControllerList* cl = workingInstrument.controller(); + for(iMidiController ic = cl->begin(); ic != cl->end(); ++ic) + { + MidiController* c = ic->second; + if(c->name() == name) + { + QMessageBox::critical(this, + tr("MusE: Cannot add common controller"), + tr("A controller named ") + name + tr(" already exists."), + QMessageBox::Ok, + Qt::NoButton, + Qt::NoButton); + + return; + } + + if(c->num() == num) + { + QMessageBox::critical(this, + tr("MusE: Cannot add common controller"), + tr("A controller number ") + QString().setNum(num) + tr(" already exists."), + QMessageBox::Ok, + Qt::NoButton, + Qt::NoButton); + + return; + } + } + + MidiController* ctrl = new MidiController(); + ctrl->setNum(num); + ctrl->setMinVal(0); + ctrl->setMaxVal(127); + ctrl->setInitVal(CTRL_VAL_UNKNOWN); + ctrl->setName(name); + + workingInstrument.controller()->add(ctrl); + + QTreeWidgetItem* item = addControllerToView(ctrl); + + viewController->blockSignals(true); + item->setSelected(true); + viewController->blockSignals(false); + + controllerChanged(); + + workingInstrument.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<void*>(); + //SysEx* sysex = (SysEx*)item2->data(Qt::UserRole).value<void*>(); + //QList<SysEx*> sl = instrument->sysex(); + //instrument->removeSysex(sysex); + //delete item2; + //instrument->setDirty(true); + + + + ListBoxData* item = (ListBoxData*)sysexList->selectedItem(); + if(!item) + return; + + EventList* el = (EventList*)item->data(); + if(!el) + return; + + } +*/ + +//--------------------------------------------------------- +// updatePatchGroup +//--------------------------------------------------------- + +void EditInstrument::updatePatchGroup(MidiInstrument* instrument, PatchGroup* pg) + { + QString a = pg->name; + QString b = patchNameEdit->text(); + if (pg->name != patchNameEdit->text()) { + pg->name = patchNameEdit->text(); + instrument->setDirty(true); + } + } + +//--------------------------------------------------------- +// updatePatch +//--------------------------------------------------------- + +void EditInstrument::updatePatch(MidiInstrument* instrument, Patch* p) + { + if (p->name != patchNameEdit->text()) { + p->name = patchNameEdit->text(); + instrument->setDirty(true); + } + + signed char hb = (spinBoxHBank->value() - 1) & 0xff; + //if (p->hbank != (spinBoxHBank->value() & 0xff)) { + // p->hbank = spinBoxHBank->value() & 0xff; + if (p->hbank != hb) { + p->hbank = hb; + + instrument->setDirty(true); + } + + signed char lb = (spinBoxLBank->value() - 1) & 0xff; + //if (p->lbank != (spinBoxLBank->value() & 0xff)) { + // p->lbank = spinBoxLBank->value() & 0xff; + if (p->lbank != lb) { + p->lbank = lb; + + instrument->setDirty(true); + } + + signed char pr = (spinBoxProgram->value() - 1) & 0xff; + if (p->prog != pr) { + p->prog = pr; + + instrument->setDirty(true); + } + + if (p->drum != checkBoxDrum->isChecked()) { + p->drum = checkBoxDrum->isChecked(); + 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); + // } + } + +/* +//--------------------------------------------------------- +// updateController +//--------------------------------------------------------- + +void EditInstrument::updateController(MidiInstrument* instrument, MidiController* oc) + { + printf("updateController: A\n"); + + int ctrlH = spinBoxHCtrlNo->value(); + int ctrlL = spinBoxLCtrlNo->value(); + //MidiController::ControllerType type = (MidiController::ControllerType)ctrlType->currentIndex(); + MidiController::ControllerType type = (MidiController::ControllerType)ctrlType->currentItem(); + int num = MidiController::genNum(type, ctrlH, ctrlL); + //int num = (ctrlH << 8) & 0x7f + ctrlL & 0x7f; + + printf("updateController: B\n"); + + if (num != oc->num()) { + + printf("updateController: num changed, setting dirty. num:%d c->num:%d\n", num, oc->num()); + + oc->setNum(num); + instrument->setDirty(true); + } + + if(type != MidiController::Pitch && type != MidiController::Program) + { + if (spinBoxMin->value() != oc->minVal()) { + + printf("updateController: min changed, setting dirty. min:%d c->min:%d\n", spinBoxMin->value(), oc->minVal()); + + oc->setMinVal(spinBoxMin->value()); + instrument->setDirty(true); + } + if (spinBoxMax->value() != oc->maxVal()) { + + printf("updateController: max changed, setting dirty. num:%d max:%d c->max:%d\n", num, spinBoxMax->value(), oc->maxVal()); + + oc->setMaxVal(spinBoxMax->value()); + instrument->setDirty(true); + } + + int dv = spinBoxDefault->value(); + if(dv == oc->minVal() - 1) + dv = CTRL_VAL_UNKNOWN; + + //if (spinBoxDefault->value() != oc->initVal()) { + if(dv != oc->initVal()) { + //oc->setInitVal(spinBoxDefault->value()); + oc->setInitVal(dv); + + printf("updateController: default changed, setting dirty. def:%d c->init:%d\n", dv, oc->initVal()); + + instrument->setDirty(true); + } + } + + + printf("updateController: C\n"); + + //if (moveWithPart->isChecked() ^ oc->moveWithPart()) { + // oc->setMoveWithPart(moveWithPart->isChecked()); + // instrument->setDirty(true); + // } + if (ctrlName->text() != oc->name()) { + oc->setName(ctrlName->text()); + + printf("updateController: name changed, setting dirty. name:%s c->name:%s\n", ctrlName->text().toLatin1().constData(), oc->name().toLatin1().constData()); + + instrument->setDirty(true); + } + //if (ctrlComment->toPlainText() != oc->comment()) { + // oc->setComment(ctrlComment->toPlainText()); + // instrument->setDirty(true); + // } + + printf("updateController: D\n"); + + } +*/ + +//--------------------------------------------------------- +// updateInstrument +//--------------------------------------------------------- + +void EditInstrument::updateInstrument(MidiInstrument* instrument) + { + //QListWidgetItem* sysexItem = sysexList->currentItem(); + //ListBoxData* sysexItem = sysexList->currentItem(); + //if (sysexItem) { + // SysEx* so = (SysEx*)sysexItem->data(Qt::UserRole).value<void*>(); + // updateSysex(instrument, so); + // } + + //QListWidgetItem* ctrlItem = listController->currentItem(); + //ListBoxData* ctrlItem = (ListBoxData*)listController->currentItem(); + //ListBoxData* ctrlItem = (ListBoxData*)listController->selectedItem(); +// ListViewData* ctrlItem = (ListViewData*)viewController->selectedItem(); + +// if (ctrlItem) { + //MidiController* ctrl = (MidiController*)ctrlItem->data(Qt::UserRole).value<void*>(); + +// printf("updateInstrument: AB\n"); + +// MidiController* ctrl = (MidiController*)ctrlItem->data(); + +// printf("updateInstrument: AC\n"); + +// updateController(instrument, ctrl); +// } + +// printf("updateInstrument: B\n"); + + QTreeWidgetItem* patchItem = patchView->currentItem(); + + if (patchItem) + { + //Patch* p = (Patch*)patchItem->data(0, Qt::UserRole).value<void*>(); + + // If the item has a parent, it's a patch item. + if(patchItem->parent()) + updatePatch(instrument, (Patch*)patchItem->data(0, Qt::UserRole).value<void*>()); + else + updatePatchGroup(instrument, (PatchGroup*)patchItem->data(0, Qt::UserRole).value<void*>()); + + } + } + +//--------------------------------------------------------- +// checkDirty +// return true on Abort +//--------------------------------------------------------- + +int EditInstrument::checkDirty(MidiInstrument* i, bool isClose) + { + updateInstrument(i); + if (!i->dirty()) + //return false; + return 0; + int n; + if(isClose) + 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); + else + n = QMessageBox::warning(this, tr("MusE"), + tr("The current Instrument contains unsaved data\n" + "Save Current Instrument?"), + tr("&Save"), tr("&Nosave"), 0, 1); + if (n == 0) { + if (i->filePath().isEmpty()) + { + //fileSaveAs(); + saveAs(); + } + else { + //QFile f(i->filePath()); + //if (!f.open(QIODevice::WriteOnly)) + FILE* f = fopen(i->filePath().toLatin1().constData(), "w"); + if(f == 0) + //fileSaveAs(); + saveAs(); + else { + //f.close(); + if(fclose(f) != 0) + printf("EditInstrument::checkDirty: Error closing file\n"); + + if(fileSave(i, i->filePath())) + i->setDirty(false); + } + } + //return false; + return 0; + } + //return n == 2; + return n; + } + +//--------------------------------------------------------- +// getPatchItemText +//--------------------------------------------------------- + +QString EditInstrument::getPatchItemText(int val) +{ + QString s; + if(val == CTRL_VAL_UNKNOWN) + s = "---"; + else + { + int hb = ((val >> 16) & 0xff) + 1; + if (hb == 0x100) + hb = 0; + int lb = ((val >> 8) & 0xff) + 1; + if (lb == 0x100) + lb = 0; + int pr = (val & 0xff) + 1; + if (pr == 0x100) + pr = 0; + s.sprintf("%d-%d-%d", hb, lb, pr); + } + + return s; +} + +//--------------------------------------------------------- +// enableDefaultControls +//--------------------------------------------------------- + +void EditInstrument::enableDefaultControls(bool enVal, bool enPatch) +{ + spinBoxDefault->setEnabled(enVal); + patchButton->setEnabled(enPatch); + if(!enPatch) + { + patchButton->blockSignals(true); + patchButton->setText("---"); + patchButton->blockSignals(false); + } + defPatchH->setEnabled(enPatch); + defPatchL->setEnabled(enPatch); + defPatchProg->setEnabled(enPatch); +} + +//--------------------------------------------------------- +// setDefaultPatchName +//--------------------------------------------------------- + +void EditInstrument::setDefaultPatchName(int val) +{ + patchButton->blockSignals(true); + patchButton->setText(getPatchName(val)); + patchButton->blockSignals(false); +} + +//--------------------------------------------------------- +// getDefaultPatchNumber +//--------------------------------------------------------- + +int EditInstrument::getDefaultPatchNumber() +{ + int hval = defPatchH->value() - 1; + int lval = defPatchL->value() - 1; + int prog = defPatchProg->value() - 1; + if(hval == -1) + hval = 0xff; + if(lval == -1) + lval = 0xff; + if(prog == -1) + prog = 0xff; + + return ((hval & 0xff) << 16) + ((lval & 0xff) << 8) + (prog & 0xff); +} + +//--------------------------------------------------------- +// setDefaultPatchNumbers +//--------------------------------------------------------- + +void EditInstrument::setDefaultPatchNumbers(int val) +{ + int hb; + int lb; + int pr; + + if(val == CTRL_VAL_UNKNOWN) + hb = lb = pr = 0; + else + { + hb = ((val >> 16) & 0xff) + 1; + if (hb == 0x100) + hb = 0; + lb = ((val >> 8) & 0xff) + 1; + if (lb == 0x100) + lb = 0; + pr = (val & 0xff) + 1; + if (pr == 0x100) + pr = 0; + } + + defPatchH->blockSignals(true); + defPatchL->blockSignals(true); + defPatchProg->blockSignals(true); + defPatchH->setValue(hb); + defPatchL->setValue(lb); + defPatchProg->setValue(pr); + defPatchH->blockSignals(false); + defPatchL->blockSignals(false); + defPatchProg->blockSignals(false); +} + +//--------------------------------------------------------- +// setDefaultPatchControls +//--------------------------------------------------------- + +void EditInstrument::setDefaultPatchControls(int val) +{ + setDefaultPatchNumbers(val); + setDefaultPatchName(val); +} + +//--------------------------------------------------------- +// getPatchName +//--------------------------------------------------------- + +QString EditInstrument::getPatchName(int prog) +{ + int pr = prog & 0xff; + if(prog == CTRL_VAL_UNKNOWN || pr == 0xff) + return "---"; + + //int hbank = (prog >> 16) & 0x7f; + //int lbank = (prog >> 8) & 0x7f; + int hbank = (prog >> 16) & 0xff; + int lbank = (prog >> 8) & 0xff; + + PatchGroupList* pg = workingInstrument.groups(); + + for(ciPatchGroup i = pg->begin(); i != pg->end(); ++i) { + const PatchList& pl = (*i)->patches; + for (ciPatch ipl = pl.begin(); ipl != pl.end(); ++ipl) { + const Patch* mp = *ipl; + if (//(mp->typ & tmask) && + (pr == mp->prog) + //&& ((drum && mode != MT_GM) || + // (mp->drum == drumchan)) + + //&& (hbank == mp->hbank || !hb || mp->hbank == -1) + //&& (lbank == mp->lbank || !lb || mp->lbank == -1)) + && (hbank == mp->hbank || mp->hbank == -1) + && (lbank == mp->lbank || mp->lbank == -1)) + return mp->name; + } + } + return "---"; +} + diff --git a/attic/muse2-oom/muse2/muse/instruments/editinstrument.h b/attic/muse2-oom/muse2/muse/instruments/editinstrument.h new file mode 100644 index 00000000..b3c6b5e0 --- /dev/null +++ b/attic/muse2-oom/muse2/muse/instruments/editinstrument.h @@ -0,0 +1,91 @@ +//========================================================= +// MusE +// Linux Music Editor +// $Id: editinstrument.h,v 1.1.1.1.2.4 2009/05/31 05:12:12 terminator356 Exp $ +// +// (C) Copyright 2003 Werner Schweer (ws@seh.de) +//========================================================= + +#ifndef __EDITINSTRUMENT_H__ +#define __EDITINSTRUMENT_H__ + +#include "ui_editinstrumentbase.h" +#include "minstrument.h" +#include "midictrl.h" + +class QDialog; +class QMenu; +class QCloseEvent; + +//--------------------------------------------------------- +// EditInstrument +//--------------------------------------------------------- + +class EditInstrument : public QMainWindow, public Ui::EditInstrumentBase { + Q_OBJECT + + MidiInstrument workingInstrument; + QListWidgetItem* oldMidiInstrument; + QTreeWidgetItem* oldPatchItem; + void closeEvent(QCloseEvent*); + int checkDirty(MidiInstrument*, bool isClose = false); + bool fileSave(MidiInstrument*, const QString&); + void saveAs(); + void updateInstrument(MidiInstrument*); + void updatePatch(MidiInstrument*, Patch*); + void updatePatchGroup(MidiInstrument*, PatchGroup*); + void changeInstrument(); + QTreeWidgetItem* addControllerToView(MidiController* mctrl); + QString getPatchItemText(int); + void enableDefaultControls(bool, bool); + void setDefaultPatchName(int); + int getDefaultPatchNumber(); + void setDefaultPatchNumbers(int); + void setDefaultPatchControls(int); + QString getPatchName(int); + void deleteInstrument(QListWidgetItem*); + ///QMenu* patchpopup; + + private slots: + virtual void fileNew(); + virtual void fileOpen(); + virtual void fileSave(); + virtual void fileSaveAs(); + virtual void fileExit(); + virtual void helpWhatsThis(); + void instrumentChanged(); + void tabChanged(QWidget*); + void patchChanged(); + void controllerChanged(); + //void instrumentNameChanged(const QString&); + void instrumentNameReturn(); + void patchNameReturn(); + void deletePatchClicked(); + void newPatchClicked(); + void newGroupClicked(); + void patchButtonClicked(); + void defPatchChanged(int); + //void newCategoryClicked(); + void deleteControllerClicked(); + void newControllerClicked(); + void addControllerClicked(); + void ctrlTypeChanged(int); + //void ctrlNameChanged(const QString&); + void ctrlNameReturn(); + void ctrlHNumChanged(int); + void ctrlLNumChanged(int); + void ctrlMinChanged(int); + void ctrlMaxChanged(int); + void ctrlDefaultChanged(int); + //void sysexChanged(); + //void deleteSysexClicked(); + //void newSysexClicked(); + void ctrlNullParamHChanged(int); + void ctrlNullParamLChanged(int); + + public: + EditInstrument(QWidget* parent = 0, Qt::WFlags fl = Qt::Window); + }; + +#endif + diff --git a/attic/muse2-oom/muse2/muse/instruments/editinstrumentbase.ui b/attic/muse2-oom/muse2/muse/instruments/editinstrumentbase.ui new file mode 100644 index 00000000..3337cfc0 --- /dev/null +++ b/attic/muse2-oom/muse2/muse/instruments/editinstrumentbase.ui @@ -0,0 +1,1649 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>EditInstrumentBase</class> + <widget class="QMainWindow" name="EditInstrumentBase"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>802</width> + <height>505</height> + </rect> + </property> + <property name="minimumSize"> + <size> + <width>802</width> + <height>464</height> + </size> + </property> + <property name="windowTitle"> + <string>MusE: Instrument Editor</string> + </property> + <widget class="QWidget" name="widget"> + <layout class="QVBoxLayout"> + <item> + <widget class="QSplitter" name="splitter4"> + <property name="minimumSize"> + <size> + <width>780</width> + <height>365</height> + </size> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <widget class="QWidget" name="layout26"> + <layout class="QVBoxLayout"> + <item> + <widget class="QLabel" name="textLabel2"> + <property name="text"> + <string>Instrument Name:</string> + </property> + <property name="wordWrap"> + <bool>false</bool> + </property> + </widget> + </item> + <item> + <widget class="QLineEdit" name="instrumentName"> + <property name="toolTip"> + <string/> + </property> + <property name="whatsThis"> + <string>Selected instrument name.</string> + </property> + </widget> + </item> + <item> + <widget class="QListWidget" name="instrumentList"> + <property name="whatsThis"> + <string>List of defined instruments.</string> + </property> + </widget> + </item> + </layout> + </widget> + <widget class="QTabWidget" name="tabWidget3"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="currentIndex"> + <number>0</number> + </property> + <widget class="QWidget" name="patchesTab"> + <attribute name="title"> + <string>Pa&tches</string> + </attribute> + <layout class="QVBoxLayout"> + <item> + <widget class="QSplitter" name="splitter5"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <widget class="QTreeWidget" name="patchView"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="toolTip"> + <string/> + </property> + <property name="whatsThis"> + <string>List of groups and patches.</string> + </property> + <property name="rootIsDecorated"> + <bool>true</bool> + </property> + <property name="allColumnsShowFocus"> + <bool>true</bool> + </property> + <column> + <property name="text"> + <string>Group/Patch</string> + </property> + </column> + </widget> + <widget class="QWidget" name="layout27"> + <layout class="QVBoxLayout"> + <item> + <widget class="QGroupBox" name="groupBox2"> + <property name="title"> + <string>Properties</string> + </property> + <layout class="QVBoxLayout"> + <item> + <widget class="QLabel" name="textLabelPatchName"> + <property name="text"> + <string>Name:</string> + </property> + <property name="wordWrap"> + <bool>false</bool> + </property> + </widget> + </item> + <item> + <widget class="QLineEdit" name="patchNameEdit"> + <property name="toolTip"> + <string>Group or patch name</string> + </property> + <property name="whatsThis"> + <string>Group or patch name</string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="textLabel2_2"> + <property name="text"> + <string>High Bank:</string> + </property> + <property name="wordWrap"> + <bool>false</bool> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout"> + <item> + <widget class="QSpinBox" name="spinBoxHBank"> + <property name="toolTip"> + <string>Patch high bank number</string> + </property> + <property name="whatsThis"> + <string>Patch high bank number. --- means don't care.</string> + </property> + <property name="specialValueText"> + <string comment="dont care">---</string> + </property> + <property name="minimum"> + <number>0</number> + </property> + <property name="maximum"> + <number>128</number> + </property> + <property name="value"> + <number>0</number> + </property> + </widget> + </item> + <item> + <spacer name="spacer8"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Expanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>373</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <widget class="QLabel" name="textLabel3_2"> + <property name="text"> + <string>Low Bank:</string> + </property> + <property name="wordWrap"> + <bool>false</bool> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout"> + <item> + <widget class="QSpinBox" name="spinBoxLBank"> + <property name="toolTip"> + <string>Patch low bank number</string> + </property> + <property name="whatsThis"> + <string>Patch low bank number. --- means don't care.</string> + </property> + <property name="specialValueText"> + <string>---</string> + </property> + <property name="minimum"> + <number>0</number> + </property> + <property name="maximum"> + <number>128</number> + </property> + <property name="value"> + <number>0</number> + </property> + </widget> + </item> + <item> + <spacer name="spacer9"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Expanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>373</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <widget class="QLabel" name="textLabel4_3"> + <property name="text"> + <string>Program:</string> + </property> + <property name="wordWrap"> + <bool>false</bool> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout"> + <item> + <widget class="QSpinBox" name="spinBoxProgram"> + <property name="toolTip"> + <string>Patch program number</string> + </property> + <property name="whatsThis"> + <string>Patch program number</string> + </property> + <property name="minimum"> + <number>1</number> + </property> + <property name="maximum"> + <number>128</number> + </property> + <property name="value"> + <number>1</number> + </property> + </widget> + </item> + <item> + <spacer name="spacer10"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Expanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>373</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout"> + <item> + <widget class="QCheckBox" name="checkBoxDrum"> + <property name="toolTip"> + <string>Drum patch</string> + </property> + <property name="whatsThis"> + <string>If set, the patch is available only for drum channels.</string> + </property> + <property name="text"> + <string>Drum</string> + </property> + <property name="shortcut"> + <string/> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="checkBoxGM"> + <property name="toolTip"> + <string>GM patch</string> + </property> + <property name="whatsThis"> + <string>If set, the patch is available in a 'GM' or 'NO' midi song type.</string> + </property> + <property name="text"> + <string>GM</string> + </property> + <property name="shortcut"> + <string/> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="checkBoxGS"> + <property name="toolTip"> + <string>GS patch</string> + </property> + <property name="whatsThis"> + <string>If set, the patch is available in a 'GS' or 'NO' midi song type.</string> + </property> + <property name="text"> + <string>GS</string> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="checkBoxXG"> + <property name="toolTip"> + <string>XG patch</string> + </property> + <property name="whatsThis"> + <string>If set, the patch is available in an 'XG' or 'NO' midi song type.</string> + </property> + <property name="text"> + <string>XG</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + </item> + <item> + <spacer name="spacer7"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Expanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>90</height> + </size> + </property> + </spacer> + </item> + <item> + <layout class="QHBoxLayout"> + <item> + <widget class="QToolButton" name="patchDelete"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="toolTip"> + <string>Delete group or patch</string> + </property> + <property name="text"> + <string>&Delete</string> + </property> + <property name="shortcut"> + <string>Alt+D</string> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="patchNew"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Minimum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="toolTip"> + <string>New patch</string> + </property> + <property name="text"> + <string>New &Patch</string> + </property> + <property name="shortcut"> + <string>Alt+P</string> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="patchNewGroup"> + <property name="toolTip"> + <string>New group</string> + </property> + <property name="text"> + <string>New &Group</string> + </property> + <property name="shortcut"> + <string>Alt+G</string> + </property> + </widget> + </item> + <item> + <spacer name="spacer11"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Expanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>240</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + </layout> + </widget> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" name="controllerTab"> + <attribute name="title"> + <string>Contro&ller</string> + </attribute> + <layout class="QVBoxLayout"> + <item> + <widget class="QSplitter" name="splitter6"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <widget class="QWidget" name="layout13"> + <layout class="QVBoxLayout"> + <item> + <widget class="QLabel" name="textLabel1"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Common:</string> + </property> + <property name="wordWrap"> + <bool>false</bool> + </property> + </widget> + </item> + <item> + <widget class="QListWidget" name="listController"> + <property name="toolTip"> + <string/> + </property> + <property name="whatsThis"> + <string>This is a list of commonly used midi controllers. +Note that in MusE pitch and program changes are +handled like normal controllers.</string> + </property> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" name="layout17"> + <layout class="QVBoxLayout"> + <item> + <widget class="QTreeWidget" name="viewController"> + <property name="toolTip"> + <string>List of defined controllers</string> + </property> + <property name="whatsThis"> + <string>List of defined controllers.</string> + </property> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Sunken</enum> + </property> + <property name="allColumnsShowFocus"> + <bool>true</bool> + </property> + <column> + <property name="text"> + <string>Name </string> + </property> + </column> + <column> + <property name="text"> + <string>Type </string> + </property> + </column> + <column> + <property name="text"> + <string>H-Ctrl</string> + </property> + </column> + <column> + <property name="text"> + <string>L-Ctrl</string> + </property> + </column> + <column> + <property name="text"> + <string>Min </string> + </property> + </column> + <column> + <property name="text"> + <string>Max </string> + </property> + </column> + <column> + <property name="text"> + <string>Def </string> + </property> + </column> + </widget> + </item> + <item> + <widget class="QGroupBox" name="GroupBox1"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="title"> + <string>Properties</string> + </property> + <layout class="QVBoxLayout"> + <item> + <layout class="QHBoxLayout"> + <item> + <widget class="QLabel" name="TextLabel1_3"> + <property name="text"> + <string>Name:</string> + </property> + <property name="wordWrap"> + <bool>false</bool> + </property> + </widget> + </item> + <item> + <widget class="QLineEdit" name="ctrlName"> + <property name="toolTip"> + <string/> + </property> + <property name="whatsThis"> + <string>Midi controller name</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout"> + <item> + <widget class="QLabel" name="TextLabel2_4"> + <property name="text"> + <string>Type:</string> + </property> + <property name="wordWrap"> + <bool>false</bool> + </property> + </widget> + </item> + <item> + <widget class="QComboBox" name="ctrlType"> + <property name="toolTip"> + <string>Midi controller type</string> + </property> + <property name="whatsThis"> + <string>Midi controller type</string> + </property> + <item> + <property name="text"> + <string>Control7</string> + </property> + </item> + <item> + <property name="text"> + <string>Control14</string> + </property> + </item> + <item> + <property name="text"> + <string>RPN</string> + </property> + </item> + <item> + <property name="text"> + <string>NRPN</string> + </property> + </item> + <item> + <property name="text"> + <string>RPN14</string> + </property> + </item> + <item> + <property name="text"> + <string>NRPN14</string> + </property> + </item> + <item> + <property name="text"> + <string>Pitch</string> + </property> + </item> + <item> + <property name="text"> + <string>Program</string> + </property> + </item> + </widget> + </item> + <item> + <spacer name="spacer15"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Expanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="TextLabel3_2"> + <property name="text"> + <string>H-Ctrl</string> + </property> + <property name="wordWrap"> + <bool>false</bool> + </property> + <property name="indent"> + <number>10</number> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="spinBoxHCtrlNo"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="toolTip"> + <string>Midi controller number high byte</string> + </property> + <property name="whatsThis"> + <string>Midi controller number high byte</string> + </property> + <property name="minimum"> + <number>0</number> + </property> + <property name="maximum"> + <number>127</number> + </property> + <property name="value"> + <number>0</number> + </property> + </widget> + </item> + <item> + <spacer name="spacer16"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Expanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="TextLabel2_3_2"> + <property name="text"> + <string>L-Ctrl</string> + </property> + <property name="wordWrap"> + <bool>false</bool> + </property> + <property name="indent"> + <number>10</number> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="spinBoxLCtrlNo"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="toolTip"> + <string>Midi controller number low byte (* means drum controller)</string> + </property> + <property name="whatsThis"> + <string>Midi controller number low byte. +If low byte is * then the controller is a + 'drum controller'. For drum tracks and + GS/XG type songs and instruments. +Allows controllers for each instrument in + Muse's drum map. The low byte will be + replaced by the 'ANote' in the drum map. +Examples: The GS and XG instruments' + Drum controllers.</string> + </property> + <property name="specialValueText"> + <string comment="wild card">*</string> + </property> + <property name="minimum"> + <number>-1</number> + </property> + <property name="maximum"> + <number>127</number> + </property> + <property name="value"> + <number>0</number> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout"> + <item> + <widget class="QLabel" name="textLabel4_2"> + <property name="text"> + <string>Range:</string> + </property> + <property name="wordWrap"> + <bool>false</bool> + </property> + </widget> + </item> + <item> + <spacer name="spacer17"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Expanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="TextLabel1_2_2"> + <property name="text"> + <string>Min</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <property name="wordWrap"> + <bool>false</bool> + </property> + <property name="indent"> + <number>10</number> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="spinBoxMin"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="toolTip"> + <string>Minimum value. If negative, auto-translate.</string> + </property> + <property name="whatsThis"> + <string>Minimum value. If the minimum value + is negative, the range will automatically + be translated to a positive range. + +Useful for controllers which should be + displayed with zero bias. For example, +'Pan': Minimum: -64 Maximum: 63 +True range: Min: 0 Max: 127 (bias = 64) +'CoarseTuning': Min: -24 Max: 23 +True range: Min: 40 Max: 87 (bias = 64) + +Bias is determined from controller type: +7-bit Controller7 / RPN: Bias = 64 +14-bit Controller14 / RPN14: Bias = 8192 + +Type 'Pitch' is the exception. It is biased + at zero, even with a negative minimum: +'Pitch': Min: -8192 Max: 8191 +True range: Min: -8192 Max: 8191 (bias 0)</string> + </property> + <property name="minimum"> + <number>-16384</number> + </property> + <property name="maximum"> + <number>16383</number> + </property> + </widget> + </item> + <item> + <spacer name="spacer18"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Expanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="TextLabel2_2_2"> + <property name="text"> + <string>Max</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <property name="wordWrap"> + <bool>false</bool> + </property> + <property name="indent"> + <number>10</number> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="spinBoxMax"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="toolTip"> + <string>Maximum value</string> + </property> + <property name="whatsThis"> + <string>Maximum value</string> + </property> + <property name="minimum"> + <number>-16384</number> + </property> + <property name="maximum"> + <number>16383</number> + </property> + <property name="value"> + <number>127</number> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QGridLayout"> + <item row="1" column="0" colspan="2"> + <spacer name="spacer13_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Expanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="0" column="0"> + <widget class="QLabel" name="textLabel1_3"> + <property name="text"> + <string>Default:</string> + </property> + <property name="alignment"> + <set>Qt::AlignVCenter</set> + </property> + <property name="wordWrap"> + <bool>false</bool> + </property> + </widget> + </item> + <item row="0" column="6"> + <widget class="QLabel" name="textLabel2_4"> + <property name="text"> + <string>L-Bank</string> + </property> + <property name="wordWrap"> + <bool>false</bool> + </property> + </widget> + </item> + <item row="0" column="5"> + <widget class="QSpinBox" name="defPatchH"> + <property name="specialValueText"> + <string>off</string> + </property> + <property name="minimum"> + <number>0</number> + </property> + <property name="maximum"> + <number>128</number> + </property> + <property name="value"> + <number>0</number> + </property> + </widget> + </item> + <item row="0" column="7"> + <widget class="QSpinBox" name="defPatchL"> + <property name="specialValueText"> + <string>off</string> + </property> + <property name="minimum"> + <number>0</number> + </property> + <property name="maximum"> + <number>128</number> + </property> + <property name="value"> + <number>0</number> + </property> + </widget> + </item> + <item row="1" column="6"> + <widget class="QLabel" name="textLabel3"> + <property name="text"> + <string>Progr.</string> + </property> + <property name="wordWrap"> + <bool>false</bool> + </property> + </widget> + </item> + <item row="1" column="7"> + <widget class="QSpinBox" name="defPatchProg"> + <property name="specialValueText"> + <string>off</string> + </property> + <property name="minimum"> + <number>0</number> + </property> + <property name="maximum"> + <number>128</number> + </property> + <property name="value"> + <number>0</number> + </property> + </widget> + </item> + <item row="1" column="2" colspan="4"> + <widget class="QPushButton" name="patchButton"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="minimumSize"> + <size> + <width>210</width> + <height>0</height> + </size> + </property> + <property name="text"> + <string>???</string> + </property> + <property name="shortcut"> + <string/> + </property> + </widget> + </item> + <item row="0" column="4"> + <widget class="QLabel" name="textLabel1_5"> + <property name="text"> + <string>H-Bank</string> + </property> + <property name="wordWrap"> + <bool>false</bool> + </property> + </widget> + </item> + <item row="0" column="3"> + <spacer name="spacer12_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Expanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="0" column="1" colspan="2"> + <widget class="QSpinBox" name="spinBoxDefault"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>85</width> + <height>32767</height> + </size> + </property> + <property name="toolTip"> + <string>Default value. Off: No default.</string> + </property> + <property name="whatsThis"> + <string>Default (initial) value. Off means no default. + +If a default value is chosen, the value will be sent + to the controller when the controller is added to + the song (in piano roll or event editor). When + the song is re-loaded, the value is sent again. +Otherwise the controller remains at its last value. +Controllers are also automatically added to a + song upon reception of a midi controller event. + +Caution! Watch out for controllers such as + 'Sustain' and 'ResetAllController' with default + values. You should probably turn 'off' their + default (in piano roll or drum edit, and + instrument editor).</string> + </property> + <property name="specialValueText"> + <string comment="dont care">off</string> + </property> + <property name="minimum"> + <number>-1</number> + </property> + <property name="maximum"> + <number>16383</number> + </property> + <property name="value"> + <number>-1</number> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + </item> + <item> + <layout class="QHBoxLayout"> + <item> + <widget class="QToolButton" name="addController"> + <property name="toolTip"> + <string>Add common controller</string> + </property> + <property name="text"> + <string>&Add</string> + </property> + <property name="shortcut"> + <string>Alt+A</string> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="deleteController"> + <property name="toolTip"> + <string>Delete controller</string> + </property> + <property name="text"> + <string>&Delete</string> + </property> + <property name="shortcut"> + <string>Alt+D</string> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="newController"> + <property name="toolTip"> + <string>Create a new controller</string> + </property> + <property name="text"> + <string>New &Controller</string> + </property> + <property name="shortcut"> + <string>Alt+C</string> + </property> + </widget> + </item> + <item> + <spacer name="spacer13"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Expanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>200</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="nullValLabelH"> + <property name="text"> + <string>Null Param Hi:</string> + </property> + <property name="wordWrap"> + <bool>false</bool> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="nullParamSpinBoxH"> + <property name="toolTip"> + <string>Null parameter number High byte</string> + </property> + <property name="whatsThis"> + <string>If set, these 'null' parameter numbers will + be sent after each RPN/NRPN event. +This prevents subsequent 'data' events + from corrupting the RPN/NRPN controller. +Typically, set to 127/127, or an unused + RPN/NRPN controller number.</string> + </property> + <property name="specialValueText"> + <string>off</string> + </property> + <property name="minimum"> + <number>-1</number> + </property> + <property name="maximum"> + <number>127</number> + </property> + <property name="value"> + <number>127</number> + </property> + </widget> + </item> + <item> + <spacer name="spacer13_3"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Expanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>200</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="nullValLabelL"> + <property name="text"> + <string> Lo:</string> + </property> + <property name="wordWrap"> + <bool>false</bool> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="nullParamSpinBoxL"> + <property name="toolTip"> + <string>Null parameter number Low byte</string> + </property> + <property name="whatsThis"> + <string>If set, these 'null' parameter numbers will + be sent after each RPN/NRPN event. +This prevents subsequent 'data' events + from corrupting the RPN/NRPN controller. +Typically, set to 127/127, or an unused + RPN/NRPN controller number.</string> + </property> + <property name="specialValueText"> + <string>off</string> + </property> + <property name="minimum"> + <number>-1</number> + </property> + <property name="maximum"> + <number>127</number> + </property> + <property name="value"> + <number>127</number> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" name="sysExTab"> + <attribute name="title"> + <string>S&ysEx</string> + </attribute> + <layout class="QVBoxLayout"> + <item> + <widget class="QSplitter" name="splitter2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <widget class="QWidget" name="layout12"> + <layout class="QVBoxLayout"> + <item> + <widget class="QLabel" name="textLabel2_3"> + <property name="text"> + <string>SysEx List:</string> + </property> + <property name="wordWrap"> + <bool>false</bool> + </property> + </widget> + </item> + <item> + <widget class="QListWidget" name="sysexList"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" name="layout11"> + <layout class="QVBoxLayout"> + <item> + <widget class="QLabel" name="textLabel1_4"> + <property name="text"> + <string>Name:</string> + </property> + <property name="wordWrap"> + <bool>false</bool> + </property> + </widget> + </item> + <item> + <widget class="QLineEdit" name="sysexName"/> + </item> + <item> + <widget class="QLabel" name="textLabel1_2"> + <property name="text"> + <string>Hex Entry:</string> + </property> + <property name="wordWrap"> + <bool>false</bool> + </property> + </widget> + </item> + <item> + <widget class="QTextEdit" name="sysexData"/> + </item> + <item> + <layout class="QHBoxLayout"> + <item> + <widget class="QToolButton" name="deleteSysex"> + <property name="text"> + <string>&Delete</string> + </property> + <property name="shortcut"> + <string>Alt+D</string> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="newSysex"> + <property name="text"> + <string>New SysE&x</string> + </property> + <property name="shortcut"> + <string>Alt+X</string> + </property> + </widget> + </item> + <item> + <spacer name="spacer12"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Expanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>60</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + </layout> + </widget> + </widget> + </item> + </layout> + </widget> + </widget> + </widget> + </item> + </layout> + </widget> + <widget class="QToolBar" name="toolBar"> + <property name="label" stdset="0"> + <string>Tools</string> + </property> + <attribute name="toolBarArea"> + <enum>TopToolBarArea</enum> + </attribute> + <attribute name="toolBarBreak"> + <bool>false</bool> + </attribute> + <addaction name="fileNewAction"/> + <addaction name="fileOpenAction"/> + <addaction name="fileSaveAction"/> + <addaction name="fileSaveAsAction"/> + </widget> + <widget class="QMenuBar" name="MenuBar"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>802</width> + <height>21</height> + </rect> + </property> + <property name="defaultUp"> + <bool>false</bool> + </property> + <widget class="QMenu" name="fileMenu"> + <property name="title"> + <string>&File</string> + </property> + <addaction name="fileNewAction"/> + <addaction name="fileOpenAction"/> + <addaction name="fileSaveAction"/> + <addaction name="fileSaveAsAction"/> + <addaction name="separator"/> + <addaction name="fileExitAction"/> + </widget> + <widget class="QMenu" name="Help"> + <property name="title"> + <string>&Help</string> + </property> + </widget> + <addaction name="fileMenu"/> + <addaction name="Help"/> + </widget> + <action name="fileNewAction"> + <property name="text"> + <string>&New</string> + </property> + <property name="iconText"> + <string>New</string> + </property> + <property name="shortcut"> + <string>Ctrl+N</string> + </property> + <property name="name" stdset="0"> + <cstring>fileNewAction</cstring> + </property> + </action> + <action name="fileOpenAction"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>&Open...</string> + </property> + <property name="iconText"> + <string>Open</string> + </property> + <property name="shortcut"> + <string>Ctrl+O</string> + </property> + <property name="visible"> + <bool>false</bool> + </property> + <property name="name" stdset="0"> + <cstring>fileOpenAction</cstring> + </property> + </action> + <action name="fileSaveAction"> + <property name="text"> + <string>&Save</string> + </property> + <property name="iconText"> + <string>Save</string> + </property> + <property name="shortcut"> + <string>Ctrl+S</string> + </property> + <property name="name" stdset="0"> + <cstring>fileSaveAction</cstring> + </property> + </action> + <action name="fileSaveAsAction"> + <property name="text"> + <string>Save &As...</string> + </property> + <property name="iconText"> + <string>Save As</string> + </property> + <property name="shortcut"> + <string/> + </property> + <property name="name" stdset="0"> + <cstring>fileSaveAsAction</cstring> + </property> + </action> + <action name="fileExitAction"> + <property name="text"> + <string>E&xit</string> + </property> + <property name="iconText"> + <string>Exit</string> + </property> + <property name="shortcut"> + <string/> + </property> + <property name="name" stdset="0"> + <cstring>fileExitAction</cstring> + </property> + </action> + <action name="filenew_itemAction"> + <property name="text"> + <string>new item</string> + </property> + <property name="iconText"> + <string>new item</string> + </property> + <property name="name" stdset="0"> + <cstring>filenew_itemAction</cstring> + </property> + </action> + <action name="whatsThisAction"> + <property name="text"> + <string>What's this?</string> + </property> + <property name="iconText"> + <string>What's this?</string> + </property> + <property name="name" stdset="0"> + <cstring>whatsThisAction</cstring> + </property> + </action> + </widget> + <layoutdefault spacing="6" margin="11"/> + <tabstops> + <tabstop>instrumentName</tabstop> + <tabstop>instrumentList</tabstop> + <tabstop>tabWidget3</tabstop> + <tabstop>patchView</tabstop> + <tabstop>patchNameEdit</tabstop> + <tabstop>spinBoxHBank</tabstop> + <tabstop>spinBoxLBank</tabstop> + <tabstop>spinBoxProgram</tabstop> + <tabstop>checkBoxDrum</tabstop> + <tabstop>checkBoxGM</tabstop> + <tabstop>checkBoxGS</tabstop> + <tabstop>checkBoxXG</tabstop> + <tabstop>listController</tabstop> + <tabstop>viewController</tabstop> + <tabstop>ctrlName</tabstop> + <tabstop>ctrlType</tabstop> + <tabstop>spinBoxHCtrlNo</tabstop> + <tabstop>spinBoxLCtrlNo</tabstop> + <tabstop>spinBoxMin</tabstop> + <tabstop>spinBoxMax</tabstop> + <tabstop>spinBoxDefault</tabstop> + <tabstop>sysexList</tabstop> + <tabstop>sysexName</tabstop> + <tabstop>sysexData</tabstop> + </tabstops> + <resources/> + <connections> + <connection> + <sender>fileNewAction</sender> + <signal>activated()</signal> + <receiver>EditInstrumentBase</receiver> + <slot>fileNew()</slot> + <hints> + <hint type="sourcelabel"> + <x>-1</x> + <y>-1</y> + </hint> + <hint type="destinationlabel"> + <x>20</x> + <y>20</y> + </hint> + </hints> + </connection> + <connection> + <sender>fileOpenAction</sender> + <signal>activated()</signal> + <receiver>EditInstrumentBase</receiver> + <slot>fileOpen()</slot> + <hints> + <hint type="sourcelabel"> + <x>-1</x> + <y>-1</y> + </hint> + <hint type="destinationlabel"> + <x>20</x> + <y>20</y> + </hint> + </hints> + </connection> + <connection> + <sender>fileSaveAction</sender> + <signal>activated()</signal> + <receiver>EditInstrumentBase</receiver> + <slot>fileSave()</slot> + <hints> + <hint type="sourcelabel"> + <x>-1</x> + <y>-1</y> + </hint> + <hint type="destinationlabel"> + <x>20</x> + <y>20</y> + </hint> + </hints> + </connection> + <connection> + <sender>fileSaveAsAction</sender> + <signal>activated()</signal> + <receiver>EditInstrumentBase</receiver> + <slot>fileSaveAs()</slot> + <hints> + <hint type="sourcelabel"> + <x>-1</x> + <y>-1</y> + </hint> + <hint type="destinationlabel"> + <x>20</x> + <y>20</y> + </hint> + </hints> + </connection> + <connection> + <sender>fileExitAction</sender> + <signal>activated()</signal> + <receiver>EditInstrumentBase</receiver> + <slot>fileExit()</slot> + <hints> + <hint type="sourcelabel"> + <x>-1</x> + <y>-1</y> + </hint> + <hint type="destinationlabel"> + <x>20</x> + <y>20</y> + </hint> + </hints> + </connection> + <connection> + <sender>whatsThisAction</sender> + <signal>activated()</signal> + <receiver>EditInstrumentBase</receiver> + <slot>helpWhatsThis()</slot> + <hints> + <hint type="sourcelabel"> + <x>-1</x> + <y>-1</y> + </hint> + <hint type="destinationlabel"> + <x>20</x> + <y>20</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/attic/muse2-oom/muse2/muse/instruments/midictrledit.cpp b/attic/muse2-oom/muse2/muse/instruments/midictrledit.cpp new file mode 100644 index 00000000..9dcac628 --- /dev/null +++ b/attic/muse2-oom/muse2/muse/instruments/midictrledit.cpp @@ -0,0 +1,725 @@ +//========================================================= +// MusE +// Linux Music Editor +// $Id: midictrledit.cpp,v 1.1.1.1.2.2 2008/08/18 00:15:24 terminator356 Exp $ +// +// (C) Copyright 2003 Werner Schweer (ws@seh.de) +//========================================================= + +#include <stdio.h> + +#include "app.h" +#include "midiport.h" +#include "mididev.h" +#include "midictrl.h" +#include "midictrledit.h" +#include "minstrument.h" +#include "song.h" +#include "xml.h" +#include "filedialog.h" +#include "globals.h" + +MidiControllerEditDialog* midiControllerEditDialog; + +static MidiController predefinedMidiController[] = { + MidiController(QString("Pitch"), 0x40000, -8192, +8191, 0), + }; +enum { + COL_NAME = 0, COL_TYPE, + COL_HNUM, COL_LNUM, COL_MIN, COL_MAX + }; +//--------------------------------------------------------- +// addControllerToView +//--------------------------------------------------------- + +void MidiControllerEditDialog::addControllerToView(MidiController* mctrl) + { + QString hnum; + QString lnum; + QString min; + QString max; + int n = mctrl->num(); + int h = (n >> 8) & 0x7f; + int l = n & 0x7f; + MidiController::ControllerType t = midiControllerType(n); + switch(t) + { + case MidiController::Controller7: + hnum = "---"; + lnum.setNum(l); + min.setNum(mctrl->minVal()); + max.setNum(mctrl->maxVal()); + break; + case MidiController::RPN: + case MidiController::NRPN: + case MidiController::RPN14: + case MidiController::NRPN14: + case MidiController::Controller14: + hnum.setNum(h); + lnum.setNum(l); + min.setNum(mctrl->minVal()); + max.setNum(mctrl->maxVal()); + break; + case MidiController::Pitch: + hnum = "---"; + lnum = "---"; + min.setNum(mctrl->minVal()); + max.setNum(mctrl->maxVal()); + break; + default: + hnum = "---"; + lnum = "---"; + min.setNum(0); + max.setNum(0); + break; + } + + new Q3ListViewItem(viewController, + mctrl->name(), + int2ctrlType(t), + hnum, lnum, min, max + ); + + } +//--------------------------------------------------------- +// MidiControllerEditDialog +//--------------------------------------------------------- + +MidiControllerEditDialog::MidiControllerEditDialog(QWidget* parent, const char* name, bool modal, Qt::WFlags fl) + : MidiControllerEditDialogBase(parent, name, modal, fl) + { + _lastPort = midiPortsList->currentItem(); + viewController->setColumnAlignment(COL_HNUM, Qt::AlignCenter); + viewController->setColumnAlignment(COL_LNUM, Qt::AlignCenter); + viewController->setColumnAlignment(COL_MIN, Qt::AlignCenter); + viewController->setColumnAlignment(COL_MAX, Qt::AlignCenter); + viewController->setColumnWidthMode(COL_NAME, Q3ListView::Maximum); + + // populate list of predefined controller + updatePredefinedList(); + + // populate ports pulldown + updateMidiPortsList(); + connect(buttonNew, SIGNAL(clicked()), SLOT(ctrlAdd())); + connect(buttonDelete, SIGNAL(clicked()), SLOT(ctrlDelete())); + connect(entryName, SIGNAL(textChanged(const QString&)), SLOT(nameChanged(const QString&))); + connect(comboType, SIGNAL(activated(const QString&)), SLOT(typeChanged(const QString&))); + connect(spinboxHCtrlNo, SIGNAL(valueChanged(int)), SLOT(valueHChanged(int))); + connect(spinboxLCtrlNo, SIGNAL(valueChanged(int)), SLOT(valueLChanged(int))); + connect(spinboxMin, SIGNAL(valueChanged(int)), SLOT(minChanged(int))); + connect(spinboxMax, SIGNAL(valueChanged(int)), SLOT(maxChanged(int))); + connect(viewController, SIGNAL(selectionChanged()), SLOT(controllerChanged())); + connect(buttonApply, SIGNAL(clicked()), SLOT(apply())); + connect(midiPortsList, SIGNAL(activated(int)), SLOT(portChanged(int))); + + updateViewController(); + _modified = false; + buttonApply->setEnabled(false); + connect(song, SIGNAL(songChanged(int)), SLOT(songChanged(int))); + } + +//--------------------------------------------------------- +// songChanged +//--------------------------------------------------------- + +void MidiControllerEditDialog::songChanged(int flags) +{ + // Is it simply a midi controller value adjustment? Forget it. + if(flags == SC_MIDI_CONTROLLER) + return; + + if(flags & (SC_CONFIG | SC_MIDI_CONTROLLER)) + //if(flags & (SC_CONFIG | SC_MIDI_CONTROLLER_ADD)) + { + //listController->blockSignals(true); + midiPortsList->blockSignals(true); + //viewController->blockSignals(true); + updatePredefinedList(); + updateMidiPortsList(); + updateViewController(); + //viewController->setCurrentItem(viewController->firstChild()); + //controllerChanged(viewController->currentItem()); + //listController->blockSignals(false); + midiPortsList->blockSignals(false); + //viewController->blockSignals(false); + } +} + +//--------------------------------------------------------- +// updatePredefinedList +//--------------------------------------------------------- + +void MidiControllerEditDialog::updatePredefinedList() +{ + listController->clear(); + int size = sizeof(predefinedMidiController) / sizeof(*predefinedMidiController); + for (int i = 0; i < size; ++i) + listController->insertItem(predefinedMidiController[i].name()); + listController->setSelected(0, true); +} + +//--------------------------------------------------------- +// updateMidiPortsList +//--------------------------------------------------------- + +void MidiControllerEditDialog::updateMidiPortsList() +{ + midiPortsList->clear(); + for (int i = 0; i < MIDI_PORTS; ++i) { + MidiPort* port = &midiPorts[i]; + MidiDevice* dev = port->device(); + QString name; + name.sprintf("%d(%s)", port->portno()+1, + dev ? dev->name().toLatin1() : "none"); + midiPortsList->insertItem(name, i); + } + _lastPort = midiPortsList->currentItem(); +} + +//--------------------------------------------------------- +// updateViewController +//--------------------------------------------------------- + +void MidiControllerEditDialog::updateViewController() +{ + //for (iMidiController i = midiControllerList.begin(); + // i != midiControllerList.end(); ++i) { + // addControllerToView(&*i); + int mpidx = midiPortsList->currentItem(); + + viewController->clear(); + //MidiControllerList* mcl; + MidiInstrument* mi = midiPorts[mpidx].instrument(); + //if(mi) + MidiControllerList* mcl = mi->controller(); + //else + // mcl = &defaultMidiController; + for (iMidiController i = mcl->begin(); i != mcl->end(); ++i) + addControllerToView(*i); + + viewController->blockSignals(true); + viewController->setCurrentItem(viewController->firstChild()); + controllerChanged(viewController->currentItem()); + viewController->blockSignals(false); + + setModified(false); +} + +//--------------------------------------------------------- +// reject +//--------------------------------------------------------- + +void MidiControllerEditDialog::setModified(bool v) +{ + if(v == _modified) + return; + + _modified = v; + + if(v) + { + buttonApply->setEnabled(true); + } + else + { + buttonApply->setEnabled(false); + } +} + +//--------------------------------------------------------- +// reject +//--------------------------------------------------------- + +void MidiControllerEditDialog::reject() + { + //MidiControllerList* mcl; +// MidiInstrument* mi = midiPorts[mpidx].instrument(); + //if(mi) +// MidiControllerList* mcl = mi->controller(); + //else + // mcl = &defaultMidiController; +// for (iMidiController i = mcl->begin(); i != mcl->end(); ++i) +// addControllerToView(*i); + + // Restore the list before closing this dialog. + updateViewController(); + //setModified(false); + + MidiControllerEditDialogBase::reject(); + } + +//--------------------------------------------------------- +// apply +//--------------------------------------------------------- + +void MidiControllerEditDialog::apply() +{ + int mpidx = midiPortsList->currentItem(); + //MidiControllerList* mcl; + MidiInstrument* mi = midiPorts[mpidx].instrument(); + //if(mi) + MidiControllerList* mcl = mi->controller(); + //else + // mcl = &defaultMidiController; + mcl->clear(); + + + Q3ListViewItem* item = viewController->firstChild(); + int hval; + int lval; + while (item) { + hval = item->text(COL_HNUM).toInt(); + lval = item->text(COL_LNUM).toInt(); + MidiController* c = new MidiController(); + c->setName(item->text(COL_NAME)); + + MidiController::ControllerType type = ctrlType2Int(item->text(COL_TYPE)); + + switch(type) { + case MidiController::Controller7: + c->setNum(lval); + break; + case MidiController::Controller14: + c->setNum((hval << 8 | lval) | CTRL_14_OFFSET); + break; + case MidiController::RPN: + c->setNum((hval << 8 | lval) | CTRL_RPN_OFFSET); + break; + case MidiController::NRPN: + c->setNum((hval << 8 | lval) | CTRL_NRPN_OFFSET); + break; + case MidiController::RPN14: + c->setNum((hval << 8 | lval) | CTRL_RPN14_OFFSET); + break; + case MidiController::NRPN14: + c->setNum((hval << 8 | lval) | CTRL_NRPN14_OFFSET); + break; + case MidiController::Program: + c->setNum(CTRL_PROGRAM); + break; + case MidiController::Pitch: + c->setNum(CTRL_PITCH); + break; + default: + break; + } + if(type == MidiController::Program) + { + c->setMinVal(0); + c->setMaxVal(0xffffff); + } + else + { + c->setMinVal(item->text(COL_MIN).toInt()); + c->setMaxVal(item->text(COL_MAX).toInt()); + } + + mcl->push_back(c); + + item = item->nextSibling(); + } + + // Update the list before closing this dialog. + //updateViewController(); + //setModified(false); + song->update(SC_CONFIG | SC_MIDI_CONTROLLER); +} + +//--------------------------------------------------------- +// ctrlAdd +//--------------------------------------------------------- + +void MidiControllerEditDialog::ctrlAdd() + { + Q3ListBoxItem* item = listController->selectedItem(); + if (item == 0) + return; + QString name = item->text(); + int size = sizeof(predefinedMidiController) / sizeof(*predefinedMidiController); + for (int i = 0; i < size; ++i) { + MidiController* c = &predefinedMidiController[i]; + if (c->name() != name) + continue; + MidiController::ControllerType t = midiControllerType(c->num()); + QString type = int2ctrlType(t); + QString min, max; + QString hno, lno; + int h = (c->num() >> 8) & 0x7f; + int l = c->num() & 0x7f; + + switch(t) { + case MidiController::Controller7: + min.setNum(c->minVal()); + max.setNum(c->maxVal()); + hno = "---"; + lno.setNum(l); + break; + case MidiController::RPN: + case MidiController::NRPN: + case MidiController::RPN14: + case MidiController::NRPN14: + case MidiController::Controller14: + min.setNum(c->minVal()); + max.setNum(c->maxVal()); + hno.setNum(h); + lno.setNum(l); + break; + case MidiController::Pitch: + min.setNum(c->minVal()); + max.setNum(c->maxVal()); + hno = "---"; + lno = "---"; + break; + default: + hno = "---"; + lno = "---"; + min.setNum(0); + max.setNum(0); + break; + } + + Q3ListViewItem* item = new Q3ListViewItem(viewController, + name, type, hno, lno, min, max); + + viewController->blockSignals(true); + viewController->setCurrentItem(item); + controllerChanged(item); + viewController->blockSignals(false); + + setModified(true); + break; + } + } + +//--------------------------------------------------------- +// ctrlDelete +//--------------------------------------------------------- + +void MidiControllerEditDialog::ctrlDelete() + { + Q3ListViewItem* item = viewController->currentItem(); + if (item == 0) + return; + delete item; + + setModified(true); + } + +//--------------------------------------------------------- +// accept +//--------------------------------------------------------- + +void MidiControllerEditDialog::accept() + { + apply(); + MidiControllerEditDialogBase::accept(); + } + +//--------------------------------------------------------- +// portChanged +//--------------------------------------------------------- + +void MidiControllerEditDialog::portChanged(int n) + { + if(n == _lastPort) + return; + _lastPort = n; + + //listController->blockSignals(true); + //midiPortsList->blockSignals(true); + //viewController->blockSignals(true); + //updatePredefinedList(); + //updateMidiPortsList(); + //reject(); // populate list + updateViewController(); + //viewController->setCurrentItem(viewController->firstChild()); + //controllerChanged(viewController->currentItem()); + //listController->blockSignals(false); + //midiPortsList->blockSignals(false); + //viewController->blockSignals(false); + } + +//--------------------------------------------------------- +// nameChanged +//--------------------------------------------------------- + +void MidiControllerEditDialog::nameChanged(const QString& s) + { + Q3ListViewItem* item = viewController->currentItem(); + if (item == 0) + return; + item->setText(COL_NAME, s); + + setModified(true); + } + +//--------------------------------------------------------- +// typeChanged +//--------------------------------------------------------- + +void MidiControllerEditDialog::typeChanged(const QString& s) + { + Q3ListViewItem* item = viewController->currentItem(); + if (item == 0) + return; + item->setText(COL_TYPE, s); + switch(ctrlType2Int(s)) { + case MidiController::Controller14: + case MidiController::RPN14: + case MidiController::NRPN14: + item->setText(COL_LNUM, QString("0")); + item->setText(COL_HNUM, QString("0")); + item->setText(COL_MIN, QString("0")); + item->setText(COL_MAX, QString("16383")); + break; + case MidiController::Controller7: + item->setText(COL_MIN, QString("0")); + item->setText(COL_MAX, QString("127")); + item->setText(COL_LNUM, QString("0")); + item->setText(COL_HNUM, QString("---")); + break; + case MidiController::RPN: + case MidiController::NRPN: + item->setText(COL_MIN, QString("0")); + item->setText(COL_MAX, QString("127")); + item->setText(COL_LNUM, QString("0")); + item->setText(COL_HNUM, QString("0")); + break; + + case MidiController::Program: + + item->setText(COL_MIN, QString("---")); + item->setText(COL_MAX, QString("---")); + item->setText(COL_LNUM, QString("---")); + item->setText(COL_HNUM, QString("---")); + break; + case MidiController::Pitch: + item->setText(COL_MIN, QString("-8192")); + item->setText(COL_MAX, QString("8191")); + item->setText(COL_LNUM, QString("---")); + item->setText(COL_HNUM, QString("---")); + break; + default: + break; + } + + setModified(true); + + controllerChanged(item); + } + +//--------------------------------------------------------- +// valueHChanged +//--------------------------------------------------------- + +void MidiControllerEditDialog::valueHChanged(int val) + { + Q3ListViewItem* item = viewController->currentItem(); + if (item == 0) + return; + QString s; + s.setNum(val); + item->setText(COL_HNUM, s); + + setModified(true); + } + +//--------------------------------------------------------- +// valueLChanged +//--------------------------------------------------------- + +void MidiControllerEditDialog::valueLChanged(int val) + { + Q3ListViewItem* item = viewController->currentItem(); + if (item == 0) + return; + QString s; + s.setNum(val); + item->setText(COL_LNUM, s); + + setModified(true); + } + +//--------------------------------------------------------- +// controllerChanged +//--------------------------------------------------------- + +void MidiControllerEditDialog::controllerChanged() + { + Q3ListViewItem* item = viewController->selectedItem(); + controllerChanged(item); + } + +void MidiControllerEditDialog::controllerChanged(Q3ListViewItem* item) + { + if (item == 0) { + entryName->setEnabled(false); + comboType->setEnabled(false); + spinboxHCtrlNo->setEnabled(false); + spinboxLCtrlNo->setEnabled(false); + spinboxMin->setEnabled(false); + spinboxMax->setEnabled(false); + return; + } + + entryName->blockSignals(true); + comboType->blockSignals(true); + spinboxHCtrlNo->blockSignals(true); + spinboxLCtrlNo->blockSignals(true); + spinboxMin->blockSignals(true); + spinboxMax->blockSignals(true); + + entryName->setEnabled(true); + entryName->setText(item->text(COL_NAME)); + comboType->setCurrentItem(int(ctrlType2Int(item->text(COL_TYPE)))); + switch (ctrlType2Int(item->text(COL_TYPE))) { + case MidiController::Controller7: + comboType->setEnabled(true); + spinboxHCtrlNo->setEnabled(false); + spinboxLCtrlNo->setEnabled(true); + spinboxMin->setEnabled(true); + spinboxMax->setEnabled(true); + spinboxHCtrlNo->setValue(0); + spinboxLCtrlNo->setValue(item->text(COL_LNUM).toInt()); + spinboxMin->setRange(0, 127); + spinboxMax->setRange(0, 127); + spinboxMin->setValue(item->text(COL_MIN).toInt()); + spinboxMax->setValue(item->text(COL_MAX).toInt()); + break; + + case MidiController::RPN: + case MidiController::NRPN: + comboType->setEnabled(true); + spinboxHCtrlNo->setEnabled(true); + spinboxLCtrlNo->setEnabled(true); + spinboxMin->setEnabled(true); + spinboxMax->setEnabled(true); + spinboxHCtrlNo->setValue(item->text(COL_HNUM).toInt()); + spinboxLCtrlNo->setValue(item->text(COL_LNUM).toInt()); + spinboxMin->setRange(0, 127); + spinboxMax->setRange(0, 127); + spinboxMin->setValue(item->text(COL_MIN).toInt()); + spinboxMax->setValue(item->text(COL_MAX).toInt()); + break; + case MidiController::Controller14: + case MidiController::RPN14: + case MidiController::NRPN14: + comboType->setEnabled(true); + spinboxHCtrlNo->setEnabled(true); + spinboxLCtrlNo->setEnabled(true); + spinboxMin->setEnabled(true); + spinboxMax->setEnabled(true); + + spinboxHCtrlNo->setValue(item->text(COL_HNUM).toInt()); + spinboxLCtrlNo->setValue(item->text(COL_LNUM).toInt()); + spinboxMin->setRange(0, 16383); + spinboxMax->setRange(0, 16383); + spinboxMin->setValue(item->text(COL_MIN).toInt()); + spinboxMax->setValue(item->text(COL_MAX).toInt()); + break; + + case MidiController::Pitch: + comboType->setEnabled(true); + spinboxHCtrlNo->setEnabled(false); + spinboxLCtrlNo->setEnabled(false); + spinboxMin->setEnabled(true); + spinboxMax->setEnabled(true); + spinboxHCtrlNo->setValue(0); + spinboxLCtrlNo->setValue(0); + spinboxMin->setRange(-8192, 8191); + spinboxMax->setRange(-8192, 8191); + spinboxMin->setValue(item->text(COL_MIN).toInt()); + spinboxMax->setValue(item->text(COL_MAX).toInt()); + break; + + case MidiController::Program: + comboType->setEnabled(true); + spinboxHCtrlNo->setEnabled(false); + spinboxLCtrlNo->setEnabled(false); + spinboxMin->setEnabled(false); + spinboxMax->setEnabled(false); + spinboxHCtrlNo->setValue(0); + spinboxLCtrlNo->setValue(0); + spinboxMin->setRange(0, 0); + spinboxMax->setRange(0, 0); + spinboxMin->setValue(0); + spinboxMax->setValue(0); + break; + default: + break; + } + entryName->blockSignals(false); + comboType->blockSignals(false); + spinboxHCtrlNo->blockSignals(false); + spinboxLCtrlNo->blockSignals(false); + spinboxMin->blockSignals(false); + spinboxMax->blockSignals(false); + } + +//--------------------------------------------------------- +// minChanged +//--------------------------------------------------------- + +void MidiControllerEditDialog::minChanged(int val) + { + Q3ListViewItem* item = viewController->currentItem(); + if (item == 0) + return; + + QString s; + s.setNum(val); + item->setText(COL_MIN, s); + + if(val > item->text(COL_MAX).toInt()) + { + spinboxMax->blockSignals(true); + spinboxMax->setValue(val); + item->setText(COL_MAX, s); + spinboxMax->blockSignals(false); + } + setModified(true); + } + +//--------------------------------------------------------- +// maxChanged +//--------------------------------------------------------- + +void MidiControllerEditDialog::maxChanged(int val) + { + Q3ListViewItem* item = viewController->currentItem(); + if (item == 0) + return; + + QString s; + s.setNum(val); + item->setText(COL_MAX, s); + + if(val < item->text(COL_MIN).toInt()) + { + spinboxMin->blockSignals(true); + spinboxMin->setValue(val); + item->setText(COL_MIN, s); + spinboxMin->blockSignals(false); + } + setModified(true); + } + +//--------------------------------------------------------- +// configMidiController +//--------------------------------------------------------- + +void configMidiController() + { + if (midiControllerEditDialog == 0) + { + midiControllerEditDialog = new MidiControllerEditDialog(); + midiControllerEditDialog->show(); + } + else + { + if(midiControllerEditDialog->isShown()) + midiControllerEditDialog->hide(); + else + midiControllerEditDialog->show(); + } + } diff --git a/attic/muse2-oom/muse2/muse/instruments/midictrledit.h b/attic/muse2-oom/muse2/muse/instruments/midictrledit.h new file mode 100644 index 00000000..e1624f29 --- /dev/null +++ b/attic/muse2-oom/muse2/muse/instruments/midictrledit.h @@ -0,0 +1,56 @@ +//========================================================= +// MusE +// Linux Music Editor +// $Id: midictrledit.h,v 1.1.1.1.2.1 2008/08/18 00:15:25 terminator356 Exp $ +// +// (C) Copyright 1999/2000 Werner Schweer (ws@seh.de) +//========================================================= + +#ifndef __MIDICTRLEDIT_H__ +#define __MIDICTRLEDIT_H__ + +#include "ccontrolbase.h" +#include "midictrl.h" + +//--------------------------------------------------------- +// MidiControllerEditDialog +//--------------------------------------------------------- + +class MidiControllerEditDialog : public MidiControllerEditDialogBase { + Q_OBJECT + + int _lastPort; + bool _modified; + + void addControllerToView(MidiController* mctrl); + void mergeReplace(bool replace); + void updatePredefinedList(); + void updateMidiPortsList(); + void updateViewController(); + void setModified(bool); + + private slots: + void ctrlAdd(); + void ctrlDelete(); + virtual void accept(); + virtual void reject(); + void apply(); + void nameChanged(const QString&); + void typeChanged(const QString&); + void valueHChanged(int); + void valueLChanged(int); + void controllerChanged(Q3ListViewItem*); + void controllerChanged(); + void minChanged(int); + void maxChanged(int); + void portChanged(int); + void songChanged(int); + + public: + MidiControllerEditDialog(QWidget* parent = 0, const char* name = 0, bool modal = false, Qt::WFlags fl = 0); + }; + +extern MidiControllerEditDialog* midiControllerEditDialog; +extern void configMidiController(); +#endif + diff --git a/attic/muse2-oom/muse2/muse/instruments/minstrument.cpp b/attic/muse2-oom/muse2/muse/instruments/minstrument.cpp new file mode 100644 index 00000000..8df7d4c7 --- /dev/null +++ b/attic/muse2-oom/muse2/muse/instruments/minstrument.cpp @@ -0,0 +1,927 @@ +//========================================================= +// MusE +// Linux Music Editor +// $Id: minstrument.cpp,v 1.10.2.5 2009/03/28 01:46:10 terminator356 Exp $ +// +// (C) Copyright 2000-2003 Werner Schweer (ws@seh.de) +//========================================================= + +#include <stdio.h> + +#include <QAction> +#include <QDir> +#include <QFileInfo> +#include <QMenu> +#include <QMessageBox> +#include <QList> + +#include "minstrument.h" +#include "midiport.h" +#include "globals.h" +#include "xml.h" +#include "event.h" +#include "mpevent.h" +#include "midictrl.h" +#include "gconfig.h" + +MidiInstrumentList midiInstruments; +MidiInstrument* genericMidiInstrument; + +static const char* gmdrumname = "GM-drums"; + +//--------------------------------------------------------- +// string2sysex +//--------------------------------------------------------- + +int string2sysex(const QString& s, unsigned char** data) + { + QByteArray ba = s.toLatin1(); + const char* src = ba.constData(); + char buffer[2048]; + char* dst = buffer; + + if(src) { + while (*src) { + while (*src == ' ' || *src == '\n') { + ++src; + } + char* ep; + long val = strtol(src, &ep, 16); + if (ep == src) { + QMessageBox::information(0, + QString("MusE"), + QWidget::tr("Cannot convert sysex string")); + return 0; + } + src = ep; + *dst++ = val; + if (dst - buffer >= 2048) { + QMessageBox::information(0, + QString("MusE"), + QWidget::tr("Hex String too long (2048 bytes limit)")); + return 0; + } + } + } + int len = dst - buffer; + unsigned char* b = new unsigned char[len+1]; + memcpy(b, buffer, len); + b[len] = 0; + *data = b; + return len; + } + +//--------------------------------------------------------- +// sysex2string +//--------------------------------------------------------- + +QString sysex2string(int len, unsigned char* data) + { + QString d; + QString s; + for (int i = 0; i < len; ++i) { + if ((i > 0) && ((i % 8)==0)) { + d += "\n"; + } + else if (i) + d += " "; + d += s.sprintf("%02x", data[i]); + } + return d; + } + +//--------------------------------------------------------- +// readEventList +//--------------------------------------------------------- + +static void readEventList(Xml& xml, EventList* el, const char* name) + { + for (;;) { + Xml::Token token = xml.parse(); + const QString& tag = xml.s1(); + switch (token) { + case Xml::Error: + case Xml::End: + return; + case Xml::TagStart: + if (tag == "event") { + Event e(Note); + e.read(xml); + el->add(e); + } + else + xml.unknown("readEventList"); + break; + case Xml::TagEnd: + if (tag == name) + return; + default: + break; + } + } + } + +//--------------------------------------------------------- +// read +//--------------------------------------------------------- + +//--------------------------------------------------------- +// loadIDF +//--------------------------------------------------------- + +static void loadIDF(QFileInfo* fi) + { +/* + QFile qf(fi->filePath()); + if (!qf.open(IO_ReadOnly)) { + printf("cannot open file %s\n", fi->fileName().toLatin1()); + return; + } + if (debugMsg) + printf(" load instrument definition <%s>\n", fi->filePath().local8Bit().data()); + QDomDocument doc; + int line, column; + QString err; + if (!doc.setContent(&qf, false, &err, &line, &column)) { + QString col, ln, error; + col.setNum(column); + ln.setNum(line); + error = err + " at line: " + ln + " col: " + col; + printf("error reading file <%s>:\n %s\n", + fi->filePath().toLatin1(), error.toLatin1()); + return; + } + QDomNode node = doc.documentElement(); + while (!node.isNull()) { + QDomElement e = node.toElement(); + if (e.isNull()) + continue; + if (e.tagName() == "muse") { + QString version = e.attribute(QString("version")); + for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) { + QDomElement e = n.toElement(); + if (e.tagName() == "MidiInstrument") { + MidiInstrument* i = new MidiInstrument(); + i->read(n); + i->setFilePath(fi->filePath()); + 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; + } + } + } + else + printf("MusE:laodIDF: %s not supported\n", e.tagName().toLatin1()); + node = node.nextSibling(); + } + qf.close(); +*/ + + FILE* f = fopen(fi->filePath().toAscii().constData(), "r"); + if (f == 0) + return; + if (debugMsg) + printf("READ IDF %s\n", fi->filePath().toLatin1().constData()); + Xml xml(f); + + bool skipmode = true; + for (;;) { + Xml::Token token = xml.parse(); + const QString& tag = xml.s1(); + switch (token) { + case Xml::Error: + case Xml::End: + return; + case Xml::TagStart: + if (skipmode && tag == "muse") + skipmode = false; + else if (skipmode) + break; + else if (tag == "MidiInstrument") { + MidiInstrument* i = new MidiInstrument(); + i->setFilePath(fi->filePath()); + i->read(xml); + // Ignore duplicate named instruments. + iMidiInstrument ii = midiInstruments.begin(); + for(; ii != midiInstruments.end(); ++ii) + { + if((*ii)->iname() == i->iname()) + break; + } + if(ii == midiInstruments.end()) + midiInstruments.push_back(i); + else + delete i; + } + else + xml.unknown("muse"); + break; + case Xml::Attribut: + break; + case Xml::TagEnd: + if (!skipmode && tag == "muse") { + return; + } + default: + break; + } + } + fclose(f); + + + } + +//--------------------------------------------------------- +// initMidiInstruments +//--------------------------------------------------------- + +void initMidiInstruments() + { + genericMidiInstrument = new MidiInstrument(QWidget::tr("generic midi")); + midiInstruments.push_back(genericMidiInstrument); + if (debugMsg) + printf("load user instrument definitions from <%s>\n", museUserInstruments.toLatin1().constData()); + QDir usrInstrumentsDir(museUserInstruments, QString("*.idf")); + if (usrInstrumentsDir.exists()) { + QFileInfoList list = usrInstrumentsDir.entryInfoList(); + QFileInfoList::iterator it=list.begin(); // ddskrjo + while(it != list.end()) { // ddskrjo + loadIDF(&*it); + ++it; + } + } + //else + //{ + // if(usrInstrumentsDir.mkdir(museUserInstruments)) + // printf("Created user instrument directory: %s\n", museUserInstruments.toLatin1()); + // else + // printf("Unable to create user instrument directory: %s\n", museUserInstruments.toLatin1()); + //} + + if (debugMsg) + printf("load instrument definitions from <%s>\n", museInstruments.toLatin1().constData()); + QDir instrumentsDir(museInstruments, QString("*.idf")); + if (instrumentsDir.exists()) { + QFileInfoList list = instrumentsDir.entryInfoList(); + QFileInfoList::iterator it=list.begin(); // ddskrjo + while(it!=list.end()) { + loadIDF(&*it); + ++it; + } + } + else + printf("Instrument directory not found: %s\n", museInstruments.toLatin1().constData()); + + } + +//--------------------------------------------------------- +// registerMidiInstrument +//--------------------------------------------------------- + +MidiInstrument* registerMidiInstrument(const QString& name) + { + for (iMidiInstrument i = midiInstruments.begin(); + i != midiInstruments.end(); ++i) { + if ((*i)->iname() == name) + return *i; + } + return genericMidiInstrument; + } + +//--------------------------------------------------------- +// removeMidiInstrument +//--------------------------------------------------------- + +void removeMidiInstrument(const QString& name) + { + for (iMidiInstrument i = midiInstruments.begin(); + i != midiInstruments.end(); ++i) { + if ((*i)->iname() == name) { + midiInstruments.erase(i); + return; + } + } + } + +void removeMidiInstrument(const MidiInstrument* instr) + { + for (iMidiInstrument i = midiInstruments.begin(); + i != midiInstruments.end(); ++i) { + if (*i == instr) { + midiInstruments.erase(i); + return; + } + } + } + +//--------------------------------------------------------- +// MidiInstrument +//--------------------------------------------------------- + +void MidiInstrument::init() + { + _nullvalue = -1; + _initScript = 0; + _midiInit = new EventList(); + _midiReset = new EventList(); + _midiState = new EventList(); + _controller = new MidiControllerList; + + // add some default controller to controller list + // this controllers are always available for all instruments + // + MidiController* prog = new MidiController("Program", CTRL_PROGRAM, 0, 0xffffff, 0); + _controller->add(prog); + _dirty = false; + } + +MidiInstrument::MidiInstrument() + { + init(); + } + +//--------------------------------------------------------- +// MidiInstrument +//--------------------------------------------------------- + +MidiInstrument::MidiInstrument(const QString& txt) + { + _name = txt; + init(); + } + +//--------------------------------------------------------- +// MidiInstrument +//--------------------------------------------------------- + +MidiInstrument::~MidiInstrument() + { + for (ciPatchGroup g = pg.begin(); g != pg.end(); ++g) + { + PatchGroup* pgp = *g; + const PatchList& pl = pgp->patches; + for (ciPatch p = pl.begin(); p != pl.end(); ++p) + { + delete *p; + } + delete pgp; + } + + + delete _midiInit; + delete _midiReset; + delete _midiState; + for(iMidiController i = _controller->begin(); i != _controller->end(); ++i) + delete i->second; + delete _controller; + + if (_initScript) + delete _initScript; + } + +/* +//--------------------------------------------------------- +// uniqueCopy +//--------------------------------------------------------- + +MidiInstrument& MidiInstrument::uniqueCopy(const MidiInstrument& ins) +{ + _initScript = 0; + _midiInit = new EventList(); + _midiReset = new EventList(); + _midiState = new EventList(); + //--------------------------------------------------------- + // TODO: Copy the init script, and the lists. + //--------------------------------------------------------- + _controller = new MidiControllerList(*(ins._controller)); + + // Assignment + pg = ins.pg; + + _name = ins._name; + _filePath = ins._filePath; + + // Hmm, dirty, yes? But init sets it to false... + //_dirty = ins._dirty; + //_dirty = false; + _dirty = true; + + return *this; +} +*/ + +//--------------------------------------------------------- +// assign +//--------------------------------------------------------- + +MidiInstrument& MidiInstrument::assign(const MidiInstrument& ins) +{ + //--------------------------------------------------------- + // TODO: Copy the _initScript, and _midiInit, _midiReset, and _midiState lists. + //--------------------------------------------------------- + + for(iMidiController i = _controller->begin(); i != _controller->end(); ++i) + delete i->second; + _controller->clear(); + + _nullvalue = ins._nullvalue; + + // Assignment + // *_controller = *(ins._controller); + for(ciMidiController i = ins._controller->begin(); i != ins._controller->end(); ++i) + { + MidiController* mc = i->second; + _controller->add(new MidiController(*mc)); + } + +// pg.clear(); +// for(iPatchGroup ipg = pg.begin(); ipg != pg.end(); ++ipg) +// { + //ipg->patches.clear(); + + //const PatchGroup& g = *ipg; + //for(ciPatch ip = ipg->begin(); ip != ipg->end(); ++ipg) + //{ + + //} +// } + + for (ciPatchGroup g = pg.begin(); g != pg.end(); ++g) + { + PatchGroup* pgp = *g; + const PatchList& pl = pgp->patches; + for (ciPatch p = pl.begin(); p != pl.end(); ++p) + { + delete *p; + } + + delete pgp; + } + pg.clear(); + + // Assignment +// pg = ins.pg; + for(ciPatchGroup g = ins.pg.begin(); g != ins.pg.end(); ++g) + { + PatchGroup* pgp = *g; + const PatchList& pl = pgp->patches; + PatchGroup* npg = new PatchGroup; + npg->name = pgp->name; + pg.push_back(npg); + for (ciPatch p = pl.begin(); p != pl.end(); ++p) + { + Patch* pp = *p; + Patch* np = new Patch; + np->typ = pp->typ; + np->hbank = pp->hbank; + np->lbank = pp->lbank; + np->prog = pp->prog; + np->name = pp->name; + np->drum = pp->drum; + npg->patches.push_back(np); + } + } + + _name = ins._name; + _filePath = ins._filePath; + + // Hmm, dirty, yes? But init sets it to false... + //_dirty = ins._dirty; + //_dirty = false; + //_dirty = true; + + return *this; +} + +//--------------------------------------------------------- +// reset +// send note off to all channels +//--------------------------------------------------------- + +void MidiInstrument::reset(int portNo, MType) + { + MidiPlayEvent ev; + ev.setType(0x90); + MidiPort* port = &midiPorts[portNo]; + if (port == 0) + return; + ev.setPort(portNo); + for (int chan = 0; chan < MIDI_CHANNELS; ++chan) { + ev.setChannel(chan); + for (int pitch = 0; pitch < 128; ++pitch) { + ev.setA(pitch); + ev.setB(0); + port->sendEvent(ev); + } + } + } + +//--------------------------------------------------------- +// readPatchGroup +//--------------------------------------------------------- + +void PatchGroup::read(Xml& xml) + { + for (;;) { + Xml::Token token = xml.parse(); + const QString& tag = xml.s1(); + switch (token) { + case Xml::Error: + case Xml::End: + return; + case Xml::TagStart: + if (tag == "Patch") { + Patch* patch = new Patch; + patch->read(xml); + patches.push_back(patch); + } + else + xml.unknown("PatchGroup"); + break; + case Xml::Attribut: + if (tag == "name") + name = xml.s2(); + break; + case Xml::TagEnd: + if (tag == "PatchGroup") + return; + default: + break; + } + } + } + +//--------------------------------------------------------- +// read +//--------------------------------------------------------- + +void Patch::read(Xml& xml) + { + typ = -1; + hbank = -1; + lbank = -1; + prog = 0; + drum = false; + for (;;) { + Xml::Token token = xml.parse(); + const QString& tag = xml.s1(); + switch (token) { + case Xml::Error: + case Xml::End: + return; + case Xml::TagStart: + xml.unknown("Patch"); + break; + case Xml::Attribut: + if (tag == "name") + name = xml.s2(); + else if (tag == "mode") + typ = xml.s2().toInt(); + else if (tag == "hbank") + hbank = xml.s2().toInt(); + else if (tag == "lbank") + lbank = xml.s2().toInt(); + else if (tag == "prog") + prog = xml.s2().toInt(); + else if (tag == "drum") + drum = xml.s2().toInt(); + break; + case Xml::TagEnd: + if (tag == "Patch") + return; + default: + break; + } + } + } + +//--------------------------------------------------------- +// write +//--------------------------------------------------------- + +void Patch::write(int level, Xml& xml) + { + //if (drumMap == 0) + //{ + //QString s = QString("Patch name=\"%1\"").arg(Xml::xmlString(name)); + //if (typ != -1) + // s += QString(" mode=\"%d\"").arg(typ); + //s += QString(" hbank=\"%1\" lbank=\"%2\" prog=\"%3\"").arg(hbank).arg(lbank).arg(prog); + //xml.tagE(s); + xml.nput(level, "<Patch name=\"%s\"", Xml::xmlString(name).toLatin1().constData()); + if(typ != -1) + xml.nput(" mode=\"%d\"", typ); + + if(hbank != -1) + xml.nput(" hbank=\"%d\"", hbank); + + if(lbank != -1) + xml.nput(" lbank=\"%d\"", lbank); + + xml.nput(" prog=\"%d\"", prog); + + //xml.nput(level, " hbank=\"%d\" lbank=\"%d\" prog=\"%d\"", hbank, lbank, prog); + if(drum) + //xml.nput(level, " drum=\"%d\"", int(drum)); + xml.nput(" drum=\"%d\"", int(drum)); + //xml.put(level, " />"); + xml.put(" />"); + + //return; + //} + + //QString s = QString("drummap name=\"%1\"").arg(Xml::xmlString(name)); + //s += QString(" hbank=\"%1\" lbank=\"%2\" prog=\"%3\"").arg(hbank).arg(lbank).arg(prog); + //xml.stag(s); + //for (int i = 0; i < DRUM_MAPSIZE; ++i) { + // DrumMapEntry* dm = drumMap->entry(i); + // dm->write(xml); + // } + //xml.etag("drummap"); + } + +//--------------------------------------------------------- +// readMidiState +//--------------------------------------------------------- + +void MidiInstrument::readMidiState(Xml& xml) + { + _midiState->read(xml, "midistate", true); + } + +//--------------------------------------------------------- +// read +//--------------------------------------------------------- + +void MidiInstrument::read(Xml& xml) + { + bool ok; + int base = 10; + _nullvalue = -1; + for (;;) { + Xml::Token token = xml.parse(); + const QString& tag = xml.s1(); + switch (token) { + case Xml::Error: + case Xml::End: + return; + case Xml::TagStart: + if (tag == "Patch") { + Patch* patch = new Patch; + patch->read(xml); + if (pg.empty()) { + PatchGroup* p = new PatchGroup; + p->patches.push_back(patch); + pg.push_back(p); + } + else + pg[0]->patches.push_back(patch); + } + else if (tag == "PatchGroup") { + PatchGroup* p = new PatchGroup; + p->read(xml); + pg.push_back(p); + } + else if (tag == "Controller") { + MidiController* mc = new MidiController(); + mc->read(xml); + // Added by Tim. Copied from muse 2. + // + // HACK: make predefined "Program" controller overloadable + // + if (mc->name() == "Program") { + for (iMidiController i = _controller->begin(); i != _controller->end(); ++i) { + if (i->second->name() == mc->name()) { + delete i->second; + _controller->erase(i); + break; + } + } + } + + _controller->add(mc); + } + else if (tag == "Init") + readEventList(xml, _midiInit, "Init"); + else if (tag == "Reset") + readEventList(xml, _midiReset, "Reset"); + else if (tag == "State") + readEventList(xml, _midiState, "State"); + else if (tag == "InitScript") { + if (_initScript) + delete _initScript; + QByteArray ba = xml.parse1().toLatin1(); + const char* istr = ba.constData(); + int len = strlen(istr) +1; + if (len > 1) { + _initScript = new char[len]; + memcpy(_initScript, istr, len); + } + } + + else + xml.unknown("MidiInstrument"); + break; + case Xml::Attribut: + if (tag == "name") + setIName(xml.s2()); + else if(tag == "nullparam") { + _nullvalue = xml.s2().toInt(&ok, base); + } + break; + case Xml::TagEnd: + if (tag == "MidiInstrument") + return; + default: + break; + } + } + } + +//--------------------------------------------------------- +// write +//--------------------------------------------------------- + +void MidiInstrument::write(int level, Xml& xml) + { + xml.header(); + //xml.stag("muse version=\"2.1\""); + xml.tag(level, "muse version=\"1.0\""); + //xml.stag(QString("MidiInstrument name=\"%1\"").arg(Xml::xmlString(iname()))); + level++; + //xml.tag(level, "MidiInstrument name=\"%s\"", Xml::xmlString(iname()).toLatin1().constData()); + xml.nput(level, "<MidiInstrument name=\"%s\"", Xml::xmlString(iname()).toLatin1().constData()); + + if(_nullvalue != -1) + { + QString nv; + nv.setNum(_nullvalue); + xml.nput(" nullparam=\"%s\"", nv.toLatin1().constData()); + } + xml.put(">"); + + // ------------- + // What about Init, Reset, State, and InitScript ? + // ------------- + + //std::vector<PatchGroup>* pg = groups(); + //for (std::vector<PatchGroup>::iterator g = pg->begin(); g != pg->end(); ++g) { + level++; + //for (std::vector<PatchGroup>::iterator g = pg.begin(); g != pg.end(); ++g) { + for (ciPatchGroup g = pg.begin(); g != pg.end(); ++g) { + PatchGroup* pgp = *g; + const PatchList& pl = pgp->patches; + //xml.stag(QString("PatchGroup name=\"%1\"").arg(Xml::xmlString(g->name))); + //xml.tag(level, "PatchGroup name=\"%s\"", Xml::xmlString(g->name).toLatin1().constData()); + xml.tag(level, "PatchGroup name=\"%s\"", Xml::xmlString(pgp->name).toLatin1().constData()); + level++; + //for (iPatch p = g->patches.begin(); p != g->patches.end(); ++p) + for (ciPatch p = pl.begin(); p != pl.end(); ++p) + //(*p)->write(xml); + //p->write(level, xml); + (*p)->write(level, xml); + level--; + //xml.etag("PatchGroup"); + xml.etag(level, "PatchGroup"); + } + for (iMidiController ic = _controller->begin(); ic != _controller->end(); ++ic) + //(*ic)->write(xml); + ic->second->write(level, xml); + //xml.etag("MidiInstrument"); + level--; + xml.etag(level, "MidiInstrument"); + //xml.etag("muse"); + level--; + xml.etag(level, "muse"); + } + +//--------------------------------------------------------- +// getPatchName +//--------------------------------------------------------- + +QString MidiInstrument::getPatchName(int channel, int prog, MType mode, bool drum) + { + int pr = prog & 0xff; + if(prog == CTRL_VAL_UNKNOWN || pr == 0xff) + return "<unknown>"; + + int hbank = (prog >> 16) & 0xff; + int lbank = (prog >> 8) & 0xff; + int tmask = 1; + bool drumchan = channel == 9; + bool hb = false; + bool lb = false; + switch (mode) { + case MT_GS: + tmask = 2; + hb = true; + break; + case MT_XG: + hb = true; + lb = true; + tmask = 4; + break; + case MT_GM: + if(drumchan) + return gmdrumname; + tmask = 1; + break; + default: + hb = true; // MSB bank matters + lb = true; // LSB bank matters + break; + } + for (ciPatchGroup i = pg.begin(); i != pg.end(); ++i) { + const PatchList& pl = (*i)->patches; + for (ciPatch ipl = pl.begin(); ipl != pl.end(); ++ipl) { + const Patch* mp = *ipl; + if ((mp->typ & tmask) + && (pr == mp->prog) + && ((drum && mode != MT_GM) || + (mp->drum == drumchan)) + + && (hbank == mp->hbank || !hb || mp->hbank == -1) + && (lbank == mp->lbank || !lb || mp->lbank == -1)) + return mp->name; + } + } + return "<unknown>"; + } + +//--------------------------------------------------------- +// populatePatchPopup +//--------------------------------------------------------- + +void MidiInstrument::populatePatchPopup(QMenu* menu, int chan, MType songType, bool drum) + { + menu->clear(); + int mask = 0; + bool drumchan = chan == 9; + switch (songType) { + case MT_XG: mask = 4; break; + case MT_GS: mask = 2; break; + case MT_GM: + if(drumchan) + return; + mask = 1; + break; + case MT_UNKNOWN: mask = 7; break; + } + if (pg.size() > 1) { + for (ciPatchGroup i = pg.begin(); i != pg.end(); ++i) { + PatchGroup* pgp = *i; + QMenu* pm = menu->addMenu(pgp->name); + pm->setFont(config.fonts[0]); + const PatchList& pl = pgp->patches; + QString& gname = pgp->name; + for (ciPatch ipl = pl.begin(); ipl != pl.end(); ++ipl) { + const Patch* mp = *ipl; + if ((mp->typ & mask) && + ((drum && songType != MT_GM) || + (mp->drum == drumchan)) ) + { + int id = ((mp->hbank & 0xff) << 16) + + ((mp->lbank & 0xff) << 8) + (mp->prog & 0xff); + QAction* act = pm->addAction(mp->name); + //act->setCheckable(true); + QString strId = QString::number(id); + QStringList _data = (QStringList() << strId << gname); + //_data->append(strId); + //_data->append(gname); + //act->setData(id); + act->setData(_data); + } + + } + } + } + else if (pg.size() == 1 ){ + // no groups + const PatchList& pl = pg.front()->patches; + for (ciPatch ipl = pl.begin(); ipl != pl.end(); ++ipl) { + const Patch* mp = *ipl; + if (mp->typ & mask) { + int id = ((mp->hbank & 0xff) << 16) + + ((mp->lbank & 0xff) << 8) + (mp->prog & 0xff); + QAction* act = menu->addAction(mp->name); + //act->setCheckable(true); + QString strId = QString::number(id); + QStringList _data = (QStringList() << strId); + //_data->append(strId); + //act->setData(id); + act->setData(_data); + } + } + } + } + diff --git a/attic/muse2-oom/muse2/muse/instruments/minstrument.h b/attic/muse2-oom/muse2/muse/instruments/minstrument.h new file mode 100644 index 00000000..0c37701f --- /dev/null +++ b/attic/muse2-oom/muse2/muse/instruments/minstrument.h @@ -0,0 +1,145 @@ +//========================================================= +// MusE +// Linux Music Editor +// $Id: minstrument.h,v 1.3.2.3 2009/03/09 02:05:18 terminator356 Exp $ +// +// (C) Copyright 2000 Werner Schweer (ws@seh.de) +//========================================================= + +#ifndef __MINSTRUMENT_H__ +#define __MINSTRUMENT_H__ + +#include "globaldefs.h" +#include <list> +#include <vector> + +class MidiPort; +class QMenu; +class MidiPlayEvent; +class Xml; +class EventList; +class MidiControllerList; +class QString; + +//--------------------------------------------------------- +// Patch +//--------------------------------------------------------- + +struct Patch { + signed char typ; // 1 - GM 2 - GS 4 - XG + signed char hbank, lbank, prog; + QString name; + bool drum; + void read(Xml&); + void write(int level, Xml&); + }; + +typedef std::list<Patch*> PatchList; +typedef PatchList::iterator iPatch; +typedef PatchList::const_iterator ciPatch; + +//--------------------------------------------------------- +// PatchGroup +//--------------------------------------------------------- + +struct PatchGroup { + QString name; + PatchList patches; + void read(Xml&); + }; + +typedef std::vector<PatchGroup*> PatchGroupList; +typedef PatchGroupList::iterator iPatchGroup; +typedef PatchGroupList::const_iterator ciPatchGroup; + +struct SysEx { + QString name; + QString comment; + int dataLen; + unsigned char* data; + }; + +//--------------------------------------------------------- +// MidiInstrument +//--------------------------------------------------------- + +class MidiInstrument { + PatchGroupList pg; + MidiControllerList* _controller; + QList<SysEx*> _sysex; + bool _dirty; + int _nullvalue; + + void init(); + + protected: + EventList* _midiInit; + EventList* _midiReset; + EventList* _midiState; + char* _initScript; + QString _name; + QString _filePath; + + public: + MidiInstrument(); + virtual ~MidiInstrument(); + MidiInstrument(const QString& txt); + const QString& iname() const { return _name; } + void setIName(const QString& txt) { _name = txt; } + + //MidiInstrument& uniqueCopy(const MidiInstrument&); + // Assign will 'delete' all existing patches and groups from the instrument. + MidiInstrument& assign(const MidiInstrument&); + QString filePath() const { return _filePath; } + void setFilePath(const QString& s) { _filePath = s; } + bool dirty() const { return _dirty; } + void setDirty(bool v) { _dirty = v; } + + const QList<SysEx*>& sysex() const { return _sysex; } + void removeSysex(SysEx* sysex) { _sysex.removeAll(sysex); } + void addSysex(SysEx* sysex) { _sysex.append(sysex); } + + EventList* midiInit() const { return _midiInit; } + EventList* midiReset() const { return _midiReset; } + EventList* midiState() const { return _midiState; } + const char* initScript() const { return _initScript; } + MidiControllerList* controller() const { return _controller; } + int nullSendValue() { return _nullvalue; } + void setNullSendValue(int v) { _nullvalue = v; } + + void readMidiState(Xml& xml); + virtual bool guiVisible() const { return false; } + virtual void showGui(bool) {} + virtual bool hasGui() const { return false; } + virtual void writeToGui(const MidiPlayEvent&) {} + + virtual void reset(int, MType); + virtual QString getPatchName(int,int,MType,bool); + virtual void populatePatchPopup(QMenu*, int, MType, bool); + void read(Xml&); + void write(int level, Xml&); + + PatchGroupList* groups() { return &pg; } + }; + +//--------------------------------------------------------- +// MidiInstrumentList +//--------------------------------------------------------- + +class MidiInstrumentList : public std::list<MidiInstrument*> { + + public: + MidiInstrumentList() {} + }; + +typedef MidiInstrumentList::iterator iMidiInstrument; + +extern MidiInstrumentList midiInstruments; +extern MidiInstrument* genericMidiInstrument; +extern void initMidiInstruments(); +extern MidiInstrument* registerMidiInstrument(const QString&); +extern void removeMidiInstrument(const QString& name); +extern void removeMidiInstrument(const MidiInstrument* instr); + +#endif + |