//========================================================= // MusE // Linux Music Editor // // midi_audio_control.cpp // Copyright (C) 2012 by Tim E. Real (terminator356 at users.sourceforge.net) // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; version 2 of // the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // //========================================================= #include "midi_audio_control.h" #include "globals.h" #include "globaldefs.h" #include "mididev.h" #include "midiport.h" #include "midictrl.h" #include "audio.h" #include "app.h" #include namespace MusEGui { // ----------------------------------- // MidiAudioControl // Set port to -1 to automatically set it to the port of // the first combo box item (the first readable port). // ----------------------------------- MidiAudioControl::MidiAudioControl(int port, int chan, int ctrl, QWidget* parent) : QDialog(parent) { setupUi(this); controlTypeComboBox->addItem(tr("Control7"), MusECore::MidiController::Controller7); controlTypeComboBox->addItem(tr("Control14"), MusECore::MidiController::Controller14); controlTypeComboBox->addItem(tr("RPN"), MusECore::MidiController::RPN); controlTypeComboBox->addItem(tr("NPRN"), MusECore::MidiController::NRPN); controlTypeComboBox->addItem(tr("RPN14"), MusECore::MidiController::RPN14); controlTypeComboBox->addItem(tr("NRPN14"), MusECore::MidiController::NRPN14); controlTypeComboBox->addItem(tr("Pitch"), MusECore::MidiController::Pitch); controlTypeComboBox->addItem(tr("Program"), MusECore::MidiController::Program); //controlTypeComboBox->addItem(tr("PolyAftertouch"), MusECore::MidiController::PolyAftertouch); // Not supported yet. Need a way to select pitch. controlTypeComboBox->addItem(tr("Aftertouch"), MusECore::MidiController::Aftertouch); controlTypeComboBox->setCurrentIndex(0); _port = port; _chan = chan; _ctrl = ctrl; _is_learning = false; update(); connect(learnPushButton, SIGNAL(clicked(bool)), SLOT(learnChanged(bool))); connect(portComboBox, SIGNAL(currentIndexChanged(int)), SLOT(portChanged(int))); connect(channelSpinBox, SIGNAL(valueChanged(int)), SLOT(chanChanged())); connect(controlTypeComboBox, SIGNAL(currentIndexChanged(int)), SLOT(ctrlTypeChanged(int))); connect(ctrlHiSpinBox, SIGNAL(valueChanged(int)), SLOT(ctrlHChanged())); connect(ctrlLoSpinBox, SIGNAL(valueChanged(int)), SLOT(ctrlLChanged())); connect(MusEGlobal::muse, SIGNAL(configChanged()), SLOT(configChanged())); connect(MusEGlobal::heartBeatTimer, SIGNAL(timeout()), SLOT(heartbeat())); } void MidiAudioControl::heartbeat() { if(_is_learning) { if(MusEGlobal::midiLearnPort != -1) { int port_item = portComboBox->findData(MusEGlobal::midiLearnPort); if(port_item != -1 && port_item != portComboBox->currentIndex()) { _port = MusEGlobal::midiLearnPort; portComboBox->blockSignals(true); portComboBox->setCurrentIndex(port_item); portComboBox->blockSignals(false); } } if(MusEGlobal::midiLearnChan != -1 && (MusEGlobal::midiLearnChan + 1) != channelSpinBox->value()) { _chan = MusEGlobal::midiLearnChan; channelSpinBox->blockSignals(true); channelSpinBox->setValue(_chan + 1); channelSpinBox->blockSignals(false); } if(MusEGlobal::midiLearnCtrl != -1) { MusECore::MidiController::ControllerType type = MusECore::midiControllerType(MusEGlobal::midiLearnCtrl); int idx = controlTypeComboBox->findData(type); if(idx != -1 && idx != controlTypeComboBox->currentIndex()) { controlTypeComboBox->blockSignals(true); controlTypeComboBox->setCurrentIndex(idx); controlTypeComboBox->blockSignals(false); } int hv = (MusEGlobal::midiLearnCtrl >> 8) & 0xff; int lv = MusEGlobal::midiLearnCtrl & 0xff; switch(type) { case MusECore::MidiController::Program: case MusECore::MidiController::Pitch: case MusECore::MidiController::PolyAftertouch: // Unsupported yet. Need a way to select pitch. case MusECore::MidiController::Aftertouch: ctrlHiSpinBox->setEnabled(false); ctrlLoSpinBox->setEnabled(false); ctrlHiSpinBox->blockSignals(true); ctrlLoSpinBox->blockSignals(true); ctrlHiSpinBox->setValue(0); ctrlLoSpinBox->setValue(0); ctrlHiSpinBox->blockSignals(false); ctrlLoSpinBox->blockSignals(false); break; case MusECore::MidiController::Controller7: ctrlHiSpinBox->setEnabled(false); ctrlLoSpinBox->setEnabled(true); ctrlHiSpinBox->blockSignals(true); ctrlHiSpinBox->setValue(0); ctrlHiSpinBox->blockSignals(false); if(lv != ctrlLoSpinBox->value()) { ctrlLoSpinBox->blockSignals(true); ctrlLoSpinBox->setValue(lv); ctrlLoSpinBox->blockSignals(false); } break; case MusECore::MidiController::Controller14: case MusECore::MidiController::RPN: case MusECore::MidiController::RPN14: case MusECore::MidiController::NRPN: case MusECore::MidiController::NRPN14: ctrlHiSpinBox->setEnabled(true); ctrlLoSpinBox->setEnabled(true); if(hv != ctrlHiSpinBox->value()) { ctrlHiSpinBox->blockSignals(true); ctrlHiSpinBox->setValue(hv); ctrlHiSpinBox->blockSignals(false); } if(lv != ctrlLoSpinBox->value()) { ctrlLoSpinBox->blockSignals(true); ctrlLoSpinBox->setValue(lv); ctrlLoSpinBox->blockSignals(false); } break; default: printf("FIXME: MidiAudioControl::heartbeat: Unknown control type: %d\n", type); break; } _ctrl = MusECore::midiCtrlTerms2Number(type, (ctrlHiSpinBox->value() << 8) + ctrlLoSpinBox->value()); } } } void MidiAudioControl::learnChanged(bool v) { _is_learning = v; if(_is_learning) MusEGlobal::audio->msgStartMidiLearn(); // Resets the learn values to -1. } void MidiAudioControl::resetLearn() { _is_learning = false; learnPushButton->blockSignals(true); learnPushButton->setChecked(false); learnPushButton->blockSignals(false); MusEGlobal::audio->msgStartMidiLearn(); // Resets the learn values to -1. } void MidiAudioControl::portChanged(int idx) { if(idx == -1) return; int port_num = portComboBox->itemData(idx).toInt(); if(port_num < 0 || port_num >= MIDI_PORTS) return; _port = port_num; resetLearn(); } void MidiAudioControl::chanChanged() { _chan = channelSpinBox->value() - 1; resetLearn(); } void MidiAudioControl::updateCtrlBoxes() { if(controlTypeComboBox->currentIndex() == -1) return; MusECore::MidiController::ControllerType t = (MusECore::MidiController::ControllerType)controlTypeComboBox->itemData(controlTypeComboBox->currentIndex()).toInt(); switch(t) { case MusECore::MidiController::Program: case MusECore::MidiController::Pitch: case MusECore::MidiController::PolyAftertouch: // Unsupported yet. Need a way to select pitch. case MusECore::MidiController::Aftertouch: ctrlHiSpinBox->setEnabled(false); ctrlLoSpinBox->setEnabled(false); ctrlHiSpinBox->blockSignals(true); ctrlLoSpinBox->blockSignals(true); ctrlHiSpinBox->setValue(0); ctrlLoSpinBox->setValue(0); ctrlHiSpinBox->blockSignals(false); ctrlLoSpinBox->blockSignals(false); break; case MusECore::MidiController::Controller7: ctrlHiSpinBox->setEnabled(false); ctrlLoSpinBox->setEnabled(true); ctrlHiSpinBox->blockSignals(true); ctrlHiSpinBox->setValue(0); ctrlHiSpinBox->blockSignals(false); break; case MusECore::MidiController::Controller14: case MusECore::MidiController::RPN: case MusECore::MidiController::RPN14: case MusECore::MidiController::NRPN: case MusECore::MidiController::NRPN14: ctrlHiSpinBox->setEnabled(true); ctrlLoSpinBox->setEnabled(true); break; default: printf("FIXME: MidiAudioControl::updateCtrlBoxes: Unknown control type: %d\n", t); break; } } void MidiAudioControl::ctrlTypeChanged(int idx) { if(idx == -1) return; updateCtrlBoxes(); _ctrl = (ctrlHiSpinBox->value() << 8) + ctrlLoSpinBox->value(); _ctrl = MusECore::midiCtrlTerms2Number((MusECore::MidiController::ControllerType)controlTypeComboBox->itemData(idx).toInt(), _ctrl); resetLearn(); } void MidiAudioControl::ctrlHChanged() { if(controlTypeComboBox->currentIndex() == -1) return; _ctrl = (ctrlHiSpinBox->value() << 8) + ctrlLoSpinBox->value(); _ctrl = MusECore::midiCtrlTerms2Number((MusECore::MidiController::ControllerType)controlTypeComboBox->itemData(controlTypeComboBox->currentIndex()).toInt(), _ctrl); resetLearn(); } void MidiAudioControl::ctrlLChanged() { if(controlTypeComboBox->currentIndex() == -1) return; _ctrl = (ctrlHiSpinBox->value() << 8) + ctrlLoSpinBox->value(); _ctrl = MusECore::midiCtrlTerms2Number((MusECore::MidiController::ControllerType)controlTypeComboBox->itemData(controlTypeComboBox->currentIndex()).toInt(), _ctrl); resetLearn(); } void MidiAudioControl::configChanged() { update(); } void MidiAudioControl::update() { portComboBox->blockSignals(true); portComboBox->clear(); int item_idx = 0; for (int i = 0; i < MIDI_PORTS; ++i) { MusECore::MidiDevice* md = MusEGlobal::midiPorts[i].device(); if(!md) // In the case of this combo box, don't bother listing empty ports. continue; //if(!(md->rwFlags() & 1 || md->isSynti()) && (i != outPort)) if(!(md->rwFlags() & 2) && (i != _port)) // Only readable ports, or current one. continue; QString name; name.sprintf("%d:%s", i+1, MusEGlobal::midiPorts[i].portname().toLatin1().constData()); portComboBox->insertItem(item_idx, name, i); if(_port == -1) _port = i; // Initialize if(i == _port) portComboBox->setCurrentIndex(item_idx); item_idx++; } portComboBox->blockSignals(false); channelSpinBox->blockSignals(true); channelSpinBox->setValue(_chan + 1); channelSpinBox->blockSignals(false); int type = MusECore::midiControllerType(_ctrl); int idx = controlTypeComboBox->findData(type); if(idx != -1 && idx != controlTypeComboBox->currentIndex()) { controlTypeComboBox->blockSignals(true); controlTypeComboBox->setCurrentIndex(idx); controlTypeComboBox->blockSignals(false); } int hv = (_ctrl >> 8) & 0xff; int lv = _ctrl & 0xff; switch(type) { case MusECore::MidiController::Program: case MusECore::MidiController::Pitch: case MusECore::MidiController::PolyAftertouch: // Unsupported yet. Need a way to select pitch. case MusECore::MidiController::Aftertouch: ctrlHiSpinBox->setEnabled(false); ctrlLoSpinBox->setEnabled(false); ctrlHiSpinBox->blockSignals(true); ctrlLoSpinBox->blockSignals(true); ctrlHiSpinBox->setValue(0); ctrlLoSpinBox->setValue(0); ctrlHiSpinBox->blockSignals(false); ctrlLoSpinBox->blockSignals(false); break; case MusECore::MidiController::Controller7: ctrlHiSpinBox->setEnabled(false); ctrlLoSpinBox->setEnabled(true); ctrlHiSpinBox->blockSignals(true); ctrlHiSpinBox->setValue(0); ctrlHiSpinBox->blockSignals(false); if(lv != ctrlLoSpinBox->value()) { ctrlLoSpinBox->blockSignals(true); ctrlLoSpinBox->setValue(lv); ctrlLoSpinBox->blockSignals(false); } break; case MusECore::MidiController::Controller14: case MusECore::MidiController::RPN: case MusECore::MidiController::RPN14: case MusECore::MidiController::NRPN: case MusECore::MidiController::NRPN14: ctrlHiSpinBox->setEnabled(true); ctrlLoSpinBox->setEnabled(true); if(hv != ctrlHiSpinBox->value()) { ctrlHiSpinBox->blockSignals(true); ctrlHiSpinBox->setValue(hv); ctrlHiSpinBox->blockSignals(false); } if(lv != ctrlLoSpinBox->value()) { ctrlLoSpinBox->blockSignals(true); ctrlLoSpinBox->setValue(lv); ctrlLoSpinBox->blockSignals(false); } break; default: printf("FIXME: MidiAudioControl::updateCtrlBoxes: Unknown control type: %d\n", type); break; } } } // namespace MusEGui