diff --git a/data/themes/default/send_bg_arrow.png b/data/themes/default/send_bg_arrow.png new file mode 100644 index 000000000..fde514da6 Binary files /dev/null and b/data/themes/default/send_bg_arrow.png differ diff --git a/include/FxMixer.h b/include/FxMixer.h index 12d4af42a..116dbcde0 100644 --- a/include/FxMixer.h +++ b/include/FxMixer.h @@ -31,7 +31,6 @@ #include "JournallingObject.h" -const int NumFxChannels = 64; struct FxChannel @@ -54,6 +53,7 @@ struct FxChannel // pointers to other channels that this one sends to QVector m_sends; + QVector m_sendAmount; // pointers to other channels that send to this one QVector m_receives; @@ -86,26 +86,36 @@ public: FxChannel * effectChannel( int _ch ) { - if( _ch >= 0 && _ch <= NumFxChannels ) - { - return m_fxChannels[_ch]; - } - return NULL; + return m_fxChannels[_ch]; } // make the output of channel fromChannel go to the input of channel toChannel - void createChannelSend(fx_ch_t fromChannel, fx_ch_t toChannel); + // it is safe to call even if the send already exists + void createChannelSend(fx_ch_t fromChannel, fx_ch_t toChannel, + float amount = 1.0f); // delete the connection made by createChannelSend void deleteChannelSend(fx_ch_t fromChannel, fx_ch_t toChannel); - // does fromChannel send its output to the input of toChannel? - bool channelSendsTo(fx_ch_t fromChannel, fx_ch_t toChannel); + // return the FloatModel of fromChannel sending its output to the input of + // toChannel. NULL if there is no send. + FloatModel * channelSendModel(fx_ch_t fromChannel, fx_ch_t toChannel); + // add a new channel to the Fx Mixer. + // returns the index of the channel that was just added + int createChannel(); + // reset a channel's name, fx, sends, etc + void clearChannel(fx_ch_t channelIndex); + + inline fx_ch_t numChannels() const + { + return m_fxChannels.size(); + } private: - FxChannel * m_fxChannels[NumFxChannels+1]; // +1 = master + // the fx channels in the mixer. index 0 is always master. + QVector m_fxChannels; friend class mixerWorkerThread; friend class FxMixerView; diff --git a/include/FxMixerView.h b/include/FxMixerView.h index dab34caaf..297ab5061 100644 --- a/include/FxMixerView.h +++ b/include/FxMixerView.h @@ -26,6 +26,8 @@ #define _FX_MIXER_VIEW_H #include +#include +#include #include "FxMixer.h" #include "ModelView.h" @@ -61,7 +63,7 @@ public: private slots: void updateFaders(); - + void addNewChannel(); private: struct FxChannelView @@ -72,13 +74,15 @@ private: fader * m_fader; } ; - FxChannelView m_fxChannelViews[NumFxChannels+1]; + QVector m_fxChannelViews; QStackedLayout * m_fxRacksLayout; - QStackedLayout * m_fxLineBanks; - QButtonGroup * m_bankButtons; FxLine * m_currentFxLine; + QScrollArea * channelArea; + QHBoxLayout * chLayout; + + void addFxLine(int i, QWidget * parent, QLayout * layout); } ; #endif diff --git a/include/classic_style.h b/include/classic_style.h index ccd1b5482..629960133 100644 --- a/include/classic_style.h +++ b/include/classic_style.h @@ -59,7 +59,7 @@ public: // LMMS Stuff virtual void drawFxLine(QPainter * _painter, const QWidget *_fxLine, - const QString & _name, bool _active); + const QString & _name, bool _active, bool _sendToThis); virtual void drawTrackContentBackground(QPainter * _painter, const QSize & _size, const int _pixelsPerTact); diff --git a/include/cusis_style.h b/include/cusis_style.h index 3e359cfd1..f000b520f 100644 --- a/include/cusis_style.h +++ b/include/cusis_style.h @@ -66,7 +66,7 @@ public: virtual void unpolish( QWidget * widget ); virtual void drawFxLine( QPainter * _painter, const QWidget *_fxLine, - const QString & _name, bool _active ); + const QString & _name, bool _active, bool _sendToThis ); virtual void drawTrackContentBackground( QPainter * _painter, const QSize & _size, const int _pixelsPerTact ); diff --git a/include/lmms_style.h b/include/lmms_style.h index eb6b0635c..3018e27c0 100644 --- a/include/lmms_style.h +++ b/include/lmms_style.h @@ -91,7 +91,7 @@ public: virtual void drawFxLine(QPainter * _painter, const QWidget *_fxLine, - const QString & _name, bool _active) = 0; + const QString & _name, bool _active, bool _sendToThis) = 0; virtual void drawTrackContentBackground(QPainter * _painter, const QSize & _size, const int _pixelsPerTact) = 0; diff --git a/plugins/flp_import/FlpImport.cpp b/plugins/flp_import/FlpImport.cpp index 1c36b5c4b..b243c9427 100644 --- a/plugins/flp_import/FlpImport.cpp +++ b/plugins/flp_import/FlpImport.cpp @@ -104,7 +104,7 @@ extern QString outstring; } - +const int NumFLFxChannels = 64; static void dump_mem( const void * buffer, uint n_bytes ) { @@ -542,7 +542,7 @@ struct FL_Project int currentPattern; int activeEditPattern; - FL_EffectChannel effectChannels[NumFxChannels+1]; + FL_EffectChannel effectChannels[NumFLFxChannels+1]; int currentEffectChannel; QString projectNotes; @@ -1022,7 +1022,7 @@ bool FlpImport::tryFLPImport( trackContainer * _tc ) break; case FLP_EffectChannelMuted: -if( p.currentEffectChannel <= NumFxChannels ) +if( p.currentEffectChannel <= NumFLFxChannels ) { p.effectChannels[p.currentEffectChannel].isMuted = ( data & 0x08 ) > 0 ? false : true; @@ -1274,7 +1274,7 @@ if( p.currentEffectChannel <= NumFxChannels ) case FLP_Text_EffectChanName: ++p.currentEffectChannel; - if( p.currentEffectChannel <= NumFxChannels ) + if( p.currentEffectChannel <= NumFLFxChannels ) { p.effectChannels[p.currentEffectChannel].name = text; } @@ -1497,7 +1497,7 @@ if( p.currentEffectChannel <= NumFxChannels ) const int param = pi[i*3+1] & 0xffff; const int ch = ( pi[i*3+1] >> 22 ) & 0x7f; - if( ch < 0 || ch > NumFxChannels ) + if( ch < 0 || ch > NumFLFxChannels ) { continue; } @@ -1797,7 +1797,7 @@ p->putValue( jt->pos, value, false ); } } - for( int fx_ch = 0; fx_ch <= NumFxChannels ; ++fx_ch ) + for( int fx_ch = 0; fx_ch <= NumFLFxChannels ; ++fx_ch ) { FxChannel * ch = engine::fxMixer()->effectChannel( fx_ch ); if( !ch ) @@ -1857,7 +1857,7 @@ p->putValue( jt->pos, value, false ); break; } if( effName.isEmpty() || it->fxChannel < 0 || - it->fxChannel > NumFxChannels ) + it->fxChannel > NumFLFxChannels ) { continue; } diff --git a/src/core/FxMixer.cpp b/src/core/FxMixer.cpp index ce8351cad..53c1152a7 100644 --- a/src/core/FxMixer.cpp +++ b/src/core/FxMixer.cpp @@ -61,49 +61,64 @@ FxChannel::~FxChannel() FxMixer::FxMixer() : JournallingObject(), - Model( NULL ) + Model( NULL ), + m_fxChannels() { // create master channel - m_fxChannels[0] = new FxChannel(this); - - // create the rest of the channels - for( int i = 1; i < NumFxChannels+1; ++i ) - { - // create new channel - m_fxChannels[i] = new FxChannel( this ); - - // send the channel into master - createChannelSend(i, 0); - } - - // reset name etc. - clear(); + createChannel(); } - FxMixer::~FxMixer() { - for( int i = 0; i < NumFxChannels+1; ++i ) + for( int i = 0; i < m_fxChannels.size(); ++i ) { + delete m_fxChannels[i]->m_sendAmount[i]; delete m_fxChannels[i]; } } -void FxMixer::createChannelSend(fx_ch_t fromChannel, fx_ch_t toChannel) +int FxMixer::createChannel() { - // first make sure the send doesn't already exist - if( ! channelSendsTo(fromChannel, toChannel) ) - { - // add to from's sends - m_fxChannels[fromChannel]->m_sends.push_back(toChannel); + // create new channel + m_fxChannels.push_back(new FxChannel( this )); - // add to to's receives - m_fxChannels[toChannel]->m_receives.push_back(fromChannel); + // reset channel state + int index = m_fxChannels.size() - 1; + clearChannel(index); + + return index; +} + + + +void FxMixer::createChannelSend(fx_ch_t fromChannel, fx_ch_t toChannel, + float amount) +{ + // find the existing connection + FxChannel * from = m_fxChannels[fromChannel]; + for(int i=0; im_sends.size(); ++i){ + if( from->m_sends[i] == toChannel ) + { + // simply adjust the amount + from->m_sendAmount[i]->setValue(amount); + return; + } } + + // connection does not exist. create a new one + + // add to from's sends + from->m_sends.push_back(toChannel); + from->m_sendAmount.push_back(new FloatModel(amount, 0, 1, 0.001, NULL, + tr("Amount to send"))); + + // add to to's receives + m_fxChannels[toChannel]->m_receives.push_back(fromChannel); + } @@ -120,6 +135,8 @@ void FxMixer::deleteChannelSend(fx_ch_t fromChannel, fx_ch_t toChannel) if( from->m_sends[i] == toChannel ) { // delete this index + delete from->m_sendAmount[i]; + from->m_sendAmount.remove(i); from->m_sends.remove(i); break; } @@ -139,15 +156,15 @@ void FxMixer::deleteChannelSend(fx_ch_t fromChannel, fx_ch_t toChannel) -// does fromChannel send its output to the input of toChannel? -bool FxMixer::channelSendsTo(fx_ch_t fromChannel, fx_ch_t toChannel) +// how much does fromChannel send its output to the input of toChannel? +FloatModel * FxMixer::channelSendModel(fx_ch_t fromChannel, fx_ch_t toChannel) { FxChannel * from = m_fxChannels[fromChannel]; for(int i=0; im_sends.size(); ++i){ if( from->m_sends[i] == toChannel ) - return true; + return from->m_sendAmount[i]; } - return false; + return NULL; } @@ -182,12 +199,13 @@ void FxMixer::processChannel( fx_ch_t _ch, sampleFrame * _buf ) processChannel( senderIndex ); // mix it with this one + float amt = channelSendModel(senderIndex, _ch)->value(); sampleFrame * ch_buf = sender->m_buffer; const float v = sender->m_volumeModel.value(); for( f_cnt_t f = 0; f < fpp; ++f ) { - _buf[f][0] += ch_buf[f][0] * v; - _buf[f][1] += ch_buf[f][1] * v; + _buf[f][0] += ch_buf[f][0] * v * amt; + _buf[f][1] += ch_buf[f][1] * v * amt; } engine::getMixer()->clearAudioBuffer( ch_buf, engine::getMixer()->framesPerPeriod() ); @@ -233,13 +251,6 @@ void FxMixer::masterMix( sampleFrame * _buf ) processChannel( 0, _buf ); - /*if( m_fxChannels[0]->m_muteModel.value() ) - { - engine::getMixer()->clearAudioBuffer( _buf, - engine::getMixer()->framesPerPeriod() ); - return; - }*/ - const float v = m_fxChannels[0]->m_volumeModel.value(); for( f_cnt_t f = 0; f < engine::getMixer()->framesPerPeriod(); ++f ) { @@ -256,25 +267,46 @@ void FxMixer::masterMix( sampleFrame * _buf ) void FxMixer::clear() { - for( int i = 0; i <= NumFxChannels; ++i ) + for( int i = 0; i < m_fxChannels.size(); ++i ) { - m_fxChannels[i]->m_fxChain.clear(); - m_fxChannels[i]->m_volumeModel.setValue( 1.0f ); - m_fxChannels[i]->m_muteModel.setValue( false ); - m_fxChannels[i]->m_name = ( i == 0 ) ? - tr( "Master" ) : tr( "FX %1" ).arg( i ); - m_fxChannels[i]->m_volumeModel.setDisplayName( - m_fxChannels[i]->m_name ); - + clearChannel(i); } } +void FxMixer::clearChannel(fx_ch_t index) +{ + FxChannel * ch = m_fxChannels[index]; + ch->m_fxChain.clear(); + ch->m_volumeModel.setValue( 1.0f ); + ch->m_muteModel.setValue( false ); + ch->m_name = ( index == 0 ) ? tr( "Master" ) : tr( "FX %1" ).arg( index ); + ch->m_volumeModel.setDisplayName(ch->m_name ); + // send only to master + if( index > 0) + { + // delete existing sends + for( int i=0; im_sends.size(); ++i) + { + deleteChannelSend(index, ch->m_sends[i]); + } + + // add send to master + createChannelSend(index, 0); + } + + // delete receives + for( int i=0; im_receives.size(); ++i) + { + deleteChannelSend(ch->m_receives[i], index); + } + +} void FxMixer::saveSettings( QDomDocument & _doc, QDomElement & _this ) { - for( int i = 0; i <= NumFxChannels; ++i ) + for( int i = 0; i < m_fxChannels.size(); ++i ) { QDomElement fxch = _doc.createElement( QString( "fxchannel" ) ); _this.appendChild( fxch ); @@ -295,7 +327,7 @@ void FxMixer::loadSettings( const QDomElement & _this ) { clear(); QDomNode node = _this.firstChild(); - for( int i = 0; i <= NumFxChannels; ++i ) + for( int i = 0; i <= 64; ++i ) // TODO make this work { QDomElement fxch = node.toElement(); int num = fxch.attribute( "num" ).toInt(); diff --git a/src/core/mixer.cpp b/src/core/mixer.cpp index 35fdb62cd..819ef0be2 100644 --- a/src/core/mixer.cpp +++ b/src/core/mixer.cpp @@ -61,10 +61,6 @@ #endif -static QVector __fx_channel_jobs( NumFxChannels ); - - - class MixerWorkerThread : public QThread { public: @@ -284,11 +280,6 @@ mixer::mixer() : clearAudioBuffer( m_inputBuffer[i], m_inputBufferSize[i] ); } - for( int i = 1; i < NumFxChannels+1; ++i ) - { - __fx_channel_jobs[i-1] = (fx_ch_t) i; - } - // just rendering? if( !engine::hasGUI() ) { diff --git a/src/gui/FxMixerView.cpp b/src/gui/FxMixerView.cpp index bde8e5a04..3be23bcfe 100644 --- a/src/gui/FxMixerView.cpp +++ b/src/gui/FxMixerView.cpp @@ -22,6 +22,8 @@ * */ +#include + #include #include #include @@ -31,9 +33,12 @@ #include #include #include +#include + #include "FxMixerView.h" #include "fader.h" +#include "knob.h" #include "EffectRackView.h" #include "engine.h" #include "embed.h" @@ -44,26 +49,40 @@ #include "pixmap_button.h" +class SendIndicator : public QWidget +{ + public: + SendIndicator( QWidget * _parent ) : + QWidget( _parent ) + { + setFixedSize(23, 16); + } + +}; class FxLine : public QWidget { public: - FxLine( QWidget * _parent, FxMixerView * _mv, QString & _name ) : + FxLine( QWidget * _parent, FxMixerView * _mv, QString & _name, + int _channelIndex) : QWidget( _parent ), + m_channelIndex( _channelIndex ), m_mv( _mv ), m_name( _name ) { - setFixedSize( 32, 232 ); + setFixedSize( 32, 287 ); setAttribute( Qt::WA_OpaquePaintEvent, true ); setCursor( QCursor( embed::getIconPixmap( "hand" ), 0, 0 ) ); } virtual void paintEvent( QPaintEvent * ) { + bool sendToThis = engine::fxMixer()->channelSendModel( + m_mv->currentFxLine()->m_channelIndex, m_channelIndex) != NULL; QPainter painter; painter.begin( this ); - engine::getLmmsStyle()->drawFxLine( &painter, - this, m_name, m_mv->currentFxLine() == this ); + engine::getLmmsStyle()->drawFxLine( &painter, this, m_name, + m_mv->currentFxLine() == this, sendToThis ); painter.end(); } @@ -87,7 +106,8 @@ public: } } - + knob * m_sendKnob; + int m_channelIndex; private: FxMixerView * m_mv; QString & m_name; @@ -114,10 +134,6 @@ FxMixerView::FxMixerView() : setWindowTitle( tr( "FX-Mixer" ) ); setWindowIcon( embed::getIconPixmap( "fx_mixer" ) ); - m_fxLineBanks = new QStackedLayout; - m_fxLineBanks->setSpacing( 0 ); - m_fxLineBanks->setMargin( 1 ); - m_fxRacksLayout = new QStackedLayout; m_fxRacksLayout->setSpacing( 0 ); m_fxRacksLayout->setMargin( 0 ); @@ -128,93 +144,40 @@ FxMixerView::FxMixerView() : ml->setSpacing( 0 ); ml->addSpacing( 6 ); + m_fxChannelViews.resize(m->numChannels()); + channelArea = new QScrollArea(this); + chLayout = new QHBoxLayout(channelArea); - QHBoxLayout * banks[NumFxChannels/16]; - for( int i = 0; i < NumFxChannels/16; ++i ) + // add master channel + FxChannelView * masterView = &m_fxChannelViews[0]; + addFxLine(0, this, ml); + ml->addSpacing(5); + QSize fxLineSize = masterView->m_fxLine->size(); + + chLayout->setSizeConstraint(QLayout::SetMinimumSize); + channelArea->setWidgetResizable(true); + + // add mixer channels + for( int i = 1; i < m_fxChannelViews.size(); ++i ) { - QWidget * w = new QWidget( this ); - banks[i] = new QHBoxLayout( w ); - banks[i]->setMargin( 5 ); - banks[i]->setSpacing( 1 ); - m_fxLineBanks->addWidget( w ); + addFxLine(i, channelArea, chLayout); } + // add the scrolling section to the main layout + ml->addLayout(chLayout); - for( int i = 0; i < NumFxChannels+1; ++i ) - { - FxChannelView * cv = &m_fxChannelViews[i]; - if( i == 0 ) - { - cv->m_fxLine = new FxLine( NULL, this, - m->m_fxChannels[i]->m_name ); - ml->addWidget( cv->m_fxLine ); - ml->addSpacing( 10 ); - } - else - { - const int bank = (i-1) / 16; - cv->m_fxLine = new FxLine( NULL, this, - m->m_fxChannels[i]->m_name ); - banks[bank]->addWidget( cv->m_fxLine ); - } - lcdSpinBox * l = new lcdSpinBox( 2, cv->m_fxLine ); - l->model()->setRange( i, i ); - l->model()->setValue( i ); - l->move( 2, 4 ); - l->setMarginWidth( 1 ); + // show the add new effect channel button + QPushButton * newChannelBtn = new QPushButton("new", this ); + newChannelBtn->setFont(QFont("sans-serif", 10, 1, false)); + newChannelBtn->setFixedSize(fxLineSize); + connect( newChannelBtn, SIGNAL(clicked()), this, SLOT(addNewChannel())); + ml->addWidget( newChannelBtn ); - - cv->m_fader = new fader( &m->m_fxChannels[i]->m_volumeModel, - tr( "FX Fader %1" ).arg( i ), - cv->m_fxLine ); - cv->m_fader->move( 15-cv->m_fader->width()/2, - cv->m_fxLine->height()- - cv->m_fader->height()-5 ); - - cv->m_muteBtn = new pixmapButton( cv->m_fxLine, tr( "Mute" ) ); - cv->m_muteBtn->setModel( &m->m_fxChannels[i]->m_muteModel ); - cv->m_muteBtn->setActiveGraphic( - embed::getIconPixmap( "led_off" ) ); - cv->m_muteBtn->setInactiveGraphic( - embed::getIconPixmap( "led_green" ) ); - cv->m_muteBtn->setCheckable( true ); - cv->m_muteBtn->move( 9, cv->m_fader->y()-16); - toolTip::add( cv->m_muteBtn, tr( "Mute this FX channel" ) ); - - cv->m_rackView = new EffectRackView( - &m->m_fxChannels[i]->m_fxChain, this ); - m_fxRacksLayout->addWidget( cv->m_rackView ); - if( i == 0 ) - { - QVBoxLayout * l = new QVBoxLayout; - l->addSpacing( 10 ); - QButtonGroup * g = new QButtonGroup( this ); - m_bankButtons = g; - g->setExclusive( true ); - for( int j = 0; j < 4; ++j ) - { - QToolButton * btn = new QToolButton; - btn->setText( QString( 'A'+j ) ); - btn->setCheckable( true ); - btn->setSizePolicy( QSizePolicy::Preferred, - QSizePolicy::Expanding ); - l->addWidget( btn ); - g->addButton( btn, j ); - btn->setChecked( j == 0); - } - l->addSpacing( 10 ); - ml->addLayout( l ); - connect( g, SIGNAL( buttonClicked( int ) ), - m_fxLineBanks, SLOT( setCurrentIndex( int ) ) ); - } - } - - ml->addLayout( m_fxLineBanks ); ml->addLayout( m_fxRacksLayout ); + setLayout( ml ); updateGeometry(); - m_fxLineBanks->setCurrentIndex( 0 ); setCurrentFxLine( m_fxChannelViews[0].m_fxLine ); // timer for updating faders @@ -226,10 +189,9 @@ FxMixerView::FxMixerView() : QMdiSubWindow * subWin = engine::mainWindow()->workspace()->addSubWindow( this ); Qt::WindowFlags flags = subWin->windowFlags(); - flags |= Qt::MSWindowsFixedSizeDialogHint; flags &= ~Qt::WindowMaximizeButtonHint; subWin->setWindowFlags( flags ); - subWin->layout()->setSizeConstraint(QLayout::SetFixedSize); + subWin->layout()->setSizeConstraint(QLayout::SetMinimumSize); parentWidget()->setAttribute( Qt::WA_DeleteOnClose, false ); parentWidget()->move( 5, 310 ); @@ -239,6 +201,54 @@ FxMixerView::FxMixerView() : } +void FxMixerView::addFxLine(int i, QWidget * parent, QLayout * layout) +{ + FxMixer * m = engine::fxMixer(); + + FxChannelView * cv = &m_fxChannelViews[i]; + + cv->m_fxLine = new FxLine( parent, this, + m->m_fxChannels[i]->m_name, i ); + layout->addWidget(cv->m_fxLine); + + // mixer sends knob + cv->m_fxLine->m_sendKnob = new knob(0, cv->m_fxLine, + tr("Channel send amount")); + cv->m_fxLine->m_sendKnob->move(0, 22); + cv->m_fxLine->m_sendKnob->setVisible(false); + + // send light indicator + + + // channel number + lcdSpinBox * l = new lcdSpinBox( 2, cv->m_fxLine ); + l->model()->setRange( i, i ); + l->model()->setValue( i ); + l->move( 2, 58 ); + l->setMarginWidth( 1 ); + + + cv->m_fader = new fader( &m->m_fxChannels[i]->m_volumeModel, + tr( "FX Fader %1" ).arg( i ), + cv->m_fxLine ); + cv->m_fader->move( 15-cv->m_fader->width()/2, + cv->m_fxLine->height()- + cv->m_fader->height()-5 ); + + cv->m_muteBtn = new pixmapButton( cv->m_fxLine, tr( "Mute" ) ); + cv->m_muteBtn->setModel( &m->m_fxChannels[i]->m_muteModel ); + cv->m_muteBtn->setActiveGraphic( + embed::getIconPixmap( "led_off" ) ); + cv->m_muteBtn->setInactiveGraphic( + embed::getIconPixmap( "led_green" ) ); + cv->m_muteBtn->setCheckable( true ); + cv->m_muteBtn->move( 9, cv->m_fader->y()-16); + toolTip::add( cv->m_muteBtn, tr( "Mute this FX channel" ) ); + + cv->m_rackView = new EffectRackView( + &m->m_fxChannels[i]->m_fxChain, this ); + m_fxRacksLayout->addWidget( cv->m_rackView ); +} FxMixerView::~FxMixerView() @@ -247,6 +257,18 @@ FxMixerView::~FxMixerView() +void FxMixerView::addNewChannel() +{ + // add new fx mixer channel and redraw the form. + FxMixer * mix = engine::fxMixer(); + + int newChannelIndex = mix->createChannel(); + m_fxChannelViews.push_back(FxChannelView()); + + addFxLine(newChannelIndex, channelArea, chLayout); +} + + void FxMixerView::saveSettings( QDomDocument & _doc, QDomElement & _this ) { @@ -266,13 +288,29 @@ void FxMixerView::loadSettings( const QDomElement & _this ) void FxMixerView::setCurrentFxLine( FxLine * _line ) { + FxMixer * mix = engine::fxMixer(); + + // select m_currentFxLine = _line; - for( int i = 0; i < NumFxChannels+1; ++i ) + m_fxRacksLayout->setCurrentIndex( _line->m_channelIndex ); + + // set up send knob + for(int i = 0; i < m_fxChannelViews.size(); ++i) { - if( m_fxChannelViews[i].m_fxLine == _line ) + // does current channel send to this channel? + FloatModel * sendModel = mix->channelSendModel(_line->m_channelIndex, i); + if( sendModel == NULL ) { - m_fxRacksLayout->setCurrentIndex( i ); + // does not send, hide send knob + m_fxChannelViews[i].m_fxLine->m_sendKnob->setVisible(false); } + else + { + // it does send, show knob and connect + m_fxChannelViews[i].m_fxLine->m_sendKnob->setVisible(true); + m_fxChannelViews[i].m_fxLine->m_sendKnob->setModel(sendModel); + } + m_fxChannelViews[i].m_fxLine->update(); } } @@ -281,12 +319,7 @@ void FxMixerView::setCurrentFxLine( FxLine * _line ) void FxMixerView::setCurrentFxLine( int _line ) { - if ( _line >= 0 && _line < NumFxChannels+1 ) - { - setCurrentFxLine( m_fxChannelViews[_line].m_fxLine ); - - m_bankButtons->button( (_line-1) / 16 )->click(); - } + setCurrentFxLine( m_fxChannelViews[_line].m_fxLine ); } @@ -294,7 +327,7 @@ void FxMixerView::setCurrentFxLine( int _line ) void FxMixerView::clear() { - for( int i = 0; i <= NumFxChannels; ++i ) + for( int i = 0; i < m_fxChannelViews.size(); ++i ) { m_fxChannelViews[i].m_rackView->clearViews(); } @@ -306,7 +339,7 @@ void FxMixerView::clear() void FxMixerView::updateFaders() { FxMixer * m = engine::fxMixer(); - for( int i = 0; i < NumFxChannels+1; ++i ) + for( int i = 0; i < m_fxChannelViews.size(); ++i ) { const float opl = m_fxChannelViews[i].m_fader->getPeak_L(); const float opr = m_fxChannelViews[i].m_fader->getPeak_R(); diff --git a/src/gui/classic_style.cpp b/src/gui/classic_style.cpp index 602fcdf78..9160c9028 100644 --- a/src/gui/classic_style.cpp +++ b/src/gui/classic_style.cpp @@ -279,7 +279,7 @@ int ClassicStyle::pixelMetric( PixelMetric _metric, void ClassicStyle::drawFxLine( QPainter * _painter, const QWidget *_fxLine, - const QString & _name, bool _active ) + const QString & _name, bool _active, bool _sendToThis ) { int width = _fxLine->rect().width(); int height = _fxLine->rect().height(); @@ -293,10 +293,18 @@ void ClassicStyle::drawFxLine( QPainter * _painter, const QWidget *_fxLine, p->setPen( QColor( 20, 24, 32 ) ); p->drawRect( 0, 0, width-1, height-1 ); + // draw the mixer send background + if( _sendToThis ) + { + p->drawPixmap(2, 0, 28, 56, + embed::getIconPixmap("send_bg_arrow", 28, 56)); + } + + // draw the channel name p->rotate( -90 ); p->setPen( _active ? QColor( 0, 255, 0 ) : Qt::white ); p->setFont( pointSizeF( _fxLine->font(), 7.5f ) ); - p->drawText( -90, 20, _name ); + p->drawText( -145, 20, _name ); } void ClassicStyle::drawTrackContentBackground(QPainter * _painter, diff --git a/src/gui/cusis_style.cpp b/src/gui/cusis_style.cpp index 87a739a27..a78d14762 100644 --- a/src/gui/cusis_style.cpp +++ b/src/gui/cusis_style.cpp @@ -881,7 +881,7 @@ int CusisStyle::pixelMetric( PixelMetric _metric, const QStyleOption * _option, void CusisStyle::drawFxLine( QPainter * _painter, const QWidget *_fxLine, - const QString & _name, bool _active ) + const QString & _name, bool _active, bool _sendToThis ) { int width = _fxLine->rect().width(); int height = _fxLine->rect().height(); diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index cbddc519e..f56d6487b 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -103,7 +103,7 @@ InstrumentTrack::InstrumentTrack( trackContainer * _tc ) : this, tr( "Panning" ) ), m_pitchModel( 0, -100, 100, 1, this, tr( "Pitch" ) ), m_pitchRangeModel( 1, 1, 24, this, tr( "Pitch range" ) ), - m_effectChannelModel( 0, 0, NumFxChannels, this, tr( "FX channel" ) ), + m_effectChannelModel( 0, 0, 10, this, tr( "FX channel" ) ), // change this so it's a combo box, all the channels and then new. m_instrument( NULL ), m_soundShaping( this ), m_arpeggiator( this ),