Checking for a remote server runs in a separate thread, so it doesn't lock up the...
[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;
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;
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;
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;
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;
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;
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;
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     [_ratingMenu release];
475     [_upcomingSongsMenu release];
476     [_playlistsMenu release];
477     [_eqMenu release];
478     ITDebugLog(@"Beginning Rebuild of \"Song Rating\" submenu.");
479     _ratingMenu = [self ratingMenu];
480     ITDebugLog(@"Beginning Rebuild of \"Upcoming Songs\" submenu.");
481     _upcomingSongsMenu = [self upcomingSongsMenu];
482     ITDebugLog(@"Beginning Rebuild of \"Playlists\" submenu.");
483     _playlistsMenu = [self playlistsMenu];
484     ITDebugLog(@"Beginning Rebuild of \"EQ Presets\" submenu.");
485     _eqMenu = [self eqMenu];
486     ITDebugLog(@"Done rebuilding all of the submenus.");
487 }
488
489 - (NSMenu *)ratingMenu
490 {
491     NSMenu *ratingMenu = [[NSMenu alloc] initWithTitle:@""];
492     NSEnumerator *itemEnum;
493     id  anItem;
494     int itemTag = 0;
495     SEL itemSelector = @selector(performRatingMenuAction:);
496     
497     ITDebugLog(@"Building \"Song Rating\" menu.");
498     
499     [ratingMenu addItemWithTitle:[NSString stringWithUTF8String:"☆☆☆☆☆"] action:nil keyEquivalent:@""];
500     [ratingMenu addItemWithTitle:[NSString stringWithUTF8String:"★☆☆☆☆"] action:nil keyEquivalent:@""];
501     [ratingMenu addItemWithTitle:[NSString stringWithUTF8String:"★★☆☆☆"] action:nil keyEquivalent:@""];
502     [ratingMenu addItemWithTitle:[NSString stringWithUTF8String:"★★★☆☆"] action:nil keyEquivalent:@""];
503     [ratingMenu addItemWithTitle:[NSString stringWithUTF8String:"★★★★☆"] action:nil keyEquivalent:@""];
504     [ratingMenu addItemWithTitle:[NSString stringWithUTF8String:"★★★★★"] action:nil keyEquivalent:@""];
505     
506     itemEnum = [[ratingMenu itemArray] objectEnumerator];
507     while ( (anItem = [itemEnum nextObject]) ) {
508         ITDebugLog(@"Setting up \"%@\" menu item.", [anItem title]);
509         [anItem setAction:itemSelector];
510         [anItem setTarget:self];
511         [anItem setTag:itemTag];
512         itemTag += 20;
513     }
514     ITDebugLog(@"Done Building \"Song Rating\" menu.");
515     return ratingMenu;
516 }
517
518 - (NSMenu *)upcomingSongsMenu
519 {
520     NSMenu *upcomingSongsMenu = [[NSMenu alloc] initWithTitle:@""];
521     int numSongs, numSongsInAdvance = [[NSUserDefaults standardUserDefaults] integerForKey:@"SongsInAdvance"];
522     
523     NS_DURING
524         numSongs = [[[MainController sharedController] currentRemote] numberOfSongsInPlaylistAtIndex:_currentPlaylist];
525     NS_HANDLER
526         [[MainController sharedController] networkError:localException];
527     NS_ENDHANDLER
528     
529     ITDebugLog(@"Building \"Upcoming Songs\" menu.");
530     if (_currentPlaylist && !_playingRadio) {
531         if (numSongs > 0) {
532             int i;
533             for (i = _currentTrack + 1; i <= _currentTrack + numSongsInAdvance; i++) {
534                 if (i <= numSongs) {
535                     NSString *curSong;
536                     NS_DURING
537                         curSong = [[[MainController sharedController] currentRemote] songTitleAtIndex:i];
538                     NS_HANDLER
539                         [[MainController sharedController] networkError:localException];
540                     NS_ENDHANDLER
541                     id <NSMenuItem> songItem;
542                     ITDebugLog(@"Adding song: %@", curSong);
543                     songItem = [upcomingSongsMenu addItemWithTitle:curSong action:@selector(performUpcomingSongsMenuAction:) keyEquivalent:@""];
544                     [songItem setTag:i];
545                     [songItem setTarget:self];
546                 } else {
547                     break;
548                 }
549             }
550         }
551         
552         if ([upcomingSongsMenu numberOfItems] == 0) {
553             [upcomingSongsMenu addItemWithTitle:NSLocalizedString(@"noUpcomingSongs", @"No upcoming songs.") action:NULL keyEquivalent:@""];
554         }
555     }
556     ITDebugLog(@"Done Building \"Upcoming Songs\" menu.");
557     return upcomingSongsMenu;
558 }
559
560 /*- (NSMenu *)playlistsMenu
561 {
562     NSMenu *playlistsMenu = [[NSMenu alloc] initWithTitle:@""];
563     NSArray *playlists;
564     id <NSMenuItem> tempItem;
565     ITMTRemotePlayerSource source = [[[MainController sharedController] currentRemote] currentSource];
566     int i;
567     NS_DURING
568         playlists = [[[MainController sharedController] currentRemote] playlists];
569     NS_HANDLER
570         [[MainController sharedController] networkError:localException];
571     NS_ENDHANDLER
572     
573     ITDebugLog(@"Building \"Playlists\" menu.");
574     
575     for (i = 0; i < [playlists count]; i++) {
576         NSString *curPlaylist = [playlists objectAtIndex:i];
577         ITDebugLog(@"Adding playlist: %@", curPlaylist);
578         tempItem = [playlistsMenu addItemWithTitle:curPlaylist action:@selector(performPlaylistMenuAction:) keyEquivalent:@""];
579         [tempItem setTag:i + 1];
580         [tempItem setTarget:self];
581     }
582     
583     if (source == ITMTRemoteRadioSource) {
584         [[playlistsMenu addItemWithTitle:NSLocalizedString(@"radio", @"Radio") action:NULL keyEquivalent:@""] setState:NSOnState];
585     } else if (source == ITMTRemoteGenericDeviceSource) {
586         [[playlistsMenu addItemWithTitle:NSLocalizedString(@"genericDevice", @"Generic Device") action:NULL keyEquivalent:@""] setState:NSOnState];
587     } else if (source == ITMTRemoteiPodSource) {
588         [[playlistsMenu addItemWithTitle:NSLocalizedString(@"iPod", @"iPod") action:NULL keyEquivalent:@""] setState:NSOnState];
589     } else if (source == ITMTRemoteCDSource) {
590         [[playlistsMenu addItemWithTitle:NSLocalizedString(@"cd", @"CD") action:NULL keyEquivalent:@""] setState:NSOnState];
591     } else if (source == ITMTRemoteSharedLibrarySource) {
592         [[playlistsMenu addItemWithTitle:NSLocalizedString(@"sharedLibrary", @"Shared Library") action:NULL keyEquivalent:@""] setState:NSOnState];
593     } else if (source == ITMTRemoteLibrarySource && _currentPlaylist) {
594         [[playlistsMenu itemAtIndex:_currentPlaylist - 1] setState:NSOnState];
595     }
596     ITDebugLog(@"Done Building \"Playlists\" menu");
597     return playlistsMenu;
598 }*/
599
600
601 - (NSMenu *)playlistsMenu
602 {
603     NSMenu *playlistsMenu = [[NSMenu alloc] initWithTitle:@""];
604     NSArray *playlists;
605     id <NSMenuItem> tempItem;
606     ITMTRemotePlayerSource source = [[[MainController sharedController] currentRemote] currentSource];
607     int i, j;
608     NSMutableArray *indices = [[NSMutableArray alloc] init];
609     NS_DURING
610         playlists = [[[MainController sharedController] currentRemote] playlists];
611     NS_HANDLER
612         [[MainController sharedController] networkError:localException];
613     NS_ENDHANDLER
614     ITDebugLog(@"Building \"Playlists\" menu.");
615     {
616         NSArray *curPlaylist = [playlists objectAtIndex:0];
617         NSString *name = [curPlaylist objectAtIndex:0];
618         ITDebugLog(@"Adding main source: %@", name);
619         for (i = 3; i < [curPlaylist count]; i++) {
620             ITDebugLog(@"Adding playlist: %@", [curPlaylist objectAtIndex:i]);
621             tempItem = [playlistsMenu addItemWithTitle:[curPlaylist objectAtIndex:i] action:@selector(performPlaylistMenuAction:) keyEquivalent:@""];
622             [tempItem setTag:i - 1];
623             [tempItem setTarget:self];
624         }
625         ITDebugLog(@"Adding index to the index array.");
626         [indices addObject:[curPlaylist objectAtIndex:2]];
627     }
628     if ([playlists count] > 1) {
629         if ([[[playlists objectAtIndex:1] objectAtIndex:1] intValue] == ITMTRemoteRadioSource) {
630             [indices addObject:[[playlists objectAtIndex:1] objectAtIndex:2]];
631             if (source == ITMTRemoteRadioSource) {
632                 [playlistsMenu addItem:[NSMenuItem separatorItem]];
633                 [[playlistsMenu addItemWithTitle:NSLocalizedString(@"radio", @"Radio") action:@selector(performPlaylistMenuAction:) keyEquivalent:@""] setState:NSOnState];
634             }
635         } else {
636             [playlistsMenu addItem:[NSMenuItem separatorItem]];
637         }
638     }
639     
640     if ([playlists count] > 1) {
641         for (i = 1; i < [playlists count]; i++) {
642             NSArray *curPlaylist = [playlists objectAtIndex:i];
643             if ([[curPlaylist objectAtIndex:1] intValue] != ITMTRemoteRadioSource) {
644                 NSString *name = [curPlaylist objectAtIndex:0];
645                 NSMenu *submenu = [[NSMenu alloc] init];
646                 ITDebugLog(@"Adding source: %@", name);
647                 
648                 if ( ([[curPlaylist objectAtIndex:1] intValue] == ITMTRemoteiPodSource) && [self iPodWithNameAutomaticallyUpdates:name] ) {
649                     ITDebugLog(@"Invalid iPod source.");
650                     [playlistsMenu addItemWithTitle:name action:NULL keyEquivalent:@""];
651                 } else {
652                     for (j = 3; j < [curPlaylist count]; j++) {
653                         ITDebugLog(@"Adding playlist: %@", [curPlaylist objectAtIndex:j]);
654                         tempItem = [submenu addItemWithTitle:[curPlaylist objectAtIndex:j] action:@selector(performPlaylistMenuAction:) keyEquivalent:@""];
655                         [tempItem setTag:(i * 1000) + j - 1];
656                         [tempItem setTarget:self];
657                     }
658                     [[playlistsMenu addItemWithTitle:name action:NULL keyEquivalent:@""] setSubmenu:[submenu autorelease]];
659                 }
660                 ITDebugLog(@"Adding index to the index array.");
661                 [indices addObject:[curPlaylist objectAtIndex:2]];
662             }
663         }
664     }
665     ITDebugLog(@"Checking the current source.");
666     if ( (source == ITMTRemoteSharedLibrarySource) || (source == ITMTRemoteiPodSource) || (source == ITMTRemoteGenericDeviceSource) || (source == ITMTRemoteCDSource) ) {
667         tempItem = [playlistsMenu itemAtIndex:[playlistsMenu numberOfItems] + [indices indexOfObject:[NSNumber numberWithInt:[[[MainController sharedController] currentRemote] currentSourceIndex]]] - [indices count]];
668         [tempItem setState:NSOnState];
669         [[[tempItem submenu] itemAtIndex:_currentPlaylist - 1] setState:NSOnState];
670     } else if (source == ITMTRemoteLibrarySource && _currentPlaylist) {
671         [[playlistsMenu itemAtIndex:_currentPlaylist - 1] setState:NSOnState];
672     }
673     [indices release];
674     ITDebugLog(@"Done Building \"Playlists\" menu");
675     return playlistsMenu;
676 }
677
678 - (NSMenu *)eqMenu
679 {
680     NSMenu *eqMenu = [[NSMenu alloc] initWithTitle:@""];
681     NSArray *eqPresets;
682     id <NSMenuItem> tempItem;
683     int i;
684     
685     NS_DURING
686         eqPresets = [[[MainController sharedController] currentRemote] eqPresets];
687     NS_HANDLER
688         [[MainController sharedController] networkError:localException];
689     NS_ENDHANDLER
690     
691     ITDebugLog(@"Building \"EQ Presets\" menu.");
692     
693     for (i = 0; i < [eqPresets count]; i++) {
694         NSString *name;
695            if ( ( name = [eqPresets objectAtIndex:i] ) ) {
696             ITDebugLog(@"Adding EQ Preset: %@", name);
697             tempItem = [eqMenu addItemWithTitle:name
698                     action:@selector(performEqualizerMenuAction:)
699                     keyEquivalent:@""];
700             [tempItem setTag:i];
701             [tempItem setTarget:self];
702            }
703     }
704     ITDebugLog(@"Done Building \"EQ Presets\" menu");
705     return eqMenu;
706 }
707
708 - (void)performMainMenuAction:(id)sender
709 {
710     switch ( [sender tag] )
711     {
712         case MTMenuPlayPauseItem:
713             ITDebugLog(@"Performing Menu Action: Play/Pause");
714             [[MainController sharedController] playPause];
715             break;
716         case MTMenuFastForwardItem:
717             ITDebugLog(@"Performing Menu Action: Fast Forward");
718             [[MainController sharedController] fastForward];
719             break;
720         case MTMenuRewindItem:
721             ITDebugLog(@"Performing Menu Action: Rewind");
722             [[MainController sharedController] rewind];
723             break;
724         case MTMenuPreviousTrackItem:
725             ITDebugLog(@"Performing Menu Action: Previous Track");
726             [[MainController sharedController] prevSong];
727             break;
728         case MTMenuNextTrackItem:
729             ITDebugLog(@"Performing Menu Action: Next Track");
730             [[MainController sharedController] nextSong];
731             break;
732         case MTMenuShowPlayerItem:
733             ITDebugLog(@"Performing Menu Action: Show Main Interface");
734             [[MainController sharedController] showPlayer];
735             break;
736         case MTMenuPreferencesItem:
737             ITDebugLog(@"Performing Menu Action: Preferences...");
738             [[MainController sharedController] showPreferences];
739             break;
740         case MTMenuQuitItem:
741             ITDebugLog(@"Performing Menu Action: Quit");
742             [[MainController sharedController] quitMenuTunes];
743             break;
744         case MTMenuRegisterItem:
745             ITDebugLog(@"Performing Menu Action: Register");
746             [[MainController sharedController] blingNow];
747             break;
748         default:
749             ITDebugLog(@"Performing Menu Action: Unimplemented Menu Item OR Child-bearing Menu Item");
750             break;
751     }
752 }
753
754 - (void)performRatingMenuAction:(id)sender
755 {
756     ITDebugLog(@"Rating action selected on item with tag %i", [sender tag]);
757     [[MainController sharedController] selectSongRating:[sender tag]];
758 }
759
760 - (void)performPlaylistMenuAction:(id)sender
761 {
762     ITDebugLog(@"Playlist action selected on item with tag %i", [sender tag]);
763     [[MainController sharedController] selectPlaylistAtIndex:[sender tag]];
764 }
765
766 - (void)performEqualizerMenuAction:(id)sender
767 {
768     ITDebugLog(@"EQ action selected on item with tag %i", [sender tag]);
769     [[MainController sharedController] selectEQPresetAtIndex:[sender tag]];
770 }
771
772 - (void)performUpcomingSongsMenuAction:(id)sender
773 {
774     ITDebugLog(@"Song action selected on item with tag %i", [sender tag]);
775     [[MainController sharedController] selectSongAtIndex:[sender tag]];
776 }
777
778 - (void)updateMenu
779 {
780     ITDebugLog(@"Update Menu");
781     [_currentMenu update];
782 }
783
784 - (BOOL)validateMenuItem:(id <NSMenuItem>)menuItem
785 {
786     return YES;
787 }
788
789 //This is never used I know, keep it though
790 - (NSString *)systemUIColor
791 {
792     NSDictionary *tmpDict;
793     NSNumber *tmpNumber;
794     if ( (tmpDict = [NSDictionary dictionaryWithContentsOfFile:[@"~/Library/Preferences/.GlobalPreferences.plist" stringByExpandingTildeInPath]]) ) {
795         if ( (tmpNumber = [tmpDict objectForKey:@"AppleAquaColorVariant"]) ) {
796             if ( ([tmpNumber intValue] == 1) ) {
797                 return @"Aqua";
798             } else {
799                 return @"Graphite";
800             }
801         } else {
802             return @"Aqua";
803         }
804     } else {
805         return @"Aqua";
806     }
807 }
808
809 - (void)setKeyEquivalentForCode:(short)code andModifiers:(long)modifiers
810         onItem:(id <NSMenuItem>)item
811 {
812     unichar charcode = 'a';
813     int i;
814     long cocoaModifiers = 0;
815     static long carbonToCocoa[6][2] = 
816     {
817         { cmdKey, NSCommandKeyMask },
818         { optionKey, NSAlternateKeyMask },
819         { controlKey, NSControlKeyMask },
820         { shiftKey, NSShiftKeyMask },
821     };
822     
823     ITDebugLog(@"Setting Key Equivelent on menu item \"%@\".", [item title]);
824     
825     for (i = 0; i < 6; i++) {
826         if (modifiers & carbonToCocoa[i][0]) {
827             cocoaModifiers += carbonToCocoa[i][1];
828         }
829     }
830     [item setKeyEquivalentModifierMask:cocoaModifiers];
831     
832     //Missing key combos for some keys. Must find them later.
833     switch (code)
834     {
835         case 36:
836             ITDebugLog(@"Keycode for menu item \"%@\": 36 (Return)", [item title]);
837             charcode = '\r';
838         break;
839         
840         case 48:
841             ITDebugLog(@"Keycode for menu item \"%@\": 48 (Tab)", [item title]);
842             charcode = '\t';
843         break;
844         
845         //Space -- ARGH!
846         case 49:
847         {
848             ITDebugLog(@"Keycode for menu item \"%@\": 49 (Space)", [item title]);
849             // Haven't tested this, though it should work.
850             // This doesn't work. :'(
851             //unichar buffer;
852             //[[NSString stringWithString:@"Space"] getCharacters:&buffer];
853             //charcode = buffer;
854             /*MenuRef menuRef = _NSGetCarbonMenu([item menu]);
855             ITDebugLog(@"%@", menuRef);
856             SetMenuItemCommandKey(menuRef, 0, NO, 49);
857             SetMenuItemModifiers(menuRef, 0, kMenuNoCommandModifier);
858             SetMenuItemKeyGlyph(menuRef, 0, kMenuBlankGlyph);
859             charcode = 'b';*/
860             unichar buffer;
861             [[NSString stringWithString:@" "] getCharacters:&buffer]; // this will have to do for now :(
862             charcode = buffer;
863         }
864         break;
865         
866         case 51:
867             ITDebugLog(@"Keycode for menu item \"%@\": 51 (Delete)", [item title]);
868             charcode = NSDeleteFunctionKey;
869         break;
870         
871         case 53:
872             ITDebugLog(@"Keycode for menu item \"%@\": 53 (Escape)", [item title]);
873             charcode = '\e';
874         break;
875         
876         case 71:
877             ITDebugLog(@"Keycode for menu item \"%@\": 71 (Escape)", [item title]);
878             charcode = '\e';
879         break;
880         
881         case 76:
882             ITDebugLog(@"Keycode for menu item \"%@\": 76 (Return)", [item title]);
883             charcode = '\r';
884         break;
885         
886         case 96:
887             ITDebugLog(@"Keycode for menu item \"%@\": 96 (F5)", [item title]);
888             charcode = NSF5FunctionKey;
889         break;
890         
891         case 97:
892             ITDebugLog(@"Keycode for menu item \"%@\": 97 (F6)", [item title]);
893             charcode = NSF6FunctionKey;
894         break;
895         
896         case 98:
897             ITDebugLog(@"Keycode for menu item \"%@\": 98 (F7)", [item title]);
898             charcode = NSF7FunctionKey;
899         break;
900         
901         case 99:
902             ITDebugLog(@"Keycode for menu item \"%@\": 99 (F3)", [item title]);
903             charcode = NSF3FunctionKey;
904         break;
905         
906         case 100:
907             ITDebugLog(@"Keycode for menu item \"%@\": 100 (F8)", [item title]);
908             charcode = NSF8FunctionKey;
909         break;
910         
911         case 101:
912             ITDebugLog(@"Keycode for menu item \"%@\": 101 (F9)", [item title]);
913             charcode = NSF9FunctionKey;
914         break;
915         
916         case 103:
917             ITDebugLog(@"Keycode for menu item \"%@\": 103 (F11)", [item title]);
918             charcode = NSF11FunctionKey;
919         break;
920         
921         case 105:
922             ITDebugLog(@"Keycode for menu item \"%@\": 105 (F13)", [item title]);
923             charcode = NSF13FunctionKey;
924         break;
925         
926         case 107:
927             ITDebugLog(@"Keycode for menu item \"%@\": 107 (F14)", [item title]);
928             charcode = NSF14FunctionKey;
929         break;
930         
931         case 109:
932             ITDebugLog(@"Keycode for menu item \"%@\": 109 (F10)", [item title]);
933             charcode = NSF10FunctionKey;
934         break;
935         
936         case 111:
937             ITDebugLog(@"Keycode for menu item \"%@\": 111 (F12)", [item title]);
938             charcode = NSF12FunctionKey;
939         break;
940         
941         case 113:
942             ITDebugLog(@"Keycode for menu item \"%@\": 113 (F13)", [item title]);
943             charcode = NSF13FunctionKey;
944         break;
945         
946         case 114:
947             ITDebugLog(@"Keycode for menu item \"%@\": 114 (Insert)", [item title]);
948             charcode = NSInsertFunctionKey;
949         break;
950         
951         case 115:
952             ITDebugLog(@"Keycode for menu item \"%@\": 115 (Home)", [item title]);
953             charcode = NSHomeFunctionKey;
954         break;
955         
956         case 116:
957             ITDebugLog(@"Keycode for menu item \"%@\": 116 (PgUp)", [item title]);
958             charcode = NSPageUpFunctionKey;
959         break;
960         
961         case 117:
962             ITDebugLog(@"Keycode for menu item \"%@\": 117 (Delete)", [item title]);
963             charcode = NSDeleteFunctionKey;
964         break;
965         
966         case 118:
967             ITDebugLog(@"Keycode for menu item \"%@\": 118 (F4)", [item title]);
968             charcode = NSF4FunctionKey;
969         break;
970         
971         case 119:
972             ITDebugLog(@"Keycode for menu item \"%@\": 119 (End)", [item title]);
973             charcode = NSEndFunctionKey;
974         break;
975         
976         case 120:
977             ITDebugLog(@"Keycode for menu item \"%@\": 120 (F2)", [item title]);
978             charcode = NSF2FunctionKey;
979         break;
980         
981         case 121:
982             ITDebugLog(@"Keycode for menu item \"%@\": 121 (PgDown)", [item title]);
983             charcode = NSPageDownFunctionKey;
984         break;
985         
986         case 122:
987             ITDebugLog(@"Keycode for menu item \"%@\": 122 (F1)", [item title]);
988             charcode = NSF1FunctionKey;
989         break;
990         
991         case 123:
992             ITDebugLog(@"Keycode for menu item \"%@\": 123 (Left Arrow)", [item title]);
993             charcode = NSLeftArrowFunctionKey;
994         break;
995         
996         case 124:
997             ITDebugLog(@"Keycode for menu item \"%@\": 124 (Right Arrow)", [item title]);
998             charcode = NSRightArrowFunctionKey;
999         break;
1000         
1001         case 125:
1002             ITDebugLog(@"Keycode for menu item \"%@\": 125 (Down Arrow)", [item title]);
1003             charcode = NSDownArrowFunctionKey;
1004         break;
1005         
1006         case 126:
1007             ITDebugLog(@"Keycode for menu item \"%@\": 126 (Up Arrow)", [item title]);
1008             charcode = NSUpArrowFunctionKey;
1009         break;
1010     }
1011     
1012     if (charcode == 'a') {
1013         unsigned long state;
1014         long keyTrans;
1015         char charCode;
1016         Ptr kchr;
1017         state = 0;
1018         kchr = (Ptr) GetScriptVariable(smCurrentScript, smKCHRCache);
1019         keyTrans = KeyTranslate(kchr, code, &state);
1020         charCode = keyTrans;
1021         ITDebugLog(@"Keycode for menu item \"%@\": %i (%c)", [item title], code, charCode);
1022         [item setKeyEquivalent:[NSString stringWithCString:&charCode length:1]];
1023     } else if (charcode != 'b') {
1024         [item setKeyEquivalent:[NSString stringWithCharacters:&charcode length:1]];
1025     }
1026     ITDebugLog(@"Done setting key equivalent on menu item: %@", [item title]);
1027 }
1028
1029 - (BOOL)iPodWithNameAutomaticallyUpdates:(NSString *)name
1030 {
1031     NSArray *volumes = [[NSWorkspace sharedWorkspace] mountedLocalVolumePaths];
1032     NSEnumerator *volEnum = [volumes objectEnumerator];
1033     NSString *nextVolume;
1034     ITDebugLog(@"Looking for an iPod named %@", name);
1035     while ( (nextVolume = [volEnum nextObject]) ) {
1036         ITDebugLog(@"- %@", nextVolume);
1037         if ([nextVolume rangeOfString:name options:nil /*range:NSMakeRange(0, [name length] - 1)*/].location != NSNotFound) {
1038             NSFileHandle *handle;
1039             NSData *data;
1040             NSString *path = [nextVolume stringByAppendingPathComponent:@"/iPod_Control/iTunes/iTunesPrefs"];
1041             if ( ![[NSFileManager defaultManager] fileExistsAtPath:path] ) {
1042                 ITDebugLog(@"Error, path isn't an iPod! %@", path);
1043                 return NO;
1044             }
1045             handle = [NSFileHandle fileHandleForReadingAtPath:path];
1046             ITDebugLog(@"File handle: %@", handle);
1047             [handle seekToFileOffset:10];
1048             data = [handle readDataOfLength:1];
1049             ITDebugLog(@"Data: %@", data);
1050             if ( (*((unsigned char*)[data bytes]) == 0x00) ) {
1051                 ITDebugLog(@"iPod is manually updated. %@", path);
1052                 return NO;
1053             } else if ( ( *((unsigned char*)[data bytes]) == 0x01 ) ) {
1054                 ITDebugLog(@"iPod is automatically updated. %@", path);
1055                 return YES;
1056             } else {
1057                 ITDebugLog(@"Error! Value: %h  Desc: %@ Path: %@", *((unsigned char*)[data bytes]), [data description], path);
1058                 return NO;
1059             }
1060         }
1061     }
1062     return YES;
1063 }
1064
1065 @end