Core Audio output: Correctly terminate output when requested to stop, preventing a case where multiple outputs were draining the playback buffer at once
parent
2633e713a3
commit
8664bacc60
|
@ -20,6 +20,7 @@
|
||||||
@interface OutputCoreAudio : NSObject {
|
@interface OutputCoreAudio : NSObject {
|
||||||
OutputNode * outputController;
|
OutputNode * outputController;
|
||||||
|
|
||||||
|
BOOL running;
|
||||||
BOOL stopping;
|
BOOL stopping;
|
||||||
BOOL stopped;
|
BOOL stopped;
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@ extern void scale_by_volume(float * buffer, size_t count, float volume);
|
||||||
volume = 1.0;
|
volume = 1.0;
|
||||||
outputDeviceID = -1;
|
outputDeviceID = -1;
|
||||||
listenerapplied = NO;
|
listenerapplied = NO;
|
||||||
|
running = NO;
|
||||||
|
|
||||||
_sema = dispatch_semaphore_create(0);
|
_sema = dispatch_semaphore_create(0);
|
||||||
|
|
||||||
|
@ -54,9 +55,11 @@ default_device_changed(AudioObjectID inObjectID, UInt32 inNumberAddresses, const
|
||||||
|
|
||||||
- (void)threadEntry:(id)arg
|
- (void)threadEntry:(id)arg
|
||||||
{
|
{
|
||||||
|
running = YES;
|
||||||
while (!stopping) {
|
while (!stopping) {
|
||||||
dispatch_semaphore_wait(_sema, DISPATCH_TIME_FOREVER);
|
dispatch_semaphore_wait(_sema, DISPATCH_TIME_FOREVER);
|
||||||
}
|
}
|
||||||
|
stopped = YES;
|
||||||
[self stop];
|
[self stop];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -231,7 +234,9 @@ default_device_changed(AudioObjectID inObjectID, UInt32 inNumberAddresses, const
|
||||||
if (_au)
|
if (_au)
|
||||||
[self stop];
|
[self stop];
|
||||||
|
|
||||||
|
running = NO;
|
||||||
stopping = NO;
|
stopping = NO;
|
||||||
|
stopped = NO;
|
||||||
outputDeviceID = -1;
|
outputDeviceID = -1;
|
||||||
|
|
||||||
AVAudioFormat *format, *renderFormat;
|
AVAudioFormat *format, *renderFormat;
|
||||||
|
@ -326,7 +331,7 @@ default_device_changed(AudioObjectID inObjectID, UInt32 inNumberAddresses, const
|
||||||
|
|
||||||
amountToRead = inputData->mBuffers[0].mDataByteSize;
|
amountToRead = inputData->mBuffers[0].mDataByteSize;
|
||||||
|
|
||||||
if (self->stopping == YES || [outputController endOfStream] == YES)
|
if (self->stopping == YES || [outputController shouldContinue] == NO)
|
||||||
{
|
{
|
||||||
memset(readPointer, 0, amountToRead);
|
memset(readPointer, 0, amountToRead);
|
||||||
self->stopping = YES;
|
self->stopping = YES;
|
||||||
|
@ -381,6 +386,7 @@ default_device_changed(AudioObjectID inObjectID, UInt32 inNumberAddresses, const
|
||||||
|
|
||||||
- (void)stop
|
- (void)stop
|
||||||
{
|
{
|
||||||
|
stopping = YES;
|
||||||
if (listenerapplied) {
|
if (listenerapplied) {
|
||||||
AudioObjectPropertyAddress theAddress = {
|
AudioObjectPropertyAddress theAddress = {
|
||||||
.mSelector = kAudioHardwarePropertyDefaultOutputDevice,
|
.mSelector = kAudioHardwarePropertyDefaultOutputDevice,
|
||||||
|
@ -393,15 +399,20 @@ default_device_changed(AudioObjectID inObjectID, UInt32 inNumberAddresses, const
|
||||||
if (_au) {
|
if (_au) {
|
||||||
[_au stopHardware];
|
[_au stopHardware];
|
||||||
_au = nil;
|
_au = nil;
|
||||||
|
}
|
||||||
|
if (running)
|
||||||
|
while (!stopped)
|
||||||
|
{
|
||||||
stopping = YES;
|
stopping = YES;
|
||||||
dispatch_semaphore_signal(_sema);
|
dispatch_semaphore_signal(_sema);
|
||||||
|
usleep(500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)dealloc
|
- (void)dealloc
|
||||||
{
|
{
|
||||||
[self stop];
|
[self stop];
|
||||||
|
|
||||||
[[NSUserDefaultsController sharedUserDefaultsController] removeObserver:self forKeyPath:@"values.outputDevice"];
|
[[NSUserDefaultsController sharedUserDefaultsController] removeObserver:self forKeyPath:@"values.outputDevice"];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue