X-Git-Url: http://git.ithinksw.org/MenuTunes.git/blobdiff_plain/dc685d1d1cffcfd6bb95dd948c30f1dc315919e0..f259f879db5bb904afca6f0fa31effa5511c476e:/MainController.m diff --git a/MainController.m b/MainController.m index c4fd253..40f50ce 100755 --- a/MainController.m +++ b/MainController.m @@ -6,10 +6,35 @@ #import #import #import +#import #import "StatusWindow.h" #import "StatusWindowController.h" #import "StatusItemHack.h" +@interface NSCarbonMenuImpl:NSObject +{ + NSMenu *_menu; +} + ++ (void)initialize; ++ (void)setupForNoMenuBar; +- (void)dealloc; +- (void)setMenu:fp8; +- menu; +- (void)itemChanged:fp8; +- (void)itemAdded:fp8; +- (void)itemRemoved:fp8; +- (void)performActionWithHighlightingForItemAtIndex:(int)fp8; +- (void)performMenuAction:(SEL)fp8 withTarget:fp12; +- (void)setupCarbonMenuBar; +- (void)setAsMainCarbonMenuBar; +- (void)clearAsMainCarbonMenuBar; +- (void)popUpMenu:fp8 atLocation:(NSPoint)fp12 width:(float)fp20 forView:fp24 withSelectedItem:(int)fp28 withFont:fp32; +- (void)_popUpContextMenu:fp8 withEvent:fp12 forView:fp16 withFont:fp20; +- (void)_popUpContextMenu:fp8 withEvent:fp12 forView:fp16; +- window; +@end + @implementation NSImage (SmoothAdditions) - (NSImage *)imageScaledSmoothlyToSize:(NSSize)scaledSize @@ -89,9 +114,7 @@ static MainController *sharedController; if ([df boolForKey:@"enableSharing"]) { [self setServerStatus:YES]; } else if ([df boolForKey:@"useSharedPlayer"]) { - if ([self connectToServer] == 0) { - [NSTimer scheduledTimerWithTimeInterval:45 target:self selector:@selector(checkForRemoteServer:) userInfo:nil repeats:YES]; - } + [self checkForRemoteServerAndConnectImmediately:YES]; } //Setup for notification of the remote player launching or quitting @@ -107,7 +130,7 @@ static MainController *sharedController; name:NSWorkspaceDidLaunchApplicationNotification object:nil]; - if ( ! [df objectForKey:@"menu"] ) { // If this is nil, defaults have never been registered. + if (![df objectForKey:@"menu"]) { // If this is nil, defaults have never been registered. [[PreferencesController sharedPrefs] registerDefaults]; } @@ -164,7 +187,7 @@ static MainController *sharedController; Class remoteClass = [remoteBundle principalClass]; if ([remoteClass conformsToProtocol:@protocol(ITMTRemote)] && - [remoteClass isKindOfClass:[NSObject class]]) { + [(NSObject *)remoteClass isKindOfClass:[NSObject class]]) { id remote = [remoteClass remote]; ITDebugLog(@"Adding remote at path %@", bundlePath); [remoteArray addObject:remote]; @@ -336,7 +359,6 @@ static MainController *sharedController; { if ( [self songChanged] && (timerUpdating != YES) && (playerRunningState == ITMTRemotePlayerRunning) ) { ITDebugLog(@"The song changed."); - if ([df boolForKey:@"runScripts"]) { NSArray *scripts = [[NSFileManager defaultManager] directoryContentsAtPath:[NSHomeDirectory() stringByAppendingPathComponent:@"Library/Application Support/MenuTunes/Scripts"]]; NSEnumerator *scriptsEnum = [scripts objectEnumerator]; @@ -523,13 +545,28 @@ static MainController *sharedController; { ITDebugLog(@"Selecting EQ preset %i", index); NS_DURING - [[self currentRemote] switchToEQAtIndex:index]; + if (index == -1) { + [[self currentRemote] setEqualizerEnabled:![[self currentRemote] equalizerEnabled]]; + } else { + [[self currentRemote] switchToEQAtIndex:index]; + } NS_HANDLER [self networkError:localException]; NS_ENDHANDLER [self timerUpdate]; } +- (void)makePlaylistWithTerm:(NSString *)term ofType:(int)type +{ + ITDebugLog(@"Making playlist with term %@, type %i", term, type); + NS_DURING + [[self currentRemote] makePlaylistWithTerm:term ofType:type]; + NS_HANDLER + [self networkError:localException]; + NS_ENDHANDLER + ITDebugLog(@"Done making playlist"); +} + - (void)showPlayer { ITDebugLog(@"Beginning show player."); @@ -546,7 +583,7 @@ static MainController *sharedController; NSString *path; if ( (path = [df stringForKey:@"CustomPlayerPath"]) ) { } else { - path = [[self currentRemote] playerFullName]; + pathITDebugLog(@"Showing player interface."); = [[self currentRemote] playerFullName]; } if (![[NSWorkspace sharedWorkspace] launchApplication:path]) { ITDebugLog(@"Error Launching Player"); @@ -665,6 +702,26 @@ static MainController *sharedController; [[ITHotKeyCenter sharedCenter] registerHotKey:[hotKey autorelease]]; } + if ([df objectForKey:@"FastForward"] != nil) { + ITDebugLog(@"Setting up fast forward hot key."); + hotKey = [[ITHotKey alloc] init]; + [hotKey setName:@"FastForward"]; + [hotKey setKeyCombo:[ITKeyCombo keyComboWithPlistRepresentation:[df objectForKey:@"FastForward"]]]; + [hotKey setTarget:self]; + [hotKey setAction:@selector(fastForward)]; + [[ITHotKeyCenter sharedCenter] registerHotKey:[hotKey autorelease]]; + } + + if ([df objectForKey:@"Rewind"] != nil) { + ITDebugLog(@"Setting up rewind hot key."); + hotKey = [[ITHotKey alloc] init]; + [hotKey setName:@"Rewind"]; + [hotKey setKeyCombo:[ITKeyCombo keyComboWithPlistRepresentation:[df objectForKey:@"Rewind"]]]; + [hotKey setTarget:self]; + [hotKey setAction:@selector(rewind)]; + [[ITHotKeyCenter sharedCenter] registerHotKey:[hotKey autorelease]]; + } + if ([df objectForKey:@"ShowPlayer"] != nil) { ITDebugLog(@"Setting up show player hot key."); hotKey = [[ITHotKey alloc] init]; @@ -754,6 +811,30 @@ static MainController *sharedController; [hotKey setAction:@selector(decrementRating)]; [[ITHotKeyCenter sharedCenter] registerHotKey:[hotKey autorelease]]; } + + if ([df objectForKey:@"PopupMenu"] != nil) { + ITDebugLog(@"Setting up popup menu hot key."); + hotKey = [[ITHotKey alloc] init]; + [hotKey setName:@"PopupMenu"]; + [hotKey setKeyCombo:[ITKeyCombo keyComboWithPlistRepresentation:[df objectForKey:@"PopupMenu"]]]; + [hotKey setTarget:self]; + [hotKey setAction:@selector(popupMenu)]; + [[ITHotKeyCenter sharedCenter] registerHotKey:[hotKey autorelease]]; + } + + int i; + for (i = 0; i <= 5; i++) { + NSString *curName = [NSString stringWithFormat:@"SetRating%i", i]; + if ([df objectForKey:curName] != nil) { + ITDebugLog(@"Setting up set rating %i hot key.", i); + hotKey = [[ITHotKey alloc] init]; + [hotKey setName:curName]; + [hotKey setKeyCombo:[ITKeyCombo keyComboWithPlistRepresentation:[df objectForKey:curName]]]; + [hotKey setTarget:self]; + [hotKey setAction:@selector(setRating:)]; + [[ITHotKeyCenter sharedCenter] registerHotKey:[hotKey autorelease]]; + } + } ITDebugLog(@"Finished setting up hot keys."); } @@ -768,6 +849,7 @@ static MainController *sharedController; NSString *track = nil; NSImage *art = nil; int rating = -1; + int playCount = -1; ITDebugLog(@"Showing track info status window."); @@ -779,7 +861,19 @@ static MainController *sharedController; NS_ENDHANDLER if ( title ) { - + if ( [df boolForKey:@"showAlbumArtwork"] ) { + NSSize oldSize, newSize; + NS_DURING + art = [[self currentRemote] currentSongAlbumArt]; + oldSize = [art size]; + if (oldSize.width > oldSize.height) newSize = NSMakeSize(110,oldSize.height * (110.0f / oldSize.width)); + else newSize = NSMakeSize(oldSize.width * (110.0f / oldSize.height),110); + art = [[[[NSImage alloc] initWithData:[art TIFFRepresentation]] autorelease] imageScaledSmoothlyToSize:newSize]; + NS_HANDLER + [self networkError:localException]; + NS_ENDHANDLER + } + if ( [df boolForKey:@"showAlbum"] ) { NS_DURING album = [[self currentRemote] currentSongAlbum]; @@ -807,7 +901,7 @@ static MainController *sharedController; if ( [df boolForKey:@"showTime"] ) { NS_DURING time = [NSString stringWithFormat:@"%@: %@ / %@", - @"Time", + NSLocalizedString(@"time", @"Time"), [[self currentRemote] currentSongElapsed], [[self currentRemote] currentSongLength]]; NS_HANDLER @@ -846,19 +940,13 @@ static MainController *sharedController; } } - if ( [df boolForKey:@"showAlbumArtwork"] ) { - NSSize oldSize, newSize; - NS_DURING - art = [[self currentRemote] currentSongAlbumArt]; - oldSize = [art size]; - if (oldSize.width > oldSize.height) newSize = NSMakeSize(110,oldSize.height * (110.0f / oldSize.width)); - else newSize = NSMakeSize(oldSize.width * (110.0f / oldSize.height),110); - art = [[[[NSImage alloc] initWithData:[art TIFFRepresentation]] autorelease] imageScaledSmoothlyToSize:newSize]; + if ( [df boolForKey:@"showPlayCount"] && ![self radioIsPlaying] && [[self currentRemote] currentSource] == ITMTRemoteLibrarySource ) { + NS_DURING + playCount = [[self currentRemote] currentSongPlayCount]; NS_HANDLER [self networkError:localException]; NS_ENDHANDLER } - } else { title = NSLocalizedString(@"noSongPlaying", @"No song is playing."); } @@ -871,6 +959,7 @@ static MainController *sharedController; time:time track:track rating:rating + playCount:playCount image:art]; } @@ -910,6 +999,17 @@ static MainController *sharedController; NS_ENDHANDLER } +- (void)popupMenu +{ + if (!_popped) { + _popped = YES; + [self menuClicked]; + NSMenu *menu = [statusItem menu]; + [(NSCarbonMenuImpl *)[menu _menuImpl] popUpMenu:menu atLocation:[NSEvent mouseLocation] width:1 forView:nil withSelectedItem:-30 withFont:[NSFont menuFontOfSize:32]]; + _popped = NO; + } +} + - (void)incrementVolume { NS_DURING @@ -1008,6 +1108,13 @@ static MainController *sharedController; NS_ENDHANDLER } +- (void)setRating:(ITHotKey *)sender +{ + int stars = [[sender name] characterAtIndex:9] - 48; + [self selectSongRating:stars * 20]; + [statusWindowController showRatingWindowWithRating:(float)stars / 5.0]; +} + - (void)toggleLoop { NS_DURING @@ -1134,17 +1241,57 @@ static MainController *sharedController; return YES; } -- (void)checkForRemoteServer:(NSTimer *)timer +- (void)checkForRemoteServer +{ + [self checkForRemoteServerAndConnectImmediately:NO]; +} + +- (void)checkForRemoteServerAndConnectImmediately:(BOOL)connectImmediately { ITDebugLog(@"Checking for remote server."); + if (!_checkingForServer) { + if (!_serverCheckLock) { + _serverCheckLock = [[NSLock alloc] init]; + } + [_serverCheckLock lock]; + _checkingForServer = YES; + [_serverCheckLock unlock]; + [NSThread detachNewThreadSelector:@selector(runRemoteServerCheck:) toTarget:self withObject:[NSNumber numberWithBool:connectImmediately]]; + } +} + +- (void)runRemoteServerCheck:(id)sender +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + ITDebugLog(@"Remote server check running."); if ([networkController checkForServerAtHost:[df stringForKey:@"sharedPlayerHost"]]) { ITDebugLog(@"Remote server found."); - [timer invalidate]; - if (![networkController isServerOn] && ![networkController isConnectedToServer]) { - [[StatusWindowController sharedController] showReconnectQueryWindow]; + if ([sender boolValue]) { + [self performSelectorOnMainThread:@selector(connectToServer) withObject:nil waitUntilDone:NO]; + } else { + [self performSelectorOnMainThread:@selector(remoteServerFound:) withObject:nil waitUntilDone:NO]; } } else { ITDebugLog(@"Remote server not found."); + [self performSelectorOnMainThread:@selector(remoteServerNotFound:) withObject:nil waitUntilDone:NO]; + } + [_serverCheckLock lock]; + _checkingForServer = NO; + [_serverCheckLock unlock]; + [pool release]; +} + +- (void)remoteServerFound:(id)sender +{ + if (![networkController isServerOn] && ![networkController isConnectedToServer]) { + [[StatusWindowController sharedController] showReconnectQueryWindow]; + } +} + +- (void)remoteServerNotFound:(id)sender +{ + if (![[NetworkController sharedController] isConnectedToServer]) { + [NSTimer scheduledTimerWithTimeInterval:90.0 target:self selector:@selector(checkForRemoteServer) userInfo:nil repeats:NO]; } } @@ -1152,10 +1299,11 @@ static MainController *sharedController; { ITDebugLog(@"Remote exception thrown: %@: %@", [exception name], [exception reason]); if ( ((exception == nil) || [[exception name] isEqualToString:NSPortTimeoutException]) && [networkController isConnectedToServer]) { - NSRunCriticalAlertPanel(@"Remote MenuTunes Disconnected", @"The MenuTunes server you were connected to stopped responding or quit. MenuTunes will revert back to the local player.", @"OK", nil, nil); + //NSRunCriticalAlertPanel(@"Remote MenuTunes Disconnected", @"The MenuTunes server you were connected to stopped responding or quit. MenuTunes will revert back to the local player.", @"OK", nil, nil); + [[StatusWindowController sharedController] showNetworkErrorQueryWindow]; if ([self disconnectFromServer]) { [[PreferencesController sharedPrefs] resetRemotePlayerTextFields]; - [NSTimer scheduledTimerWithTimeInterval:45 target:self selector:@selector(checkForRemoteServer:) userInfo:nil repeats:YES]; + [NSTimer scheduledTimerWithTimeInterval:90.0 target:self selector:@selector(checkForRemoteServer) userInfo:nil repeats:NO]; } else { ITDebugLog(@"CRITICAL ERROR, DISCONNECTING!"); } @@ -1164,9 +1312,10 @@ static MainController *sharedController; - (void)reconnect { - if ([self connectToServer] == 0) { - [NSTimer scheduledTimerWithTimeInterval:45 target:self selector:@selector(checkForRemoteServer:) userInfo:nil repeats:YES]; - } + /*if ([self connectToServer] == 0) { + [NSTimer scheduledTimerWithTimeInterval:90.0 target:self selector:@selector(checkForRemoteServer) userInfo:nil repeats:NO]; + }*/ + [self checkForRemoteServerAndConnectImmediately:YES]; [[StatusWindow sharedWindow] setLocked:NO]; [[StatusWindow sharedWindow] vanish:self]; [[StatusWindow sharedWindow] setIgnoresMouseEvents:YES]; @@ -1261,6 +1410,7 @@ static MainController *sharedController; [statusWindowController release]; [menuController release]; [networkController release]; + [_serverCheckLock release]; [super dealloc]; }