Fix occasional audio interface deadlock (#4450)
This commit is contained in:
@@ -37,7 +37,6 @@
|
||||
#include <QtCore/QVector>
|
||||
#include <QtCore/QList>
|
||||
#include <QtCore/QMap>
|
||||
#include <QMutexLocker>
|
||||
|
||||
#include "AudioDevice.h"
|
||||
#include "AudioDeviceSetupWidget.h"
|
||||
@@ -108,7 +107,6 @@ private:
|
||||
|
||||
bool m_active;
|
||||
bool m_stopped;
|
||||
QMutex m_processingMutex;
|
||||
|
||||
MidiJack *m_midiClient;
|
||||
QVector<jack_port_t *> m_outputPorts;
|
||||
|
||||
@@ -145,7 +145,6 @@ private:
|
||||
int m_outBufSize;
|
||||
|
||||
bool m_stopped;
|
||||
QSemaphore m_stopSemaphore;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
@@ -109,6 +109,8 @@ private:
|
||||
fpp_t m_outBufFramesTotal;
|
||||
fpp_t m_outBufFrameIndex;
|
||||
|
||||
bool m_stopped;
|
||||
|
||||
int m_disconnectErr;
|
||||
void onBackendDisconnect(int err);
|
||||
|
||||
|
||||
@@ -66,6 +66,12 @@ public:
|
||||
return( element );
|
||||
}
|
||||
|
||||
void waitUntilRead()
|
||||
{
|
||||
m_writer_sem.acquire( m_size );
|
||||
m_writer_sem.release( m_size );
|
||||
}
|
||||
|
||||
bool available()
|
||||
{
|
||||
return( m_reader_sem.available() );
|
||||
|
||||
@@ -640,7 +640,7 @@ void Mixer::storeAudioDevice()
|
||||
|
||||
void Mixer::restoreAudioDevice()
|
||||
{
|
||||
if( m_oldAudioDev != NULL )
|
||||
if( m_oldAudioDev && m_audioDev != m_oldAudioDev )
|
||||
{
|
||||
stopProcessing();
|
||||
delete m_audioDev;
|
||||
@@ -648,9 +648,9 @@ void Mixer::restoreAudioDevice()
|
||||
m_audioDev = m_oldAudioDev;
|
||||
emit sampleRateChanged();
|
||||
|
||||
m_oldAudioDev = NULL;
|
||||
startProcessing();
|
||||
}
|
||||
m_oldAudioDev = NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -1127,7 +1127,9 @@ void Mixer::fifoWriter::run()
|
||||
write( buffer );
|
||||
}
|
||||
|
||||
// Let audio backend stop processing
|
||||
write( NULL );
|
||||
m_fifo->waitUntilRead();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -201,7 +201,6 @@ bool AudioJack::initJackClient()
|
||||
|
||||
void AudioJack::startProcessing()
|
||||
{
|
||||
QMutexLocker m( &m_processingMutex );
|
||||
m_stopped = false;
|
||||
|
||||
if( m_active || m_client == NULL )
|
||||
@@ -254,7 +253,6 @@ void AudioJack::startProcessing()
|
||||
|
||||
void AudioJack::stopProcessing()
|
||||
{
|
||||
QMutexLocker m( &m_processingMutex );
|
||||
m_stopped = true;
|
||||
}
|
||||
|
||||
@@ -342,7 +340,6 @@ void AudioJack::renamePort( AudioPort * _port )
|
||||
|
||||
int AudioJack::processCallback( jack_nframes_t _nframes, void * _udata )
|
||||
{
|
||||
QMutexLocker m( &m_processingMutex );
|
||||
|
||||
// do midi processing first so that midi input can
|
||||
// add to the following sound processing
|
||||
@@ -406,6 +403,7 @@ int AudioJack::processCallback( jack_nframes_t _nframes, void * _udata )
|
||||
m_framesDoneInCurBuf = 0;
|
||||
if( !m_framesToDoInCurBuf )
|
||||
{
|
||||
m_stopped = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,8 +57,7 @@ AudioPortAudio::AudioPortAudio( bool & _success_ful, Mixer * _mixer ) :
|
||||
m_paStream( NULL ),
|
||||
m_wasPAInitError( false ),
|
||||
m_outBuf( new surroundSampleFrame[mixer()->framesPerPeriod()] ),
|
||||
m_outBufPos( 0 ),
|
||||
m_stopSemaphore( 1 )
|
||||
m_outBufPos( 0 )
|
||||
{
|
||||
_success_ful = false;
|
||||
|
||||
@@ -167,8 +166,6 @@ AudioPortAudio::AudioPortAudio( bool & _success_ful, Mixer * _mixer ) :
|
||||
printf( "Input device: '%s' backend: '%s'\n", Pa_GetDeviceInfo( inDevIdx )->name, Pa_GetHostApiInfo( Pa_GetDeviceInfo( inDevIdx )->hostApi )->name );
|
||||
printf( "Output device: '%s' backend: '%s'\n", Pa_GetDeviceInfo( outDevIdx )->name, Pa_GetHostApiInfo( Pa_GetDeviceInfo( outDevIdx )->hostApi )->name );
|
||||
|
||||
m_stopSemaphore.acquire();
|
||||
|
||||
// TODO: debug Mixer::pushInputFrames()
|
||||
//m_supportsCapture = true;
|
||||
|
||||
@@ -181,7 +178,6 @@ AudioPortAudio::AudioPortAudio( bool & _success_ful, Mixer * _mixer ) :
|
||||
AudioPortAudio::~AudioPortAudio()
|
||||
{
|
||||
stopProcessing();
|
||||
m_stopSemaphore.release();
|
||||
|
||||
if( !m_wasPAInitError )
|
||||
{
|
||||
@@ -212,8 +208,7 @@ void AudioPortAudio::stopProcessing()
|
||||
{
|
||||
if( m_paStream && Pa_IsStreamActive( m_paStream ) )
|
||||
{
|
||||
m_stopSemaphore.acquire();
|
||||
|
||||
m_stopped = true;
|
||||
PaError err = Pa_StopStream( m_paStream );
|
||||
|
||||
if( err != paNoError )
|
||||
@@ -283,7 +278,6 @@ int AudioPortAudio::process_callback(
|
||||
if( !frames )
|
||||
{
|
||||
m_stopped = true;
|
||||
m_stopSemaphore.release();
|
||||
memset( _outputBuffer, 0, _framesPerBuffer *
|
||||
channels() * sizeof(float) );
|
||||
return paComplete;
|
||||
|
||||
@@ -103,6 +103,7 @@ void AudioPulseAudio::startProcessing()
|
||||
|
||||
void AudioPulseAudio::stopProcessing()
|
||||
{
|
||||
m_quit = true;
|
||||
stopProcessingThread( this );
|
||||
}
|
||||
|
||||
|
||||
@@ -168,6 +168,7 @@ void AudioSdl::sdlAudioCallback( Uint8 * _buf, int _len )
|
||||
const fpp_t frames = getNextBuffer( m_outBuf );
|
||||
if( !frames )
|
||||
{
|
||||
m_stopped = true;
|
||||
memset( _buf, 0, _len );
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -49,6 +49,7 @@ AudioSoundIo::AudioSoundIo( bool & outSuccessful, Mixer * _mixer ) :
|
||||
m_disconnectErr = 0;
|
||||
m_outBufFrameIndex = 0;
|
||||
m_outBufFramesTotal = 0;
|
||||
m_stopped = true;
|
||||
|
||||
m_soundio = soundio_create();
|
||||
if (!m_soundio)
|
||||
@@ -210,15 +211,18 @@ void AudioSoundIo::startProcessing()
|
||||
|
||||
m_outBuf = new surroundSampleFrame[m_outBufSize];
|
||||
|
||||
m_stopped = false;
|
||||
int err;
|
||||
if ((err = soundio_outstream_start(m_outstream)))
|
||||
{
|
||||
m_stopped = true;
|
||||
fprintf(stderr, "soundio unable to start stream: %s\n", soundio_strerror(err));
|
||||
}
|
||||
}
|
||||
|
||||
void AudioSoundIo::stopProcessing()
|
||||
{
|
||||
m_stopped = true;
|
||||
if (m_outstream)
|
||||
{
|
||||
soundio_outstream_destroy(m_outstream);
|
||||
@@ -244,6 +248,7 @@ void AudioSoundIo::underflowCallback()
|
||||
|
||||
void AudioSoundIo::writeCallback(int frameCountMin, int frameCountMax)
|
||||
{
|
||||
if (m_stopped) {return;}
|
||||
const struct SoundIoChannelLayout *layout = &m_outstream->layout;
|
||||
SoundIoChannelArea *areas;
|
||||
int bytesPerSample = m_outstream->bytes_per_sample;
|
||||
@@ -265,11 +270,27 @@ void AudioSoundIo::writeCallback(int frameCountMin, int frameCountMax)
|
||||
if (!frameCount)
|
||||
break;
|
||||
|
||||
|
||||
if (m_stopped)
|
||||
{
|
||||
for (int channel = 0; channel < layout->channel_count; ++channel)
|
||||
{
|
||||
memset(areas[channel].ptr, 0, bytesPerSample * frameCount);
|
||||
areas[channel].ptr += areas[channel].step * frameCount;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int frame = 0; frame < frameCount; frame += 1)
|
||||
{
|
||||
if (m_outBufFrameIndex >= m_outBufFramesTotal)
|
||||
{
|
||||
m_outBufFramesTotal = getNextBuffer(m_outBuf);
|
||||
if (m_outBufFramesTotal == 0)
|
||||
{
|
||||
m_stopped = true;
|
||||
break;
|
||||
}
|
||||
m_outBufFrameIndex = 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user