#import "MainController.h"
#import "NetworkController.h"
#import "ITMTRemote.h"
+#import "PlaylistNode.h"
#import <ITFoundation/ITDebug.h>
#import <ITKit/ITHotKeyCenter.h>
#import <ITKit/ITHotKey.h>
#import <ITKit/ITKeyCombo.h>
#import <ITKit/ITCategory-NSMenu.h>
+#import <ITKit/ITAboutWindowController.h>
@interface MenuController (SubmenuMethods)
- (NSMenu *)ratingMenu;
- (NSMenu *)eqMenu;
- (NSMenu *)artistsMenu;
- (NSMenu *)albumsMenu;
+- (void)playlistsMenuAux:(NSMenu *)menu node:(PlaylistNode *)node tagPrefix:(int)p;
- (void)setKeyEquivalentForCode:(short)code andModifiers:(long)modifiers
onItem:(id <NSMenuItem>)item;
- (BOOL)iPodWithNameAutomaticallyUpdates:(NSString *)name;
NS_HANDLER
[[MainController sharedController] networkError:localException];
NS_ENDHANDLER
-
+
ITDebugLog(@"Reset menu if required.");
//Kill the old submenu items
keyEquivalent:@""];
[tempItem setTag:MTMenuPreferencesItem];
[tempItem setTarget:self];
- } else if ([nextObject isEqualToString:@"quit"]) {
- if ([[MainController sharedController] blingBling] == NO) {
- ITDebugLog(@"Add \"Register MenuTunes...\" menu item.");
- tempItem = [menu addItemWithTitle:NSLocalizedString(@"register", @"Register MenuTunes...") action:@selector(performMainMenuAction:) keyEquivalent:@""];
- [tempItem setTag:MTMenuRegisterItem];
- [tempItem setTarget:self];
- }
+ } else if ([nextObject isEqualToString:@"about"]) {
+ ITDebugLog(@"Add \"About MenuTunes...\" menu item.");
+ tempItem = [menu addItemWithTitle:NSLocalizedString(@"about", @"About MenuTunes...")
+ action:@selector(performMainMenuAction:)
+ keyEquivalent:@""];
+ [tempItem setTag:MTMenuAboutItem];
+ [tempItem setTarget:self];
+ } else if ([nextObject isEqualToString:@"quit"]) {
ITDebugLog(@"Add \"Quit\" menu item.");
tempItem = [menu addItemWithTitle:NSLocalizedString(@"quit", @"Quit")
action:@selector(performMainMenuAction:)
} else if ([nextObject isEqualToString:@"trackInfo"]) {
ITDebugLog(@"Check to see if a Track is playing...");
//Handle playing radio too
- if (_currentPlaylist) {
+ if (_currentTrack != -1 && _currentPlaylist > 0) {
NSString *title = nil;
NS_DURING
title = [mtr currentSongTitle];
NS_DURING
[[_eqMenu itemAtIndex:0] setState:[mtr equalizerEnabled] ? NSOnState : NSOffState];
[[_eqMenu itemAtIndex:([mtr currentEQPresetIndex] + 1)] setState:NSOnState];
- [[_eqMenu itemAtIndex:([mtr currentEQPresetIndex] - 1)] setState:NSOnState];
NS_HANDLER
[[MainController sharedController] networkError:localException];
NS_ENDHANDLER
keyEquivalent:@""];
[tempItem setSubmenu:_upcomingSongsMenu];
[tempItem setTag:2];
- if (_playingRadio || !_currentPlaylist) {
+ if (_playingRadio || _currentPlaylist < 1) {
[tempItem setEnabled:NO];
}
} else if ([nextObject isEqualToString:@"artists"]) {
tempItem = [menu addItemWithTitle:NSLocalizedString(@"preferences", @"Preferences...") action:@selector(performMainMenuAction:) keyEquivalent:@""];
[tempItem setTag:MTMenuPreferencesItem];
[tempItem setTarget:self];
- if ([[MainController sharedController] blingBling] == NO) {
- ITDebugLog(@"Add \"Register MenuTunes...\" menu item.");
- tempItem = [menu addItemWithTitle:NSLocalizedString(@"register", @"Register MenuTunes...") action:@selector(performMainMenuAction:) keyEquivalent:@""];
- [tempItem setTag:MTMenuRegisterItem];
- [tempItem setTarget:self];
- }
ITDebugLog(@"Add \"Quit\" menu item.");
tempItem = [menu addItemWithTitle:NSLocalizedString(@"quit", @"Quit") action:@selector(performMainMenuAction:) keyEquivalent:@""];
[tempItem setTag:MTMenuQuitItem];
return [menu autorelease];
}
-- (void)rebuildSubmenus
+- (BOOL)rebuildSubmenus
{
NSArray *menu = [[NSUserDefaults standardUserDefaults] arrayForKey:@"menu"];
ITDebugLog(@"Rebuilding all of the submenus.");
NS_DURING
- _currentPlaylist = [[[MainController sharedController] currentRemote] currentPlaylistIndex];
- _currentTrack = [[[MainController sharedController] currentRemote] currentSongIndex];
+ _currentTrack = [[[MainController sharedController] currentRemote] currentSongIndex];
+ if (_currentTrack > -1) {
+ _currentPlaylist = [[[MainController sharedController] currentRemote] currentPlaylistIndex];
+ }
_playingRadio = ([[[MainController sharedController] currentRemote] currentPlaylistClass] == ITMTRemotePlayerRadioPlaylist);
NS_HANDLER
[[MainController sharedController] networkError:localException];
NS_ENDHANDLER
ITDebugLog(@"Releasing old submenus.");
+ _continue = YES;
ITDebugLog(@" - Rating menu");
[_ratingMenu release];
+ _ratingMenu = nil;
ITDebugLog(@" - Upcoming songs menu");
[_upcomingSongsMenu release];
+ _upcomingSongsMenu = nil;
ITDebugLog(@" - Playlists menu");
[_playlistsMenu release];
+ _playlistsMenu = nil;
ITDebugLog(@" - EQ menu");
[_eqMenu release];
+ _eqMenu = nil;
ITDebugLog(@"Beginning Rebuild of \"Song Rating\" submenu.");
_ratingMenu = [self ratingMenu];
ITDebugLog(@"Beginning Rebuild of \"Upcoming Songs\" submenu.");
_upcomingSongsMenu = [self upcomingSongsMenu];
- ITDebugLog(@"Beginning Rebuild of \"Playlists\" submenu.");
- _playlistsMenu = [self playlistsMenu];
- ITDebugLog(@"Beginning Rebuild of \"EQ Presets\" submenu.");
- _eqMenu = [self eqMenu];
-
- if ([menu containsObject:@"artists"]) {
+ if (_continue) {
+ ITDebugLog(@"Beginning Rebuild of \"Playlists\" submenu.");
+ _playlistsMenu = [self playlistsMenu];
+ }
+ if (_continue) {
+ ITDebugLog(@"Beginning Rebuild of \"EQ Presets\" submenu.");
+ _eqMenu = [self eqMenu];
+ }
+ if (_continue && [menu containsObject:@"artists"]) {
ITDebugLog(@"Releasing artists menu");
[_artistsMenu release];
ITDebugLog(@"Beginning Rebuild of \"Artists\" submenu.");
_artistsMenu = [self artistsMenu];
}
- if ([menu containsObject:@"albums"]) {
+ if (_continue && [menu containsObject:@"albums"]) {
ITDebugLog(@"Releasing albums menu");
[_albumsMenu release];
ITDebugLog(@"Beginning Rebuild of \"Albums\" submenu.");
_albumsMenu = [self albumsMenu];
}
ITDebugLog(@"Done rebuilding all of the submenus.");
+ return _continue;
}
- (NSMenu *)ratingMenu
- (NSMenu *)upcomingSongsMenu
{
- NSMenu *upcomingSongsMenu = [[NSMenu alloc] initWithTitle:@""];
+ NSMenu *upcomingSongsMenu;
int numSongs = 0, numSongsInAdvance = [[NSUserDefaults standardUserDefaults] integerForKey:@"SongsInAdvance"];
-
+ if (_currentTrack == -1) {
+ return nil;
+ }
NS_DURING
numSongs = [[[MainController sharedController] currentRemote] numberOfSongsInPlaylistAtIndex:_currentPlaylist];
NS_HANDLER
[[MainController sharedController] networkError:localException];
NS_ENDHANDLER
+ if (numSongs == -1) {
+ return nil;
+ }
+ upcomingSongsMenu = [[NSMenu alloc] initWithTitle:@""];
+ NS_DURING
ITDebugLog(@"Building \"Upcoming Songs\" menu.");
if (_currentPlaylist && !_playingRadio) {
if (numSongs > 0) {
int i;
- for (i = _currentTrack + 1; i <= _currentTrack + numSongsInAdvance; i++) {
- if (i <= numSongs) {
+ for (i = _currentTrack + 1; i <= _currentTrack + numSongsInAdvance && i <= numSongs; i++) {
+ BOOL enabled = YES;
+
+ //Check if the song at this index is enabled for playback. If it isn't, skip over it
+ NS_DURING
+ enabled = [[[MainController sharedController] currentRemote] songEnabledAtIndex:i];
+ NS_HANDLER
+ [[MainController sharedController] networkError:localException];
+ NS_ENDHANDLER
+
+ if (enabled) {
NSString *curSong = nil;
NS_DURING
curSong = [[[MainController sharedController] currentRemote] songTitleAtIndex:i];
[songItem setTag:i];
[songItem setTarget:self];
} else {
- break;
- }
+ numSongsInAdvance++;
+ }
}
}
}
}
ITDebugLog(@"Done Building \"Upcoming Songs\" menu.");
- return upcomingSongsMenu;
+ NS_VALUERETURN(upcomingSongsMenu, NSMenu *);
+ NS_HANDLER
+ [upcomingSongsMenu release];
+ _continue = NO;
+ NS_VALUERETURN(nil, NSMenu *);
+ NS_ENDHANDLER
}
/*- (NSMenu *)playlistsMenu
return playlistsMenu;
}*/
+- (void)playlistsMenuAux:(NSMenu *)menu node:(PlaylistNode *)node tagPrefix:(int)p
+{
+ id <NSMenuItem> tempItem;
+ int i;
+
+ for (i = 0; i < [[node children] count]; i++) {
+ PlaylistNode *nextNode = [[node children] objectAtIndex:i];
+ if ([nextNode type] == ITMTFolderNode) {
+ NSMenu *submenu = [[NSMenu alloc] init];
+ tempItem = [menu addItemWithTitle:[nextNode name] action:@selector(performPlaylistMenuAction:) keyEquivalent:@""];
+ [tempItem setTag:p + [nextNode index] + 1];
+ [tempItem setTarget:self];
+ [tempItem setSubmenu:submenu];
+ [self playlistsMenuAux:[submenu autorelease] node:nextNode tagPrefix:p];
+ } else {
+ tempItem = [menu addItemWithTitle:[nextNode name] action:@selector(performPlaylistMenuAction:) keyEquivalent:@""];
+ [tempItem setTag:p + [nextNode index] + 1];
+ [tempItem setTarget:self];
+ }
+
+ PlaylistNode *root = node;
+ while ([root type] == ITMTPlaylistNode || [root type] == ITMTFolderNode) {
+ root = [root parent];
+ }
+
+ if ([root index] == [[[MainController sharedController] currentRemote] currentSourceIndex] && [nextNode index] == _currentPlaylist) {
+ [tempItem setState:NSOnState];
+ }
+ }
+}
- (NSMenu *)playlistsMenu
{
NSArray *playlists = nil;
id <NSMenuItem> tempItem;
ITMTRemotePlayerSource source = [[[MainController sharedController] currentRemote] currentSource];
- int i, j;
+ int i;
NSMutableArray *indices = [[NSMutableArray alloc] init];
NS_DURING
playlists = [[[MainController sharedController] currentRemote] playlists];
NS_HANDLER
[[MainController sharedController] networkError:localException];
NS_ENDHANDLER
+
+ if (!playlists) {
+ [playlistsMenu release];
+ return nil;
+ }
+ NS_DURING
ITDebugLog(@"Building \"Playlists\" menu.");
{
- NSArray *curPlaylist = [playlists objectAtIndex:0];
- NSString *name = [curPlaylist objectAtIndex:0];
- ITDebugLog(@"Adding main source: %@", name);
- for (i = 3; i < [curPlaylist count]; i++) {
- ITDebugLog(@"Adding playlist: %@", [curPlaylist objectAtIndex:i]);
- tempItem = [playlistsMenu addItemWithTitle:[curPlaylist objectAtIndex:i] action:@selector(performPlaylistMenuAction:) keyEquivalent:@""];
- [tempItem setTag:i - 1];
- [tempItem setTarget:self];
- }
+ //First we add the main Library source, since it is guaranteed to be there.
+ PlaylistNode *library = [playlists objectAtIndex:0];
+ ITDebugLog(@"Adding main source: %@", [library name]);
+ [self playlistsMenuAux:playlistsMenu node:library tagPrefix:0];
ITDebugLog(@"Adding index to the index array.");
- [indices addObject:[curPlaylist objectAtIndex:2]];
+ [indices addObject:[NSNumber numberWithInt:[library index]]];
}
+
+ //Next go through the other sources
if ([playlists count] > 1) {
- if ([[[playlists objectAtIndex:1] objectAtIndex:1] intValue] == ITMTRemoteRadioSource) {
- [indices addObject:[[playlists objectAtIndex:1] objectAtIndex:2]];
+ //Add the radio source if it is playing
+ if ([[playlists objectAtIndex:1] sourceType] == ITMTRemoteRadioSource) {
+ [indices addObject:[NSNumber numberWithInt:[[playlists objectAtIndex:1] index]]];
if (source == ITMTRemoteRadioSource) {
[playlistsMenu addItem:[NSMenuItem separatorItem]];
[[playlistsMenu addItemWithTitle:NSLocalizedString(@"radio", @"Radio") action:@selector(performPlaylistMenuAction:) keyEquivalent:@""] setState:NSOnState];
- }
- } else {
- [playlistsMenu addItem:[NSMenuItem separatorItem]];
+ } else if ([playlists count] > 2) {
+ [playlistsMenu addItem:[NSMenuItem separatorItem]];
+ }
}
- }
-
- if ([playlists count] > 1) {
- for (i = 1; i < [playlists count]; i++) {
- NSArray *curPlaylist = [playlists objectAtIndex:i];
- if ([[curPlaylist objectAtIndex:1] intValue] != ITMTRemoteRadioSource) {
- NSString *name = [curPlaylist objectAtIndex:0];
- NSMenu *submenu = [[NSMenu alloc] init];
+
+ //Add other sources as needed (shared music, iPods, CDs)
+ for (i = [playlists count] - 1; i > 1 ; i--) {
+ PlaylistNode *nextSource = [playlists objectAtIndex:i];
+ if ([nextSource type] != ITMTRemoteRadioSource) {
+ NSString *name = [nextSource name];
ITDebugLog(@"Adding source: %@", name);
- if ( ([[curPlaylist objectAtIndex:1] intValue] == ITMTRemoteiPodSource) && [self iPodWithNameAutomaticallyUpdates:name] ) {
+ if ( ([nextSource type] == ITMTRemoteiPodSource) && [self iPodWithNameAutomaticallyUpdates:name] ) {
ITDebugLog(@"Invalid iPod source.");
[playlistsMenu addItemWithTitle:name action:NULL keyEquivalent:@""];
} else {
- for (j = 3; j < [curPlaylist count]; j++) {
- ITDebugLog(@"Adding playlist: %@", [curPlaylist objectAtIndex:j]);
- tempItem = [submenu addItemWithTitle:[curPlaylist objectAtIndex:j] action:@selector(performPlaylistMenuAction:) keyEquivalent:@""];
- [tempItem setTag:(i * 1000) + j - 1];
- [tempItem setTarget:self];
- }
- [[playlistsMenu addItemWithTitle:name action:NULL keyEquivalent:@""] setSubmenu:[submenu autorelease]];
+ NSMenu *menu = [[NSMenu alloc] init];
+ [[playlistsMenu addItemWithTitle:name action:NULL keyEquivalent:@""] setSubmenu:[menu autorelease]];
+ [self playlistsMenuAux:menu node:nextSource tagPrefix:(i * 1000)];
}
ITDebugLog(@"Adding index to the index array.");
- [indices addObject:[curPlaylist objectAtIndex:2]];
+ [indices addObject:[NSNumber numberWithInt:[nextSource index]]];
}
}
}
- ITDebugLog(@"Checking the current source.");
- if ( (source == ITMTRemoteSharedLibrarySource) || (source == ITMTRemoteiPodSource) || (source == ITMTRemoteGenericDeviceSource) || (source == ITMTRemoteCDSource) ) {
- tempItem = [playlistsMenu itemAtIndex:[playlistsMenu numberOfItems] + [indices indexOfObject:[NSNumber numberWithInt:[[[MainController sharedController] currentRemote] currentSourceIndex]]] - [indices count]];
- [tempItem setState:NSOnState];
- [[[tempItem submenu] itemAtIndex:_currentPlaylist - 1] setState:NSOnState];
- } else if (source == ITMTRemoteLibrarySource && _currentPlaylist) {
- [[playlistsMenu itemAtIndex:_currentPlaylist - 1] setState:NSOnState];
- }
+ NS_DURING
+ if (_currentPlaylist != -1) {
+ if ( (source == ITMTRemoteSharedLibrarySource) || (source == ITMTRemoteiPodSource) || (source == ITMTRemoteGenericDeviceSource) || (source == ITMTRemoteCDSource) ) {
+ tempItem = [playlistsMenu itemAtIndex:[playlistsMenu numberOfItems] + [indices indexOfObject:[NSNumber numberWithInt:[[[MainController sharedController] currentRemote] currentSourceIndex]]] - [indices count]];
+ [tempItem setState:NSOnState];
+ }
+ }
+ NS_HANDLER
+ NS_ENDHANDLER
[indices release];
tempItem = [playlistsMenu addItemWithTitle:NSLocalizedString(@"refresh", @"Refresh") action:@selector(rebuildSubmenus) keyEquivalent:@""];
[tempItem setTarget:self];
[tempItem setImage:[NSImage imageNamed:@"ChasingArrow"]];
ITDebugLog(@"Done Building \"Playlists\" menu");
- return playlistsMenu;
+ NS_VALUERETURN(playlistsMenu, NSMenu *);
+ NS_HANDLER
+ [playlistsMenu release];
+ _continue = NO;
+ NS_VALUERETURN(nil, NSMenu *);
+ NS_ENDHANDLER
}
- (NSMenu *)eqMenu
tempItem = [eqMenu addItemWithTitle:@"Enabled" action:@selector(performEqualizerMenuAction:) keyEquivalent:@""];
[tempItem setTag:-1];
[tempItem setTarget:self];
- NS_DURING
- [tempItem setState:[[[MainController sharedController] currentRemote] equalizerEnabled] ? NSOnState : NSOffState];
- NS_HANDLER
- [[MainController sharedController] networkError:localException];
- NS_ENDHANDLER
[eqMenu addItem:[NSMenuItem separatorItem]];
for (i = 0; i < [eqPresets count]; i++) {
- (NSMenu *)artistsMenu
{
- NSMenu *artistsMenu = [[NSMenu alloc] initWithTitle:@""];
+ NSMenu *artistsMenu = [[NSMenu alloc] initWithTitle:@"Artists"];
NSEnumerator *artistsEnumerator;
NSString *nextArtist;
id <NSMenuItem> tempItem;
artistsEnumerator = [[[[MainController sharedController] currentRemote] artists] objectEnumerator];
while ( (nextArtist = [artistsEnumerator nextObject]) ) {
tempItem = [artistsMenu addItemWithTitle:nextArtist action:@selector(performBrowseMenuAction:) keyEquivalent:@""];
- [tempItem setRepresentedObject:nextArtist];
- [tempItem setTag:1];
[tempItem setTarget:self];
}
NS_HANDLER
- (NSMenu *)albumsMenu
{
- NSMenu *albumsMenu = [[NSMenu alloc] initWithTitle:@""];
+ NSMenu *albumsMenu = [[NSMenu alloc] initWithTitle:@"Albums"];
NSEnumerator *albumsEnumerator;
NSString *nextAlbum;
id <NSMenuItem> tempItem;
albumsEnumerator = [[[[MainController sharedController] currentRemote] albums] objectEnumerator];
while ( (nextAlbum = [albumsEnumerator nextObject]) ) {
tempItem = [albumsMenu addItemWithTitle:nextAlbum action:@selector(performBrowseMenuAction:) keyEquivalent:@""];
- [tempItem setRepresentedObject:nextAlbum];
- [tempItem setTag:2];
[tempItem setTarget:self];
}
NS_HANDLER
ITDebugLog(@"Performing Menu Action: Preferences...");
[[MainController sharedController] showPreferences];
break;
+ case MTMenuAboutItem:
+ ITDebugLog(@"Performing Menu Action: About MenuTunes...");
+ [[ITAboutWindowController sharedController] showAboutWindow];
+ break;
case MTMenuQuitItem:
ITDebugLog(@"Performing Menu Action: Quit");
[[MainController sharedController] quitMenuTunes];
break;
- case MTMenuRegisterItem:
- ITDebugLog(@"Performing Menu Action: Register");
- [[MainController sharedController] blingNow];
- break;
default:
ITDebugLog(@"Performing Menu Action: Unimplemented Menu Item OR Child-bearing Menu Item");
break;
- (void)performBrowseMenuAction:(id)sender
{
- ITDebugLog(@"Browse action selected on item with object %@ and tag %i", [sender representedObject], [sender tag]);
+ ITDebugLog(@"Browse action selected on item named %@", [sender title]);
/*
** 1 - Artist
** 2 - Album
** 3 - Genre?
*/
- [[MainController sharedController] makePlaylistWithTerm:[sender representedObject] ofType:[sender tag]];
+ [[MainController sharedController] makePlaylistWithTerm:[sender title] ofType:(([[[sender menu] title] isEqualToString:@"Artists"]) ? 1 : 2)];
}
- (void)updateMenu