summaryrefslogtreecommitdiffstats
path: root/src/multimedia/darwin/qdarwinaudiosink.mm
diff options
context:
space:
mode:
Diffstat (limited to 'src/multimedia/darwin/qdarwinaudiosink.mm')
-rw-r--r--src/multimedia/darwin/qdarwinaudiosink.mm65
1 files changed, 48 insertions, 17 deletions
diff --git a/src/multimedia/darwin/qdarwinaudiosink.mm b/src/multimedia/darwin/qdarwinaudiosink.mm
index 340472671..f29b642c2 100644
--- a/src/multimedia/darwin/qdarwinaudiosink.mm
+++ b/src/multimedia/darwin/qdarwinaudiosink.mm
@@ -104,7 +104,7 @@ int QDarwinAudioSinkBuffer::available() const
void QDarwinAudioSinkBuffer::reset()
{
m_buffer->reset();
- m_device = 0;
+ m_device = nullptr;
m_deviceError = false;
}
@@ -582,7 +582,7 @@ bool QDarwinAudioSink::open()
void QDarwinAudioSink::close()
{
if (m_audioUnit != 0) {
- AudioOutputUnitStop(m_audioUnit);
+ audioDeviceStop();
AudioUnitUninitialize(m_audioUnit);
AudioComponentInstanceDispose(m_audioUnit);
}
@@ -592,32 +592,61 @@ void QDarwinAudioSink::close()
void QDarwinAudioSink::audioThreadStart()
{
- QMutexLocker lock(&m_mutex);
startTimers();
- m_audioThreadState.storeRelaxed(Running);
- AudioOutputUnitStart(m_audioUnit);
+ audioDeviceStart();
}
void QDarwinAudioSink::audioThreadStop()
{
- QMutexLocker lock(&m_mutex);
stopTimers();
- if (m_audioThreadState.testAndSetAcquire(Running, Stopped))
- m_threadFinished.wait(&m_mutex, 500);
+
+ // It's common practice to call AudioOutputUnitStop
+ // from the thread where the audio output was started,
+ // so we don't have to rely on the stops inside renderCallback.
+ audioDeviceStop();
}
void QDarwinAudioSink::audioThreadDrain()
{
- QMutexLocker lock(&m_mutex);
stopTimers();
- if (m_audioThreadState.testAndSetAcquire(Running, Draining))
- m_threadFinished.wait(&m_mutex, 500);
+
+ QMutexLocker lock(&m_mutex);
+
+ if (m_audioThreadState.testAndSetAcquire(Running, Draining)) {
+ constexpr int MaxDrainWaitingTime = 500;
+
+ m_threadFinished.wait(&m_mutex, MaxDrainWaitingTime);
+
+ if (m_audioThreadState.fetchAndStoreRelaxed(Stopped) != Stopped) {
+ qWarning() << "Couldn't wait for draining; force stop";
+
+ AudioOutputUnitStop(m_audioUnit);
+ }
+ }
+}
+
+void QDarwinAudioSink::audioDeviceStart()
+{
+ QMutexLocker lock(&m_mutex);
+
+ const auto state = m_audioThreadState.loadAcquire();
+ if (state == Stopped) {
+ m_audioThreadState.storeRelaxed(Running);
+ AudioOutputUnitStart(m_audioUnit);
+ } else {
+ qWarning() << "Unexpected state on audio device start:" << state;
+ }
}
void QDarwinAudioSink::audioDeviceStop()
{
- AudioOutputUnitStop(m_audioUnit);
- m_audioThreadState.storeRelaxed(Stopped);
+ {
+ QMutexLocker lock(&m_mutex);
+
+ AudioOutputUnitStop(m_audioUnit);
+ m_audioThreadState.storeRelaxed(Stopped);
+ }
+
m_threadFinished.wakeOne();
}
@@ -626,10 +655,11 @@ void QDarwinAudioSink::audioDeviceIdle()
if (m_stateCode != QAudio::ActiveState)
return;
- audioDeviceStop();
-
m_errorCode = QAudio::UnderrunError;
m_stateCode = QAudio::IdleState;
+
+ audioDeviceStop();
+
QMetaObject::invokeMethod(this, "deviceStopped", Qt::QueuedConnection);
}
@@ -638,10 +668,11 @@ void QDarwinAudioSink::audioDeviceError()
if (m_stateCode != QAudio::ActiveState)
return;
- audioDeviceStop();
-
m_errorCode = QAudio::IOError;
m_stateCode = QAudio::StoppedState;
+
+ audioDeviceStop();
+
QMetaObject::invokeMethod(this, "deviceStopped", Qt::QueuedConnection);
}