diff --git a/Application/PlaybackController.m b/Application/PlaybackController.m index 1675a6bdf..5b1a17167 100644 --- a/Application/PlaybackController.m +++ b/Application/PlaybackController.m @@ -62,6 +62,7 @@ NSString *CogPlaybackDidStopNotficiation = @"CogPlaybackDidStopNotficiation"; [NSNumber numberWithDouble:100.0], @"volume", [NSNumber numberWithBool:NO], @"GraphicEQenable", [NSNumber numberWithInt:-1], @"GraphicEQpreset", + [NSNumber numberWithBool:NO], @"GraphicEQtrackgenre", nil]; [[NSUserDefaults standardUserDefaults] registerDefaults:defaultsDictionary]; @@ -667,6 +668,8 @@ NSDictionary * makeRGInfo(PlaylistEntry *pe) CFRelease(classData); } + + equalizerLoadPreset(eq); } if (_eqWasOpen) @@ -677,6 +680,11 @@ NSDictionary * makeRGInfo(PlaylistEntry *pe) } } +- (void)audioPlayer:(AudioPlayer *)player refreshEqualizer:(AudioUnit)eq +{ + equalizerLoadPreset(eq); +} + - (void)audioPlayer:(AudioPlayer *)player removeEqualizer:(AudioUnit)eq { if (eq == _eq) @@ -738,6 +746,8 @@ NSDictionary * makeRGInfo(PlaylistEntry *pe) [playlistController setCurrentEntry:pe]; + equalizerApplyGenre([pe genre]); + lastPosition = -10; [self setPosition:0]; diff --git a/Audio/AudioPlayer.h b/Audio/AudioPlayer.h index a0b10d275..5127dbf14 100644 --- a/Audio/AudioPlayer.h +++ b/Audio/AudioPlayer.h @@ -96,6 +96,10 @@ - (void)notifyStreamChanged:(id)userInfo; - (void)notifyStreamChangedMainThread:(id)userInfo; +- (void)beginEqualizer:(AudioUnit)eq; +- (void)refreshEqualizer:(AudioUnit)eq; +- (void)endEqualizer:(AudioUnit)eq; + - (BOOL)endOfInputReached:(BufferChain *)sender; - (void)setShouldContinue:(BOOL)s; //- (BufferChain *)bufferChain; @@ -113,6 +117,7 @@ - (void)audioPlayer:(AudioPlayer *)player didBeginStream:(id)userInfo; - (void)audioPlayer:(AudioPlayer *)player didChangeStatus:(id)status userInfo:(id)userInfo; - (void)audioPlayer:(AudioPlayer *)player displayEqualizer:(AudioUnit)eq; +- (void)audioPlayer:(AudioPlayer *)player refreshEqualizer:(AudioUnit)eq; - (void)audioPlayer:(AudioPlayer *)player removeEqualizer:(AudioUnit)eq; @end diff --git a/Audio/AudioPlayer.m b/Audio/AudioPlayer.m index 5c9ec9a03..9d8a23967 100644 --- a/Audio/AudioPlayer.m +++ b/Audio/AudioPlayer.m @@ -269,6 +269,11 @@ [self sendDelegateMethod:@selector(audioPlayer:displayEqualizer:) withVoid:eq waitUntilDone:YES]; } +- (void)refreshEqualizer:(AudioUnit)eq +{ + [self sendDelegateMethod:@selector(audioPlayer:refreshEqualizer:) withVoid:eq waitUntilDone:YES]; +} + - (void)endEqualizer:(AudioUnit)eq { [self sendDelegateMethod:@selector(audioPlayer:removeEqualizer:) withVoid:eq waitUntilDone:YES]; diff --git a/Audio/Chain/OutputNode.h b/Audio/Chain/OutputNode.h index 240e58ced..b9a4da750 100644 --- a/Audio/Chain/OutputNode.h +++ b/Audio/Chain/OutputNode.h @@ -27,6 +27,7 @@ } - (void)beginEqualizer:(AudioUnit)eq; +- (void)refreshEqualizer:(AudioUnit)eq; - (void)endEqualizer:(AudioUnit)eq; - (double)amountPlayed; diff --git a/Audio/Chain/OutputNode.m b/Audio/Chain/OutputNode.m index b95725694..ee0d9cba5 100644 --- a/Audio/Chain/OutputNode.m +++ b/Audio/Chain/OutputNode.m @@ -162,6 +162,11 @@ [controller beginEqualizer:eq]; } +- (void)refreshEqualizer:(AudioUnit)eq +{ + [controller refreshEqualizer:eq]; +} + - (void)endEqualizer:(AudioUnit)eq { [controller endEqualizer:eq]; diff --git a/Audio/Output/OutputCoreAudio.m b/Audio/Output/OutputCoreAudio.m index 7c1b76e3c..e072148a4 100644 --- a/Audio/Output/OutputCoreAudio.m +++ b/Audio/Output/OutputCoreAudio.m @@ -154,6 +154,7 @@ static OSStatus renderCallback( void *inRefCon, AudioUnitRenderActionFlags *ioAc [[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.outputDevice" options:0 context:NULL]; [[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.GraphicEQenable" options:0 context:NULL]; + [[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.GraphicEQpreset" options:0 context:NULL]; } return self; @@ -179,6 +180,10 @@ default_device_changed(AudioObjectID inObjectID, UInt32 inNumberAddresses, const [self setEqualizerEnabled:enabled]; } + else if ([keyPath isEqualToString:@"values.GraphicEQpreset"]) { + if (_eq) + [outputController refreshEqualizer:_eq]; + } } - (void)signalEndOfStream @@ -726,6 +731,7 @@ default_device_changed(AudioObjectID inObjectID, UInt32 inNumberAddresses, const [[NSUserDefaultsController sharedUserDefaultsController] removeObserver:self forKeyPath:@"values.outputDevice"]; [[NSUserDefaultsController sharedUserDefaultsController] removeObserver:self forKeyPath:@"values.GraphicEQenable"]; + [[NSUserDefaultsController sharedUserDefaultsController] removeObserver:self forKeyPath:@"values.GraphicEQpreset"]; } - (void)pause diff --git a/Window/AUPlayerView.h b/Window/AUPlayerView.h index 2c711c3aa..8c7c18936 100644 --- a/Window/AUPlayerView.h +++ b/Window/AUPlayerView.h @@ -14,6 +14,10 @@ #import #import +void equalizerApplyGenre(NSString *genre); +void equalizerLoadPreset(AudioUnit au); +void equalizerApplyPreset(AudioUnit au, NSDictionary * preset); + @interface AUPluginUI : NSObject { AudioUnit au; diff --git a/Window/AUPlayerView.m b/Window/AUPlayerView.m index d55a769d4..ad3f79d83 100644 --- a/Window/AUPlayerView.m +++ b/Window/AUPlayerView.m @@ -14,7 +14,10 @@ #import "json.h" +static NSString * equalizerGenre = @""; +static const NSString * equalizerDefaultGenre = @"Flat"; static NSArray * equalizer_presets_processed = nil; +static NSDictionary * equalizer_presets_by_name = nil; static json_value * equalizer_presets = NULL; static const float winamp_equalizer_bands[10] = { 70, 180, 320, 600, 1000, 3000, 6000, 12000, 14000, 16000 }; @@ -145,6 +148,7 @@ static void loadPresets() { // Got the array of presets NSMutableArray * array = [[NSMutableArray alloc] init]; + NSMutableDictionary * dict = [[NSMutableDictionary alloc] init]; size_t count = equalizer_presets->u.object.values[1].value->u.array.length; json_value ** values = equalizer_presets->u.object.values[1].value->u.array.values; @@ -168,12 +172,15 @@ static void loadPresets() } } } - [array addObject:[NSDictionary dictionaryWithDictionary:equalizerItem]]; + NSDictionary *outItem = [NSDictionary dictionaryWithDictionary:equalizerItem]; + [array addObject:outItem]; + [dict setObject:outItem forKey:[outItem objectForKey:@"name"]]; } } } equalizer_presets_processed = [NSArray arrayWithArray:array]; + equalizer_presets_by_name = [NSDictionary dictionaryWithDictionary:dict]; } } [fileHandle closeFile]; @@ -185,6 +192,76 @@ static void loadPresets() CFRelease(appUrlRef); } +void equalizerApplyGenre(NSString *genre) { + equalizerGenre = genre; + if ([[[NSUserDefaultsController sharedUserDefaultsController] defaults] boolForKey:@"GraphicEQtrackgenre"]) { + NSDictionary * preset = [equalizer_presets_by_name objectForKey:genre]; + if (!preset) { + // Find a match + if (genre && ![genre isEqualToString:@""]) + { + NSUInteger matchLength = 0; + NSString *lowerCaseGenre = [genre lowercaseString]; + for (NSString *key in [equalizer_presets_by_name allKeys]) { + NSString *lowerCaseKey = [key lowercaseString]; + if ([lowerCaseGenre containsString:lowerCaseKey]) { + if ([key length] > matchLength) + { + matchLength = [key length]; + preset = [equalizer_presets_by_name objectForKey:key]; + } + } + } + } + + if (!preset) { + preset = [equalizer_presets_by_name objectForKey:equalizerDefaultGenre]; + } + } + if (preset) { + NSInteger index = [equalizer_presets_processed indexOfObject:preset]; + [[[NSUserDefaultsController sharedUserDefaultsController] defaults] setInteger:index forKey:@"GraphicEQpreset"]; + } + } +} + +void equalizerLoadPreset(AudioUnit au) { + NSInteger index = [[[NSUserDefaultsController sharedUserDefaultsController] defaults] integerForKey:@"GraphicEQpreset"]; + if (index >= 0 && index < [equalizer_presets_processed count]) { + NSDictionary * preset = [equalizer_presets_processed objectAtIndex:index]; + equalizerApplyPreset(au, preset); + } +} + +void equalizerApplyPreset(AudioUnit au, NSDictionary * preset) { + if (au && preset) { + AudioUnitParameterValue paramValue = 0; + if (AudioUnitGetParameter(au, kGraphicEQParam_NumberOfBands, kAudioUnitScope_Global, 0, ¶mValue)) + return; + + size_t numberOfBands = paramValue ? 31 : 10; + + if (numberOfBands == 31) { + float presetValues[31]; + interpolateBandsTo31(presetValues, preset); + + for (unsigned int i = 0; i < 31; ++i) + { + AudioUnitSetParameter(au, i, kAudioUnitScope_Global, 0, presetValues[i], 0); + } + } + else if (numberOfBands == 10) { + float presetValues[10]; + interpolateBandsTo10(presetValues, preset); + + for (unsigned int i = 0; i < 10; ++i) + { + AudioUnitSetParameter(au, i, kAudioUnitScope_Global, 0, presetValues[i], 0); + } + } + } +} + @interface AUPluginUI (Private) - (BOOL)test_cocoa_view_support; - (int)create_cocoa_view; @@ -389,21 +466,14 @@ static void loadPresets() [self setAutodisplay:YES]; [self setOneShot:YES]; - if (front) - { - [self orderFront:self]; - } - else - [self orderWindow:NSWindowBelow relativeTo:window]; - [self setReleasedWhenClosed:NO]; - NSRect topRect = NSMakeRect(0, 0, req_width, 32); + NSRect topRect = NSMakeRect(0, 0, req_width, 40); topView = [[NSView alloc] initWithFrame:topRect]; - NSRect topFrame = NSMakeRect(0, req_height, req_width, req_height); - NSRect newFrame = NSMakeRect(0, 0, req_width, topRect.size.height); + NSRect topFrame = NSMakeRect(0, req_height, req_width, topRect.size.height); + NSRect newFrame = NSMakeRect(0, 0, req_width, req_height); topRect = NSMakeRect(0, 0, req_width, req_height + topRect.size.height); @@ -416,16 +486,26 @@ static void loadPresets() [topView setFrame:topFrame]; [auView setFrame:newFrame]; - BOOL enabled = [[NSUserDefaults standardUserDefaults] boolForKey:@"GraphicEQenable"]; + BOOL enabled = [[[NSUserDefaultsController sharedUserDefaultsController] defaults] boolForKey:@"GraphicEQenable"]; NSButton *button = [NSButton checkboxWithTitle:@"Enabled" target:self action:@selector(toggleEnable:)]; [button setState:enabled ? NSControlStateValueOn : NSControlStateValueOff]; NSRect buttonFrame = [button frame]; - buttonFrame.origin = NSMakePoint( 18, 4 ); + buttonFrame.origin = NSMakePoint( 18, 7 ); [button setFrame:buttonFrame]; [topView addSubview:button]; + + enabled = [[[NSUserDefaultsController sharedUserDefaultsController] defaults] boolForKey:@"GraphicEQtrackgenre"]; + NSButton *trackButton = [NSButton checkboxWithTitle:@"Tracking genre tags" target:self action:@selector(toggleTracking:)]; + [trackButton setState:enabled ? NSControlStateValueOn : NSControlStateValueOff]; + + NSRect trackButtonFrame = [trackButton frame]; + trackButtonFrame.origin = NSMakePoint(buttonFrame.origin.x + buttonFrame.size.width + 4, 7); + [trackButton setFrame:trackButtonFrame]; + + [topView addSubview:trackButton]; loadPresets(); @@ -444,16 +524,17 @@ static void loadPresets() [array addObject:@"Custom"]; [presetButton addItemsWithTitles:array]; - NSInteger presetSelected = [[NSUserDefaults standardUserDefaults] integerForKey:@"GraphicEQpreset"]; + NSInteger presetSelected = [[[NSUserDefaultsController sharedUserDefaultsController] defaults] integerForKey:@"GraphicEQpreset"]; if (presetSelected < 0 || presetSelected >= [equalizer_presets_processed count]) presetSelected = [equalizer_presets_processed count]; [presetButton selectItemAtIndex:presetSelected]; + equalizerLoadPreset(au); NSTextField * presetLabel = [NSTextField labelWithString:@"Preset:"]; NSRect labelFrame = [presetLabel frame]; - labelFrame.origin = NSMakePoint(popupFrame.origin.x - labelFrame.size.width - 2, 6); + labelFrame.origin = NSMakePoint(popupFrame.origin.x - labelFrame.size.width - 2, 7); [presetLabel setFrame:labelFrame]; [topView addSubview:presetLabel]; @@ -481,6 +562,15 @@ static void loadPresets() param.mParameterID = i; AUListenerAddParameter(listenerRef, (__bridge void *)self, ¶m); } + + [[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.GraphicEQpreset" options:0 context:nil]; + + if (front) + { + [self orderFront:self]; + } + else + [self orderWindow:NSWindowBelow relativeTo:window]; } return self; @@ -491,6 +581,19 @@ static void loadPresets() if (listenerRef) { AUListenerDispose(listenerRef); } + [[NSUserDefaultsController sharedUserDefaultsController] removeObserver:self forKeyPath:@"values.GraphicEQpreset"]; +} + +- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context +{ + if ([keyPath isEqualToString:@"values.GraphicEQpreset"]) { + NSInteger index = [[[NSUserDefaultsController sharedUserDefaultsController] defaults] integerForKey:@"GraphicEQpreset"]; + + if (index < 0 || index > [equalizer_presets_processed count]) + index = [equalizer_presets_processed count]; + + [presetButton selectItemAtIndex:index]; + } } - (NSRect)splitView:(NSSplitView *)splitView effectiveRect:(NSRect)proposedEffectiveRect forDrawnRect:(NSRect)drawnRect ofDividerAtIndex:(NSInteger)dividerIndex @@ -502,51 +605,41 @@ static void loadPresets() { BOOL enabled = [sender state] == NSControlStateValueOn; - [[NSUserDefaults standardUserDefaults] setBool:enabled forKey:@"GraphicEQenable"]; + [[[NSUserDefaultsController sharedUserDefaultsController] defaults] setBool:enabled forKey:@"GraphicEQenable"]; +} + +- (void) toggleTracking:(id)sender +{ + BOOL enabled = [sender state] == NSControlStateValueOn; + + [[[NSUserDefaultsController sharedUserDefaultsController] defaults] setBool:enabled forKey:@"GraphicEQtrackgenre"]; + + equalizerApplyGenre(equalizerGenre); + + [self changePreset:presetButton]; } - (void) changePreset:(id)sender { - AudioUnitParameterValue paramValue = 0; - if (AudioUnitGetParameter(au, kGraphicEQParam_NumberOfBands, kAudioUnitScope_Global, 0, ¶mValue)) - return; - NSInteger index = [sender indexOfSelectedItem]; - size_t numberOfBands = paramValue ? 31 : 10; - if (index < [equalizer_presets_processed count]) { NSDictionary * preset = [equalizer_presets_processed objectAtIndex:index]; - - if (numberOfBands == 31) { - float presetValues[31]; - interpolateBandsTo31(presetValues, preset); - - for (unsigned int i = 0; i < 31; ++i) - { - AudioUnitSetParameter(au, i, kAudioUnitScope_Global, 0, presetValues[i], 0); - } - } - else if (numberOfBands == 10) { - float presetValues[10]; - interpolateBandsTo10(presetValues, preset); - - for (unsigned int i = 0; i < 10; ++i) - { - AudioUnitSetParameter(au, i, kAudioUnitScope_Global, 0, presetValues[i], 0); - } - } - NSEvent * event = [NSEvent mouseEventWithType:NSEventTypeLeftMouseDown - location:NSMakePoint(0, 0) modifierFlags:0 timestamp:0 windowNumber:[self windowNumber] context:nil eventNumber:0 clickCount:1 pressure:1.0]; + equalizerApplyPreset(au, preset); - [auView mouseDown:event]; + NSEvent * event = [NSEvent mouseEventWithType:NSEventTypeLeftMouseDown location:NSMakePoint(0, 0) modifierFlags:0 timestamp:0 windowNumber:[self windowNumber] context:nil eventNumber:0 clickCount:1 pressure:1.0]; - [[NSUserDefaults standardUserDefaults] setInteger:index forKey:@"GraphicEQpreset"]; + [auView mouseDown:event]; + [auView mouseUp:event]; + + [[[NSUserDefaultsController sharedUserDefaultsController] defaults] setInteger:index forKey:@"GraphicEQpreset"]; } else - [[NSUserDefaults standardUserDefaults] setInteger:-1 forKey:@"GraphicEQpreset"]; + { + [[[NSUserDefaultsController sharedUserDefaultsController] defaults] setInteger:-1 forKey:@"GraphicEQpreset"]; + } } @end