//========================================================= // MusE // Linux Music Editor // $Id: mstrip.cpp,v 1.9.2.13 2009/11/14 03:37:48 terminator356 Exp $ // // (C) Copyright 2000-2004 Werner Schweer (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 #include #include //#include #include #include #include #include "app.h" #include "midi.h" #include "midictrl.h" #include "mstrip.h" #include "midiport.h" #include "globals.h" #include "audio.h" #include "song.h" #include "slider.h" #include "knob.h" #include "combobox.h" #include "meter.h" #include "track.h" #include "doublelabel.h" #include "rack.h" #include "node.h" #include "amixer.h" #include "icons.h" #include "gconfig.h" #include "ttoolbutton.h" //#include "utils.h" //#include "popupmenu.h" #include "routepopup.h" namespace MusEGui { enum { KNOB_PAN, KNOB_VAR_SEND, KNOB_REV_SEND, KNOB_CHO_SEND }; //--------------------------------------------------------- // addKnob //--------------------------------------------------------- void MidiStrip::addKnob(int idx, const QString& tt, const QString& label, const char* slot, bool enabled) { int ctl = MusECore::CTRL_PANPOT, mn, mx, v; int chan = ((MusECore::MidiTrack*)track)->outChannel(); switch(idx) { //case KNOB_PAN: // ctl = MusECore::CTRL_PANPOT; //break; case KNOB_VAR_SEND: ctl = MusECore::CTRL_VARIATION_SEND; break; case KNOB_REV_SEND: ctl = MusECore::CTRL_REVERB_SEND; break; case KNOB_CHO_SEND: ctl = MusECore::CTRL_CHORUS_SEND; break; } MusECore::MidiPort* mp = &MusEGlobal::midiPorts[((MusECore::MidiTrack*)track)->outPort()]; MusECore::MidiController* mc = mp->midiController(ctl); mn = mc->minVal(); mx = mc->maxVal(); MusEGui::Knob* knob = new MusEGui::Knob(this); knob->setRange(double(mn), double(mx), 1.0); knob->setId(ctl); controller[idx].knob = knob; knob->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum)); knob->setBackgroundRole(QPalette::Mid); knob->setToolTip(tt); knob->setEnabled(enabled); MusEGui::DoubleLabel* dl = new MusEGui::DoubleLabel(0.0, double(mn), double(mx), this); dl->setId(idx); dl->setSpecialText(tr("off")); dl->setToolTip(tr("ctrl-double-click on/off")); controller[idx].dl = dl; ///dl->setFont(MusEGlobal::config.fonts[1]); dl->setBackgroundRole(QPalette::Mid); dl->setFrame(true); dl->setPrecision(0); dl->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum)); dl->setEnabled(enabled); double dlv; v = mp->hwCtrlState(chan, ctl); if(v == MusECore::CTRL_VAL_UNKNOWN) { //v = mc->initVal(); //if(v == MusECore::CTRL_VAL_UNKNOWN) // v = 0; // v = mn - 1; int lastv = mp->lastValidHWCtrlState(chan, ctl); if(lastv == MusECore::CTRL_VAL_UNKNOWN) { if(mc->initVal() == MusECore::CTRL_VAL_UNKNOWN) v = 0; else v = mc->initVal(); } else v = lastv - mc->bias(); //dlv = mn - 1; dlv = dl->off() - 1.0; } else { // Auto bias... v -= mc->bias(); dlv = double(v); } knob->setValue(double(v)); dl->setValue(dlv); //} //else // knob->setRange(0.0, 127.0); QLabel* lb = new QLabel(label, this); controller[idx].lb = lb; ///lb->setFont(MusEGlobal::config.fonts[1]); lb->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum)); lb->setAlignment(Qt::AlignCenter); lb->setEnabled(enabled); grid->addWidget(lb, _curGridRow, 0); grid->addWidget(dl, _curGridRow+1, 0); grid->addWidget(knob, _curGridRow, 1, 2, 1); _curGridRow += 2; connect(knob, SIGNAL(sliderMoved(double,int)), slot); connect(knob, SIGNAL(sliderRightClicked(const QPoint &, int)), SLOT(controlRightClicked(const QPoint &, int))); connect(dl, SIGNAL(valueChanged(double, int)), slot); connect(dl, SIGNAL(ctrlDoubleClicked(int)), SLOT(labelDoubleClicked(int))); } //--------------------------------------------------------- // MidiStrip //--------------------------------------------------------- MidiStrip::MidiStrip(QWidget* parent, MusECore::MidiTrack* t) : Strip(parent, t) { inHeartBeat = true; // Set the whole strip's font, except for the label. p4.0.45 setFont(MusEGlobal::config.fonts[1]); // Clear so the meters don't start off by showing stale values. t->setActivity(0); t->setLastActivity(0); volume = MusECore::CTRL_VAL_UNKNOWN; pan = MusECore::CTRL_VAL_UNKNOWN; variSend = MusECore::CTRL_VAL_UNKNOWN; chorusSend = MusECore::CTRL_VAL_UNKNOWN; reverbSend = MusECore::CTRL_VAL_UNKNOWN; addKnob(KNOB_VAR_SEND, tr("VariationSend"), tr("Var"), SLOT(setVariSend(double)), false); addKnob(KNOB_REV_SEND, tr("ReverbSend"), tr("Rev"), SLOT(setReverbSend(double)), false); addKnob(KNOB_CHO_SEND, tr("ChorusSend"), tr("Cho"), SLOT(setChorusSend(double)), false); ///int auxsSize = MusEGlobal::song->auxs()->size(); ///if (auxsSize) //layout->addSpacing((STRIP_WIDTH/2 + 1) * auxsSize); ///grid->addSpacing((STRIP_WIDTH/2 + 1) * auxsSize); // ?? //--------------------------------------------------- // slider, label, meter //--------------------------------------------------- MusECore::MidiPort* mp = &MusEGlobal::midiPorts[t->outPort()]; MusECore::MidiController* mc = mp->midiController(MusECore::CTRL_VOLUME); int chan = t->outChannel(); int mn = mc->minVal(); int mx = mc->maxVal(); slider = new MusEGui::Slider(this, "vol", Qt::Vertical, MusEGui::Slider::None, QColor(100, 255, 100)); slider->setCursorHoming(true); slider->setRange(double(mn), double(mx), 1.0); slider->setFixedWidth(20); ///slider->setFont(MusEGlobal::config.fonts[1]); slider->setId(MusECore::CTRL_VOLUME); meter[0] = new MusEGui::Meter(this, MusEGui::Meter::LinMeter); meter[0]->setRange(0, 127.0); meter[0]->setFixedWidth(15); connect(meter[0], SIGNAL(mousePress()), this, SLOT(resetPeaks())); sliderGrid = new QGridLayout(); sliderGrid->setRowStretch(0, 100); sliderGrid->addWidget(slider, 0, 0, Qt::AlignHCenter); sliderGrid->addWidget(meter[0], 0, 1, Qt::AlignHCenter); grid->addLayout(sliderGrid, _curGridRow++, 0, 1, 2); sl = new MusEGui::DoubleLabel(0.0, -98.0, 0.0, this); ///sl->setFont(MusEGlobal::config.fonts[1]); sl->setBackgroundRole(QPalette::Mid); sl->setSpecialText(tr("off")); sl->setSuffix(tr("dB")); sl->setToolTip(tr("ctrl-double-click on/off")); sl->setFrame(true); sl->setPrecision(0); sl->setSizePolicy(QSizePolicy(QSizePolicy::Maximum, QSizePolicy::Minimum)); // Set the label's slider 'buddy'. sl->setSlider(slider); double dlv; int v = mp->hwCtrlState(chan, MusECore::CTRL_VOLUME); if(v == MusECore::CTRL_VAL_UNKNOWN) { int lastv = mp->lastValidHWCtrlState(chan, MusECore::CTRL_VOLUME); if(lastv == MusECore::CTRL_VAL_UNKNOWN) { if(mc->initVal() == MusECore::CTRL_VAL_UNKNOWN) v = 0; else v = mc->initVal(); } else v = lastv - mc->bias(); dlv = sl->off() - 1.0; } else { if(v == 0) dlv = sl->minValue() - 0.5 * (sl->minValue() - sl->off()); else { dlv = -MusECore::fast_log10(float(127*127)/float(v*v))*20.0; if(dlv > sl->maxValue()) dlv = sl->maxValue(); } // Auto bias... v -= mc->bias(); } slider->setValue(double(v)); sl->setValue(dlv); // connect(sl, SIGNAL(valueChanged(double,int)), slider, SLOT(setValue(double))); // connect(slider, SIGNAL(valueChanged(double,int)), sl, SLOT(setValue(double))); connect(slider, SIGNAL(sliderMoved(double,int)), SLOT(setVolume(double))); connect(slider, SIGNAL(sliderRightClicked(const QPoint &, int)), SLOT(controlRightClicked(const QPoint &, int))); connect(sl, SIGNAL(valueChanged(double, int)), SLOT(volLabelChanged(double))); connect(sl, SIGNAL(ctrlDoubleClicked(int)), SLOT(labelDoubleClicked(int))); grid->addWidget(sl, _curGridRow++, 0, 1, 2, Qt::AlignCenter); //--------------------------------------------------- // pan, balance //--------------------------------------------------- addKnob(KNOB_PAN, tr("Pan/Balance"), tr("Pan"), SLOT(setPan(double)), true); updateControls(); //--------------------------------------------------- // mute, solo // or // record, mixdownfile //--------------------------------------------------- record = new MusEGui::TransparentToolButton(this); record->setFocusPolicy(Qt::NoFocus); record->setBackgroundRole(QPalette::Mid); record->setCheckable(true); record->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum)); record->setToolTip(tr("record")); record->setChecked(track->recordFlag()); record->setIcon(track->recordFlag() ? QIcon(*record_on_Icon) : QIcon(*record_off_Icon)); ///record->setIconSize(record_on_Icon->size()); connect(record, SIGNAL(clicked(bool)), SLOT(recordToggled(bool))); mute = new QToolButton(); mute->setFocusPolicy(Qt::NoFocus); mute->setCheckable(true); mute->setToolTip(tr("mute")); mute->setChecked(track->mute()); mute->setIcon(track->mute() ? QIcon(*muteIconOff) : QIcon(*muteIconOn)); ///mute->setIconSize(muteIconOn->size()); mute->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum)); connect(mute, SIGNAL(clicked(bool)), SLOT(muteToggled(bool))); solo = new QToolButton(); solo->setFocusPolicy(Qt::NoFocus); solo->setToolTip(tr("solo mode")); solo->setCheckable(true); solo->setChecked(track->solo()); solo->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum)); if(track->internalSolo()) solo->setIcon(track->solo() ? QIcon(*soloblksqIconOn) : QIcon(*soloblksqIconOff)); else solo->setIcon(track->solo() ? QIcon(*soloIconOn) : QIcon(*soloIconOff)); ///solo->setIconSize(soloIconOn->size()); connect(solo, SIGNAL(clicked(bool)), SLOT(soloToggled(bool))); off = new MusEGui::TransparentToolButton(this); off->setFocusPolicy(Qt::NoFocus); off->setBackgroundRole(QPalette::Mid); off->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum)); off->setCheckable(true); off->setToolTip(tr("off")); off->setChecked(track->off()); off->setIcon(track->off() ? QIcon(*exit1Icon) : QIcon(*exitIcon)); ///off->setIconSize(exit1Icon->size()); connect(off, SIGNAL(clicked(bool)), SLOT(offToggled(bool))); grid->addWidget(off, _curGridRow, 0); grid->addWidget(record, _curGridRow++, 1); grid->addWidget(mute, _curGridRow, 0); grid->addWidget(solo, _curGridRow++, 1); //--------------------------------------------------- // routing //--------------------------------------------------- iR = new QToolButton(); iR->setFocusPolicy(Qt::NoFocus); ///iR->setFont(MusEGlobal::config.fonts[1]); iR->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum)); ///iR->setText(tr("iR")); iR->setIcon(QIcon(*routesMidiInIcon)); iR->setIconSize(routesMidiInIcon->size()); iR->setCheckable(false); iR->setToolTip(tr("input routing")); grid->addWidget(iR, _curGridRow, 0); connect(iR, SIGNAL(pressed()), SLOT(iRoutePressed())); oR = new QToolButton(); oR->setFocusPolicy(Qt::NoFocus); ///oR->setFont(MusEGlobal::config.fonts[1]); oR->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum)); ///oR->setText(tr("oR")); oR->setIcon(QIcon(*routesMidiOutIcon)); oR->setIconSize(routesMidiOutIcon->size()); oR->setCheckable(false); // TODO: Works OK, but disabled for now, until we figure out what to do about multiple out routes and display values... // Enabled (for Midi Port to Audio Input routing). p4.0.14 Tim. //oR->setEnabled(false); oR->setToolTip(tr("output routing")); grid->addWidget(oR, _curGridRow++, 1); connect(oR, SIGNAL(pressed()), SLOT(oRoutePressed())); //--------------------------------------------------- // automation mode //--------------------------------------------------- autoType = new MusEGui::ComboBox(); autoType->setFocusPolicy(Qt::NoFocus); ///autoType->setFont(MusEGlobal::config.fonts[1]); autoType->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum)); autoType->setEnabled(false); // Removed by T356. // Disabled for now. There is no midi automation mechanism yet... //autoType->addAction(tr("Off"), AUTO_OFF); //autoType->addAction(tr("Read"), AUTO_READ); //autoType->addAction(tr("Touch"), AUTO_TOUCH); //autoType->addAction(tr("Write"), AUTO_WRITE); //autoType->setCurrentItem(t->automationType()); //autoType->setToolTip(tr("automation type")); //connect(autoType, SIGNAL(activated(int)), SLOT(setAutomationType(int))); autoType->addAction(" ", AUTO_OFF); // Just a dummy text to fix sizing problems. REMOVE later if full automation added. autoType->setCurrentItem(AUTO_OFF); // grid->addWidget(autoType, _curGridRow++, 0, 1, 2); connect(MusEGlobal::heartBeatTimer, SIGNAL(timeout()), SLOT(heartBeat())); inHeartBeat = false; } //--------------------------------------------------------- // updateOffState //--------------------------------------------------------- void MidiStrip::updateOffState() { bool val = !track->off(); slider->setEnabled(val); sl->setEnabled(val); controller[KNOB_PAN].knob->setEnabled(val); controller[KNOB_PAN].dl->setEnabled(val); label->setEnabled(val); if (record) record->setEnabled(val); if (solo) solo->setEnabled(val); if (mute) mute->setEnabled(val); // TODO: Disabled for now. //if (autoType) // autoType->setEnabled(val); //if (iR) // iR->setEnabled(val); //if (oR) // oR->setEnabled(val); if (off) { off->blockSignals(true); off->setChecked(track->off()); off->blockSignals(false); off->setIcon(track->off() ? QIcon(*exit1Icon) : QIcon(*exitIcon)); //off->setIconSize(exit1Icon->size()); } } //--------------------------------------------------------- // configChanged // Catch when config label font changes, viewable tracks etc. //--------------------------------------------------------- void MidiStrip::configChanged() { // Set the whole strip's font, except for the label. p4.0.45 if(font() != MusEGlobal::config.fonts[1]) setFont(MusEGlobal::config.fonts[1]); // Set the strip label's font. setLabelFont(); setLabelText(); } //--------------------------------------------------------- // songChanged //--------------------------------------------------------- void MidiStrip::songChanged(MusECore::SongChangedFlags_t val) { if (mute && (val & SC_MUTE)) { // mute && off mute->blockSignals(true); //mute->setChecked(track->isMute()); mute->setChecked(track->mute()); mute->blockSignals(false); mute->setIcon(track->mute() ? QIcon(*muteIconOff) : QIcon(*muteIconOn)); //mute->setIconSize(muteIconOn->size()); updateOffState(); } if (solo && (val & SC_SOLO)) { solo->blockSignals(true); solo->setChecked(track->solo()); solo->blockSignals(false); if(track->internalSolo()) solo->setIcon(track->solo() ? QIcon(*soloblksqIconOn) : QIcon(*soloblksqIconOff)); else solo->setIcon(track->solo() ? QIcon(*soloIconOn) : QIcon(*soloIconOff)); //solo->setIconSize(soloIconOn->size()); } if (val & SC_RECFLAG) setRecordFlag(track->recordFlag()); if (val & SC_TRACK_MODIFIED) { setLabelText(); setLabelFont(); } // Catch when label font changes. if (val & SC_CONFIG) { // So far only 1 instance of sending SC_CONFIG in the entire app, in instrument editor when a new instrument is saved. } } //--------------------------------------------------------- // controlRightClicked //--------------------------------------------------------- void MidiStrip::controlRightClicked(const QPoint &p, int id) { MusEGlobal::song->execMidiAutomationCtlPopup((MusECore::MidiTrack*)track, 0, p, id); } //--------------------------------------------------------- // labelDoubleClicked //--------------------------------------------------------- void MidiStrip::labelDoubleClicked(int idx) { //int mn, mx, v; //int num = MusECore::CTRL_VOLUME; int num; switch(idx) { case KNOB_PAN: num = MusECore::CTRL_PANPOT; break; case KNOB_VAR_SEND: num = MusECore::CTRL_VARIATION_SEND; break; case KNOB_REV_SEND: num = MusECore::CTRL_REVERB_SEND; break; case KNOB_CHO_SEND: num = MusECore::CTRL_CHORUS_SEND; break; //case -1: default: num = MusECore::CTRL_VOLUME; break; } int outport = ((MusECore::MidiTrack*)track)->outPort(); int chan = ((MusECore::MidiTrack*)track)->outChannel(); MusECore::MidiPort* mp = &MusEGlobal::midiPorts[outport]; MusECore::MidiController* mc = mp->midiController(num); int lastv = mp->lastValidHWCtrlState(chan, num); int curv = mp->hwCtrlState(chan, num); 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 = _ctrl->initVal()); int kiv; if(idx == -1) kiv = lrint(slider->value()); else kiv = lrint(controller[idx].knob->value()); if(kiv < mc->minVal()) kiv = mc->minVal(); if(kiv > mc->maxVal()) kiv = mc->maxVal(); kiv += mc->bias(); //MusECore::MidiPlayEvent ev(MusEGlobal::song->cpos(), outport, chan, MusECore::ME_CONTROLLER, num, kiv); MusECore::MidiPlayEvent ev(0, outport, chan, MusECore::ME_CONTROLLER, num, kiv); MusEGlobal::audio->msgPlayMidiEvent(&ev); } else { //MidiPlayEvent ev(MusEGlobal::song->cpos(), outport, chan, MusECore::ME_CONTROLLER, num, lastv); MusECore::MidiPlayEvent ev(0, outport, chan, MusECore::ME_CONTROLLER, num, lastv); MusEGlobal::audio->msgPlayMidiEvent(&ev); } } else { if(mp->hwCtrlState(chan, num) != MusECore::CTRL_VAL_UNKNOWN) MusEGlobal::audio->msgSetHwCtrlState(mp, chan, num, MusECore::CTRL_VAL_UNKNOWN); } MusEGlobal::song->update(SC_MIDI_CONTROLLER); } //--------------------------------------------------------- // offToggled //--------------------------------------------------------- void MidiStrip::offToggled(bool val) { track->setOff(val); MusEGlobal::song->update(SC_MUTE); } /* //--------------------------------------------------------- // routeClicked //--------------------------------------------------------- void MidiStrip::routeClicked() { } */ //--------------------------------------------------------- // heartBeat //--------------------------------------------------------- void MidiStrip::heartBeat() { inHeartBeat = true; int act = track->activity(); double dact = double(act) * (slider->value() / 127.0); if((int)dact > track->lastActivity()) track->setLastActivity((int)dact); if(meter[0]) //meter[0]->setVal(int(double(act) * (slider->value() / 127.0)), 0, false); meter[0]->setVal(dact, track->lastActivity(), false); // Gives reasonable decay with gui update set to 20/sec. if(act) track->setActivity((int)((double)act * 0.8)); Strip::heartBeat(); updateControls(); inHeartBeat = false; } //--------------------------------------------------------- // updateControls //--------------------------------------------------------- void MidiStrip::updateControls() { bool en; int channel = ((MusECore::MidiTrack*)track)->outChannel(); MusECore::MidiPort* mp = &MusEGlobal::midiPorts[((MusECore::MidiTrack*)track)->outPort()]; MusECore::MidiCtrlValListList* mc = mp->controller(); MusECore::ciMidiCtrlValList icl; MusECore::MidiController* ctrl = mp->midiController(MusECore::CTRL_VOLUME); int nvolume = mp->hwCtrlState(channel, MusECore::CTRL_VOLUME); if(nvolume == MusECore::CTRL_VAL_UNKNOWN) { //if(nvolume != volume) //{ // MusEGui::DoubleLabel ignores the value if already set... sl->setValue(sl->off() - 1.0); //volume = nvolume; //} volume = MusECore::CTRL_VAL_UNKNOWN; nvolume = mp->lastValidHWCtrlState(channel, MusECore::CTRL_VOLUME); //if(nvolume != volume) if(nvolume != MusECore::CTRL_VAL_UNKNOWN) { nvolume -= ctrl->bias(); //slider->blockSignals(true); if(double(nvolume) != slider->value()) { //printf("MidiStrip::updateControls setting volume slider\n"); slider->setValue(double(nvolume)); } } } else { int ivol = nvolume; nvolume -= ctrl->bias(); if(nvolume != volume) { //printf("MidiStrip::updateControls setting volume slider\n"); //slider->blockSignals(true); slider->setValue(double(nvolume)); //sl->setValue(double(nvolume)); if(ivol == 0) { //printf("MidiStrip::updateControls setting volume slider label\n"); sl->setValue(sl->minValue() - 0.5 * (sl->minValue() - sl->off())); } else { double v = -MusECore::fast_log10(float(127*127)/float(ivol*ivol))*20.0; if(v > sl->maxValue()) { //printf("MidiStrip::updateControls setting volume slider label\n"); sl->setValue(sl->maxValue()); } else { //printf("MidiStrip::updateControls setting volume slider label\n"); sl->setValue(v); } } //slider->blockSignals(false); volume = nvolume; } } KNOB* gcon = &controller[KNOB_PAN]; ctrl = mp->midiController(MusECore::CTRL_PANPOT); int npan = mp->hwCtrlState(channel, MusECore::CTRL_PANPOT); if(npan == MusECore::CTRL_VAL_UNKNOWN) { // MusEGui::DoubleLabel ignores the value if already set... //if(npan != pan) //{ gcon->dl->setValue(gcon->dl->off() - 1.0); //pan = npan; //} pan = MusECore::CTRL_VAL_UNKNOWN; npan = mp->lastValidHWCtrlState(channel, MusECore::CTRL_PANPOT); if(npan != MusECore::CTRL_VAL_UNKNOWN) { npan -= ctrl->bias(); if(double(npan) != gcon->knob->value()) { //printf("MidiStrip::updateControls setting pan knob\n"); gcon->knob->setValue(double(npan)); } } } else { npan -= ctrl->bias(); if(npan != pan) { //printf("MidiStrip::updateControls setting pan label and knob\n"); //controller[KNOB_PAN].knob->blockSignals(true); gcon->knob->setValue(double(npan)); gcon->dl->setValue(double(npan)); //controller[KNOB_PAN].knob->blockSignals(false); pan = npan; } } icl = mc->find(channel, MusECore::CTRL_VARIATION_SEND); en = icl != mc->end(); gcon = &controller[KNOB_VAR_SEND]; if(gcon->knob->isEnabled() != en) gcon->knob->setEnabled(en); if(gcon->lb->isEnabled() != en) gcon->lb->setEnabled(en); if(gcon->dl->isEnabled() != en) gcon->dl->setEnabled(en); if(en) { ctrl = mp->midiController(MusECore::CTRL_VARIATION_SEND); int nvariSend = icl->second->hwVal(); if(nvariSend == MusECore::CTRL_VAL_UNKNOWN) { // MusEGui::DoubleLabel ignores the value if already set... //if(nvariSend != variSend) //{ gcon->dl->setValue(gcon->dl->off() - 1.0); //variSend = nvariSend; //} variSend = MusECore::CTRL_VAL_UNKNOWN; nvariSend = mp->lastValidHWCtrlState(channel, MusECore::CTRL_VARIATION_SEND); if(nvariSend != MusECore::CTRL_VAL_UNKNOWN) { nvariSend -= ctrl->bias(); if(double(nvariSend) != gcon->knob->value()) { gcon->knob->setValue(double(nvariSend)); } } } else { nvariSend -= ctrl->bias(); if(nvariSend != variSend) { //controller[KNOB_VAR_SEND].knob->blockSignals(true); gcon->knob->setValue(double(nvariSend)); gcon->dl->setValue(double(nvariSend)); //controller[KNOB_VAR_SEND].knob->blockSignals(false); variSend = nvariSend; } } } icl = mc->find(channel, MusECore::CTRL_REVERB_SEND); en = icl != mc->end(); gcon = &controller[KNOB_REV_SEND]; if(gcon->knob->isEnabled() != en) gcon->knob->setEnabled(en); if(gcon->lb->isEnabled() != en) gcon->lb->setEnabled(en); if(gcon->dl->isEnabled() != en) gcon->dl->setEnabled(en); if(en) { ctrl = mp->midiController(MusECore::CTRL_REVERB_SEND); int nreverbSend = icl->second->hwVal(); if(nreverbSend == MusECore::CTRL_VAL_UNKNOWN) { // MusEGui::DoubleLabel ignores the value if already set... //if(nreverbSend != reverbSend) //{ gcon->dl->setValue(gcon->dl->off() - 1.0); //reverbSend = nreverbSend; //} reverbSend = MusECore::CTRL_VAL_UNKNOWN; nreverbSend = mp->lastValidHWCtrlState(channel, MusECore::CTRL_REVERB_SEND); if(nreverbSend != MusECore::CTRL_VAL_UNKNOWN) { nreverbSend -= ctrl->bias(); if(double(nreverbSend) != gcon->knob->value()) { gcon->knob->setValue(double(nreverbSend)); } } } else { nreverbSend -= ctrl->bias(); if(nreverbSend != reverbSend) { //controller[KNOB_REV_SEND].knob->blockSignals(true); gcon->knob->setValue(double(nreverbSend)); gcon->dl->setValue(double(nreverbSend)); //controller[KNOB_REV_SEND].knob->blockSignals(false); reverbSend = nreverbSend; } } } icl = mc->find(channel, MusECore::CTRL_CHORUS_SEND); en = icl != mc->end(); gcon = &controller[KNOB_CHO_SEND]; if(gcon->knob->isEnabled() != en) gcon->knob->setEnabled(en); if(gcon->lb->isEnabled() != en) gcon->lb->setEnabled(en); if(gcon->dl->isEnabled() != en) gcon->dl->setEnabled(en); if(en) { ctrl = mp->midiController(MusECore::CTRL_CHORUS_SEND); int nchorusSend = icl->second->hwVal(); if(nchorusSend == MusECore::CTRL_VAL_UNKNOWN) { // MusEGui::DoubleLabel ignores the value if already set... //if(nchorusSend != chorusSend) //{ gcon->dl->setValue(gcon->dl->off() - 1.0); //chorusSend = nchorusSend; //} chorusSend = MusECore::CTRL_VAL_UNKNOWN; nchorusSend = mp->lastValidHWCtrlState(channel, MusECore::CTRL_CHORUS_SEND); if(nchorusSend != MusECore::CTRL_VAL_UNKNOWN) { nchorusSend -= ctrl->bias(); if(double(nchorusSend) != gcon->knob->value()) { gcon->knob->setValue(double(nchorusSend)); } } } else { nchorusSend -= ctrl->bias(); if(nchorusSend != chorusSend) { gcon->knob->setValue(double(nchorusSend)); gcon->dl->setValue(double(nchorusSend)); chorusSend = nchorusSend; } } } } //--------------------------------------------------------- // ctrlChanged //--------------------------------------------------------- void MidiStrip::ctrlChanged(int num, int val) { if (inHeartBeat) return; MusECore::MidiTrack* t = (MusECore::MidiTrack*) track; int port = t->outPort(); int chan = t->outChannel(); MusECore::MidiPort* mp = &MusEGlobal::midiPorts[port]; MusECore::MidiController* mctl = mp->midiController(num); if((val < mctl->minVal()) || (val > mctl->maxVal())) { if(mp->hwCtrlState(chan, num) != MusECore::CTRL_VAL_UNKNOWN) MusEGlobal::audio->msgSetHwCtrlState(mp, chan, num, MusECore::CTRL_VAL_UNKNOWN); } else { val += mctl->bias(); int tick = MusEGlobal::song->cpos(); MusECore::MidiPlayEvent ev(tick, port, chan, MusECore::ME_CONTROLLER, num, val); MusEGlobal::audio->msgPlayMidiEvent(&ev); } MusEGlobal::song->update(SC_MIDI_CONTROLLER); } //--------------------------------------------------------- // volLabelChanged //--------------------------------------------------------- void MidiStrip::volLabelChanged(double val) { val = sqrt( float(127*127) / pow(10.0, -val/20.0) ); ctrlChanged(MusECore::CTRL_VOLUME, lrint(val)); } //--------------------------------------------------------- // setVolume //--------------------------------------------------------- void MidiStrip::setVolume(double val) { // printf("Vol %d\n", lrint(val)); ctrlChanged(MusECore::CTRL_VOLUME, lrint(val)); } //--------------------------------------------------------- // setPan //--------------------------------------------------------- void MidiStrip::setPan(double val) { ctrlChanged(MusECore::CTRL_PANPOT, lrint(val)); } //--------------------------------------------------------- // setVariSend //--------------------------------------------------------- void MidiStrip::setVariSend(double val) { ctrlChanged(MusECore::CTRL_VARIATION_SEND, lrint(val)); } //--------------------------------------------------------- // setChorusSend //--------------------------------------------------------- void MidiStrip::setChorusSend(double val) { ctrlChanged(MusECore::CTRL_CHORUS_SEND, lrint(val)); } //--------------------------------------------------------- // setReverbSend //--------------------------------------------------------- void MidiStrip::setReverbSend(double val) { ctrlChanged(MusECore::CTRL_REVERB_SEND, lrint(val)); } //--------------------------------------------------------- // iRoutePressed //--------------------------------------------------------- void MidiStrip::iRoutePressed() { //MusEGui::RoutePopupMenu* pup = MusEGlobal::muse->getRoutingPopupMenu(); RoutePopupMenu* pup = new RoutePopupMenu(); pup->exec(QCursor::pos(), track, false); delete pup; iR->setDown(false); } //--------------------------------------------------------- // oRoutePressed //--------------------------------------------------------- void MidiStrip::oRoutePressed() { //MusEGui::RoutePopupMenu* pup = MusEGlobal::muse->getRoutingPopupMenu(); RoutePopupMenu* pup = new RoutePopupMenu(); pup->exec(QCursor::pos(), track, true); delete pup; oR->setDown(false); } } // namespace MusEGui