diff options
Diffstat (limited to 'attic/muse2-oom/muse2/muse/mixer/astrip.cpp')
-rw-r--r-- | attic/muse2-oom/muse2/muse/mixer/astrip.cpp | 1996 |
1 files changed, 1996 insertions, 0 deletions
diff --git a/attic/muse2-oom/muse2/muse/mixer/astrip.cpp b/attic/muse2-oom/muse2/muse/mixer/astrip.cpp new file mode 100644 index 00000000..58e75f67 --- /dev/null +++ b/attic/muse2-oom/muse2/muse/mixer/astrip.cpp @@ -0,0 +1,1996 @@ +//========================================================= +// MusE +// Linux Music Editor +// $Id: astrip.cpp,v 1.23.2.17 2009/11/16 01:55:55 terminator356 Exp $ +// +// (C) Copyright 2000-2004 Werner Schweer (ws@seh.de) +//========================================================= + +#include <fastlog.h> + +#include <QLayout> +#include <QApplication> +//#include <QDialog> +#include <QToolButton> +#include <QLabel> +#include <QComboBox> +#include <QToolTip> +#include <QTimer> +//#include <QPopupMenu> +#include <QCursor> +#include <QPainter> +#include <QString> +#include <QPoint> +#include <QEvent> +#include <QWidget> +#include <QVariant> +#include <QAction> +#include <QGridLayout> + +#include "app.h" +#include "globals.h" +#include "audio.h" +#include "driver/audiodev.h" +#include "song.h" +#include "slider.h" +#include "knob.h" +#include "combobox.h" +#include "meter.h" +#include "astrip.h" +#include "track.h" +#include "synth.h" +//#include "route.h" +#include "doublelabel.h" +#include "rack.h" +#include "node.h" +#include "amixer.h" +#include "icons.h" +#include "gconfig.h" +#include "ttoolbutton.h" +#include "menutitleitem.h" +#include "popupmenu.h" + +//--------------------------------------------------------- +// MenuTitleItem +//--------------------------------------------------------- + +MenuTitleItem::MenuTitleItem(const QString& ss, QWidget* parent) + : QWidgetAction(parent) + { + s = ss; + // Don't allow to click on it. + setEnabled(false); + // Just to be safe, set to -1 instead of default 0. + setData(-1); + } + +QWidget* MenuTitleItem::createWidget(QWidget *parent) +{ + QLabel* l = new QLabel(s, parent); + l->setAlignment(Qt::AlignCenter); + return l; +} + +/* +//--------------------------------------------------------- +// minimumSizeHint +//--------------------------------------------------------- + +QSize AudioStrip::minimumSizeHint () const +{ + // We force the width of the size hint to be what we want + //return QWidget::minimumSizeHint(); + ///return QSize(66,QWidget::minimumSizeHint().height()); +} + +//--------------------------------------------------------- +// sizeHint +//--------------------------------------------------------- + +QSize AudioStrip::sizeHint () const +{ + // We force the width of the size hint to be what we want + //return QWidget::minimumSizeHint(); + //return QSize(66,QWidget::minimumSizeHint().height()); + return minimumSizeHint(); +} +*/ + +//--------------------------------------------------------- +// heartBeat +//--------------------------------------------------------- + +void AudioStrip::heartBeat() + { + for (int ch = 0; ch < track->channels(); ++ch) { + if (meter[ch]) { + //int meterVal = track->meter(ch); + //int peak = track->peak(ch); + //meter[ch]->setVal(meterVal, peak, false); + meter[ch]->setVal(track->meter(ch), track->peak(ch), false); + } + } + Strip::heartBeat(); + updateVolume(); + updatePan(); + } + +//--------------------------------------------------------- +// configChanged +//--------------------------------------------------------- + +void AudioStrip::configChanged() +{ + songChanged(SC_CONFIG); +} + +//--------------------------------------------------------- +// songChanged +//--------------------------------------------------------- + +void AudioStrip::songChanged(int val) + { + // Is it simply a midi controller value adjustment? Forget it. + if (val == SC_MIDI_CONTROLLER) + return; + + AudioTrack* src = (AudioTrack*)track; + + // Do channels before config... + if (val & SC_CHANNELS) + updateChannels(); + + // p3.3.47 + // Update the routing popup menu if anything relevant changed. + if (val & (SC_ROUTE | SC_CHANNELS | SC_CONFIG)) + { + //updateRouteMenus(); + muse->updateRouteMenus(track, this); // p3.3.50 Use this handy shared routine. + } + + // Catch when label font, or configuration min slider and meter values change. + if (val & SC_CONFIG) + { + // Added by Tim. p3.3.9 + + // Set the strip label's font. + //label->setFont(config.fonts[1]); + setLabelFont(); + + // Adjust minimum volume slider and label values. + slider->setRange(config.minSlider-0.1, 10.0); + sl->setRange(config.minSlider, 10.0); + + // Adjust minimum aux knob and label values. + int n = auxKnob.size(); + for (int idx = 0; idx < n; ++idx) + { + auxKnob[idx]->blockSignals(true); + auxLabel[idx]->blockSignals(true); + auxKnob[idx]->setRange(config.minSlider-0.1, 10.0); + auxLabel[idx]->setRange(config.minSlider, 10.1); + auxKnob[idx]->blockSignals(false); + auxLabel[idx]->blockSignals(false); + } + + // Adjust minimum meter values. + for(int c = 0; c < channel; ++c) + meter[c]->setRange(config.minMeter, 10.0); + } + + if (mute && (val & SC_MUTE)) { // mute && off + mute->blockSignals(true); + mute->setChecked(src->mute()); + mute->blockSignals(false); + updateOffState(); + } + if (solo && (val & SC_SOLO)) { + if((bool)track->internalSolo()) + { + if(!useSoloIconSet2) + { + solo->setIcon(*soloIconSet2); + solo->setIconSize(soloIconOn->size()); + useSoloIconSet2 = true; + } + } + else if(useSoloIconSet2) + { + solo->setIcon(*soloIconSet1); + solo->setIconSize(soloblksqIconOn->size()); + useSoloIconSet2 = false; + } + + solo->blockSignals(true); + solo->setChecked(track->solo()); + solo->blockSignals(false); + } + if (val & SC_RECFLAG) + setRecordFlag(track->recordFlag()); + if (val & SC_TRACK_MODIFIED) + { + setLabelText(); + // Added by Tim. p3.3.9 + setLabelFont(); + + } + //if (val & SC_CHANNELS) + // updateChannels(); + if (val & SC_ROUTE) { + if (pre) { + pre->blockSignals(true); + pre->setChecked(src->prefader()); + pre->blockSignals(false); + } + } + if (val & SC_AUX) { + int n = auxKnob.size(); + for (int idx = 0; idx < n; ++idx) { + double val = fast_log10(src->auxSend(idx)) * 20.0; + auxKnob[idx]->blockSignals(true); + auxLabel[idx]->blockSignals(true); + auxKnob[idx]->setValue(val); + auxLabel[idx]->setValue(val); + auxKnob[idx]->blockSignals(false); + auxLabel[idx]->blockSignals(false); + } + } + if (autoType && (val & SC_AUTOMATION)) { + autoType->blockSignals(true); + autoType->setCurrentItem(track->automationType()); + if(track->automationType() == AUTO_TOUCH || track->automationType() == AUTO_WRITE) + { + //autoType->setPaletteBackgroundColor(Qt::red); + QPalette palette; + palette.setColor(autoType->backgroundRole(), QColor(Qt::red)); + autoType->setPalette(palette); + } + else + { + //autoType->setPaletteBackgroundColor(qApp->palette().active().background()); + QPalette palette; + palette.setColor(autoType->backgroundRole(), qApp->palette().color(QPalette::Active, QPalette::Background)); + autoType->setPalette(palette); + } + + autoType->blockSignals(false); + } + } + +//--------------------------------------------------------- +// updateVolume +//--------------------------------------------------------- + +void AudioStrip::updateVolume() +{ + double vol = ((AudioTrack*)track)->volume(); + if (vol != volume) + { + //printf("AudioStrip::updateVolume setting slider and label\n"); + + slider->blockSignals(true); + sl->blockSignals(true); + double val = fast_log10(vol) * 20.0; + slider->setValue(val); + sl->setValue(val); + sl->blockSignals(false); + slider->blockSignals(false); + volume = vol; + } +} + +//--------------------------------------------------------- +// updatePan +//--------------------------------------------------------- + +void AudioStrip::updatePan() +{ + double v = ((AudioTrack*)track)->pan(); + if (v != panVal) + { + //printf("AudioStrip::updatePan setting slider and label\n"); + + pan->blockSignals(true); + panl->blockSignals(true); + pan->setValue(v); + panl->setValue(v); + panl->blockSignals(false); + pan->blockSignals(false); + panVal = v; + } +} + +//--------------------------------------------------------- +// offToggled +//--------------------------------------------------------- + +void AudioStrip::offToggled(bool val) + { + track->setOff(val); + song->update(SC_MUTE); + } + +//--------------------------------------------------------- +// updateOffState +//--------------------------------------------------------- + +void AudioStrip::updateOffState() + { + bool val = !track->off(); + slider->setEnabled(val); + sl->setEnabled(val); + pan->setEnabled(val); + panl->setEnabled(val); + if (track->type() != Track::AUDIO_SOFTSYNTH) + stereo->setEnabled(val); + label->setEnabled(val); + + int n = auxKnob.size(); + for (int i = 0; i < n; ++i) + { + auxKnob[i]->setEnabled(val); + auxLabel[i]->setEnabled(val); + } + + if (pre) + pre->setEnabled(val); + if (record) + record->setEnabled(val); + if (solo) + solo->setEnabled(val); + if (mute) + mute->setEnabled(val); + 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); + } + } + +//--------------------------------------------------------- +// preToggled +//--------------------------------------------------------- + +void AudioStrip::preToggled(bool val) + { + audio->msgSetPrefader((AudioTrack*)track, val); + resetPeaks(); + song->update(SC_ROUTE); + } + +//--------------------------------------------------------- +// stereoToggled +//--------------------------------------------------------- + +void AudioStrip::stereoToggled(bool val) + { + int oc = track->channels(); + int nc = val ? 2 : 1; +// stereo->setIcon(nc == 2 ? *stereoIcon : *monoIcon); + if (oc == nc) + return; + audio->msgSetChannels((AudioTrack*)track, nc); + song->update(SC_CHANNELS); + } + +//--------------------------------------------------------- +// auxChanged +//--------------------------------------------------------- + +void AudioStrip::auxChanged(double val, int idx) + { + double vol; + if (val <= config.minSlider) { + vol = 0.0; + val -= 1.0; // display special value "off" + } + else + vol = pow(10.0, val/20.0); + audio->msgSetAux((AudioTrack*)track, idx, vol); + song->update(SC_AUX); + } + +//--------------------------------------------------------- +// auxLabelChanged +//--------------------------------------------------------- + +void AudioStrip::auxLabelChanged(double val, unsigned int idx) + { + if(idx >= auxKnob.size()) + return; + auxKnob[idx]->setValue(val); + } + +//--------------------------------------------------------- +// volumeChanged +//--------------------------------------------------------- + +void AudioStrip::volumeChanged(double val) + { + AutomationType at = ((AudioTrack*)track)->automationType(); + if(at == AUTO_WRITE || (audio->isPlaying() && at == AUTO_TOUCH)) + track->enableVolumeController(false); + + double vol; + if (val <= config.minSlider) { + vol = 0.0; + val -= 1.0; // display special value "off" + } + else + vol = pow(10.0, val/20.0); + volume = vol; + audio->msgSetVolume((AudioTrack*)track, vol); + ((AudioTrack*)track)->recordAutomation(AC_VOLUME, vol); + } + +//--------------------------------------------------------- +// volumePressed +//--------------------------------------------------------- + +void AudioStrip::volumePressed() + { + AutomationType at = ((AudioTrack*)track)->automationType(); + if(at == AUTO_WRITE || (at == AUTO_READ || at == AUTO_TOUCH)) + track->enableVolumeController(false); + + double val = slider->value(); + double vol; + if (val <= config.minSlider) { + vol = 0.0; + //val -= 1.0; // display special value "off" + } + else + vol = pow(10.0, val/20.0); + volume = vol; + audio->msgSetVolume((AudioTrack*)track, volume); + ((AudioTrack*)track)->startAutoRecord(AC_VOLUME, volume); + } + +//--------------------------------------------------------- +// volumeReleased +//--------------------------------------------------------- + +void AudioStrip::volumeReleased() + { + if(track->automationType() != AUTO_WRITE) + track->enableVolumeController(true); + + ((AudioTrack*)track)->stopAutoRecord(AC_VOLUME, volume); + } + +//--------------------------------------------------------- +// volumeRightClicked +//--------------------------------------------------------- +void AudioStrip::volumeRightClicked(const QPoint &p) +{ + song->execAutomationCtlPopup((AudioTrack*)track, p, AC_VOLUME); +} + +//--------------------------------------------------------- +// volLabelChanged +//--------------------------------------------------------- + +void AudioStrip::volLabelChanged(double val) + { + AutomationType at = ((AudioTrack*)track)->automationType(); + if(at == AUTO_WRITE || (audio->isPlaying() && at == AUTO_TOUCH)) + track->enableVolumeController(false); + + double vol; + if (val <= config.minSlider) { + vol = 0.0; + val -= 1.0; // display special value "off" + } + else + vol = pow(10.0, val/20.0); + volume = vol; + slider->setValue(val); + audio->msgSetVolume((AudioTrack*)track, vol); + ((AudioTrack*)track)->startAutoRecord(AC_VOLUME, vol); + } + +//--------------------------------------------------------- +// panChanged +//--------------------------------------------------------- + +void AudioStrip::panChanged(double val) + { + AutomationType at = ((AudioTrack*)track)->automationType(); + if(at == AUTO_WRITE || (audio->isPlaying() && at == AUTO_TOUCH)) + track->enablePanController(false); + + panVal = val; + audio->msgSetPan(((AudioTrack*)track), val); + ((AudioTrack*)track)->recordAutomation(AC_PAN, val); + } + +//--------------------------------------------------------- +// panPressed +//--------------------------------------------------------- + +void AudioStrip::panPressed() + { + AutomationType at = ((AudioTrack*)track)->automationType(); + if(at == AUTO_WRITE || (at == AUTO_READ || at == AUTO_TOUCH)) + track->enablePanController(false); + + panVal = pan->value(); + audio->msgSetPan(((AudioTrack*)track), panVal); + ((AudioTrack*)track)->startAutoRecord(AC_PAN, panVal); + } + +//--------------------------------------------------------- +// panReleased +//--------------------------------------------------------- + +void AudioStrip::panReleased() + { + if(track->automationType() != AUTO_WRITE) + track->enablePanController(true); + ((AudioTrack*)track)->stopAutoRecord(AC_PAN, panVal); + } + +//--------------------------------------------------------- +// panRightClicked +//--------------------------------------------------------- +void AudioStrip::panRightClicked(const QPoint &p) +{ + song->execAutomationCtlPopup((AudioTrack*)track, p, AC_PAN); +} + +//--------------------------------------------------------- +// panLabelChanged +//--------------------------------------------------------- + +void AudioStrip::panLabelChanged(double val) + { + AutomationType at = ((AudioTrack*)track)->automationType(); + if(at == AUTO_WRITE || (audio->isPlaying() && at == AUTO_TOUCH)) + track->enablePanController(false); + + panVal = val; + pan->setValue(val); + audio->msgSetPan((AudioTrack*)track, val); + ((AudioTrack*)track)->startAutoRecord(AC_PAN, val); + } + +//--------------------------------------------------------- +// updateChannels +//--------------------------------------------------------- + +void AudioStrip::updateChannels() + { + AudioTrack* t = (AudioTrack*)track; + int c = t->channels(); + //printf("AudioStrip::updateChannels track channels:%d current channels:%d\n", c, channel); + + if (c > channel) { + for (int cc = channel; cc < c; ++cc) { + meter[cc] = new Meter(this); + //meter[cc]->setRange(config.minSlider, 10.0); + meter[cc]->setRange(config.minMeter, 10.0); + meter[cc]->setFixedWidth(15); + connect(meter[cc], SIGNAL(mousePress()), this, SLOT(resetPeaks())); + sliderGrid->addWidget(meter[cc], 0, cc+1, Qt::AlignHCenter); + sliderGrid->setColumnStretch(cc, 50); + meter[cc]->show(); + } + } + else if (c < channel) { + for (int cc = channel-1; cc >= c; --cc) { + delete meter[cc]; + meter[cc] = 0; + } + } + channel = c; + stereo->blockSignals(true); + stereo->setChecked(channel == 2); + stereo->blockSignals(false); + } + +//--------------------------------------------------------- +// addKnob +// type = 0 - panorama +// 1 - aux send +//--------------------------------------------------------- + +Knob* AudioStrip::addKnob(int type, int id, DoubleLabel** dlabel) + { + Knob* knob = new Knob(this); + knob->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum)); + if (type == 0) + knob->setRange(-1.0, +1.0); + else + knob->setRange(config.minSlider-0.1, 10.0); + knob->setBackgroundRole(QPalette::Mid); + + if (type == 0) + { + knob->setToolTip(tr("panorama")); + knob->setKnobImage(":/images/knob.png"); + } + else + { + knob->setKnobImage(":/images/knob_aux.png"); + knob->setToolTip(tr("aux send level")); + } + + DoubleLabel* pl; + if (type == 0) + pl = new DoubleLabel(0, -1.0, +1.0, this); + else + pl = new DoubleLabel(0.0, config.minSlider, 10.1, this); + + if (dlabel) + *dlabel = pl; + pl->setSlider(knob); + pl->setFont(config.fonts[1]); + pl->setBackgroundRole(QPalette::Mid); + pl->setFrame(true); + if (type == 0) + pl->setPrecision(2); + else { + pl->setPrecision(0); + } + pl->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum)); + + QString label; + if (type == 0) + label = tr("Pan"); + else + label.sprintf("Aux%d", id+1); + + QLabel* plb = new QLabel(label, this); + plb->setFont(config.fonts[1]); + plb->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum)); + plb->setAlignment(Qt::AlignCenter); + + grid->addWidget(plb, _curGridRow, 0); + grid->addWidget(pl, _curGridRow+1, 0); + grid->addWidget(knob, _curGridRow, 1, 2, 1); + //grid->addWidget(plb, _curGridRow, 0, Qt::AlignCenter); + //grid->addWidget(pl, _curGridRow+1, 0, Qt::AlignCenter); + //grid->addWidget(knob, _curGridRow, 1, 2, 1, Qt::AlignCenter); + _curGridRow += 2; + + connect(knob, SIGNAL(valueChanged(double,int)), pl, SLOT(setValue(double))); + //connect(pl, SIGNAL(valueChanged(double, int)), SLOT(panChanged(double))); + + if (type == 0) { + connect(pl, SIGNAL(valueChanged(double, int)), SLOT(panLabelChanged(double))); + connect(knob, SIGNAL(sliderMoved(double,int)), SLOT(panChanged(double))); + connect(knob, SIGNAL(sliderPressed(int)), SLOT(panPressed())); + connect(knob, SIGNAL(sliderReleased(int)), SLOT(panReleased())); + connect(knob, SIGNAL(sliderRightClicked(const QPoint &, int)), SLOT(panRightClicked(const QPoint &))); + } + else { + knob->setId(id); + + connect(pl, SIGNAL(valueChanged(double, int)), knob, SLOT(setValue(double))); + // Not used yet. Switch if/when necessary. + //connect(pl, SIGNAL(valueChanged(double, int)), SLOT(auxLabelChanged(double, int))); + + connect(knob, SIGNAL(sliderMoved(double, int)), SLOT(auxChanged(double, int))); + } + return knob; + } + +//--------------------------------------------------------- +// AudioStrip +//--------------------------------------------------------- + +AudioStrip::~AudioStrip() + { + } + + +//--------------------------------------------------------- +// AudioStrip +// create mixer strip +//--------------------------------------------------------- + +AudioStrip::AudioStrip(QWidget* parent, AudioTrack* at) + : Strip(parent, at) + { + + volume = -1.0; + panVal = 0; + + record = 0; + off = 0; + + AudioTrack* t = (AudioTrack*)track; + channel = at->channels(); + ///setMinimumWidth(STRIP_WIDTH); + //grid->setVerticalSpacing(4); + + int ch = 0; + for (; ch < channel; ++ch) + meter[ch] = new Meter(this); + for (; ch < MAX_CHANNELS; ++ch) + meter[ch] = 0; + + //--------------------------------------------------- + // plugin rack + //--------------------------------------------------- + + rack = new EffectRack(this, t); + rack->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); + grid->addWidget(rack, _curGridRow++, 0, 1, 2); + + //--------------------------------------------------- + // mono/stereo pre/post + //--------------------------------------------------- + + stereo = new QToolButton(); + stereo->setFont(config.fonts[1]); + QIcon stereoSet; + stereoSet.addPixmap(*monoIcon, QIcon::Normal, QIcon::Off); + stereoSet.addPixmap(*stereoIcon, QIcon::Normal, QIcon::On); + stereo->setIcon(stereoSet); + stereo->setIconSize(monoIcon->size()); + + stereo->setCheckable(true); + stereo->setObjectName("btnStereo"); + stereo->setToolTip(tr("1/2 channel")); + stereo->setChecked(channel == 2); + stereo->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum)); + connect(stereo, SIGNAL(clicked(bool)), SLOT(stereoToggled(bool))); + + // disable mono/stereo for Synthesizer-Plugins + if (t->type() == Track::AUDIO_SOFTSYNTH) + stereo->setEnabled(false); + + pre = new QToolButton(); + pre->setFont(config.fonts[1]); + pre->setCheckable(true); + //pre->setText(tr("Pre")); + QIcon preSet; + preSet.addPixmap(*preIcon, QIcon::Normal, QIcon::Off); + preSet.addPixmap(*preIconOn, QIcon::Normal, QIcon::On); + //preSet.addPixmap(*muteIcon, QIcon::Active, QIcon::On); + pre->setIcon(preSet); + pre->setObjectName("btnPre"); + pre->setIconSize(preIcon->size()); + pre->setToolTip(tr("pre fader - post fader")); + pre->setChecked(t->prefader()); + pre->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum)); + connect(pre, SIGNAL(clicked(bool)), SLOT(preToggled(bool))); + //pre->setAttribute(Qt::WA_Hover); + + grid->addItem(new QSpacerItem(0, 4), _curGridRow++, 0); + grid->addWidget(stereo, _curGridRow, 0); + grid->addWidget(pre, _curGridRow++, 1); + + //--------------------------------------------------- + // aux send + //--------------------------------------------------- + + int auxsSize = song->auxs()->size(); + if (t->hasAuxSend()) { + grid->addItem(new QSpacerItem(0, 4), _curGridRow++, 0); + for (int idx = 0; idx < auxsSize; ++idx) { + DoubleLabel* al; + Knob* ak = addKnob(1, idx, &al); + auxKnob.push_back(ak); + auxLabel.push_back(al); + double val = fast_log10(t->auxSend(idx))*20.0; + ak->setValue(val); + al->setValue(val); + } + } + else { + ///if (auxsSize) + //layout->addSpacing((STRIP_WIDTH/2 + 2) * auxsSize); + ///grid->addSpacing((STRIP_WIDTH/2 + 2) * auxsSize); // ??? + } + + grid->addItem(new QSpacerItem(0, 10), _curGridRow++, 0); + //--------------------------------------------------- + // slider, label, meter + //--------------------------------------------------- + + sliderGrid = new QGridLayout(); + sliderGrid->setRowStretch(0, 100); + sliderGrid->setContentsMargins(0, 0, 8, 0); + sliderGrid->setSpacing(0); + + slider = new Slider(this, "vol", Qt::Vertical, Slider::None, Slider::BgSlot); + slider->setCursorHoming(true); + slider->setRange(config.minSlider-0.1, 10.0); + slider->setFixedWidth(20); + slider->setFont(config.fonts[1]); + slider->setValue(fast_log10(t->volume())*20.0); + + sliderGrid->addWidget(slider, 0, 0, Qt::AlignHCenter); + + for (int i = 0; i < channel; ++i) { + //meter[i]->setRange(config.minSlider, 10.0); + meter[i]->setRange(config.minMeter, 10.0); + meter[i]->setFixedWidth(15); + connect(meter[i], SIGNAL(mousePress()), this, SLOT(resetPeaks())); + connect(meter[i], SIGNAL(meterClipped()), this, SLOT(playbackClipped())); + sliderGrid->addWidget(meter[i], 0, i+1);// , Qt::AlignHCenter); + sliderGrid->setColumnStretch(i, 50); + } + grid->addLayout(sliderGrid, _curGridRow++, 0, 1, 2); + + sl = new DoubleLabel(0.0, config.minSlider, 10.0, this); + sl->setSlider(slider); + sl->setFont(config.fonts[1]); + sl->setBackgroundRole(QPalette::Mid); + sl->setSuffix(tr("dB")); + sl->setFrame(true); + sl->setPrecision(0); + sl->setSizePolicy(QSizePolicy(QSizePolicy::Maximum, QSizePolicy::Minimum)); + sl->setValue(fast_log10(t->volume()) * 20.0); + slDefaultStyle = sl->styleSheet(); + + connect(sl, SIGNAL(valueChanged(double,int)), SLOT(volLabelChanged(double))); + //connect(sl, SIGNAL(valueChanged(double,int)), SLOT(volumeChanged(double))); + connect(slider, SIGNAL(valueChanged(double,int)), sl, SLOT(setValue(double))); + connect(slider, SIGNAL(sliderMoved(double,int)), SLOT(volumeChanged(double))); + connect(slider, SIGNAL(sliderPressed(int)), SLOT(volumePressed())); + connect(slider, SIGNAL(sliderReleased(int)), SLOT(volumeReleased())); + connect(slider, SIGNAL(sliderRightClicked(const QPoint &, int)), SLOT(volumeRightClicked(const QPoint &))); + grid->addItem(new QSpacerItem(0, 6), _curGridRow++, 0); + grid->addWidget(sl, _curGridRow++, 0, 1, 2, Qt::AlignCenter); + grid->addItem(new QSpacerItem(0, 8), _curGridRow++, 0); + + //--------------------------------------------------- + // pan, balance + //--------------------------------------------------- + + pan = addKnob(0, 0, &panl); + pan->setValue(t->pan()); + + //--------------------------------------------------- + // mute, solo, record + //--------------------------------------------------- + + record = new TransparentToolButton(this); + if (track->canRecord()) + { + record->setCheckable(true); + record->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum)); + record->setBackgroundRole(QPalette::Mid); + QIcon iconSet; + iconSet.addPixmap(*record_on_Icon, QIcon::Normal, QIcon::On); + iconSet.addPixmap(*record_off_Icon, QIcon::Normal, QIcon::Off); + record->setIcon(iconSet); + record->setIconSize(record_on_Icon->size()); + record->setToolTip(tr("record")); + record->setObjectName("btnRecord"); + record->setChecked(t->recordFlag()); + connect(record, SIGNAL(clicked(bool)), SLOT(recordToggled(bool))); + grid->addItem(new QSpacerItem(0, 2), _curGridRow++, 0); + } + else + { + record->setCheckable(false); + record->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum)); + record->setBackgroundRole(QPalette::Mid); + QIcon iconSet; + iconSet.addPixmap(*blankRecord, QIcon::Normal, QIcon::On); + record->setIcon(iconSet); + record->setObjectName("btnRecord"); + record->setIconSize(record_on_Icon->size()); + grid->addItem(new QSpacerItem(0, 2), _curGridRow++, 0); + + } + + grid->addItem(new QSpacerItem(0, 8), _curGridRow++, 0); + + Track::TrackType type = t->type(); + + mute = new QToolButton(); + QIcon muteSet; + muteSet.addPixmap(*muteIconOn, QIcon::Normal, QIcon::Off); + muteSet.addPixmap(*muteIconOff, QIcon::Normal, QIcon::On); + mute->setIcon(muteSet); + mute->setIconSize(muteIconOn->size()); + mute->setCheckable(true); + mute->setToolTip(tr("mute")); + mute->setObjectName("btnMute"); + mute->setChecked(t->mute()); + mute->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum)); + connect(mute, SIGNAL(clicked(bool)), SLOT(muteToggled(bool))); + + solo = new QToolButton(); + + if((bool)t->internalSolo()) + { + solo->setIcon(*soloIconSet2); + solo->setIconSize(soloIconOn->size()); + useSoloIconSet2 = true; + } + else + { + solo->setIcon(*soloIconSet1); + solo->setIconSize(soloblksqIconOn->size()); + useSoloIconSet2 = false; + } + + solo->setCheckable(true); + solo->setChecked(t->solo()); + solo->setObjectName("btnSolo"); + solo->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum)); + connect(solo, SIGNAL(clicked(bool)), SLOT(soloToggled(bool))); + if (type == Track::AUDIO_OUTPUT) { + record->setToolTip(tr("record downmix")); + //solo->setToolTip(tr("solo mode (monitor)")); + solo->setToolTip(tr("solo mode")); + } + else { + //solo->setToolTip(tr("pre fader listening")); + solo->setToolTip(tr("solo mode")); + } + + off = new TransparentToolButton(this); + QIcon iconSet; + iconSet.addPixmap(*exit1Icon, QIcon::Normal, QIcon::On); + iconSet.addPixmap(*exitIcon, QIcon::Normal, QIcon::Off); + off->setIcon(iconSet); + off->setObjectName("btnExit"); + off->setIconSize(exit1Icon->size()); + off->setBackgroundRole(QPalette::Mid); + off->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum)); + off->setCheckable(true); + off->setToolTip(tr("off")); + off->setChecked(t->off()); + connect(off, SIGNAL(clicked(bool)), SLOT(offToggled(bool))); + + grid->addWidget(off, _curGridRow, 0); + if (record) + grid->addWidget(record, _curGridRow, 1); + ++_curGridRow; + grid->addWidget(mute, _curGridRow, 0); + grid->addWidget(solo, _curGridRow++, 1); + + //--------------------------------------------------- + // routing + //--------------------------------------------------- + + if (type != Track::AUDIO_AUX) { + iR = new QToolButton(); + iR->setFont(config.fonts[1]); + iR->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum)); + //iR->setText(tr("iR")); + iR->setIcon(*mixerIn); + iR->setObjectName("btnIns"); + iR->setIconSize(mixerIn->size()); + iR->setCheckable(false); + iR->setToolTip(tr("input routing")); + grid->addWidget(iR, _curGridRow, 0); + connect(iR, SIGNAL(pressed()), SLOT(iRoutePressed())); + } + + oR = new QToolButton(); + oR->setFont(config.fonts[1]); + oR->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum)); + //oR->setText(tr("oR")); + oR->setIcon(*mixerOut); + oR->setObjectName("btnOuts"); + oR->setIconSize(mixerOut->size()); + oR->setCheckable(false); + oR->setToolTip(tr("output routing")); + grid->addWidget(oR, _curGridRow++, 1); + connect(oR, SIGNAL(pressed()), SLOT(oRoutePressed())); + + grid->addItem(new QSpacerItem(0, 5), _curGridRow++, 0); + //--------------------------------------------------- + // automation type + //--------------------------------------------------- + + autoType = new ComboBox(this); + autoType->setFont(config.fonts[1]); + autoType->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum)); + autoType->setAlignment(Qt::AlignCenter); + + autoType->insertItem(tr("Off"), AUTO_OFF); + autoType->insertItem(tr("Read"), AUTO_READ); + autoType->insertItem(tr("Touch"), AUTO_TOUCH); + autoType->insertItem(tr("Write"), AUTO_WRITE); + autoType->setCurrentItem(t->automationType()); + // FIXME: TODO: Convert ComboBox to QT4 + //autoType->insertItem(AUTO_OFF, tr("Off")); + //autoType->insertItem(AUTO_READ, tr("Read")); + //autoType->insertItem(AUTO_TOUCH, tr("Touch")); + //autoType->insertItem(AUTO_WRITE, tr("Write")); + //autoType->setCurrentIndex(t->automationType()); + + if(t->automationType() == AUTO_TOUCH || t->automationType() == AUTO_WRITE) + { + // FIXME: + //autoType->setPaletteBackgroundColor(Qt::red); + QPalette palette; + palette.setColor(autoType->backgroundRole(), QColor(Qt::red)); + autoType->setPalette(palette); + } + else + { + // FIXME: + //autoType->setPaletteBackgroundColor(qApp->palette().active().background()); + QPalette palette; + palette.setColor(autoType->backgroundRole(), qApp->palette().color(QPalette::Active, QPalette::Background)); + autoType->setPalette(palette); + } + autoType->setToolTip(tr("automation type")); + connect(autoType, SIGNAL(activated(int,int)), SLOT(setAutomationType(int,int))); + grid->addWidget(autoType, _curGridRow++, 0, 1, 2); + grid->addItem(new QSpacerItem(0, 5), _curGridRow++, 0); + QLabel* toprack = new QLabel(); + toprack->setPixmap(QPixmap(":/images/bottom_rack.png")); + grid->addWidget(toprack, _curGridRow++, 0, 1, 2); + + if (off) { + off->blockSignals(true); + updateOffState(); // init state + off->blockSignals(false); + } + connect(heartBeatTimer, SIGNAL(timeout()), SLOT(heartBeat())); + } + +//--------------------------------------------------------- +// addMenuItem +//--------------------------------------------------------- + +static int addMenuItem(AudioTrack* track, Track* route_track, PopupMenu* lb, int id, RouteMenuMap& mm, int channel, int channels, bool isOutput) +{ + // totalInChannels is only used by syntis. + int toch = ((AudioTrack*)track)->totalOutChannels(); + // If track channels = 1, it must be a mono synth. And synti channels cannot be changed by user. + if(track->channels() == 1) + toch = 1; + + // Don't add the last stray mono route if the track is stereo. + //if(route_track->channels() > 1 && (channel+1 == chans)) + // return id; + + RouteList* rl = isOutput ? track->outRoutes() : track->inRoutes(); + + QAction* act; + + QString s(route_track->name()); + + act = lb->addAction(s); + act->setData(id); + act->setCheckable(true); + + int ach = channel; + int bch = -1; + + Route r(route_track, isOutput ? ach : bch, channels); + + r.remoteChannel = isOutput ? bch : ach; + + mm.insert( pRouteMenuMap(id, r) ); + + for(iRoute ir = rl->begin(); ir != rl->end(); ++ir) + { + if(ir->type == Route::TRACK_ROUTE && ir->track == route_track && ir->remoteChannel == r.remoteChannel) + { + int tcompch = r.channel; + if(tcompch == -1) + tcompch = 0; + int tcompchs = r.channels; + if(tcompchs == -1) + tcompchs = isOutput ? track->channels() : route_track->channels(); + + int compch = ir->channel; + if(compch == -1) + compch = 0; + int compchs = ir->channels; + if(compchs == -1) + compchs = isOutput ? track->channels() : ir->track->channels(); + + if(compch == tcompch && compchs == tcompchs) + { + act->setChecked(true); + break; + } + } + } + return ++id; +} + +//--------------------------------------------------------- +// addAuxPorts +//--------------------------------------------------------- + +static int addAuxPorts(AudioTrack* t, PopupMenu* lb, int id, RouteMenuMap& mm, int channel, int channels, bool isOutput) + { + AuxList* al = song->auxs(); + for (iAudioAux i = al->begin(); i != al->end(); ++i) { + Track* track = *i; + if (t == track) + continue; + id = addMenuItem(t, track, lb, id, mm, channel, channels, isOutput); + } + return id; + } + +//--------------------------------------------------------- +// addInPorts +//--------------------------------------------------------- + +static int addInPorts(AudioTrack* t, PopupMenu* lb, int id, RouteMenuMap& mm, int channel, int channels, bool isOutput) + { + InputList* al = song->inputs(); + for (iAudioInput i = al->begin(); i != al->end(); ++i) { + Track* track = *i; + if (t == track) + continue; + id = addMenuItem(t, track, lb, id, mm, channel, channels, isOutput); + } + return id; + } + +//--------------------------------------------------------- +// addOutPorts +//--------------------------------------------------------- + +static int addOutPorts(AudioTrack* t, PopupMenu* lb, int id, RouteMenuMap& mm, int channel, int channels, bool isOutput) + { + OutputList* al = song->outputs(); + for (iAudioOutput i = al->begin(); i != al->end(); ++i) { + Track* track = *i; + if (t == track) + continue; + id = addMenuItem(t, track, lb, id, mm, channel, channels, isOutput); + } + return id; + } + +//--------------------------------------------------------- +// addGroupPorts +//--------------------------------------------------------- + +static int addGroupPorts(AudioTrack* t, PopupMenu* lb, int id, RouteMenuMap& mm, int channel, int channels, bool isOutput) + { + GroupList* al = song->groups(); + for (iAudioGroup i = al->begin(); i != al->end(); ++i) { + Track* track = *i; + if (t == track) + continue; + id = addMenuItem(t, track, lb, id, mm, channel, channels, isOutput); + } + return id; + } + +//--------------------------------------------------------- +// addWavePorts +//--------------------------------------------------------- + +static int addWavePorts(AudioTrack* t, PopupMenu* lb, int id, RouteMenuMap& mm, int channel, int channels, bool isOutput) + { + WaveTrackList* al = song->waves(); + for (iWaveTrack i = al->begin(); i != al->end(); ++i) { + Track* track = *i; + if (t == track) + continue; + id = addMenuItem(t, track, lb, id, mm, channel, channels, isOutput); + } + return id; + } + +//--------------------------------------------------------- +// addSyntiPorts +//--------------------------------------------------------- + +static int addSyntiPorts(AudioTrack* t, PopupMenu* lb, int id, + RouteMenuMap& mm, int channel, int channels, bool isOutput) +{ + RouteList* rl = isOutput ? t->outRoutes() : t->inRoutes(); + + QAction* act; + + SynthIList* al = song->syntis(); + for (iSynthI i = al->begin(); i != al->end(); ++i) + { + Track* track = *i; + if (t == track) + continue; + int toch = ((AudioTrack*)track)->totalOutChannels(); + // If track channels = 1, it must be a mono synth. And synti channels cannot be changed by user. + if(track->channels() == 1) + toch = 1; + + // totalInChannels is only used by syntis. + int chans = (!isOutput || track->type() != Track::AUDIO_SOFTSYNTH) ? toch : ((AudioTrack*)track)->totalInChannels(); + + int tchans = (channels != -1) ? channels: t->channels(); + if(tchans == 2) + { + // Ignore odd numbered left-over mono channel. + //chans = chans & ~1; + //if(chans != 0) + chans -= 1; + } + + if(chans > 0) + { + PopupMenu* chpup = new PopupMenu(lb); + chpup->setTitle(track->name()); + for(int ch = 0; ch < chans; ++ch) + { + char buffer[128]; + if(tchans == 2) + snprintf(buffer, 128, "%s %d,%d", chpup->tr("Channel").toLatin1().constData(), ch+1, ch+2); + else + snprintf(buffer, 128, "%s %d", chpup->tr("Channel").toLatin1().constData(), ch+1); + act = chpup->addAction(QString(buffer)); + act->setData(id); + act->setCheckable(true); + + int ach = (channel == -1) ? ch : channel; + int bch = (channel == -1) ? -1 : ch; + + Route rt(track, (t->type() != Track::AUDIO_SOFTSYNTH || isOutput) ? ach : bch, tchans); + //Route rt(track, ch); + //rt.remoteChannel = -1; + rt.remoteChannel = (t->type() != Track::AUDIO_SOFTSYNTH || isOutput) ? bch : ach; + + mm.insert( pRouteMenuMap(id, rt) ); + + for(iRoute ir = rl->begin(); ir != rl->end(); ++ir) + { + if(ir->type == Route::TRACK_ROUTE && ir->track == track && ir->remoteChannel == rt.remoteChannel) + { + int tcompch = rt.channel; + if(tcompch == -1) + tcompch = 0; + int tcompchs = rt.channels; + if(tcompchs == -1) + tcompchs = isOutput ? t->channels() : track->channels(); + + int compch = ir->channel; + if(compch == -1) + compch = 0; + int compchs = ir->channels; + if(compchs == -1) + compchs = isOutput ? t->channels() : ir->track->channels(); + + if(compch == tcompch && compchs == tcompchs) + { + act->setChecked(true); + break; + } + } + } + ++id; + } + + lb->addMenu(chpup); + } + } + return id; +} + +//--------------------------------------------------------- +// addMultiChannelOutPorts +//--------------------------------------------------------- + +static int addMultiChannelPorts(AudioTrack* t, PopupMenu* pup, int id, RouteMenuMap& mm, bool isOutput) +{ + int toch = t->totalOutChannels(); + // If track channels = 1, it must be a mono synth. And synti channels cannot be changed by user. + if(t->channels() == 1) + toch = 1; + + // Number of allocated buffers is always MAX_CHANNELS or more, even if _totalOutChannels is less. + // totalInChannels is only used by syntis. + int chans = (isOutput || t->type() != Track::AUDIO_SOFTSYNTH) ? toch : t->totalInChannels(); + + if(chans > 1) + pup->addAction(new MenuTitleItem("<Mono>", pup)); + + // + // If it's more than one channel, create a sub-menu. If it's just one channel, don't bother with a sub-menu... + // + + PopupMenu* chpup = pup; + + for(int ch = 0; ch < chans; ++ch) + { + // If more than one channel, create the sub-menu. + if(chans > 1) + chpup = new PopupMenu(pup); + + if(isOutput) + { + switch(t->type()) + { + + case Track::AUDIO_INPUT: + id = addWavePorts(t, chpup, id, mm, ch, 1, isOutput); + case Track::WAVE: + case Track::AUDIO_GROUP: + case Track::AUDIO_SOFTSYNTH: + id = addOutPorts(t, chpup, id, mm, ch, 1, isOutput); + id = addGroupPorts(t, chpup, id, mm, ch, 1, isOutput); + id = addSyntiPorts(t, chpup, id, mm, ch, 1, isOutput); + break; + case Track::AUDIO_AUX: + id = addOutPorts(t, chpup, id, mm, ch, 1, isOutput); + break; + default: + break; + } + } + else + { + switch(t->type()) + { + + case Track::AUDIO_OUTPUT: + id = addWavePorts(t, chpup, id, mm, ch, 1, isOutput); + id = addInPorts(t, chpup, id, mm, ch, 1, isOutput); + id = addGroupPorts(t, chpup, id, mm, ch, 1, isOutput); + id = addAuxPorts(t, chpup, id, mm, ch, 1, isOutput); + id = addSyntiPorts(t, chpup, id, mm, ch, 1, isOutput); + break; + case Track::WAVE: + id = addInPorts(t, chpup, id, mm, ch, 1, isOutput); + break; + case Track::AUDIO_SOFTSYNTH: + case Track::AUDIO_GROUP: + id = addWavePorts(t, chpup, id, mm, ch, 1, isOutput); + id = addInPorts(t, chpup, id, mm, ch, 1, isOutput); + id = addGroupPorts(t, chpup, id, mm, ch, 1, isOutput); + id = addSyntiPorts(t, chpup, id, mm, ch, 1, isOutput); + break; + default: + break; + } + } + + // If more than one channel, add the created sub-menu. + if(chans > 1) + { + char buffer[128]; + snprintf(buffer, 128, "%s %d", pup->tr("Channel").toLatin1().constData(), ch+1); + chpup->setTitle(QString(buffer)); + pup->addMenu(chpup); + } + } + + // For stereo listing, ignore odd numbered left-over channels. + chans -= 1; + if(chans > 0) + { + // Ignore odd numbered left-over channels. + //int schans = (chans & ~1) - 1; + + pup->addSeparator(); + pup->addAction(new MenuTitleItem("<Stereo>", pup)); + + // + // If it's more than two channels, create a sub-menu. If it's just two channels, don't bother with a sub-menu... + // + + chpup = pup; + if(chans <= 2) + // Just do one iteration. + chans = 1; + + for(int ch = 0; ch < chans; ++ch) + { + // If more than two channels, create the sub-menu. + if(chans > 2) + chpup = new PopupMenu(pup); + + if(isOutput) + { + switch(t->type()) + { + case Track::AUDIO_INPUT: + id = addWavePorts(t, chpup, id, mm, ch, 2, isOutput); + case Track::WAVE: + case Track::AUDIO_GROUP: + case Track::AUDIO_SOFTSYNTH: + id = addOutPorts(t, chpup, id, mm, ch, 2, isOutput); + id = addGroupPorts(t, chpup, id, mm, ch, 2, isOutput); + id = addSyntiPorts(t, chpup, id, mm, ch, 2, isOutput); + break; + case Track::AUDIO_AUX: + id = addOutPorts(t, chpup, id, mm, ch, 2, isOutput); + break; + default: + break; + } + } + else + { + switch(t->type()) + { + case Track::AUDIO_OUTPUT: + id = addWavePorts(t, chpup, id, mm, ch, 2, isOutput); + id = addInPorts(t, chpup, id, mm, ch, 2, isOutput); + id = addGroupPorts(t, chpup, id, mm, ch, 2, isOutput); + id = addAuxPorts(t, chpup, id, mm, ch, 2, isOutput); + id = addSyntiPorts(t, chpup, id, mm, ch, 2, isOutput); + break; + case Track::WAVE: + id = addInPorts(t, chpup, id, mm, ch, 2, isOutput); + break; + case Track::AUDIO_SOFTSYNTH: + case Track::AUDIO_GROUP: + id = addWavePorts(t, chpup, id, mm, ch, 2, isOutput); + id = addInPorts(t, chpup, id, mm, ch, 2, isOutput); + id = addGroupPorts(t, chpup, id, mm, ch, 2, isOutput); + id = addSyntiPorts(t, chpup, id, mm, ch, 2, isOutput); + break; + default: + break; + } + } + + // If more than two channels, add the created sub-menu. + if(chans > 2) + { + char buffer[128]; + snprintf(buffer, 128, "%s %d,%d", pup->tr("Channel").toLatin1().constData(), ch+1, ch+2); + chpup->setTitle(QString(buffer)); + pup->addMenu(chpup); + } + } + } + + return id; +} + +//--------------------------------------------------------- +// nonSyntiTrackAddSyntis +//--------------------------------------------------------- + +static int nonSyntiTrackAddSyntis(AudioTrack* t, PopupMenu* lb, int id, RouteMenuMap& mm, bool isOutput) +{ + RouteList* rl = isOutput ? t->outRoutes() : t->inRoutes(); + + QAction* act; + SynthIList* al = song->syntis(); + for (iSynthI i = al->begin(); i != al->end(); ++i) + { + Track* track = *i; + if (t == track) + continue; + + int toch = ((AudioTrack*)track)->totalOutChannels(); + // If track channels = 1, it must be a mono synth. And synti channels cannot be changed by user. + if(track->channels() == 1) + toch = 1; + + // totalInChannels is only used by syntis. + int chans = (!isOutput || track->type() != Track::AUDIO_SOFTSYNTH) ? toch : ((AudioTrack*)track)->totalInChannels(); + + //int schans = synti->channels(); + //if(schans < chans) + // chans = schans; +// int tchans = (channels != -1) ? channels: t->channels(); +// if(tchans == 2) +// { + // Ignore odd numbered left-over mono channel. + //chans = chans & ~1; + //if(chans != 0) +// chans -= 1; +// } + //int tchans = (channels != -1) ? channels: t->channels(); + + if(chans > 0) + { + PopupMenu* chpup = new PopupMenu(lb); + chpup->setTitle(track->name()); + if(chans > 1) + chpup->addAction(new MenuTitleItem("<Mono>", chpup)); + + for(int ch = 0; ch < chans; ++ch) + { + char buffer[128]; + snprintf(buffer, 128, "%s %d", chpup->tr("Channel").toLatin1().constData(), ch+1); + act = chpup->addAction(QString(buffer)); + act->setData(id); + act->setCheckable(true); + + int ach = ch; + int bch = -1; + + Route rt(track, isOutput ? bch : ach, 1); + + rt.remoteChannel = isOutput ? ach : bch; + + mm.insert( pRouteMenuMap(id, rt) ); + + for(iRoute ir = rl->begin(); ir != rl->end(); ++ir) + { + if(ir->type == Route::TRACK_ROUTE && ir->track == track && ir->remoteChannel == rt.remoteChannel) + { + int tcompch = rt.channel; + if(tcompch == -1) + tcompch = 0; + int tcompchs = rt.channels; + if(tcompchs == -1) + tcompchs = isOutput ? t->channels() : track->channels(); + + int compch = ir->channel; + if(compch == -1) + compch = 0; + int compchs = ir->channels; + if(compchs == -1) + compchs = isOutput ? t->channels() : ir->track->channels(); + + if(compch == tcompch && compchs == tcompchs) + { + act->setChecked(true); + break; + } + } + } + ++id; + } + + chans -= 1; + if(chans > 0) + { + // Ignore odd numbered left-over channels. + //int schans = (chans & ~1) - 1; + + chpup->addSeparator(); + chpup->addAction(new MenuTitleItem("<Stereo>", chpup)); + + for(int ch = 0; ch < chans; ++ch) + { + char buffer[128]; + snprintf(buffer, 128, "%s %d,%d", chpup->tr("Channel").toLatin1().constData(), ch+1, ch+2); + act = chpup->addAction(QString(buffer)); + act->setData(id); + act->setCheckable(true); + + int ach = ch; + int bch = -1; + + Route rt(track, isOutput ? bch : ach, 2); + + rt.remoteChannel = isOutput ? ach : bch; + + mm.insert( pRouteMenuMap(id, rt) ); + + for(iRoute ir = rl->begin(); ir != rl->end(); ++ir) + { + if(ir->type == Route::TRACK_ROUTE && ir->track == track && ir->remoteChannel == rt.remoteChannel) + { + int tcompch = rt.channel; + if(tcompch == -1) + tcompch = 0; + int tcompchs = rt.channels; + if(tcompchs == -1) + tcompchs = isOutput ? t->channels() : track->channels(); + + int compch = ir->channel; + if(compch == -1) + compch = 0; + int compchs = ir->channels; + if(compchs == -1) + compchs = isOutput ? t->channels() : ir->track->channels(); + + if(compch == tcompch && compchs == tcompchs) + { + act->setChecked(true); + break; + } + } + } + ++id; + } + } + + lb->addMenu(chpup); + } + } + return id; +} + +//--------------------------------------------------------- +// iRoutePressed +//--------------------------------------------------------- + +void AudioStrip::iRoutePressed() + { + //if(track->isMidiTrack() || (track->type() == Track::AUDIO_AUX) || (track->type() == Track::AUDIO_SOFTSYNTH)) + if(!track || track->isMidiTrack() || track->type() == Track::AUDIO_AUX) + { + gRoutingPopupMenuMaster = 0; + return; + } + + QPoint ppt = QCursor::pos(); + + PopupMenu* pup = muse->getRoutingPopupMenu(); + pup->disconnect(); + + + AudioTrack* t = (AudioTrack*)track; + RouteList* irl = t->inRoutes(); + + QAction* act = 0; + int gid = 0; + int id = 0; + + pup->clear(); + gRoutingMenuMap.clear(); + gid = 0; + + switch(track->type()) + { + case Track::AUDIO_INPUT: + { + for(int i = 0; i < channel; ++i) + { + char buffer[128]; + snprintf(buffer, 128, "%s %d", tr("Channel").toLatin1().constData(), i+1); + MenuTitleItem* titel = new MenuTitleItem(QString(buffer), pup); + pup->addAction(titel); + + if(!checkAudioDevice()) + { + gRoutingPopupMenuMaster = 0; + pup->clear(); + gRoutingMenuMap.clear(); + iR->setDown(false); + return; + } + std::list<QString> ol = audioDevice->outputPorts(); + + if(ol.size() >= 75 && ol.size() <= 125) + { + pup->setStyleSheet("font-size:8pt"); + } + else if(ol.size() >= 126) + { + pup->setStyleSheet("font-size:6pt; font-family:'fixed'; "); + } + + for(std::list<QString>::iterator ip = ol.begin(); ip != ol.end(); ++ip) + { + id = gid * 16 + i; + act = pup->addAction(*ip); + act->setData(id); + act->setCheckable(true); + + Route dst(*ip, true, i, Route::JACK_ROUTE); + gRoutingMenuMap.insert( pRouteMenuMap(id, dst) ); + ++gid; + for(iRoute ir = irl->begin(); ir != irl->end(); ++ir) + { + if(*ir == dst) + { + act->setChecked(true); + break; + } + } + } + if(i+1 != channel) + pup->addSeparator(); + } + } + break; + //case Track::AUDIO_OUTPUT: + //case Track::WAVE: + //case Track::AUDIO_GROUP: + + case Track::AUDIO_OUTPUT: + gid = addWavePorts( t, pup, gid, gRoutingMenuMap, -1, -1, false); + gid = addInPorts( t, pup, gid, gRoutingMenuMap, -1, -1, false); + gid = addGroupPorts(t, pup, gid, gRoutingMenuMap, -1, -1, false); + gid = addAuxPorts( t, pup, gid, gRoutingMenuMap, -1, -1, false); + gid = nonSyntiTrackAddSyntis(t, pup, gid, gRoutingMenuMap, false); + break; + case Track::WAVE: + gid = addInPorts( t, pup, gid, gRoutingMenuMap, -1, -1, false); + break; + case Track::AUDIO_GROUP: + gid = addWavePorts( t, pup, gid, gRoutingMenuMap, -1, -1, false); + gid = addInPorts( t, pup, gid, gRoutingMenuMap, -1, -1, false); + gid = addGroupPorts(t, pup, gid, gRoutingMenuMap, -1, -1, false); + gid = nonSyntiTrackAddSyntis(t, pup, gid, gRoutingMenuMap, false); + break; + + case Track::AUDIO_SOFTSYNTH: + gid = addMultiChannelPorts(t, pup, gid, gRoutingMenuMap, false); + break; + default: + gRoutingPopupMenuMaster = 0; + pup->clear(); + gRoutingMenuMap.clear(); + iR->setDown(false); + return; + } + + if(pup->actions().isEmpty()) + { + gRoutingPopupMenuMaster = 0; + gRoutingMenuMap.clear(); + iR->setDown(false); + return; + } + + gIsOutRoutingPopupMenu = false; + gRoutingPopupMenuMaster = this; + connect(pup, SIGNAL(triggered(QAction*)), SLOT(routingPopupMenuActivated(QAction*))); + connect(pup, SIGNAL(aboutToHide()), muse, SLOT(routingPopupMenuAboutToHide())); + pup->popup(ppt); + iR->setDown(false); + } + +//--------------------------------------------------------- +// routingPopupMenuActivated +//--------------------------------------------------------- + +void AudioStrip::routingPopupMenuActivated(QAction* act) +{ + if(!track || gRoutingPopupMenuMaster != this || track->isMidiTrack()) + return; + + PopupMenu* pup = muse->getRoutingPopupMenu(); + + if(pup->actions().isEmpty()) + return; + + AudioTrack* t = (AudioTrack*)track; + RouteList* rl = gIsOutRoutingPopupMenu ? t->outRoutes() : t->inRoutes(); + + int n = act->data().toInt(); + if (n == -1) + return; + + if(gIsOutRoutingPopupMenu) + { + if(track->type() == Track::AUDIO_OUTPUT) + { + + int chan = n & 0xf; + + Route srcRoute(t, chan); + Route dstRoute(act->text(), true, -1, Route::JACK_ROUTE); + dstRoute.channel = chan; + + // check if route src->dst exists: + iRoute irl = rl->begin(); + for (; irl != rl->end(); ++irl) { + if (*irl == dstRoute) + break; + } + if (irl != rl->end()) { + // disconnect if route exists + audio->msgRemoveRoute(srcRoute, dstRoute); + } + else { + // connect if route does not exist + audio->msgAddRoute(srcRoute, dstRoute); + } + audio->msgUpdateSoloStates(); + song->update(SC_ROUTE); + return; + } + + iRouteMenuMap imm = gRoutingMenuMap.find(n); + if(imm == gRoutingMenuMap.end()) + return; + + Route srcRoute(t, imm->second.channel, imm->second.channels); + srcRoute.remoteChannel = imm->second.remoteChannel; + + Route &dstRoute = imm->second; + + // check if route src->dst exists: + iRoute irl = rl->begin(); + for (; irl != rl->end(); ++irl) { + if (*irl == dstRoute) + break; + } + if (irl != rl->end()) { + // disconnect if route exists + audio->msgRemoveRoute(srcRoute, dstRoute); + } + else { + // connect if route does not exist + audio->msgAddRoute(srcRoute, dstRoute); + } + audio->msgUpdateSoloStates(); + song->update(SC_ROUTE); + } + else + { + if(track->type() == Track::AUDIO_INPUT) + { + int chan = n & 0xf; + + Route srcRoute(act->text(), false, -1, Route::JACK_ROUTE); + Route dstRoute(t, chan); + + srcRoute.channel = chan; + + iRoute irl = rl->begin(); + for(; irl != rl->end(); ++irl) + { + if(*irl == srcRoute) + break; + } + if(irl != rl->end()) + // disconnect + audio->msgRemoveRoute(srcRoute, dstRoute); + else + // connect + audio->msgAddRoute(srcRoute, dstRoute); + + audio->msgUpdateSoloStates(); + song->update(SC_ROUTE); + return; + } + + iRouteMenuMap imm = gRoutingMenuMap.find(n); + if(imm == gRoutingMenuMap.end()) + return; + + Route &srcRoute = imm->second; + + Route dstRoute(t, imm->second.channel, imm->second.channels); + dstRoute.remoteChannel = imm->second.remoteChannel; + + iRoute irl = rl->begin(); + for (; irl != rl->end(); ++irl) { + if (*irl == srcRoute) + break; + } + if (irl != rl->end()) { + // disconnect + audio->msgRemoveRoute(srcRoute, dstRoute); + } + else { + // connect + audio->msgAddRoute(srcRoute, dstRoute); + } + audio->msgUpdateSoloStates(); + song->update(SC_ROUTE); + } +} + +//--------------------------------------------------------- +// oRoutePressed +//--------------------------------------------------------- + +void AudioStrip::oRoutePressed() +{ + if(!track || track->isMidiTrack()) + { + gRoutingPopupMenuMaster = 0; + return; + } + + QPoint ppt = QCursor::pos(); + + PopupMenu* pup = muse->getRoutingPopupMenu(); + pup->disconnect(); + + AudioTrack* t = (AudioTrack*)track; + RouteList* orl = t->outRoutes(); + + QAction* act = 0; + int gid = 0; + int id = 0; + + pup->clear(); + gRoutingMenuMap.clear(); + gid = 0; + + switch(track->type()) + { + case Track::AUDIO_OUTPUT: + { + for(int i = 0; i < channel; ++i) + { + char buffer[128]; + snprintf(buffer, 128, "%s %d", tr("Channel").toLatin1().constData(), i+1); + MenuTitleItem* titel = new MenuTitleItem(QString(buffer), pup); + pup->addAction(titel); + + if(!checkAudioDevice()) + { + gRoutingPopupMenuMaster = 0; + pup->clear(); + gRoutingMenuMap.clear(); + oR->setDown(false); + return; + } + std::list<QString> ol = audioDevice->inputPorts(); + for(std::list<QString>::iterator ip = ol.begin(); ip != ol.end(); ++ip) + { + id = gid * 16 + i; + act = pup->addAction(*ip); + act->setData(id); + act->setCheckable(true); + + Route dst(*ip, true, i, Route::JACK_ROUTE); + gRoutingMenuMap.insert( pRouteMenuMap(id, dst) ); + ++gid; + for(iRoute ir = orl->begin(); ir != orl->end(); ++ir) + { + if(*ir == dst) + { + act->setChecked(true); + break; + } + } + } + if(i+1 != channel) + pup->addSeparator(); + } + } + break; + //case Track::AUDIO_INPUT: + //case Track::WAVE: + //case Track::AUDIO_GROUP: + + case Track::AUDIO_SOFTSYNTH: + gid = addMultiChannelPorts(t, pup, gid, gRoutingMenuMap, true); + break; + + case Track::AUDIO_INPUT: + gid = addWavePorts( t, pup, gid, gRoutingMenuMap, -1, -1, true); + case Track::WAVE: + case Track::AUDIO_GROUP: + case Track::AUDIO_AUX: + //case Track::AUDIO_SOFTSYNTH: + gid = addOutPorts( t, pup, gid, gRoutingMenuMap, -1, -1, true); + gid = addGroupPorts( t, pup, gid, gRoutingMenuMap, -1, -1, true); + gid = nonSyntiTrackAddSyntis(t, pup, gid, gRoutingMenuMap, true); + break; + //case Track::AUDIO_AUX: + // gid = addOutPorts( t, pup, gid, gRoutingMenuMap, -1, -1, true); + //break; + + default: + gRoutingPopupMenuMaster = 0; + pup->clear(); + gRoutingMenuMap.clear(); + oR->setDown(false); + return; + } + + if(pup->actions().isEmpty()) + { + gRoutingPopupMenuMaster = 0; + gRoutingMenuMap.clear(); + oR->setDown(false); + return; + } + + gIsOutRoutingPopupMenu = true; + gRoutingPopupMenuMaster = this; + connect(pup, SIGNAL(triggered(QAction*)), SLOT(routingPopupMenuActivated(QAction*))); + connect(pup, SIGNAL(aboutToHide()), muse, SLOT(routingPopupMenuAboutToHide())); + pup->popup(ppt); + oR->setDown(false); +} + +void AudioStrip::playbackClipped() +{ + sl->setStyleSheet("DoubleLabel { padding-left: 2px; border: 1px solid #9d9d9d; border-image: none; background-color: black; color: #ba0000; font-weight: normal;}"); +} + +//--------------------------------------------------------- +// resetPeaks +//--------------------------------------------------------- + +void AudioStrip::resetPeaks() +{ + track->resetPeaks(); + sl->setStyleSheet(slDefaultStyle); +} + |