X-Git-Url: http://git.ithinksw.org/MenuTunes.git/blobdiff_plain/3a1a21d1ea3e060f88ca1d24ea881f3ccb97640c..6d099bbe927a1dc3934c7b6254223961fc849453:/PreferencesController.m?ds=sidebyside diff --git a/PreferencesController.m b/PreferencesController.m index 590e6de..726f1e8 100755 --- a/PreferencesController.m +++ b/PreferencesController.m @@ -1,14 +1,27 @@ #import "PreferencesController.h" #import "MainController.h" +#import "NetworkController.h" +#import "NetworkObject.h" #import "StatusWindow.h" #import "StatusWindowController.h" #import "CustomMenuTableView.h" +#import +#import +#import +#import +#import + +#import + #import #import +#import #import #import +#import +#import #import #import #import @@ -28,6 +41,11 @@ - (void)setupCustomizationTables; - (void)setupMenuItems; - (void)setupUI; +- (void)setStatusWindowEntryEffect:(Class)effectClass; +- (void)setStatusWindowExitEffect:(Class)effectClass; +- (void)setCustomColor:(NSColor *)color updateWell:(BOOL)update; +- (void)repopulateEffectPopupsForVerticalPosition:(ITVerticalWindowPosition)vPos horizontalPosition:(ITHorizontalWindowPosition)hPos; +- (BOOL)effect:(Class)effectClass supportsVerticalPosition:(ITVerticalWindowPosition)vPos withHorizontalPosition:(ITHorizontalWindowPosition)hPos; - (IBAction)changeMenus:(id)sender; - (void)setLaunchesAtLogin:(BOOL)flag; @end @@ -62,8 +80,41 @@ static PreferencesController *prefs = nil; if ( (self = [super init]) ) { ITDebugLog(@"Preferences initialized."); df = [[NSUserDefaults standardUserDefaults] retain]; + + effectClasses = [[ITWindowEffect effectClasses] retain]; + + hotKeysArray = [[NSArray alloc] initWithObjects:@"PlayPause", + @"NextTrack", + @"PrevTrack", + @"ShowPlayer", + @"TrackInfo", + @"UpcomingSongs", + @"IncrementVolume", + @"DecrementVolume", + @"IncrementRating", + @"DecrementRating", + @"ToggleShuffle", + @"ToggleLoop", + nil]; + + hotKeyNamesArray = [[NSArray alloc] initWithObjects:@"Play/Pause", + @"Next Track", + @"Previous Track", + @"Show Player", + @"Track Info", + @"Upcoming Songs", + @"Increment Volume", + @"Decrement Volume", + @"Increment Rating", + @"Decrement Rating", + @"Toggle Shuffle", + @"Toggle Loop", + nil]; hotKeysDictionary = [[NSMutableDictionary alloc] init]; controller = nil; + + [self setupWindow]; // Load in the nib, and perform any initial setup. + [[NSColorPanel sharedColorPanel] setShowsAlpha:YES]; } return self; } @@ -91,25 +142,73 @@ static PreferencesController *prefs = nil; #pragma mark INSTANCE METHODS /*************************************************************************/ +- (BOOL)showPasswordPanel +{ + [passwordPanel setLevel:NSStatusWindowLevel]; + [passwordPanelOKButton setTitle:@"Connect"]; + [passwordPanelTitle setStringValue:@"Password Required"]; + [passwordPanelMessage setStringValue:[NSString stringWithFormat:@"Please enter a password for access to the MenuTunes player named %@ at %@.", [[[NetworkController sharedController] networkObject] serverName], [[NetworkController sharedController] remoteHost]]]; + [passwordPanel setLevel:NSStatusWindowLevel]; + [NSApp activateIgnoringOtherApps:YES]; + [passwordPanel center]; + [passwordPanel orderFrontRegardless]; + [passwordPanel makeKeyWindow]; + if ([NSApp runModalForWindow:passwordPanel]) { + return YES; + } else { + return NO; + } +} + +- (BOOL)showInvalidPasswordPanel +{ + [passwordPanel setLevel:NSStatusWindowLevel]; + [passwordPanelOKButton setTitle:@"Retry"]; + [passwordPanelTitle setStringValue:@"Invalid Password"]; + [passwordPanelMessage setStringValue:[NSString stringWithFormat:@"The password entered for access to the MenuTunes player named %@ at %@ is invalid. Please provide a new password.", [[[NetworkController sharedController] networkObject] serverName], [[NetworkController sharedController] remoteHost]]]; + [passwordPanel setLevel:NSStatusWindowLevel]; + [NSApp activateIgnoringOtherApps:YES]; + [passwordPanel center]; + [passwordPanel orderFrontRegardless]; + [passwordPanel makeKeyWindow]; + if ([NSApp runModalForWindow:passwordPanel]) { + return YES; + } else { + return NO; + } +} + - (IBAction)showPrefsWindow:(id)sender { ITDebugLog(@"Showing preferences window."); - if (! window) { // If window does not exist yet, then the nib hasn't been loaded. + if (!myItems) { // If menu array does not exist yet, then the window hasn't been setup. ITDebugLog(@"Window doesn't exist, initial setup."); - [self setupWindow]; // Load in the nib, and perform any initial setup. [self setupCustomizationTables]; // Setup the DnD manu config tables. [self setupMenuItems]; // Setup the arrays of menu items [self setupUI]; // Sets up additional UI [window setDelegate:self]; [menuTableView reloadData]; + [hotKeysTableView setDoubleAction:@selector(hotKeysTableViewDoubleClicked:)]; //Change the launch player checkbox to the proper name - [launchPlayerAtLaunchCheckbox setTitle:[NSString stringWithFormat:@"Launch %@ when MenuTunes launches", [[controller currentRemote] playerSimpleName]]]; //This isn't localized... + NS_DURING + [launchPlayerAtLaunchCheckbox setTitle:[NSString stringWithFormat:@"Launch %@ when MenuTunes launches", [[controller currentRemote] playerSimpleName]]]; //This isn't localized... + NS_HANDLER + [controller networkError:localException]; + NS_ENDHANDLER } - [window center]; + [self resetRemotePlayerTextFields]; + [launchAtLoginCheckbox becomeFirstResponder]; [NSApp activateIgnoringOtherApps:YES]; - [window performSelector:@selector(makeKeyAndOrderFront:) withObject:self afterDelay:0.0]; + [window center]; + [window orderFrontRegardless]; + [window makeKeyWindow]; +} + +- (IBAction)showTestWindow:(id)sender +{ + [controller showTestWindow]; } - (IBAction)changeGeneralSetting:(id)sender @@ -135,6 +234,166 @@ static PreferencesController *prefs = nil; [df setBool:SENDER_STATE forKey:@"showTrackNumber"]; } else if ( [sender tag] == 1090) { [df setBool:SENDER_STATE forKey:@"showTrackRating"]; + } else if ( [sender tag] == 1100) { + [df setBool:SENDER_STATE forKey:@"showAlbumArtwork"]; + } else if ( [sender tag] == 1110) { + [df setBool:SENDER_STATE forKey:@"runScripts"]; + if (SENDER_STATE) { + [runScriptsCheckbox setState:NSOnState]; + [showScriptsButton setEnabled:YES]; + } else { + [showScriptsButton setEnabled:NO]; + } + } else if ( [sender tag] == 1120) { + mkdir([[NSHomeDirectory() stringByAppendingPathComponent:@"Library/Application Support/MenuTunes/Scripts"] cString], 0744); + [[NSWorkspace sharedWorkspace] openFile:[NSHomeDirectory() stringByAppendingPathComponent:@"Library/Application Support/MenuTunes/Scripts"]]; + } + [df synchronize]; +} + +- (IBAction)changeSharingSetting:(id)sender +{ + ITDebugLog(@"Changing sharing setting of tag %i.", [sender tag]); + if ( [sender tag] == 5010 ) { + BOOL state = SENDER_STATE; + [df setBool:state forKey:@"enableSharing"]; + //Disable/enable the use of shared player options + [useSharedMenuTunesCheckbox setEnabled:!state]; + [passwordTextField setEnabled:state]; + [nameTextField setEnabled:state]; + [selectSharedPlayerButton setEnabled:NO]; + [controller setServerStatus:state]; //Set server status + } else if ( [sender tag] == 5015 ) { + [df setObject:[sender stringValue] forKey:@"sharedPlayerName"]; + [[NetworkController sharedController] resetServerName]; + } else if ( [sender tag] == 5030 ) { + //Set the server password + const char *instring = [[sender stringValue] UTF8String]; + const char *password = "p4s5w0rdMT1.2"; + unsigned char *result; + NSData *hashedPass, *passwordStringHash; + if ([[sender stringValue] length] == 0) { + [df setObject:[NSData data] forKey:@"sharedPlayerPassword"]; + return; + } + result = SHA1(instring, strlen(instring), NULL); + hashedPass = [NSData dataWithBytes:result length:strlen(result)]; + result = SHA1(password, strlen(password), NULL); + passwordStringHash = [NSData dataWithBytes:result length:strlen(result)]; + if (![hashedPass isEqualToData:passwordStringHash]) { + [df setObject:hashedPass forKey:@"sharedPlayerPassword"]; + [sender setStringValue:@"p4s5w0rdMT1.2"]; + } + } else if ( [sender tag] == 5040 ) { + BOOL state = SENDER_STATE; + [df setBool:state forKey:@"useSharedPlayer"]; + //Disable/enable the use of sharing options + [shareMenuTunesCheckbox setEnabled:!state]; + [passwordTextField setEnabled:NO]; + [nameTextField setEnabled:NO]; + [selectSharedPlayerButton setEnabled:state]; + + if (state && ([controller connectToServer] == 1)) { + [selectedPlayerTextField setStringValue:[[[NetworkController sharedController] networkObject] serverName]]; + [locationTextField setStringValue:[[NetworkController sharedController] remoteHost]]; + } else { + [selectedPlayerTextField setStringValue:@"No shared player selected."]; + [locationTextField setStringValue:@"-"]; + if ([[NetworkController sharedController] isConnectedToServer]) { + [controller disconnectFromServer]; + } + + } + } else if ( [sender tag] == 5050 ) { + //If no player is selected in the table view, turn off OK button. + if ([sender clickedRow] == -1 ) { + [sharingPanelOKButton setEnabled:NO]; + } else { + [sharingPanelOKButton setEnabled:YES]; + } + } else if ( [sender tag] == 5051 ) { + [df setObject:[sender stringValue] forKey:@"sharedPlayerHost"]; + } else if ( [sender tag] == 5060 ) { + //Set OK button state + if (([selectPlayerBox contentView] == zeroConfView && [sharingTableView selectedRow] == -1) || + ([selectPlayerBox contentView] == manualView && [[hostTextField stringValue] length] == 0)) { + [sharingPanelOKButton setEnabled:NO]; + } else { + [sharingPanelOKButton setEnabled:YES]; + } + //Show selection sheet + [NSApp beginSheet:selectPlayerSheet modalForWindow:window modalDelegate:self didEndSelector:NULL contextInfo:nil]; + } else if ( [sender tag] == 5100 ) { + //Change view + if ( ([sender indexOfItem:[sender selectedItem]] == 0) && ([selectPlayerBox contentView] != zeroConfView) ) { + NSRect frame = [selectPlayerSheet frame]; + frame.origin.y -= 58; + frame.size.height = 273; + if ([sharingTableView selectedRow] == -1) { + [sharingPanelOKButton setEnabled:NO]; + } + [selectPlayerBox setContentView:zeroConfView]; + [selectPlayerSheet setFrame:frame display:YES animate:YES]; + } else if ( ([sender indexOfItem:[sender selectedItem]] == 1) && ([selectPlayerBox contentView] != manualView) ){ + NSRect frame = [selectPlayerSheet frame]; + frame.origin.y += 58; + frame.size.height = 215; + if ([[hostTextField stringValue] length] == 0) { + [sharingPanelOKButton setEnabled:NO]; + } else { + [sharingPanelOKButton setEnabled:YES]; + } + [selectPlayerBox setContentView:manualView]; + [selectPlayerSheet setFrame:frame display:YES animate:YES]; + [hostTextField selectText:nil]; + } + } else if ( [sender tag] == 5150 ) { + const char *instring = [[sender stringValue] UTF8String]; + unsigned char *result; + result = SHA1(instring, strlen(instring), NULL); + [df setObject:[NSData dataWithBytes:result length:strlen(result)] forKey:@"connectPassword"]; + } else if ( [sender tag] == 5110 ) { + //Cancel + [NSApp endSheet:selectPlayerSheet]; + [selectPlayerSheet orderOut:nil]; + if ([selectPlayerBox contentView] == manualView) { + [hostTextField setStringValue:[df stringForKey:@"sharedPlayerHost"]]; + } else { + } + } else if ( [sender tag] == 5120 ) { + //OK, try to connect + [NSApp endSheet:selectPlayerSheet]; + [selectPlayerSheet orderOut:nil]; + + [self changeSharingSetting:clientPasswordTextField]; + + if ([selectPlayerBox contentView] == manualView) { + [df setObject:[hostTextField stringValue] forKey:@"sharedPlayerHost"]; + } else { + if ([sharingTableView selectedRow] > -1) { + [df setObject:[NSString stringWithCString:inet_ntoa((*(struct sockaddr_in*)[[[[[[NetworkController sharedController] remoteServices] objectAtIndex:[sharingTableView selectedRow]] addresses] objectAtIndex:0] bytes]).sin_addr)] forKey:@"sharedPlayerHost"]; + } + } + + if ([controller connectToServer] == 1) { + [useSharedMenuTunesCheckbox setState:NSOnState]; + [selectedPlayerTextField setStringValue:[[[NetworkController sharedController] networkObject] serverName]]; + [locationTextField setStringValue:[[NetworkController sharedController] remoteHost]]; + } else { + NSRunAlertPanel(@"Connection error.", @"The MenuTunes server you attempted to connect to was not responding. MenuTunes will revert back to the local player.", @"OK", nil, nil); + } + } else if ( [sender tag] == 6010 ) { + //Cancel password entry + [passwordPanel orderOut:nil]; + [NSApp stopModalWithCode:0]; + } else if ( [sender tag] == 6020 ) { + //OK password entry, retry connect + const char *instring = [[passwordPanelTextField stringValue] UTF8String]; + unsigned char *result; + result = SHA1(instring, strlen(instring), NULL); + [df setObject:[NSData dataWithBytes:result length:strlen(result)] forKey:@"connectPassword"]; + [passwordPanel orderOut:nil]; + [NSApp stopModalWithCode:1]; } [df synchronize]; } @@ -143,58 +402,63 @@ static PreferencesController *prefs = nil; { StatusWindow *sw = [StatusWindow sharedWindow]; ITDebugLog(@"Changing status window setting of tag %i", [sender tag]); + if ( [sender tag] == 2010) { + + BOOL entryEffectValid = YES; + BOOL exitEffectValid = YES; + [df setInteger:[sender selectedRow] forKey:@"statusWindowVerticalPosition"]; [df setInteger:[sender selectedColumn] forKey:@"statusWindowHorizontalPosition"]; - // update the window's position here + [sw setVerticalPosition:[sender selectedRow]]; + [sw setHorizontalPosition:[sender selectedColumn]]; + + // Enable/disable the items in the popups. + [self repopulateEffectPopupsForVerticalPosition:[sw verticalPosition] + horizontalPosition:[sw horizontalPosition]]; + + // Make sure the effects support the new position. + entryEffectValid = ( [self effect:[[sw entryEffect] class] + supportsVerticalPosition:[sw verticalPosition] + withHorizontalPosition:[sw horizontalPosition]] ); + exitEffectValid = ( [self effect:[[sw exitEffect] class] + supportsVerticalPosition:[sw verticalPosition] + withHorizontalPosition:[sw horizontalPosition]] ); + + if ( ! entryEffectValid ) { + [appearanceEffectPopup selectItemAtIndex:[[appearanceEffectPopup menu] indexOfItemWithRepresentedObject:NSClassFromString(@"ITCutWindowEffect")]]; + [self setStatusWindowEntryEffect:NSClassFromString(@"ITCutWindowEffect")]; + } else { + [appearanceEffectPopup selectItemAtIndex:[[appearanceEffectPopup menu] indexOfItemWithRepresentedObject:[[sw entryEffect] class]]]; + } + + if ( ! exitEffectValid ) { + [vanishEffectPopup selectItemAtIndex:[[vanishEffectPopup menu] indexOfItemWithRepresentedObject:NSClassFromString(@"ITDissolveWindowEffect")]]; + [self setStatusWindowExitEffect:NSClassFromString(@"ITDissolveWindowEffect")]; + } else { + [vanishEffectPopup selectItemAtIndex:[[vanishEffectPopup menu] indexOfItemWithRepresentedObject:[[sw exitEffect] class]]]; + } + + [(MainController *)controller showCurrentTrackInfo]; + } else if ( [sender tag] == 2020) { - // update screen selection + + // Update screen selection. + } else if ( [sender tag] == 2030) { - int effectTag = [[sender selectedItem] tag]; - float time = ([df floatForKey:@"statusWindowAppearanceSpeed"] ? [df floatForKey:@"statusWindowAppearanceSpeed"] : 0.8); - [df setInteger:effectTag forKey:@"statusWindowAppearanceEffect"]; - - if ( effectTag == 2100 ) { - [sw setEntryEffect:[[[ITCutWindowEffect alloc] initWithWindow:sw] autorelease]]; - } else if ( effectTag == 2101 ) { - [sw setEntryEffect:[[[ITDissolveWindowEffect alloc] initWithWindow:sw] autorelease]]; - } else if ( effectTag == 2102 ) { - [sw setEntryEffect:[[[ITSlideVerticallyWindowEffect alloc] initWithWindow:sw] autorelease]]; - } else if ( effectTag == 2103 ) { - [sw setEntryEffect:[[[ITSlideHorizontallyWindowEffect alloc] initWithWindow:sw] autorelease]]; - } else if ( effectTag == 2104 ) { - NSLog(@"dflhgldf"); - [sw setEntryEffect:[[[ITPivotWindowEffect alloc] initWithWindow:sw] autorelease]]; - } - - [[sw entryEffect] setEffectTime:time]; + + [self setStatusWindowEntryEffect:[[sender selectedItem] representedObject]]; } else if ( [sender tag] == 2040) { - int effectTag = [[sender selectedItem] tag]; - float time = ([df floatForKey:@"statusWindowVanishSpeed"] ? [df floatForKey:@"statusWindowVanishSpeed"] : 0.8); - - [df setInteger:[[sender selectedItem] tag] forKey:@"statusWindowVanishEffect"]; + + [self setStatusWindowExitEffect:[[sender selectedItem] representedObject]]; - if ( effectTag == 2100 ) { - [sw setExitEffect:[[[ITCutWindowEffect alloc] initWithWindow:sw] autorelease]]; - } else if ( effectTag == 2101 ) { - [sw setExitEffect:[[[ITDissolveWindowEffect alloc] initWithWindow:sw] autorelease]]; - } else if ( effectTag == 2102 ) { - [sw setExitEffect:[[[ITSlideVerticallyWindowEffect alloc] initWithWindow:sw] autorelease]]; - } else if ( effectTag == 2103 ) { - [sw setExitEffect:[[[ITSlideHorizontallyWindowEffect alloc] initWithWindow:sw] autorelease]]; - } else if ( effectTag == 2104 ) { - [sw setExitEffect:[[[ITPivotWindowEffect alloc] initWithWindow:sw] autorelease]]; - } - - [[sw exitEffect] setEffectTime:time]; - } else if ( [sender tag] == 2050) { - float newTime = (-([sender floatValue])); + float newTime = ( -([sender floatValue]) ); [df setFloat:newTime forKey:@"statusWindowAppearanceSpeed"]; [[sw entryEffect] setEffectTime:newTime]; } else if ( [sender tag] == 2060) { - float newTime = (-([sender floatValue])); + float newTime = ( -([sender floatValue]) ); [df setFloat:newTime forKey:@"statusWindowVanishSpeed"]; [[sw exitEffect] setEffectTime:newTime]; } else if ( [sender tag] == 2070) { @@ -202,65 +466,52 @@ static PreferencesController *prefs = nil; [sw setExitDelay:[sender floatValue]]; } else if ( [sender tag] == 2080) { [df setBool:SENDER_STATE forKey:@"showSongInfoOnChange"]; - } - [df synchronize]; -} + } else if ( [sender tag] == 2090) { + + int setting = [sender indexOfSelectedItem]; + + if ( setting == 0 ) { + [(ITTSWBackgroundView *)[sw contentView] setBackgroundMode:ITTSWBackgroundApple]; + [backgroundColorWell setEnabled:NO]; + [backgroundColorPopup setEnabled:NO]; + } else if ( setting == 1 ) { + [(ITTSWBackgroundView *)[sw contentView] setBackgroundMode:ITTSWBackgroundReadable]; + [backgroundColorWell setEnabled:NO]; + [backgroundColorPopup setEnabled:NO]; + } else if ( setting == 2 ) { + [(ITTSWBackgroundView *)[sw contentView] setBackgroundMode:ITTSWBackgroundColored]; + [backgroundColorWell setEnabled:YES]; + [backgroundColorPopup setEnabled:YES]; + } -- (IBAction)changeHotKey:(id)sender -{ - ITDebugLog(@"Changing hot keys."); - [controller clearHotKeys]; - switch ([sender tag]) - { - case 4010: - [self setKeyCombo:[hotKeysDictionary objectForKey:@"PlayPause"]]; - [self setCurrentHotKey:@"PlayPause"]; - break; - case 4020: - [self setKeyCombo:[hotKeysDictionary objectForKey:@"NextTrack"]]; - [self setCurrentHotKey:@"NextTrack"]; - break; - case 4030: - [self setKeyCombo:[hotKeysDictionary objectForKey:@"PrevTrack"]]; - [self setCurrentHotKey:@"PrevTrack"]; - break; - case 4035: - [self setKeyCombo:[hotKeysDictionary objectForKey:@"ShowPlayer"]]; - [self setCurrentHotKey:@"ShowPlayer"]; - break; - case 4040: - [self setKeyCombo:[hotKeysDictionary objectForKey:@"ToggleLoop"]]; - [self setCurrentHotKey:@"ToggleLoop"]; - break; - case 4050: - [self setKeyCombo:[hotKeysDictionary objectForKey:@"ToggleShuffle"]]; - [self setCurrentHotKey:@"ToggleShuffle"]; - break; - case 4060: - [self setKeyCombo:[hotKeysDictionary objectForKey:@"TrackInfo"]]; - [self setCurrentHotKey:@"TrackInfo"]; - break; - case 4070: - [self setKeyCombo:[hotKeysDictionary objectForKey:@"UpcomingSongs"]]; - [self setCurrentHotKey:@"UpcomingSongs"]; - break; - case 4080: - [self setKeyCombo:[hotKeysDictionary objectForKey:@"IncrementVolume"]]; - [self setCurrentHotKey:@"IncrementVolume"]; - break; - case 4090: - [self setKeyCombo:[hotKeysDictionary objectForKey:@"DecrementVolume"]]; - [self setCurrentHotKey:@"DecrementVolume"]; - break; - case 4100: - [self setKeyCombo:[hotKeysDictionary objectForKey:@"IncrementRating"]]; - [self setCurrentHotKey:@"IncrementRating"]; - break; - case 4110: - [self setKeyCombo:[hotKeysDictionary objectForKey:@"DecrementRating"]]; - [self setCurrentHotKey:@"DecrementRating"]; - break; + [df setInteger:setting forKey:@"statusWindowBackgroundMode"]; + + } else if ( [sender tag] == 2091) { + [self setCustomColor:[sender color] updateWell:NO]; + } else if ( [sender tag] == 2092) { + + int selectedItem = [sender indexOfSelectedItem]; + + if ( selectedItem == 1 ) { // An NSPopUpButton in PullDown mode uses item 0 as its title. Its first selectable item is 1. + [self setCustomColor:[NSColor colorWithCalibratedRed:0.92549 green:0.686275 blue:0.0 alpha:1.0] updateWell:YES]; + } else if ( selectedItem == 2 ) { + [self setCustomColor:[NSColor colorWithCalibratedRed:0.380392 green:0.670588 blue:0.0 alpha:1.0] updateWell:YES]; + } else if ( selectedItem == 3 ) { + [self setCustomColor:[NSColor colorWithCalibratedRed:0.443137 green:0.231373 blue:0.619608 alpha:1.0] updateWell:YES]; + } else if ( selectedItem == 4 ) { + [self setCustomColor:[NSColor colorWithCalibratedRed:0.831373 green:0.12549 blue:0.509804 alpha:1.0] updateWell:YES]; + } else if ( selectedItem == 5 ) { + [self setCustomColor:[NSColor colorWithCalibratedRed:0.00784314 green:0.611765 blue:0.662745 alpha:1.0] updateWell:YES]; + } else { + [self setCustomColor:[NSColor colorWithCalibratedWhite:0.15 alpha:0.70] updateWell:YES]; + } + + } else if ( [sender tag] == 2095) { + [df setInteger:[sender indexOfSelectedItem] forKey:@"statusWindowSizing"]; + [(MainController *)controller showCurrentTrackInfo]; } + + [df synchronize]; } - (void)registerDefaults @@ -272,30 +523,40 @@ static PreferencesController *prefs = nil; id anItem; ITDebugLog(@"Registering defaults."); [df setObject:[NSArray arrayWithObjects: + @"trackInfo", + @"separator", @"playPause", @"prevTrack", @"nextTrack", - @"fastForward", - @"rewind", - @"showPlayer", @"separator", - @"songRating", - @"eqPresets", @"playlists", @"upcomingSongs", @"separator", @"preferences", @"quit", - @"separator", - @"trackInfo", nil] forKey:@"menu"]; + [df setInteger:1200 forKey:@"appVersion"]; [df setInteger:5 forKey:@"SongsInAdvance"]; - // [df setBool:YES forKey:@"showName"]; // Song info will always show song title. +// [df setBool:YES forKey:@"showName"]; // Song info will always show song title. [df setBool:YES forKey:@"showArtist"]; + [df setBool:YES forKey:@"showAlbumArtwork"]; [df setBool:NO forKey:@"showAlbum"]; [df setBool:NO forKey:@"showTime"]; + [df setObject:@"ITCutWindowEffect" forKey:@"statusWindowAppearanceEffect"]; + [df setObject:@"ITDissolveWindowEffect" forKey:@"statusWindowVanishEffect"]; + [df setFloat:0.8 forKey:@"statusWindowAppearanceSpeed"]; + [df setFloat:0.8 forKey:@"statusWindowVanishSpeed"]; + [df setFloat:4.0 forKey:@"statusWindowVanishDelay"]; + [df setInteger:(int)ITWindowPositionBottom forKey:@"statusWindowVerticalPosition"]; + [df setInteger:(int)ITWindowPositionLeft forKey:@"statusWindowHorizontalPosition"]; + [[StatusWindow sharedWindow] setVerticalPosition:(int)ITWindowPositionBottom]; + [[StatusWindow sharedWindow] setHorizontalPosition:(int)ITWindowPositionLeft]; + [df setBool:YES forKey:@"showSongInfoOnChange"]; + + [df setObject:[NSArchiver archivedDataWithRootObject:[NSColor blueColor]] forKey:@"statusWindowBackgroundColor"]; + [df synchronize]; loginWindow = [[df persistentDomainForName:@"loginwindow"] mutableCopy]; @@ -330,111 +591,6 @@ static PreferencesController *prefs = nil; [[StatusWindow sharedWindow] setIgnoresMouseEvents:YES]; } -- (IBAction)cancelHotKey:(id)sender -{ - ITDebugLog(@"Hot key canceled."); - [[NSNotificationCenter defaultCenter] removeObserver:self]; - [NSApp endSheet:keyComboPanel]; - [keyComboPanel orderOut:nil]; -} - -- (IBAction)clearHotKey:(id)sender -{ - ITDebugLog(@"Hot key cleared."); - [self setKeyCombo:[ITKeyCombo clearKeyCombo]]; -} - -- (IBAction)okHotKey:(id)sender -{ - NSString *string = [combo description]; - NSEnumerator *enumerator = [hotKeysDictionary keyEnumerator]; - NSString *enumKey; - - ITDebugLog(@"Hot key ok'd, saving."); - - if (string == nil) { - string = @""; - } - - ITDebugLog(@"Checking for duplicate hot keys."); - while ( (enumKey = [enumerator nextObject]) ) { - if (![enumKey isEqualToString:currentHotKey]) { - if (![combo isEqual:[ITKeyCombo clearKeyCombo]] && - [combo isEqual:[hotKeysDictionary objectForKey:enumKey]]) { - [window setLevel:NSNormalWindowLevel]; - ITDebugLog(@"Duplicate hot key found: %@", enumKey); - if ( NSRunAlertPanel(NSLocalizedString(@"duplicateCombo", @"Duplicate Key Combo") , NSLocalizedString(@"duplicateCombo_msg", @"The specified key combo is already in use..."), NSLocalizedString(@"replace", @"Replace"), NSLocalizedString(@"cancel", @"Cancel"), nil) ) { - [hotKeysDictionary setObject:[ITKeyCombo clearKeyCombo] forKey:currentHotKey]; - if ([enumKey isEqualToString:@"PlayPause"]) { - [playPauseButton setTitle:@"(None)"]; - } else if ([enumKey isEqualToString:@"NextTrack"]) { - [nextTrackButton setTitle:@"(None)"]; - } else if ([enumKey isEqualToString:@"PrevTrack"]) { - [previousTrackButton setTitle:@"(None)"]; - } else if ([enumKey isEqualToString:@"ShowPlayer"]) { - [showPlayerButton setTitle:@"(None)"]; - } else if ([enumKey isEqualToString:@"TrackInfo"]) { - [trackInfoButton setTitle:@"(None)"]; - } else if ([enumKey isEqualToString:@"UpcomingSongs"]) { - [upcomingSongsButton setTitle:@"(None)"]; - } else if ([enumKey isEqualToString:@"IncrementVolume"]) { - [volumeIncrementButton setTitle:@"(None)"]; - } else if ([enumKey isEqualToString:@"DecrementVolume"]) { - [volumeDecrementButton setTitle:@"(None)"]; - } else if ([enumKey isEqualToString:@"IncrementRating"]) { - [ratingIncrementButton setTitle:@"(None)"]; - } else if ([enumKey isEqualToString:@"DecrementRating"]) { - [ratingDecrementButton setTitle:@"(None)"]; - } else if ([enumKey isEqualToString:@"ToggleShuffle"]) { - [toggleShuffleButton setTitle:@"(None)"]; - } else if ([enumKey isEqualToString:@"ToggleLoop"]) { - [toggleLoopButton setTitle:@"(None)"]; - } - ITDebugLog(@"Saved hot key named %@.", enumKey); - [df setObject:[[ITKeyCombo clearKeyCombo] plistRepresentation] forKey:enumKey]; - [hotKeysDictionary setObject:[ITKeyCombo clearKeyCombo] forKey:enumKey]; - } else { - return; - } - [window setLevel:NSStatusWindowLevel]; - } - } - } - - ITDebugLog(@"Saved hot key named %@.", currentHotKey); - [hotKeysDictionary setObject:combo forKey:currentHotKey]; - [df setObject:[combo plistRepresentation] forKey:currentHotKey]; - - ITDebugLog(@"Setting button name."); - if ([currentHotKey isEqualToString:@"PlayPause"]) { - [playPauseButton setTitle:string]; - } else if ([currentHotKey isEqualToString:@"NextTrack"]) { - [nextTrackButton setTitle:string]; - } else if ([currentHotKey isEqualToString:@"PrevTrack"]) { - [previousTrackButton setTitle:string]; - } else if ([currentHotKey isEqualToString:@"ShowPlayer"]) { - [showPlayerButton setTitle:string]; - } else if ([currentHotKey isEqualToString:@"TrackInfo"]) { - [trackInfoButton setTitle:string]; - } else if ([currentHotKey isEqualToString:@"UpcomingSongs"]) { - [upcomingSongsButton setTitle:string]; - } else if ([currentHotKey isEqualToString:@"IncrementVolume"]) { - [volumeIncrementButton setTitle:string]; - } else if ([currentHotKey isEqualToString:@"DecrementVolume"]) { - [volumeDecrementButton setTitle:string]; - } else if ([currentHotKey isEqualToString:@"IncrementRating"]) { - [ratingIncrementButton setTitle:string]; - } else if ([currentHotKey isEqualToString:@"DecrementRating"]) { - [ratingDecrementButton setTitle:string]; - } else if ([currentHotKey isEqualToString:@"ToggleShuffle"]) { - [toggleShuffleButton setTitle:string]; - } else if ([currentHotKey isEqualToString:@"ToggleLoop"]) { - [toggleLoopButton setTitle:string]; - } - [controller setupHotKeys]; - [self cancelHotKey:sender]; -} - - (void)deletePressedInTableView:(NSTableView *)tableView { if (tableView == menuTableView) { @@ -459,40 +615,73 @@ static PreferencesController *prefs = nil; } } +- (void)resetRemotePlayerTextFields +{ + if ([[NetworkController sharedController] isConnectedToServer]) { + [selectedPlayerTextField setStringValue:[[[NetworkController sharedController] networkObject] serverName]]; + [locationTextField setStringValue:[[NetworkController sharedController] remoteHost]]; + } else { + [selectedPlayerTextField setStringValue:@"No shared player selected."]; + [locationTextField setStringValue:@"-"]; + } +} /*************************************************************************/ #pragma mark - #pragma mark HOTKEY SUPPORT METHODS /*************************************************************************/ -- (void)setCurrentHotKey:(NSString *)key +- (IBAction)clearHotKey:(id)sender { - ITDebugLog(@"Setting current hot key to %@", key); - [currentHotKey autorelease]; - currentHotKey = [key copy]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyEvent:) name:ITKeyBroadcasterKeyEvent object:nil]; - [NSApp beginSheet:keyComboPanel modalForWindow:window modalDelegate:self didEndSelector:nil contextInfo:nil]; + [hotKeysDictionary setObject:[ITKeyCombo clearKeyCombo] forKey:[hotKeysArray objectAtIndex:[hotKeysTableView selectedRow]]]; + [df setObject:[[ITKeyCombo clearKeyCombo] plistRepresentation] forKey:[hotKeysArray objectAtIndex:[hotKeysTableView selectedRow]]]; + [controller setupHotKeys]; + [hotKeysTableView reloadData]; } -- (void)keyEvent:(NSNotification *)note +- (IBAction)editHotKey:(id)sender { - [self setKeyCombo:[[[note userInfo] objectForKey:@"keyCombo"] copy]]; + ITKeyComboPanel *panel = [ITKeyComboPanel sharedPanel]; + NSString *keyComboKey = [hotKeysArray objectAtIndex:[hotKeysTableView selectedRow]]; + ITKeyCombo *keyCombo; + + ITDebugLog(@"Setting key combo on hot key %@.", keyComboKey); + [controller clearHotKeys]; + [panel setKeyCombo:[hotKeysDictionary objectForKey:[hotKeysArray objectAtIndex:[hotKeysTableView selectedRow]]]]; + [panel setKeyBindingName:[hotKeyNamesArray objectAtIndex:[hotKeysTableView selectedRow]]]; + if ([panel runModal] == NSOKButton) { + NSEnumerator *keyEnumerator = [[hotKeysDictionary allKeys] objectEnumerator]; + NSString *nextKey; + keyCombo = [panel keyCombo]; + + //Check for duplicate key combo + while ( (nextKey = [keyEnumerator nextObject]) ) { + if ([[hotKeysDictionary objectForKey:nextKey] isEqual:keyCombo] && + ![keyCombo isEqual:[ITKeyCombo clearKeyCombo]]) { + [hotKeysDictionary setObject:[ITKeyCombo clearKeyCombo] + forKey:nextKey]; + [df setObject:[[ITKeyCombo clearKeyCombo] plistRepresentation] + forKey:nextKey]; + } + } + + [hotKeysDictionary setObject:keyCombo forKey:keyComboKey]; + [df setObject:[keyCombo plistRepresentation] forKey:keyComboKey]; + [controller setupHotKeys]; + [hotKeysTableView reloadData]; + ITDebugLog(@"Set combo %@ on hot key %@.", keyCombo, keyComboKey); + } else { + ITDebugLog(@"Hot key setting on hot key %@ cancelled.", keyComboKey); + } } -- (void)setKeyCombo:(ITKeyCombo *)newCombo +- (void)hotKeysTableViewDoubleClicked:(id)sender { - NSString *string; - [combo release]; - combo = [newCombo copy]; - ITDebugLog(@"Setting key combo to %@", newCombo); - string = [combo description]; - if (string == nil) { - string = @"(None)"; + if ([sender clickedRow] > -1) { + [self editHotKey:sender]; } - [keyComboField setStringValue:string]; } - /*************************************************************************/ #pragma mark - #pragma mark PRIVATE METHOD IMPLEMENTATIONS @@ -573,156 +762,247 @@ static PreferencesController *prefs = nil; - (void)setupUI { NSMutableDictionary *loginwindow; - NSMutableArray *loginarray; - NSEnumerator *loginEnum; + NSMutableArray *loginarray; + NSEnumerator *loginEnum; + NSEnumerator *keyArrayEnum; + NSString *serverName; + NSData *colorData; + int selectedBGStyle; id anItem; + ITDebugLog(@"Setting up preferences UI."); // Fill in the number of songs in advance to show field [songsInAdvance setIntValue:[df integerForKey:@"SongsInAdvance"]]; - // Fill in hot key buttons - if ([df objectForKey:@"PlayPause"]) { - ITDebugLog(@"Setting up \"PlayPause\" hot key."); - anItem = [ITKeyCombo keyComboWithPlistRepresentation:[df objectForKey:@"PlayPause"]]; - [hotKeysDictionary setObject:anItem forKey:@"PlayPause"]; - [playPauseButton setTitle:[anItem description]]; - } else { - [hotKeysDictionary setObject:[ITKeyCombo clearKeyCombo] forKey:@"PlayPause"]; - [playPauseButton setTitle:[[ITKeyCombo clearKeyCombo] description]]; + // Fill hot key array + keyArrayEnum = [hotKeysArray objectEnumerator]; + + while ( (anItem = [keyArrayEnum nextObject]) ) { + if ([df objectForKey:anItem]) { + ITDebugLog(@"Setting up \"%@\" hot key.", anItem); + [hotKeysDictionary setObject:[ITKeyCombo keyComboWithPlistRepresentation:[df objectForKey:anItem]] forKey:anItem]; + } else { + [hotKeysDictionary setObject:[ITKeyCombo clearKeyCombo] forKey:anItem]; + } } - if ([df objectForKey:@"NextTrack"]) { - ITDebugLog(@"Setting up \"NextTrack\" hot key."); - anItem = [ITKeyCombo keyComboWithPlistRepresentation:[df objectForKey:@"NextTrack"]]; - [hotKeysDictionary setObject:anItem forKey:@"NextTrack"]; - [nextTrackButton setTitle:[anItem description]]; + ITDebugLog(@"Setting up track info checkboxes."); + // Check current track info buttons + [albumCheckbox setState:[df boolForKey:@"showAlbum"] ? NSOnState : NSOffState]; + [nameCheckbox setState:NSOnState]; // Song info will ALWAYS show song title. + [nameCheckbox setEnabled:NO]; // Song info will ALWAYS show song title. + [artistCheckbox setState:[df boolForKey:@"showArtist"] ? NSOnState : NSOffState]; + [trackTimeCheckbox setState:[df boolForKey:@"showTime"] ? NSOnState : NSOffState]; + [trackNumberCheckbox setState:[df boolForKey:@"showTrackNumber"] ? NSOnState : NSOffState]; + [ratingCheckbox setState:[df boolForKey:@"showTrackRating"] ? NSOnState : NSOffState]; + [albumArtworkCheckbox setState:[df boolForKey:@"showAlbumArtwork"] ? NSOnState : NSOffState]; + + if ([df boolForKey:@"runScripts"]) { + [runScriptsCheckbox setState:NSOnState]; + [showScriptsButton setEnabled:YES]; } else { - [hotKeysDictionary setObject:[ITKeyCombo clearKeyCombo] forKey:@"NextTrack"]; - [nextTrackButton setTitle:[[ITKeyCombo clearKeyCombo] description]]; + [showScriptsButton setEnabled:NO]; } - if ([df objectForKey:@"PrevTrack"]) { - ITDebugLog(@"Setting up \"PrevTrack\" hot key."); - anItem = [ITKeyCombo keyComboWithPlistRepresentation:[df objectForKey:@"PrevTrack"]]; - [hotKeysDictionary setObject:anItem forKey:@"PrevTrack"]; - [previousTrackButton setTitle:[anItem description]]; - } else { - [hotKeysDictionary setObject:[ITKeyCombo clearKeyCombo] forKey:@"PrevTrack"]; - [previousTrackButton setTitle:[[ITKeyCombo clearKeyCombo] description]]; + // Set the launch at login checkbox state + ITDebugLog(@"Setting launch at login state."); + [df synchronize]; + loginwindow = [[df persistentDomainForName:@"loginwindow"] mutableCopy]; + loginarray = [loginwindow objectForKey:@"AutoLaunchedApplicationDictionary"]; + + loginEnum = [loginarray objectEnumerator]; + while ( (anItem = [loginEnum nextObject]) ) { + if ([[[anItem objectForKey:@"Path"] lastPathComponent] isEqualToString:[[[NSBundle mainBundle] bundlePath] lastPathComponent]]) { + [launchAtLoginCheckbox setState:NSOnState]; + } } - if ([df objectForKey:@"ShowPlayer"]) { - ITDebugLog(@"Setting up \"ShowPlayer\" hot key."); - anItem = [ITKeyCombo keyComboWithPlistRepresentation:[df objectForKey:@"ShowPlayer"]]; - [hotKeysDictionary setObject:anItem forKey:@"ShowPlayer"]; - [showPlayerButton setTitle:[anItem description]]; + // Set the launch player checkbox state + ITDebugLog(@"Setting launch player with MenuTunes state."); + [launchPlayerAtLaunchCheckbox setState:[df boolForKey:@"LaunchPlayerWithMT"] ? NSOnState : NSOffState]; + + // Setup the positioning controls + [positionMatrix selectCellAtRow:[df integerForKey:@"statusWindowVerticalPosition"] + column:[df integerForKey:@"statusWindowHorizontalPosition"]]; + + // Setup effects controls + // Populate the effects popups + [appearanceEffectPopup setAutoenablesItems:NO]; + [vanishEffectPopup setAutoenablesItems:NO]; + [self repopulateEffectPopupsForVerticalPosition:[df integerForKey:@"statusWindowVerticalPosition"] + horizontalPosition:[df integerForKey:@"statusWindowHorizontalPosition"]]; + + // Attempt to find the pref'd effect in the list. + // If it's not there, use cut/dissolve. + if ( [effectClasses containsObject:NSClassFromString([df stringForKey:@"statusWindowAppearanceEffect"])] ) { + [appearanceEffectPopup selectItemAtIndex:[effectClasses indexOfObject:NSClassFromString([df stringForKey:@"statusWindowAppearanceEffect"])]]; } else { - [hotKeysDictionary setObject:[ITKeyCombo clearKeyCombo] forKey:@"ShowPlayer"]; - [showPlayerButton setTitle:[[ITKeyCombo clearKeyCombo] description]]; + [appearanceEffectPopup selectItemAtIndex:[effectClasses indexOfObject:NSClassFromString(@"ITCutWindowEffect")]]; } - if ([df objectForKey:@"TrackInfo"]) { - ITDebugLog(@"Setting up \"TrackInfo\" hot key."); - anItem = [ITKeyCombo keyComboWithPlistRepresentation:[df objectForKey:@"TrackInfo"]]; - [hotKeysDictionary setObject:anItem forKey:@"TrackInfo"]; - [trackInfoButton setTitle:[anItem description]]; + if ( [effectClasses containsObject:NSClassFromString([df stringForKey:@"statusWindowVanishEffect"])] ) { + [vanishEffectPopup selectItemAtIndex:[effectClasses indexOfObject:NSClassFromString([df stringForKey:@"statusWindowVanishEffect"])]]; } else { - [hotKeysDictionary setObject:[ITKeyCombo clearKeyCombo] forKey:@"TrackInfo"]; - [trackInfoButton setTitle:[[ITKeyCombo clearKeyCombo] description]]; + [vanishEffectPopup selectItemAtIndex:[effectClasses indexOfObject:NSClassFromString(@"ITCutWindowEffect")]]; } - if ([df objectForKey:@"UpcomingSongs"]) { - ITDebugLog(@"Setting up \"UpcomingSongs\" hot key."); - anItem = [ITKeyCombo keyComboWithPlistRepresentation:[df objectForKey:@"UpcomingSongs"]]; - [hotKeysDictionary setObject:anItem forKey:@"UpcomingSongs"]; - [upcomingSongsButton setTitle:[anItem description]]; + [appearanceSpeedSlider setFloatValue:( -([df floatForKey:@"statusWindowAppearanceSpeed"]) )]; + [vanishSpeedSlider setFloatValue:( -([df floatForKey:@"statusWindowVanishSpeed"]) )]; + [vanishDelaySlider setFloatValue:[df floatForKey:@"statusWindowVanishDelay"]]; + + // Setup General Controls + selectedBGStyle = [df integerForKey:@"statusWindowBackgroundMode"]; + [backgroundStylePopup selectItem:[backgroundStylePopup itemAtIndex:[backgroundStylePopup indexOfItemWithTag:selectedBGStyle]]]; + + if ( selectedBGStyle == ITTSWBackgroundColored ) { + [backgroundColorWell setEnabled:YES]; + [backgroundColorPopup setEnabled:YES]; } else { - [hotKeysDictionary setObject:[ITKeyCombo clearKeyCombo] forKey:@"UpcomingSongs"]; - [upcomingSongsButton setTitle:[[ITKeyCombo clearKeyCombo] description]]; + [backgroundColorWell setEnabled:NO]; + [backgroundColorPopup setEnabled:NO]; } - - if ([df objectForKey:@"IncrementVolume"]) { - ITDebugLog(@"Setting up \"IncrementVolume\" hot key."); - anItem = [ITKeyCombo keyComboWithPlistRepresentation:[df objectForKey:@"IncrementVolume"]]; - [hotKeysDictionary setObject:anItem forKey:@"IncrementVolume"]; - [volumeIncrementButton setTitle:[anItem description]]; + + colorData = [df dataForKey:@"statusWindowBackgroundColor"]; + + if ( colorData ) { + [backgroundColorWell setColor:(NSColor *)[NSUnarchiver unarchiveObjectWithData:colorData]]; } else { - [hotKeysDictionary setObject:[ITKeyCombo clearKeyCombo] forKey:@"IncrementVolume"]; - [volumeIncrementButton setTitle:[[ITKeyCombo clearKeyCombo] description]]; + [backgroundColorWell setColor:[NSColor blueColor]]; } - if ([df objectForKey:@"DecrementVolume"]) { - ITDebugLog(@"Setting up \"DecrementVolume\" hot key."); - anItem = [ITKeyCombo keyComboWithPlistRepresentation:[df objectForKey:@"DecrementVolume"]]; - [hotKeysDictionary setObject:anItem forKey:@"DecrementVolume"]; - [volumeDecrementButton setTitle:[anItem description]]; - } else { - [hotKeysDictionary setObject:[ITKeyCombo clearKeyCombo] forKey:@"DecrementVolume"]; - [volumeDecrementButton setTitle:[[ITKeyCombo clearKeyCombo] description]]; + [showOnChangeCheckbox setState:([df boolForKey:@"showSongInfoOnChange"] ? NSOnState : NSOffState)]; + + [windowSizingPopup selectItem:[windowSizingPopup itemAtIndex:[windowSizingPopup indexOfItemWithTag:[df integerForKey:@"statusWindowSizing"]]]]; + + // Setup the sharing controls + if ([df boolForKey:@"enableSharing"]) { + [shareMenuTunesCheckbox setState:NSOnState]; + [useSharedMenuTunesCheckbox setEnabled:NO]; + [selectSharedPlayerButton setEnabled:NO]; + [passwordTextField setEnabled:YES]; + [nameTextField setEnabled:YES]; + } else if ([df boolForKey:@"useSharedPlayer"]) { + [useSharedMenuTunesCheckbox setState:NSOnState]; + [shareMenuTunesCheckbox setEnabled:NO]; + [selectSharedPlayerButton setEnabled:YES]; } - if ([df objectForKey:@"IncrementRating"]) { - ITDebugLog(@"Setting up \"IncrementRating\" hot key."); - anItem = [ITKeyCombo keyComboWithPlistRepresentation:[df objectForKey:@"IncrementRating"]]; - [hotKeysDictionary setObject:anItem forKey:@"IncrementRating"]; - [ratingIncrementButton setTitle:[anItem description]]; - } else { - [hotKeysDictionary setObject:[ITKeyCombo clearKeyCombo] forKey:@"IncrementRating"]; - [ratingIncrementButton setTitle:[[ITKeyCombo clearKeyCombo] description]]; + [[NSNotificationCenter defaultCenter] addObserver:sharingTableView selector:@selector(reloadData) name:@"ITMTFoundNetService" object:nil]; + + serverName = [df stringForKey:@"sharedPlayerName"]; + if (!serverName || [serverName length] == 0) { + serverName = @"MenuTunes Shared Player"; } + [nameTextField setStringValue:serverName]; - if ([df objectForKey:@"DecrementRating"]) { - ITDebugLog(@"Setting up \"DecrementRating\" hot key."); - anItem = [ITKeyCombo keyComboWithPlistRepresentation:[df objectForKey:@"DecrementRating"]]; - [hotKeysDictionary setObject:anItem forKey:@"DecrementRating"]; - [ratingDecrementButton setTitle:[anItem description]]; + [selectPlayerBox setContentView:zeroConfView]; + if ([[df dataForKey:@"sharedPlayerPassword"] length] > 0) { + [passwordTextField setStringValue:@"p4s5w0rdMT1.2"]; } else { - [hotKeysDictionary setObject:[ITKeyCombo clearKeyCombo] forKey:@"DecrementRating"]; - [ratingDecrementButton setTitle:[[ITKeyCombo clearKeyCombo] description]]; + [passwordTextField setStringValue:@""]; + } + if ([df stringForKey:@"sharedPlayerHost"]) { + [hostTextField setStringValue:[df stringForKey:@"sharedPlayerHost"]]; } - if ([df objectForKey:@"ToggleLoop"]) { - ITDebugLog(@"Setting up \"ToggleLoop\" hot key."); - anItem = [ITKeyCombo keyComboWithPlistRepresentation:[df objectForKey:@"ToggleLoop"]]; - [hotKeysDictionary setObject:anItem forKey:@"ToggleLoop"]; - [toggleLoopButton setTitle:[anItem description]]; + if ([[NetworkController sharedController] isConnectedToServer]) { + [selectedPlayerTextField setStringValue:[[[NetworkController sharedController] networkObject] serverName]]; + [locationTextField setStringValue:[[NetworkController sharedController] remoteHost]]; } else { - [hotKeysDictionary setObject:[ITKeyCombo clearKeyCombo] forKey:@"ToggleLoop"]; - [toggleLoopButton setTitle:[[ITKeyCombo clearKeyCombo] description]]; + [selectedPlayerTextField setStringValue:@"No shared player selected."]; + [locationTextField setStringValue:@"-"]; } +} + +- (void)setStatusWindowEntryEffect:(Class)effectClass +{ + StatusWindow *sw = [StatusWindow sharedWindow]; - if ([df objectForKey:@"ToggleShuffle"]) { - ITDebugLog(@"Setting up \"ToggleShuffle\" hot key."); - anItem = [ITKeyCombo keyComboWithPlistRepresentation:[df objectForKey:@"ToggleShuffle"]]; - [hotKeysDictionary setObject:anItem forKey:@"ToggleShuffle"]; - [toggleShuffleButton setTitle:[anItem description]]; - } else { - [hotKeysDictionary setObject:[ITKeyCombo clearKeyCombo] forKey:@"ToggleShuffle"]; - [toggleShuffleButton setTitle:[[ITKeyCombo clearKeyCombo] description]]; + float time = ([df floatForKey:@"statusWindowAppearanceSpeed"] ? [df floatForKey:@"statusWindowAppearanceSpeed"] : 0.8); + [df setObject:NSStringFromClass(effectClass) forKey:@"statusWindowAppearanceEffect"]; + + [sw setEntryEffect:[[[effectClass alloc] initWithWindow:sw] autorelease]]; + [[sw entryEffect] setEffectTime:time]; +} + +- (void)setStatusWindowExitEffect:(Class)effectClass +{ + StatusWindow *sw = [StatusWindow sharedWindow]; + + float time = ([df floatForKey:@"statusWindowVanishSpeed"] ? [df floatForKey:@"statusWindowVanishSpeed"] : 0.8); + [df setObject:NSStringFromClass(effectClass) forKey:@"statusWindowVanishEffect"]; + + [sw setExitEffect:[[[effectClass alloc] initWithWindow:sw] autorelease]]; + [[sw exitEffect] setEffectTime:time]; +} + +- (void)setCustomColor:(NSColor *)color updateWell:(BOOL)update +{ + [(ITTSWBackgroundView *)[[StatusWindow sharedWindow] contentView] setBackgroundColor:color]; + [df setObject:[NSArchiver archivedDataWithRootObject:color] forKey:@"statusWindowBackgroundColor"]; + + if ( update ) { + [backgroundColorWell setColor:color]; } +} + +- (void)repopulateEffectPopupsForVerticalPosition:(ITVerticalWindowPosition)vPos horizontalPosition:(ITHorizontalWindowPosition)hPos +{ + NSEnumerator *effectEnum = [effectClasses objectEnumerator]; + id anItem; - ITDebugLog(@"Setting up track info checkboxes."); - // Check current track info buttons - [albumCheckbox setState:[df boolForKey:@"showAlbum"] ? NSOnState : NSOffState]; - [nameCheckbox setState:NSOnState]; // Song info will ALWAYS show song title. - [nameCheckbox setEnabled:NO]; // Song info will ALWAYS show song title. - [artistCheckbox setState:[df boolForKey:@"showArtist"] ? NSOnState : NSOffState]; - [trackTimeCheckbox setState:[df boolForKey:@"showTime"] ? NSOnState : NSOffState]; - [trackNumberCheckbox setState:[df boolForKey:@"showTrackNumber"] ? NSOnState : NSOffState]; - [ratingCheckbox setState:[df boolForKey:@"showTrackRating"] ? NSOnState : NSOffState]; + [appearanceEffectPopup removeAllItems]; + [vanishEffectPopup removeAllItems]; - // Set the launch at login checkbox state - ITDebugLog(@"Setting launch at login state."); - [df synchronize]; - loginwindow = [[df persistentDomainForName:@"loginwindow"] mutableCopy]; - loginarray = [loginwindow objectForKey:@"AutoLaunchedApplicationDictionary"]; + while ( (anItem = [effectEnum nextObject]) ) { + [appearanceEffectPopup addItemWithTitle:[anItem effectName]]; + [vanishEffectPopup addItemWithTitle:[anItem effectName]]; + + [[appearanceEffectPopup lastItem] setRepresentedObject:anItem]; + [[vanishEffectPopup lastItem] setRepresentedObject:anItem]; + + if ( [self effect:anItem supportsVerticalPosition:vPos withHorizontalPosition:hPos] ) { + [[appearanceEffectPopup lastItem] setEnabled:YES]; + [[vanishEffectPopup lastItem] setEnabled:YES]; + } else { + [[appearanceEffectPopup lastItem] setEnabled:NO]; + [[vanishEffectPopup lastItem] setEnabled:NO]; + } + } - loginEnum = [loginarray objectEnumerator]; - while ( (anItem = [loginEnum nextObject]) ) { - if ([[[anItem objectForKey:@"Path"] lastPathComponent] isEqualToString:[[[NSBundle mainBundle] bundlePath] lastPathComponent]]) { - [launchAtLoginCheckbox setState:NSOnState]; +} + +- (BOOL)effect:(Class)effectClass supportsVerticalPosition:(ITVerticalWindowPosition)vPos withHorizontalPosition:(ITHorizontalWindowPosition)hPos +{ + BOOL valid = NO; + + if ( vPos == ITWindowPositionTop ) { + if ( hPos == ITWindowPositionLeft ) { + valid = ( [[[[effectClass supportedPositions] objectForKey:@"Top"] objectForKey:@"Left"] boolValue] ) ; + } else if ( hPos == ITWindowPositionCenter ) { + valid = ( [[[[effectClass supportedPositions] objectForKey:@"Top"] objectForKey:@"Center"] boolValue] ); + } else if ( hPos == ITWindowPositionRight ) { + valid = ( [[[[effectClass supportedPositions] objectForKey:@"Top"] objectForKey:@"Right"] boolValue] ); + } + } else if ( vPos == ITWindowPositionMiddle ) { + if ( hPos == ITWindowPositionLeft ) { + valid = ( [[[[effectClass supportedPositions] objectForKey:@"Middle"] objectForKey:@"Left"] boolValue] ); + } else if ( hPos == ITWindowPositionCenter ) { + valid = ( [[[[effectClass supportedPositions] objectForKey:@"Middle"] objectForKey:@"Center"] boolValue] ); + } else if ( hPos == ITWindowPositionRight ) { + valid = ( [[[[effectClass supportedPositions] objectForKey:@"Middle"] objectForKey:@"Right"] boolValue] ); + } + } else if ( vPos == ITWindowPositionBottom ) { + if ( hPos == ITWindowPositionLeft ) { + valid = ( [[[[effectClass supportedPositions] objectForKey:@"Bottom"] objectForKey:@"Left"] boolValue] ); + } else if ( hPos == ITWindowPositionCenter ) { + valid = ( [[[[effectClass supportedPositions] objectForKey:@"Bottom"] objectForKey:@"Center"] boolValue] ); + } else if ( hPos == ITWindowPositionRight ) { + valid = ( [[[[effectClass supportedPositions] objectForKey:@"Bottom"] objectForKey:@"Right"] boolValue] ); } } + + return valid; } - (IBAction)changeMenus:(id)sender @@ -730,6 +1010,11 @@ static PreferencesController *prefs = nil; ITDebugLog(@"Synchronizing menus"); [df setObject:myItems forKey:@"menu"]; [df synchronize]; + + //If we're connected over a network, refresh the menu immediately + if ([[NetworkController sharedController] isConnectedToServer]) { + [controller timerUpdate]; + } } - (void)setLaunchesAtLogin:(BOOL)flag @@ -773,6 +1058,21 @@ static PreferencesController *prefs = nil; [(MainController *)controller closePreferences]; } +/*************************************************************************/ +#pragma mark - +#pragma mark NSTextField DELEGATE METHODS +/*************************************************************************/ + +- (void)controlTextDidChange:(NSNotification*)note +{ + if ([note object] == hostTextField) { + if ([[hostTextField stringValue] length] == 0) { + [sharingPanelOKButton setEnabled:NO]; + } else { + [sharingPanelOKButton setEnabled:YES]; + } + } +} /*************************************************************************/ #pragma mark - @@ -783,8 +1083,12 @@ static PreferencesController *prefs = nil; { if (aTableView == menuTableView) { return [myItems count]; - } else { + } else if (aTableView == allTableView) { return [availableItems count]; + } else if (aTableView == hotKeysTableView) { + return [hotKeysArray count]; + } else { + return [[[NetworkController sharedController] remoteServices] count]; } } @@ -794,7 +1098,13 @@ static PreferencesController *prefs = nil; NSString *object = [myItems objectAtIndex:rowIndex]; if ([[aTableColumn identifier] isEqualToString:@"name"]) { if ([object isEqualToString:@"showPlayer"]) { - return [NSString stringWithFormat:@"%@ %@", NSLocalizedString(@"show", @"Show"), [[controller currentRemote] playerSimpleName]]; + NSString *string = nil; + NS_DURING + string = [NSString stringWithFormat:@"%@ %@", NSLocalizedString(@"show", @"Show"), [[controller currentRemote] playerSimpleName]]; + NS_HANDLER + [controller networkError:localException]; + NS_ENDHANDLER + return string; } return NSLocalizedString(object, @"ERROR"); } else { @@ -805,11 +1115,17 @@ static PreferencesController *prefs = nil; return nil; } } - } else { + } else if (aTableView == allTableView) { NSString *object = [availableItems objectAtIndex:rowIndex]; if ([[aTableColumn identifier] isEqualToString:@"name"]) { if ([object isEqualToString:@"showPlayer"]) { - return [NSString stringWithFormat:@"%@ %@", NSLocalizedString(@"show", @"Show"), [[controller currentRemote] playerSimpleName]]; + NSString *string = nil; + NS_DURING + string = [NSString stringWithFormat:@"%@ %@", NSLocalizedString(@"show", @"Show"), [[controller currentRemote] playerSimpleName]]; + NS_HANDLER + [controller networkError:localException]; + NS_ENDHANDLER + return string; } return NSLocalizedString(object, @"ERROR"); } else { @@ -819,6 +1135,14 @@ static PreferencesController *prefs = nil; return nil; } } + } else if (aTableView == hotKeysTableView) { + if ([[aTableColumn identifier] isEqualToString:@"name"]) { + return [hotKeyNamesArray objectAtIndex:rowIndex]; + } else { + return [[hotKeysDictionary objectForKey:[hotKeysArray objectAtIndex:rowIndex]] description]; + } + } else { + return [[[[NetworkController sharedController] remoteServices] objectAtIndex:rowIndex] name]; } } @@ -858,7 +1182,7 @@ static PreferencesController *prefs = nil; } else { [myItems removeObjectAtIndex:dragRow + 1]; } - } else { + } else if (tableView == allTableView) { if (![temp isEqualToString:@"separator"]) { [availableItems addObject:temp]; } @@ -891,7 +1215,7 @@ static PreferencesController *prefs = nil; if ([[[info draggingPasteboard] types] containsObject:@"MenuTableViewPboardType"]) { NSString *item = [myItems objectAtIndex:[[[info draggingPasteboard] stringForType:@"MenuTableViewPboardType"] intValue]]; - if ([item isEqualToString:@"preferences"]) { + if ([item isEqualToString:@"preferences"] || [item isEqualToString:@"quit"]) { return NSDragOperationNone; } } @@ -904,7 +1228,6 @@ static PreferencesController *prefs = nil; { return NSDragOperationNone; } - return NSDragOperationGeneric; } @@ -916,9 +1239,9 @@ static PreferencesController *prefs = nil; - (void)dealloc { - [self setKeyCombo:nil]; + [hotKeysArray release]; [hotKeysDictionary release]; - [keyComboPanel release]; + [effectClasses release]; [menuTableView setDataSource:nil]; [allTableView setDataSource:nil]; [controller release]; @@ -928,5 +1251,4 @@ static PreferencesController *prefs = nil; [df release]; } - @end