From 168805745eb94b99ec211b5cb547a3417ed4dbe5 Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Fri, 20 Nov 2009 22:28:47 +0100 Subject: [PATCH] AudioPulseAudio: fixed improper shutdown + free allocated resources There have been some problems with the threading logic in the AudioPulseAudio backend resulting in an endless loop when quitting LMMS. Furthermore allocated PulseAudio resources were not freed properly. Thanks to Armin Kazmi for pointing out this issue. --- include/AudioPulseAudio.h | 1 + src/core/audio/AudioPulseAudio.cpp | 48 ++++++++++++++++-------------- 2 files changed, 27 insertions(+), 22 deletions(-) diff --git a/include/AudioPulseAudio.h b/include/AudioPulseAudio.h index 99cc9e462..33a11da1f 100644 --- a/include/AudioPulseAudio.h +++ b/include/AudioPulseAudio.h @@ -79,6 +79,7 @@ private: virtual void applyQualitySettings(); virtual void run(); + volatile bool m_quit; bool m_convertEndian; diff --git a/src/core/audio/AudioPulseAudio.cpp b/src/core/audio/AudioPulseAudio.cpp index 0e6ea6871..14a0a3b86 100644 --- a/src/core/audio/AudioPulseAudio.cpp +++ b/src/core/audio/AudioPulseAudio.cpp @@ -51,6 +51,7 @@ AudioPulseAudio::AudioPulseAudio( bool & _success_ful, mixer * _mixer ) : DEFAULT_CHANNELS, SURROUND_CHANNELS ), _mixer ), m_s( NULL ), + m_quit( false ), m_convertEndian( false ) { _success_ful = false; @@ -68,11 +69,6 @@ AudioPulseAudio::AudioPulseAudio( bool & _success_ful, mixer * _mixer ) : AudioPulseAudio::~AudioPulseAudio() { stopProcessing(); - - if( m_s != NULL ) - { - pa_stream_unref( m_s ); - } } @@ -195,38 +191,45 @@ static void context_state_callback(pa_context *c, void *userdata) void AudioPulseAudio::run() { - pa_mainloop * m = NULL; - - - if (!(m = pa_mainloop_new())) { + pa_mainloop * mainLoop = pa_mainloop_new(); + if( !mainLoop ) + { qCritical( "pa_mainloop_new() failed.\n" ); return; } - pa_mainloop_api * mainloop_api = pa_mainloop_get_api(m); + pa_mainloop_api * mainloop_api = pa_mainloop_get_api( mainLoop ); - pa_context *context = pa_context_new(mainloop_api, "lmms"); + pa_context *context = pa_context_new( mainloop_api, "lmms" ); if ( context == NULL ) { - qCritical( "pa_context_new() failed." ); + qCritical( "pa_context_new() failed." ); return; } - pa_context_set_state_callback(context, context_state_callback, this ); - /* Connect the context */ - pa_context_connect(context, NULL, (pa_context_flags) 0, NULL); + pa_context_set_state_callback( context, context_state_callback, this ); + // connect the context + pa_context_connect( context, NULL, (pa_context_flags) 0, NULL ); - int ret; - /* Run the main loop */ - if (pa_mainloop_run(m, &ret) < 0) + // run the main loop + int ret = 0; + m_quit = false; + while( m_quit == false && pa_mainloop_iterate( mainLoop, 1, &ret ) >= 0 ) { - qCritical( "pa_mainloop_run() failed.\n" ); } + + pa_stream_disconnect( m_s ); + pa_stream_unref( m_s ); + + pa_context_disconnect( context ); + pa_context_unref( context ); + + pa_mainloop_free( mainLoop ); } -void AudioPulseAudio::streamWriteCallback(pa_stream *s, size_t length) +void AudioPulseAudio::streamWriteCallback( pa_stream *s, size_t length ) { const fpp_t fpp = getMixer()->framesPerPeriod(); sampleFrameA * temp = CPU::allocFrames( fpp ); @@ -234,12 +237,13 @@ void AudioPulseAudio::streamWriteCallback(pa_stream *s, size_t length) sizeof(Sint16) ); size_t fd = 0; - while( fd < length/4 ) + while( fd < length/4 && m_quit == false ) { const fpp_t frames = getNextBuffer( temp ); if( !frames ) { - return; + m_quit = true; + break; } int bytes = CPU::convertToS16( temp, (intSampleFrameA *) pcmbuf,