[Core Audio Output] Improve safety on stopping

Synchronize audio setup and audio stopping on the object's own pointer,
to hopefully prevent race conditions with out of sync calls to the stop
function from both the main and the audio thread.

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
swiftingly
Christopher Snowhill 2022-06-15 21:46:02 -07:00
parent e9230a080c
commit 0997ca2c93
1 changed files with 189 additions and 184 deletions

View File

@ -344,7 +344,6 @@ default_device_changed(AudioObjectID inObjectID, UInt32 inNumberAddresses, const
}
stopped = YES;
if(!stopInvoked)
[self stop];
}
@ -623,7 +622,9 @@ default_device_changed(AudioObjectID inObjectID, UInt32 inNumberAddresses, const
if(_au)
[self stop];
@synchronized(self) {
stopInvoked = NO;
running = NO;
stopping = NO;
stopped = NO;
@ -787,6 +788,7 @@ default_device_changed(AudioObjectID inObjectID, UInt32 inNumberAddresses, const
observersapplied = YES;
return (err == nil);
}
}
- (void)setVolume:(double)v {
@ -810,6 +812,8 @@ default_device_changed(AudioObjectID inObjectID, UInt32 inNumberAddresses, const
}
- (void)stop {
@synchronized(self) {
if(stopInvoked) return;
stopInvoked = YES;
if(observersapplied) {
[[NSUserDefaultsController sharedUserDefaultsController] removeObserver:self forKeyPath:@"values.outputDevice" context:kOutputCoreAudioContext];
@ -852,12 +856,13 @@ default_device_changed(AudioObjectID inObjectID, UInt32 inNumberAddresses, const
[_au stopHardware];
_au = nil;
}
if(running)
if(running) {
while(!stopped) {
stopping = YES;
[readSemaphore signal];
[writeSemaphore timedWait:5000];
}
}
if(_eq) {
[outputController endEqualizer:_eq];
if(eqInitialized) {
@ -881,10 +886,10 @@ default_device_changed(AudioObjectID inObjectID, UInt32 inNumberAddresses, const
#endif
outputController = nil;
visController = nil;
}
}
- (void)dealloc {
if(!stopInvoked)
[self stop];
}