Lots of rewritten code. Not yet working because the status item doesn't
[MenuTunes.git] / OldMainController.m
1 #import "MainController.h"
2 #import "PreferencesController.h"
3 #import "HotKeyCenter.h"
4 #import "StatusWindow.h"
5
6 @interface MainController(Private)
7 - (ITMTRemote *)loadRemote;
8 - (void)setupHotKeys;
9 - (void)setKeyEquivalentForCode:(short)code andModifiers:(long)modifiers
10         onItem:(NSMenuItem *)item;
11 - (NSMenu *)mainMenu;
12 - (NSMenu *)songRatingMenu;
13 - (NSMenu *)playlistsMenu;
14 - (NSMenu *)upcomingSongsMenu;
15 - (NSMenu *)eqPresetsMenu;
16 @end
17
18 @implementation MainController
19
20 - (id)init
21 {
22     if ( ( self = [super init] ) ) {
23         remoteArray = [[NSMutableArray alloc] initWithCapacity:1];
24         statusWindow = [StatusWindow sharedWindow];
25     }
26     return self;
27 }
28
29 - (void)dealloc
30 {
31     if (refreshTimer) {
32         [refreshTimer invalidate];
33         [refreshTimer release];
34         refreshTimer = nil;
35     }
36     [currentRemote halt];
37     [statusItem release];
38     [super dealloc];
39 }
40
41 - (void)applicationDidFinishLaunching:(NSNotification *)note
42 {
43     currentRemote = [self loadRemote];
44     [currentRemote begin];
45     
46     //Setup for notification of the remote player launching or quitting
47     [[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:self selector:@selector(applicationTerminated:) name:NSWorkspaceDidTerminateApplicationNotification object:nil];
48     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationLaunched:) name:NSWorkspaceDidLaunchApplicationNotification object:nil];
49     
50     [self registerDefaults];
51     
52     statusItem = [[ITStatusItem alloc] initWithStatusBar:[NSStatusBar systemStatusBar] withLength:NSSquareStatusItemLength];
53     [statusItem setImage:[NSImage imageNamed:@"menu"]];
54     [statusItem setAlternateImage:[NSImage imageNamed:@"selected_image"]];
55     // Below line of code is for creating builds for Beta Testers
56     // [statusItem setToolTip:@[NSString stringWithFormat:@"This Nontransferable Beta (Built on %s) of iThink Software's MenuTunes is Registered to: Beta Tester (betatester@somedomain.com).",__DATE__]];
57     
58     if ( ( [currentRemote playerRunningState] == ITMTRemotePlayerRunning ) ) {
59         [self applicationLaunched:nil];
60     } else {
61         [self applicationTerminated:nil];
62     }
63 }
64
65 - (void)applicationWillTerminate:(NSNotification *)note
66 {
67     [self clearHotKeys];
68     [[NSStatusBar systemStatusBar] removeStatusItem:statusItem];
69     [[[NSWorkspace sharedWorkspace] notificationCenter] removeObserver:self];
70 }
71
72 //
73 //
74
75 - (ITMTRemote *)loadRemote
76 {
77     NSString *folderPath = [[NSBundle mainBundle] builtInPlugInsPath];
78     
79     if (folderPath) {
80         NSArray      *bundlePathList = [NSBundle pathsForResourcesOfType:@"remote" inDirectory:folderPath];
81         NSEnumerator *enumerator     = [bundlePathList objectEnumerator];
82         NSString     *bundlePath;
83
84         while ( (bundlePath = [enumerator nextObject]) ) {
85             NSBundle* remoteBundle = [NSBundle bundleWithPath:bundlePath];
86
87             if (remoteBundle) {
88                 Class remoteClass = [remoteBundle principalClass];
89
90                 if ([remoteClass conformsToProtocol:@protocol(ITMTRemote)] &&
91                     [remoteClass isKindOfClass:[NSObject class]]) {
92
93                     id remote = [remoteClass remote];
94                     [remoteArray addObject:remote];
95                 }
96             }
97         }
98
99 //      if ( [remoteArray count] > 0 ) {  // UNCOMMENT WHEN WE HAVE > 1 PLUGIN
100 //          if ( [remoteArray count] > 1 ) {
101 //              [remoteArray sortUsingSelector:@selector(sortAlpha:)];
102 //          }
103 //          [self loadModuleAccessUI]; //Comment out this line to disable remote visibility
104 //      }
105     }
106 //  NSLog(@"%@", [remoteArray objectAtIndex:0]);  //DEBUG
107     return [remoteArray objectAtIndex:0];
108 }
109
110 - (void)registerDefaults
111 {
112     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
113     if (![defaults objectForKey:@"menu"]) {
114         BOOL found = NO;
115         NSMutableDictionary *loginwindow;
116         NSMutableArray *loginarray;
117         int i;
118         
119         [defaults setObject:
120             [NSArray arrayWithObjects:
121                 @"Play/Pause",
122                 @"Next Track",
123                 @"Previous Track",
124                 @"Fast Forward",
125                 @"Rewind",
126                 @"<separator>",
127                 @"Upcoming Songs",
128                 @"Playlists",
129                 @"Song Rating",
130                 @"<separator>",
131                 @"PreferencesÉ",
132                 @"Quit",
133                 @"<separator>",
134                 @"Current Track Info",
135                 nil] forKey:@"menu"];
136         
137         [defaults synchronize];
138         loginwindow = [[defaults persistentDomainForName:@"loginwindow"] mutableCopy];
139         loginarray = [loginwindow objectForKey:@"AutoLaunchedApplicationDictionary"];
140         
141         for (i = 0; i < [loginarray count]; i++) {
142             NSDictionary *tempDict = [loginarray objectAtIndex:i];
143             if ([[[tempDict objectForKey:@"Path"] lastPathComponent] isEqualToString:[[[NSBundle mainBundle] bundlePath] lastPathComponent]]) {
144                 found = YES;
145             }
146         }
147         
148         //
149         //This is teh sux
150         //We must fix it so it is no longer suxy
151         if (!found) {
152             if (NSRunInformationalAlertPanel(@"Auto-launch MenuTunes", @"Would you like MenuTunes to automatically launch at login?", @"Yes", @"No", nil) == NSOKButton) {
153                 AEDesc scriptDesc, resultDesc;
154                 NSString *script = [NSString stringWithFormat:@"tell application \"System Events\"\nmake new login item at end of login items with properties {path:\"%@\", kind:\"APPLICATION\"}\nend tell", [[NSBundle mainBundle] bundlePath]];
155                 ComponentInstance asComponent = OpenDefaultComponent(kOSAComponentType, kAppleScriptSubtype);
156                 
157                 AECreateDesc(typeChar, [script cString], [script cStringLength], 
158             &scriptDesc);
159                 
160                 OSADoScript(asComponent, &scriptDesc, kOSANullScript, typeChar, kOSAModeCanInteract, &resultDesc);
161                 
162                 AEDisposeDesc(&scriptDesc);
163                 AEDisposeDesc(&resultDesc);
164                 
165                 CloseComponent(asComponent);
166             }
167         }
168     }
169     
170     if (![defaults integerForKey:@"SongsInAdvance"])
171     {
172         [defaults setInteger:5 forKey:@"SongsInAdvance"];
173     }
174     
175     if (![defaults objectForKey:@"showName"]) {
176         [defaults setBool:YES forKey:@"showName"];
177     }
178     
179     if (![defaults objectForKey:@"showArtist"]) {
180         [defaults setBool:YES forKey:@"showArtist"];
181     }
182     
183     if (![defaults objectForKey:@"showAlbum"]) {
184         [defaults setBool:NO forKey:@"showAlbum"];
185     }
186     
187     if (![defaults objectForKey:@"showTime"]) {
188         [defaults setBool:NO forKey:@"showTime"];
189     }
190 }
191
192 //
193 //
194
195 - (void)applicationLaunched:(NSNotification *)note
196 {
197     if (!note || [[[note userInfo] objectForKey:@"NSApplicationName"] isEqualToString:[currentRemote playerFullName]]) {
198         [NSThread detachNewThreadSelector:@selector(startTimerInNewThread) toTarget:self withObject:nil];
199         [statusItem setMenu:[self mainMenu]];
200         [self setupHotKeys];
201         isAppRunning = ITMTRemotePlayerRunning;
202         return;
203     }
204     
205     isAppRunning = ITMTRemotePlayerRunning;
206 }
207
208 - (void)applicationTerminated:(NSNotification *)note
209 {
210     if (!note || [[[note userInfo] objectForKey:@"NSApplicationName"] isEqualToString:[currentRemote playerFullName]]) {        
211         NSMenu *menu = [[NSMenu alloc] initWithTitle:@""];
212         [[menu addItemWithTitle:[NSString stringWithFormat:@"Open %@", [currentRemote playerSimpleName]] action:@selector(showPlayer:) keyEquivalent:@""] setTarget:self];
213         [menu addItem:[NSMenuItem separatorItem]];
214         [[menu addItemWithTitle:@"Preferences" action:@selector(showPreferences:) keyEquivalent:@""] setTarget:self];
215         [[menu addItemWithTitle:@"Quit" action:@selector(quitMenuTunes:) keyEquivalent:@""] setTarget:self];
216         [statusItem setMenu:[menu autorelease]];
217         
218         [refreshTimer invalidate];
219         [refreshTimer release];
220         refreshTimer = nil;
221         [self clearHotKeys];
222         isAppRunning = NO;
223         return;
224     }
225 }
226
227 - (void)startTimerInNewThread
228 {
229     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
230     NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
231     refreshTimer = [[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(timerUpdate) userInfo:nil repeats:YES] retain];
232     [runLoop run];
233     [pool release];
234 }
235
236 - (void)timerUpdate
237 {
238     ITMTRemotePlayerPlayingState playerPlayingState = [currentRemote playerPlayingState];
239     NSMenu *statusMenu = [statusItem menu];
240     int index;
241     
242     //Update play/pause menu item
243     if (playerPlayingState == ITMTRemotePlayerPlaying) {
244         index = [statusMenu indexOfItemWithTitle:@"Play"];
245         if (index > -1) {
246             [[statusMenu itemAtIndex:index] setTitle:@"Pause"];
247         }
248     } else {
249         index = [statusMenu indexOfItemWithTitle:@"Pause"];
250         if (index > -1) {
251             [[statusMenu itemAtIndex:index] setTitle:@"Play"];
252         }
253     }
254     
255     if (0 == 1/*Maybe set this to something better sometime*/) {
256         [statusItem setMenu:[self mainMenu]];
257     }
258 }
259
260 //
261 //
262
263 - (NSMenu *)mainMenu
264 {
265     NSMenu *mainMenu = [[NSMenu alloc] initWithTitle:@""];
266     NSArray *myMenu = [[NSUserDefaults standardUserDefaults] arrayForKey:@"menu"];
267     int i;
268     
269     for (i = 0; i < [myMenu count]; i++) {
270         NSString *currentItem = [myMenu objectAtIndex:i];
271         
272         if ([currentItem isEqualToString:@"Play/Pause"]) {
273             KeyCombo *tempCombo = [[NSUserDefaults standardUserDefaults] keyComboForKey:@"PlayPause"];
274             NSMenuItem *playPauseMenuItem = [mainMenu addItemWithTitle:@"Play" action:@selector(playPause:) keyEquivalent:@""];
275             [playPauseMenuItem setTarget:self];
276             
277             if (tempCombo) {
278                 [self setKeyEquivalentForCode:[tempCombo keyCode]
279                     andModifiers:[tempCombo modifiers] onItem:playPauseMenuItem];
280                 [tempCombo release];
281             }
282         } else if ([currentItem isEqualToString:@"Next Track"]) {
283             KeyCombo *tempCombo = [[NSUserDefaults standardUserDefaults] keyComboForKey:@"NextTrack"];
284             NSMenuItem *nextTrack = [mainMenu addItemWithTitle:@"Next Track" action:@selector(nextSong:) keyEquivalent:@""];
285             [nextTrack setTarget:self];
286             if (tempCombo) {
287                 [self setKeyEquivalentForCode:[tempCombo keyCode]
288                     andModifiers:[tempCombo modifiers] onItem:nextTrack];
289                 [tempCombo release];
290             }
291         } else if ([currentItem isEqualToString:@"Previous Track"]) {
292             KeyCombo *tempCombo = [[NSUserDefaults standardUserDefaults] keyComboForKey:@"PrevTrack"];
293             NSMenuItem *prevTrack = [mainMenu addItemWithTitle:@"Previous Track" action:@selector(prevSong:) keyEquivalent:@""];
294             [prevTrack setTarget:self];
295             if (tempCombo) {
296                 [self setKeyEquivalentForCode:[tempCombo keyCode]
297                     andModifiers:[tempCombo modifiers] onItem:prevTrack];
298                 [tempCombo release];
299             }
300         } else if ([currentItem isEqualToString:@"Fast Forward"]) {
301             [[mainMenu addItemWithTitle:@"Fast Forward"action:@selector(fastForward:) keyEquivalent:@""] setTarget:self];
302         } else if ([currentItem isEqualToString:@"Rewind"]) {
303             [[mainMenu addItemWithTitle:@"Rewind" action:@selector(rewind:) keyEquivalent:@""] setTarget:self];
304         } else if ([currentItem isEqualToString:@"EQ Presets"]) {
305             [[mainMenu addItemWithTitle:@"EQ Presets" action:NULL keyEquivalent:@""] setSubmenu:[self eqPresetsMenu]];
306         } else if ([currentItem isEqualToString:@"Playlists"]) {
307             [[mainMenu addItemWithTitle:@"Playlists" action:NULL keyEquivalent:@""] setSubmenu:[self playlistsMenu]];
308         } else if ([currentItem isEqualToString:@"Song Rating"]) {
309             [[mainMenu addItemWithTitle:@"Song Rating"action:NULL keyEquivalent:@""] setSubmenu:[self songRatingMenu]];
310         } else if ([currentItem isEqualToString:@"Upcoming Songs"]) {
311             [[mainMenu addItemWithTitle:@"Upcoming Songs"action:NULL keyEquivalent:@""] setSubmenu:[self upcomingSongsMenu]];
312         } else if ([currentItem isEqualToString:@"PreferencesÉ"]) {
313             [[mainMenu addItemWithTitle:@"Preferences..." action:@selector(showPreferences:) keyEquivalent:@""] setTarget:self];
314         } else if ([currentItem isEqualToString:@"Quit"]) {
315             [[mainMenu addItemWithTitle:@"Quit" action:@selector(quitMenuTunes:) keyEquivalent:@""] setTarget:self];
316         } else if ([currentItem isEqualToString:@"Current Song Info"]) {
317             //Current Song Info
318             {
319                 int currentSongIndex = [currentRemote currentSongIndex];
320                 
321                 if (currentSongIndex == 0) {
322                     [mainMenu addItemWithTitle:@"No Song" action:NULL keyEquivalent:@""];
323                 } else {
324                     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
325                     [mainMenu addItemWithTitle:@"Now Playing" action:NULL keyEquivalent:@""];
326                     
327                     if ([defaults objectForKey:@"showName"]) {
328                         [mainMenu addItemWithTitle:[NSString stringWithFormat:@"        %@", [currentRemote currentSongTitle]] action:NULL keyEquivalent:@""];
329                     }
330                     
331                     if ([defaults objectForKey:@"showAlbum"]) {
332                         [mainMenu addItemWithTitle:[NSString stringWithFormat:@"        %@", [currentRemote currentSongAlbum]] action:NULL keyEquivalent:@""];
333                     }
334                     
335                     if ([defaults objectForKey:@"showArtist"]) {
336                         [mainMenu addItemWithTitle:[NSString stringWithFormat:@"        %@", [currentRemote currentSongArtist]] action:NULL keyEquivalent:@""];
337                     }
338                     
339                     if ([defaults objectForKey:@"showTime"]) {
340                         [mainMenu addItemWithTitle:[NSString stringWithFormat:@"        %@", [currentRemote currentSongLength]] action:NULL keyEquivalent:@""];
341                     }
342                 }
343             }
344         } else if ([currentItem isEqualToString:@"<separator>"]) {
345             [mainMenu addItem:[NSMenuItem separatorItem]];
346         }
347     }
348     
349     NSLog(@"%@", mainMenu);
350     return [mainMenu autorelease];
351 }
352
353 - (NSMenu *)songRatingMenu
354 {
355     NSMenu *songRatingMenu = [[NSMenu alloc] initWithTitle:@""];
356     unichar fullstar = 0x2605;
357     unichar emptystar = 0x2606;
358     NSString *fullStarChar = [NSString stringWithCharacters:&fullstar length:1];
359     NSString *emptyStarChar = [NSString stringWithCharacters:&emptystar length:1];
360     NSMenuItem *item;
361     int currentSongRating = ([currentRemote currentSongRating] * 5);
362     
363     item = [songRatingMenu addItemWithTitle:[NSString stringWithFormat:@"%@%@%@%@%@", emptyStarChar, emptyStarChar, emptyStarChar, emptyStarChar, emptyStarChar] action:@selector(selectSongRating:) keyEquivalent:@""];
364     [item setTarget:self];
365     [item setTag:0];
366     
367     item = [songRatingMenu addItemWithTitle:[NSString stringWithFormat:@"%@%@%@%@%@", fullStarChar, emptyStarChar, emptyStarChar, emptyStarChar, emptyStarChar] action:@selector(selectSongRating:) keyEquivalent:@""];
368     [item setTarget:self];
369     [item setTag:20];
370     
371     item = [songRatingMenu addItemWithTitle:[NSString stringWithFormat:@"%@%@%@%@%@", fullStarChar, fullStarChar, emptyStarChar, emptyStarChar, emptyStarChar] action:@selector(selectSongRating:) keyEquivalent:@""];
372     [item setTarget:self];
373     [item setTag:40];
374     
375     item = [songRatingMenu addItemWithTitle:[NSString stringWithFormat:@"%@%@%@%@%@", fullStarChar, fullStarChar, fullStarChar, emptyStarChar, emptyStarChar] action:@selector(selectSongRating:) keyEquivalent:@""];
376     [item setTarget:self];
377     [item setTag:60];
378     
379     item = [songRatingMenu addItemWithTitle:[NSString stringWithFormat:@"%@%@%@%@%@", fullStarChar, fullStarChar, fullStarChar, fullStarChar, emptyStarChar] action:@selector(selectSongRating:) keyEquivalent:@""];
380     [item setTarget:self];
381     [item setTag:80];
382     
383     item = [songRatingMenu addItemWithTitle:[NSString stringWithFormat:@"%@%@%@%@%@", fullStarChar, fullStarChar, fullStarChar, fullStarChar, fullStarChar] action:@selector(selectSongRating:) keyEquivalent:@""];
384     [item setTarget:self];
385     [item setTag:100];
386     
387     [[songRatingMenu itemAtIndex:(currentSongRating / 20)] setState:NSOnState];
388     
389     return [songRatingMenu autorelease];
390 }
391
392 - (void)selectSongRating:(id)sender
393 {
394     [currentRemote setCurrentSongRating:(float)[sender tag] / 100.0];
395 }
396
397 - (NSMenu *)playlistsMenu
398 {
399     NSMenu *playlistsMenu = [[NSMenu alloc] initWithTitle:@""];
400     NSArray *playlists = [currentRemote playlists];
401     int i, currentPlaylistIndex = [currentRemote currentPlaylistIndex];
402     
403     if ([currentRemote classOfPlaylistAtIndex:currentPlaylistIndex] == ITMTRemotePlayerRadioPlaylist) {
404         currentPlaylistIndex = 0;
405     }
406     
407     for (i = 0; i < [playlists count]; i++) {
408         NSString *name = [playlists objectAtIndex:i];
409         NSMenuItem *item;
410         item = [playlistsMenu addItemWithTitle:name action:@selector(selectPlaylist:) keyEquivalent:@""];
411         [item setTarget:self];
412         [item setTag:i + 1];
413         
414         if (i + 1 == currentPlaylistIndex) {
415             [item setState:NSOnState];
416         }
417     }
418     return [playlistsMenu autorelease];
419 }
420
421 - (void)selectPlaylist:(id)sender
422 {
423     int newPlaylistIndex = [sender tag];
424     if ([currentRemote currentPlaylistIndex] + 1 != newPlaylistIndex) {
425         [currentRemote switchToPlaylistAtIndex:newPlaylistIndex];
426     }
427 }
428
429 - (NSMenu *)upcomingSongsMenu
430 {
431     NSMenu *upcomingSongsMenu;
432     int i, currentPlaylistIndex, currentPlaylistLength, currentSongIndex, songsInAdvance;
433     
434     if ([currentRemote classOfPlaylistAtIndex:currentPlaylistIndex] == ITMTRemotePlayerRadioPlaylist)
435     {
436         return nil;
437     }
438     
439     upcomingSongsMenu = [[NSMenu alloc] initWithTitle:@""];
440     currentPlaylistIndex = [currentRemote currentPlaylistIndex];
441     currentPlaylistLength = [currentRemote numberOfSongsInPlaylistAtIndex:currentPlaylistIndex];
442     currentSongIndex = [currentRemote currentSongIndex];
443     songsInAdvance = 8; //Change according to the preferences
444     
445     for (i = currentSongIndex + 1; i <= currentSongIndex + songsInAdvance; i++) {
446         if (i <= currentPlaylistLength) {
447             NSString *name = [currentRemote songTitleAtIndex:i];
448             NSMenuItem *item;
449             
450             item = [upcomingSongsMenu addItemWithTitle:name action:@selector(selectUpcomingSong:) keyEquivalent:@""];
451             [item setTarget:self];
452             [item setTag:i];
453         }
454     }
455     return [upcomingSongsMenu autorelease];    
456 }
457
458 - (void)selectUpcomingSong:(id)sender
459 {
460     [currentRemote switchToSongAtIndex:[sender tag]];
461 }
462
463 - (NSMenu *)eqPresetsMenu
464 {
465     NSMenu *eqPresetsMenu = [[NSMenu alloc] initWithTitle:@""];
466     NSArray *eqPresets = [currentRemote eqPresets];
467     int i, currentPresetIndex = [currentRemote currentEQPresetIndex];
468     
469     NSMenuItem *eqEnabledMenuItem;
470     
471     eqEnabledMenuItem = [eqPresetsMenu addItemWithTitle:@"Enabled" action:@selector(selectEQPreset:) keyEquivalent:@""];
472     [eqEnabledMenuItem setTarget:self];
473     [eqEnabledMenuItem setTag:-1];
474     if ([currentRemote equalizerEnabled] == YES) {
475         [eqEnabledMenuItem setState:NSOnState];
476     }
477     
478     [eqPresetsMenu addItem:[NSMenuItem separatorItem]];
479     
480     for (i = 0; i < [eqPresets count]; i++) {
481         NSString *name = [eqPresets objectAtIndex:i];
482         NSMenuItem *item;
483         
484         item = [eqPresetsMenu addItemWithTitle:name action:@selector(selectEQPreset:) keyEquivalent:@""];
485         [item setTarget:self];
486         [item setTag:i];
487         
488         if (currentPresetIndex == i) {
489             [item setState:NSOnState];
490         }
491     }
492     return [eqPresetsMenu autorelease];
493 }
494
495 - (void)selectEQPreset:(id)sender
496 {
497     int newEQPresetIndex = [sender tag];
498     
499     if (newEQPresetIndex == -1) {
500         [currentRemote setEqualizerEnabled:![currentRemote equalizerEnabled]];
501     }
502     
503     if ([currentRemote currentEQPresetIndex] + 1 != newEQPresetIndex) {
504         [currentRemote switchToEQAtIndex:newEQPresetIndex];
505     }
506 }
507
508 //
509 //
510
511 - (void)clearHotKeys
512 {
513     [[HotKeyCenter sharedCenter] removeHotKey:@"PlayPause"];
514     [[HotKeyCenter sharedCenter] removeHotKey:@"NextTrack"];
515     [[HotKeyCenter sharedCenter] removeHotKey:@"PrevTrack"];
516     [[HotKeyCenter sharedCenter] removeHotKey:@"TrackInfo"];
517     [[HotKeyCenter sharedCenter] removeHotKey:@"UpcomingSongs"];
518 }
519
520 - (void)setupHotKeys
521 {
522     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
523     
524     if ([defaults objectForKey:@"PlayPause"] != nil) {
525         [[HotKeyCenter sharedCenter] addHotKey:@"PlayPause"
526                 combo:[defaults keyComboForKey:@"PlayPause"]
527                 target:self action:@selector(playPause:)];
528     }
529     
530     if ([defaults objectForKey:@"NextTrack"] != nil) {
531         [[HotKeyCenter sharedCenter] addHotKey:@"NextTrack"
532                 combo:[defaults keyComboForKey:@"NextTrack"]
533                 target:self action:@selector(nextSong:)];
534     }
535     
536     if ([defaults objectForKey:@"PrevTrack"] != nil) {
537         [[HotKeyCenter sharedCenter] addHotKey:@"PrevTrack"
538                 combo:[defaults keyComboForKey:@"PrevTrack"]
539                 target:self action:@selector(prevSong:)];
540     }
541     
542     if ([defaults objectForKey:@"TrackInfo"] != nil) {
543         [[HotKeyCenter sharedCenter] addHotKey:@"TrackInfo"
544                 combo:[defaults keyComboForKey:@"TrackInfo"]
545                 target:self action:@selector(showCurrentTrackInfo)];
546     }
547     
548     if ([defaults objectForKey:@"UpcomingSongs"] != nil) {
549         [[HotKeyCenter sharedCenter] addHotKey:@"UpcomingSongs"
550                combo:[defaults keyComboForKey:@"UpcomingSongs"]
551                target:self action:@selector(showUpcomingSongs)];
552     }
553 }
554
555 //
556 //
557
558 - (void)playPause:(id)sender
559 {
560     ITMTRemotePlayerPlayingState state = [currentRemote playerPlayingState];
561     NSMenu *statusMenu = [statusItem menu];
562     
563     if (state == ITMTRemotePlayerPlaying) {
564         [currentRemote pause];
565         [[statusMenu itemAtIndex:[statusMenu indexOfItemWithTitle:@"Pause"]] setTitle:@"Play"];
566     } else if ((state == ITMTRemotePlayerForwarding) || (state == ITMTRemotePlayerRewinding)) {
567         [currentRemote pause];
568         [currentRemote play];
569     } else {
570         [currentRemote play];
571         [[statusMenu itemAtIndex:[statusMenu indexOfItemWithTitle:@"Play"]] setTitle:@"Pause"];
572     }
573 }
574
575 - (void)nextSong:(id)sender
576 {
577     [currentRemote goToNextSong];
578 }
579
580 - (void)prevSong:(id)sender
581 {
582     [currentRemote goToPreviousSong];
583 }
584
585 - (void)fastForward:(id)sender
586 {
587     [currentRemote forward];
588 }
589
590 - (void)rewind:(id)sender
591 {
592     [currentRemote rewind];
593 }
594
595 - (void)toggleEqualizer
596 {
597     [currentRemote setEqualizerEnabled:![currentRemote equalizerEnabled]];
598 }
599
600 - (void)quitMenuTunes:(id)sender
601 {
602     [NSApp terminate:self];
603 }
604
605 - (void)showPreferences:(id)sender
606 {
607     if (!prefsController) {
608         prefsController = [[PreferencesController alloc] initWithMenuTunes:self];
609         [self clearHotKeys];
610     }
611 }
612
613 - (void)closePreferences
614 {
615     if ( ( isAppRunning == ITMTRemotePlayerRunning) ) {
616         [self setupHotKeys];
617     }
618     [prefsController release];
619     prefsController = nil;
620 }
621
622 - (void)showPlayer:(id)sender
623 {
624     if ( ( isAppRunning == ITMTRemotePlayerRunning) ) {
625         [currentRemote showPrimaryInterface];
626     } else {
627         if (![[NSWorkspace sharedWorkspace] launchApplication:[currentRemote playerFullName]]) {
628             NSLog(@"Error Launching Player");
629         }
630     }
631 }
632
633 //
634 //
635
636 //The status window methods go here!
637
638 //
639 //
640
641 - (void)setKeyEquivalentForCode:(short)code andModifiers:(long)modifiers
642         onItem:(NSMenuItem *)item
643 {
644     unichar charcode = 'a';
645     int i;
646     long cocoaModifiers = 0;
647     static long carbonToCocoa[6][2] = 
648     {
649         { cmdKey, NSCommandKeyMask },
650         { optionKey, NSAlternateKeyMask },
651         { controlKey, NSControlKeyMask },
652         { shiftKey, NSShiftKeyMask },
653     };
654     
655     for (i = 0; i < 6; i++) {
656         if (modifiers & carbonToCocoa[i][0]) {
657             cocoaModifiers += carbonToCocoa[i][1];
658         }
659     }
660     [item setKeyEquivalentModifierMask:cocoaModifiers];
661     
662     //Missing key combos for some keys. Must find them later.
663     switch (code)
664     {
665         case 36:
666             charcode = '\r';
667         break;
668         
669         case 48:
670             charcode = '\t';
671         break;
672         
673         //Space -- ARGH!
674         case 49:
675         {
676             /*MenuRef menuRef = _NSGetCarbonMenu([item menu]);
677             NSLog(@"%@", menuRef);
678             SetMenuItemCommandKey(menuRef, 0, NO, 49);
679             SetMenuItemModifiers(menuRef, 0, kMenuNoCommandModifier);
680             SetMenuItemKeyGlyph(menuRef, 0, kMenuBlankGlyph);
681             charcode = 'b';*/
682         }
683         break;
684         
685         case 51:
686             charcode = NSDeleteFunctionKey;
687         break;
688         
689         case 53:
690             charcode = '\e';
691         break;
692         
693         case 71:
694             charcode = '\e';
695         break;
696         
697         case 76:
698             charcode = '\r';
699         break;
700         
701         case 96:
702             charcode = NSF5FunctionKey;
703         break;
704         
705         case 97:
706             charcode = NSF6FunctionKey;
707         break;
708         
709         case 98:
710             charcode = NSF7FunctionKey;
711         break;
712         
713         case 99:
714             charcode = NSF3FunctionKey;
715         break;
716         
717         case 100:
718             charcode = NSF8FunctionKey;
719         break;
720         
721         case 101:
722             charcode = NSF9FunctionKey;
723         break;
724         
725         case 103:
726             charcode = NSF11FunctionKey;
727         break;
728         
729         case 105:
730             charcode = NSF3FunctionKey;
731         break;
732         
733         case 107:
734             charcode = NSF14FunctionKey;
735         break;
736         
737         case 109:
738             charcode = NSF10FunctionKey;
739         break;
740         
741         case 111:
742             charcode = NSF12FunctionKey;
743         break;
744         
745         case 113:
746             charcode = NSF13FunctionKey;
747         break;
748         
749         case 114:
750             charcode = NSInsertFunctionKey;
751         break;
752         
753         case 115:
754             charcode = NSHomeFunctionKey;
755         break;
756         
757         case 116:
758             charcode = NSPageUpFunctionKey;
759         break;
760         
761         case 117:
762             charcode = NSDeleteFunctionKey;
763         break;
764         
765         case 118:
766             charcode = NSF4FunctionKey;
767         break;
768         
769         case 119:
770             charcode = NSEndFunctionKey;
771         break;
772         
773         case 120:
774             charcode = NSF2FunctionKey;
775         break;
776         
777         case 121:
778             charcode = NSPageDownFunctionKey;
779         break;
780         
781         case 122:
782             charcode = NSF1FunctionKey;
783         break;
784         
785         case 123:
786             charcode = NSLeftArrowFunctionKey;
787         break;
788         
789         case 124:
790             charcode = NSRightArrowFunctionKey;
791         break;
792         
793         case 125:
794             charcode = NSDownArrowFunctionKey;
795         break;
796         
797         case 126:
798             charcode = NSUpArrowFunctionKey;
799         break;
800     }
801     
802     if (charcode == 'a') {
803         unsigned long state;
804         long keyTrans;
805         char charCode;
806         Ptr kchr;
807         state = 0;
808         kchr = (Ptr) GetScriptVariable(smCurrentScript, smKCHRCache);
809         keyTrans = KeyTranslate(kchr, code, &state);
810         charCode = keyTrans;
811         [item setKeyEquivalent:[NSString stringWithCString:&charCode length:1]];
812     } else if (charcode != 'b') {
813         [item setKeyEquivalent:[NSString stringWithCharacters:&charcode length:1]];
814     }
815 }
816
817 @end