void ControlEditorDialog::slotEdit(QTreeWidgetItem *i, int) { RG_DEBUG << "ControlEditorDialog::slotEdit" << endl; ControlParameterItem *item = dynamic_cast<ControlParameterItem*>(i); MidiDevice *md = dynamic_cast<MidiDevice *>(m_studio->getDevice(m_device)); if (item && md) { ControlParameterEditDialog dialog (this, md->getControlParameter(item->getId()), m_doc); if (dialog.exec() == QDialog::Accepted) { ModifyControlParameterCommand *command = new ModifyControlParameterCommand(m_studio, m_device, dialog.getControl(), item->getId()); addCommandToHistory(command); } } }
// Run through the Devices checking for MidiDevices and // returning the first Metronome we come across // const MidiMetronome* Studio::getMetronomeFromDevice(DeviceId id) { std::vector<Device*>::iterator it; for (it = m_devices.begin(); it != m_devices.end(); ++it) { std::cerr << "Studio::getMetronomeFromDevice: Having a look at device " << (*it)->getId() << std::endl; MidiDevice *midiDevice = dynamic_cast<MidiDevice*>(*it); if (midiDevice && midiDevice->getId() == id && midiDevice->getMetronome()) { std::cerr << "Studio::getMetronomeFromDevice(" << id << "): device is a MIDI device" << std::endl; return midiDevice->getMetronome(); } SoftSynthDevice *ssDevice = dynamic_cast<SoftSynthDevice *>(*it); if (ssDevice && ssDevice->getId() == id && ssDevice->getMetronome()) { std::cerr << "Studio::getMetronomeFromDevice(" << id << "): device is a soft synth device" << std::endl; return ssDevice->getMetronome(); } } return 0; }
std::string Studio::getSegmentName(InstrumentId id) { MidiDevice *midiDevice; std::vector<Device*>::iterator it; Rosegarden::InstrumentList::iterator iit; Rosegarden::InstrumentList instList; for (it = m_devices.begin(); it != m_devices.end(); ++it) { midiDevice = dynamic_cast<MidiDevice*>(*it); if (midiDevice) { instList = (*it)->getAllInstruments(); for (iit = instList.begin(); iit != instList.end(); ++iit) { if ((*iit)->getId() == id) { if ((*iit)->sendsProgramChange()) { return (*iit)->getProgramName(); } else { return midiDevice->getName() + " " + (*iit)->getName(); } } } } } return std::string(""); }
// From a user selection (from a "Presentation" list) return // the matching Instrument // Instrument* Studio::getInstrumentFromList(int index) { std::vector<Device*>::iterator it; InstrumentList list; InstrumentList::iterator iit; int count = 0; for (it = m_devices.begin(); it != m_devices.end(); ++it) { MidiDevice *midiDevice = dynamic_cast<MidiDevice*>(*it); if (midiDevice) { // skip read-only devices if (midiDevice->getDirection() == MidiDevice::Record) continue; } list = (*it)->getPresentationInstruments(); for (iit = list.begin(); iit != list.end(); ++iit) { if (count == index) return (*iit); count++; } } return 0; }
void MIDIInstrumentParameterPanel::slotSelectProgram(int index) { RG_DEBUG << "slotSelectProgram()"; if (!getSelectedInstrument()) return; MidiDevice *md = dynamic_cast<MidiDevice *>(getSelectedInstrument()->getDevice()); if (!md) return; const MidiProgram *prg = &m_programs[index]; // If there has been no change, bail. if (getSelectedInstrument()->getProgramChange() == prg->getProgram()) return; getSelectedInstrument()->setProgramChange(prg->getProgram()); // In Variations mode, select the 0th variation. // In Variations mode, it's very easy to select an "invalid" // program change. I.e. one for which the bank is not valid. Go // from one program/variation to a program that doesn't have that // variation. We need to handle that here by selecting the 0th // variation. That's what the user expects. if (md->getVariationType() == MidiDevice::VariationFromMSB) { MidiBank bank = getSelectedInstrument()->getProgram().getBank(); // Get the list of MSB variations. BankList bankList = md->getBanksByLSB( getSelectedInstrument()->isPercussion(), bank.getLSB()); if (!bankList.empty()) { // Pick the first MSB variation getSelectedInstrument()->setMSB(bankList.front().getMSB()); } } if (md->getVariationType() == MidiDevice::VariationFromLSB) { MidiBank bank = getSelectedInstrument()->getProgram().getBank(); // Get the list of LSB variations. BankList bankList = md->getBanksByMSB( getSelectedInstrument()->isPercussion(), bank.getMSB()); if (!bankList.empty()) { // Pick the first LSB variation getSelectedInstrument()->setLSB(bankList.front().getLSB()); } } getSelectedInstrument()->sendChannelSetup(); // Just one change notification for the two potential changes. // See comments in slotSelectBank() for further discussion. getSelectedInstrument()->changed(); }
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(); }
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; }
const MidiMetronome * ManageMetronomeDialog::getMetronome(Device *dev) { MidiDevice *md = dynamic_cast<MidiDevice *>(dev); if (md) { return md->getMetronome(); } SoftSynthDevice *ssd = dynamic_cast<SoftSynthDevice *>(dev); if (ssd) { return ssd->getMetronome(); } return 0; }
void ManageMetronomeDialog::setMetronome(Device *dev, const MidiMetronome &metronome) { MidiDevice *md = dynamic_cast<MidiDevice *>(dev); if (md) { md->setMetronome(metronome); return; } SoftSynthDevice *ssd = dynamic_cast<SoftSynthDevice *>(dev); if (ssd) { ssd->setMetronome(metronome); return; } }
void AddControlParameterCommand::unexecute() { MidiDevice *md = dynamic_cast<MidiDevice *> (m_studio->getDevice(m_device)); if (!md) { std::cerr << "WARNING: AddControlParameterCommand::unexecute: device " << m_device << " is not a MidiDevice in current studio" << std::endl; return ; } md->removeControlParameter(m_id); }
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 ModifyControlParameterCommand::execute() { MidiDevice *md = dynamic_cast<MidiDevice *> (m_studio->getDevice(m_device)); if (!md) { std::cerr << "WARNING: ModifyControlParameterCommand::execute: device " << m_device << " is not a MidiDevice in current studio" << std::endl; return ; } ControlParameter *param = md->getControlParameter(m_id); if (param) m_originalControl = *param; md->modifyControlParameter(m_control, m_id); }
void Studio::clearMidiBanksAndPrograms() { MidiDevice *midiDevice; std::vector<Device*>::iterator it; for (it = m_devices.begin(); it != m_devices.end(); ++it) { midiDevice = dynamic_cast<MidiDevice*>(*it); if (midiDevice) { midiDevice->clearProgramList(); midiDevice->clearBankList(); } } }
void AddControlParameterCommand::execute() { MidiDevice *md = dynamic_cast<MidiDevice *> (m_studio->getDevice(m_device)); if (!md) { std::cerr << "WARNING: AddControlParameterCommand::execute: device " << m_device << " is not a MidiDevice in current studio" << std::endl; return ; } md->addControlParameter(m_control, true); // store id of the new control m_id = int(md->getControlParameters().size()) - 1; }
bool ManageMetronomeDialog::isSuitable(Device *dev, bool *hasConnectionReturn) { MidiDevice *md = dynamic_cast<MidiDevice *>(dev); if (md && md->getDirection() == MidiDevice::Play) { if (hasConnectionReturn) { QString conn = RosegardenSequencer::getInstance()->getConnection (md->getId()); if (conn == "") *hasConnectionReturn = false; else *hasConnectionReturn = true; } return true; } if (dynamic_cast<SoftSynthDevice *>(dev)) { if (hasConnectionReturn) *hasConnectionReturn = true; return true; } return false; }
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; }
MidiDevice::MidiDevice(DeviceId id, InstrumentId ibase, const MidiDevice &dev) : Device(id, dev.getName(), Device::Midi), m_programList(dev.m_programList), m_bankList(dev.m_bankList), m_controlList(0), 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)) { createInstruments(ibase); // Populate device and Instrument with Controllers. ControlList::const_iterator cIt = dev.m_controlList.begin(); for(; cIt != dev.m_controlList.end(); ++cIt) { addControlParameter(*cIt, true); } // Create and assign a metronome if required // if (dev.getMetronome()) { m_metronome = new MidiMetronome(*dev.getMetronome()); } generatePresentationList(); }
CreateOrDeleteDeviceCommand::CreateOrDeleteDeviceCommand(Studio *studio, DeviceId id) : NamedCommand(getGlobalName(true)), m_studio(studio), m_deviceId(id), m_deviceCreated(true) { Device *device = m_studio->getDevice(m_deviceId); if (device) { m_name = device->getName(); m_type = device->getType(); m_direction = MidiDevice::Play; MidiDevice *md = dynamic_cast<MidiDevice *>(device); if (md) m_direction = md->getDirection(); m_connection = qstrtostr(RosegardenSequencer::getInstance() ->getConnection(md->getId())); } else { RG_DEBUG << "CreateOrDeleteDeviceCommand: No such device as " << m_deviceId << endl; } }
QWidget* MenuList::createWidget(QWidget* parent) { if(!_track) return 0; //if(!_track->isMidiTrack() || _track->type() != Track::AUDIO_SOFTSYNTH) // return 0; MidiTrack* track = (MidiTrack*) _track; MidiDevice* md = 0; int port = -1; if (track->type() == Track::AUDIO_SOFTSYNTH) { md = dynamic_cast<MidiDevice*> (track); if (md) port = md->midiPort(); } else port = track->outPort(); list = new QListWidget(parent); list->setSelectionMode(QAbstractItemView::SingleSelection); list->setAlternatingRowColors(true); list->setEditTriggers(QAbstractItemView::NoEditTriggers); list->setFixedHeight(300); for (int i = 0; i < MIDI_PORTS; ++i) { QString name; name.sprintf("%d:%s", i + 1, midiPorts[i].portname().toLatin1().constData()); list->insertItem(i, name); if (i == port) list->setCurrentRow(i); } connect(list, SIGNAL(itemPressed(QListWidgetItem*)), this, SLOT(updateData(QListWidgetItem*))); //connect(list, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(updateData(QListWidgetItem*))); //connect(list, SIGNAL(itemActivated(QListWidgetItem*)), this, SLOT(updateData(QListWidgetItem*))); return list; }
void MidiSeq::updatePollFd() { if (!isRunning()) return; clearPollFd(); addPollFd(timerFd, POLLIN, midiTick, this, 0); if (timerFd == -1) { fprintf(stderr, "updatePollFd: no timer fd\n"); if (!MusEGlobal::debugMode) exit(-1); } addPollFd(toThreadFdr, POLLIN, MusECore::readMsg, this, 0); //--------------------------------------------------- // midi ports //--------------------------------------------------- for (iMidiDevice imd = MusEGlobal::midiDevices.begin(); imd != MusEGlobal::midiDevices.end(); ++imd) { MidiDevice* dev = *imd; int port = dev->midiPort(); if (port == -1) continue; if ((dev->rwFlags() & 0x2) || (MusEGlobal::extSyncFlag.value() && (MusEGlobal::midiPorts[port].syncInfo().MCIn()))) addPollFd(dev->selectRfd(), POLLIN, MusECore::midiRead, this, dev); if (dev->bytesToWrite()) addPollFd(dev->selectWfd(), POLLOUT, MusECore::midiWrite, this, dev); } // special handling for alsa midi: // (one fd for all devices) // this allows for processing of some alsa events // even if no alsa driver is active (assigned to a port) addPollFd(alsaSelectRfd(), POLLIN, MusECore::alsaMidiRead, this, 0); }
void MidiMixerWindow::slotUpdateInstrument(InstrumentId id) { //RG_DEBUG << "MidiMixerWindow::slotUpdateInstrument - id = " << id << endl; DeviceListConstIterator it; MidiDevice *dev = 0; InstrumentList instruments; InstrumentList::const_iterator iIt; int count = 0; blockSignals(true); for (it = m_studio->begin(); it != m_studio->end(); ++it) { dev = dynamic_cast<MidiDevice*>(*it); if (dev) { instruments = dev->getPresentationInstruments(); ControlList controls = getIPBForMidiMixer(dev); for (iIt = instruments.begin(); iIt != instruments.end(); ++iIt) { // Match and set // if ((*iIt)->getId() == id) { // Set Volume fader // m_faders[count]->m_volumeFader->blockSignals(true); MidiByte volumeValue; try { volumeValue = (*iIt)-> getControllerValue(MIDI_CONTROLLER_VOLUME); } catch (std::string s) { // This should never get called. volumeValue = (*iIt)->getVolume(); } m_faders[count]->m_volumeFader->setFader(float(volumeValue)); m_faders[count]->m_volumeFader->blockSignals(false); /* StaticControllers &staticControls = (*iIt)->getStaticControllers(); RG_DEBUG << "STATIC CONTROLS SIZE = " << staticControls.size() << endl; */ // Set all controllers for this Instrument // for (size_t i = 0; i < controls.size(); ++i) { float value = 0.0; m_faders[count]->m_controllerRotaries[i].second->blockSignals(true); // The ControllerValues might not yet be set on // the actual Instrument so don't always expect // to find one. There might be a hole here for // deleted Controllers to hang around on // Instruments.. // try { value = float((*iIt)->getControllerValue (controls[i].getControllerValue())); } catch (std::string s) { /* RG_DEBUG << "MidiMixerWindow::slotUpdateInstrument - " << "can't match controller " << int(controls[i]. getControllerValue()) << " - \"" << s << "\"" << endl; */ continue; } /* RG_DEBUG << "MidiMixerWindow::slotUpdateInstrument" << " - MATCHED " << int(controls[i].getControllerValue()) << endl; */ m_faders[count]->m_controllerRotaries[i]. second->setPosition(value); m_faders[count]->m_controllerRotaries[i].second->blockSignals(false); } } count++; } } } blockSignals(false); }
void CreateOrDeleteDeviceCommand::execute() { if (!m_deviceCreated) { //!DEVPUSH: Not ideal; we probably just want to add it to the studio (and then trigger a re-push) rather than add it twice to studio and sequencer // Create // don't want to do this again on undo even if it fails -- only on redo m_deviceCreated = true; m_deviceId = m_studio->getSpareDeviceId(m_baseInstrumentId); bool success = RosegardenSequencer::getInstance()-> addDevice(m_type, m_deviceId, m_baseInstrumentId, m_direction); if (!success) { SEQMAN_DEBUG << "CreateDeviceCommand::execute - " << "sequencer addDevice failed" << endl; return ; } SEQMAN_DEBUG << "CreateDeviceCommand::execute - " << " added device " << m_deviceId << " with base instrument id " << m_baseInstrumentId << endl; RosegardenSequencer::getInstance()->setConnection (m_deviceId, strtoqstr(m_connection)); SEQMAN_DEBUG << "CreateDeviceCommand::execute - " << " reconnected device " << m_deviceId << " to " << m_connection << endl; m_studio->addDevice(m_name, m_deviceId, m_baseInstrumentId, m_type); Device *device = m_studio->getDevice(m_deviceId); if (device) { device->setConnection(m_connection); MidiDevice *md = dynamic_cast<MidiDevice *>(device); if (md) md->setDirection(m_direction); } /* update view automatically (without pressing refresh button) */ DeviceManagerDialog *dmd=RosegardenMainWindow::self()->getDeviceManager(); if (dmd!=NULL) { dmd->slotResyncDevicesReceived(); } } else { // Delete RosegardenSequencer::getInstance()->removeDevice(m_deviceId); SEQMAN_DEBUG << "CreateDeviceCommand::unexecute - " << " removed device " << m_deviceId << endl; m_studio->removeDevice(m_deviceId); m_deviceId = Device::NO_DEVICE; m_deviceCreated = false; } }
SplitByRecordingSrcDialog::SplitByRecordingSrcDialog(QWidget *parent, RosegardenDocument *doc) : QDialog(parent) { setModal(true); setWindowTitle(tr("Split by Recording Source")); QGridLayout *metagrid = new QGridLayout; setLayout(metagrid); QWidget *vBox = new QWidget(this); QVBoxLayout *vBoxLayout = new QVBoxLayout; metagrid->addWidget(vBox, 0, 0); QGroupBox *groupBox = new QGroupBox( tr("Recording Source"), vBox ); groupBox->setContentsMargins(10, 10, 10, 10); QGridLayout *layout = new QGridLayout(groupBox); layout->setSpacing(5); vBoxLayout->addWidget(groupBox); vBox->setLayout(vBoxLayout); layout->addWidget(new QLabel( tr("Channel:"), groupBox ), 0, 0); m_channel = new QComboBox( groupBox ); m_channel->setMaxVisibleItems( 17 ); layout->addWidget(m_channel, 0, 1); QSpacerItem *spacer = new QSpacerItem( 1, 1, QSizePolicy::Expanding, QSizePolicy::Minimum ); layout->addItem( spacer, 0, 2 ); m_channel->addItem(tr("any")); for (int i = 1; i < 17; ++i) { m_channel->addItem(QString::number(i)); } layout->addWidget(new QLabel( tr("Device:"), groupBox ), 1, 0); m_device = new QComboBox( groupBox ); layout->addWidget( m_device, 1, 1, 0+1, 2 - 1+1); m_deviceIds.clear(); m_deviceIds.push_back( -1); m_device->addItem(tr("any")); DeviceList *devices = doc->getStudio().getDevices(); DeviceListConstIterator it; for (it = devices->begin(); it != devices->end(); it++) { MidiDevice *dev = dynamic_cast<MidiDevice*>(*it); if (dev && dev->getDirection() == MidiDevice::Record) { QString label = QString::number(dev->getId()); label += ": "; label += strtoqstr(dev->getName()); QString connection = RosegardenSequencer::getInstance()->getConnection (dev->getId()); label += " - "; if (connection == "") label += tr("No connection"); else label += connection; m_device->addItem(label); m_deviceIds.push_back(dev->getId()); } } m_channel->setCurrentIndex(0); m_device->setCurrentIndex(0); groupBox->setLayout(layout); QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel ); metagrid->addWidget(buttonBox, 1, 0); metagrid->setRowStretch(0, 10); connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept())); connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); }
void MidiMixerWindow::setupTabs() { DeviceListConstIterator it; MidiDevice *dev = 0; InstrumentList instruments; InstrumentList::const_iterator iIt; int faderCount = 0, deviceCount = 1; if (m_tabFrame) delete m_tabFrame; // Setup m_tabFrame // QWidget *blackWidget = new QWidget(this); setCentralWidget(blackWidget); QVBoxLayout *centralLayout = new QVBoxLayout; blackWidget->setLayout(centralLayout); m_tabWidget = new QTabWidget; centralLayout->addWidget(m_tabWidget); connect(m_tabWidget, SIGNAL(currentChanged(QWidget *)), this, SLOT(slotCurrentTabChanged(QWidget *))); m_tabWidget->setTabPosition(QTabWidget::South); setWindowTitle(tr("MIDI Mixer")); setWindowIcon(IconLoader().loadPixmap("window-midimixer")); for (it = m_studio->begin(); it != m_studio->end(); ++it) { dev = dynamic_cast<MidiDevice*>(*it); if (dev) { // Get the control parameters that are on the IPB (and hence can // be shown here too). // ControlList controls = getIPBForMidiMixer(dev); instruments = dev->getPresentationInstruments(); // Don't add a frame for empty devices // if (!instruments.size()) continue; m_tabFrame = new QFrame(m_tabWidget); m_tabFrame->setContentsMargins(10, 10, 10, 10); // m_tabFrame->setContentsMargins(5, 5, 5, 5); ??? QGridLayout *mainLayout = new QGridLayout(m_tabFrame); // MIDI Mixer label QLabel *label = new QLabel("", m_tabFrame); mainLayout->addWidget(label, 0, 0, 0, 16, Qt::AlignCenter); // control labels for (size_t i = 0; i < controls.size(); ++i) { label = new QLabel(QObject::tr(controls[i].getName().c_str()), m_tabFrame); mainLayout->addWidget(label, i + 1, 0, Qt::AlignCenter); } // meter label // (obsolete abandoned code deleted here) // volume label label = new QLabel(tr("Volume"), m_tabFrame); mainLayout->addWidget(label, controls.size() + 2, 0, Qt::AlignCenter); // instrument label label = new QLabel(tr("Instrument"), m_tabFrame); label->setFixedWidth(80); //!!! this should come from metrics mainLayout->addWidget(label, controls.size() + 3, 0, Qt::AlignLeft); int posCount = 1; int firstInstrument = -1; for (iIt = instruments.begin(); iIt != instruments.end(); ++iIt) { // Add new fader struct // m_faders.push_back(new FaderStruct()); // Store the first ID // if (firstInstrument == -1) firstInstrument = (*iIt)->getId(); // Add the controls // for (size_t i = 0; i < controls.size(); ++i) { QColor knobColour = QColor(Qt::white); if (controls[i].getColourIndex() > 0) { Colour c = m_document->getComposition().getGeneralColourMap(). getColourByIndex(controls[i].getColourIndex()); knobColour = QColor(c.getRed(), c.getGreen(), c.getBlue()); } Rotary *controller = new Rotary(m_tabFrame, controls[i].getMin(), controls[i].getMax(), 1.0, 5.0, controls[i].getDefault(), 20, Rotary::NoTicks, false, controls[i].getDefault() == 64); //!!! hacky controller->setKnobColour(knobColour); connect(controller, SIGNAL(valueChanged(float)), this, SLOT(slotControllerChanged(float))); mainLayout->addWidget(controller, i + 1, posCount, Qt::AlignCenter); // Store the rotary // m_faders[faderCount]->m_controllerRotaries.push_back( std::pair<MidiByte, Rotary*> (controls[i].getControllerValue(), controller)); } // VU meter // MidiMixerVUMeter *meter = new MidiMixerVUMeter(m_tabFrame, VUMeter::FixedHeightVisiblePeakHold, 6, 30); mainLayout->addWidget(meter, controls.size() + 1, posCount, Qt::AlignCenter); m_faders[faderCount]->m_vuMeter = meter; // Volume fader // Fader *fader = new Fader(0, 127, 100, 20, 80, m_tabFrame); mainLayout->addWidget(fader, controls.size() + 2, posCount, Qt::AlignCenter); m_faders[faderCount]->m_volumeFader = fader; // Label // QLabel *idLabel = new QLabel(QString("%1"). arg((*iIt)->getId() - firstInstrument + 1), m_tabFrame); idLabel->setObjectName("idLabel"); mainLayout->addWidget(idLabel, controls.size() + 3, posCount, Qt::AlignCenter); // store id in struct m_faders[faderCount]->m_id = (*iIt)->getId(); // Connect them up // connect(fader, SIGNAL(faderChanged(float)), this, SLOT(slotFaderLevelChanged(float))); // Update all the faders and controllers // slotUpdateInstrument((*iIt)->getId()); // Increment counters // posCount++; faderCount++; } QString name = QString("%1 (%2)") .arg(QObject::tr(dev->getName().c_str())) .arg(deviceCount++); addTab(m_tabFrame, name); } } }
static void readConfigMidiPort(Xml& xml)/*{{{*/ { int idx = 0; qint64 id = -1; QString device; bool isGlobal = false; QString instrument("GM"); QList<PatchSequence*> patchSequences; QList<QPair<int, QString> > presets; int openFlags = 1; int dic = 0; int doc = 0; int type = MidiDevice::ALSA_MIDI; bool cachenrpn = false; MidiDevice* dev = 0; for (;;) { Xml::Token token = xml.parse(); if (token == Xml::Error || token == Xml::End) break; QString tag = xml.s1(); switch (token) { case Xml::TagStart: if (tag == "name") { device = xml.parse1(); if (!dev)//Look for it as an alsa or already created device dev = midiDevices.find(device); } else if (tag == "type") { type = xml.parseInt(); } else if (tag == "record") { // old bool f = xml.parseInt(); if (f) openFlags |= 2; } else if (tag == "openFlags") openFlags = xml.parseInt(); else if (tag == "defaultInChans") dic = xml.parseInt(); else if (tag == "defaultOutChans") doc = xml.parseInt(); else if (tag == "instrument") { instrument = xml.parse1(); } else if (tag == "channel") { readPortChannel(xml, idx); } else if (tag == "preset" || tag == "patchSequence") { PatchSequence* p = readMidiPortPatchSequences(xml); if (p) patchSequences.append(p); } else if(tag == "midiPreset") { presets.append(readMidiPortPreset(xml)); } else if(tag == "cacheNRPN") { cachenrpn = xml.parseInt(); } else xml.skip(tag); break; case Xml::Attribut: if (tag == "idx") {//Check to see if this port is already used, and bump if so idx = xml.s2().toInt(); int freePort = getFreeMidiPort(); if(freePort != idx) {//Set a flag here so we know when loading tracks later that we are dealing with an old file or global inputs changed idx = freePort; } } else if(tag == "portId") {//New style id = xml.s2().toLongLong(); idx = getFreeMidiPort(); } else if(tag == "isGlobalInput") {//Find the matching input if posible and set our index to it isGlobal = xml.s2().toInt(); } break; case Xml::TagEnd: if (tag == "midiport") { if(isGlobal) {//Find the global input that matches // if(gInputListPorts.size()) { int myport = -1; for(int i = 0; i < gInputListPorts.size(); ++i) { myport = gInputListPorts.at(i); MidiPort* inport = &midiPorts[i]; if(inport && inport->device() && inport->device()->name() == device) { idx = myport; break; } } } } if (idx < 0 || idx >= MIDI_PORTS) { fprintf(stderr, "bad midi port %d (>%d)\n", idx, MIDI_PORTS); idx = 0; } if (!dev) { if (type == MidiDevice::JACK_MIDI) { dev = MidiJackDevice::createJackMidiDevice(device); // p3.3.55 if (debugMsg) fprintf(stderr, "readConfigMidiPort: creating jack midi device %s\n", device.toLatin1().constData()); } else dev = midiDevices.find(device); } if (debugMsg && !dev) fprintf(stderr, "readConfigMidiPort: device not found %s\n", device.toLatin1().constData()); MidiPort* mp = &midiPorts[idx]; if(id) mp->setPortId(id); mp->setInstrument(registerMidiInstrument(instrument)); mp->setDefaultInChannels(dic); mp->setDefaultOutChannels(doc); //Indicate the port was found in the song file, even if no device is assigned to it. mp->setFoundInSongFile(true); if (!patchSequences.isEmpty()) { for (int i = 0; i < patchSequences.size(); ++i) { mp->appendPatchSequence(patchSequences.at(i)); } } if(!presets.isEmpty()) { for(int i = 0; i < presets.size(); ++i) { QPair<int, QString> pair = presets.at(i); mp->addPreset(pair.first, pair.second); } } if (dev) { dev->setOpenFlags(openFlags); midiSeq->msgSetMidiDevice(mp, dev); dev->setCacheNRPN(cachenrpn); } losMidiPorts.insert(mp->id(), mp); return; } default: break; } } }/*}}}*/
void Route::read(Xml& xml)/*{{{*/ { QString s; int dtype = MidiDevice::ALSA_MIDI; int port = -1; unsigned char rtype = Route::TRACK_ROUTE; for (;;) { const QString& tag = xml.s1(); Xml::Token token = xml.parse(); switch (token) { case Xml::Error: case Xml::End: return; case Xml::Attribut: #ifdef ROUTE_DEBUG printf("Route::read(): attribute:%s\n", tag.toLatin1().constData()); #endif if (tag == "type") rtype = xml.s2().toInt(); else if (tag == "devtype") { dtype = xml.s2().toInt(); rtype = Route::MIDI_DEVICE_ROUTE; } else if (tag == "name") s = xml.s2(); else if(tag == "trackId") { trackId = xml.s2().toLongLong(); rtype = Route::TRACK_ROUTE; } else if (tag == "mport") // p3.3.49 { port = xml.s2().toInt(); rtype = Route::MIDI_PORT_ROUTE; } else if(tag == "mportId") { midiPortId = xml.s2().toLongLong(); rtype = Route::MIDI_PORT_ROUTE; } else printf("Route::read(): unknown attribute:%s\n", tag.toLatin1().constData()); break; case Xml::TagEnd: #ifdef ROUTE_DEBUG printf("Route::read(): tag end type:%d channel:%d name:%s\n", rtype, channel, s.toLatin1().constData()); #endif if (rtype == MIDI_PORT_ROUTE) { if(midiPortId > 0) { //qDebug("Route::read(): MIDI_PORT_ROUTE Finding midiport from id"); type = rtype; MidiPort *mp = oomMidiPorts.value(midiPortId); if(mp) { midiPort = mp->portno(); //qDebug("Route::read(): Found midiport from id: %d", midiPort); } } else if (port >= 0 && port < MIDI_PORTS) { type = rtype; midiPort = port; MidiPort *mp = &midiPorts[midiPort]; midiPortId = mp->id(); } else printf("Route::read(): midi port <%d> out of range\n", port); } else if (!s.isEmpty()) { if (rtype == TRACK_ROUTE) { if(trackId > 0) { track = song->findTrackById(trackId); type = rtype; } else { TrackList* tl = song->tracks(); iTrack i = tl->begin(); for (; i != tl->end(); ++i) { Track* t = *i; if (t->name() == s) { track = t; type = rtype; trackId = t->id(); break; } } if (i == tl->end()) printf("Route::read(): track <%s> not found\n", s.toLatin1().constData()); } } else if (rtype == JACK_ROUTE) { void* jport = 0; if (audioDevice) //Fix from Robert at muse jport = audioDevice->findPort(s.toLatin1().constData()); if (jport == 0) printf("Route::read(): jack port <%s> not found audioDevice(%p)\n", s.toLatin1().constData(), audioDevice); else { jackPort = jport; type = rtype; } } else if (rtype == MIDI_DEVICE_ROUTE) { iMidiDevice imd = midiDevices.begin(); for (; imd != midiDevices.end(); ++imd) { MidiDevice* md = *imd; if (md->name() == s && md->deviceType() == dtype) { // We found a device, but if it is not in use by the song (port is -1), ignore it. // This prevents loading and propagation of bogus routes in the oom file. if (md->midiPort() == -1) break; device = md; type = rtype; break; } } if (imd == midiDevices.end()) printf("Route::read(): midi device <%s> not found\n", s.toLatin1().constData()); } } return; default: break; } } }/*}}}*/
void MidiMixerWindow::slotControllerDeviceEventReceived(MappedEvent *e, const void *preferredCustomer) { if (preferredCustomer != this) return ; RG_DEBUG << "MidiMixerWindow::slotControllerDeviceEventReceived: this one's for me" << endl; raise(); // get channel number n from event // get nth instrument on current tab if (e->getType() != MappedEvent::MidiController) return ; unsigned int channel = e->getRecordedChannel(); MidiByte controller = e->getData1(); MidiByte value = e->getData2(); int tabIndex = m_tabWidget->currentIndex(); int i = 0; for (DeviceList::const_iterator it = m_studio->begin(); it != m_studio->end(); ++it) { MidiDevice *dev = dynamic_cast<MidiDevice*>(*it); if (!dev) continue; if (i != tabIndex) { ++i; continue; } InstrumentList instruments = dev->getPresentationInstruments(); for (InstrumentList::const_iterator iIt = instruments.begin(); iIt != instruments.end(); ++iIt) { Instrument *instrument = *iIt; if (instrument->getNaturalChannel() != channel) continue; ControlList cl = dev->getIPBControlParameters(); for (ControlList::const_iterator i = cl.begin(); i != cl.end(); ++i) { if ((*i).getControllerValue() == controller) { RG_DEBUG << "Setting controller " << controller << " for instrument " << instrument->getId() << " to " << value << endl; instrument->setControllerValue(controller, value); break; } } slotUpdateInstrument(instrument->getId()); emit instrumentParametersChanged(instrument->getId()); } break; } }
static void writeSeqConfiguration(int level, Xml& xml, bool writePortInfo)/*{{{*/ { xml.tag(level++, "sequencer"); if (writePortInfo) { // // write information about all midi ports, their assigned // instruments and all managed midi controllers // for (int i = 0; i < MIDI_PORTS; ++i) { bool used = false; MidiPort* mport = &midiPorts[i]; // Route check by Tim. Port can now be used for routing even if no device. // Also, check for other non-defaults and save port, to preserve settings even if no device. // Dont write the config for the global inputs list they will be auto created with each startup if (mport->defaultInChannels() || mport->defaultOutChannels() || (mport->instrument() && !mport->instrument()->iname().isEmpty() && mport->instrument()->iname() != "GM") /*|| !mport->syncInfo().isDefault()*/ ) { used = true; } else {//Put the ID of this track into a list MidiTrackList* tl = song->midis(); for (iMidiTrack it = tl->begin(); it != tl->end(); ++it) { MidiTrack* t = *it; if (t->outPort() == i) { used = true; break; } } } MidiDevice* dev = mport->device(); if (!used && !dev) continue; bool isGlobal = gInputListPorts.contains(mport->portno()); xml.tag(level++, "midiport portId=\"%lld\" isGlobalInput=\"%d\"", mport->id(), isGlobal); if (mport->defaultInChannels()) xml.intTag(level, "defaultInChans", mport->defaultInChannels()); if (mport->defaultOutChannels()) xml.intTag(level, "defaultOutChans", mport->defaultOutChannels()); if (mport->instrument() && !mport->instrument()->iname().isEmpty() && (mport->instrument()->iname() != "GM")) // FIXME: TODO: Make this user configurable. { xml.strTag(level, "instrument", mport->instrument()->iname()); } if (dev) { xml.strTag(level, "name", dev->name()); xml.intTag(level, "cacheNRPN", (int)dev->cacheNRPN()); if (dev->deviceType() != MidiDevice::ALSA_MIDI) xml.intTag(level, "type", dev->deviceType()); xml.intTag(level, "openFlags", dev->openFlags()); } // write out registered controller for all channels MidiCtrlValListList* vll = mport->controller(); for (int k = 0; k < MIDI_CHANNELS; ++k) { int min = k << 24; int max = min + 0x100000; xml.tag(level++, "channel idx=\"%d\"", k); iMidiCtrlValList s = vll->lower_bound(min); iMidiCtrlValList e = vll->lower_bound(max); if (s != e) { for (iMidiCtrlValList i = s; i != e; ++i) { if(i->second->num() != 262145) { xml.tag(level++, "controller id=\"%d\"", i->second->num()); if (i->second->hwVal() != CTRL_VAL_UNKNOWN) xml.intTag(level, "val", i->second->hwVal()); xml.etag(--level, "controller"); } } } xml.etag(--level, "channel"); } QList<PatchSequence*> *patchSequences = mport->patchSequences(); if (patchSequences && !patchSequences->isEmpty()) { for (int p = 0; p < patchSequences->size(); ++p) { PatchSequence* ps = patchSequences->at(p); QString pm = ps->name.replace('\n', " "); xml.put(level, "<patchSequence id=\"%d\" name=\"%s\" checked=\"%d\" />", ps->id, pm.toLatin1().constData(), ps->selected); } } if(!mport->presets()->isEmpty()) { QHashIterator<int, QString> iter(*mport->presets()); while(iter.hasNext()) { iter.next(); xml.put(level, "<midiPreset id=\"%d\" sysex=\"%s\"/>", iter.key(), iter.value().toLatin1().constData()); } } xml.etag(--level, "midiport"); } } xml.tag(--level, "/sequencer"); }/*}}}*/
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; } }