void MIDIInstrumentParameterPanel::updateVariationComboBox() { RG_DEBUG << "updateVariationComboBox() begin..."; if (!getSelectedInstrument()) return; MidiDevice *md = dynamic_cast<MidiDevice *>(getSelectedInstrument()->getDevice()); if (!md) { std::cerr << "WARNING: MIDIInstrumentParameterPanel::updateVariationComboBox(): No MidiDevice for Instrument " << getSelectedInstrument()->getId() << '\n'; return; } RG_DEBUG << "updateVariationComboBox(): Variation type is " << md->getVariationType(); if (md->getVariationType() == MidiDevice::NoVariations) { showVariation(false); return; } // Get the variations. bool useMSB = (md->getVariationType() == MidiDevice::VariationFromMSB); MidiByteList variationBanks; if (useMSB) { MidiByte lsb = getSelectedInstrument()->getLSB(); variationBanks = md->getDistinctMSBs(getSelectedInstrument()->isPercussion(), lsb); RG_DEBUG << "updateVariationComboBox(): Have " << variationBanks.size() << " variations for LSB " << lsb; } else { MidiByte msb = getSelectedInstrument()->getMSB(); variationBanks = md->getDistinctLSBs(getSelectedInstrument()->isPercussion(), msb); RG_DEBUG << "updateVariationComboBox(): Have " << variationBanks.size() << " variations for MSB " << msb; } // Convert variationBanks to a ProgramList. ProgramList variations; // For each variation for (size_t i = 0; i < variationBanks.size(); ++i) { // Assemble the program for the variation. MidiBank bank; if (useMSB) { bank = MidiBank(getSelectedInstrument()->isPercussion(), variationBanks[i], getSelectedInstrument()->getLSB()); } else { bank = MidiBank(getSelectedInstrument()->isPercussion(), getSelectedInstrument()->getMSB(), variationBanks[i]); } MidiProgram program(bank, getSelectedInstrument()->getProgramChange()); // Skip any programs without names. if (md->getProgramName(program) == "") continue; variations.push_back(program); } // Compute the current variation. // ??? This might be combined into the previous for loop. int currentVariation = -1; // For each variation for (size_t i = 0; i < variations.size(); ++i) { if (getSelectedInstrument()->getProgram().partialCompare(variations[i])) { currentVariation = i; break; } } // If the variations have changed, repopulate the combobox. if (!partialCompareWithName(variations, m_variations)) { RG_DEBUG << "updateVariationComboBox(): Repopulating the combobox"; // Update the cache. m_variations = variations; // Copy from m_variations to m_variationComboBox. m_variationComboBox->clear(); for (size_t i = 0; i < m_variations.size(); ++i) { std::string programName = md->getProgramName(m_variations[i]); // Pick the correct bank number. MidiBank bank = m_variations[i].getBank(); MidiByte variationBank = useMSB ? bank.getMSB() : bank.getLSB(); m_variationComboBox->addItem(QObject::tr("%1. %2") .arg(variationBank) .arg(QObject::tr(programName.c_str()))); } } // Display the current variation. m_variationComboBox->setCurrentIndex(currentVariation); // Show the variation widgets in either of two cases: // 1. More than one variation is available for this program. // 2. The variation was not in the Device and there is a variation // to choose from. showVariation(m_variations.size() > 1 || (currentVariation == -1 && !m_variations.empty())); m_variationComboBox->setEnabled(getSelectedInstrument()->sendsBankSelect()); }
void MIDIInstrumentParameterPanel::updateBankComboBox() { RG_DEBUG << "updateBankComboBox()"; if (!getSelectedInstrument()) return; MidiDevice *md = dynamic_cast<MidiDevice *>(getSelectedInstrument()->getDevice()); if (!md) { std::cerr << "WARNING: MIDIInstrumentParameterPanel::updateBankComboBox(): No MidiDevice for Instrument " << getSelectedInstrument()->getId() << '\n'; return; } int currentBank = -1; BankList banks; RG_DEBUG << "updateBankComboBox(): Variation type is " << md->getVariationType(); if (md->getVariationType() == MidiDevice::NoVariations) { banks = md->getBanks(getSelectedInstrument()->isPercussion()); // If there are banks to display, show the bank widgets. // Why not showBank(banks.size()>1)? Because that would hide the // bank checkbox which would take away the user's ability to // enable/disable bank selects. If we do away with the checkbox // in the future, we should re-evaluate this decision. showBank(!banks.empty()); // Find the selected bank in the MIDI Device's bank list. for (unsigned int i = 0; i < banks.size(); ++i) { if (getSelectedInstrument()->getProgram().getBank().partialCompare(banks[i])) { currentBank = i; break; } } } else { // Usually in variation mode, the bank widgets will be hidden. // E.g. in GM2, the MSB for all banks is 121 with the variations // in the LSB numbered 0-9. If, however, there were another // MSB, say 122, with some variations in the LSB, this code would // display the Bank combobox to allow selection of the MSB. // If the variations are in the LSB, then the banks are in the MSB // and vice versa. bool useMSB = (md->getVariationType() == MidiDevice::VariationFromLSB); MidiByteList bytes; if (useMSB) { bytes = md->getDistinctMSBs(getSelectedInstrument()->isPercussion()); } else { bytes = md->getDistinctLSBs(getSelectedInstrument()->isPercussion()); } // If more than one bank value is found, show the bank widgets. showBank(bytes.size() > 1); // Load "banks" with the banks and figure out currentBank. if (useMSB) { for (unsigned int i = 0; i < bytes.size(); ++i) { BankList bl = md->getBanksByMSB (getSelectedInstrument()->isPercussion(), bytes[i]); RG_DEBUG << "updateBankComboBox(): Have " << bl.size() << " variations for MSB " << bytes[i]; if (bl.size() == 0) continue; if (getSelectedInstrument()->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 (getSelectedInstrument()->isPercussion(), bytes[i]); RG_DEBUG << "updateBankComboBox(): Have " << bl.size() << " variations for LSB " << bytes[i]; if (bl.size() == 0) continue; if (getSelectedInstrument()->getLSB() == bytes[i]) { currentBank = banks.size(); } banks.push_back(bl[0]); } } } // Populate the combobox with bank names. // If we need to repopulate m_bankComboBox if (banks != m_banks) { // Update the cache. m_banks = banks; // Copy from m_banks to m_bankComboBox. m_bankComboBox->clear(); for (BankList::const_iterator i = m_banks.begin(); i != m_banks.end(); ++i) { m_bankComboBox->addItem(QObject::tr(i->getName().c_str())); } } m_bankComboBox->setEnabled(getSelectedInstrument()->sendsBankSelect()); #if 0 // ??? This is a pretty nifty idea, but unfortunately, it requires // that we maintain a bogus combobox entry. For now, we'll go // with the simpler "unselected" approach. // If the current bank was not found... if (currentBank < 0 && !banks.empty()) { // Format bank MSB:LSB and add to combobox. MidiBank bank = getSelectedInstrument()->getProgram().getBank(); QString bankString = QString("%1:%2").arg(bank.getMSB()).arg(bank.getLSB()); m_bankComboBox.addItem(bankString); currentBank = banks.size(); } #endif // If the bank wasn't in the Device, show the bank widgets so // the user can fix it if they want. if (currentBank == -1 && !banks.empty()) showBank(true); // Display the current bank. m_bankComboBox->setCurrentIndex(currentBank); }