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 NSString *curAlbum = [currentRemote currentSongAlbum];
180 if ([curAlbum length]) {
181 [menu addItemWithTitle:[NSString stringWithFormat:@" %@", curAlbum]
187 if ([defaults boolForKey:@"showArtist"]) {
188 NSString *curArtist = [currentRemote currentSongArtist];
189 if ([curArtist length]) {
190 [menu addItemWithTitle:[NSString stringWithFormat:@" %@", curArtist]
196 if ([defaults boolForKey:@"showTrackNumber"]) {
197 int track = [currentRemote currentSongTrack];
199 [menu addItemWithTitle:[NSString stringWithFormat:@" %@ %i", NSLocalizedString(@"track", @"Track"), track]
205 if ([defaults boolForKey:@"showTime"]) {
206 int left = [[currentRemote currentSongRemaining] intValue];
207 NSString *remaining = [NSString stringWithFormat:@"%i:%02i", left / 60, left % 60];
208 [menu addItemWithTitle:[NSString stringWithFormat:@" %@/%@", remaining, [currentRemote currentSongLength]]
213 [menu addItemWithTitle:NSLocalizedString(@"noSong", @"No Song") action:NULL keyEquivalent:@""];
215 } else if ([nextObject isEqualToString:@"separator"]) {
216 [menu addItem:[NSMenuItem separatorItem]];
218 } else if ([nextObject isEqualToString:@"songRating"]) {
219 tempItem = [menu addItemWithTitle:NSLocalizedString(@"songRating", @"Song Rating")
222 [tempItem setSubmenu:_ratingMenu];
224 if (_playingRadio || !_currentPlaylist) {
225 [tempItem setEnabled:NO];
228 itemEnum = [[_ratingMenu itemArray] objectEnumerator];
229 while ( (tempItem = [itemEnum nextObject]) ) {
230 [tempItem setState:NSOffState];
233 [[_ratingMenu itemAtIndex:([currentRemote currentSongRating] * 5)] setState:NSOnState];
234 } else if ([nextObject isEqualToString:@"upcomingSongs"]) {
235 tempItem = [menu addItemWithTitle:NSLocalizedString(@"upcomingSongs", @"Upcoming Songs")
238 [tempItem setSubmenu:_upcomingSongsMenu];
240 if (_playingRadio || !_currentPlaylist) {
241 [tempItem setEnabled:NO];
243 } else if ([nextObject isEqualToString:@"playlists"]) {
244 tempItem = [menu addItemWithTitle:NSLocalizedString(@"playlists", @"Playlists")
247 [tempItem setSubmenu:_playlistsMenu];
249 } else if ([nextObject isEqualToString:@"eqPresets"]) {
250 tempItem = [menu addItemWithTitle:NSLocalizedString(@"eqPresets", @"EQ Presets")
253 [tempItem setSubmenu:_eqMenu];
256 itemEnum = [[_eqMenu itemArray] objectEnumerator];
257 while ( (tempItem = [itemEnum nextObject]) ) {
258 [tempItem setState:NSOffState];
260 [[_eqMenu itemAtIndex:([currentRemote currentEQPresetIndex] - 1)] setState:NSOnState];
263 [_currentMenu release];
268 - (NSMenu *)menuForNoPlayer
270 NSMenu *menu = [[NSMenu alloc] initWithTitle:@""];
271 NSMenuItem *tempItem;
272 tempItem = [menu addItemWithTitle:[NSString stringWithFormat:@"%@ %@", NSLocalizedString(@"open", @"Open"), [[[MainController sharedController] currentRemote] playerSimpleName]] action:@selector(performMainMenuAction:) keyEquivalent:@""];
273 [tempItem setTag:MTMenuShowPlayerItem];
274 [tempItem setTarget:self];
275 [menu addItem:[NSMenuItem separatorItem]];
276 tempItem = [menu addItemWithTitle:NSLocalizedString(@"preferences", @"Preferences...") action:@selector(performMainMenuAction:) keyEquivalent:@""];
277 [tempItem setTag:MTMenuPreferencesItem];
278 [tempItem setTarget:self];
279 tempItem = [menu addItemWithTitle:NSLocalizedString(@"quit", @"Quit") action:@selector(performMainMenuAction:) keyEquivalent:@""];
280 [tempItem setTag:MTMenuQuitItem];
281 [tempItem setTarget:self];
282 return [menu autorelease];
285 - (void)rebuildSubmenus
287 currentRemote = [[MainController sharedController] currentRemote];
288 _currentPlaylist = [currentRemote currentPlaylistIndex];
289 _currentTrack = [currentRemote currentSongIndex];
290 _playingRadio = ([currentRemote currentPlaylistClass] == ITMTRemotePlayerRadioPlaylist);
292 [_ratingMenu release];
293 [_upcomingSongsMenu release];
294 [_playlistsMenu release];
296 _ratingMenu = [self ratingMenu];
297 _upcomingSongsMenu = [self upcomingSongsMenu];
298 _playlistsMenu = [self playlistsMenu];
299 _eqMenu = [self eqMenu];
302 - (NSMenu *)ratingMenu
304 NSMenu *ratingMenu = [[NSMenu alloc] initWithTitle:@""];
305 NSEnumerator *itemEnum;
308 SEL itemSelector = @selector(performRatingMenuAction:);
310 [ratingMenu addItemWithTitle:[NSString stringWithUTF8String:"☆☆☆☆☆"] action:nil keyEquivalent:@""];
311 [ratingMenu addItemWithTitle:[NSString stringWithUTF8String:"★☆☆☆☆"] action:nil keyEquivalent:@""];
312 [ratingMenu addItemWithTitle:[NSString stringWithUTF8String:"★★☆☆☆"] action:nil keyEquivalent:@""];
313 [ratingMenu addItemWithTitle:[NSString stringWithUTF8String:"★★★☆☆"] action:nil keyEquivalent:@""];
314 [ratingMenu addItemWithTitle:[NSString stringWithUTF8String:"★★★★☆"] action:nil keyEquivalent:@""];
315 [ratingMenu addItemWithTitle:[NSString stringWithUTF8String:"★★★★★"] action:nil keyEquivalent:@""];
317 itemEnum = [[ratingMenu itemArray] objectEnumerator];
318 while ( (anItem = [itemEnum nextObject]) ) {
319 [anItem setAction:itemSelector];
320 [anItem setTarget:self];
321 [anItem setTag:itemTag];
327 - (NSMenu *)upcomingSongsMenu
329 NSMenu *upcomingSongsMenu = [[NSMenu alloc] initWithTitle:@""];
330 int numSongs = [currentRemote numberOfSongsInPlaylistAtIndex:_currentPlaylist];
331 int numSongsInAdvance = [[NSUserDefaults standardUserDefaults] integerForKey:@"SongsInAdvance"];
333 if (_currentPlaylist && !_playingRadio) {
337 for (i = _currentTrack + 1; i <= _currentTrack + numSongsInAdvance; i++) {
339 NSString *curSong = [currentRemote songTitleAtIndex:i];
340 NSMenuItem *songItem;
341 songItem = [upcomingSongsMenu addItemWithTitle:curSong action:@selector(performUpcomingSongsMenuAction:) keyEquivalent:@""];
343 [songItem setTarget:self];
350 return upcomingSongsMenu;
353 - (NSMenu *)playlistsMenu
355 NSMenu *playlistsMenu = [[NSMenu alloc] initWithTitle:@""];
356 NSArray *playlists = [currentRemote playlists];
357 NSMenuItem *tempItem;
360 for (i = 0; i < [playlists count]; i++) {
361 tempItem = [playlistsMenu addItemWithTitle:[playlists objectAtIndex:i] action:@selector(performPlaylistMenuAction:) keyEquivalent:@""];
362 [tempItem setTag:i + 1];
363 [tempItem setTarget:self];
366 if (!_playingRadio && _currentPlaylist) {
367 [[playlistsMenu itemAtIndex:_currentPlaylist - 1] setState:NSOnState];
369 return playlistsMenu;
374 NSMenu *eqMenu = [[NSMenu alloc] initWithTitle:@""];
375 NSArray *eqPresets = [currentRemote eqPresets];
376 NSMenuItem *tempItem;
379 for (i = 0; i < [eqPresets count]; i++) {
381 if ( ( name = [eqPresets objectAtIndex:i] ) ) {
382 tempItem = [eqMenu addItemWithTitle:name action:@selector(performEqualizerMenuAction:) keyEquivalent:@""];
384 [tempItem setTarget:self];
390 - (void)performMainMenuAction:(id)sender
392 switch ( [sender tag] )
394 case MTMenuPlayPauseItem:
395 NSLog(@"MenuController: Play/Pause");
396 [[MainController sharedController] playPause];
398 case MTMenuFastForwardItem:
399 NSLog(@"MenuController: Fast Forward");
400 [[MainController sharedController] fastForward];
402 case MTMenuRewindItem:
403 NSLog(@"MenuController: Rewind");
404 [[MainController sharedController] rewind];
406 case MTMenuPreviousTrackItem:
407 NSLog(@"MenuController: Previous Track");
408 [[MainController sharedController] prevSong];
410 case MTMenuNextTrackItem:
411 NSLog(@"MenuController: Next Track");
412 [[MainController sharedController] nextSong];
414 case MTMenuShowPlayerItem:
415 NSLog(@"MainController: Show Main Interface");
416 [[MainController sharedController] showPlayer];
418 case MTMenuPreferencesItem:
419 NSLog(@"MenuController: Preferences...");
420 [[MainController sharedController] showPreferences];
423 NSLog(@"MenuController: Quit");
424 [[MainController sharedController] quitMenuTunes];
427 NSLog(@"MenuController: Unimplemented Menu Item OR Child-bearing Menu Item");
432 - (void)performRatingMenuAction:(id)sender
434 [[MainController sharedController] selectSongRating:[sender tag]];
437 - (void)performPlaylistMenuAction:(id)sender
439 [[MainController sharedController] selectPlaylistAtIndex:[sender tag]];
442 - (void)performEqualizerMenuAction:(id)sender
444 [[MainController sharedController] selectEQPresetAtIndex:[sender tag]];
447 - (void)performUpcomingSongsMenuAction:(id)sender
449 [[MainController sharedController] selectSongAtIndex:[sender tag]];
455 [_currentMenu update];
458 - (BOOL)validateMenuItem:(id <NSMenuItem>)menuItem
463 - (NSString *)systemUIColor
465 NSDictionary *tmpDict;
467 if ( (tmpDict = [NSDictionary dictionaryWithContentsOfFile:[@"~/Library/Preferences/.GlobalPreferences.plist" stringByExpandingTildeInPath]]) ) {
468 if ( (tmpNumber = [tmpDict objectForKey:@"AppleAquaColorVariant"]) ) {
469 if ( ([tmpNumber intValue] == 1) ) {
482 - (void)setKeyEquivalentForCode:(short)code andModifiers:(long)modifiers
483 onItem:(NSMenuItem *)item
485 unichar charcode = 'a';
487 long cocoaModifiers = 0;
488 static long carbonToCocoa[6][2] =
490 { cmdKey, NSCommandKeyMask },
491 { optionKey, NSAlternateKeyMask },
492 { controlKey, NSControlKeyMask },
493 { shiftKey, NSShiftKeyMask },
496 for (i = 0; i < 6; i++) {
497 if (modifiers & carbonToCocoa[i][0]) {
498 cocoaModifiers += carbonToCocoa[i][1];
501 [item setKeyEquivalentModifierMask:cocoaModifiers];
503 //Missing key combos for some keys. Must find them later.
517 // Haven't tested this, though it should work.
518 // This doesn't work. :'(
520 [[NSString stringWithString:@"Space"] getCharacters:&buffer];
522 /*MenuRef menuRef = _NSGetCarbonMenu([item menu]);
523 NSLog(@"%@", menuRef);
524 SetMenuItemCommandKey(menuRef, 0, NO, 49);
525 SetMenuItemModifiers(menuRef, 0, kMenuNoCommandModifier);
526 SetMenuItemKeyGlyph(menuRef, 0, kMenuBlankGlyph);
533 charcode = NSDeleteFunctionKey;
549 charcode = NSF5FunctionKey;
553 charcode = NSF6FunctionKey;
557 charcode = NSF7FunctionKey;
561 charcode = NSF3FunctionKey;
565 charcode = NSF8FunctionKey;
569 charcode = NSF9FunctionKey;
573 charcode = NSF11FunctionKey;
577 charcode = NSF3FunctionKey;
581 charcode = NSF14FunctionKey;
585 charcode = NSF10FunctionKey;
589 charcode = NSF12FunctionKey;
593 charcode = NSF13FunctionKey;
597 charcode = NSInsertFunctionKey;
601 charcode = NSHomeFunctionKey;
605 charcode = NSPageUpFunctionKey;
609 charcode = NSDeleteFunctionKey;
613 charcode = NSF4FunctionKey;
617 charcode = NSEndFunctionKey;
621 charcode = NSF2FunctionKey;
625 charcode = NSPageDownFunctionKey;
629 charcode = NSF1FunctionKey;
633 charcode = NSLeftArrowFunctionKey;
637 charcode = NSRightArrowFunctionKey;
641 charcode = NSDownArrowFunctionKey;
645 charcode = NSUpArrowFunctionKey;
649 if (charcode == 'a') {
655 kchr = (Ptr) GetScriptVariable(smCurrentScript, smKCHRCache);
656 keyTrans = KeyTranslate(kchr, code, &state);
658 [item setKeyEquivalent:[NSString stringWithCString:&charCode length:1]];
659 } else if (charcode != 'b') {
660 [item setKeyEquivalent:[NSString stringWithCharacters:&charcode length:1]];