5 // Created by Joseph Spiros on Wed Apr 30 2003.
6 // Copyright (c) 2003 iThink Software. All rights reserved.
9 #import "MenuController.h"
10 #import "NewMainController.h"
11 #import "HotKeyCenter.h"
14 @interface MenuController (SubmenuMethods)
15 - (NSMenu *)ratingMenu;
16 - (NSMenu *)upcomingSongsMenu;
17 - (NSMenu *)playlistsMenu;
19 - (void)setKeyEquivalentForCode:(short)code andModifiers:(long)modifiers
20 onItem:(NSMenuItem *)item;
23 @implementation MenuController
27 if ( (self = [super init]) ) {
28 _menuLayout = [[NSMutableArray alloc] initWithCapacity:0];
35 NSMenu *menu = [[NSMenu alloc] initWithTitle:@""];
36 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
37 NSArray *menuArray = [defaults arrayForKey:@"menu"];
38 NSEnumerator *enumerator = [menuArray objectEnumerator];
41 NSEnumerator *itemEnum;
45 _currentPlaylist = [currentRemote currentPlaylistIndex];
46 _playingRadio = ([currentRemote currentPlaylistClass] == ITMTRemotePlayerRadioPlaylist);
48 //Kill the old submenu items
49 if ( (tempItem = [_currentMenu itemWithTag:1]) ) {
50 [tempItem setSubmenu:nil];
53 if ( (tempItem = [_currentMenu itemWithTag:2]) ) {
54 [tempItem setSubmenu:nil];
57 if ( (tempItem = [_currentMenu itemWithTag:3]) ) {
58 [tempItem setSubmenu:nil];
61 if ( (tempItem = [_currentMenu itemWithTag:4]) ) {
62 [tempItem setSubmenu:nil];
66 while ( (nextObject = [enumerator nextObject]) ) {
68 if ([nextObject isEqualToString:@"playPause"]) {
69 tempItem = [menu addItemWithTitle:NSLocalizedString(@"play", @"Play")
70 action:@selector(performMainMenuAction:)
72 [tempItem setTag:MTMenuPlayPauseItem];
73 [tempItem setTarget:self];
75 if ( (keyCombo = [[HotKeyCenter sharedCenter] keyComboForName:@"PlayPause"]) ) {
76 [self setKeyEquivalentForCode:[keyCombo keyCode]
77 andModifiers:[keyCombo modifiers]
81 switch ([currentRemote playerPlayingState]) {
82 case ITMTRemotePlayerPlaying:
83 [tempItem setTitle:NSLocalizedString(@"pause", @"Pause")];
85 case ITMTRemotePlayerRewinding:
86 case ITMTRemotePlayerForwarding:
87 [tempItem setTitle:NSLocalizedString(@"resume", @"Resume")];
92 } else if ([nextObject isEqualToString:@"nextTrack"]) {
93 tempItem = [menu addItemWithTitle:NSLocalizedString(@"nextTrack", @"Next Track")
94 action:@selector(performMainMenuAction:)
97 if ( (keyCombo = [[HotKeyCenter sharedCenter] keyComboForName:@"NextTrack"]) ) {
98 [self setKeyEquivalentForCode:[keyCombo keyCode]
99 andModifiers:[keyCombo modifiers]
103 if (_currentPlaylist) {
104 [tempItem setTag:MTMenuNextTrackItem];
105 [tempItem setTarget:self];
107 } else if ([nextObject isEqualToString:@"prevTrack"]) {
108 tempItem = [menu addItemWithTitle:NSLocalizedString(@"prevTrack", @"Previous Track")
109 action:@selector(performMainMenuAction:)
112 if ( (keyCombo = [[HotKeyCenter sharedCenter] keyComboForName:@"PrevTrack"]) ) {
113 [self setKeyEquivalentForCode:[keyCombo keyCode]
114 andModifiers:[keyCombo modifiers]
118 if (_currentPlaylist) {
119 [tempItem setTag:MTMenuPreviousTrackItem];
120 [tempItem setTarget:self];
122 } else if ([nextObject isEqualToString:@"fastForward"]) {
123 tempItem = [menu addItemWithTitle:NSLocalizedString(@"fastForward", @"Fast Forward")
124 action:@selector(performMainMenuAction:)
126 if (_currentPlaylist) {
127 [tempItem setTag:MTMenuFastForwardItem];
128 [tempItem setTarget:self];
130 } else if ([nextObject isEqualToString:@"rewind"]) {
131 tempItem = [menu addItemWithTitle:NSLocalizedString(@"rewind", @"Rewind")
132 action:@selector(performMainMenuAction:)
134 if (_currentPlaylist) {
135 [tempItem setTag:MTMenuRewindItem];
136 [tempItem setTarget:self];
138 } else if ([nextObject isEqualToString:@"showPlayer"]) {
139 tempItem = [menu addItemWithTitle:[NSString stringWithFormat:@"%@ %@",
140 NSLocalizedString(@"show", @"Show"),
141 [[[MainController sharedController] currentRemote] playerSimpleName]]
142 action:@selector(performMainMenuAction:)
145 if ( (keyCombo = [[HotKeyCenter sharedCenter] keyComboForName:@"ShowPlayer"]) ) {
146 [self setKeyEquivalentForCode:[keyCombo keyCode]
147 andModifiers:[keyCombo modifiers]
151 [tempItem setTarget:self];
152 [tempItem setTag:MTMenuShowPlayerItem];
153 } else if ([nextObject isEqualToString:@"preferences"]) {
154 tempItem = [menu addItemWithTitle:NSLocalizedString(@"preferences", @"Preferences...")
155 action:@selector(performMainMenuAction:)
157 [tempItem setTag:MTMenuPreferencesItem];
158 [tempItem setTarget:self];
159 } else if ([nextObject isEqualToString:@"quit"]) {
160 tempItem = [menu addItemWithTitle:NSLocalizedString(@"quit", @"Quit")
161 action:@selector(performMainMenuAction:)
163 [tempItem setTag:MTMenuQuitItem];
164 [tempItem setTarget:self];
165 } else if ([nextObject isEqualToString:@"trackInfo"]) {
166 //Handle playing radio too
167 if (_currentPlaylist) {
168 NSString *title = [currentRemote currentSongTitle];
170 [menu addItemWithTitle:NSLocalizedString(@"nowPlaying", @"Now Playing") action:NULL keyEquivalent:@""];
172 if ([title length] > 0) {
173 [menu addItemWithTitle:[NSString stringWithFormat:@" %@", title]
178 if ([defaults boolForKey:@"showAlbum"]) {
179 [menu addItemWithTitle:[NSString stringWithFormat:@" %@", [currentRemote currentSongAlbum]]
184 if ([defaults boolForKey:@"showArtist"]) {
185 [menu addItemWithTitle:[NSString stringWithFormat:@" %@", [currentRemote currentSongArtist]]
190 if ([defaults boolForKey:@"showTrackNumber"]) {
191 int track = [currentRemote currentSongTrack];
193 [menu addItemWithTitle:[NSString stringWithFormat:@" %@ %i", NSLocalizedString(@"track", @"Track"), track]
199 if ([defaults boolForKey:@"showTime"]) {
200 int left = [[currentRemote currentSongRemaining] intValue];
201 NSString *remaining = [NSString stringWithFormat:@"%i:%02i", left / 60, left % 60];
202 [menu addItemWithTitle:[NSString stringWithFormat:@" %@/%@", remaining, [currentRemote currentSongLength]]
207 [menu addItemWithTitle:NSLocalizedString(@"noSong", @"No Song") action:NULL keyEquivalent:@""];
209 } else if ([nextObject isEqualToString:@"separator"]) {
210 [menu addItem:[NSMenuItem separatorItem]];
212 } else if ([nextObject isEqualToString:@"songRating"]) {
213 tempItem = [menu addItemWithTitle:NSLocalizedString(@"songRating", @"Song Rating")
216 [tempItem setSubmenu:_ratingMenu];
218 if (_playingRadio || !_currentPlaylist) {
219 [tempItem setEnabled:NO];
222 itemEnum = [[_ratingMenu itemArray] objectEnumerator];
223 while ( (tempItem = [itemEnum nextObject]) ) {
224 [tempItem setState:NSOffState];
227 [[_ratingMenu itemAtIndex:([currentRemote currentSongRating] * 5)] setState:NSOnState];
228 } else if ([nextObject isEqualToString:@"upcomingSongs"]) {
229 tempItem = [menu addItemWithTitle:NSLocalizedString(@"upcomingSongs", @"Upcoming Songs")
232 [tempItem setSubmenu:_upcomingSongsMenu];
234 if (_playingRadio || !_currentPlaylist) {
235 [tempItem setEnabled:NO];
237 } else if ([nextObject isEqualToString:@"playlists"]) {
238 tempItem = [menu addItemWithTitle:NSLocalizedString(@"playlists", @"Playlists")
241 [tempItem setSubmenu:_playlistsMenu];
243 } else if ([nextObject isEqualToString:@"eqPresets"]) {
244 tempItem = [menu addItemWithTitle:NSLocalizedString(@"eqPresets", @"EQ Presets")
247 [tempItem setSubmenu:_eqMenu];
250 itemEnum = [[_eqMenu itemArray] objectEnumerator];
251 while ( (tempItem = [itemEnum nextObject]) ) {
252 [tempItem setState:NSOffState];
254 [[_eqMenu itemAtIndex:([currentRemote currentEQPresetIndex] - 1)] setState:NSOnState];
257 [_currentMenu release];
262 - (NSMenu *)menuForNoPlayer
264 NSMenu *menu = [[NSMenu alloc] initWithTitle:@""];
265 NSMenuItem *tempItem;
266 tempItem = [menu addItemWithTitle:[NSString stringWithFormat:@"%@ %@", NSLocalizedString(@"open", @"Open"), [[[MainController sharedController] currentRemote] playerSimpleName]] action:@selector(performMainMenuAction:) keyEquivalent:@""];
267 [tempItem setTag:MTMenuShowPlayerItem];
268 [tempItem setTarget:self];
269 [menu addItem:[NSMenuItem separatorItem]];
270 tempItem = [menu addItemWithTitle:NSLocalizedString(@"preferences", @"Preferences...") action:@selector(performMainMenuAction:) keyEquivalent:@""];
271 [tempItem setTag:MTMenuPreferencesItem];
272 [tempItem setTarget:self];
273 tempItem = [menu addItemWithTitle:NSLocalizedString(@"quit", @"Quit") action:@selector(performMainMenuAction:) keyEquivalent:@""];
274 [tempItem setTag:MTMenuQuitItem];
275 [tempItem setTarget:self];
276 return [menu autorelease];
279 - (void)rebuildSubmenus
281 currentRemote = [[MainController sharedController] currentRemote];
282 _currentPlaylist = [currentRemote currentPlaylistIndex];
283 _currentTrack = [currentRemote currentSongIndex];
284 _playingRadio = ([currentRemote currentPlaylistClass] == ITMTRemotePlayerRadioPlaylist);
286 [_ratingMenu release];
287 [_upcomingSongsMenu release];
288 [_playlistsMenu release];
290 _ratingMenu = [self ratingMenu];
291 _upcomingSongsMenu = [self upcomingSongsMenu];
292 _playlistsMenu = [self playlistsMenu];
293 _eqMenu = [self eqMenu];
296 - (NSMenu *)ratingMenu
298 NSMenu *ratingMenu = [[NSMenu alloc] initWithTitle:@""];
299 NSEnumerator *itemEnum;
302 SEL itemSelector = @selector(performRatingMenuAction:);
304 [ratingMenu addItemWithTitle:[NSString stringWithUTF8String:"☆☆☆☆☆"] action:nil keyEquivalent:@""];
305 [ratingMenu addItemWithTitle:[NSString stringWithUTF8String:"★☆☆☆☆"] action:nil keyEquivalent:@""];
306 [ratingMenu addItemWithTitle:[NSString stringWithUTF8String:"★★☆☆☆"] action:nil keyEquivalent:@""];
307 [ratingMenu addItemWithTitle:[NSString stringWithUTF8String:"★★★☆☆"] action:nil keyEquivalent:@""];
308 [ratingMenu addItemWithTitle:[NSString stringWithUTF8String:"★★★★☆"] action:nil keyEquivalent:@""];
309 [ratingMenu addItemWithTitle:[NSString stringWithUTF8String:"★★★★★"] action:nil keyEquivalent:@""];
311 itemEnum = [[ratingMenu itemArray] objectEnumerator];
312 while ( (anItem = [itemEnum nextObject]) ) {
313 [anItem setAction:itemSelector];
314 [anItem setTarget:self];
315 [anItem setTag:itemTag];
321 - (NSMenu *)upcomingSongsMenu
323 NSMenu *upcomingSongsMenu = [[NSMenu alloc] initWithTitle:@""];
324 int numSongs = [currentRemote numberOfSongsInPlaylistAtIndex:_currentPlaylist];
325 int numSongsInAdvance = [[NSUserDefaults standardUserDefaults] integerForKey:@"SongsInAdvance"];
327 if (_currentPlaylist && !_playingRadio) {
331 for (i = _currentTrack + 1; i <= _currentTrack + numSongsInAdvance; i++) {
333 NSString *curSong = [currentRemote songTitleAtIndex:i];
334 NSMenuItem *songItem;
335 songItem = [upcomingSongsMenu addItemWithTitle:curSong action:@selector(performUpcomingSongsMenuAction:) keyEquivalent:@""];
337 [songItem setTarget:self];
344 return upcomingSongsMenu;
347 - (NSMenu *)playlistsMenu
349 NSMenu *playlistsMenu = [[NSMenu alloc] initWithTitle:@""];
350 NSArray *playlists = [currentRemote playlists];
351 NSMenuItem *tempItem;
354 for (i = 0; i < [playlists count]; i++) {
355 tempItem = [playlistsMenu addItemWithTitle:[playlists objectAtIndex:i] action:@selector(performPlaylistMenuAction:) keyEquivalent:@""];
356 [tempItem setTag:i + 1];
357 [tempItem setTarget:self];
360 if (!_playingRadio && _currentPlaylist) {
361 [[playlistsMenu itemAtIndex:_currentPlaylist - 1] setState:NSOnState];
363 return playlistsMenu;
368 NSMenu *eqMenu = [[NSMenu alloc] initWithTitle:@""];
369 NSArray *eqPresets = [currentRemote eqPresets];
370 NSMenuItem *tempItem;
373 for (i = 0; i < [eqPresets count]; i++) {
375 if ( ( name = [eqPresets objectAtIndex:i] ) ) {
376 tempItem = [eqMenu addItemWithTitle:name action:@selector(performEqualizerMenuAction:) keyEquivalent:@""];
378 [tempItem setTarget:self];
384 - (void)performMainMenuAction:(id)sender
386 switch ( [sender tag] )
388 case MTMenuPlayPauseItem:
389 NSLog(@"MenuController: Play/Pause");
390 [[MainController sharedController] playPause];
392 case MTMenuFastForwardItem:
393 NSLog(@"MenuController: Fast Forward");
394 [[MainController sharedController] fastForward];
396 case MTMenuRewindItem:
397 NSLog(@"MenuController: Rewind");
398 [[MainController sharedController] rewind];
400 case MTMenuPreviousTrackItem:
401 NSLog(@"MenuController: Previous Track");
402 [[MainController sharedController] prevSong];
404 case MTMenuNextTrackItem:
405 NSLog(@"MenuController: Next Track");
406 [[MainController sharedController] nextSong];
408 case MTMenuShowPlayerItem:
409 NSLog(@"MainController: Show Main Interface");
410 [[MainController sharedController] showPlayer];
412 case MTMenuPreferencesItem:
413 NSLog(@"MenuController: Preferences...");
414 [[MainController sharedController] showPreferences];
417 NSLog(@"MenuController: Quit");
418 [[MainController sharedController] quitMenuTunes];
421 NSLog(@"MenuController: Unimplemented Menu Item OR Child-bearing Menu Item");
426 - (void)performRatingMenuAction:(id)sender
428 [[MainController sharedController] selectSongRating:[sender tag]];
431 - (void)performPlaylistMenuAction:(id)sender
433 [[MainController sharedController] selectPlaylistAtIndex:[sender tag]];
436 - (void)performEqualizerMenuAction:(id)sender
438 [[MainController sharedController] selectEQPresetAtIndex:[sender tag]];
441 - (void)performUpcomingSongsMenuAction:(id)sender
443 [[MainController sharedController] selectSongAtIndex:[sender tag]];
449 [_currentMenu update];
452 - (BOOL)validateMenuItem:(id <NSMenuItem>)menuItem
457 - (NSString *)systemUIColor
459 NSDictionary *tmpDict;
461 if ( (tmpDict = [NSDictionary dictionaryWithContentsOfFile:[@"~/Library/Preferences/.GlobalPreferences.plist" stringByExpandingTildeInPath]]) ) {
462 if ( (tmpNumber = [tmpDict objectForKey:@"AppleAquaColorVariant"]) ) {
463 if ( ([tmpNumber intValue] == 1) ) {
476 - (void)setKeyEquivalentForCode:(short)code andModifiers:(long)modifiers
477 onItem:(NSMenuItem *)item
479 unichar charcode = 'a';
481 long cocoaModifiers = 0;
482 static long carbonToCocoa[6][2] =
484 { cmdKey, NSCommandKeyMask },
485 { optionKey, NSAlternateKeyMask },
486 { controlKey, NSControlKeyMask },
487 { shiftKey, NSShiftKeyMask },
490 for (i = 0; i < 6; i++) {
491 if (modifiers & carbonToCocoa[i][0]) {
492 cocoaModifiers += carbonToCocoa[i][1];
495 [item setKeyEquivalentModifierMask:cocoaModifiers];
497 //Missing key combos for some keys. Must find them later.
511 // Haven't tested this, though it should work.
512 // This doesn't work. :'(
514 [[NSString stringWithString:@"Space"] getCharacters:&buffer];
516 /*MenuRef menuRef = _NSGetCarbonMenu([item menu]);
517 NSLog(@"%@", menuRef);
518 SetMenuItemCommandKey(menuRef, 0, NO, 49);
519 SetMenuItemModifiers(menuRef, 0, kMenuNoCommandModifier);
520 SetMenuItemKeyGlyph(menuRef, 0, kMenuBlankGlyph);
527 charcode = NSDeleteFunctionKey;
543 charcode = NSF5FunctionKey;
547 charcode = NSF6FunctionKey;
551 charcode = NSF7FunctionKey;
555 charcode = NSF3FunctionKey;
559 charcode = NSF8FunctionKey;
563 charcode = NSF9FunctionKey;
567 charcode = NSF11FunctionKey;
571 charcode = NSF3FunctionKey;
575 charcode = NSF14FunctionKey;
579 charcode = NSF10FunctionKey;
583 charcode = NSF12FunctionKey;
587 charcode = NSF13FunctionKey;
591 charcode = NSInsertFunctionKey;
595 charcode = NSHomeFunctionKey;
599 charcode = NSPageUpFunctionKey;
603 charcode = NSDeleteFunctionKey;
607 charcode = NSF4FunctionKey;
611 charcode = NSEndFunctionKey;
615 charcode = NSF2FunctionKey;
619 charcode = NSPageDownFunctionKey;
623 charcode = NSF1FunctionKey;
627 charcode = NSLeftArrowFunctionKey;
631 charcode = NSRightArrowFunctionKey;
635 charcode = NSDownArrowFunctionKey;
639 charcode = NSUpArrowFunctionKey;
643 if (charcode == 'a') {
649 kchr = (Ptr) GetScriptVariable(smCurrentScript, smKCHRCache);
650 keyTrans = KeyTranslate(kchr, code, &state);
652 [item setKeyEquivalent:[NSString stringWithCString:&charCode length:1]];
653 } else if (charcode != 'b') {
654 [item setKeyEquivalent:[NSString stringWithCharacters:&charcode length:1]];