diff --git a/include/AudioAlsa.h b/include/AudioAlsa.h index 570b8600575..3e6c2417d8d 100644 --- a/include/AudioAlsa.h +++ b/include/AudioAlsa.h @@ -33,6 +33,7 @@ #define ALSA_PCM_NEW_HW_PARAMS_API #include +#include #include "AudioDevice.h" diff --git a/include/AudioDevice.h b/include/AudioDevice.h index fa7a6b2ea2a..cb635f10a08 100644 --- a/include/AudioDevice.h +++ b/include/AudioDevice.h @@ -25,17 +25,15 @@ #ifndef AUDIO_DEVICE_H #define AUDIO_DEVICE_H -#include #include -#include #include #include "lmms_basics.h" -#include "TabWidget.h" class AudioPort; class Mixer; +class QThread; class AudioDevice @@ -135,6 +133,8 @@ class AudioDevice bool hqAudio() const; + static void stopProcessingThread( QThread * thread ); + protected: bool m_supportsCapture; diff --git a/include/AudioDummy.h b/include/AudioDummy.h index 02b1ec9afb1..b026a6e2067 100644 --- a/include/AudioDummy.h +++ b/include/AudioDummy.h @@ -84,11 +84,7 @@ class AudioDummy : public AudioDevice, public QThread virtual void stopProcessing() { - if( isRunning() ) - { - wait( 1000 ); - terminate(); - } + stopProcessingThread( this ); } virtual void run() diff --git a/include/AudioOss.h b/include/AudioOss.h index 76dbeecb8c9..8c6295d675c 100644 --- a/include/AudioOss.h +++ b/include/AudioOss.h @@ -29,6 +29,8 @@ #ifdef LMMS_HAVE_OSS +#include + #include "AudioDevice.h" #include "AudioDeviceSetupWidget.h" diff --git a/include/AudioPulseAudio.h b/include/AudioPulseAudio.h index fc2f77bd432..20e727093eb 100644 --- a/include/AudioPulseAudio.h +++ b/include/AudioPulseAudio.h @@ -30,6 +30,7 @@ #ifdef LMMS_HAVE_PULSEAUDIO #include +#include #include "AudioDevice.h" #include "AudioDeviceSetupWidget.h" diff --git a/include/AudioSndio.h b/include/AudioSndio.h index ce42883ad69..b956c99b8d2 100644 --- a/include/AudioSndio.h +++ b/include/AudioSndio.h @@ -5,6 +5,7 @@ #ifdef LMMS_HAVE_SNDIO +#include #include #include "AudioDevice.h" diff --git a/include/Mixer.h b/include/Mixer.h index a79dc977149..f3c849c3ee1 100644 --- a/include/Mixer.h +++ b/include/Mixer.h @@ -331,6 +331,8 @@ class EXPORT Mixer : public QObject virtual void run(); + void write( surroundSampleFrame * buffer ); + } ; @@ -347,6 +349,7 @@ class EXPORT Mixer : public QObject const surroundSampleFrame * renderNextBuffer(); + void clearInternal(); void runChangesInModel(); @@ -403,6 +406,8 @@ class EXPORT Mixer : public QObject bool m_metronomeActive; + bool m_clearSignal; + bool m_changesSignal; bool m_waitForMixer; unsigned int m_changes; diff --git a/include/fifo_buffer.h b/include/fifo_buffer.h index a1983008cf2..fd5da778594 100644 --- a/include/fifo_buffer.h +++ b/include/fifo_buffer.h @@ -57,6 +57,18 @@ class fifoBuffer m_reader_sem.release(); } + bool tryWrite( T _element ) + { + if( m_writer_sem.tryAcquire() ) + { + m_buffer[m_writer_index++] = _element; + m_writer_index %= m_size; + m_reader_sem.release(); + return true; + } + return false; + } + T read() { m_reader_sem.acquire(); diff --git a/src/core/Mixer.cpp b/src/core/Mixer.cpp index 213b8165343..de89d2bd28d 100644 --- a/src/core/Mixer.cpp +++ b/src/core/Mixer.cpp @@ -82,6 +82,7 @@ Mixer::Mixer( bool renderOnly ) : m_audioDevStartFailed( false ), m_profiler(), m_metronomeActive(false), + m_clearSignal( false ), m_changesSignal( false ), m_waitForMixer( true ), m_changes( 0 ), @@ -234,9 +235,9 @@ void Mixer::stopProcessing() { m_fifoWriter->finish(); m_fifoWriter->wait(); + m_audioDev->stopProcessing(); delete m_fifoWriter; m_fifoWriter = NULL; - m_audioDev->stopProcessing(); } else { @@ -365,6 +366,12 @@ const surroundSampleFrame * Mixer::renderNextBuffer() // clear new write buffer m_inputBufferFrames[ m_inputBufferWrite ] = 0; + if( m_clearSignal ) + { + m_clearSignal = false; + clearInternal(); + } + // remove all play-handles that have to be deleted and delete // them if they still exist... // maybe this algorithm could be optimized... @@ -469,12 +476,19 @@ const surroundSampleFrame * Mixer::renderNextBuffer() +void Mixer::clear() +{ + m_clearSignal = true; +} + + + + // removes all play-handles. this is necessary, when the song is stopped -> // all remaining notes etc. would be played until their end -void Mixer::clear() +void Mixer::clearInternal() { // TODO: m_midiClient->noteOffAll(); - requestChangeInModel(); for( PlayHandleList::Iterator it = m_playHandles.begin(); it != m_playHandles.end(); ++it ) { // we must not delete instrument-play-handles as they exist @@ -484,7 +498,6 @@ void Mixer::clear() m_playHandlesToRemove.push_back( *it ); } } - doneChangeInModel(); } @@ -1053,10 +1066,26 @@ void Mixer::fifoWriter::run() surroundSampleFrame * buffer = new surroundSampleFrame[frames]; const surroundSampleFrame * b = m_mixer->renderNextBuffer(); memcpy( buffer, b, frames * sizeof( surroundSampleFrame ) ); - m_fifo->write( buffer ); + write( buffer ); } - m_fifo->write( NULL ); + write( NULL ); +} + + + + +void Mixer::fifoWriter::write( surroundSampleFrame * buffer ) +{ + while( !m_fifo->tryWrite( buffer ) ) + { + if( m_mixer->m_changesSignal ) + { + m_mixer->runChangesInModel(); + continue; + } + yieldCurrentThread(); + } } diff --git a/src/core/audio/AudioAlsa.cpp b/src/core/audio/AudioAlsa.cpp index 93ac1698328..996b9faebfa 100644 --- a/src/core/audio/AudioAlsa.cpp +++ b/src/core/audio/AudioAlsa.cpp @@ -245,11 +245,7 @@ void AudioAlsa::startProcessing() void AudioAlsa::stopProcessing() { - if( isRunning() ) - { - wait( 1000 ); - terminate(); - } + stopProcessingThread( this ); } diff --git a/src/core/audio/AudioDevice.cpp b/src/core/audio/AudioDevice.cpp index 690a2b0126a..8bd21ffae35 100644 --- a/src/core/audio/AudioDevice.cpp +++ b/src/core/audio/AudioDevice.cpp @@ -131,6 +131,22 @@ void AudioDevice::stopProcessing() +void AudioDevice::stopProcessingThread( QThread * thread ) +{ + if( !thread->wait( 30000 ) ) + { + fprintf( stderr, "Terminating audio device thread\n" ); + thread->terminate(); + if( !thread->wait( 1000 ) ) + { + fprintf( stderr, "Thread not terminated yet\n" ); + } + } +} + + + + void AudioDevice::applyQualitySettings() { src_delete( m_srcState ); diff --git a/src/core/audio/AudioOss.cpp b/src/core/audio/AudioOss.cpp index dbc46ee27ff..3686088285e 100644 --- a/src/core/audio/AudioOss.cpp +++ b/src/core/audio/AudioOss.cpp @@ -255,11 +255,7 @@ void AudioOss::startProcessing() void AudioOss::stopProcessing() { - if( isRunning() ) - { - wait( 1000 ); - terminate(); - } + stopProcessingThread( this ); } diff --git a/src/core/audio/AudioPulseAudio.cpp b/src/core/audio/AudioPulseAudio.cpp index 827d1f5e454..8dd9e29568a 100644 --- a/src/core/audio/AudioPulseAudio.cpp +++ b/src/core/audio/AudioPulseAudio.cpp @@ -105,11 +105,7 @@ void AudioPulseAudio::startProcessing() void AudioPulseAudio::stopProcessing() { - if( isRunning() ) - { - wait( 1000 ); - terminate(); - } + stopProcessingThread( this ); } diff --git a/src/core/audio/AudioSndio.cpp b/src/core/audio/AudioSndio.cpp index 301fe1e0cb0..1e4e1281e11 100644 --- a/src/core/audio/AudioSndio.cpp +++ b/src/core/audio/AudioSndio.cpp @@ -114,11 +114,7 @@ void AudioSndio::startProcessing( void ) void AudioSndio::stopProcessing( void ) { - if( isRunning() ) - { - wait( 1000 ); - terminate(); - } + stopProcessingThread( this ); }