Skip to content

Commit a4c91f8

Browse files
superpaikmichaelgregoriussakertooth
authored
Recursively unmute channels when soloing in the mixer (LMMS#6746)
* unmute related FX channels When soled one FX channel, unmute send and receive channels, to allow complex FX channel routing (BUS, SENDs, etc.) * Comment change * SEND channels Activate also SEND channels recursively * Remove unnecessary whitespace * Encapsulate mixer channel index Make the mixer channel index `m_channelIndex` private and add getters and setters. Also add a method to determine if the channel is the master channel. Move `m_channelIndex` to the end of the initialization list of the `MixerChannel` constructor because it is now the last member in the header. Adjust all clients to make use of the new methods. * Replace const int& getIndex() with int index() const * Format changes --------- Co-authored-by: Michael Gregorius <michael.gregorius.git@arcor.de> Co-authored-by: Sotonye Atemie <sakertooth@gmail.com>
1 parent 9b04e29 commit a4c91f8

File tree

4 files changed

+70
-17
lines changed

4 files changed

+70
-17
lines changed

include/Mixer.h

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@ class MixerChannel : public ThreadableJob
6363
FloatModel m_volumeModel;
6464
QString m_name;
6565
QMutex m_lock;
66-
int m_channelIndex; // what channel index are we
6766
bool m_queued; // are we queued up for rendering yet?
6867
bool m_muted; // are we muted? updated per period so we don't have to call m_muteModel.value() twice
6968

@@ -73,8 +72,15 @@ class MixerChannel : public ThreadableJob
7372
// pointers to other channels that send to this one
7473
MixerRouteVector m_receives;
7574

75+
int index() const { return m_channelIndex; }
76+
void setIndex(int index) { m_channelIndex = index; }
77+
78+
bool isMaster() { return m_channelIndex == 0; }
79+
7680
bool requiresProcessing() const override { return true; }
7781
void unmuteForSolo();
82+
void unmuteSenderForSolo();
83+
void unmuteReceiverForSolo();
7884

7985
auto color() const -> const std::optional<QColor>& { return m_color; }
8086
void setColor(const std::optional<QColor>& color) { m_color = color; }
@@ -85,7 +91,7 @@ class MixerChannel : public ThreadableJob
8591

8692
private:
8793
void doProcessing() override;
88-
94+
int m_channelIndex;
8995
std::optional<QColor> m_color;
9096
};
9197

@@ -98,12 +104,12 @@ class MixerRoute : public QObject
98104

99105
mix_ch_t senderIndex() const
100106
{
101-
return m_from->m_channelIndex;
107+
return m_from->index();
102108
}
103109

104110
mix_ch_t receiverIndex() const
105111
{
106-
return m_to->m_channelIndex;
112+
return m_to->index();
107113
}
108114

109115
FloatModel * amount()

src/core/Mixer.cpp

Lines changed: 56 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ MixerRoute::MixerRoute( MixerChannel * from, MixerChannel * to, float amount ) :
4444
m_from( from ),
4545
m_to( to ),
4646
m_amount(amount, 0, 1, 0.001f, nullptr,
47-
tr("Amount to send from channel %1 to channel %2").arg(m_from->m_channelIndex).arg(m_to->m_channelIndex))
47+
tr("Amount to send from channel %1 to channel %2").arg(m_from->index()).arg(m_to->index()))
4848
{
4949
//qDebug( "created: %d to %d", m_from->m_channelIndex, m_to->m_channelIndex );
5050
// create send amount model
@@ -54,7 +54,7 @@ MixerRoute::MixerRoute( MixerChannel * from, MixerChannel * to, float amount ) :
5454
void MixerRoute::updateName()
5555
{
5656
m_amount.setDisplayName(
57-
tr( "Amount to send from channel %1 to channel %2" ).arg( m_from->m_channelIndex ).arg( m_to->m_channelIndex ) );
57+
tr("Amount to send from channel %1 to channel %2").arg(m_from->index()).arg(m_to->index()));
5858
}
5959

6060

@@ -70,9 +70,9 @@ MixerChannel::MixerChannel( int idx, Model * _parent ) :
7070
m_volumeModel(1.f, 0.f, 2.f, 0.001f, _parent),
7171
m_name(),
7272
m_lock(),
73-
m_channelIndex( idx ),
7473
m_queued( false ),
75-
m_dependenciesMet(0)
74+
m_dependenciesMet(0),
75+
m_channelIndex(idx)
7676
{
7777
zeroSampleFrames(m_buffer, Engine::audioEngine()->framesPerPeriod());
7878
}
@@ -109,8 +109,55 @@ void MixerChannel::incrementDeps()
109109

110110
void MixerChannel::unmuteForSolo()
111111
{
112-
//TODO: Recursively activate every channel, this channel sends to
113112
m_muteModel.setValue(false);
113+
114+
// if channel is not master, unmute also every channel it sends to/receives from
115+
if (!isMaster())
116+
{
117+
for (const MixerRoute* sendsRoute : m_sends)
118+
{
119+
sendsRoute->receiver()->unmuteSenderForSolo();
120+
}
121+
122+
for (const MixerRoute* receiverRoute : m_receives)
123+
{
124+
receiverRoute->sender()->unmuteReceiverForSolo();
125+
}
126+
}
127+
}
128+
129+
void MixerChannel::unmuteSenderForSolo()
130+
{
131+
m_muteModel.setValue(false);
132+
133+
// if channel is not master, unmute every channel it sends to
134+
if (!isMaster())
135+
{
136+
for (const MixerRoute* sendsRoute : m_sends)
137+
{
138+
sendsRoute->receiver()->unmuteSenderForSolo();
139+
}
140+
}
141+
}
142+
143+
144+
void MixerChannel::unmuteReceiverForSolo()
145+
{
146+
m_muteModel.setValue(false);
147+
148+
// if channel is not master, unmute every channel it receives from, and of those, unmute the channels they send to
149+
if (!isMaster())
150+
{
151+
for (const MixerRoute* receiverRoute : m_receives)
152+
{
153+
receiverRoute->sender()->unmuteReceiverForSolo();
154+
}
155+
156+
for (const MixerRoute* sendsRoute : m_sends)
157+
{
158+
sendsRoute->receiver()->unmuteSenderForSolo();
159+
}
160+
}
114161
}
115162

116163

@@ -275,7 +322,7 @@ void Mixer::toggledSolo()
275322
} else {
276323
activateSolo();
277324
}
278-
// unmute the soloed chan and every channel it sends to
325+
// unmute the soloed chan and every channel it sends to/receives from
279326
m_mixerChannels[soloedChan]->unmuteForSolo();
280327
} else {
281328
deactivateSolo();
@@ -360,7 +407,7 @@ void Mixer::deleteChannel( int index )
360407
validateChannelName( i, i + 1 );
361408

362409
// set correct channel index
363-
m_mixerChannels[i]->m_channelIndex = i;
410+
m_mixerChannels[i]->setIndex(i);
364411

365412
// now check all routes and update names of the send models
366413
for( MixerRoute * r : m_mixerChannels[i]->m_sends )
@@ -433,8 +480,8 @@ void Mixer::moveChannelLeft( int index )
433480
qSwap(m_mixerChannels[index], m_mixerChannels[index - 1]);
434481

435482
// Update m_channelIndex of both channels
436-
m_mixerChannels[index]->m_channelIndex = index;
437-
m_mixerChannels[index - 1]->m_channelIndex = index -1;
483+
m_mixerChannels[index]->setIndex(index);
484+
m_mixerChannels[index - 1]->setIndex(index - 1);
438485
}
439486

440487

src/gui/tracks/InstrumentTrackView.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -385,8 +385,8 @@ QMenu * InstrumentTrackView::createMixerMenu(QString title, QString newMixerLabe
385385

386386
if ( currentChannel != mixerChannel )
387387
{
388-
auto index = currentChannel->m_channelIndex;
389-
QString label = tr( "%1: %2" ).arg( currentChannel->m_channelIndex ).arg( currentChannel->m_name );
388+
auto index = currentChannel->index();
389+
QString label = tr( "%1: %2" ).arg(index).arg(currentChannel->m_name);
390390
mixerMenu->addAction(label, [this, index](){
391391
assignMixerLine(index);
392392
});

src/gui/tracks/SampleTrackView.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,8 @@ QMenu * SampleTrackView::createMixerMenu(QString title, QString newMixerLabel)
155155

156156
if (currentChannel != mixerChannel)
157157
{
158-
const auto index = currentChannel->m_channelIndex;
159-
QString label = tr("%1: %2").arg(currentChannel->m_channelIndex).arg(currentChannel->m_name);
158+
const auto index = currentChannel->index();
159+
QString label = tr("%1: %2").arg(index).arg(currentChannel->m_name);
160160
mixerMenu->addAction(label, [this, index](){
161161
assignMixerLine(index);
162162
});

0 commit comments

Comments
 (0)