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 <armin.kazmi@tu-dortmund.de> for pointing out
this issue.
(cherry picked from commit 168805745e)
This commit is contained in:
Tobias Doerffel
2009-11-20 22:28:47 +01:00
parent 6e6d6e89c1
commit 5309e7a374
2 changed files with 27 additions and 22 deletions

View File

@@ -79,6 +79,7 @@ private:
virtual void applyQualitySettings();
virtual void run();
volatile bool m_quit;
bool m_convertEndian;

View File

@@ -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(),