Added checking to prevent cascading threads and server checks.
[MenuTunes.git] / MenuController.m
1 //
2 //  MenuController.m
3 //  MenuTunes
4 //
5 //  Created by Joseph Spiros on Wed Apr 30 2003.
6 //  Copyright (c) 2003 iThink Software. All rights reserved.
7 //
8
9 #import "MenuController.h"
10 #import "MainController.h"
11 #import "NetworkController.h"
12 #import "ITMTRemote.h"
13 #import <ITFoundation/ITDebug.h>
14 #import <ITKit/ITHotKeyCenter.h>
15 #import <ITKit/ITHotKey.h>
16 #import <ITKit/ITKeyCombo.h>
17 #import <ITKit/ITCategory-NSMenu.h>
18
19 @interface MenuController (SubmenuMethods)
20 - (NSMenu *)ratingMenu;
21 - (NSMenu *)upcomingSongsMenu;
22 - (NSMenu *)playlistsMenu;
23 - (NSMenu *)eqMenu;
24 - (void)setKeyEquivalentForCode:(short)code andModifiers:(long)modifiers
25         onItem:(id <NSMenuItem>)item;
26 - (BOOL)iPodWithNameAutomaticallyUpdates:(NSString *)name;
27 @end
28
29 @implementation MenuController
30
31 - (id)init
32 {
33     if ( (self = [super init]) ) {
34         _menuLayout = [[NSMutableArray alloc] initWithCapacity:0];
35     }
36     return self;
37 }
38
39 - (NSMenu *)menu
40 {
41     NSMenu *menu = [[NSMenu alloc] initWithTitle:@""];
42     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
43     NSArray *menuArray = [defaults arrayForKey:@"menu"];
44     NSEnumerator *enumerator = [menuArray objectEnumerator];
45     NSString *nextObject;
46     id <NSMenuItem> tempItem;
47     NSEnumerator *itemEnum;
48     ITHotKey *hotKey;
49     NSArray *hotKeys = [[ITHotKeyCenter sharedCenter] allHotKeys];
50     int currentSongRating = 0;
51     
52     //Get the information
53     NS_DURING
54         _currentPlaylist = [[[MainController sharedController] currentRemote] currentPlaylistIndex];
55         _playingRadio = ([[[MainController sharedController] currentRemote] currentPlaylistClass] == ITMTRemotePlayerRadioPlaylist);
56         currentSongRating = ( [[[MainController sharedController] currentRemote] currentSongRating] != -1 );
57     NS_HANDLER
58         [[MainController sharedController] networkError:localException];
59     NS_ENDHANDLER
60     
61     ITDebugLog(@"Reset menu if required.");
62     
63     //Kill the old submenu items
64     if ( (tempItem = [_currentMenu itemWithTag:1]) ) {
65         ITDebugLog(@"Removing \"Song Rating\" submenu.");
66         [tempItem setSubmenu:nil];
67     }
68     
69     if ( (tempItem = [_currentMenu itemWithTag:2]) ) {
70         ITDebugLog(@"Removing \"Upcoming Songs\" submenu.");
71         [tempItem setSubmenu:nil];
72     }
73     
74     if ( (tempItem = [_currentMenu itemWithTag:3]) ) {
75         ITDebugLog(@"Removing \"Playlists\" submenu.");
76         [tempItem setSubmenu:nil];
77     }
78     
79     if ( (tempItem = [_currentMenu itemWithTag:4]) ) {
80         ITDebugLog(@"Removing \"EQ Presets\" submenu.");
81         [tempItem setSubmenu:nil];
82     }
83     
84     ITDebugLog(@"Begin building menu.");
85     
86     //create our menu
87     while ( (nextObject = [enumerator nextObject]) ) {
88         //Main menu items
89         if ([nextObject isEqualToString:@"playPause"]) {
90             ITDebugLog(@"Add \"Play\"/\"Pause\" menu item.");
91             tempItem = [menu addItemWithTitle:NSLocalizedString(@"play", @"Play")
92                     action:@selector(performMainMenuAction:)
93                     keyEquivalent:@""];
94             [tempItem setTag:MTMenuPlayPauseItem];
95             [tempItem setTarget:self];
96             
97             itemEnum = [hotKeys objectEnumerator];
98             while ( (hotKey = [itemEnum nextObject]) ) {
99                 if ([[hotKey name] isEqualToString:@"PlayPause"]) {
100                     ITKeyCombo *combo = [hotKey keyCombo];
101                     [self setKeyEquivalentForCode:[combo keyCode]
102                           andModifiers:[combo modifiers]
103                           onItem:tempItem];
104                 }
105             }
106             
107             ITDebugLog(@"Set \"Play\"/\"Pause\" menu item's title to correct state.");
108             NS_DURING
109                 switch ([[[MainController sharedController] currentRemote] playerPlayingState]) {
110                     case ITMTRemotePlayerPlaying:
111                         [tempItem setTitle:NSLocalizedString(@"pause", @"Pause")];
112                     break;
113                     case ITMTRemotePlayerRewinding:
114                     case ITMTRemotePlayerForwarding:
115                         [tempItem setTitle:NSLocalizedString(@"resume", @"Resume")];
116                     break;
117                     default:
118                     break;
119                 }
120             NS_HANDLER
121                 [[MainController sharedController] networkError:localException];
122             NS_ENDHANDLER
123         } else if ([nextObject isEqualToString:@"nextTrack"]) {
124             ITDebugLog(@"Add \"Next Track\" menu item.");
125             tempItem = [menu addItemWithTitle:NSLocalizedString(@"nextTrack", @"Next Track")
126                     action:@selector(performMainMenuAction:)
127                     keyEquivalent:@""];
128             
129             itemEnum = [hotKeys objectEnumerator];
130             while ( (hotKey = [itemEnum nextObject]) ) {
131                 if ([[hotKey name] isEqualToString:@"NextTrack"]) {
132                     ITKeyCombo *combo = [hotKey keyCombo];
133                     [self setKeyEquivalentForCode:[combo keyCode]
134                           andModifiers:[combo modifiers]
135                           onItem:tempItem];
136                 }
137             }
138             
139             if (_currentPlaylist) {
140                 [tempItem setTag:MTMenuNextTrackItem];
141                 [tempItem setTarget:self];
142             }
143         } else if ([nextObject isEqualToString:@"prevTrack"]) {
144             ITDebugLog(@"Add \"Previous Track\" menu item.");
145             tempItem = [menu addItemWithTitle:NSLocalizedString(@"prevTrack", @"Previous Track")
146                     action:@selector(performMainMenuAction:)
147                     keyEquivalent:@""];
148             
149             itemEnum = [hotKeys objectEnumerator];
150             while ( (hotKey = [itemEnum nextObject]) ) {
151                 if ([[hotKey name] isEqualToString:@"PrevTrack"]) {
152                     ITKeyCombo *combo = [hotKey keyCombo];
153                     [self setKeyEquivalentForCode:[combo keyCode]
154                           andModifiers:[combo modifiers]
155                           onItem:tempItem];
156                 }
157             }
158             
159             if (_currentPlaylist) {
160                 [tempItem setTag:MTMenuPreviousTrackItem];
161                 [tempItem setTarget:self];
162             }
163         } else if ([nextObject isEqualToString:@"fastForward"]) {
164             ITDebugLog(@"Add \"Fast Forward\" menu item.");
165             tempItem = [menu addItemWithTitle:NSLocalizedString(@"fastForward", @"Fast Forward")
166                     action:@selector(performMainMenuAction:)
167                     keyEquivalent:@""];
168             if (_currentPlaylist) {
169                 [tempItem setTag:MTMenuFastForwardItem];
170                 [tempItem setTarget:self];
171             }
172         } else if ([nextObject isEqualToString:@"rewind"]) {
173             ITDebugLog(@"Add \"Rewind\" menu item.");
174             tempItem = [menu addItemWithTitle:NSLocalizedString(@"rewind", @"Rewind")
175                     action:@selector(performMainMenuAction:)
176                     keyEquivalent:@""];
177             if (_currentPlaylist) {
178                 [tempItem setTag:MTMenuRewindItem];
179                 [tempItem setTarget:self];
180             }
181         } else if ([nextObject isEqualToString:@"showPlayer"]) {
182             ITDebugLog(@"Add \"Show Player\" menu item.");
183             NS_DURING
184                 tempItem = [menu addItemWithTitle:[NSString stringWithFormat:@"%@ %@",
185                                 NSLocalizedString(@"show", @"Show"),
186                                     [[[MainController sharedController] currentRemote] playerSimpleName]]
187                                 action:@selector(performMainMenuAction:)
188                                 keyEquivalent:@""];
189             NS_HANDLER
190                 [[MainController sharedController] networkError:localException];
191             NS_ENDHANDLER
192             
193             itemEnum = [hotKeys objectEnumerator];
194             while ( (hotKey = [itemEnum nextObject]) ) {
195                 if ([[hotKey name] isEqualToString:@"ShowPlayer"]) {
196                     ITKeyCombo *combo = [hotKey keyCombo];
197                     [self setKeyEquivalentForCode:[combo keyCode]
198                           andModifiers:[combo modifiers]
199                           onItem:tempItem];
200                 }
201             }
202             
203             [tempItem setTarget:self];
204             [tempItem setTag:MTMenuShowPlayerItem];
205         } else if ([nextObject isEqualToString:@"preferences"]) {
206             ITDebugLog(@"Add \"Preferences...\" menu item.");
207             tempItem = [menu addItemWithTitle:NSLocalizedString(@"preferences", @"Preferences...")
208                     action:@selector(performMainMenuAction:)
209                     keyEquivalent:@""];
210             [tempItem setTag:MTMenuPreferencesItem];
211             [tempItem setTarget:self];
212         } else if ([nextObject isEqualToString:@"quit"]) {
213             if ([[MainController sharedController] blingBling] == NO) {
214                 ITDebugLog(@"Add \"Register MenuTunes...\" menu item.");
215                 tempItem = [menu addItemWithTitle:NSLocalizedString(@"register", @"Register MenuTunes...") action:@selector(performMainMenuAction:) keyEquivalent:@""];
216                 [tempItem setTag:MTMenuRegisterItem];
217                 [tempItem setTarget:self];
218             }
219             ITDebugLog(@"Add \"Quit\" menu item.");
220             tempItem = [menu addItemWithTitle:NSLocalizedString(@"quit", @"Quit")
221                     action:@selector(performMainMenuAction:)
222                     keyEquivalent:@""];
223             [tempItem setTag:MTMenuQuitItem];
224             [tempItem setTarget:self];
225         } else if ([nextObject isEqualToString:@"trackInfo"]) {
226             ITDebugLog(@"Check to see if a Track is playing...");
227             //Handle playing radio too
228             if (_currentPlaylist) {
229                 NSString *title = nil;
230                 NS_DURING
231                     title = [[[MainController sharedController] currentRemote] currentSongTitle];
232                 NS_HANDLER
233                     [[MainController sharedController] networkError:localException];
234                 NS_ENDHANDLER
235                 ITDebugLog(@"A Track is Playing, Add \"Track Info\" menu items.");
236                 ITDebugLog(@"Add \"Now Playing\" menu item.");
237                 [menu addItemWithTitle:NSLocalizedString(@"nowPlaying", @"Now Playing") action:NULL keyEquivalent:@""];
238                 
239                 if ([title length] > 0) {
240                     ITDebugLog(@"Add Track Title (\"%@\") menu item.", title);
241                     [menu indentItem:
242                         [menu addItemWithTitle:title action:nil keyEquivalent:@""]];
243                 }
244                 
245                 if (!_playingRadio) {
246                     if ([defaults boolForKey:@"showAlbum"]) {
247                         NSString *curAlbum = nil;
248                         NS_DURING
249                             curAlbum = [[[MainController sharedController] currentRemote] currentSongAlbum];
250                         NS_HANDLER
251                             [[MainController sharedController] networkError:localException];
252                         NS_ENDHANDLER
253                         ITDebugLog(@"Add Track Album (\"%@\") menu item.", curAlbum);
254                         if ( curAlbum ) {
255                             [menu indentItem:
256                                 [menu addItemWithTitle:curAlbum action:nil keyEquivalent:@""]];
257                         }
258                     }
259                     
260                     if ([defaults boolForKey:@"showArtist"]) {
261                         NSString *curArtist = nil;
262                         NS_DURING
263                             curArtist = [[[MainController sharedController] currentRemote] currentSongArtist];
264                         NS_HANDLER
265                             [[MainController sharedController] networkError:localException];
266                         NS_ENDHANDLER
267                         ITDebugLog(@"Add Track Artist (\"%@\") menu item.", curArtist);
268                         if ( curArtist ) {
269                             [menu indentItem:
270                                 [menu addItemWithTitle:curArtist action:nil keyEquivalent:@""]];
271                         }
272                     }
273                     
274                     if ([defaults boolForKey:@"showComposer"]) {
275                         NSString *curComposer = nil;
276                         NS_DURING
277                             curComposer = [[[MainController sharedController] currentRemote] currentSongComposer];
278                         NS_HANDLER
279                             [[MainController sharedController] networkError:localException];
280                         NS_ENDHANDLER
281                         ITDebugLog(@"Add Track Composer (\"%@\") menu item.", curComposer);
282                         if ( curComposer ) {
283                             [menu indentItem:
284                                 [menu addItemWithTitle:curComposer action:nil keyEquivalent:@""]];
285                         }
286                     }
287                     
288                     if ([defaults boolForKey:@"showTrackNumber"]) {
289                         int track = 0;
290                         NS_DURING
291                             track = [[[MainController sharedController] currentRemote] currentSongTrack];
292                         NS_HANDLER
293                             [[MainController sharedController] networkError:localException];
294                         NS_ENDHANDLER
295                         ITDebugLog(@"Add Track Number (\"Track %i\") menu item.", track);
296                         if ( track > 0 ) {
297                             [menu indentItem:
298                                 [menu addItemWithTitle:[NSString stringWithFormat:@"%@ %i", NSLocalizedString(@"track", @"Track"), track] action:nil keyEquivalent:@""]];
299                         }
300                     }
301                 }
302                 
303                 NS_DURING
304                     if ([defaults boolForKey:@"showTime"] && ( ([[[MainController sharedController] currentRemote] currentSongElapsed] != nil) || ([[[MainController sharedController] currentRemote] currentSongLength] != nil) )) {
305                         ITDebugLog(@"Add Track Elapsed (\"%@/%@\") menu item.", [[[MainController sharedController] currentRemote] currentSongElapsed], [[[MainController sharedController] currentRemote] currentSongLength]);
306                         [menu indentItem:[menu addItemWithTitle:[NSString stringWithFormat:@"%@/%@", [[[MainController sharedController] currentRemote] currentSongElapsed], [[[MainController sharedController] currentRemote] currentSongLength]] action:nil keyEquivalent:@""]];
307                     }
308                 NS_HANDLER
309                     [[MainController sharedController] networkError:localException];
310                 NS_ENDHANDLER
311                 
312                 if (!_playingRadio) {
313                     NS_DURING
314                         if ([defaults boolForKey:@"showTrackRating"] && ( [[[MainController sharedController] currentRemote] currentSongRating] != -1.0 )) {
315                             NSString *string = nil;
316                             switch ((int)([[[MainController sharedController] currentRemote] currentSongRating] * 5)) {
317                                 case 0:
318                                     string = [NSString stringWithUTF8String:"☆☆☆☆☆"];
319                                 break;
320                                 case 1:
321                                     string = [NSString stringWithUTF8String:"★☆☆☆☆"];
322                                 break;
323                                 case 2:
324                                     string = [NSString stringWithUTF8String:"★★☆☆☆"];
325                                 break;
326                                 case 3:
327                                     string = [NSString stringWithUTF8String:"★★★☆☆"];
328                                 break;
329                                 case 4:
330                                     string = [NSString stringWithUTF8String:"★★★★☆"];
331                                 break;
332                                 case 5:
333                                     string = [NSString stringWithUTF8String:"★★★★★"];
334                                 break;
335                             }
336                             ITDebugLog(@"Add Track Rating (\"%@\") menu item.", string);
337                             [menu indentItem:[menu addItemWithTitle:string action:nil keyEquivalent:@""]];
338                         }
339                     NS_HANDLER
340                         [[MainController sharedController] networkError:localException];
341                     NS_ENDHANDLER
342                     
343                     /*if ([tempItem respondsToSelector:@selector(setAttributedTitle:)] && [defaults boolForKey:@"showAlbumArtwork"] && ![[NetworkController sharedController] isConnectedToServer]) {
344                         NSImage *image = [[[MainController sharedController] currentRemote] currentSongAlbumArt];
345                         if (image) {
346                             NSSize oldSize, newSize;
347                             oldSize = [image size];
348                             if (oldSize.width > oldSize.height) newSize = NSMakeSize(110,oldSize.height * (110.0f / oldSize.width));
349                             else newSize = NSMakeSize(oldSize.width * (110.0f / oldSize.height),110);
350                             image = [[[[NSImage alloc] initWithData:[image TIFFRepresentation]] autorelease] imageScaledSmoothlyToSize:newSize];
351                             
352                             tempItem = [menu addItemWithTitle:@"" action:nil keyEquivalent:@""];
353                             NSTextAttachment *attachment = [[[NSTextAttachment alloc] init] autorelease];
354                             [[attachment attachmentCell] setImage:image];
355                             NSAttributedString *attrString = [NSAttributedString attributedStringWithAttachment:attachment];
356                             [tempItem setAttributedTitle:attrString];
357                         }
358                     }*/
359                 }
360             } else {
361                 ITDebugLog(@"No Track is Playing, Add \"No Song\" menu item.");
362                 [menu addItemWithTitle:NSLocalizedString(@"noSong", @"No Song") action:NULL keyEquivalent:@""];
363             }
364         } else if ([nextObject isEqualToString:@"separator"]) {
365             ITDebugLog(@"Add a separator menu item.");
366             [menu addItem:[NSMenuItem separatorItem]];
367         //Submenu items
368         } else if ([nextObject isEqualToString:@"playlists"]) {
369             ITDebugLog(@"Add \"Playlists\" submenu.");
370             tempItem = [menu addItemWithTitle:NSLocalizedString(@"playlists", @"Playlists")
371                     action:nil
372                     keyEquivalent:@""];
373             [tempItem setSubmenu:_playlistsMenu];
374             [tempItem setTag:3];
375         } else if ([nextObject isEqualToString:@"eqPresets"]) {
376             ITDebugLog(@"Add \"EQ Presets\" submenu.");
377             tempItem = [menu addItemWithTitle:NSLocalizedString(@"eqPresets", @"EQ Presets")
378                     action:nil
379                     keyEquivalent:@""];
380             [tempItem setSubmenu:_eqMenu];
381             [tempItem setTag:4];
382             
383             itemEnum = [[_eqMenu itemArray] objectEnumerator];
384             while ( (tempItem = [itemEnum nextObject]) ) {
385                 [tempItem setState:NSOffState];
386             }
387             NS_DURING
388                 [[_eqMenu itemAtIndex:([[[MainController sharedController] currentRemote] currentEQPresetIndex] - 1)] setState:NSOnState];
389             NS_HANDLER
390                 [[MainController sharedController] networkError:localException];
391             NS_ENDHANDLER
392         } else if ([nextObject isEqualToString:@"songRating"] && currentSongRating) {
393                 ITDebugLog(@"Add \"Song Rating\" submenu.");
394                 tempItem = [menu addItemWithTitle:NSLocalizedString(@"songRating", @"Song Rating")
395                         action:nil
396                         keyEquivalent:@""];
397                 [tempItem setSubmenu:_ratingMenu];
398                 [tempItem setTag:1];
399                 if (_playingRadio || !_currentPlaylist) {
400                     [tempItem setEnabled:NO];
401                 }
402                 
403                 itemEnum = [[_ratingMenu itemArray] objectEnumerator];
404                 while ( (tempItem = [itemEnum nextObject]) ) {
405                     [tempItem setState:NSOffState];
406                 }
407                 
408                 NS_DURING
409                     [[_ratingMenu itemAtIndex:([[[MainController sharedController] currentRemote] currentSongRating] * 5)] setState:NSOnState];
410                 NS_HANDLER
411                     [[MainController sharedController] networkError:localException];
412                 NS_ENDHANDLER
413             } else if ([nextObject isEqualToString:@"upcomingSongs"]) {
414                 ITDebugLog(@"Add \"Upcoming Songs\" submenu.");
415                 tempItem = [menu addItemWithTitle:NSLocalizedString(@"upcomingSongs", @"Upcoming Songs")
416                         action:nil
417                         keyEquivalent:@""];
418                 [tempItem setSubmenu:_upcomingSongsMenu];
419                 [tempItem setTag:2];
420                 if (_playingRadio || !_currentPlaylist) {
421                     [tempItem setEnabled:NO];
422                 }
423             }
424         }
425     ITDebugLog(@"Finished building menu.");
426     [_currentMenu release];
427     _currentMenu = menu;
428     return _currentMenu;
429 }
430
431 - (NSMenu *)menuForNoPlayer
432 {
433     NSMenu *menu = [[NSMenu alloc] initWithTitle:@""];
434     id <NSMenuItem> tempItem = nil;
435     ITDebugLog(@"Creating menu for when player isn't running.");
436     NS_DURING
437         ITDebugLog(@"Add \"Open %@\" menu item.", [[[MainController sharedController] currentRemote] playerSimpleName]);
438         tempItem = [menu addItemWithTitle:[NSString stringWithFormat:@"%@ %@", NSLocalizedString(@"open", @"Open"), [[[MainController sharedController] currentRemote] playerSimpleName]] action:@selector(performMainMenuAction:) keyEquivalent:@""];
439     NS_HANDLER
440         [[MainController sharedController] networkError:localException];
441     NS_ENDHANDLER
442     [tempItem setTag:MTMenuShowPlayerItem];
443     [tempItem setTarget:self];
444     ITDebugLog(@"Add a separator menu item.");
445     [menu addItem:[NSMenuItem separatorItem]];
446     ITDebugLog(@"Add \"Preferences...\" menu item.");
447     tempItem = [menu addItemWithTitle:NSLocalizedString(@"preferences", @"Preferences...") action:@selector(performMainMenuAction:) keyEquivalent:@""];
448     [tempItem setTag:MTMenuPreferencesItem];
449     [tempItem setTarget:self];
450     if ([[MainController sharedController] blingBling] == NO) {
451         ITDebugLog(@"Add \"Register MenuTunes...\" menu item.");
452         tempItem = [menu addItemWithTitle:NSLocalizedString(@"register", @"Register MenuTunes...") action:@selector(performMainMenuAction:) keyEquivalent:@""];
453         [tempItem setTag:MTMenuRegisterItem];
454         [tempItem setTarget:self];
455     }
456     ITDebugLog(@"Add \"Quit\" menu item.");
457     tempItem = [menu addItemWithTitle:NSLocalizedString(@"quit", @"Quit") action:@selector(performMainMenuAction:) keyEquivalent:@""];
458     [tempItem setTag:MTMenuQuitItem];
459     [tempItem setTarget:self];
460     return [menu autorelease];
461 }
462
463 - (void)rebuildSubmenus
464 {
465     ITDebugLog(@"Rebuilding all of the submenus.");
466     NS_DURING
467         _currentPlaylist = [[[MainController sharedController] currentRemote] currentPlaylistIndex];
468         _currentTrack = [[[MainController sharedController] currentRemote] currentSongIndex];
469         _playingRadio = ([[[MainController sharedController] currentRemote] currentPlaylistClass] == ITMTRemotePlayerRadioPlaylist);
470     NS_HANDLER
471         [[MainController sharedController] networkError:localException];
472     NS_ENDHANDLER
473     ITDebugLog(@"Releasing old submenus.");
474     ITDebugLog(@" - Rating menu");
475     [_ratingMenu release];
476     ITDebugLog(@" - Upcoming songs menu");
477     [_upcomingSongsMenu release];
478     ITDebugLog(@" - Playlists menu");
479     [_playlistsMenu release];
480     ITDebugLog(@" - EQ menu");
481     [_eqMenu release];
482     ITDebugLog(@"Beginning Rebuild of \"Song Rating\" submenu.");
483     _ratingMenu = [self ratingMenu];
484     ITDebugLog(@"Beginning Rebuild of \"Upcoming Songs\" submenu.");
485     _upcomingSongsMenu = [self upcomingSongsMenu];
486     ITDebugLog(@"Beginning Rebuild of \"Playlists\" submenu.");
487     _playlistsMenu = [self playlistsMenu];
488     ITDebugLog(@"Beginning Rebuild of \"EQ Presets\" submenu.");
489     _eqMenu = [self eqMenu];
490     ITDebugLog(@"Done rebuilding all of the submenus.");
491 }
492
493 - (NSMenu *)ratingMenu
494 {
495     NSMenu *ratingMenu = [[NSMenu alloc] initWithTitle:@""];
496     NSEnumerator *itemEnum;
497     id  anItem;
498     int itemTag = 0;
499     SEL itemSelector = @selector(performRatingMenuAction:);
500     
501     ITDebugLog(@"Building \"Song Rating\" menu.");
502     
503     [ratingMenu addItemWithTitle:[NSString stringWithUTF8String:"☆☆☆☆☆"] action:nil keyEquivalent:@""];
504     [ratingMenu addItemWithTitle:[NSString stringWithUTF8String:"★☆☆☆☆"] action:nil keyEquivalent:@""];
505     [ratingMenu addItemWithTitle:[NSString stringWithUTF8String:"★★☆☆☆"] action:nil keyEquivalent:@""];
506     [ratingMenu addItemWithTitle:[NSString stringWithUTF8String:"★★★☆☆"] action:nil keyEquivalent:@""];
507     [ratingMenu addItemWithTitle:[NSString stringWithUTF8String:"★★★★☆"] action:nil keyEquivalent:@""];
508     [ratingMenu addItemWithTitle:[NSString stringWithUTF8String:"★★★★★"] action:nil keyEquivalent:@""];
509     
510     itemEnum = [[ratingMenu itemArray] objectEnumerator];
511     while ( (anItem = [itemEnum nextObject]) ) {
512         ITDebugLog(@"Setting up \"%@\" menu item.", [anItem title]);
513         [anItem setAction:itemSelector];
514         [anItem setTarget:self];
515         [anItem setTag:itemTag];
516         itemTag += 20;
517     }
518     ITDebugLog(@"Done Building \"Song Rating\" menu.");
519     return ratingMenu;
520 }
521
522 - (NSMenu *)upcomingSongsMenu
523 {
524     NSMenu *upcomingSongsMenu = [[NSMenu alloc] initWithTitle:@""];
525     int numSongs = 0, numSongsInAdvance = [[NSUserDefaults standardUserDefaults] integerForKey:@"SongsInAdvance"];
526     
527     NS_DURING
528         numSongs = [[[MainController sharedController] currentRemote] numberOfSongsInPlaylistAtIndex:_currentPlaylist];
529     NS_HANDLER
530         [[MainController sharedController] networkError:localException];
531     NS_ENDHANDLER
532     
533     ITDebugLog(@"Building \"Upcoming Songs\" menu.");
534     if (_currentPlaylist && !_playingRadio) {
535         if (numSongs > 0) {
536             int i;
537             for (i = _currentTrack + 1; i <= _currentTrack + numSongsInAdvance; i++) {
538                 if (i <= numSongs) {
539                     NSString *curSong = nil;
540                     NS_DURING
541                         curSong = [[[MainController sharedController] currentRemote] songTitleAtIndex:i];
542                     NS_HANDLER
543                         [[MainController sharedController] networkError:localException];
544                     NS_ENDHANDLER
545                     id <NSMenuItem> songItem;
546                     ITDebugLog(@"Adding song: %@", curSong);
547                     songItem = [upcomingSongsMenu addItemWithTitle:curSong action:@selector(performUpcomingSongsMenuAction:) keyEquivalent:@""];
548                     [songItem setTag:i];
549                     [songItem setTarget:self];
550                 } else {
551                     break;
552                 }
553             }
554         }
555         
556         if ([upcomingSongsMenu numberOfItems] == 0) {
557             [upcomingSongsMenu addItemWithTitle:NSLocalizedString(@"noUpcomingSongs", @"No upcoming songs.") action:NULL keyEquivalent:@""];
558         }
559     }
560     ITDebugLog(@"Done Building \"Upcoming Songs\" menu.");
561     return upcomingSongsMenu;
562 }
563
564 /*- (NSMenu *)playlistsMenu
565 {
566     NSMenu *playlistsMenu = [[NSMenu alloc] initWithTitle:@""];
567     NSArray *playlists;
568     id <NSMenuItem> tempItem;
569     ITMTRemotePlayerSource source = [[[MainController sharedController] currentRemote] currentSource];
570     int i;
571     NS_DURING
572         playlists = [[[MainController sharedController] currentRemote] playlists];
573     NS_HANDLER
574         [[MainController sharedController] networkError:localException];
575     NS_ENDHANDLER
576     
577     ITDebugLog(@"Building \"Playlists\" menu.");
578     
579     for (i = 0; i < [playlists count]; i++) {
580         NSString *curPlaylist = [playlists objectAtIndex:i];
581         ITDebugLog(@"Adding playlist: %@", curPlaylist);
582         tempItem = [playlistsMenu addItemWithTitle:curPlaylist action:@selector(performPlaylistMenuAction:) keyEquivalent:@""];
583         [tempItem setTag:i + 1];
584         [tempItem setTarget:self];
585     }
586     
587     if (source == ITMTRemoteRadioSource) {
588         [[playlistsMenu addItemWithTitle:NSLocalizedString(@"radio", @"Radio") action:NULL keyEquivalent:@""] setState:NSOnState];
589     } else if (source == ITMTRemoteGenericDeviceSource) {
590         [[playlistsMenu addItemWithTitle:NSLocalizedString(@"genericDevice", @"Generic Device") action:NULL keyEquivalent:@""] setState:NSOnState];
591     } else if (source == ITMTRemoteiPodSource) {
592         [[playlistsMenu addItemWithTitle:NSLocalizedString(@"iPod", @"iPod") action:NULL keyEquivalent:@""] setState:NSOnState];
593     } else if (source == ITMTRemoteCDSource) {
594         [[playlistsMenu addItemWithTitle:NSLocalizedString(@"cd", @"CD") action:NULL keyEquivalent:@""] setState:NSOnState];
595     } else if (source == ITMTRemoteSharedLibrarySource) {
596         [[playlistsMenu addItemWithTitle:NSLocalizedString(@"sharedLibrary", @"Shared Library") action:NULL keyEquivalent:@""] setState:NSOnState];
597     } else if (source == ITMTRemoteLibrarySource && _currentPlaylist) {
598         [[playlistsMenu itemAtIndex:_currentPlaylist - 1] setState:NSOnState];
599     }
600     ITDebugLog(@"Done Building \"Playlists\" menu");
601     return playlistsMenu;
602 }*/
603
604
605 - (NSMenu *)playlistsMenu
606 {
607     NSMenu *playlistsMenu = [[NSMenu alloc] initWithTitle:@""];
608     NSArray *playlists = nil;
609     id <NSMenuItem> tempItem;
610     ITMTRemotePlayerSource source = [[[MainController sharedController] currentRemote] currentSource];
611     int i, j;
612     NSMutableArray *indices = [[NSMutableArray alloc] init];
613     NS_DURING
614         playlists = [[[MainController sharedController] currentRemote] playlists];
615     NS_HANDLER
616         [[MainController sharedController] networkError:localException];
617     NS_ENDHANDLER
618     ITDebugLog(@"Building \"Playlists\" menu.");
619     {
620         NSArray *curPlaylist = [playlists objectAtIndex:0];
621         NSString *name = [curPlaylist objectAtIndex:0];
622         ITDebugLog(@"Adding main source: %@", name);
623         for (i = 3; i < [curPlaylist count]; i++) {
624             ITDebugLog(@"Adding playlist: %@", [curPlaylist objectAtIndex:i]);
625             tempItem = [playlistsMenu addItemWithTitle:[curPlaylist objectAtIndex:i] action:@selector(performPlaylistMenuAction:) keyEquivalent:@""];
626             [tempItem setTag:i - 1];
627             [tempItem setTarget:self];
628         }
629         ITDebugLog(@"Adding index to the index array.");
630         [indices addObject:[curPlaylist objectAtIndex:2]];
631     }
632     if ([playlists count] > 1) {
633         if ([[[playlists objectAtIndex:1] objectAtIndex:1] intValue] == ITMTRemoteRadioSource) {
634             [indices addObject:[[playlists objectAtIndex:1] objectAtIndex:2]];
635             if (source == ITMTRemoteRadioSource) {
636                 [playlistsMenu addItem:[NSMenuItem separatorItem]];
637                 [[playlistsMenu addItemWithTitle:NSLocalizedString(@"radio", @"Radio") action:@selector(performPlaylistMenuAction:) keyEquivalent:@""] setState:NSOnState];
638             }
639         } else {
640             [playlistsMenu addItem:[NSMenuItem separatorItem]];
641         }
642     }
643     
644     if ([playlists count] > 1) {
645         for (i = 1; i < [playlists count]; i++) {
646             NSArray *curPlaylist = [playlists objectAtIndex:i];
647             if ([[curPlaylist objectAtIndex:1] intValue] != ITMTRemoteRadioSource) {
648                 NSString *name = [curPlaylist objectAtIndex:0];
649                 NSMenu *submenu = [[NSMenu alloc] init];
650                 ITDebugLog(@"Adding source: %@", name);
651                 
652                 if ( ([[curPlaylist objectAtIndex:1] intValue] == ITMTRemoteiPodSource) && [self iPodWithNameAutomaticallyUpdates:name] ) {
653                     ITDebugLog(@"Invalid iPod source.");
654                     [playlistsMenu addItemWithTitle:name action:NULL keyEquivalent:@""];
655                 } else {
656                     for (j = 3; j < [curPlaylist count]; j++) {
657                         ITDebugLog(@"Adding playlist: %@", [curPlaylist objectAtIndex:j]);
658                         tempItem = [submenu addItemWithTitle:[curPlaylist objectAtIndex:j] action:@selector(performPlaylistMenuAction:) keyEquivalent:@""];
659                         [tempItem setTag:(i * 1000) + j - 1];
660                         [tempItem setTarget:self];
661                     }
662                     [[playlistsMenu addItemWithTitle:name action:NULL keyEquivalent:@""] setSubmenu:[submenu autorelease]];
663                 }
664                 ITDebugLog(@"Adding index to the index array.");
665                 [indices addObject:[curPlaylist objectAtIndex:2]];
666             }
667         }
668     }
669     ITDebugLog(@"Checking the current source.");
670     if ( (source == ITMTRemoteSharedLibrarySource) || (source == ITMTRemoteiPodSource) || (source == ITMTRemoteGenericDeviceSource) || (source == ITMTRemoteCDSource) ) {
671         tempItem = [playlistsMenu itemAtIndex:[playlistsMenu numberOfItems] + [indices indexOfObject:[NSNumber numberWithInt:[[[MainController sharedController] currentRemote] currentSourceIndex]]] - [indices count]];
672         [tempItem setState:NSOnState];
673         [[[tempItem submenu] itemAtIndex:_currentPlaylist - 1] setState:NSOnState];
674     } else if (source == ITMTRemoteLibrarySource && _currentPlaylist) {
675         [[playlistsMenu itemAtIndex:_currentPlaylist - 1] setState:NSOnState];
676     }
677     [indices release];
678     ITDebugLog(@"Done Building \"Playlists\" menu");
679     return playlistsMenu;
680 }
681
682 - (NSMenu *)eqMenu
683 {
684     NSMenu *eqMenu = [[NSMenu alloc] initWithTitle:@""];
685     NSArray *eqPresets = nil;
686     id <NSMenuItem> tempItem;
687     int i;
688     
689     NS_DURING
690         eqPresets = [[[MainController sharedController] currentRemote] eqPresets];
691     NS_HANDLER
692         [[MainController sharedController] networkError:localException];
693     NS_ENDHANDLER
694     
695     ITDebugLog(@"Building \"EQ Presets\" menu.");
696     
697     for (i = 0; i < [eqPresets count]; i++) {
698         NSString *name;
699            if ( ( name = [eqPresets objectAtIndex:i] ) ) {
700             ITDebugLog(@"Adding EQ Preset: %@", name);
701             tempItem = [eqMenu addItemWithTitle:name
702                     action:@selector(performEqualizerMenuAction:)
703                     keyEquivalent:@""];
704             [tempItem setTag:i];
705             [tempItem setTarget:self];
706            }
707     }
708     ITDebugLog(@"Done Building \"EQ Presets\" menu");
709     return eqMenu;
710 }
711
712 - (void)performMainMenuAction:(id)sender
713 {
714     switch ( [sender tag] )
715     {
716         case MTMenuPlayPauseItem:
717             ITDebugLog(@"Performing Menu Action: Play/Pause");
718             [[MainController sharedController] playPause];
719             break;
720         case MTMenuFastForwardItem:
721             ITDebugLog(@"Performing Menu Action: Fast Forward");
722             [[MainController sharedController] fastForward];
723             break;
724         case MTMenuRewindItem:
725             ITDebugLog(@"Performing Menu Action: Rewind");
726             [[MainController sharedController] rewind];
727             break;
728         case MTMenuPreviousTrackItem:
729             ITDebugLog(@"Performing Menu Action: Previous Track");
730             [[MainController sharedController] prevSong];
731             break;
732         case MTMenuNextTrackItem:
733             ITDebugLog(@"Performing Menu Action: Next Track");
734             [[MainController sharedController] nextSong];
735             break;
736         case MTMenuShowPlayerItem:
737             ITDebugLog(@"Performing Menu Action: Show Main Interface");
738             [[MainController sharedController] showPlayer];
739             break;
740         case MTMenuPreferencesItem:
741             ITDebugLog(@"Performing Menu Action: Preferences...");
742             [[MainController sharedController] showPreferences];
743             break;
744         case MTMenuQuitItem:
745             ITDebugLog(@"Performing Menu Action: Quit");
746             [[MainController sharedController] quitMenuTunes];
747             break;
748         case MTMenuRegisterItem:
749             ITDebugLog(@"Performing Menu Action: Register");
750             [[MainController sharedController] blingNow];
751             break;
752         default:
753             ITDebugLog(@"Performing Menu Action: Unimplemented Menu Item OR Child-bearing Menu Item");
754             break;
755     }
756 }
757
758 - (void)performRatingMenuAction:(id)sender
759 {
760     ITDebugLog(@"Rating action selected on item with tag %i", [sender tag]);
761     [[MainController sharedController] selectSongRating:[sender tag]];
762 }
763
764 - (void)performPlaylistMenuAction:(id)sender
765 {
766     ITDebugLog(@"Playlist action selected on item with tag %i", [sender tag]);
767     [[MainController sharedController] selectPlaylistAtIndex:[sender tag]];
768 }
769
770 - (void)performEqualizerMenuAction:(id)sender
771 {
772     ITDebugLog(@"EQ action selected on item with tag %i", [sender tag]);
773     [[MainController sharedController] selectEQPresetAtIndex:[sender tag]];
774 }
775
776 - (void)performUpcomingSongsMenuAction:(id)sender
777 {
778     ITDebugLog(@"Song action selected on item with tag %i", [sender tag]);
779     [[MainController sharedController] selectSongAtIndex:[sender tag]];
780 }
781
782 - (void)updateMenu
783 {
784     ITDebugLog(@"Update Menu");
785     [_currentMenu update];
786 }
787
788 - (BOOL)validateMenuItem:(id <NSMenuItem>)menuItem
789 {
790     return YES;
791 }
792
793 //This is never used I know, keep it though
794 - (NSString *)systemUIColor
795 {
796     NSDictionary *tmpDict;
797     NSNumber *tmpNumber;
798     if ( (tmpDict = [NSDictionary dictionaryWithContentsOfFile:[@"~/Library/Preferences/.GlobalPreferences.plist" stringByExpandingTildeInPath]]) ) {
799         if ( (tmpNumber = [tmpDict objectForKey:@"AppleAquaColorVariant"]) ) {
800             if ( ([tmpNumber intValue] == 1) ) {
801                 return @"Aqua";
802             } else {
803                 return @"Graphite";
804             }
805         } else {
806             return @"Aqua";
807         }
808     } else {
809         return @"Aqua";
810     }
811 }
812
813 - (void)setKeyEquivalentForCode:(short)code andModifiers:(long)modifiers
814         onItem:(id <NSMenuItem>)item
815 {
816     unichar charcode = 'a';
817     int i;
818     long cocoaModifiers = 0;
819     static long carbonToCocoa[6][2] = 
820     {
821         { cmdKey, NSCommandKeyMask },
822         { optionKey, NSAlternateKeyMask },
823         { controlKey, NSControlKeyMask },
824         { shiftKey, NSShiftKeyMask },
825     };
826     
827     ITDebugLog(@"Setting Key Equivelent on menu item \"%@\".", [item title]);
828     
829     for (i = 0; i < 6; i++) {
830         if (modifiers & carbonToCocoa[i][0]) {
831             cocoaModifiers += carbonToCocoa[i][1];
832         }
833     }
834     [item setKeyEquivalentModifierMask:cocoaModifiers];
835     
836     //Missing key combos for some keys. Must find them later.
837     switch (code)
838     {
839         case 36:
840             ITDebugLog(@"Keycode for menu item \"%@\": 36 (Return)", [item title]);
841             charcode = '\r';
842         break;
843         
844         case 48:
845             ITDebugLog(@"Keycode for menu item \"%@\": 48 (Tab)", [item title]);
846             charcode = '\t';
847         break;
848         
849         //Space -- ARGH!
850         case 49:
851         {
852             ITDebugLog(@"Keycode for menu item \"%@\": 49 (Space)", [item title]);
853             // Haven't tested this, though it should work.
854             // This doesn't work. :'(
855             //unichar buffer;
856             //[[NSString stringWithString:@"Space"] getCharacters:&buffer];
857             //charcode = buffer;
858             /*MenuRef menuRef = _NSGetCarbonMenu([item menu]);
859             ITDebugLog(@"%@", menuRef);
860             SetMenuItemCommandKey(menuRef, 0, NO, 49);
861             SetMenuItemModifiers(menuRef, 0, kMenuNoCommandModifier);
862             SetMenuItemKeyGlyph(menuRef, 0, kMenuBlankGlyph);
863             charcode = 'b';*/
864             unichar buffer;
865             [[NSString stringWithString:@" "] getCharacters:&buffer]; // this will have to do for now :(
866             charcode = buffer;
867         }
868         break;
869         
870         case 51:
871             ITDebugLog(@"Keycode for menu item \"%@\": 51 (Delete)", [item title]);
872             charcode = NSDeleteFunctionKey;
873         break;
874         
875         case 53:
876             ITDebugLog(@"Keycode for menu item \"%@\": 53 (Escape)", [item title]);
877             charcode = '\e';
878         break;
879         
880         case 71:
881             ITDebugLog(@"Keycode for menu item \"%@\": 71 (Escape)", [item title]);
882             charcode = '\e';
883         break;
884         
885         case 76:
886             ITDebugLog(@"Keycode for menu item \"%@\": 76 (Return)", [item title]);
887             charcode = '\r';
888         break;
889         
890         case 96:
891             ITDebugLog(@"Keycode for menu item \"%@\": 96 (F5)", [item title]);
892             charcode = NSF5FunctionKey;
893         break;
894         
895         case 97:
896             ITDebugLog(@"Keycode for menu item \"%@\": 97 (F6)", [item title]);
897             charcode = NSF6FunctionKey;
898         break;
899         
900         case 98:
901             ITDebugLog(@"Keycode for menu item \"%@\": 98 (F7)", [item title]);
902             charcode = NSF7FunctionKey;
903         break;
904         
905         case 99:
906             ITDebugLog(@"Keycode for menu item \"%@\": 99 (F3)", [item title]);
907             charcode = NSF3FunctionKey;
908         break;
909         
910         case 100:
911             ITDebugLog(@"Keycode for menu item \"%@\": 100 (F8)", [item title]);
912             charcode = NSF8FunctionKey;
913         break;
914         
915         case 101:
916             ITDebugLog(@"Keycode for menu item \"%@\": 101 (F9)", [item title]);
917             charcode = NSF9FunctionKey;
918         break;
919         
920         case 103:
921             ITDebugLog(@"Keycode for menu item \"%@\": 103 (F11)", [item title]);
922             charcode = NSF11FunctionKey;
923         break;
924         
925         case 105:
926             ITDebugLog(@"Keycode for menu item \"%@\": 105 (F13)", [item title]);
927             charcode = NSF13FunctionKey;
928         break;
929         
930         case 107:
931             ITDebugLog(@"Keycode for menu item \"%@\": 107 (F14)", [item title]);
932             charcode = NSF14FunctionKey;
933         break;
934         
935         case 109:
936             ITDebugLog(@"Keycode for menu item \"%@\": 109 (F10)", [item title]);
937             charcode = NSF10FunctionKey;
938         break;
939         
940         case 111:
941             ITDebugLog(@"Keycode for menu item \"%@\": 111 (F12)", [item title]);
942             charcode = NSF12FunctionKey;
943         break;
944         
945         case 113:
946             ITDebugLog(@"Keycode for menu item \"%@\": 113 (F13)", [item title]);
947             charcode = NSF13FunctionKey;
948         break;
949         
950         case 114:
951             ITDebugLog(@"Keycode for menu item \"%@\": 114 (Insert)", [item title]);
952             charcode = NSInsertFunctionKey;
953         break;
954         
955         case 115:
956             ITDebugLog(@"Keycode for menu item \"%@\": 115 (Home)", [item title]);
957             charcode = NSHomeFunctionKey;
958         break;
959         
960         case 116:
961             ITDebugLog(@"Keycode for menu item \"%@\": 116 (PgUp)", [item title]);
962             charcode = NSPageUpFunctionKey;
963         break;
964         
965         case 117:
966             ITDebugLog(@"Keycode for menu item \"%@\": 117 (Delete)", [item title]);
967             charcode = NSDeleteFunctionKey;
968         break;
969         
970         case 118:
971             ITDebugLog(@"Keycode for menu item \"%@\": 118 (F4)", [item title]);
972             charcode = NSF4FunctionKey;
973         break;
974         
975         case 119:
976             ITDebugLog(@"Keycode for menu item \"%@\": 119 (End)", [item title]);
977             charcode = NSEndFunctionKey;
978         break;
979         
980         case 120:
981             ITDebugLog(@"Keycode for menu item \"%@\": 120 (F2)", [item title]);
982             charcode = NSF2FunctionKey;
983         break;
984         
985         case 121:
986             ITDebugLog(@"Keycode for menu item \"%@\": 121 (PgDown)", [item title]);
987             charcode = NSPageDownFunctionKey;
988         break;
989         
990         case 122:
991             ITDebugLog(@"Keycode for menu item \"%@\": 122 (F1)", [item title]);
992             charcode = NSF1FunctionKey;
993         break;
994         
995         case 123:
996             ITDebugLog(@"Keycode for menu item \"%@\": 123 (Left Arrow)", [item title]);
997             charcode = NSLeftArrowFunctionKey;
998         break;
999         
1000         case 124:
1001             ITDebugLog(@"Keycode for menu item \"%@\": 124 (Right Arrow)", [item title]);
1002             charcode = NSRightArrowFunctionKey;
1003         break;
1004         
1005         case 125:
1006             ITDebugLog(@"Keycode for menu item \"%@\": 125 (Down Arrow)", [item title]);
1007             charcode = NSDownArrowFunctionKey;
1008         break;
1009         
1010         case 126:
1011             ITDebugLog(@"Keycode for menu item \"%@\": 126 (Up Arrow)", [item title]);
1012             charcode = NSUpArrowFunctionKey;
1013         break;
1014     }
1015     
1016     if (charcode == 'a') {
1017         unsigned long state;
1018         long keyTrans;
1019         char charCode;
1020         Ptr kchr;
1021         state = 0;
1022         kchr = (Ptr) GetScriptVariable(smCurrentScript, smKCHRCache);
1023         keyTrans = KeyTranslate(kchr, code, &state);
1024         charCode = keyTrans;
1025         ITDebugLog(@"Keycode for menu item \"%@\": %i (%c)", [item title], code, charCode);
1026         [item setKeyEquivalent:[NSString stringWithCString:&charCode length:1]];
1027     } else if (charcode != 'b') {
1028         [item setKeyEquivalent:[NSString stringWithCharacters:&charcode length:1]];
1029     }
1030     ITDebugLog(@"Done setting key equivalent on menu item: %@", [item title]);
1031 }
1032
1033 - (BOOL)iPodWithNameAutomaticallyUpdates:(NSString *)name
1034 {
1035     NSArray *volumes = [[NSWorkspace sharedWorkspace] mountedLocalVolumePaths];
1036     NSEnumerator *volEnum = [volumes objectEnumerator];
1037     NSString *nextVolume;
1038     ITDebugLog(@"Looking for an iPod named %@", name);
1039     while ( (nextVolume = [volEnum nextObject]) ) {
1040         ITDebugLog(@"- %@", nextVolume);
1041         if ([nextVolume rangeOfString:name options:nil /*range:NSMakeRange(0, [name length] - 1)*/].location != NSNotFound) {
1042             NSFileHandle *handle;
1043             NSData *data;
1044             NSString *path = [nextVolume stringByAppendingPathComponent:@"/iPod_Control/iTunes/iTunesPrefs"];
1045             if ( ![[NSFileManager defaultManager] fileExistsAtPath:path] ) {
1046                 ITDebugLog(@"Error, path isn't an iPod! %@", path);
1047                 return NO;
1048             }
1049             handle = [NSFileHandle fileHandleForReadingAtPath:path];
1050             ITDebugLog(@"File handle: %@", handle);
1051             [handle seekToFileOffset:10];
1052             data = [handle readDataOfLength:1];
1053             ITDebugLog(@"Data: %@", data);
1054             if ( (*((unsigned char*)[data bytes]) == 0x00) ) {
1055                 ITDebugLog(@"iPod is manually updated. %@", path);
1056                 return NO;
1057             } else if ( ( *((unsigned char*)[data bytes]) == 0x01 ) ) {
1058                 ITDebugLog(@"iPod is automatically updated. %@", path);
1059                 return YES;
1060             } else {
1061                 ITDebugLog(@"Error! Value: %h  Desc: %@ Path: %@", *((unsigned char*)[data bytes]), [data description], path);
1062                 return NO;
1063             }
1064         }
1065     }
1066     return YES;
1067 }
1068
1069 @end