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"
12 @interface MenuController (SubmenuMethods)
13 - (NSMenu *)ratingMenu;
14 - (NSMenu *)upcomingSongsMenu;
15 - (NSMenu *)playlistsMenu;
19 @implementation MenuController
23 if ( (self = [super init]) ) {
24 _menuLayout = [[NSMutableArray alloc] initWithCapacity:0];
31 NSMenu *menu = [[NSMenu alloc] initWithTitle:@""];
32 NSArray *menuArray = [[NSUserDefaults standardUserDefaults] arrayForKey:@"menu"];
33 NSEnumerator *enumerator = [menuArray objectEnumerator];
38 _currentPlaylist = [currentRemote currentPlaylistIndex];
39 _playingRadio = ([currentRemote currentPlaylistClass] == ITMTRemotePlayerRadioPlaylist);
41 //Kill the old submenu items
42 if ( (tempItem = [_currentMenu itemWithTag:1]) ) {
43 [tempItem setSubmenu:nil];
46 if ( (tempItem = [_currentMenu itemWithTag:2]) ) {
47 [tempItem setSubmenu:nil];
50 if ( (tempItem = [_currentMenu itemWithTag:3]) ) {
51 [tempItem setSubmenu:nil];
54 if ( (tempItem = [_currentMenu itemWithTag:4]) ) {
55 [tempItem setSubmenu:nil];
59 while ( (nextObject = [enumerator nextObject]) ) {
61 if ([nextObject isEqualToString:@"Play/Pause"]) {
62 tempItem = [menu addItemWithTitle:@"Play"
63 action:@selector(performMainMenuAction:)
65 [tempItem setTag:MTMenuPlayPauseItem];
66 [tempItem setTarget:self];
68 switch ([currentRemote playerPlayingState]) {
69 case ITMTRemotePlayerPlaying:
70 [tempItem setTitle:@"Pause"];
72 case ITMTRemotePlayerRewinding:
73 case ITMTRemotePlayerForwarding:
74 [tempItem setTitle:@"Resume"];
79 } else if ([nextObject isEqualToString:@"Next Track"]) {
80 tempItem = [menu addItemWithTitle:@"Next Track"
81 action:@selector(performMainMenuAction:)
83 if (_currentPlaylist) {
84 [tempItem setTag:MTMenuNextTrackItem];
85 [tempItem setTarget:self];
87 } else if ([nextObject isEqualToString:@"Previous Track"]) {
88 tempItem = [menu addItemWithTitle:@"Previous Track"
89 action:@selector(performMainMenuAction:)
91 if (_currentPlaylist) {
92 [tempItem setTag:MTMenuPreviousTrackItem];
93 [tempItem setTarget:self];
95 } else if ([nextObject isEqualToString:@"Fast Forward"]) {
96 tempItem = [menu addItemWithTitle:@"Fast Forward"
97 action:@selector(performMainMenuAction:)
99 if (_currentPlaylist) {
100 [tempItem setTag:MTMenuFastForwardItem];
101 [tempItem setTarget:self];
103 } else if ([nextObject isEqualToString:@"Rewind"]) {
104 tempItem = [menu addItemWithTitle:@"Rewind"
105 action:@selector(performMainMenuAction:)
107 if (_currentPlaylist) {
108 [tempItem setTag:MTMenuRewindItem];
109 [tempItem setTarget:self];
111 } else if ([nextObject isEqualToString:@"Preferences"]) {
112 tempItem = [menu addItemWithTitle:@"Preferences..."
113 action:@selector(performMainMenuAction:)
115 [tempItem setTag:MTMenuPreferencesItem];
116 [tempItem setTarget:self];
117 } else if ([nextObject isEqualToString:@"Quit"]) {
118 tempItem = [menu addItemWithTitle:@"Quit"
119 action:@selector(performMainMenuAction:)
121 [tempItem setTag:MTMenuQuitItem];
122 [tempItem setTarget:self];
123 } else if ([nextObject isEqualToString:@"Current Track Info"]) {
124 //Handle playing radio too
125 if (_currentPlaylist) {
126 NSString *title = [currentRemote currentSongTitle];
128 [menu addItemWithTitle:@"Now Playing" action:NULL keyEquivalent:@""];
130 if ([title length] > 0) {
131 [menu addItemWithTitle:[NSString stringWithFormat:@" %@", title] action:nil keyEquivalent:@""];
133 //Gotta add artist, album, track, time, etc, blah, blah, blah...
135 [menu addItemWithTitle:@"No Song" action:NULL keyEquivalent:@""];
137 } else if ([nextObject isEqualToString:@"<separator>"]) {
138 [menu addItem:[NSMenuItem separatorItem]];
140 } else if ([nextObject isEqualToString:@"Song Rating"]) {
141 tempItem = [menu addItemWithTitle:@"Song Rating"
144 [tempItem setSubmenu:_ratingMenu];
146 if (_playingRadio || !_currentPlaylist) {
147 [tempItem setEnabled:NO];
149 } else if ([nextObject isEqualToString:@"Upcoming Songs"]) {
150 tempItem = [menu addItemWithTitle:@"Upcoming Songs"
153 [tempItem setSubmenu:_upcomingSongsMenu];
155 if (_playingRadio || !_currentPlaylist) {
156 [tempItem setEnabled:NO];
158 } else if ([nextObject isEqualToString:@"Playlists"]) {
159 tempItem = [menu addItemWithTitle:@"Playlists"
162 [tempItem setSubmenu:_playlistsMenu];
164 } else if ([nextObject isEqualToString:@"EQ Presets"]) {
165 tempItem = [menu addItemWithTitle:@"EQ Presets"
168 [tempItem setSubmenu:_eqMenu];
172 [_currentMenu release];
177 - (NSMenu *)menuForNoPlayer
179 NSMenu *menu = [[NSMenu alloc] initWithTitle:@""];
180 NSMenuItem *tempItem;
181 tempItem = [menu addItemWithTitle:[NSString stringWithFormat:@"Open %@", [[[MainController sharedController] currentRemote] playerSimpleName]] action:@selector(performMainMenuAction:) keyEquivalent:@""];
182 [tempItem setTag:MTMenuShowPlayerItem];
183 [tempItem setTarget:self];
184 [menu addItem:[NSMenuItem separatorItem]];
185 tempItem = [menu addItemWithTitle:@"Preferences" action:@selector(performMainMenuAction:) keyEquivalent:@""];
186 [tempItem setTag:MTMenuPreferencesItem];
187 [tempItem setTarget:self];
188 tempItem = [menu addItemWithTitle:@"Quit" action:@selector(performMainMenuAction:) keyEquivalent:@""];
189 [tempItem setTag:MTMenuQuitItem];
190 [tempItem setTarget:self];
191 return [menu autorelease];
194 - (void)rebuildSubmenus
196 currentRemote = [[MainController sharedController] currentRemote];
197 _currentPlaylist = [currentRemote currentPlaylistIndex];
198 _currentTrack = [currentRemote currentSongIndex];
199 _playingRadio = ([currentRemote currentPlaylistClass] == ITMTRemotePlayerRadioPlaylist);
201 [_ratingMenu release];
202 [_upcomingSongsMenu release];
203 [_playlistsMenu release];
205 _ratingMenu = [self ratingMenu];
206 _upcomingSongsMenu = [self upcomingSongsMenu];
207 _playlistsMenu = [self playlistsMenu];
208 _eqMenu = [self eqMenu];
211 - (NSMenu *)ratingMenu
213 NSMenu *ratingMenu = [[NSMenu alloc] initWithTitle:@""];
214 if (_currentPlaylist && !_playingRadio) {
215 NSEnumerator *itemEnum;
218 SEL itemSelector = @selector(performRatingMenuAction:);
220 [ratingMenu addItemWithTitle:[NSString stringWithUTF8String:"☆☆☆☆☆"] action:nil keyEquivalent:@""];
221 [ratingMenu addItemWithTitle:[NSString stringWithUTF8String:"★☆☆☆☆"] action:nil keyEquivalent:@""];
222 [ratingMenu addItemWithTitle:[NSString stringWithUTF8String:"★★☆☆☆"] action:nil keyEquivalent:@""];
223 [ratingMenu addItemWithTitle:[NSString stringWithUTF8String:"★★★☆☆"] action:nil keyEquivalent:@""];
224 [ratingMenu addItemWithTitle:[NSString stringWithUTF8String:"★★★★☆"] action:nil keyEquivalent:@""];
225 [ratingMenu addItemWithTitle:[NSString stringWithUTF8String:"★★★★★"] action:nil keyEquivalent:@""];
227 [[ratingMenu itemAtIndex:([currentRemote currentSongRating] * 5)] setState:NSOnState];
229 itemEnum = [[ratingMenu itemArray] objectEnumerator];
230 while ( (anItem = [itemEnum nextObject]) ) {
231 [anItem setAction:itemSelector];
232 [anItem setTarget:self];
233 [anItem setTag:itemTag];
240 - (NSMenu *)upcomingSongsMenu
242 NSMenu *upcomingSongsMenu = [[NSMenu alloc] initWithTitle:@""];
243 int numSongs = [currentRemote numberOfSongsInPlaylistAtIndex:_currentPlaylist];
244 int numSongsInAdvance = [[NSUserDefaults standardUserDefaults] integerForKey:@"SongsInAdvance"];
246 if (_currentPlaylist && !_playingRadio) {
250 for (i = _currentTrack + 1; i <= _currentTrack + numSongsInAdvance; i++) {
252 NSString *curSong = [currentRemote songTitleAtIndex:i];
253 NSMenuItem *songItem;
254 songItem = [upcomingSongsMenu addItemWithTitle:curSong action:@selector(performUpcomingSongsMenuAction:) keyEquivalent:@""];
256 [songItem setTarget:self];
263 return upcomingSongsMenu;
266 - (NSMenu *)playlistsMenu
268 NSMenu *playlistsMenu = [[NSMenu alloc] initWithTitle:@""];
269 NSArray *playlists = [currentRemote playlists];
270 NSMenuItem *tempItem;
273 for (i = 0; i < [playlists count]; i++) {
274 tempItem = [playlistsMenu addItemWithTitle:[playlists objectAtIndex:i] action:@selector(performPlaylistMenuAction:) keyEquivalent:@""];
275 [tempItem setTag:i + 1];
276 [tempItem setTarget:self];
279 if (!_playingRadio && _currentPlaylist) {
280 [[playlistsMenu itemAtIndex:_currentPlaylist - 1] setState:NSOnState];
282 return playlistsMenu;
287 NSMenu *eqMenu = [[NSMenu alloc] initWithTitle:@""];
288 NSArray *eqPresets = [currentRemote eqPresets];
289 NSMenuItem *tempItem;
292 for (i = 0; i < [eqPresets count]; i++) {
294 if ( ( name = [eqPresets objectAtIndex:i] ) ) {
295 tempItem = [eqMenu addItemWithTitle:name action:@selector(performEqualizerMenuAction:) keyEquivalent:@""];
297 [tempItem setTarget:self];
300 [[eqMenu itemAtIndex:([currentRemote currentEQPresetIndex] - 1)] setState:NSOnState];
304 - (void)performMainMenuAction:(id)sender
306 switch ( [sender tag] )
308 case MTMenuPlayPauseItem:
309 NSLog(@"MenuController: Play/Pause");
310 [[MainController sharedController] playPause];
311 //We're gonna have to change the Play menu item to Pause here too.
313 case MTMenuFastForwardItem:
314 NSLog(@"MenuController: Fast Forward");
315 [[MainController sharedController] fastForward];
316 //make sure play/pause item says sane through this
318 case MTMenuRewindItem:
319 NSLog(@"MenuController: Rewind");
320 [[MainController sharedController] rewind];
321 //make sure play/pause item says sane through this
323 case MTMenuPreviousTrackItem:
324 NSLog(@"MenuController: Previous Track");
325 [[MainController sharedController] prevSong];
327 case MTMenuNextTrackItem:
328 NSLog(@"MenuController: Next Track");
329 [[MainController sharedController] nextSong];
331 case MTMenuShowPlayerItem:
332 NSLog(@"MainController: Show Main Interface");
333 [[MainController sharedController] showPlayer];
335 case MTMenuPreferencesItem:
336 NSLog(@"MenuController: Preferences...");
337 [[MainController sharedController] showPreferences];
340 NSLog(@"MenuController: Quit");
341 [[MainController sharedController] quitMenuTunes];
344 NSLog(@"MenuController: Unimplemented Menu Item OR Child-bearing Menu Item");
349 - (void)performRatingMenuAction:(id)sender
351 [[MainController sharedController] selectSongRating:[sender tag]];
354 - (void)performPlaylistMenuAction:(id)sender
356 [[MainController sharedController] selectPlaylistAtIndex:[sender tag]];
359 - (void)performEqualizerMenuAction:(id)sender
361 [[MainController sharedController] selectEQPresetAtIndex:[sender tag]];
364 - (void)performUpcomingSongsMenuAction:(id)sender
366 [[MainController sharedController] selectSongAtIndex:[sender tag]];
372 [_currentMenu update];
375 - (BOOL)validateMenuItem:(id <NSMenuItem>)menuItem
380 - (NSString *)systemUIColor
382 NSDictionary *tmpDict;
384 if ( (tmpDict = [NSDictionary dictionaryWithContentsOfFile:[@"~/Library/Preferences/.GlobalPreferences.plist" stringByExpandingTildeInPath]]) ) {
385 if ( (tmpNumber = [tmpDict objectForKey:@"AppleAquaColorVariant"]) ) {
386 if ( ([tmpNumber intValue] == 1) ) {
399 - (void)setKeyEquivalentForCode:(short)code andModifiers:(long)modifiers
400 onItem:(NSMenuItem *)item
402 unichar charcode = 'a';
404 long cocoaModifiers = 0;
405 static long carbonToCocoa[6][2] =
407 { cmdKey, NSCommandKeyMask },
408 { optionKey, NSAlternateKeyMask },
409 { controlKey, NSControlKeyMask },
410 { shiftKey, NSShiftKeyMask },
413 for (i = 0; i < 6; i++) {
414 if (modifiers & carbonToCocoa[i][0]) {
415 cocoaModifiers += carbonToCocoa[i][1];
418 [item setKeyEquivalentModifierMask:cocoaModifiers];
420 //Missing key combos for some keys. Must find them later.
434 // Haven't tested this, though it should work.
435 // This doesn't work. :'(
437 [[NSString stringWithString:@"Space"] getCharacters:&buffer];
439 /*MenuRef menuRef = _NSGetCarbonMenu([item menu]);
440 NSLog(@"%@", menuRef);
441 SetMenuItemCommandKey(menuRef, 0, NO, 49);
442 SetMenuItemModifiers(menuRef, 0, kMenuNoCommandModifier);
443 SetMenuItemKeyGlyph(menuRef, 0, kMenuBlankGlyph);
450 charcode = NSDeleteFunctionKey;
466 charcode = NSF5FunctionKey;
470 charcode = NSF6FunctionKey;
474 charcode = NSF7FunctionKey;
478 charcode = NSF3FunctionKey;
482 charcode = NSF8FunctionKey;
486 charcode = NSF9FunctionKey;
490 charcode = NSF11FunctionKey;
494 charcode = NSF3FunctionKey;
498 charcode = NSF14FunctionKey;
502 charcode = NSF10FunctionKey;
506 charcode = NSF12FunctionKey;
510 charcode = NSF13FunctionKey;
514 charcode = NSInsertFunctionKey;
518 charcode = NSHomeFunctionKey;
522 charcode = NSPageUpFunctionKey;
526 charcode = NSDeleteFunctionKey;
530 charcode = NSF4FunctionKey;
534 charcode = NSEndFunctionKey;
538 charcode = NSF2FunctionKey;
542 charcode = NSPageDownFunctionKey;
546 charcode = NSF1FunctionKey;
550 charcode = NSLeftArrowFunctionKey;
554 charcode = NSRightArrowFunctionKey;
558 charcode = NSDownArrowFunctionKey;
562 charcode = NSUpArrowFunctionKey;
566 if (charcode == 'a') {
572 kchr = (Ptr) GetScriptVariable(smCurrentScript, smKCHRCache);
573 keyTrans = KeyTranslate(kchr, code, &state);
575 [item setKeyEquivalent:[NSString stringWithCString:&charCode length:1]];
576 } else if (charcode != 'b') {
577 [item setKeyEquivalent:[NSString stringWithCharacters:&charcode length:1]];