void ModifyDeviceCommand::unexecute() { Device *device = m_studio->getDevice(m_device); if (!device) { std::cerr << "ERROR: ModifyDeviceCommand::unexecute(): no such device as " << m_device << std::endl; return; } MidiDevice *midiDevice = dynamic_cast<MidiDevice *>(device); if (!midiDevice) { std::cerr << "ERROR: ModifyDeviceCommand::unexecute(): device " << m_device << " is not a MIDI device" << std::endl; return; } if (m_rename) midiDevice->setName(m_oldName); midiDevice->replaceBankList(m_oldBankList); midiDevice->replaceProgramList(m_oldProgramList); midiDevice->replaceControlParameters(m_oldControlList); midiDevice->replaceKeyMappingList(m_oldKeyMappingList); midiDevice->setLibrarian(m_oldLibrarianName, m_oldLibrarianEmail); if (m_changeVariation) midiDevice->setVariationType(m_oldVariationType); InstrumentList instruments = midiDevice->getAllInstruments(); for (size_t i = 0; i < instruments.size(); ++i) { instruments[i]->setProgram(m_oldInstrumentPrograms[i]); } // ??? 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(); }
bool ImportDeviceDialog::importFromSF2(QString filename) { SF2PatchExtractor::Device sf2device; try { sf2device = SF2PatchExtractor::read( qstrtostr(filename) ); // These exceptions shouldn't happen -- the isSF2File call before this // one should have weeded them out } catch (SF2PatchExtractor::FileNotFoundException e) { return false; } catch (SF2PatchExtractor::WrongFileFormatException e) { return false; } std::vector<MidiBank> banks; std::vector<MidiProgram> programs; for (SF2PatchExtractor::Device::const_iterator i = sf2device.begin(); i != sf2device.end(); ++i) { int bankNumber = i->first; const SF2PatchExtractor::Bank &sf2bank = i->second; int msb = bankNumber / 128; int lsb = bankNumber % 128; MidiBank bank (msb == 1, msb, lsb, qstrtostr(tr("Bank %1:%2").arg(msb).arg(lsb))); banks.push_back(bank); for (SF2PatchExtractor::Bank::const_iterator j = sf2bank.begin(); j != sf2bank.end(); ++j) { MidiProgram program(bank, j->first, j->second); programs.push_back(program); } } // This is a temporary device, so we can use device and instrument // IDs that other devices in the Studio may also be using without // expecting any problems MidiDevice *device = new MidiDevice (0, MidiInstrumentBase, "", MidiDevice::Play); device->replaceBankList(banks); device->replaceProgramList(programs); m_devices.push_back(device); return true; }
bool ImportDeviceDialog::importFromLSCP(QString filename) { LSCPPatchExtractor::Device lscpDevice; lscpDevice = LSCPPatchExtractor::extractContent(filename); std::vector<MidiBank> banks; std::vector<MidiProgram> programs; int comparableBankNumber = -1; //Make sure that first bank is read too by comparing to -1 first (invalid bank number) for (LSCPPatchExtractor::Device::const_iterator i = lscpDevice.begin(); i != lscpDevice.end(); ++i) { int bankNumber = (*i).bankNumber; //Local variable bankNumber gets value from struct's member bankNumber std::string bankName = (*i).bankName; //Local variable bankName gets value from struct's member bankName int msb = bankNumber / 128; int lsb = bankNumber % 128; MidiBank bank (msb == 1, msb, lsb, bankName); if (comparableBankNumber != bankNumber) { banks.push_back(bank); comparableBankNumber = bankNumber; } MidiProgram program(bank, (*i).programNumber, (*i).programName); programs.push_back(program); } // This is a temporary device, so we can use device and instrument // IDs that other devices in the Studio may also be using without // expecting any problems MidiDevice *device = new MidiDevice (0, MidiInstrumentBase, "", MidiDevice::Play); device->replaceBankList(banks); device->replaceProgramList(programs); m_devices.push_back(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(); }