From 32b7e0418b55d2fb6e45bff9a32103e532a9dab5 Mon Sep 17 00:00:00 2001 From: Fastigium Date: Mon, 14 Mar 2016 13:37:00 +0100 Subject: [PATCH 1/2] Fix two crashes when deleting FX channels Lock the mixer before performing a channel delete to prevent any race conditions causing a crash. Also, update the audioport FX channel when an InstrumentTrack's FX channel is changed to prevent the audioport mixing to a nonexistent channel. --- include/FxMixer.h | 1 - include/InstrumentTrack.h | 1 + src/core/FxMixer.cpp | 13 +++++-------- src/tracks/InstrumentTrack.cpp | 11 +++++++++-- 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/include/FxMixer.h b/include/FxMixer.h index ac5c72530..a00df914a 100644 --- a/include/FxMixer.h +++ b/include/FxMixer.h @@ -56,7 +56,6 @@ class FxChannel : public ThreadableJob BoolModel m_soloModel; FloatModel m_volumeModel; QString m_name; - QMutex m_lock; int m_channelIndex; // what channel index are we bool m_queued; // are we queued up for rendering yet? bool m_muted; // are we muted? updated per period so we don't have to call m_muteModel.value() twice diff --git a/include/InstrumentTrack.h b/include/InstrumentTrack.h index 4067d2d37..f24097c9d 100644 --- a/include/InstrumentTrack.h +++ b/include/InstrumentTrack.h @@ -227,6 +227,7 @@ protected slots: void updateBaseNote(); void updatePitch(); void updatePitchRange(); + void updateEffectChannel(); private: diff --git a/src/core/FxMixer.cpp b/src/core/FxMixer.cpp index be4378bd8..6ed83d45b 100644 --- a/src/core/FxMixer.cpp +++ b/src/core/FxMixer.cpp @@ -68,7 +68,6 @@ FxChannel::FxChannel( int idx, Model * _parent ) : m_soloModel( false, _parent ), m_volumeModel( 1.0, 0.0, 2.0, 0.001, _parent ), m_name(), - m_lock(), m_channelIndex( idx ), m_queued( false ), m_dependenciesMet( 0 ) @@ -284,7 +283,8 @@ void FxMixer::toggledSolo() void FxMixer::deleteChannel( int index ) { - m_fxChannels[index]->m_lock.lock(); + // lock the mixer so channel deletion is performed between mixer rounds + Engine::mixer()->lock(); FxChannel * ch = m_fxChannels[index]; @@ -344,6 +344,8 @@ void FxMixer::deleteChannel( int index ) r->updateName(); } } + + Engine::mixer()->unlock(); } @@ -543,15 +545,10 @@ FloatModel * FxMixer::channelSendModel( fx_ch_t fromChannel, fx_ch_t toChannel ) void FxMixer::mixToChannel( const sampleFrame * _buf, fx_ch_t _ch ) { - // The first check is for the case where the last fxchannel was deleted but - // there was a race condition where it had to be processed. - if( _ch < m_fxChannels.size() && - m_fxChannels[_ch]->m_muteModel.value() == false ) + if( m_fxChannels[_ch]->m_muteModel.value() == false ) { - m_fxChannels[_ch]->m_lock.lock(); MixHelpers::add( m_fxChannels[_ch]->m_buffer, _buf, Engine::mixer()->framesPerPeriod() ); m_fxChannels[_ch]->m_hasInput = true; - m_fxChannels[_ch]->m_lock.unlock(); } } diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index d1eb5bc1e..b98c9a1d5 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -139,6 +139,7 @@ InstrumentTrack::InstrumentTrack( TrackContainer* tc ) : connect( &m_baseNoteModel, SIGNAL( dataChanged() ), this, SLOT( updateBaseNote() ) ); connect( &m_pitchModel, SIGNAL( dataChanged() ), this, SLOT( updatePitch() ) ); connect( &m_pitchRangeModel, SIGNAL( dataChanged() ), this, SLOT( updatePitchRange() ) ); + connect( &m_effectChannelModel, SIGNAL( dataChanged() ), this, SLOT( updateEffectChannel() ) ); } @@ -220,8 +221,6 @@ void InstrumentTrack::processAudioBuffer( sampleFrame* buf, const fpp_t frames, } } } - - m_audioPort.setNextFxChannel( m_effectChannelModel.value() ); } @@ -558,6 +557,14 @@ void InstrumentTrack::updatePitchRange() +void InstrumentTrack::updateEffectChannel() +{ + m_audioPort.setNextFxChannel( m_effectChannelModel.value() ); +} + + + + int InstrumentTrack::masterKey( int _midi_key ) const { From 82055a9bddf419f1c38ddceb6e3c607c2a87eb67 Mon Sep 17 00:00:00 2001 From: Fastigium Date: Mon, 14 Mar 2016 13:59:28 +0100 Subject: [PATCH 2/2] Use deleteLater() on the FxLine when deleting a channel to prevent a crash In Qt, it is not safe to delete a QObject inside a signal emitted by that QObject. This happened with FxLine when removing an FX channel using the context menu. This commit changes that by using deleteLater() instead of delete on the FxLine. It also hides the FxLine to prevent a ghost of it being drawn when deleting the last non-master FX channel. --- src/gui/FxMixerView.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/gui/FxMixerView.cpp b/src/gui/FxMixerView.cpp index 5826ed9d4..eb20cafa1 100644 --- a/src/gui/FxMixerView.cpp +++ b/src/gui/FxMixerView.cpp @@ -382,7 +382,9 @@ void FxMixerView::deleteChannel(int index) delete m_fxChannelViews[index]->m_fader; delete m_fxChannelViews[index]->m_muteBtn; delete m_fxChannelViews[index]->m_soloBtn; - delete m_fxChannelViews[index]->m_fxLine; + // delete fxLine later to prevent a crash when deleting from context menu + m_fxChannelViews[index]->m_fxLine->hide(); + m_fxChannelViews[index]->m_fxLine->deleteLater(); delete m_fxChannelViews[index]->m_rackView; delete m_fxChannelViews[index]; m_channelAreaWidget->adjustSize();