diff --git a/include/FxMixer.h b/include/FxMixer.h index 116dbcde0..b53045015 100644 --- a/include/FxMixer.h +++ b/include/FxMixer.h @@ -97,6 +97,10 @@ public: // delete the connection made by createChannelSend void deleteChannelSend(fx_ch_t fromChannel, fx_ch_t toChannel); + // determine if adding a send from sendFrom to + // sendTo would result in an infinite mixer loop. + bool isInfiniteLoop(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); diff --git a/src/core/FxMixer.cpp b/src/core/FxMixer.cpp index 03aa9b2da..8306b28c4 100644 --- a/src/core/FxMixer.cpp +++ b/src/core/FxMixer.cpp @@ -158,6 +158,26 @@ void FxMixer::deleteChannelSend(fx_ch_t fromChannel, fx_ch_t toChannel) } +bool FxMixer::isInfiniteLoop(fx_ch_t sendFrom, fx_ch_t sendTo) { + // can't send master to anything + if( sendFrom == 0 ) return true; + + // can't send channel to itself + if( sendFrom == sendTo ) return true; + + // follow sendTo's outputs recursively looking for something that sends + // to sendFrom + for(int i=0; im_sends.size(); ++i) + { + if( isInfiniteLoop( sendFrom, m_fxChannels[sendTo]->m_sends[i] ) ) + { + return true; + } + } + + return false; +} + // how much does fromChannel send its output to the input of toChannel? FloatModel * FxMixer::channelSendModel(fx_ch_t fromChannel, fx_ch_t toChannel) diff --git a/src/gui/FxMixerView.cpp b/src/gui/FxMixerView.cpp index cf2d5e72a..f1d591fc8 100644 --- a/src/gui/FxMixerView.cpp +++ b/src/gui/FxMixerView.cpp @@ -148,6 +148,8 @@ void FxMixerView::addNewChannel() newChannelIndex)); chLayout->addWidget(m_fxChannelViews[newChannelIndex]->m_fxLine); m_fxRacksLayout->addWidget( m_fxChannelViews[newChannelIndex]->m_rackView ); + + updateFxLine(newChannelIndex); } @@ -207,29 +209,34 @@ void FxMixerView::setCurrentFxLine( FxLine * _line ) } -void FxMixerView::updateFxLine(int i) +void FxMixerView::updateFxLine(int index) { FxMixer * mix = engine::fxMixer(); // does current channel send to this channel? - FloatModel * sendModel = mix->channelSendModel(m_currentFxLine->channelIndex(), i); + int selIndex = m_currentFxLine->channelIndex(); + FxLine * thisLine = m_fxChannelViews[index]->m_fxLine; + FloatModel * sendModel = mix->channelSendModel(selIndex, index); if( sendModel == NULL ) { // does not send, hide send knob - m_fxChannelViews[i]->m_fxLine->m_sendKnob->setVisible(false); + thisLine->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); + thisLine->m_sendKnob->setVisible(true); + thisLine->m_sendKnob->setModel(sendModel); } - - m_fxChannelViews[i]->m_fxLine->update(); - m_fxChannelViews[i]->m_fxLine->m_sendBtn->updateLightStatus(); + // disable the send button if it would cause an infinite loop + thisLine->m_sendBtn->setVisible(! mix->isInfiniteLoop(selIndex, index)); + thisLine->m_sendBtn->updateLightStatus(); + thisLine->update(); } + + void FxMixerView::setCurrentFxLine( int _line ) { setCurrentFxLine( m_fxChannelViews[_line]->m_fxLine );