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(); }
MidiDevice::MidiDevice(const MidiDevice &dev) : Device(dev.getId(), dev.getName(), dev.getType()), Controllable(), m_programList(dev.m_programList), m_bankList(dev.m_bankList), m_controlList(dev.m_controlList), m_keyMappingList(dev.m_keyMappingList), m_metronome(0), m_direction(dev.getDirection()), m_variationType(dev.getVariationType()), m_librarian(dev.getLibrarian()), m_allocator(new AllocateChannels(ChannelSetup::MIDI)) { // Create and assign a metronome if required // if (dev.getMetronome()) { m_metronome = new MidiMetronome(*dev.getMetronome()); } // Copy the instruments // InstrumentList insList = dev.getAllInstruments(); InstrumentList::iterator iIt = insList.begin(); for (; iIt != insList.end(); ++iIt) { Instrument *newInst = new Instrument(**iIt); newInst->setDevice(this); m_instruments.push_back(newInst); } // generate presentation instruments generatePresentationList(); }
void MidiMixerWindow::sendControllerRefresh() { //!!! need to know if we have a current external controller device, // as this is expensive int tabIndex = m_tabWidget->currentIndex(); RG_DEBUG << "MidiMixerWindow::slotCurrentTabChanged: current is " << tabIndex << endl; if (tabIndex < 0) return ; int i = 0; for (DeviceList::const_iterator dit = m_studio->begin(); dit != m_studio->end(); ++dit) { MidiDevice *dev = dynamic_cast<MidiDevice*>(*dit); RG_DEBUG << "device is " << (*dit)->getId() << ", dev " << dev << endl; if (!dev) continue; if (i != tabIndex) { ++i; continue; } InstrumentList instruments = dev->getPresentationInstruments(); ControlList controls = getIPBForMidiMixer(dev); RG_DEBUG << "device has " << instruments.size() << " presentation instruments, " << dev->getAllInstruments().size() << " instruments " << endl; for (InstrumentList::const_iterator iIt = instruments.begin(); iIt != instruments.end(); ++iIt) { Instrument *instrument = *iIt; if (!instrument->hasFixedChannel()) { continue; } int channel = instrument->getNaturalChannel(); RG_DEBUG << "instrument is " << instrument->getId() << endl; for (ControlList::const_iterator cIt = controls.begin(); cIt != controls.end(); ++cIt) { int controller = (*cIt).getControllerValue(); int value; try { value = instrument->getControllerValue(controller); } catch (std::string s) { std::cerr << "Exception in MidiMixerWindow::currentChanged: " << s << " (controller " << controller << ", instrument " << instrument->getId() << ")" << std::endl; value = 0; } MappedEvent mE(instrument->getId(), MappedEvent::MidiController, controller, value); mE.setRecordedChannel(channel); mE.setRecordedDevice(Device::CONTROL_DEVICE); StudioControl::sendMappedEvent(mE); } MappedEvent mE(instrument->getId(), MappedEvent::MidiController, MIDI_CONTROLLER_VOLUME, instrument->getVolume()); mE.setRecordedChannel(channel); mE.setRecordedDevice(Device::CONTROL_DEVICE); RG_DEBUG << "sending controller mapped event for channel " << channel << ", volume " << instrument->getVolume() << endl; StudioControl::sendMappedEvent(mE); } break; } }
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(); }