Cog Audio: Dealt with a major retain cycle leak

This seals up a major memory leak of the playback state whenever a chain
is released on stop or on manual track change. CogAudioMulti was
retaining the input node due to its listeners, and InputNode was not
releasing the listeners when asked to stop running. This is fixed now.

Fixes #221

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
CQTexperiment
Christopher Snowhill 2022-01-29 21:10:59 -08:00
parent 77a079bd53
commit 9e5a70c9ae
7 changed files with 53 additions and 13 deletions

View File

@ -68,7 +68,10 @@
ALog(@"Opening file for playback: %@ at seek offset %f%@", url, time, (paused) ? @", starting paused" : @"");
[self waitUntilCallbacksExit];
output = nil;
if (output) {
[output setShouldContinue:NO];
output = nil;
}
output = [[OutputNode alloc] initWithController:self previous:nil];
[output setup];
[output setVolume: volume];
@ -135,6 +138,20 @@
//Set shouldoContinue to NO on all things
[self setShouldContinue:NO];
[self setPlaybackStatus:CogStatusStopped waitUntilDone:YES];
@synchronized(chainQueue) {
for (id anObject in chainQueue)
{
[anObject setShouldContinue:NO];
}
[chainQueue removeAllObjects];
endOfInputReached = NO;
if (bufferChain)
{
bufferChain = nil;
}
}
output = nil;
}
- (void)pause

View File

@ -28,6 +28,8 @@
BOOL shouldSeek;
long seekFrame;
BOOL observersAdded;
Semaphore *exitAtTheEndOfTheStream;
}

View File

@ -90,6 +90,8 @@
forKeyPath:@"metadata"
options:(NSKeyValueObservingOptionNew)
context:NULL];
observersAdded = YES;
}
- (void)observeValueForKeyPath:(NSString *)keyPath
@ -219,8 +221,19 @@
- (void)removeObservers
{
[decoder removeObserver:self forKeyPath:@"properties"];
[decoder removeObserver:self forKeyPath:@"metadata"];
if (observersAdded)
{
[decoder removeObserver:self forKeyPath:@"properties"];
[decoder removeObserver:self forKeyPath:@"metadata"];
observersAdded = NO;
}
}
- (void)setShouldContinue:(BOOL)s
{
[super setShouldContinue:s];
if (!s)
[self removeObservers];
}
- (void)dealloc

View File

@ -137,6 +137,7 @@
- (void)close
{
[output stop];
output = nil;
}
- (void)setVolume:(double) v

View File

@ -108,10 +108,11 @@ NSArray * sortClassesByPriority(NSArray * theClasses)
- (void)close
{
if ( theDecoder != nil ) {
[theDecoder close];
for (NSDictionary *obsItem in cachedObservers) {
[theDecoder removeObserver:[obsItem objectForKey:@"observer"] forKeyPath:[obsItem objectForKey:@"keyPath"]];
}
[cachedObservers removeAllObjects];
[theDecoder close];
theDecoder = nil;
}
}

View File

@ -46,6 +46,7 @@
atomic_long bytesHdcdSustained;
BOOL listenerapplied;
BOOL observersapplied;
float volume;

View File

@ -174,10 +174,7 @@ static OSStatus renderCallback( void *inRefCon, AudioUnitRenderActionFlags *ioAc
#ifdef OUTPUT_LOG
_logFile = fopen("/tmp/CogAudioLog.raw", "wb");
#endif
[[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.outputDevice" options:0 context:NULL];
[[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.GraphicEQenable" options:0 context:NULL];
}
}
return self;
}
@ -704,6 +701,10 @@ default_device_changed(AudioObjectID inObjectID, UInt32 inNumberAddresses, const
[_au allocateRenderResourcesAndReturnError:&err];
[[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.outputDevice" options:0 context:NULL];
[[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.GraphicEQenable" options:0 context:NULL];
observersapplied = YES;
return (err == nil);
}
@ -732,6 +733,12 @@ default_device_changed(AudioObjectID inObjectID, UInt32 inNumberAddresses, const
- (void)stop
{
stopInvoked = YES;
if (observersapplied) {
observersapplied = NO;
[[NSUserDefaultsController sharedUserDefaultsController] removeObserver:self forKeyPath:@"values.outputDevice"];
[[NSUserDefaultsController sharedUserDefaultsController] removeObserver:self forKeyPath:@"values.GraphicEQenable"];
}
if (stopNext && started && !paused) {
while (![[outputController buffer] isEmpty]) {
[writeSemaphore signal];
@ -743,7 +750,6 @@ default_device_changed(AudioObjectID inObjectID, UInt32 inNumberAddresses, const
stopNext = NO;
[self signalEndOfStream];
}
stopInvoked = YES;
stopping = YES;
paused = NO;
[writeSemaphore signal];
@ -782,14 +788,13 @@ default_device_changed(AudioObjectID inObjectID, UInt32 inNumberAddresses, const
_logFile = NULL;
}
#endif
outputController = nil;
}
- (void)dealloc
{
[self stop];
[[NSUserDefaultsController sharedUserDefaultsController] removeObserver:self forKeyPath:@"values.outputDevice"];
[[NSUserDefaultsController sharedUserDefaultsController] removeObserver:self forKeyPath:@"values.GraphicEQenable"];
if (!stopInvoked)
[self stop];
}
- (void)pause