[Event Handling] Add context to all observers

Add context field to all observers that support it, in case it's useful.

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
swiftingly
Christopher Snowhill 2022-06-15 16:47:43 -07:00
parent 5bca70d141
commit 8db2e41049
12 changed files with 157 additions and 87 deletions

View File

@ -47,6 +47,8 @@ void PrintStreamDesc(AudioStreamBasicDescription *inDesc) {
@implementation ConverterNode @implementation ConverterNode
static void *kConverterNodeContext = &kConverterNodeContext;
@synthesize inputFormat; @synthesize inputFormat;
- (id)initWithController:(id)c previous:(id)p { - (id)initWithController:(id)c previous:(id)p {
@ -78,7 +80,7 @@ void PrintStreamDesc(AudioStreamBasicDescription *inDesc) {
lastChunkIn = nil; lastChunkIn = nil;
[[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.volumeScaling" options:0 context:nil]; [[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.volumeScaling" options:0 context:kConverterNodeContext];
} }
return self; return self;
@ -900,10 +902,14 @@ tryagain:
ofObject:(id)object ofObject:(id)object
change:(NSDictionary *)change change:(NSDictionary *)change
context:(void *)context { context:(void *)context {
DLog(@"SOMETHING CHANGED!"); if(context == kConverterNodeContext) {
if([keyPath isEqualToString:@"values.volumeScaling"]) { DLog(@"SOMETHING CHANGED!");
// User reset the volume scaling option if([keyPath isEqualToString:@"values.volumeScaling"]) {
[self refreshVolumeScaling]; // User reset the volume scaling option
[self refreshVolumeScaling];
}
} else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
} }
} }
@ -1056,7 +1062,7 @@ static float db_to_scale(float db) {
- (void)dealloc { - (void)dealloc {
DLog(@"Decoder dealloc"); DLog(@"Decoder dealloc");
[[NSUserDefaultsController sharedUserDefaultsController] removeObserver:self forKeyPath:@"values.volumeScaling"]; [[NSUserDefaultsController sharedUserDefaultsController] removeObserver:self forKeyPath:@"values.volumeScaling" context:kConverterNodeContext];
paused = NO; paused = NO;
[self cleanUp]; [self cleanUp];

View File

@ -250,6 +250,8 @@ static void upmix(const float *inBuffer, int inchannels, uint32_t inconfig, floa
@implementation DownmixProcessor @implementation DownmixProcessor
static void *kDownmixProcessorContext = &kDownmixProcessorContext;
- (id)initWithInputFormat:(AudioStreamBasicDescription)inf inputConfig:(uint32_t)iConfig andOutputFormat:(AudioStreamBasicDescription)outf outputConfig:(uint32_t)oConfig { - (id)initWithInputFormat:(AudioStreamBasicDescription)inf inputConfig:(uint32_t)iConfig andOutputFormat:(AudioStreamBasicDescription)outf outputConfig:(uint32_t)oConfig {
self = [super init]; self = [super init];
@ -276,16 +278,16 @@ static void upmix(const float *inBuffer, int inchannels, uint32_t inconfig, floa
[self setupVirt]; [self setupVirt];
[[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.headphoneVirtualization" options:0 context:nil]; [[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.headphoneVirtualization" options:0 context:kDownmixProcessorContext];
[[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.hrirPath" options:0 context:nil]; [[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.hrirPath" options:0 context:kDownmixProcessorContext];
} }
return self; return self;
} }
- (void)dealloc { - (void)dealloc {
[[NSUserDefaultsController sharedUserDefaultsController] removeObserver:self forKeyPath:@"values.headphoneVirtualization"]; [[NSUserDefaultsController sharedUserDefaultsController] removeObserver:self forKeyPath:@"values.headphoneVirtualization" context:kDownmixProcessorContext];
[[NSUserDefaultsController sharedUserDefaultsController] removeObserver:self forKeyPath:@"values.hrirPath"]; [[NSUserDefaultsController sharedUserDefaultsController] removeObserver:self forKeyPath:@"values.hrirPath" context:kDownmixProcessorContext];
} }
- (void)setupVirt { - (void)setupVirt {
@ -328,11 +330,15 @@ static void upmix(const float *inBuffer, int inchannels, uint32_t inconfig, floa
ofObject:(id)object ofObject:(id)object
change:(NSDictionary *)change change:(NSDictionary *)change
context:(void *)context { context:(void *)context {
DLog(@"SOMETHING CHANGED!"); if(context == kDownmixProcessorContext) {
if([keyPath isEqualToString:@"values.headphoneVirtualization"] || DLog(@"SOMETHING CHANGED!");
[keyPath isEqualToString:@"values.hrirPath"]) { if([keyPath isEqualToString:@"values.headphoneVirtualization"] ||
// Reset the converter, without rebuffering [keyPath isEqualToString:@"values.hrirPath"]) {
[self setupVirt]; // Reset the converter, without rebuffering
[self setupVirt];
}
} else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
} }
} }

View File

@ -18,6 +18,9 @@
#import "Logging.h" #import "Logging.h"
@implementation InputNode @implementation InputNode
static void *kInputNodeContext = &kInputNodeContext;
@synthesize exitAtTheEndOfTheStream; @synthesize exitAtTheEndOfTheStream;
- (id)initWithController:(id)c previous:(id)p { - (id)initWithController:(id)c previous:(id)p {
@ -84,47 +87,53 @@
} }
- (void)registerObservers { - (void)registerObservers {
DLog(@"REGISTERING OBSERVERS"); if(!observersAdded) {
[decoder addObserver:self DLog(@"REGISTERING OBSERVERS");
forKeyPath:@"properties" [decoder addObserver:self
options:(NSKeyValueObservingOptionNew) forKeyPath:@"properties"
context:NULL]; options:(NSKeyValueObservingOptionNew)
context:kInputNodeContext];
[decoder addObserver:self [decoder addObserver:self
forKeyPath:@"metadata" forKeyPath:@"metadata"
options:(NSKeyValueObservingOptionNew) options:(NSKeyValueObservingOptionNew)
context:NULL]; context:kInputNodeContext];
observersAdded = YES; observersAdded = YES;
}
} }
- (void)observeValueForKeyPath:(NSString *)keyPath - (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object ofObject:(id)object
change:(NSDictionary *)change change:(NSDictionary *)change
context:(void *)context { context:(void *)context {
DLog(@"SOMETHING CHANGED!"); if(context == kInputNodeContext) {
if([keyPath isEqual:@"properties"]) { DLog(@"SOMETHING CHANGED!");
DLog(@"Input format changed"); if([keyPath isEqual:@"properties"]) {
// Converter may need resetting, it'll do that when it reaches the new chunks DLog(@"Input format changed");
NSDictionary *properties = [decoder properties]; // Converter may need resetting, it'll do that when it reaches the new chunks
NSDictionary *properties = [decoder properties];
int bitsPerSample = [[properties objectForKey:@"bitsPerSample"] intValue]; int bitsPerSample = [[properties objectForKey:@"bitsPerSample"] intValue];
int channels = [[properties objectForKey:@"channels"] intValue]; int channels = [[properties objectForKey:@"channels"] intValue];
bytesPerFrame = ((bitsPerSample + 7) / 8) * channels; bytesPerFrame = ((bitsPerSample + 7) / 8) * channels;
nodeFormat = propertiesToASBD(properties); nodeFormat = propertiesToASBD(properties);
nodeChannelConfig = [[properties valueForKey:@"channelConfig"] unsignedIntValue]; nodeChannelConfig = [[properties valueForKey:@"channelConfig"] unsignedIntValue];
nodeLossless = [[properties valueForKey:@"encoding"] isEqualToString:@"lossless"]; nodeLossless = [[properties valueForKey:@"encoding"] isEqualToString:@"lossless"];
} else if([keyPath isEqual:@"metadata"]) { } else if([keyPath isEqual:@"metadata"]) {
// Inform something of metadata change // Inform something of metadata change
NSDictionary *entryProperties = [decoder properties]; NSDictionary *entryProperties = [decoder properties];
if(entryProperties == nil) if(entryProperties == nil)
return; return;
NSDictionary *entryInfo = [NSDictionary dictionaryByMerging:entryProperties with:[decoder metadata]]; NSDictionary *entryInfo = [NSDictionary dictionaryByMerging:entryProperties with:[decoder metadata]];
[controller pushInfo:entryInfo]; [controller pushInfo:entryInfo];
}
} else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
} }
} }
@ -251,8 +260,8 @@
- (void)removeObservers { - (void)removeObservers {
if(observersAdded) { if(observersAdded) {
[decoder removeObserver:self forKeyPath:@"properties"]; [decoder removeObserver:self forKeyPath:@"properties" context:kInputNodeContext];
[decoder removeObserver:self forKeyPath:@"metadata"]; [decoder removeObserver:self forKeyPath:@"metadata" context:kInputNodeContext];
observersAdded = NO; observersAdded = NO;
} }
} }

View File

@ -42,6 +42,8 @@ NSArray *sortClassesByPriority(NSArray *theClasses) {
@implementation CogDecoderMulti @implementation CogDecoderMulti
static void *kCogDecoderMultiContext = &kCogDecoderMultiContext;
+ (NSArray *)mimeTypes { + (NSArray *)mimeTypes {
return nil; return nil;
} }
@ -114,17 +116,17 @@ NSArray *sortClassesByPriority(NSArray *theClasses) {
[theDecoder addObserver:self [theDecoder addObserver:self
forKeyPath:@"properties" forKeyPath:@"properties"
options:(NSKeyValueObservingOptionNew) options:(NSKeyValueObservingOptionNew)
context:NULL]; context:kCogDecoderMultiContext];
[theDecoder addObserver:self [theDecoder addObserver:self
forKeyPath:@"metadata" forKeyPath:@"metadata"
options:(NSKeyValueObservingOptionNew) options:(NSKeyValueObservingOptionNew)
context:NULL]; context:kCogDecoderMultiContext];
} }
- (void)removeObservers { - (void)removeObservers {
[theDecoder removeObserver:self forKeyPath:@"properties"]; [theDecoder removeObserver:self forKeyPath:@"properties" context:kCogDecoderMultiContext];
[theDecoder removeObserver:self forKeyPath:@"metadata"]; [theDecoder removeObserver:self forKeyPath:@"metadata" context:kCogDecoderMultiContext];
} }
- (BOOL)setTrack:(NSURL *)track { - (BOOL)setTrack:(NSURL *)track {
@ -136,8 +138,12 @@ NSArray *sortClassesByPriority(NSArray *theClasses) {
ofObject:(id)object ofObject:(id)object
change:(NSDictionary *)change change:(NSDictionary *)change
context:(void *)context { context:(void *)context {
[self willChangeValueForKey:keyPath]; if(context == kCogDecoderMultiContext) {
[self didChangeValueForKey:keyPath]; [self willChangeValueForKey:keyPath];
[self didChangeValueForKey:keyPath];
} else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
} }
@end @end

View File

@ -23,6 +23,8 @@ static NSString *CogPlaybackDidBeginNotficiation = @"CogPlaybackDidBeginNotficia
@implementation OutputCoreAudio @implementation OutputCoreAudio
static void *kOutputCoreAudioContext = &kOutputCoreAudioContext;
static void fillBuffers(AudioBufferList *ioData, float *inbuffer, size_t count, size_t offset) { static void fillBuffers(AudioBufferList *ioData, float *inbuffer, size_t count, size_t offset) {
const size_t channels = ioData->mNumberBuffers; const size_t channels = ioData->mNumberBuffers;
for(int i = 0; i < channels; ++i) { for(int i = 0; i < channels; ++i) {
@ -223,6 +225,11 @@ default_device_changed(AudioObjectID inObjectID, UInt32 inNumberAddresses, const
} }
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if(context != kOutputCoreAudioContext) {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
return;
}
if([keyPath isEqualToString:@"values.outputDevice"]) { if([keyPath isEqualToString:@"values.outputDevice"]) {
NSDictionary *device = [[[NSUserDefaultsController sharedUserDefaultsController] defaults] objectForKey:@"outputDevice"]; NSDictionary *device = [[[NSUserDefaultsController sharedUserDefaultsController] defaults] objectForKey:@"outputDevice"];
@ -774,9 +781,9 @@ default_device_changed(AudioObjectID inObjectID, UInt32 inNumberAddresses, const
visController = [VisualizationController sharedController]; visController = [VisualizationController sharedController];
[[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.outputDevice" options:0 context:NULL]; [[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.outputDevice" options:0 context:kOutputCoreAudioContext];
[[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.GraphicEQenable" options:0 context:NULL]; [[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.GraphicEQenable" options:0 context:kOutputCoreAudioContext];
[[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.eqPreamp" options:(NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew) context:NULL]; [[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.eqPreamp" options:(NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew) context:kOutputCoreAudioContext];
observersapplied = YES; observersapplied = YES;
return (err == nil); return (err == nil);
@ -805,10 +812,10 @@ default_device_changed(AudioObjectID inObjectID, UInt32 inNumberAddresses, const
- (void)stop { - (void)stop {
stopInvoked = YES; stopInvoked = YES;
if(observersapplied) { if(observersapplied) {
[[NSUserDefaultsController sharedUserDefaultsController] removeObserver:self forKeyPath:@"values.outputDevice" context:kOutputCoreAudioContext];
[[NSUserDefaultsController sharedUserDefaultsController] removeObserver:self forKeyPath:@"values.GraphicEQenable" context:kOutputCoreAudioContext];
[[NSUserDefaultsController sharedUserDefaultsController] removeObserver:self forKeyPath:@"values.eqPreamp" context:kOutputCoreAudioContext];
observersapplied = NO; observersapplied = NO;
[[NSUserDefaultsController sharedUserDefaultsController] removeObserver:self forKeyPath:@"values.outputDevice"];
[[NSUserDefaultsController sharedUserDefaultsController] removeObserver:self forKeyPath:@"values.GraphicEQenable"];
[[NSUserDefaultsController sharedUserDefaultsController] removeObserver:self forKeyPath:@"values.eqPreamp"];
} }
if(stopNext && !paused) { if(stopNext && !paused) {
if(!started) { if(!started) {

View File

@ -53,6 +53,7 @@
// These are in NSObject, so as long as you are a subclass of that, you are ok. // These are in NSObject, so as long as you are a subclass of that, you are ok.
- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context; - (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context;
- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath; - (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath;
- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath context:(void *)context;
- (BOOL)isSilence; - (BOOL)isSilence;
@end @end

View File

@ -13,6 +13,8 @@
#import "Logging.h" #import "Logging.h"
static void *kFileTreeDataSourceContext = &kFileTreeDataSourceContext;
static NSURL *defaultMusicDirectory(void) { static NSURL *defaultMusicDirectory(void) {
return [[NSFileManager defaultManager] URLForDirectory:NSMusicDirectory return [[NSFileManager defaultManager] URLForDirectory:NSMusicDirectory
inDomain:NSUserDomainMask inDomain:NSUserDomainMask
@ -44,18 +46,22 @@ static NSURL *defaultMusicDirectory(void) {
forKeyPath:@"values.fileTreeRootURL" forKeyPath:@"values.fileTreeRootURL"
options:NSKeyValueObservingOptionNew | options:NSKeyValueObservingOptionNew |
NSKeyValueObservingOptionInitial NSKeyValueObservingOptionInitial
context:nil]; context:kFileTreeDataSourceContext];
} }
- (void)observeValueForKeyPath:(NSString *)keyPath - (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object ofObject:(id)object
change:(NSDictionary *)change change:(NSDictionary *)change
context:(void *)context { context:(void *)context {
if([keyPath isEqualToString:@"values.fileTreeRootURL"]) { if(context == kFileTreeDataSourceContext) {
NSString *url = if([keyPath isEqualToString:@"values.fileTreeRootURL"]) {
[[[NSUserDefaultsController sharedUserDefaultsController] defaults] objectForKey:@"fileTreeRootURL"]; NSString *url =
DLog(@"File tree root URL: %@\n", url); [[[NSUserDefaultsController sharedUserDefaultsController] defaults] objectForKey:@"fileTreeRootURL"];
self.rootURL = [NSURL URLWithString:url]; DLog(@"File tree root URL: %@\n", url);
self.rootURL = [NSURL URLWithString:url];
}
} else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
} }
} }

View File

@ -14,6 +14,8 @@
@implementation InfoWindowController @implementation InfoWindowController
static void *kInfoWindowControllerContext = &kInfoWindowControllerContext;
@synthesize valueToDisplay; @synthesize valueToDisplay;
+ (void)initialize { + (void)initialize {
@ -27,18 +29,22 @@
} }
- (void)awakeFromNib { - (void)awakeFromNib {
[playlistSelectionController addObserver:self forKeyPath:@"selection" options:NSKeyValueObservingOptionNew context:nil]; [playlistSelectionController addObserver:self forKeyPath:@"selection" options:NSKeyValueObservingOptionNew context:kInfoWindowControllerContext];
[currentEntryController addObserver:self forKeyPath:@"content" options:NSKeyValueObservingOptionNew context:nil]; [currentEntryController addObserver:self forKeyPath:@"content" options:NSKeyValueObservingOptionNew context:kInfoWindowControllerContext];
[appController addObserver:self forKeyPath:@"miniMode" options:NSKeyValueObservingOptionNew context:nil]; [appController addObserver:self forKeyPath:@"miniMode" options:NSKeyValueObservingOptionNew context:kInfoWindowControllerContext];
} }
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
// Avoid "selection" because it creates a proxy that's hard to reason with when we don't need to write. if(context == kInfoWindowControllerContext) {
PlaylistEntry *currentSelection = [[playlistSelectionController selectedObjects] firstObject]; // Avoid "selection" because it creates a proxy that's hard to reason with when we don't need to write.
if(currentSelection != NULL) { PlaylistEntry *currentSelection = [[playlistSelectionController selectedObjects] firstObject];
[self setValueToDisplay:currentSelection]; if(currentSelection != NULL) {
[self setValueToDisplay:currentSelection];
} else {
[self setValueToDisplay:[currentEntryController content]];
}
} else { } else {
[self setValueToDisplay:[currentEntryController content]]; [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
} }
} }

View File

@ -18,6 +18,8 @@
@implementation CueSheetDecoder @implementation CueSheetDecoder
static void *kCueSheetDecoderContext = &kCueSheetDecoderContext;
+ (NSArray *)fileTypes { + (NSArray *)fileTypes {
return [CueSheetContainer fileTypes]; return [CueSheetContainer fileTypes];
} }
@ -199,24 +201,26 @@
} }
- (void)registerObservers { - (void)registerObservers {
DLog(@"REGISTERING OBSERVERS"); if(!observersAdded) {
[decoder addObserver:self DLog(@"REGISTERING OBSERVERS");
forKeyPath:@"properties" [decoder addObserver:self
options:(NSKeyValueObservingOptionNew) forKeyPath:@"properties"
context:NULL]; options:(NSKeyValueObservingOptionNew)
context:kCueSheetDecoderContext];
[decoder addObserver:self [decoder addObserver:self
forKeyPath:@"metadata" forKeyPath:@"metadata"
options:(NSKeyValueObservingOptionNew) options:(NSKeyValueObservingOptionNew)
context:NULL]; context:kCueSheetDecoderContext];
observersAdded = YES; observersAdded = YES;
}
} }
- (void)removeObservers { - (void)removeObservers {
if(observersAdded) { if(observersAdded) {
[decoder removeObserver:self forKeyPath:@"properties"]; [decoder removeObserver:self forKeyPath:@"properties" context:kCueSheetDecoderContext];
[decoder removeObserver:self forKeyPath:@"metadata"]; [decoder removeObserver:self forKeyPath:@"metadata" context:kCueSheetDecoderContext];
observersAdded = NO; observersAdded = NO;
} }
} }
@ -225,8 +229,12 @@
ofObject:(id)object ofObject:(id)object
change:(NSDictionary *)change change:(NSDictionary *)change
context:(void *)context { context:(void *)context {
[self willChangeValueForKey:keyPath]; if(context == kCueSheetDecoderContext) {
[self didChangeValueForKey:keyPath]; [self willChangeValueForKey:keyPath];
[self didChangeValueForKey:keyPath];
} else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
} }
- (void)close { - (void)close {

View File

@ -109,6 +109,8 @@ extern NSString *CogPlaybackDidStopNotficiation;
} else { } else {
[self colorsDidChange:nil]; [self colorsDidChange:nil];
} }
} else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
} }
} }

View File

@ -85,6 +85,8 @@ extern NSString *CogPlaybackDidStopNotficiation;
} else { } else {
[self updateControls]; [self updateControls];
} }
} else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
} }
} }

View File

@ -10,9 +10,12 @@
#import "CogAudio/Helper.h" #import "CogAudio/Helper.h"
#import "PlaybackController.h" #import "PlaybackController.h"
static void *kVolumeSliderContext = &kVolumeSliderContext;
@implementation VolumeSlider { @implementation VolumeSlider {
NSTimer *currentTimer; NSTimer *currentTimer;
BOOL wasInsideSnapRange; BOOL wasInsideSnapRange;
BOOL observersadded;
} }
- (id)initWithFrame:(NSRect)frame { - (id)initWithFrame:(NSRect)frame {
@ -46,11 +49,14 @@
popover.animates = NO; popover.animates = NO;
[popover setContentSize:textView.bounds.size]; [popover setContentSize:textView.bounds.size];
[[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.volumeLimit" options:0 context:nil]; [[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.volumeLimit" options:0 context:kVolumeSliderContext];
observersadded = YES;
} }
- (void)dealloc { - (void)dealloc {
[[NSUserDefaultsController sharedUserDefaultsController] removeObserver:self forKeyPath:@"values.volumeLimit"]; if(observersadded) {
[[NSUserDefaultsController sharedUserDefaultsController] removeObserver:self forKeyPath:@"values.volumeLimit" context:kVolumeSliderContext];
}
} }
- (void)updateToolTip { - (void)updateToolTip {
@ -116,6 +122,11 @@
} }
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if(context != kVolumeSliderContext) {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
return;
}
if([keyPath isEqualToString:@"values.volumeLimit"]) { if([keyPath isEqualToString:@"values.volumeLimit"]) {
BOOL volumeLimit = [[[NSUserDefaultsController sharedUserDefaultsController] defaults] boolForKey:@"volumeLimit"]; BOOL volumeLimit = [[[NSUserDefaultsController sharedUserDefaultsController] defaults] boolForKey:@"volumeLimit"];
const double new_MAX_VOLUME = (volumeLimit) ? 100.0 : 800.0; const double new_MAX_VOLUME = (volumeLimit) ? 100.0 : 800.0;