/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ /* Rosegarden A MIDI and audio sequencer and musical notation editor. This program is Copyright 2000-2008 Guillaume Laurent , Chris Cannam , Richard Bown The moral rights of Guillaume Laurent, Chris Cannam, and Richard Bown to claim authorship of this work have been asserted. Other copyrights also apply to some parts of this work. Please see the AUTHORS file and individual file headers for details. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. See the file COPYING included with this distribution for more information. */ #include "MIDIInstrumentParameterPanel.h" #include #include "sound/Midi.h" #include #include "misc/Debug.h" #include "misc/Strings.h" #include "base/Colour.h" #include "base/Composition.h" #include "base/ControlParameter.h" #include "base/Instrument.h" #include "base/MidiDevice.h" #include "base/MidiProgram.h" #include "document/RosegardenGUIDoc.h" #include "gui/studio/StudioControl.h" #include "gui/widgets/Rotary.h" #include "InstrumentParameterPanel.h" #include "sound/MappedEvent.h" #include "sound/MappedInstrument.h" #include #include #include #include #include #include #include #include #include #include #include #include #include namespace Rosegarden { MIDIInstrumentParameterPanel::MIDIInstrumentParameterPanel(RosegardenGUIDoc *doc, TQWidget* parent): InstrumentParameterPanel(doc, parent), m_rotaryFrame(0), m_rotaryMapper(new TQSignalMapper(TQT_TQOBJECT(this))) { m_mainGrid = new TQGridLayout(this, 10, 3, 2, 1); m_connectionLabel = new KSqueezedTextLabel(this); m_bankValue = new KComboBox(this); m_channelValue = new KComboBox(this); m_programValue = new KComboBox(this); m_variationValue = new KComboBox(this); m_bankCheckBox = new TQCheckBox(this); m_programCheckBox = new TQCheckBox(this); m_variationCheckBox = new TQCheckBox(this); m_percussionCheckBox = new TQCheckBox(this); m_bankValue->setSizeLimit(20); m_programValue->setSizeLimit(20); m_variationValue->setSizeLimit(20); m_bankLabel = new TQLabel(i18n("Bank"), this); m_variationLabel = new TQLabel(i18n("Variation"), this); m_programLabel = new TQLabel(i18n("Program"), this); TQLabel *channelLabel = new TQLabel(i18n("Channel out"), this); TQLabel *percussionLabel = new TQLabel(i18n("Percussion"), this); // Ensure a reasonable amount of space in the program dropdowns even // if no instrument initially selected TQFontMetrics metrics(m_programValue->font()); int width22 = metrics.width("1234567890123456789012"); int width25 = metrics.width("1234567890123456789012345"); m_bankValue->setMinimumWidth(width22); m_programValue->setMinimumWidth(width22); m_variationValue->setMinimumWidth(width22); m_connectionLabel->setFixedWidth(width25); m_connectionLabel->setAlignment(TQt::AlignCenter); // Configure the empty final row to accomodate any extra vertical space. m_mainGrid->setRowStretch(m_mainGrid->numRows() - 1, 1); m_mainGrid->setColStretch(2, 1); m_mainGrid->addMultiCellWidget(m_instrumentLabel, 0, 0, 0, 2, AlignCenter); m_mainGrid->addMultiCellWidget(m_connectionLabel, 1, 1, 0, 2, AlignCenter); m_mainGrid->addMultiCellWidget(channelLabel, 2, 2, 0, 1, AlignLeft); m_mainGrid->addWidget(m_channelValue, 2, 2, AlignRight); m_mainGrid->addMultiCellWidget(percussionLabel, 3, 3, 0, 1, AlignLeft); m_mainGrid->addWidget(m_percussionCheckBox, 3, 2, AlignRight); m_mainGrid->addWidget(m_bankLabel, 4, 0, AlignLeft); m_mainGrid->addWidget(m_bankCheckBox, 4, 1, AlignRight); m_mainGrid->addWidget(m_bankValue, 4, 2, AlignRight); m_mainGrid->addWidget(m_programLabel, 5, 0, AlignLeft); m_mainGrid->addWidget(m_programCheckBox, 5, 1, AlignRight); m_mainGrid->addWidget(m_programValue, 5, 2, AlignRight); m_mainGrid->addWidget(m_variationLabel, 6, 0); m_mainGrid->addWidget(m_variationCheckBox, 6, 1); m_mainGrid->addWidget(m_variationValue, 6, 2, AlignRight); // Populate channel lists // for (int i = 0; i < 16; i++) { m_channelValue->insertItem(TQString("%1").arg(i + 1)); } m_channelValue->setSizeLimit(16); // Disable these by default - they are activate by their // checkboxes // m_programValue->setDisabled(true); m_bankValue->setDisabled(true); m_variationValue->setDisabled(true); // Only active if we have an Instrument selected // m_percussionCheckBox->setDisabled(true); m_programCheckBox->setDisabled(true); m_bankCheckBox->setDisabled(true); m_variationCheckBox->setDisabled(true); // Connect up the toggle boxes // connect(m_percussionCheckBox, TQT_SIGNAL(toggled(bool)), this, TQT_SLOT(slotTogglePercussion(bool))); connect(m_programCheckBox, TQT_SIGNAL(toggled(bool)), this, TQT_SLOT(slotToggleProgramChange(bool))); connect(m_bankCheckBox, TQT_SIGNAL(toggled(bool)), this, TQT_SLOT(slotToggleBank(bool))); connect(m_variationCheckBox, TQT_SIGNAL(toggled(bool)), this, TQT_SLOT(slotToggleVariation(bool))); // Connect activations // connect(m_bankValue, TQT_SIGNAL(activated(int)), this, TQT_SLOT(slotSelectBank(int))); connect(m_variationValue, TQT_SIGNAL(activated(int)), this, TQT_SLOT(slotSelectVariation(int))); connect(m_programValue, TQT_SIGNAL(activated(int)), this, TQT_SLOT(slotSelectProgram(int))); connect(m_channelValue, TQT_SIGNAL(activated(int)), this, TQT_SLOT(slotSelectChannel(int))); // don't select any of the options in any dropdown m_programValue->setCurrentItem( -1); m_bankValue->setCurrentItem( -1); m_channelValue->setCurrentItem( -1); m_variationValue->setCurrentItem( -1); connect(m_rotaryMapper, TQT_SIGNAL(mapped(int)), this, TQT_SLOT(slotControllerChanged(int))); } void MIDIInstrumentParameterPanel::setupForInstrument(Instrument *instrument) { RG_DEBUG << "MIDIInstrumentParameterPanel::setupForInstrument" << endl; MidiDevice *md = dynamic_cast (instrument->getDevice()); if (!md) { RG_DEBUG << "WARNING: MIDIInstrumentParameterPanel::setupForInstrument:" << " No MidiDevice for Instrument " << instrument->getId() << endl; return ; } m_selectedInstrument = instrument; // Set instrument name // m_instrumentLabel->setText(strtoqstr(instrument->getPresentationName())); // Set Studio Device name // TQString connection(strtoqstr(md->getConnection())); if (connection == "") { m_connectionLabel->setText(i18n("[ %1 ]").arg(i18n("No connection"))); } else { // remove trailing "(duplex)", "(read only)", "(write only)" etc connection.replace(TQRegExp("\\s*\\([^)0-9]+\\)\\s*$"), ""); TQString text = i18n("[ %1 ]").arg(connection); /*TQString origText(text); TQFontMetrics metrics(m_connectionLabel->fontMetrics()); int maxwidth = metrics.width ("Program: [X] Acoustic Grand Piano 123");// kind of arbitrary! int hlen = text.length() / 2; while (metrics.width(text) > maxwidth && text.length() > 10) { --hlen; text = origText.left(hlen) + "..." + origText.right(hlen); } if (text.length() > origText.length() - 7) text = origText;*/ m_connectionLabel->setText(text); } // Enable all check boxes // m_percussionCheckBox->setDisabled(false); m_programCheckBox->setDisabled(false); m_bankCheckBox->setDisabled(false); m_variationCheckBox->setDisabled(false); // Activate all checkboxes // m_percussionCheckBox->setChecked(instrument->isPercussion()); m_programCheckBox->setChecked(instrument->sendsProgramChange()); m_bankCheckBox->setChecked(instrument->sendsBankSelect()); m_variationCheckBox->setChecked(instrument->sendsBankSelect()); // Basic parameters // m_channelValue->setCurrentItem((int)instrument->getMidiChannel()); // Check for program change // populateBankList(); populateProgramList(); populateVariationList(); // Setup the ControlParameters // setupControllers(md); // Set all the positions by controller number // for (RotaryMap::iterator it = m_rotaries.begin() ; it != m_rotaries.end(); ++it) { MidiByte value = 0; // Special cases // if (it->first == MIDI_CONTROLLER_PAN) value = int(instrument->getPan()); else if (it->first == MIDI_CONTROLLER_VOLUME) value = int(instrument->getVolume()); else { try { value = instrument->getControllerValue( MidiByte(it->first)); } catch (...) { continue; } } setRotaryToValue(it->first, int(value)); } } void MIDIInstrumentParameterPanel::setupControllers(MidiDevice *md) { if (!m_rotaryFrame) { m_rotaryFrame = new TQFrame(this); m_mainGrid->addMultiCellWidget(m_rotaryFrame, 8, 8, 0, 2, TQt::AlignHCenter); m_rotaryGrid = new TQGridLayout(m_rotaryFrame, 10, 3, 8, 1); m_rotaryGrid->addItem(new TQSpacerItem(10, 4), 0, 1); } // To cut down on flicker, we avoid destroying and recreating // widgets as far as possible here. If a label already exists, // we just set its text; if a rotary exists, we only replace it // if we actually need a different one. Composition &comp = m_doc->getComposition(); ControlList list = md->getControlParameters(); // sort by IPB position // std::sort(list.begin(), list.end(), ControlParameter::ControlPositionCmp()); int count = 0; RotaryMap::iterator rmi = m_rotaries.begin(); for (ControlList::iterator it = list.begin(); it != list.end(); ++it) { if (it->getIPBPosition() == -1) continue; // Get the knob colour - only if the colour is non-default (>0) // TQColor knobColour = TQt::black; // special case for Rotary if (it->getColourIndex() > 0) { Colour c = comp.getGeneralColourMap().getColourByIndex (it->getColourIndex()); knobColour = TQColor(c.getRed(), c.getGreen(), c.getBlue()); } Rotary *rotary = 0; if (rmi != m_rotaries.end()) { // Update the controller number that is associated with the // existing rotary widget. rmi->first = it->getControllerValue(); // Update the properties of the existing rotary widget. rotary = rmi->second.first; int redraw = 0; // 1 -> position, 2 -> all if (rotary->getMinValue() != it->getMin()) { rotary->setMinValue(it->getMin()); redraw = 1; } if (rotary->getMaxValue() != it->getMax()) { rotary->setMaxValue(it->getMax()); redraw = 1; } if (rotary->getKnobColour() != knobColour) { rotary->setKnobColour(knobColour); redraw = 2; } if (redraw == 1 || rotary->getPosition() != it->getDefault()) { rotary->setPosition(it->getDefault()); if (redraw == 1) redraw = 0; } if (redraw == 2) { rotary->repaint(); } // Update the controller name that is associated with // with the existing rotary widget. TQLabel *label = rmi->second.second; label->setText(strtoqstr(it->getName())); ++rmi; } else { TQHBox *hbox = new TQHBox(m_rotaryFrame); hbox->setSpacing(8); float smallStep = 1.0; float bigStep = 5.0; if (it->getMax() - it->getMin() < 10) bigStep = 1.0; else if (it->getMax() - it->getMin() < 20) bigStep = 2.0; rotary = new Rotary (hbox, it->getMin(), it->getMax(), smallStep, bigStep, it->getDefault(), 20, Rotary::NoTicks, false, it->getDefault() == 64); //!!! hacky rotary->setKnobColour(knobColour); // Add a label TQLabel *label = new KSqueezedTextLabel(strtoqstr(it->getName()), hbox); RG_DEBUG << "Adding new widget at " << (count / 2) << "," << (count % 2) << endl; // Add the compound widget // m_rotaryGrid->addWidget(hbox, count / 2, (count % 2) * 2, AlignLeft); hbox->show(); // Add to list // m_rotaries.push_back(std::pair (it->getControllerValue(), RotaryPair(rotary, label))); // Connect // connect(rotary, TQT_SIGNAL(valueChanged(float)), m_rotaryMapper, TQT_SLOT(map())); rmi = m_rotaries.end(); } // Add signal mapping // m_rotaryMapper->setMapping(TQT_TQOBJECT(rotary), int(it->getControllerValue())); count++; } if (rmi != m_rotaries.end()) { for (RotaryMap::iterator rmj = rmi; rmj != m_rotaries.end(); ++rmj) { delete rmj->second.first; delete rmj->second.second; } m_rotaries = std::vector > (m_rotaries.begin(), rmi); } m_rotaryFrame->show(); } void MIDIInstrumentParameterPanel::setRotaryToValue(int controller, int value) { /* RG_DEBUG << "MIDIInstrumentParameterPanel::setRotaryToValue - " << "controller = " << controller << ", value = " << value << std::endl; */ for (RotaryMap::iterator it = m_rotaries.begin() ; it != m_rotaries.end(); ++it) { if (it->first == controller) { it->second.first->setPosition(float(value)); return ; } } } void MIDIInstrumentParameterPanel::slotSelectChannel(int index) { if (m_selectedInstrument == 0) return ; m_selectedInstrument->setMidiChannel(index); // don't use the emit - use this method instead StudioControl::sendMappedInstrument( MappedInstrument(m_selectedInstrument)); emit updateAllBoxes(); } void MIDIInstrumentParameterPanel::populateBankList() { if (m_selectedInstrument == 0) return ; m_bankValue->clear(); m_banks.clear(); MidiDevice *md = dynamic_cast (m_selectedInstrument->getDevice()); if (!md) { RG_DEBUG << "WARNING: MIDIInstrumentParameterPanel::populateBankList:" << " No MidiDevice for Instrument " << m_selectedInstrument->getId() << endl; return ; } int currentBank = -1; BankList banks; /* RG_DEBUG << "MIDIInstrumentParameterPanel::populateBankList: " << "variation type is " << md->getVariationType() << endl; */ if (md->getVariationType() == MidiDevice::NoVariations) { banks = md->getBanks(m_selectedInstrument->isPercussion()); if (!banks.empty()) { if (m_bankLabel->isHidden()) { m_bankLabel->show(); m_bankCheckBox->show(); m_bankValue->show(); } } else { m_bankLabel->hide(); m_bankCheckBox->hide(); m_bankValue->hide(); } for (unsigned int i = 0; i < banks.size(); ++i) { if (m_selectedInstrument->getProgram().getBank() == banks[i]) { currentBank = i; } } } else { MidiByteList bytes; bool useMSB = (md->getVariationType() == MidiDevice::VariationFromLSB); if (useMSB) { bytes = md->getDistinctMSBs(m_selectedInstrument->isPercussion()); } else { bytes = md->getDistinctLSBs(m_selectedInstrument->isPercussion()); } if (bytes.size() < 2) { if (!m_bankLabel->isHidden()) { m_bankLabel->hide(); m_bankCheckBox->hide(); m_bankValue->hide(); } } else { if (m_bankLabel->isHidden()) { m_bankLabel->show(); m_bankCheckBox->show(); m_bankValue->show(); } } if (useMSB) { for (unsigned int i = 0; i < bytes.size(); ++i) { BankList bl = md->getBanksByMSB (m_selectedInstrument->isPercussion(), bytes[i]); RG_DEBUG << "MIDIInstrumentParameterPanel::populateBankList: have " << bl.size() << " variations for msb " << bytes[i] << endl; if (bl.size() == 0) continue; if (m_selectedInstrument->getMSB() == bytes[i]) { currentBank = banks.size(); } banks.push_back(bl[0]); } } else { for (unsigned int i = 0; i < bytes.size(); ++i) { BankList bl = md->getBanksByLSB (m_selectedInstrument->isPercussion(), bytes[i]); RG_DEBUG << "MIDIInstrumentParameterPanel::populateBankList: have " << bl.size() << " variations for lsb " << bytes[i] << endl; if (bl.size() == 0) continue; if (m_selectedInstrument->getLSB() == bytes[i]) { currentBank = banks.size(); } banks.push_back(bl[0]); } } } for (BankList::const_iterator i = banks.begin(); i != banks.end(); ++i) { m_banks.push_back(*i); m_bankValue->insertItem(strtoqstr(i->getName())); } m_bankValue->setEnabled(m_selectedInstrument->sendsBankSelect()); if (currentBank < 0 && !banks.empty()) { m_bankValue->setCurrentItem(0); slotSelectBank(0); } else { m_bankValue->setCurrentItem(currentBank); } } void MIDIInstrumentParameterPanel::populateProgramList() { if (m_selectedInstrument == 0) return ; m_programValue->clear(); m_programs.clear(); MidiDevice *md = dynamic_cast (m_selectedInstrument->getDevice()); if (!md) { RG_DEBUG << "WARNING: MIDIInstrumentParameterPanel::populateProgramList: No MidiDevice for Instrument " << m_selectedInstrument->getId() << endl; return ; } /* RG_DEBUG << "MIDIInstrumentParameterPanel::populateProgramList:" << " variation type is " << md->getVariationType() << endl; */ MidiBank bank( m_selectedInstrument->isPercussion(), m_selectedInstrument->getMSB(), m_selectedInstrument->getLSB()); if (m_selectedInstrument->sendsBankSelect()) { bank = m_selectedInstrument->getProgram().getBank(); } int currentProgram = -1; ProgramList programs = md->getPrograms(bank); if (!programs.empty()) { if (m_programLabel->isHidden()) { m_programLabel->show(); m_programCheckBox->show(); m_programValue->show(); } } else { m_programLabel->hide(); m_programCheckBox->hide(); m_programValue->hide(); } for (unsigned int i = 0; i < programs.size(); ++i) { std::string programName = programs[i].getName(); if (programName != "") { m_programValue->insertItem(TQString("%1. %2") .arg(programs[i].getProgram() + 1) .arg(strtoqstr(programName))); if (m_selectedInstrument->getProgram() == programs[i]) { currentProgram = m_programs.size(); } m_programs.push_back(programs[i]); } } m_programValue->setEnabled(m_selectedInstrument->sendsProgramChange()); if (currentProgram < 0 && !m_programs.empty()) { m_programValue->setCurrentItem(0); slotSelectProgram(0); } else { m_programValue->setCurrentItem(currentProgram); // Ensure that stored program change value is same as the one // we're now showing (BUG 937371) // if (!m_programs.empty()) { m_selectedInstrument->setProgramChange ((m_programs[m_programValue->currentItem()]).getProgram()); } } } void MIDIInstrumentParameterPanel::populateVariationList() { if (m_selectedInstrument == 0) return ; m_variationValue->clear(); m_variations.clear(); MidiDevice *md = dynamic_cast (m_selectedInstrument->getDevice()); if (!md) { RG_DEBUG << "WARNING: MIDIInstrumentParameterPanel::populateVariationList: No MidiDevice for Instrument " << m_selectedInstrument->getId() << endl; return ; } /* RG_DEBUG << "MIDIInstrumentParameterPanel::populateVariationList:" << " variation type is " << md->getVariationType() << endl; */ if (md->getVariationType() == MidiDevice::NoVariations) { if (!m_variationLabel->isHidden()) { m_variationLabel->hide(); m_variationCheckBox->hide(); m_variationValue->hide(); } return ; } bool useMSB = (md->getVariationType() == MidiDevice::VariationFromMSB); MidiByteList variations; if (useMSB) { MidiByte lsb = m_selectedInstrument->getLSB(); variations = md->getDistinctMSBs(m_selectedInstrument->isPercussion(), lsb); RG_DEBUG << "MIDIInstrumentParameterPanel::populateVariationList: have " << variations.size() << " variations for lsb " << lsb << endl; } else { MidiByte msb = m_selectedInstrument->getMSB(); variations = md->getDistinctLSBs(m_selectedInstrument->isPercussion(), msb); RG_DEBUG << "MIDIInstrumentParameterPanel::populateVariationList: have " << variations.size() << " variations for msb " << msb << endl; } m_variationValue->setCurrentItem( -1); MidiProgram defaultProgram; if (useMSB) { defaultProgram = MidiProgram (MidiBank(m_selectedInstrument->isPercussion(), 0, m_selectedInstrument->getLSB()), m_selectedInstrument->getProgramChange()); } else { defaultProgram = MidiProgram (MidiBank(m_selectedInstrument->isPercussion(), m_selectedInstrument->getMSB(), 0), m_selectedInstrument->getProgramChange()); } std::string defaultProgramName = md->getProgramName(defaultProgram); int currentVariation = -1; for (unsigned int i = 0; i < variations.size(); ++i) { MidiProgram program; if (useMSB) { program = MidiProgram (MidiBank(m_selectedInstrument->isPercussion(), variations[i], m_selectedInstrument->getLSB()), m_selectedInstrument->getProgramChange()); } else { program = MidiProgram (MidiBank(m_selectedInstrument->isPercussion(), m_selectedInstrument->getMSB(), variations[i]), m_selectedInstrument->getProgramChange()); } std::string programName = md->getProgramName(program); if (programName != "") { // yes, that is how you know whether it exists /* m_variationValue->insertItem(programName == defaultProgramName ? i18n("(default)") : strtoqstr(programName)); */ m_variationValue->insertItem(TQString("%1. %2") .arg(variations[i] + 1) .arg(strtoqstr(programName))); if (m_selectedInstrument->getProgram() == program) { currentVariation = m_variations.size(); } m_variations.push_back(variations[i]); } } if (currentVariation < 0 && !m_variations.empty()) { m_variationValue->setCurrentItem(0); slotSelectVariation(0); } else { m_variationValue->setCurrentItem(currentVariation); } if (m_variations.size() < 2) { if (!m_variationLabel->isHidden()) { m_variationLabel->hide(); m_variationCheckBox->hide(); m_variationValue->hide(); } } else { //!!! seem to have problems here -- the grid layout doesn't //like us adding stuff in the middle so if we go from 1 //visible row (say program) to 2 (program + variation) the //second one overlaps the control knobs if (m_variationLabel->isHidden()) { m_variationLabel->show(); m_variationCheckBox->show(); m_variationValue->show(); } if (m_programValue->width() > m_variationValue->width()) { m_variationValue->setMinimumWidth(m_programValue->width()); } else { m_programValue->setMinimumWidth(m_variationValue->width()); } } m_variationValue->setEnabled(m_selectedInstrument->sendsBankSelect()); } void MIDIInstrumentParameterPanel::slotTogglePercussion(bool value) { if (m_selectedInstrument == 0) { m_percussionCheckBox->setChecked(false); emit updateAllBoxes(); return ; } m_selectedInstrument->setPercussion(value); populateBankList(); populateProgramList(); populateVariationList(); sendBankAndProgram(); emit changeInstrumentLabel(m_selectedInstrument->getId(), strtoqstr(m_selectedInstrument-> getProgramName())); emit updateAllBoxes(); emit instrumentParametersChanged(m_selectedInstrument->getId()); } void MIDIInstrumentParameterPanel::slotToggleBank(bool value) { if (m_selectedInstrument == 0) { m_bankCheckBox->setChecked(false); emit updateAllBoxes(); return ; } m_variationCheckBox->setChecked(value); m_selectedInstrument->setSendBankSelect(value); m_bankValue->setDisabled(!value); populateBankList(); populateProgramList(); populateVariationList(); sendBankAndProgram(); emit changeInstrumentLabel(m_selectedInstrument->getId(), strtoqstr(m_selectedInstrument-> getProgramName())); emit updateAllBoxes(); emit instrumentParametersChanged(m_selectedInstrument->getId()); } void MIDIInstrumentParameterPanel::slotToggleProgramChange(bool value) { if (m_selectedInstrument == 0) { m_programCheckBox->setChecked(false); emit updateAllBoxes(); return ; } m_selectedInstrument->setSendProgramChange(value); m_programValue->setDisabled(!value); populateProgramList(); populateVariationList(); if (value) sendBankAndProgram(); emit changeInstrumentLabel(m_selectedInstrument->getId(), strtoqstr(m_selectedInstrument-> getProgramName())); emit updateAllBoxes(); emit instrumentParametersChanged(m_selectedInstrument->getId()); } void MIDIInstrumentParameterPanel::slotToggleVariation(bool value) { if (m_selectedInstrument == 0) { m_variationCheckBox->setChecked(false); emit updateAllBoxes(); return ; } m_bankCheckBox->setChecked(value); m_selectedInstrument->setSendBankSelect(value); m_variationValue->setDisabled(!value); populateVariationList(); sendBankAndProgram(); emit changeInstrumentLabel(m_selectedInstrument->getId(), strtoqstr(m_selectedInstrument-> getProgramName())); emit updateAllBoxes(); emit instrumentParametersChanged(m_selectedInstrument->getId()); } void MIDIInstrumentParameterPanel::slotSelectBank(int index) { if (m_selectedInstrument == 0) return ; MidiDevice *md = dynamic_cast (m_selectedInstrument->getDevice()); if (!md) { RG_DEBUG << "WARNING: MIDIInstrumentParameterPanel::slotSelectBank: No MidiDevice for Instrument " << m_selectedInstrument->getId() << endl; return ; } const MidiBank *bank = &m_banks[index]; bool change = false; if (md->getVariationType() != MidiDevice::VariationFromLSB) { if (m_selectedInstrument->getLSB() != bank->getLSB()) { m_selectedInstrument->setLSB(bank->getLSB()); change = true; } } if (md->getVariationType() != MidiDevice::VariationFromMSB) { if (m_selectedInstrument->getMSB() != bank->getMSB()) { m_selectedInstrument->setMSB(bank->getMSB()); change = true; } } populateProgramList(); if (change) { sendBankAndProgram(); emit updateAllBoxes(); } emit instrumentParametersChanged(m_selectedInstrument->getId()); } void MIDIInstrumentParameterPanel::slotSelectProgram(int index) { const MidiProgram *prg = &m_programs[index]; if (prg == 0) { RG_DEBUG << "program change not found in bank" << endl; return ; } bool change = false; if (m_selectedInstrument->getProgramChange() != prg->getProgram()) { m_selectedInstrument->setProgramChange(prg->getProgram()); change = true; } populateVariationList(); if (change) { sendBankAndProgram(); emit changeInstrumentLabel(m_selectedInstrument->getId(), strtoqstr(m_selectedInstrument-> getProgramName())); emit updateAllBoxes(); } emit instrumentParametersChanged(m_selectedInstrument->getId()); } void MIDIInstrumentParameterPanel::slotSelectVariation(int index) { MidiDevice *md = dynamic_cast (m_selectedInstrument->getDevice()); if (!md) { RG_DEBUG << "WARNING: MIDIInstrumentParameterPanel::slotSelectVariation: No MidiDevice for Instrument " << m_selectedInstrument->getId() << endl; return ; } if (index < 0 || index > int(m_variations.size())) { RG_DEBUG << "WARNING: MIDIInstrumentParameterPanel::slotSelectVariation: index " << index << " out of range" << endl; return ; } MidiByte v = m_variations[index]; bool change = false; if (md->getVariationType() == MidiDevice::VariationFromLSB) { if (m_selectedInstrument->getLSB() != v) { m_selectedInstrument->setLSB(v); change = true; } } else if (md->getVariationType() == MidiDevice::VariationFromMSB) { if (m_selectedInstrument->getMSB() != v) { m_selectedInstrument->setMSB(v); change = true; } } if (change) { sendBankAndProgram(); } emit instrumentParametersChanged(m_selectedInstrument->getId()); } void MIDIInstrumentParameterPanel::sendBankAndProgram() { if (m_selectedInstrument == 0) return ; MidiDevice *md = dynamic_cast (m_selectedInstrument->getDevice()); if (!md) { RG_DEBUG << "WARNING: MIDIInstrumentParameterPanel::sendBankAndProgram: No MidiDevice for Instrument " << m_selectedInstrument->getId() << endl; return ; } if (m_selectedInstrument->sendsBankSelect()) { // Send the bank select message before any PC message // MappedEvent mEMSB(m_selectedInstrument->getId(), MappedEvent::MidiController, MIDI_CONTROLLER_BANK_MSB, m_selectedInstrument->getMSB()); RG_DEBUG << "MIDIInstrumentParameterPanel::sendBankAndProgram - " << "sending MSB = " << int(m_selectedInstrument->getMSB()) << endl; StudioControl::sendMappedEvent(mEMSB); MappedEvent mELSB(m_selectedInstrument->getId(), MappedEvent::MidiController, MIDI_CONTROLLER_BANK_LSB, m_selectedInstrument->getLSB()); RG_DEBUG << "MIDIInstrumentParameterPanel::sendBankAndProgram - " << "sending LSB = " << int(m_selectedInstrument->getLSB()) << endl; StudioControl::sendMappedEvent(mELSB); } MappedEvent mE(m_selectedInstrument->getId(), MappedEvent::MidiProgramChange, m_selectedInstrument->getProgramChange(), (MidiByte)0); RG_DEBUG << "MIDIInstrumentParameterPanel::sendBankAndProgram - " << "sending program change = " << int(m_selectedInstrument->getProgramChange()) << endl; // Send the controller change // StudioControl::sendMappedEvent(mE); } void MIDIInstrumentParameterPanel::slotControllerChanged(int controllerNumber) { RG_DEBUG << "MIDIInstrumentParameterPanel::slotControllerChanged - " << "controller = " << controllerNumber << "\n"; if (m_selectedInstrument == 0) return ; MidiDevice *md = dynamic_cast (m_selectedInstrument->getDevice()); if (!md) return ; /* ControlParameter *controller = md->getControlParameter(MidiByte(controllerNumber)); */ int value = getValueFromRotary(controllerNumber); if (value == -1) { RG_DEBUG << "MIDIInstrumentParameterPanel::slotControllerChanged - " << "couldn't get value of rotary for controller " << controllerNumber << endl; return ; } // two special cases if (controllerNumber == int(MIDI_CONTROLLER_PAN)) { float adjValue = value; if (m_selectedInstrument->getType() == Instrument::Audio || m_selectedInstrument->getType() == Instrument::SoftSynth) value += 100; m_selectedInstrument->setPan(MidiByte(adjValue)); } else if (controllerNumber == int(MIDI_CONTROLLER_VOLUME)) { m_selectedInstrument->setVolume(MidiByte(value)); } else // just set the controller (this will create it on the instrument if // it doesn't exist) { m_selectedInstrument->setControllerValue(MidiByte(controllerNumber), MidiByte(value)); RG_DEBUG << "SET CONTROLLER VALUE (" << controllerNumber << ") = " << value << endl; } /* else { RG_DEBUG << "MIDIInstrumentParameterPanel::slotControllerChanged - " << "no controller retrieved\n"; return; } */ MappedEvent mE(m_selectedInstrument->getId(), MappedEvent::MidiController, (MidiByte)controllerNumber, (MidiByte)value); StudioControl::sendMappedEvent(mE); emit updateAllBoxes(); emit instrumentParametersChanged(m_selectedInstrument->getId()); } int MIDIInstrumentParameterPanel::getValueFromRotary(int rotary) { for (RotaryMap::iterator it = m_rotaries.begin(); it != m_rotaries.end(); ++it) { if (it->first == rotary) return int(it->second.first->getPosition()); } return -1; } void MIDIInstrumentParameterPanel::showAdditionalControls(bool showThem) { m_instrumentLabel->setShown(showThem); int index = 0; for (RotaryMap::iterator it = m_rotaries.begin(); it != m_rotaries.end(); ++it) { it->second.first->parentWidget()->setShown(showThem || (index < 8)); //it->second.first->setShown(showThem || (index < 8)); //it->second.second->setShown(showThem || (index < 8)); index++; } } } #include "MIDIInstrumentParameterPanel.moc"