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 NSArray *menuArray = [[NSUserDefaults standardUserDefaults] arrayForKey:@"menu"];
37 NSEnumerator *enumerator = [menuArray objectEnumerator];
40 NSEnumerator *itemEnum;
44 _currentPlaylist = [currentRemote currentPlaylistIndex];
45 _playingRadio = ([currentRemote currentPlaylistClass] == ITMTRemotePlayerRadioPlaylist);
47 //Kill the old submenu items
48 if ( (tempItem = [_currentMenu itemWithTag:1]) ) {
49 [tempItem setSubmenu:nil];
52 if ( (tempItem = [_currentMenu itemWithTag:2]) ) {
53 [tempItem setSubmenu:nil];
56 if ( (tempItem = [_currentMenu itemWithTag:3]) ) {
57 [tempItem setSubmenu:nil];
60 if ( (tempItem = [_currentMenu itemWithTag:4]) ) {
61 [tempItem setSubmenu:nil];
65 while ( (nextObject = [enumerator nextObject]) ) {
67 if ([nextObject isEqualToString:@"Play/Pause"]) {
68 tempItem = [menu addItemWithTitle:@"Play"
69 action:@selector(performMainMenuAction:)
71 [tempItem setTag:MTMenuPlayPauseItem];
72 [tempItem setTarget:self];
74 if ( (keyCombo = [[HotKeyCenter sharedCenter] keyComboForName:@"PlayPause"]) ) {
75 [self setKeyEquivalentForCode:[keyCombo keyCode]
76 andModifiers:[keyCombo modifiers]
80 switch ([currentRemote playerPlayingState]) {
81 case ITMTRemotePlayerPlaying:
82 [tempItem setTitle:@"Pause"];
84 case ITMTRemotePlayerRewinding:
85 case ITMTRemotePlayerForwarding:
86 [tempItem setTitle:@"Resume"];
91 } else if ([nextObject isEqualToString:@"Next Track"]) {
92 tempItem = [menu addItemWithTitle:@"Next Track"
93 action:@selector(performMainMenuAction:)
96 if ( (keyCombo = [[HotKeyCenter sharedCenter] keyComboForName:@"NextTrack"]) ) {
97 [self setKeyEquivalentForCode:[keyCombo keyCode]
98 andModifiers:[keyCombo modifiers]
102 if (_currentPlaylist) {
103 [tempItem setTag:MTMenuNextTrackItem];
104 [tempItem setTarget:self];
106 } else if ([nextObject isEqualToString:@"Previous Track"]) {
107 tempItem = [menu addItemWithTitle:@"Previous Track"
108 action:@selector(performMainMenuAction:)
111 if ( (keyCombo = [[HotKeyCenter sharedCenter] keyComboForName:@"PrevTrack"]) ) {
112 [self setKeyEquivalentForCode:[keyCombo keyCode]
113 andModifiers:[keyCombo modifiers]
117 if (_currentPlaylist) {
118 [tempItem setTag:MTMenuPreviousTrackItem];
119 [tempItem setTarget:self];
121 } else if ([nextObject isEqualToString:@"Fast Forward"]) {
122 tempItem = [menu addItemWithTitle:@"Fast Forward"
123 action:@selector(performMainMenuAction:)
125 if (_currentPlaylist) {
126 [tempItem setTag:MTMenuFastForwardItem];
127 [tempItem setTarget:self];
129 } else if ([nextObject isEqualToString:@"Rewind"]) {
130 tempItem = [menu addItemWithTitle:@"Rewind"
131 action:@selector(performMainMenuAction:)
133 if (_currentPlaylist) {
134 [tempItem setTag:MTMenuRewindItem];
135 [tempItem setTarget:self];
137 } else if ([nextObject isEqualToString:@"Preferences"]) {
138 tempItem = [menu addItemWithTitle:@"Preferences..."
139 action:@selector(performMainMenuAction:)
141 [tempItem setTag:MTMenuPreferencesItem];
142 [tempItem setTarget:self];
143 } else if ([nextObject isEqualToString:@"Quit"]) {
144 tempItem = [menu addItemWithTitle:@"Quit"
145 action:@selector(performMainMenuAction:)
147 [tempItem setTag:MTMenuQuitItem];
148 [tempItem setTarget:self];
149 } else if ([nextObject isEqualToString:@"Current Track Info"]) {
150 //Handle playing radio too
151 if (_currentPlaylist) {
152 NSString *title = [currentRemote currentSongTitle];
154 [menu addItemWithTitle:@"Now Playing" action:NULL keyEquivalent:@""];
156 if ([title length] > 0) {
157 [menu addItemWithTitle:[NSString stringWithFormat:@" %@", title] action:nil keyEquivalent:@""];
159 //Gotta add artist, album, track, time, etc, blah, blah, blah...
161 [menu addItemWithTitle:@"No Song" action:NULL keyEquivalent:@""];
163 } else if ([nextObject isEqualToString:@"<separator>"]) {
164 [menu addItem:[NSMenuItem separatorItem]];
166 } else if ([nextObject isEqualToString:@"Song Rating"]) {
167 tempItem = [menu addItemWithTitle:@"Song Rating"
170 [tempItem setSubmenu:_ratingMenu];
173 itemEnum = [[_ratingMenu itemArray] objectEnumerator];
174 while ( (tempItem = [itemEnum nextObject]) ) {
175 [tempItem setState:NSOffState];
178 [[_ratingMenu itemAtIndex:([currentRemote currentSongRating] * 5)] setState:NSOnState];
179 if (_playingRadio || !_currentPlaylist) {
180 [tempItem setEnabled:NO];
182 } else if ([nextObject isEqualToString:@"Upcoming Songs"]) {
183 tempItem = [menu addItemWithTitle:@"Upcoming Songs"
186 [tempItem setSubmenu:_upcomingSongsMenu];
188 if (_playingRadio || !_currentPlaylist) {
189 [tempItem setEnabled:NO];
191 } else if ([nextObject isEqualToString:@"Playlists"]) {
192 tempItem = [menu addItemWithTitle:@"Playlists"
195 [tempItem setSubmenu:_playlistsMenu];
197 } else if ([nextObject isEqualToString:@"EQ Presets"]) {
198 tempItem = [menu addItemWithTitle:@"EQ Presets"
201 [tempItem setSubmenu:_eqMenu];
204 itemEnum = [[_eqMenu itemArray] objectEnumerator];
205 while ( (tempItem = [itemEnum nextObject]) ) {
206 [tempItem setState:NSOffState];
208 [[_eqMenu itemAtIndex:([currentRemote currentEQPresetIndex] - 1)] setState:NSOnState];
211 [_currentMenu release];
216 - (NSMenu *)menuForNoPlayer
218 NSMenu *menu = [[NSMenu alloc] initWithTitle:@""];
219 NSMenuItem *tempItem;
220 tempItem = [menu addItemWithTitle:[NSString stringWithFormat:@"Open %@", [[[MainController sharedController] currentRemote] playerSimpleName]] action:@selector(performMainMenuAction:) keyEquivalent:@""];
221 [tempItem setTag:MTMenuShowPlayerItem];
222 [tempItem setTarget:self];
223 [menu addItem:[NSMenuItem separatorItem]];
224 tempItem = [menu addItemWithTitle:@"Preferences" action:@selector(performMainMenuAction:) keyEquivalent:@""];
225 [tempItem setTag:MTMenuPreferencesItem];
226 [tempItem setTarget:self];
227 tempItem = [menu addItemWithTitle:@"Quit" action:@selector(performMainMenuAction:) keyEquivalent:@""];
228 [tempItem setTag:MTMenuQuitItem];
229 [tempItem setTarget:self];
230 return [menu autorelease];
233 - (void)rebuildSubmenus
235 currentRemote = [[MainController sharedController] currentRemote];
236 _currentPlaylist = [currentRemote currentPlaylistIndex];
237 _currentTrack = [currentRemote currentSongIndex];
238 _playingRadio = ([currentRemote currentPlaylistClass] == ITMTRemotePlayerRadioPlaylist);
240 [_ratingMenu release];
241 [_upcomingSongsMenu release];
242 [_playlistsMenu release];
244 _ratingMenu = [self ratingMenu];
245 _upcomingSongsMenu = [self upcomingSongsMenu];
246 _playlistsMenu = [self playlistsMenu];
247 _eqMenu = [self eqMenu];
250 - (NSMenu *)ratingMenu
252 NSMenu *ratingMenu = [[NSMenu alloc] initWithTitle:@""];
253 if (_currentPlaylist && !_playingRadio) {
254 NSEnumerator *itemEnum;
257 SEL itemSelector = @selector(performRatingMenuAction:);
259 [ratingMenu addItemWithTitle:[NSString stringWithUTF8String:"☆☆☆☆☆"] action:nil keyEquivalent:@""];
260 [ratingMenu addItemWithTitle:[NSString stringWithUTF8String:"★☆☆☆☆"] action:nil keyEquivalent:@""];
261 [ratingMenu addItemWithTitle:[NSString stringWithUTF8String:"★★☆☆☆"] action:nil keyEquivalent:@""];
262 [ratingMenu addItemWithTitle:[NSString stringWithUTF8String:"★★★☆☆"] action:nil keyEquivalent:@""];
263 [ratingMenu addItemWithTitle:[NSString stringWithUTF8String:"★★★★☆"] action:nil keyEquivalent:@""];
264 [ratingMenu addItemWithTitle:[NSString stringWithUTF8String:"★★★★★"] action:nil keyEquivalent:@""];
266 itemEnum = [[ratingMenu itemArray] objectEnumerator];
267 while ( (anItem = [itemEnum nextObject]) ) {
268 [anItem setAction:itemSelector];
269 [anItem setTarget:self];
270 [anItem setTag:itemTag];
277 - (NSMenu *)upcomingSongsMenu
279 NSMenu *upcomingSongsMenu = [[NSMenu alloc] initWithTitle:@""];
280 int numSongs = [currentRemote numberOfSongsInPlaylistAtIndex:_currentPlaylist];
281 int numSongsInAdvance = [[NSUserDefaults standardUserDefaults] integerForKey:@"SongsInAdvance"];
283 if (_currentPlaylist && !_playingRadio) {
287 for (i = _currentTrack + 1; i <= _currentTrack + numSongsInAdvance; i++) {
289 NSString *curSong = [currentRemote songTitleAtIndex:i];
290 NSMenuItem *songItem;
291 songItem = [upcomingSongsMenu addItemWithTitle:curSong action:@selector(performUpcomingSongsMenuAction:) keyEquivalent:@""];
293 [songItem setTarget:self];
300 return upcomingSongsMenu;
303 - (NSMenu *)playlistsMenu
305 NSMenu *playlistsMenu = [[NSMenu alloc] initWithTitle:@""];
306 NSArray *playlists = [currentRemote playlists];
307 NSMenuItem *tempItem;
310 for (i = 0; i < [playlists count]; i++) {
311 tempItem = [playlistsMenu addItemWithTitle:[playlists objectAtIndex:i] action:@selector(performPlaylistMenuAction:) keyEquivalent:@""];
312 [tempItem setTag:i + 1];
313 [tempItem setTarget:self];
316 if (!_playingRadio && _currentPlaylist) {
317 [[playlistsMenu itemAtIndex:_currentPlaylist - 1] setState:NSOnState];
319 return playlistsMenu;
324 NSMenu *eqMenu = [[NSMenu alloc] initWithTitle:@""];
325 NSArray *eqPresets = [currentRemote eqPresets];
326 NSMenuItem *tempItem;
329 for (i = 0; i < [eqPresets count]; i++) {
331 if ( ( name = [eqPresets objectAtIndex:i] ) ) {
332 tempItem = [eqMenu addItemWithTitle:name action:@selector(performEqualizerMenuAction:) keyEquivalent:@""];
334 [tempItem setTarget:self];
340 - (void)performMainMenuAction:(id)sender
342 switch ( [sender tag] )
344 case MTMenuPlayPauseItem:
345 NSLog(@"MenuController: Play/Pause");
346 [[MainController sharedController] playPause];
348 case MTMenuFastForwardItem:
349 NSLog(@"MenuController: Fast Forward");
350 [[MainController sharedController] fastForward];
352 case MTMenuRewindItem:
353 NSLog(@"MenuController: Rewind");
354 [[MainController sharedController] rewind];
356 case MTMenuPreviousTrackItem:
357 NSLog(@"MenuController: Previous Track");
358 [[MainController sharedController] prevSong];
360 case MTMenuNextTrackItem:
361 NSLog(@"MenuController: Next Track");
362 [[MainController sharedController] nextSong];
364 case MTMenuShowPlayerItem:
365 NSLog(@"MainController: Show Main Interface");
366 [[MainController sharedController] showPlayer];
368 case MTMenuPreferencesItem:
369 NSLog(@"MenuController: Preferences...");
370 [[MainController sharedController] showPreferences];
373 NSLog(@"MenuController: Quit");
374 [[MainController sharedController] quitMenuTunes];
377 NSLog(@"MenuController: Unimplemented Menu Item OR Child-bearing Menu Item");
382 - (void)performRatingMenuAction:(id)sender
384 [[MainController sharedController] selectSongRating:[sender tag]];
387 - (void)performPlaylistMenuAction:(id)sender
389 [[MainController sharedController] selectPlaylistAtIndex:[sender tag]];
392 - (void)performEqualizerMenuAction:(id)sender
394 [[MainController sharedController] selectEQPresetAtIndex:[sender tag]];
397 - (void)performUpcomingSongsMenuAction:(id)sender
399 [[MainController sharedController] selectSongAtIndex:[sender tag]];
405 [_currentMenu update];
408 - (BOOL)validateMenuItem:(id <NSMenuItem>)menuItem
413 - (NSString *)systemUIColor
415 NSDictionary *tmpDict;
417 if ( (tmpDict = [NSDictionary dictionaryWithContentsOfFile:[@"~/Library/Preferences/.GlobalPreferences.plist" stringByExpandingTildeInPath]]) ) {
418 if ( (tmpNumber = [tmpDict objectForKey:@"AppleAquaColorVariant"]) ) {
419 if ( ([tmpNumber intValue] == 1) ) {
432 - (void)setKeyEquivalentForCode:(short)code andModifiers:(long)modifiers
433 onItem:(NSMenuItem *)item
435 unichar charcode = 'a';
437 long cocoaModifiers = 0;
438 static long carbonToCocoa[6][2] =
440 { cmdKey, NSCommandKeyMask },
441 { optionKey, NSAlternateKeyMask },
442 { controlKey, NSControlKeyMask },
443 { shiftKey, NSShiftKeyMask },
446 for (i = 0; i < 6; i++) {
447 if (modifiers & carbonToCocoa[i][0]) {
448 cocoaModifiers += carbonToCocoa[i][1];
451 [item setKeyEquivalentModifierMask:cocoaModifiers];
453 //Missing key combos for some keys. Must find them later.
467 // Haven't tested this, though it should work.
468 // This doesn't work. :'(
470 [[NSString stringWithString:@"Space"] getCharacters:&buffer];
472 /*MenuRef menuRef = _NSGetCarbonMenu([item menu]);
473 NSLog(@"%@", menuRef);
474 SetMenuItemCommandKey(menuRef, 0, NO, 49);
475 SetMenuItemModifiers(menuRef, 0, kMenuNoCommandModifier);
476 SetMenuItemKeyGlyph(menuRef, 0, kMenuBlankGlyph);
483 charcode = NSDeleteFunctionKey;
499 charcode = NSF5FunctionKey;
503 charcode = NSF6FunctionKey;
507 charcode = NSF7FunctionKey;
511 charcode = NSF3FunctionKey;
515 charcode = NSF8FunctionKey;
519 charcode = NSF9FunctionKey;
523 charcode = NSF11FunctionKey;
527 charcode = NSF3FunctionKey;
531 charcode = NSF14FunctionKey;
535 charcode = NSF10FunctionKey;
539 charcode = NSF12FunctionKey;
543 charcode = NSF13FunctionKey;
547 charcode = NSInsertFunctionKey;
551 charcode = NSHomeFunctionKey;
555 charcode = NSPageUpFunctionKey;
559 charcode = NSDeleteFunctionKey;
563 charcode = NSF4FunctionKey;
567 charcode = NSEndFunctionKey;
571 charcode = NSF2FunctionKey;
575 charcode = NSPageDownFunctionKey;
579 charcode = NSF1FunctionKey;
583 charcode = NSLeftArrowFunctionKey;
587 charcode = NSRightArrowFunctionKey;
591 charcode = NSDownArrowFunctionKey;
595 charcode = NSUpArrowFunctionKey;
599 if (charcode == 'a') {
605 kchr = (Ptr) GetScriptVariable(smCurrentScript, smKCHRCache);
606 keyTrans = KeyTranslate(kchr, code, &state);
608 [item setKeyEquivalent:[NSString stringWithCString:&charCode length:1]];
609 } else if (charcode != 'b') {
610 [item setKeyEquivalent:[NSString stringWithCharacters:&charcode length:1]];