//========================================================= // MusE // Linux Music Editor // (C) Copyright 2010 Werner Schweer and others (ws@seh.de) // (C) Copyright 2011 Tim E. Real (terminator356 on sourceforge) // // 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 #include #include #include #include #include #include #include "mtrackinfo.h" #include "song.h" #include "globals.h" #include "config.h" #include "gconfig.h" #include "midiport.h" #include "minstrument.h" #include "mididev.h" #include "utils.h" #include "audio.h" #include "midi.h" #include "midictrl.h" #include "icons.h" #include "app.h" #include "route.h" #include "popupmenu.h" #include "routepopup.h" namespace MusEGui { //--------------------------------------------------------- // setTrack //--------------------------------------------------------- void MidiTrackInfo::setTrack(MusECore::Track* t) { if(!t) { selected = 0; return; } if(!t->isMidiTrack()) return; selected = t; trackNameLabel->setObjectName(selected->cname()); /*QPalette pal; if(selected->type() == MusECore::Track::DRUM) { pal.setColor(trackNameLabel->backgroundRole(), MusEGlobal::config.drumTrackLabelBg); iOutputChannel->setEnabled(false); } else { pal.setColor(trackNameLabel->backgroundRole(), MusEGlobal::config.midiTrackLabelBg); iOutputChannel->setEnabled(true); } trackNameLabel->setPalette(pal); */ //setLabelText(); updateTrackInfo(-1); } //--------------------------------------------------------- // midiTrackInfo //--------------------------------------------------------- MidiTrackInfo::MidiTrackInfo(QWidget* parent, MusECore::Track* sel_track) : QWidget(parent) { setupUi(this); _midiDetect = false; heartBeatCounter = 0; _blockHeartbeatCount = 0; selected = sel_track; // Since program covers 3 controls at once, it is in 'midi controller' units rather than 'gui control' units. //program = -1; program = MusECore::CTRL_VAL_UNKNOWN; pan = -65; volume = -1; setFont(MusEGlobal::config.fonts[1]); //iChanDetectLabel->setPixmap(*darkgreendotIcon); iChanDetectLabel->setPixmap(*darkRedLedIcon); recEchoButton->setFocusPolicy(Qt::NoFocus); recEchoButton->setIcon((selected && ((MusECore::MidiTrack*)selected)->recEcho()) ? QIcon(*midiThruOnIcon) : QIcon(*midiThruOffIcon)); recEchoButton->setIconSize(midiThruOnIcon->size()); //recEchoButton->setOffPixmap(midiThruOffIcon); //recEchoButton->setOnPixmap(midiThruOnIcon); iRButton->setFocusPolicy(Qt::NoFocus); iRButton->setIcon(QIcon(*routesMidiInIcon)); iRButton->setIconSize(routesMidiInIcon->size()); //iRButton->setOffPixmap(routesMidiInIcon); oRButton->setFocusPolicy(Qt::NoFocus); oRButton->setIcon(QIcon(*routesMidiOutIcon)); oRButton->setIconSize(routesMidiOutIcon->size()); //oRButton->setOffPixmap(routesMidiOutIcon); recordButton->setFocusPolicy(Qt::NoFocus); progRecButton->setFocusPolicy(Qt::NoFocus); volRecButton->setFocusPolicy(Qt::NoFocus); panRecButton->setFocusPolicy(Qt::NoFocus); instrPushButton->setFocusPolicy(Qt::NoFocus); iPatch->setFocusPolicy(Qt::NoFocus); iOutput->setFocusPolicy(Qt::NoFocus); iOutputChannel->setFocusPolicy(Qt::StrongFocus); iHBank->setFocusPolicy(Qt::StrongFocus); iLBank->setFocusPolicy(Qt::StrongFocus); iProgram->setFocusPolicy(Qt::StrongFocus); iHBank->setFocusPolicy(Qt::StrongFocus); iLBank->setFocusPolicy(Qt::StrongFocus); iProgram->setFocusPolicy(Qt::StrongFocus); iLautst->setFocusPolicy(Qt::StrongFocus); iLautst->setFocusPolicy(Qt::StrongFocus); iTransp->setFocusPolicy(Qt::StrongFocus); iAnschl->setFocusPolicy(Qt::StrongFocus); iVerz->setFocusPolicy(Qt::StrongFocus); iLen->setFocusPolicy(Qt::StrongFocus); iKompr->setFocusPolicy(Qt::StrongFocus); iPan->setFocusPolicy(Qt::StrongFocus); // MusE-2: AlignCenter and WordBreak are set in the ui(3) file, but not supported by QLabel. Turn them on here. trackNameLabel->setAlignment(Qt::AlignCenter); //Qt::TextWordWrap is not available for alignment in Qt4 - Orcan // MusE-2 Tested: TextWrapAnywhere actually works, but in fact it takes precedence // over word wrap, so I found it is not really desirable. Maybe with a user setting... //trackNameLabel->setAlignment(Qt::AlignCenter | Qt::TextWordWrap | Qt::TextWrapAnywhere); //trackNameLabel->setSizePolicy(QSizePolicy(QSizePolicy::Ignored, QSizePolicy::Minimum)); if(selected) trackNameLabel->setObjectName(selected->cname()); //trackNameLabel->setStyleSheet(QString("background-color: ") + QColor(0, 160, 255).name()); // Med blue trackNameLabel->setWordWrap(true); trackNameLabel->setAutoFillBackground(true); trackNameLabel->setTextFormat(Qt::PlainText); trackNameLabel->setLineWidth(2); trackNameLabel->setFrameStyle(QFrame::Sunken | QFrame::StyledPanel); trackNameLabel->setSizePolicy(QSizePolicy(QSizePolicy::Ignored, QSizePolicy::Minimum)); setLabelText(); setLabelFont(); MusECore::MidiInstrument* minstr = NULL; MusECore::MidiTrack* track = static_cast(selected); if(track) minstr = MusEGlobal::midiPorts[track->outPort()].instrument(); if(minstr) { instrPushButton->setText(minstr->iname()); if(minstr->isSynti()) instrPushButton->setEnabled(false); else instrPushButton->setEnabled(true); } else instrPushButton->setText(tr("")); //setSizePolicy(QSizePolicy(QSizePolicy::Maximum, QSizePolicy::Expanding)); connect(instrPushButton, SIGNAL(released()), SLOT(instrPopup())); connect(iPatch, SIGNAL(released()), SLOT(patchPopup())); connect(iOutputChannel, SIGNAL(valueChanged(int)), SLOT(iOutputChannelChanged(int))); connect(iHBank, SIGNAL(valueChanged(int)), SLOT(iProgHBankChanged())); connect(iLBank, SIGNAL(valueChanged(int)), SLOT(iProgLBankChanged())); connect(iProgram, SIGNAL(valueChanged(int)), SLOT(iProgramChanged())); connect(iHBank, SIGNAL(ctrlDoubleClicked()), SLOT(iProgHBankDoubleCLicked())); connect(iLBank, SIGNAL(ctrlDoubleClicked()), SLOT(iProgLBankDoubleCLicked())); connect(iProgram, SIGNAL(ctrlDoubleClicked()), SLOT(iProgramDoubleClicked())); connect(iLautst, SIGNAL(valueChanged(int)), SLOT(iLautstChanged(int))); connect(iLautst, SIGNAL(ctrlDoubleClicked()), SLOT(iLautstDoubleClicked())); connect(iTransp, SIGNAL(valueChanged(int)), SLOT(iTranspChanged(int))); connect(iAnschl, SIGNAL(valueChanged(int)), SLOT(iAnschlChanged(int))); connect(iVerz, SIGNAL(valueChanged(int)), SLOT(iVerzChanged(int))); connect(iLen, SIGNAL(valueChanged(int)), SLOT(iLenChanged(int))); connect(iKompr, SIGNAL(valueChanged(int)), SLOT(iKomprChanged(int))); connect(iPan, SIGNAL(valueChanged(int)), SLOT(iPanChanged(int))); connect(iPan, SIGNAL(ctrlDoubleClicked()), SLOT(iPanDoubleClicked())); connect(iOutput, SIGNAL(activated(int)), SLOT(iOutputPortChanged(int))); connect(recordButton, SIGNAL(clicked()), SLOT(recordClicked())); connect(progRecButton, SIGNAL(clicked()), SLOT(progRecClicked())); connect(volRecButton, SIGNAL(clicked()), SLOT(volRecClicked())); connect(panRecButton, SIGNAL(clicked()), SLOT(panRecClicked())); connect(recEchoButton, SIGNAL(toggled(bool)), SLOT(recEchoToggled(bool))); connect(iRButton, SIGNAL(pressed()), SLOT(inRoutesPressed())); connect(iOutputChannel, SIGNAL(returnPressed()), SIGNAL(returnPressed())); connect(iHBank, SIGNAL(returnPressed()), SIGNAL(returnPressed())); connect(iLBank, SIGNAL(returnPressed()), SIGNAL(returnPressed())); connect(iProgram, SIGNAL(returnPressed()), SIGNAL(returnPressed())); connect(iHBank, SIGNAL(returnPressed()), SIGNAL(returnPressed())); connect(iLBank, SIGNAL(returnPressed()), SIGNAL(returnPressed())); connect(iProgram, SIGNAL(returnPressed()), SIGNAL(returnPressed())); connect(iLautst, SIGNAL(returnPressed()), SIGNAL(returnPressed())); connect(iLautst, SIGNAL(returnPressed()), SIGNAL(returnPressed())); connect(iTransp, SIGNAL(returnPressed()), SIGNAL(returnPressed())); connect(iAnschl, SIGNAL(returnPressed()), SIGNAL(returnPressed())); connect(iVerz, SIGNAL(returnPressed()), SIGNAL(returnPressed())); connect(iLen, SIGNAL(returnPressed()), SIGNAL(returnPressed())); connect(iKompr, SIGNAL(returnPressed()), SIGNAL(returnPressed())); connect(iPan, SIGNAL(returnPressed()), SIGNAL(returnPressed())); connect(iOutputChannel, SIGNAL(escapePressed()), SIGNAL(escapePressed())); connect(iHBank, SIGNAL(escapePressed()), SIGNAL(escapePressed())); connect(iLBank, SIGNAL(escapePressed()), SIGNAL(escapePressed())); connect(iProgram, SIGNAL(escapePressed()), SIGNAL(escapePressed())); connect(iHBank, SIGNAL(escapePressed()), SIGNAL(escapePressed())); connect(iLBank, SIGNAL(escapePressed()), SIGNAL(escapePressed())); connect(iProgram, SIGNAL(escapePressed()), SIGNAL(escapePressed())); connect(iLautst, SIGNAL(escapePressed()), SIGNAL(escapePressed())); connect(iLautst, SIGNAL(escapePressed()), SIGNAL(escapePressed())); connect(iTransp, SIGNAL(escapePressed()), SIGNAL(escapePressed())); connect(iAnschl, SIGNAL(escapePressed()), SIGNAL(escapePressed())); connect(iVerz, SIGNAL(escapePressed()), SIGNAL(escapePressed())); connect(iLen, SIGNAL(escapePressed()), SIGNAL(escapePressed())); connect(iKompr, SIGNAL(escapePressed()), SIGNAL(escapePressed())); connect(iPan, SIGNAL(escapePressed()), SIGNAL(escapePressed())); connect(oRButton, SIGNAL(pressed()), SLOT(outRoutesPressed())); connect(MusEGlobal::song, SIGNAL(songChanged(MusECore::SongChangedFlags_t)), SLOT(songChanged(MusECore::SongChangedFlags_t))); connect(MusEGlobal::muse, SIGNAL(configChanged()), SLOT(configChanged())); connect(MusEGlobal::heartBeatTimer, SIGNAL(timeout()), SLOT(heartBeat())); } //--------------------------------------------------------- // heartBeat //--------------------------------------------------------- void MidiTrackInfo::heartBeat() { if(_blockHeartbeatCount < 0) // error { fprintf(stderr, "ERROR: MidiTrackInfo::heartBeat: _blockHeartbeatCount is < 0, resetting to 0\n"); _blockHeartbeatCount = 0; } if(_blockHeartbeatCount > 0 || !isVisible() || !isEnabled() || !selected) return; switch(selected->type()) { case MusECore::Track::MIDI: case MusECore::Track::DRUM: case MusECore::Track::NEW_DRUM: { MusECore::MidiTrack* track = (MusECore::MidiTrack*)selected; int outChannel = track->outChannel(); int outPort = track->outPort(); MusECore::MidiPort* mp = &MusEGlobal::midiPorts[outPort]; // Check for detection of midi general activity on chosen channels... int mpt = 0; MusECore::RouteList* rl = track->inRoutes(); MusECore::ciRoute r = rl->begin(); for( ; r != rl->end(); ++r) { if(!r->isValid() || (r->type != MusECore::Route::MIDI_PORT_ROUTE)) continue; // NOTE: TODO: Code for channelless events like sysex, ** IF we end up using the 'special channel 17' method. //if(r->channel == -1) if(r->channel == -1 || r->channel == 0) continue; // No port assigned to the device? mpt = r->midiPort; if(mpt < 0 || mpt >= MIDI_PORTS) continue; if(MusEGlobal::midiPorts[mpt].syncInfo().actDetectBits() & r->channel) { if(!_midiDetect) { _midiDetect = true; iChanDetectLabel->setPixmap(*redLedIcon); } break; } } // No activity detected? if(r == rl->end()) { if(_midiDetect) { _midiDetect = false; iChanDetectLabel->setPixmap(*darkRedLedIcon); } } int nprogram = mp->hwCtrlState(outChannel, MusECore::CTRL_PROGRAM); if(nprogram == MusECore::CTRL_VAL_UNKNOWN) { if(program != MusECore::CTRL_VAL_UNKNOWN) { program = MusECore::CTRL_VAL_UNKNOWN; if(iHBank->value() != 0) { iHBank->blockSignals(true); iHBank->setValue(0); iHBank->blockSignals(false); } if(iLBank->value() != 0) { iLBank->blockSignals(true); iLBank->setValue(0); iLBank->blockSignals(false); } if(iProgram->value() != 0) { iProgram->blockSignals(true); iProgram->setValue(0); iProgram->blockSignals(false); } } nprogram = mp->lastValidHWCtrlState(outChannel, MusECore::CTRL_PROGRAM); if(nprogram == MusECore::CTRL_VAL_UNKNOWN) { const QString n(tr("")); if(iPatch->text() != n) iPatch->setText(n); } else { MusECore::MidiInstrument* instr = mp->instrument(); const QString name = instr->getPatchName(outChannel, nprogram, track->isDrumTrack()); if(name.isEmpty()) { const QString n("???"); if(iPatch->text() != n) iPatch->setText(n); } else if(iPatch->text() != name) iPatch->setText(name); } } else { // The optimizing below, to avoid repeatedly calling getPatchName, generally worked OK. // But Fluidsynth revealed a flaw. When loading a song, updateTrackInfo is called which correctly // sets program = nprogram. But a synth will not receive midistate sysexes until later. // With Fluidsynth, that messed up our optimizing because the soundfont has not loaded yet. // fluid_synth_get_channel_preset returns 0 in FluidSynth::getPatchName which returns // when asked by updateTrackInfo, which then sets the patch box text to . Then nothing // happens here because program = nprogram. // I don't like the idea of calling getPatchName here at a high rate. // So force an update of program at a slower rate here. // // The alternative is to have a system where the synth can signal the host when a change has happened. // Or an 'isValidPatch' function, or make getPatchName (and several others) return 0, so that updateTrackInfo // can ignore it. Oops. No! Even if we make updateTrackInfo ignore it, then the same thing happens here. // Thats is, program = nprogram but the text is still wrong. Not much choice but to do this for now... if(++heartBeatCounter >= 20) heartBeatCounter = 0; if(program != nprogram || heartBeatCounter == 0) { program = nprogram; MusECore::MidiInstrument* instr = mp->instrument(); const QString name = instr->getPatchName(outChannel, program, track->isDrumTrack()); if(iPatch->text() != name) iPatch->setText(name); int hb = ((program >> 16) & 0xff) + 1; if (hb == 0x100) hb = 0; int lb = ((program >> 8) & 0xff) + 1; if (lb == 0x100) lb = 0; int pr = (program & 0xff) + 1; if (pr == 0x100) pr = 0; if(iHBank->value() != hb) { iHBank->blockSignals(true); iHBank->setValue(hb); iHBank->blockSignals(false); } if(iLBank->value() != lb) { iLBank->blockSignals(true); iLBank->setValue(lb); iLBank->blockSignals(false); } if(iProgram->value() != pr) { iProgram->blockSignals(true); iProgram->setValue(pr); iProgram->blockSignals(false); } } } MusECore::MidiController* mc = mp->midiController(MusECore::CTRL_VOLUME); int mn = mc->minVal(); int v = mp->hwCtrlState(outChannel, MusECore::CTRL_VOLUME); if(v == MusECore::CTRL_VAL_UNKNOWN) v = mn - 1; else // Auto bias... v -= mc->bias(); if(volume != v) { volume = v; if(iLautst->value() != v) { iLautst->blockSignals(true); iLautst->setValue(v); iLautst->blockSignals(false); } } mc = mp->midiController(MusECore::CTRL_PANPOT); mn = mc->minVal(); v = mp->hwCtrlState(outChannel, MusECore::CTRL_PANPOT); if(v == MusECore::CTRL_VAL_UNKNOWN) v = mn - 1; else // Auto bias... v -= mc->bias(); if(pan != v) { pan = v; if(iPan->value() != v) { iPan->blockSignals(true); iPan->setValue(v); iPan->blockSignals(false); } } } break; case MusECore::Track::WAVE: case MusECore::Track::AUDIO_OUTPUT: case MusECore::Track::AUDIO_INPUT: case MusECore::Track::AUDIO_GROUP: case MusECore::Track::AUDIO_AUX: case MusECore::Track::AUDIO_SOFTSYNTH: break; } } //--------------------------------------------------------- // configChanged //--------------------------------------------------------- void MidiTrackInfo::configChanged() { //if (MusEGlobal::config.canvasBgPixmap.isEmpty()) { // canvas->setBg(MusEGlobal::config.partCanvasBg); // canvas->setBg(QPixmap()); //} //else { // canvas->setBg(QPixmap(MusEGlobal::config.canvasBgPixmap)); //} setFont(MusEGlobal::config.fonts[1]); //updateTrackInfo(type); } //--------------------------------------------------------- // songChanged //--------------------------------------------------------- void MidiTrackInfo::songChanged(MusECore::SongChangedFlags_t type) { // Is it simply a midi controller value adjustment? Forget it. if(type == SC_MIDI_CONTROLLER) return; if(type == SC_SELECTION) return; if(!isVisible()) return; updateTrackInfo(type); } //--------------------------------------------------------- // setLabelText //--------------------------------------------------------- void MidiTrackInfo::setLabelText() { MusECore::MidiTrack* track = (MusECore::MidiTrack*)selected; if(track) trackNameLabel->setText(track->name()); else trackNameLabel->setText(QString()); if(track) { QPalette pal; QColor c; if(track->type() == MusECore::Track::DRUM) c = MusEGlobal::config.drumTrackLabelBg; else if (track->type() == MusECore::Track::MIDI) c = MusEGlobal::config.midiTrackLabelBg; else if (track->type() == MusECore::Track::NEW_DRUM) c = MusEGlobal::config.newDrumTrackLabelBg; else printf("THIS SHOULD NEVER HAPPEN: track is not a MIDI track in MidiTrackInfo::setLabelText()!\n"); QLinearGradient gradient(trackNameLabel->geometry().topLeft(), trackNameLabel->geometry().bottomLeft()); gradient.setColorAt(0, c); gradient.setColorAt(0.5, c.lighter()); gradient.setColorAt(1, c); pal.setBrush(trackNameLabel->backgroundRole(), gradient); trackNameLabel->setPalette(pal); } } //--------------------------------------------------------- // setLabelFont //--------------------------------------------------------- void MidiTrackInfo::setLabelFont() { // Use the new font #6 I created just for these labels (so far). // Set the label's font. trackNameLabel->setFont(MusEGlobal::config.fonts[6]); // Dealing with a horizontally constrained label. Ignore vertical. Use a minimum readable point size. MusECore::autoAdjustFontSize(trackNameLabel, trackNameLabel->text(), false, true, MusEGlobal::config.fonts[6].pointSize(), 5); } //--------------------------------------------------------- // iOutputChannelChanged //--------------------------------------------------------- void MidiTrackInfo::iOutputChannelChanged(int channel) { --channel; if(!selected) return; MusECore::MidiTrack* track = (MusECore::MidiTrack*)selected; if (channel != track->outChannel()) { ++_blockHeartbeatCount; MusEGlobal::audio->msgIdle(true); track->setOutChanAndUpdate(channel); MusEGlobal::audio->msgIdle(false); MusEGlobal::audio->msgUpdateSoloStates(); MusEGlobal::song->update(SC_MIDI_TRACK_PROP); --_blockHeartbeatCount; } } //--------------------------------------------------------- // iOutputPortChanged //--------------------------------------------------------- void MidiTrackInfo::iOutputPortChanged(int index) { if(!selected) return; int port_num = iOutput->itemData(index).toInt(); if(port_num < 0 || port_num >= MIDI_PORTS) return; MusECore::MidiTrack* track = (MusECore::MidiTrack*)selected; if (port_num == track->outPort()) return; ++_blockHeartbeatCount; MusEGlobal::audio->msgIdle(true); track->setOutPortAndUpdate(port_num); MusEGlobal::audio->msgIdle(false); MusEGlobal::audio->msgUpdateSoloStates(); MusEGlobal::song->update(SC_MIDI_TRACK_PROP); --_blockHeartbeatCount; } //--------------------------------------------------------- // inRoutesPressed //--------------------------------------------------------- void MidiTrackInfo::inRoutesPressed() { if(!selected) return; if(!selected->isMidiTrack()) return; RoutePopupMenu* pup = new RoutePopupMenu(); pup->exec(QCursor::pos(), selected, false); delete pup; iRButton->setDown(false); } //--------------------------------------------------------- // outRoutesPressed //--------------------------------------------------------- void MidiTrackInfo::outRoutesPressed() { if(!selected) return; if(!selected->isMidiTrack()) return; RoutePopupMenu* pup = new RoutePopupMenu(); pup->exec(QCursor::pos(), selected, true); delete pup; oRButton->setDown(false); } //--------------------------------------------------------- // iProgHBankChanged //--------------------------------------------------------- void MidiTrackInfo::iProgHBankChanged() { if(!selected) return; MusECore::MidiTrack* track = (MusECore::MidiTrack*)selected; int channel = track->outChannel(); int port = track->outPort(); int hbank = iHBank->value(); int lbank = iLBank->value(); int prog = iProgram->value(); if (hbank > 0 && hbank < 129) hbank -= 1; else hbank = 0xff; if (lbank > 0 && lbank < 129) lbank -= 1; else lbank = 0xff; if (prog > 0 && prog < 129) prog -= 1; else prog = 0xff; MusECore::MidiPort* mp = &MusEGlobal::midiPorts[port]; if(prog == 0xff && hbank == 0xff && lbank == 0xff) { program = MusECore::CTRL_VAL_UNKNOWN; ++_blockHeartbeatCount; if(mp->hwCtrlState(channel, MusECore::CTRL_PROGRAM) != MusECore::CTRL_VAL_UNKNOWN) MusEGlobal::audio->msgSetHwCtrlState(mp, channel, MusECore::CTRL_PROGRAM, MusECore::CTRL_VAL_UNKNOWN); --_blockHeartbeatCount; return; } ++_blockHeartbeatCount; int np = mp->hwCtrlState(channel, MusECore::CTRL_PROGRAM); if(np == MusECore::CTRL_VAL_UNKNOWN) { np = mp->lastValidHWCtrlState(channel, MusECore::CTRL_PROGRAM); if(np != MusECore::CTRL_VAL_UNKNOWN) { lbank = (np & 0xff00) >> 8; prog = np & 0xff; if(prog == 0xff) prog = 0; int ilbnk = lbank; int iprog = prog; if(ilbnk == 0xff) ilbnk = -1; ++ilbnk; ++iprog; iLBank->blockSignals(true); iProgram->blockSignals(true); iLBank->setValue(ilbnk); iProgram->setValue(iprog); iLBank->blockSignals(false); iProgram->blockSignals(false); } } if(prog == 0xff && (hbank != 0xff || lbank != 0xff)) { prog = 0; iProgram->blockSignals(true); iProgram->setValue(1); iProgram->blockSignals(false); } program = (hbank << 16) + (lbank << 8) + prog; MusECore::MidiPlayEvent ev(0, port, channel, MusECore::ME_CONTROLLER, MusECore::CTRL_PROGRAM, program); MusEGlobal::audio->msgPlayMidiEvent(&ev); MusECore::MidiInstrument* instr = mp->instrument(); iPatch->setText(instr->getPatchName(channel, program, track->isDrumTrack())); // updateTrackInfo(); --_blockHeartbeatCount; } //--------------------------------------------------------- // iProgLBankChanged //--------------------------------------------------------- void MidiTrackInfo::iProgLBankChanged() { if(!selected) return; MusECore::MidiTrack* track = (MusECore::MidiTrack*)selected; int channel = track->outChannel(); int port = track->outPort(); int hbank = iHBank->value(); int lbank = iLBank->value(); int prog = iProgram->value(); if (hbank > 0 && hbank < 129) hbank -= 1; else hbank = 0xff; if (lbank > 0 && lbank < 129) lbank -= 1; else lbank = 0xff; if (prog > 0 && prog < 129) prog -= 1; else prog = 0xff; MusECore::MidiPort* mp = &MusEGlobal::midiPorts[port]; if(prog == 0xff && hbank == 0xff && lbank == 0xff) { program = MusECore::CTRL_VAL_UNKNOWN; ++_blockHeartbeatCount; if(mp->hwCtrlState(channel, MusECore::CTRL_PROGRAM) != MusECore::CTRL_VAL_UNKNOWN) MusEGlobal::audio->msgSetHwCtrlState(mp, channel, MusECore::CTRL_PROGRAM, MusECore::CTRL_VAL_UNKNOWN); --_blockHeartbeatCount; return; } ++_blockHeartbeatCount; int np = mp->hwCtrlState(channel, MusECore::CTRL_PROGRAM); if(np == MusECore::CTRL_VAL_UNKNOWN) { np = mp->lastValidHWCtrlState(channel, MusECore::CTRL_PROGRAM); if(np != MusECore::CTRL_VAL_UNKNOWN) { hbank = (np & 0xff0000) >> 16; prog = np & 0xff; if(prog == 0xff) prog = 0; int ihbnk = hbank; int iprog = prog; if(ihbnk == 0xff) ihbnk = -1; ++ihbnk; ++iprog; iHBank->blockSignals(true); iProgram->blockSignals(true); iHBank->setValue(ihbnk); iProgram->setValue(iprog); iHBank->blockSignals(false); iProgram->blockSignals(false); } } if(prog == 0xff && (hbank != 0xff || lbank != 0xff)) { prog = 0; iProgram->blockSignals(true); iProgram->setValue(1); iProgram->blockSignals(false); } program = (hbank << 16) + (lbank << 8) + prog; MusECore::MidiPlayEvent ev(0, port, channel, MusECore::ME_CONTROLLER, MusECore::CTRL_PROGRAM, program); MusEGlobal::audio->msgPlayMidiEvent(&ev); MusECore::MidiInstrument* instr = mp->instrument(); iPatch->setText(instr->getPatchName(channel, program, track->isDrumTrack())); // updateTrackInfo(); --_blockHeartbeatCount; } //--------------------------------------------------------- // iProgramChanged //--------------------------------------------------------- void MidiTrackInfo::iProgramChanged() { if(!selected) return; MusECore::MidiTrack* track = (MusECore::MidiTrack*)selected; int channel = track->outChannel(); int port = track->outPort(); int hbank = iHBank->value(); int lbank = iLBank->value(); int prog = iProgram->value(); if (hbank > 0 && hbank < 129) hbank -= 1; else hbank = 0xff; if (lbank > 0 && lbank < 129) lbank -= 1; else lbank = 0xff; if (prog > 0 && prog < 129) prog -= 1; else prog = 0xff; MusECore::MidiPort *mp = &MusEGlobal::midiPorts[port]; if(prog == 0xff) { ++_blockHeartbeatCount; program = MusECore::CTRL_VAL_UNKNOWN; iHBank->blockSignals(true); iLBank->blockSignals(true); iHBank->setValue(0); iLBank->setValue(0); iHBank->blockSignals(false); iLBank->blockSignals(false); if(mp->hwCtrlState(channel, MusECore::CTRL_PROGRAM) != MusECore::CTRL_VAL_UNKNOWN) MusEGlobal::audio->msgSetHwCtrlState(mp, channel, MusECore::CTRL_PROGRAM, MusECore::CTRL_VAL_UNKNOWN); --_blockHeartbeatCount; return; } else { ++_blockHeartbeatCount; int np = mp->hwCtrlState(channel, MusECore::CTRL_PROGRAM); if(np == MusECore::CTRL_VAL_UNKNOWN) { np = mp->lastValidHWCtrlState(channel, MusECore::CTRL_PROGRAM); if(np != MusECore::CTRL_VAL_UNKNOWN) { hbank = (np & 0xff0000) >> 16; lbank = (np & 0xff00) >> 8; int ihbnk = hbank; int ilbnk = lbank; if(ihbnk == 0xff) ihbnk = -1; if(ilbnk == 0xff) ilbnk = -1; ++ihbnk; ++ilbnk; iHBank->blockSignals(true); iLBank->blockSignals(true); iHBank->setValue(ihbnk); iLBank->setValue(ilbnk); iHBank->blockSignals(false); iLBank->blockSignals(false); } } program = (hbank << 16) + (lbank << 8) + prog; MusECore::MidiPlayEvent ev(0, port, channel, MusECore::ME_CONTROLLER, MusECore::CTRL_PROGRAM, program); MusEGlobal::audio->msgPlayMidiEvent(&ev); MusECore::MidiInstrument* instr = mp->instrument(); iPatch->setText(instr->getPatchName(channel, program, track->isDrumTrack())); --_blockHeartbeatCount; } // updateTrackInfo(); } //--------------------------------------------------------- // iLautstChanged //--------------------------------------------------------- void MidiTrackInfo::iLautstChanged(int val) { if(!selected) return; MusECore::MidiTrack* track = (MusECore::MidiTrack*)selected; int outPort = track->outPort(); int chan = track->outChannel(); MusECore::MidiPort* mp = &MusEGlobal::midiPorts[outPort]; MusECore::MidiController* mctl = mp->midiController(MusECore::CTRL_VOLUME); if((val < mctl->minVal()) || (val > mctl->maxVal())) { if(mp->hwCtrlState(chan, MusECore::CTRL_VOLUME) != MusECore::CTRL_VAL_UNKNOWN) MusEGlobal::audio->msgSetHwCtrlState(mp, chan, MusECore::CTRL_VOLUME, MusECore::CTRL_VAL_UNKNOWN); } else { val += mctl->bias(); MusECore::MidiPlayEvent ev(0, outPort, chan, MusECore::ME_CONTROLLER, MusECore::CTRL_VOLUME, val); MusEGlobal::audio->msgPlayMidiEvent(&ev); } MusEGlobal::song->update(SC_MIDI_CONTROLLER); } //--------------------------------------------------------- // iTranspChanged //--------------------------------------------------------- void MidiTrackInfo::iTranspChanged(int val) { if(!selected) return; MusECore::MidiTrack* track = (MusECore::MidiTrack*)selected; track->transposition = val; MusEGlobal::song->update(SC_MIDI_TRACK_PROP); } //--------------------------------------------------------- // iAnschlChanged //--------------------------------------------------------- void MidiTrackInfo::iAnschlChanged(int val) { if(!selected) return; MusECore::MidiTrack* track = (MusECore::MidiTrack*)selected; track->velocity = val; MusEGlobal::song->update(SC_MIDI_TRACK_PROP); } //--------------------------------------------------------- // iVerzChanged //--------------------------------------------------------- void MidiTrackInfo::iVerzChanged(int val) { if(!selected) return; MusECore::MidiTrack* track = (MusECore::MidiTrack*)selected; track->delay = val; MusEGlobal::song->update(SC_MIDI_TRACK_PROP); } //--------------------------------------------------------- // iLenChanged //--------------------------------------------------------- void MidiTrackInfo::iLenChanged(int val) { if(!selected) return; MusECore::MidiTrack* track = (MusECore::MidiTrack*)selected; track->len = val; MusEGlobal::song->update(SC_MIDI_TRACK_PROP); } //--------------------------------------------------------- // iKomprChanged //--------------------------------------------------------- void MidiTrackInfo::iKomprChanged(int val) { if(!selected) return; MusECore::MidiTrack* track = (MusECore::MidiTrack*)selected; track->compression = val; MusEGlobal::song->update(SC_MIDI_TRACK_PROP); } //--------------------------------------------------------- // iPanChanged //--------------------------------------------------------- void MidiTrackInfo::iPanChanged(int val) { if(!selected) return; MusECore::MidiTrack* track = (MusECore::MidiTrack*)selected; int port = track->outPort(); int chan = track->outChannel(); MusECore::MidiPort* mp = &MusEGlobal::midiPorts[port]; MusECore::MidiController* mctl = mp->midiController(MusECore::CTRL_PANPOT); if((val < mctl->minVal()) || (val > mctl->maxVal())) { if(mp->hwCtrlState(chan, MusECore::CTRL_PANPOT) != MusECore::CTRL_VAL_UNKNOWN) MusEGlobal::audio->msgSetHwCtrlState(mp, chan, MusECore::CTRL_PANPOT, MusECore::CTRL_VAL_UNKNOWN); } else { val += mctl->bias(); // Realtime Change: MusECore::MidiPlayEvent ev(0, port, chan, MusECore::ME_CONTROLLER, MusECore::CTRL_PANPOT, val); MusEGlobal::audio->msgPlayMidiEvent(&ev); } MusEGlobal::song->update(SC_MIDI_CONTROLLER); } //--------------------------------------------------------- // patchPopupActivated //--------------------------------------------------------- void MidiTrackInfo::patchPopupActivated(QAction* act) { if(act && selected) { int rv = act->data().toInt(); if(rv != -1) { MusECore::MidiTrack* track = (MusECore::MidiTrack*)selected; int channel = track->outChannel(); int port = track->outPort(); ++_blockHeartbeatCount; MusECore::MidiPlayEvent ev(0, port, channel, MusECore::ME_CONTROLLER, MusECore::CTRL_PROGRAM, rv); MusEGlobal::audio->msgPlayMidiEvent(&ev); updateTrackInfo(-1); --_blockHeartbeatCount; } } } //--------------------------------------------------------- // instrPopup //--------------------------------------------------------- void MidiTrackInfo::instrPopup() { if(!selected) return; MusECore::MidiTrack* track = static_cast(selected); int port = track->outPort(); MusECore::MidiInstrument* instr = MusEGlobal::midiPorts[port].instrument(); PopupMenu* pup = new PopupMenu(false); MusECore::MidiInstrument::populateInstrPopup(pup, instr, false); if(pup->actions().count() == 0) { delete pup; return; } QAction *act = pup->exec(instrPushButton->mapToGlobal(QPoint(10,5))); if(act) { QString s = act->text(); for (MusECore::iMidiInstrument i = MusECore::midiInstruments.begin(); i != MusECore::midiInstruments.end(); ++i) { if((*i)->iname() == s) { MusEGlobal::midiPorts[port].setInstrument(*i); // Make sure device initializations are sent if necessary. MusEGlobal::audio->msgInitMidiDevices(false); // false = Don't force MusEGlobal::song->update(); break; } } } delete pup; } //--------------------------------------------------------- // patchPopup //--------------------------------------------------------- void MidiTrackInfo::patchPopup() { if(!selected) return; MusECore::MidiTrack* track = (MusECore::MidiTrack*)selected; int channel = track->outChannel(); int port = track->outPort(); MusECore::MidiInstrument* instr = MusEGlobal::midiPorts[port].instrument(); PopupMenu* pup = new PopupMenu(true); instr->populatePatchPopup(pup, channel, track->isDrumTrack()); if(pup->actions().count() == 0) { delete pup; return; } connect(pup, SIGNAL(triggered(QAction*)), SLOT(patchPopupActivated(QAction*))); QAction *act = pup->exec(iPatch->mapToGlobal(QPoint(10,5))); if(act) { int rv = act->data().toInt(); if(rv != -1) { ++_blockHeartbeatCount; MusECore::MidiPlayEvent ev(0, port, channel, MusECore::ME_CONTROLLER, MusECore::CTRL_PROGRAM, rv); MusEGlobal::audio->msgPlayMidiEvent(&ev); updateTrackInfo(-1); --_blockHeartbeatCount; } } delete pup; } //--------------------------------------------------------- // recEchoToggled //--------------------------------------------------------- void MidiTrackInfo::recEchoToggled(bool v) { if(!selected) return; MusECore::MidiTrack* track = (MusECore::MidiTrack*)selected; track->setRecEcho(v); MusEGlobal::song->update(SC_MIDI_TRACK_PROP); } //--------------------------------------------------------- // iProgHBankDoubleCLicked //--------------------------------------------------------- void MidiTrackInfo::iProgHBankDoubleCLicked() { if(!selected) return; MusECore::MidiTrack* track = (MusECore::MidiTrack*)selected; int port = track->outPort(); int chan = track->outChannel(); MusECore::MidiPort* mp = &MusEGlobal::midiPorts[port]; MusECore::MidiController* mctl = mp->midiController(MusECore::CTRL_PROGRAM); if(!track || !mctl) return; int lastv = mp->lastValidHWCtrlState(chan, MusECore::CTRL_PROGRAM); int curv = mp->hwCtrlState(chan, MusECore::CTRL_PROGRAM); if(curv == MusECore::CTRL_VAL_UNKNOWN) { // If no value has ever been set yet, use the current knob value // (or the controller's initial value?) to 'turn on' the controller. if(lastv == MusECore::CTRL_VAL_UNKNOWN) { int kiv = mctl->initVal(); if(kiv == MusECore::CTRL_VAL_UNKNOWN) kiv = 0; ++_blockHeartbeatCount; MusECore::MidiPlayEvent ev(0, port, chan, MusECore::ME_CONTROLLER, MusECore::CTRL_PROGRAM, kiv); MusEGlobal::audio->msgPlayMidiEvent(&ev); --_blockHeartbeatCount; } else { // TODO // int hbank = (lastv >> 16) & 0xff; // if(hbank == 0xff) // lastv &= 0xffff; // else // lastv |= 0xff0000; ++_blockHeartbeatCount; MusECore::MidiPlayEvent ev(0, port, chan, MusECore::ME_CONTROLLER, MusECore::CTRL_PROGRAM, lastv); MusEGlobal::audio->msgPlayMidiEvent(&ev); --_blockHeartbeatCount; } } else { // TODO // int lasthb = 0xff; // if(lastv != MusECore::CTRL_VAL_UNKNOWN) // lasthb = (lastv >> 16) & 0xff; // // int hbank = (curv >> 16) & 0xff; // if(hbank == 0xff) // { // curv &= 0xffff; // if(lasthb != 0xff) // curv |= lasthb; // } // else // curv |= 0xff0000; if(mp->hwCtrlState(chan, MusECore::CTRL_PROGRAM) != MusECore::CTRL_VAL_UNKNOWN) { ++_blockHeartbeatCount; MusEGlobal::audio->msgSetHwCtrlState(mp, chan, MusECore::CTRL_PROGRAM, MusECore::CTRL_VAL_UNKNOWN); --_blockHeartbeatCount; } } MusEGlobal::song->update(SC_MIDI_CONTROLLER); } //--------------------------------------------------------- // iProgLBankDoubleCLicked //--------------------------------------------------------- void MidiTrackInfo::iProgLBankDoubleCLicked() { if(!selected) return; MusECore::MidiTrack* track = (MusECore::MidiTrack*)selected; int port = track->outPort(); int chan = track->outChannel(); MusECore::MidiPort* mp = &MusEGlobal::midiPorts[port]; MusECore::MidiController* mctl = mp->midiController(MusECore::CTRL_PROGRAM); if(!track || !mctl) return; int lastv = mp->lastValidHWCtrlState(chan, MusECore::CTRL_PROGRAM); int curv = mp->hwCtrlState(chan, MusECore::CTRL_PROGRAM); if(curv == MusECore::CTRL_VAL_UNKNOWN) { // If no value has ever been set yet, use the current knob value // (or the controller's initial value?) to 'turn on' the controller. if(lastv == MusECore::CTRL_VAL_UNKNOWN) { int kiv = mctl->initVal(); if(kiv == MusECore::CTRL_VAL_UNKNOWN) kiv = 0xff0000; //MusECore::MidiPlayEvent ev(0, port, chan, MusECore::ME_CONTROLLER, num, kiv); MusECore::MidiPlayEvent ev(0, port, chan, MusECore::ME_CONTROLLER, MusECore::CTRL_PROGRAM, kiv); MusEGlobal::audio->msgPlayMidiEvent(&ev); } else { // TODO // int lbank = (lastv >> 8) & 0xff; // if(lbank == 0xff) // lastv &= 0xff00ff; // else // { // lastv |= 0xffff00; // //int hbank = (lastv >> 16) & 0xff; // //if(hbank != 0xff) // // lastv |= 0xff0000; // } MusECore::MidiPlayEvent ev(0, port, chan, MusECore::ME_CONTROLLER, MusECore::CTRL_PROGRAM, lastv); MusEGlobal::audio->msgPlayMidiEvent(&ev); } } else { // TODO // //int lasthb = 0xff; // int lastlb = 0xff; // if(lastv != MusECore::CTRL_VAL_UNKNOWN) // { // //lasthb = (lastv >> 16) & 0xff; // lastlb = (lastv >> 8) & 0xff; // } // // int lbank = (curv >> 8) & 0xff; // if(lbank == 0xff) // { // curv &= 0xff00ff; // if(lastlb != 0xff) // curv |= lastlb; // } // else // { // curv |= 0xffff00; // //int hbank = (curv >> 16) & 0xff; // //if(hbank != 0xff) // // curv |= 0xff0000; // } if(mp->hwCtrlState(chan, MusECore::CTRL_PROGRAM) != MusECore::CTRL_VAL_UNKNOWN) MusEGlobal::audio->msgSetHwCtrlState(mp, chan, MusECore::CTRL_PROGRAM, MusECore::CTRL_VAL_UNKNOWN); // MusECore::MidiPlayEvent ev(0, port, chan, MusECore::ME_CONTROLLER, MusECore::CTRL_PROGRAM, curv); // MusEGlobal::audio->msgPlayMidiEvent(&ev); } MusEGlobal::song->update(SC_MIDI_CONTROLLER); } //--------------------------------------------------------- // iProgramDoubleClicked //--------------------------------------------------------- void MidiTrackInfo::iProgramDoubleClicked() { if(!selected) return; MusECore::MidiTrack* track = (MusECore::MidiTrack*)selected; int port = track->outPort(); int chan = track->outChannel(); MusECore::MidiPort* mp = &MusEGlobal::midiPorts[port]; MusECore::MidiController* mctl = mp->midiController(MusECore::CTRL_PROGRAM); if(!track || !mctl) return; int lastv = mp->lastValidHWCtrlState(chan, MusECore::CTRL_PROGRAM); int curv = mp->hwCtrlState(chan, MusECore::CTRL_PROGRAM); if(curv == MusECore::CTRL_VAL_UNKNOWN) { // If no value has ever been set yet, use the current knob value // (or the controller's initial value?) to 'turn on' the controller. if(lastv == MusECore::CTRL_VAL_UNKNOWN) { int kiv = mctl->initVal(); if(kiv == MusECore::CTRL_VAL_UNKNOWN) kiv = 0xffff00; MusECore::MidiPlayEvent ev(0, port, chan, MusECore::ME_CONTROLLER, MusECore::CTRL_PROGRAM, kiv); MusEGlobal::audio->msgPlayMidiEvent(&ev); } else { MusECore::MidiPlayEvent ev(0, port, chan, MusECore::ME_CONTROLLER, MusECore::CTRL_PROGRAM, lastv); MusEGlobal::audio->msgPlayMidiEvent(&ev); } } else { if(mp->hwCtrlState(chan, MusECore::CTRL_PROGRAM) != MusECore::CTRL_VAL_UNKNOWN) MusEGlobal::audio->msgSetHwCtrlState(mp, chan, MusECore::CTRL_PROGRAM, MusECore::CTRL_VAL_UNKNOWN); } MusEGlobal::song->update(SC_MIDI_CONTROLLER); } //--------------------------------------------------------- // iLautstDoubleClicked //--------------------------------------------------------- void MidiTrackInfo::iLautstDoubleClicked() { if(!selected) return; MusECore::MidiTrack* track = (MusECore::MidiTrack*)selected; int port = track->outPort(); int chan = track->outChannel(); MusECore::MidiPort* mp = &MusEGlobal::midiPorts[port]; MusECore::MidiController* mctl = mp->midiController(MusECore::CTRL_VOLUME); if(!track || !mctl) return; int lastv = mp->lastValidHWCtrlState(chan, MusECore::CTRL_VOLUME); int curv = mp->hwCtrlState(chan, MusECore::CTRL_VOLUME); if(curv == MusECore::CTRL_VAL_UNKNOWN) { // If no value has ever been set yet, use the current knob value // (or the controller's initial value?) to 'turn on' the controller. if(lastv == MusECore::CTRL_VAL_UNKNOWN) { int kiv = mctl->initVal(); if(kiv == MusECore::CTRL_VAL_UNKNOWN) // Set volume to 78% of range, so that if range is 0 - 127, then value is 100. kiv = lround(double(mctl->maxVal() - mctl->minVal()) * 0.7874); else { if(kiv < mctl->minVal()) kiv = mctl->minVal(); if(kiv > mctl->maxVal()) kiv = mctl->maxVal(); kiv += mctl->bias(); } MusECore::MidiPlayEvent ev(0, port, chan, MusECore::ME_CONTROLLER, MusECore::CTRL_VOLUME, kiv); MusEGlobal::audio->msgPlayMidiEvent(&ev); } else { MusECore::MidiPlayEvent ev(0, port, chan, MusECore::ME_CONTROLLER, MusECore::CTRL_VOLUME, lastv); MusEGlobal::audio->msgPlayMidiEvent(&ev); } } else { if(mp->hwCtrlState(chan, MusECore::CTRL_VOLUME) != MusECore::CTRL_VAL_UNKNOWN) MusEGlobal::audio->msgSetHwCtrlState(mp, chan, MusECore::CTRL_VOLUME, MusECore::CTRL_VAL_UNKNOWN); } MusEGlobal::song->update(SC_MIDI_CONTROLLER); } //--------------------------------------------------------- // iPanDoubleClicked //--------------------------------------------------------- void MidiTrackInfo::iPanDoubleClicked() { if(!selected) return; MusECore::MidiTrack* track = (MusECore::MidiTrack*)selected; int port = track->outPort(); int chan = track->outChannel(); MusECore::MidiPort* mp = &MusEGlobal::midiPorts[port]; MusECore::MidiController* mctl = mp->midiController(MusECore::CTRL_PANPOT); if(!track || !mctl) return; int lastv = mp->lastValidHWCtrlState(chan, MusECore::CTRL_PANPOT); int curv = mp->hwCtrlState(chan, MusECore::CTRL_PANPOT); if(curv == MusECore::CTRL_VAL_UNKNOWN) { // If no value has ever been set yet, use the current knob value // (or the controller's initial value?) to 'turn on' the controller. if(lastv == MusECore::CTRL_VAL_UNKNOWN) { int kiv = mctl->initVal(); if(kiv == MusECore::CTRL_VAL_UNKNOWN) // Set volume to 50% of range, so that if range is 0 - 127, then value is 64. kiv = lround(double(mctl->maxVal() - mctl->minVal()) * 0.5); else { if(kiv < mctl->minVal()) kiv = mctl->minVal(); if(kiv > mctl->maxVal()) kiv = mctl->maxVal(); kiv += mctl->bias(); } MusECore::MidiPlayEvent ev(0, port, chan, MusECore::ME_CONTROLLER, MusECore::CTRL_PANPOT, kiv); MusEGlobal::audio->msgPlayMidiEvent(&ev); } else { MusECore::MidiPlayEvent ev(0, port, chan, MusECore::ME_CONTROLLER, MusECore::CTRL_PANPOT, lastv); MusEGlobal::audio->msgPlayMidiEvent(&ev); } } else { if(mp->hwCtrlState(chan, MusECore::CTRL_PANPOT) != MusECore::CTRL_VAL_UNKNOWN) MusEGlobal::audio->msgSetHwCtrlState(mp, chan, MusECore::CTRL_PANPOT, MusECore::CTRL_VAL_UNKNOWN); } MusEGlobal::song->update(SC_MIDI_CONTROLLER); } //--------------------------------------------------------- // updateTrackInfo //--------------------------------------------------------- void MidiTrackInfo::updateTrackInfo(MusECore::SongChangedFlags_t flags) { // Is it simply a midi controller value adjustment? Forget it. if(flags == SC_MIDI_CONTROLLER) return; if(flags == SC_SELECTION) return; if(!selected) return; MusECore::MidiTrack* track = (MusECore::MidiTrack*)selected; ++_blockHeartbeatCount; setLabelText(); setLabelFont(); if(flags & (SC_MIDI_TRACK_PROP)) { iTransp->blockSignals(true); iAnschl->blockSignals(true); iVerz->blockSignals(true); iLen->blockSignals(true); iKompr->blockSignals(true); iTransp->setValue(track->transposition); iAnschl->setValue(track->velocity); iVerz->setValue(track->delay); iLen->setValue(track->len); iKompr->setValue(track->compression); iTransp->blockSignals(false); iAnschl->blockSignals(false); iVerz->blockSignals(false); iLen->blockSignals(false); iKompr->blockSignals(false); int outChannel = track->outChannel(); int outPort = track->outPort(); iOutput->blockSignals(true); iOutput->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) && (i != outPort)) // Only writeable ports, or current one. continue; QString name; name.sprintf("%d:%s", i+1, MusEGlobal::midiPorts[i].portname().toLatin1().constData()); iOutput->insertItem(item_idx, name, i); if (i == outPort) iOutput->setCurrentIndex(item_idx); item_idx++; } iOutput->blockSignals(false); MusECore::MidiInstrument* minstr = MusEGlobal::midiPorts[outPort].instrument(); if(minstr) { instrPushButton->setText(minstr->iname()); if(minstr->isSynti()) instrPushButton->setEnabled(false); else instrPushButton->setEnabled(true); } else instrPushButton->setText(tr("")); iOutputChannel->blockSignals(true); iOutputChannel->setValue(outChannel+1); iOutputChannel->blockSignals(false); // Set record echo. if(recEchoButton->isChecked() != track->recEcho()) { recEchoButton->blockSignals(true); recEchoButton->setChecked(track->recEcho()); recEchoButton->blockSignals(false); } recEchoButton->setIcon(track->recEcho() ? QIcon(*midiThruOnIcon) : QIcon(*midiThruOffIcon)); } int outChannel = track->outChannel(); int outPort = track->outPort(); MusECore::MidiPort* mp = &MusEGlobal::midiPorts[outPort]; int nprogram = mp->hwCtrlState(outChannel, MusECore::CTRL_PROGRAM); if(nprogram == MusECore::CTRL_VAL_UNKNOWN) { iHBank->blockSignals(true); iLBank->blockSignals(true); iProgram->blockSignals(true); iHBank->setValue(0); iLBank->setValue(0); iProgram->setValue(0); iHBank->blockSignals(false); iLBank->blockSignals(false); iProgram->blockSignals(false); program = MusECore::CTRL_VAL_UNKNOWN; nprogram = mp->lastValidHWCtrlState(outChannel, MusECore::CTRL_PROGRAM); if(nprogram == MusECore::CTRL_VAL_UNKNOWN) iPatch->setText(tr("")); else { MusECore::MidiInstrument* instr = mp->instrument(); iPatch->setText(instr->getPatchName(outChannel, nprogram, track->isDrumTrack())); } } else { program = nprogram; MusECore::MidiInstrument* instr = mp->instrument(); iPatch->setText(instr->getPatchName(outChannel, program, track->isDrumTrack())); int hb = ((program >> 16) & 0xff) + 1; if (hb == 0x100) hb = 0; int lb = ((program >> 8) & 0xff) + 1; if (lb == 0x100) lb = 0; int pr = (program & 0xff) + 1; if (pr == 0x100) pr = 0; iHBank->blockSignals(true); iLBank->blockSignals(true); iProgram->blockSignals(true); iHBank->setValue(hb); iLBank->setValue(lb); iProgram->setValue(pr); iHBank->blockSignals(false); iLBank->blockSignals(false); iProgram->blockSignals(false); } MusECore::MidiController* mc = mp->midiController(MusECore::CTRL_VOLUME); int mn = mc->minVal(); int v = mp->hwCtrlState(outChannel, MusECore::CTRL_VOLUME); volume = v; if(v == MusECore::CTRL_VAL_UNKNOWN) v = mn - 1; else // Auto bias... v -= mc->bias(); iLautst->blockSignals(true); iLautst->setRange(mn - 1, mc->maxVal()); iLautst->setValue(v); iLautst->blockSignals(false); mc = mp->midiController(MusECore::CTRL_PANPOT); mn = mc->minVal(); v = mp->hwCtrlState(outChannel, MusECore::CTRL_PANPOT); pan = v; if(v == MusECore::CTRL_VAL_UNKNOWN) v = mn - 1; else // Auto bias... v -= mc->bias(); iPan->blockSignals(true); iPan->setRange(mn - 1, mc->maxVal()); iPan->setValue(v); iPan->blockSignals(false); --_blockHeartbeatCount; } //--------------------------------------------------------- // progRecClicked //--------------------------------------------------------- void MidiTrackInfo::progRecClicked() { if(!selected) return; MusECore::MidiTrack* track = (MusECore::MidiTrack*)selected; int portno = track->outPort(); int channel = track->outChannel(); MusECore::MidiPort* port = &MusEGlobal::midiPorts[portno]; int program = port->hwCtrlState(channel, MusECore::CTRL_PROGRAM); if(program == MusECore::CTRL_VAL_UNKNOWN || program == 0xffffff) return; unsigned tick = MusEGlobal::song->cpos(); MusECore::Event a(MusECore::Controller); a.setTick(tick); a.setA(MusECore::CTRL_PROGRAM); a.setB(program); MusEGlobal::song->recordEvent(track, a); } //--------------------------------------------------------- // volRecClicked //--------------------------------------------------------- void MidiTrackInfo::volRecClicked() { if(!selected) return; MusECore::MidiTrack* track = (MusECore::MidiTrack*)selected; int portno = track->outPort(); int channel = track->outChannel(); MusECore::MidiPort* port = &MusEGlobal::midiPorts[portno]; int volume = port->hwCtrlState(channel, MusECore::CTRL_VOLUME); if(volume == MusECore::CTRL_VAL_UNKNOWN) return; unsigned tick = MusEGlobal::song->cpos(); MusECore::Event a(MusECore::Controller); a.setTick(tick); a.setA(MusECore::CTRL_VOLUME); a.setB(volume); MusEGlobal::song->recordEvent(track, a); } //--------------------------------------------------------- // panRecClicked //--------------------------------------------------------- void MidiTrackInfo::panRecClicked() { if(!selected) return; MusECore::MidiTrack* track = (MusECore::MidiTrack*)selected; int portno = track->outPort(); int channel = track->outChannel(); MusECore::MidiPort* port = &MusEGlobal::midiPorts[portno]; int pan = port->hwCtrlState(channel, MusECore::CTRL_PANPOT); if(pan == MusECore::CTRL_VAL_UNKNOWN) return; unsigned tick = MusEGlobal::song->cpos(); MusECore::Event a(MusECore::Controller); a.setTick(tick); a.setA(MusECore::CTRL_PANPOT); a.setB(pan); MusEGlobal::song->recordEvent(track, a); } //--------------------------------------------------------- // recordClicked //--------------------------------------------------------- void MidiTrackInfo::recordClicked() { if(!selected) return; MusECore::MidiTrack* track = (MusECore::MidiTrack*)selected; int portno = track->outPort(); int channel = track->outChannel(); MusECore::MidiPort* port = &MusEGlobal::midiPorts[portno]; unsigned tick = MusEGlobal::song->cpos(); int program = port->hwCtrlState(channel, MusECore::CTRL_PROGRAM); if(program != MusECore::CTRL_VAL_UNKNOWN && program != 0xffffff) { MusECore::Event a(MusECore::Controller); a.setTick(tick); a.setA(MusECore::CTRL_PROGRAM); a.setB(program); MusEGlobal::song->recordEvent(track, a); } int volume = port->hwCtrlState(channel, MusECore::CTRL_VOLUME); if(volume != MusECore::CTRL_VAL_UNKNOWN) { MusECore::Event a(MusECore::Controller); a.setTick(tick); a.setA(MusECore::CTRL_VOLUME); a.setB(volume); MusEGlobal::song->recordEvent(track, a); } int pan = port->hwCtrlState(channel, MusECore::CTRL_PANPOT); if(pan != MusECore::CTRL_VAL_UNKNOWN) { MusECore::Event a(MusECore::Controller); a.setTick(tick); a.setA(MusECore::CTRL_PANPOT); a.setB(pan); MusEGlobal::song->recordEvent(track, a); } } void MidiTrackInfo::resizeEvent(QResizeEvent* ev) { QWidget::resizeEvent(ev); setLabelText(); setLabelFont(); } } // namespace MusEGui