From 5309e7a3742dbb150d5d8d9abf5b64c45fa3d33e Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Fri, 20 Nov 2009 22:28:47 +0100 Subject: [PATCH 1/2] 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. (cherry picked from commit 168805745eb94b99ec211b5cb547a3417ed4dbe5) --- 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 99cc9e4..33a11da 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 d9176ea..54f6b4b 100644 --- a/src/core/audio/AudioPulseAudio.cpp +++ b/src/core/audio/AudioPulseAudio.cpp @@ -50,6 +50,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; @@ -67,11 +68,6 @@ AudioPulseAudio::AudioPulseAudio( bool & _success_ful, mixer * _mixer ) : AudioPulseAudio::~AudioPulseAudio() { stopProcessing(); - - if( m_s != NULL ) - { - pa_stream_unref( m_s ); - } } @@ -194,50 +190,58 @@ 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(); surroundSampleFrame * temp = new surroundSampleFrame[fpp]; Sint16 * pcmbuf = (Sint16*)pa_xmalloc( fpp * channels() * 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 = convertToS16( temp, frames, getMixer()->masterGain(), -- 1.6.5