bool ImportDeviceDialog::importFromRG(QString fileName) { bool skipAutoload = true, clearCommandHistory = false; RosegardenDocument fileDoc(RosegardenMainWindow::self(), 0, skipAutoload, clearCommandHistory); if (!fileDoc.openDocument(fileName, false)) { return false; } for (int i = 0; i < (int)m_devices.size(); ++i) delete m_devices[i]; m_devices.clear(); DeviceList *list = fileDoc.getStudio().getDevices(); if (list->size() == 0) { return true; // true because we successfully read the document } for (DeviceListIterator it = list->begin(); it != list->end(); ++it) { MidiDevice *device = dynamic_cast<MidiDevice*>(*it); if (device) { std::vector<MidiBank> banks = device->getBanks(); // DMM - check for controllers too, because some users have // created .rgd files that contain only controllers // see bug #1183522 // std::vector<ControlParameter> controllers = device->getControlParameters(); // We've got a bank on a Device fom this file // (or a device that contains controllers or key mappings) // if (banks.size() || controllers.size() || device->getKeyMappings().size()) { m_devices.push_back(new MidiDevice(*device)); } } } return true; }
void ModifyDeviceCommand::execute() { Device *device = m_studio->getDevice(m_device); if (!device) { std::cerr << "ERROR: ModifyDeviceCommand::execute(): no such device as " << m_device << std::endl; return; } MidiDevice *midiDevice = dynamic_cast<MidiDevice *>(device); if (!midiDevice) { std::cerr << "ERROR: ModifyDeviceCommand::execute(): device " << m_device << " is not a MIDI device" << std::endl; return; } // Save Original Values for Undo // ??? Really wish we could just m_oldDevice = *(midiDevice). See below. m_oldName = midiDevice->getName(); m_oldBankList = midiDevice->getBanks(); m_oldProgramList = midiDevice->getPrograms(); m_oldControlList = midiDevice->getControlParameters(); m_oldKeyMappingList = midiDevice->getKeyMappings(); m_oldLibrarianName = midiDevice->getLibrarianName(); m_oldLibrarianEmail = midiDevice->getLibrarianEmail(); m_oldVariationType = midiDevice->getVariationType(); InstrumentList instruments = midiDevice->getAllInstruments(); for (size_t i = 0; i < instruments.size(); ++i) { // ??? Preserving just the programs isn't enough. We need // to preserve the rest of the Instrument as well. However, // the auto/fixed channel feature has made it impossible // to safely make copies of Instrument objects. Also, Instrument // has an ID. How should that be handled for undo? ISTM // that we either need to introduce some sort of copyForUndo() // hack to each object, or develop a set of standards for coding // objects that are undo-safe. Sounds like a pretty big project. m_oldInstrumentPrograms.push_back(instruments[i]->getProgram()); } // Make the Changes if (m_changeVariation) midiDevice->setVariationType(m_variationType); if (m_overwrite) { if (m_clearBankAndProgramList) { midiDevice->clearBankList(); midiDevice->clearProgramList(); midiDevice->clearKeyMappingList(); } else { if (m_changeBanks) midiDevice->replaceBankList(m_bankList); if (m_changePrograms) midiDevice->replaceProgramList(m_programList); if (m_changeBanks || m_changePrograms) { // Make sure the instruments make sense. for (size_t i = 0; i < instruments.size(); ++i) { instruments[i]->pickFirstProgram( midiDevice->isPercussionNumber(i)); } } } if (m_changeKeyMappings) { midiDevice->replaceKeyMappingList(m_keyMappingList); } if (m_rename) midiDevice->setName(m_name); midiDevice->setLibrarian(m_librarianName, m_librarianEmail); } else { if (m_clearBankAndProgramList) { midiDevice->clearBankList(); midiDevice->clearProgramList(); } else { if (m_changeBanks) midiDevice->mergeBankList(m_bankList); if (m_changePrograms) midiDevice->mergeProgramList(m_programList); } if (m_changeKeyMappings) { midiDevice->mergeKeyMappingList(m_keyMappingList); } if (m_rename) { std::string mergeName = midiDevice->getName() + std::string("/") + m_name; midiDevice->setName(mergeName); } } //!!! merge option? if (m_changeControls) { midiDevice->replaceControlParameters(m_controlList); } // ??? Instead of this kludge, we should be calling a Studio::hasChanged() // which would then notify all observers (e.g. MIPP) who, in turn, // would update themselves. RosegardenMainWindow::self()->uiUpdateKludge(); }
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); }