From aabd9431f1e81ddfeaf546b1ed4bd022db914fbf Mon Sep 17 00:00:00 2001 From: Christopher Snowhill Date: Mon, 30 May 2022 21:38:29 -0700 Subject: [PATCH] [Visualization] Gate registered observers Gate registering observers behind a check variable in the object state, which will be zero initialized by the Objective-C runtime, and will prevent the class from erroneously unregistering observers without them being registered in the first place. Apparently, services cannot be unregistered if they were never registered first, or else an exception will be thrown upon attempting to unregister them. This fixes a crash on startup in the now several times running failure to work properly on legacy Macs without Metal graphics, now that the new visualization system has been implemented. It's probably not worth bringing back the previous Core Graphics based visualizer method anyway, as on those same legacy machines, it was causing out of control CPU usage by WindowServer. At least on modern Macs, any amount of 60fps UI updating will cause WindowServer to use about 45% of a core, regardless of how many apps are drawing that much at once. Signed-off-by: Christopher Snowhill --- Visualization/SpectrumView.m | 85 +++++++++++++++++++++--------------- 1 file changed, 51 insertions(+), 34 deletions(-) diff --git a/Visualization/SpectrumView.m b/Visualization/SpectrumView.m index d5a51fbf5..a1d06dc48 100644 --- a/Visualization/SpectrumView.m +++ b/Visualization/SpectrumView.m @@ -28,6 +28,7 @@ extern NSString *CogPlaybackDidStopNotficiation; BOOL isListening; BOOL bandsReset; BOOL cameraControlEnabled; + BOOL observersRegistered; NSColor *backgroundColor; ddb_analyzer_t _analyzer; @@ -171,48 +172,64 @@ extern NSString *CogPlaybackDidStopNotficiation; _analyzer.freq_is_log = 0; _analyzer.mode = freqMode ? DDB_ANALYZER_MODE_FREQUENCIES : DDB_ANALYZER_MODE_OCTAVE_NOTE_BANDS; - [[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.spectrumProjectionMode" options:0 context:kSpectrumViewContext]; - [[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.spectrumBarColor" options:0 context:kSpectrumViewContext]; - [[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.spectrumDotColor" options:0 context:kSpectrumViewContext]; + [self registerObservers]; +} - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(playbackDidBegin:) - name:CogPlaybackDidBeginNotficiation - object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(playbackDidPause:) - name:CogPlaybackDidPauseNotficiation - object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(playbackDidResume:) - name:CogPlaybackDidResumeNotficiation - object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(playbackDidStop:) - name:CogPlaybackDidStopNotficiation - object:nil]; +- (void)registerObservers { + if(!observersRegistered) { + [[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.spectrumProjectionMode" options:0 context:kSpectrumViewContext]; + [[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.spectrumBarColor" options:0 context:kSpectrumViewContext]; + [[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.spectrumDotColor" options:0 context:kSpectrumViewContext]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(playbackDidBegin:) + name:CogPlaybackDidBeginNotficiation + object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(playbackDidPause:) + name:CogPlaybackDidPauseNotficiation + object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(playbackDidResume:) + name:CogPlaybackDidResumeNotficiation + object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(playbackDidStop:) + name:CogPlaybackDidStopNotficiation + object:nil]; + + observersRegistered = YES; + } } - (void)dealloc { ddb_analyzer_dealloc(&_analyzer); ddb_analyzer_draw_data_dealloc(&_draw_data); - [[NSUserDefaultsController sharedUserDefaultsController] removeObserver:self forKeyPath:@"values.spectrumProjectionMode"]; - [[NSUserDefaultsController sharedUserDefaultsController] removeObserver:self forKeyPath:@"values.spectrumBarColor"]; - [[NSUserDefaultsController sharedUserDefaultsController] removeObserver:self forKeyPath:@"values.spectrumDotColor"]; + [self removeObservers]; +} - [[NSNotificationCenter defaultCenter] removeObserver:self - name:CogPlaybackDidBeginNotficiation - object:nil]; - [[NSNotificationCenter defaultCenter] removeObserver:self - name:CogPlaybackDidPauseNotficiation - object:nil]; - [[NSNotificationCenter defaultCenter] removeObserver:self - name:CogPlaybackDidResumeNotficiation - object:nil]; - [[NSNotificationCenter defaultCenter] removeObserver:self - name:CogPlaybackDidStopNotficiation - object:nil]; +- (void)removeObservers { + if(observersRegistered) { + [[NSUserDefaultsController sharedUserDefaultsController] removeObserver:self forKeyPath:@"values.spectrumProjectionMode"]; + [[NSUserDefaultsController sharedUserDefaultsController] removeObserver:self forKeyPath:@"values.spectrumBarColor"]; + [[NSUserDefaultsController sharedUserDefaultsController] removeObserver:self forKeyPath:@"values.spectrumDotColor"]; + + [[NSNotificationCenter defaultCenter] removeObserver:self + name:CogPlaybackDidBeginNotficiation + object:nil]; + [[NSNotificationCenter defaultCenter] removeObserver:self + name:CogPlaybackDidPauseNotficiation + object:nil]; + [[NSNotificationCenter defaultCenter] removeObserver:self + name:CogPlaybackDidResumeNotficiation + object:nil]; + [[NSNotificationCenter defaultCenter] removeObserver:self + name:CogPlaybackDidStopNotficiation + object:nil]; + + observersRegistered = NO; + } } - (void)repaint {