From 9aaf6d1c2dc3780040a01736c2d40ebb04f4e4d0 Mon Sep 17 00:00:00 2001 From: Christopher Snowhill Date: Thu, 13 Mar 2025 19:20:12 -0700 Subject: [PATCH] Crash Fix: Only selectively register observer This affects User Defaults, but only has any effect on ChunkLists which are being used for conversion, and only if they're processing DSD source material. Thus, the observer should only be added on the one stream that is converting DSD, and should definitely be removed when the object is deallocated. This fixes a serious crash bug that mostly appears to only affect Intel Macs, and has no major side effects on Apple Silicon that I can tell. It's a good thing I still own an Intel Mac or two to test on, even if they are both trapped on older releases of macOS. Signed-off-by: Christopher Snowhill --- Audio/Chain/ChunkList.h | 1 + Audio/Chain/ChunkList.m | 24 +++++++++++++++++++++--- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/Audio/Chain/ChunkList.h b/Audio/Chain/ChunkList.h index 34fea432a..3f1a5646c 100644 --- a/Audio/Chain/ChunkList.h +++ b/Audio/Chain/ChunkList.h @@ -39,6 +39,7 @@ NS_ASSUME_NONNULL_BEGIN int dsd2pcmLatency; #endif + BOOL observersRegistered; BOOL halveDSDVolume; void *hdcd_decoder; diff --git a/Audio/Chain/ChunkList.m b/Audio/Chain/ChunkList.m index c3e832156..1854c0acc 100644 --- a/Audio/Chain/ChunkList.m +++ b/Audio/Chain/ChunkList.m @@ -399,19 +399,36 @@ static void convert_be_to_le(uint8_t *buffer, size_t bitsPerSample, size_t bytes dsd2pcmLatency = 0; #endif - halveDSDVolume = NO; - - [[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.halveDSDVolume" options:(NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew) context:kChunkListContext]; + observersRegistered = NO; } return self; } +- (void)addObservers { + if(!observersRegistered) { + halveDSDVolume = NO; + + [[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.halveDSDVolume" options:(NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew) context:kChunkListContext]; + + observersRegistered = YES; + } +} + +- (void)removeObservers { + if(observersRegistered) { + [[NSUserDefaultsController sharedUserDefaultsController] removeObserver:self forKeyPath:@"values.halveDSDVolume" context:kChunkListContext]; + + observersRegistered = NO; + } +} + - (void)dealloc { stopping = YES; while(inAdder || inRemover || inPeeker || inMerger || inConverter) { usleep(500); } + [self removeObservers]; if(hdcd_decoder) { free(hdcd_decoder); hdcd_decoder = NULL; @@ -786,6 +803,7 @@ static void convert_be_to_le(uint8_t *buffer, size_t bitsPerSample, size_t bytes isFloat = YES; inputBuffer = &tempData[buffer_adder]; inputChanged = YES; + [self addObservers]; #if DSD_DECIMATE if(halveDSDVolume) { float scaleFactor = 2.0f;