1 #import "iTunesRemote.h"
2 #import "PlaylistNode.h"
4 @implementation iTunesRemote
8 return [[[iTunesRemote alloc] init] autorelease];
11 - (NSString *)remoteTitle
13 return @"iTunes Remote";
16 - (NSString *)remoteInformation
18 return @"Default MenuTunes plugin to control iTunes, by iThink Software.";
21 - (NSImage *)remoteIcon
28 ITDebugLog(@"iTunesRemote begun");
29 savedPSN = [self iTunesPSN];
30 [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(notificationHandler:) name:@"com.apple.iTunes.playerInfo" object:@"com.apple.iTunes.player"];
32 NSString *iTunesPath = [[NSUserDefaults standardUserDefaults] stringForKey:@"CustomPlayerPath"];
33 NSDictionary *iTunesInfoPlist;
36 //Check if iTunes 5.0 or later is installed
38 iTunesPath = [[NSWorkspace sharedWorkspace] fullPathForApplication:@"iTunes.app"];
40 iTunesInfoPlist = [[NSBundle bundleWithPath:iTunesPath] infoDictionary];
41 iTunesVersion = [[iTunesInfoPlist objectForKey:@"CFBundleVersion"] floatValue];
42 ITDebugLog(@"iTunes version found: %f.", iTunesVersion);
43 _iTunesVersion = iTunesVersion;
50 ITDebugLog(@"iTunesRemote halted");
51 [[NSDistributedNotificationCenter defaultCenter] removeObserver:self];
55 - (NSString *)playerFullName
60 - (NSString *)playerSimpleName
65 - (NSDictionary *)capabilities
67 return [NSDictionary dictionaryWithObjectsAndKeys:
68 [NSNumber numberWithBool: YES], @"Remote",
69 [NSNumber numberWithBool: YES], @"Basic Track Control",
70 [NSNumber numberWithBool: YES], @"Track Information",
71 [NSNumber numberWithBool: YES], @"Track Navigation",
72 [NSNumber numberWithBool: YES], @"Upcoming Songs",
73 [NSNumber numberWithBool: YES], @"Playlists",
74 [NSNumber numberWithBool: YES], @"Volume",
75 [NSNumber numberWithBool: YES], @"Shuffle",
76 [NSNumber numberWithBool: YES], @"Repeat Modes",
77 [NSNumber numberWithBool: YES], @"Equalizer",
78 [NSNumber numberWithBool: YES], @"Track Rating",
82 - (BOOL)showPrimaryInterface
84 ITDebugLog(@"Showing player primary interface.");
86 if ([self playerRunningState] == ITMTRemotePlayerRunning) {
87 ITDebugLog(@"Showing player interface.");
88 //If not minimized and visible
89 if ( ([ITSendAEWithString(@"'----':obj { form:'prop', want:type('prop'), seld:type('pMin'), from:obj { form:'indx', want:type('cBrW'), seld:1, from:'null'() } }", 'core', 'getd', &savedPSN) booleanValue] == 0) &&
90 ([ITSendAEWithString(@"'----':obj { form:'prop', want:type('prop'), seld:type('pvis'), from:obj { form:'indx', want:type('cBrW'), seld:1, from:'null'() } }", 'core', 'getd', &savedPSN) booleanValue] != 0) &&
91 [[[[NSWorkspace sharedWorkspace] activeApplication] objectForKey:@"NSApplicationName"] isEqualToString:@"iTunes"] ) {
92 //set minimized of browser window 1 to true
93 ITSendAEWithString(@"data:long(1), '----':obj { form:'prop', want:type('prop'), seld:type('pMin'), from:obj { form:'indx', want:type('cBrW'), seld:long(1), from:'null'() } }", 'core', 'setd', &savedPSN);
95 //set minimized of browser window 1 to false
96 ITSendAEWithString(@"data:long(0), '----':obj { form:'prop', want:type('prop'), seld:type('pMin'), from:obj { form:'indx', want:type('cBrW'), seld:long(1), from:'null'() } }", 'core', 'setd', &savedPSN);
98 //set visible of browser window 1 to true
99 ITSendAEWithString(@"data:long(1), '----':obj { form:'prop', want:type('prop'), seld:type('pvis'), from:obj { form:'indx', want:type('cBrW'), seld:long(1), from:'null'() } }", 'core', 'setd', &savedPSN);
101 ITSendAEWithString(@"data:long(1), '----':obj { form:'prop', want:type('prop'), seld:type('pisf'), from:'null'() }", 'core', 'setd', &savedPSN);
102 ITDebugLog(@"Done showing player primary interface.");
106 ITDebugLog(@"Launching player.");
107 if ( (path = [[NSUserDefaults standardUserDefaults] stringForKey:@"CustomPlayerPath"]) ) {
109 path = [self playerFullName];
111 if (![[NSWorkspace sharedWorkspace] launchApplication:path]) {
112 ITDebugLog(@"Error Launching Player");
119 - (ITMTRemotePlayerRunningState)playerRunningState
121 NSArray *apps = [[NSWorkspace sharedWorkspace] launchedApplications];
123 int count = [apps count];
125 for (i = 0; i < count; i++) {
126 if ([[[apps objectAtIndex:i] objectForKey:@"NSApplicationName"] isEqualToString:@"iTunes"]) {
127 ITDebugLog(@"Player running state: 1");
128 return ITMTRemotePlayerRunning;
131 ITDebugLog(@"Player running state: 0");
132 return ITMTRemotePlayerNotRunning;
135 - (ITMTRemotePlayerPlayingState)playerPlayingState
139 ITDebugLog(@"Getting player playing state");
140 result = [ITSendAEWithString(@"'----':obj { form:'prop', want:type('prop'), seld:type('pPlS'), from:'null'() }", 'core', 'getd', &savedPSN) typeCodeValue];
144 ITDebugLog(@"Getting player playing state done. Player state: Playing");
145 return ITMTRemotePlayerPlaying;
147 ITDebugLog(@"Getting player playing state done. Player state: Paused");
148 return ITMTRemotePlayerPaused;
150 ITDebugLog(@"Getting player playing state done. Player state: Rewinding");
151 return ITMTRemotePlayerRewinding;
153 ITDebugLog(@"Getting player playing state done. Player state: Forwarding");
154 return ITMTRemotePlayerForwarding;
157 ITDebugLog(@"Getting player playing state done. Player state: Stopped");
158 return ITMTRemotePlayerStopped;
160 ITDebugLog(@"Getting player playing state done. Player state: Stopped");
161 return ITMTRemotePlayerStopped;
164 /*- (NSArray *)playlists
167 const signed long numPlaylists = [[ITAppleEventCenter sharedCenter] sendAEWithSendStringForNumber:@"kocl:type('cPly'), '----':()" eventClass:@"core" eventID:@"cnte" appPSN:savedPSN];
168 NSMutableArray *playlists = [[NSMutableArray alloc] initWithCapacity:numPlaylists];
170 for (i = 1; i <= numPlaylists; i++) {
172 NSString *sendStr = [NSString stringWithFormat:@"'----':obj { form:'prop', want:type('prop'), seld:type('pnam'), from:obj { form:'indx', want:type('cPly'), seld:long(%lu), from:'null'() } }",(unsigned long)j];
173 NSString *theObj = [[ITAppleEventCenter sharedCenter] sendAEWithSendString:sendStr eventClass:@"core" eventID:@"getd" appPSN:savedPSN];
174 [playlists addObject:theObj];
176 return [playlists autorelease];
179 //Full source awareness
180 /*- (NSArray *)playlists
183 SInt32 numSources = [ITSendAEWithString(@"kocl:type('cSrc'), '----':()", 'core', 'cnte', &savedPSN) int32Value];
184 NSMutableArray *allSources = [[NSMutableArray alloc] init];
186 ITDebugLog(@"Getting playlists.");
187 if (numSources == 0) {
188 [allSources release];
189 ITDebugLog(@"No sources.");
193 for (k = 1; k <= numSources ; k++) {
194 SInt32 numPlaylists = [ITSendAEWithString([NSString stringWithFormat:@"kocl:type('cPly'), '----':obj { form:'indx', want:type('cSrc'), seld:long(%u), from:() }",k], 'core', 'cnte', &savedPSN) int32Value];
195 SInt32 fourcc = [ITSendAEWithString([NSString stringWithFormat:@"'----':obj { form:'prop', want:type('prop'), seld:type('pKnd'), from:obj { form:'indx', want:type('cSrc'), seld:long(%u), from:() } }",k], 'core', 'getd', &savedPSN) int32Value];
196 NSString *sourceName = [ITSendAEWithString([NSString stringWithFormat:@"'----':obj { form:'prop', want:type('prop'), seld:type('pnam'), from:obj { form:'indx', want:type('cSrc'), seld:long(%u), from:() } }",k], 'core', 'getd', &savedPSN) stringValue];
197 SInt32 index = [ITSendAEWithString([NSString stringWithFormat:@"'----':obj { form:'prop', want:type('prop'), seld:type('pidx'), from:obj { form:'indx', want:type('cSrc'), seld:long(%u), from:() } }",k], 'core', 'getd', &savedPSN) int32Value];
200 NSMutableArray *aSource = [[NSMutableArray alloc] init];
201 [aSource addObject:sourceName];
204 class = ITMTRemoteRadioSource;
207 class = ITMTRemoteGenericDeviceSource;
210 class = ITMTRemoteiPodSource;
214 class = ITMTRemoteCDSource;
217 class = ITMTRemoteSharedLibrarySource;
222 class = ITMTRemoteLibrarySource;
225 ITDebugLog(@"Adding source %@ of type %i at index %i", sourceName, class, index);
226 [aSource addObject:[NSNumber numberWithInt:class]];
227 [aSource addObject:[NSNumber numberWithInt:index]];
228 for (i = 1; i <= numPlaylists; i++) {
229 NSString *sendStr = [NSString stringWithFormat:@"'----':obj { form:'prop', want:type('prop'), seld:type('pnam'), from:obj { form:'indx', want:type('cPly'), seld:long(%u), from:obj { form:'indx', want:type('cSrc'), seld:long(%u), from:() } } }",i,k];
230 NSString *theObj = [ITSendAEWithString(sendStr, 'core', 'getd', &savedPSN) stringValue];
231 ITDebugLog(@" - Adding playlist %@", theObj);
233 [aSource addObject:theObj];
236 [allSources addObject:[aSource autorelease]];
238 ITDebugLog(@"Source at index %i disappeared.", k);
241 NSLog(@"playlists: %@", allSources);
242 ITDebugLog(@"Finished getting playlists.");
243 return [allSources autorelease];
246 - (NSArray *)playlists
248 SInt32 numSources = [ITSendAEWithString(@"kocl:type('cSrc'), '----':()", 'core', 'cnte', &savedPSN) int32Value];
249 NSMutableArray *sources = [[NSMutableArray alloc] init];
252 ITDebugLog(@"Getting playlists.");
253 if (numSources == 0) {
255 ITDebugLog(@"No sources.");
259 //Loop through each source
260 for (i = 1; i <= numSources; i++) {
261 FourCharCode fourcc = [ITSendAEWithString([NSString stringWithFormat:@"'----':obj { form:'prop', want:type('prop'), seld:type('pKnd'), from:obj { form:'indx', want:type('cSrc'), seld:long(%i), from:() } }", i], 'core', 'getd', &savedPSN) typeCodeValue]; //Type of the current source
262 NSString *sourceName = [ITSendAEWithString([NSString stringWithFormat:@"'----':obj { form:'prop', want:type('prop'), seld:type('pnam'), from:obj { form:'indx', want:type('cSrc'), seld:long(%i), from:() } }", i], 'core', 'getd', &savedPSN) stringValue]; //Name of the current source
263 SInt32 index = [ITSendAEWithString([NSString stringWithFormat:@"'----':obj { form:'prop', want:type('prop'), seld:type('pidx'), from:obj { form:'indx', want:type('cSrc'), seld:long(%i), from:() } }", i], 'core', 'getd', &savedPSN) int32Value]; //Index of the current source
264 ITMTRemotePlayerSource class; //The class of the current source
266 //Make a new PlaylistNode for this source
267 PlaylistNode *sourceNode = [PlaylistNode playlistNodeWithName:sourceName type:ITMTSourceNode index:index];
271 class = ITMTRemoteRadioSource;
274 class = ITMTRemoteGenericDeviceSource;
277 class = ITMTRemoteiPodSource;
281 class = ITMTRemoteCDSource;
284 class = ITMTRemoteSharedLibrarySource;
289 class = ITMTRemoteLibrarySource;
292 [sourceNode setSourceType:class];
293 ITDebugLog(@"New source %@ of type %i at index %i", sourceName, class, index);
296 SInt32 numPlaylists = [ITSendAEWithString([NSString stringWithFormat:@"kocl:type('cPly'), '----':obj { form:'indx', want:type('cSrc'), seld:long(%i), from:() }", i], 'core', 'cnte', &savedPSN) int32Value]; //Number of playlists in the current source
298 //Pass 1, add all the playlists into the main array
299 for (j = 1; j <= numPlaylists; j++) {
300 NSString *sendStr = [NSString stringWithFormat:@"'----':obj { form:'prop', want:type('prop'), seld:type('pnam'), from:obj { form:'indx', want:type('cPly'), seld:long(%i), from:obj { form:'indx', want:type('cSrc'), seld:long(%i), from:() } } }", j, (_iTunesVersion >= 5) ? i : index];
301 NSString *parentSendStr = [NSString stringWithFormat:@"'----':obj { form:'prop', want:type('prop'), seld:type('pnam'), from:obj { form:'prop', want:type('prop'), seld:type('pPlP'), from:obj { form:'indx', want:type('cPly'), seld:long(%i), from:obj { form:'indx', want:type('cSrc'), seld:long(%i), from:() } } } }", j, i];
302 NSString *theObj = [ITSendAEWithString(sendStr, 'core', 'getd', &savedPSN) stringValue], *parent = [ITSendAEWithString(parentSendStr, 'core', 'getd', &savedPSN) stringValue];
303 ITDebugLog(@" - Adding playlist %@", theObj);
305 FourCharCode code = [ITSendAEWithString([NSString stringWithFormat:@"'----':obj { form:'prop', want:type('prop'), seld:type('pSpK'), from:obj { form:'indx', want:type('cPly'), seld:long(%i), from:obj { form:'indx', want:type('cSrc'), seld:long(%i), from:() } } }", j, i], 'core', 'getd', &savedPSN) typeCodeValue];
309 type = ITMTPlaylistNode;
312 type = ITMTFolderNode;
315 type = ITMTPartyShuffleNode;
318 type = ITMTPodcastsNode;
321 type = ITMTPurchasedMusicNode;
324 type = ITMTVideosNode;
327 PlaylistNode *node = [PlaylistNode playlistNodeWithName:theObj type:type index:j];
328 [[sourceNode children] addObject:node];
330 int parentIndex = [ITSendAEWithString([NSString stringWithFormat:@"'----':obj { form:'prop', want:type('prop'), seld:type('pidx'), from:obj { form:'prop', want:type('prop'), seld:type('pPlP'), from:obj { form:'indx', want:type('cPly'), seld:long(%i), from:obj { form:'indx', want:type('cSrc'), seld:long(%i), from:() } } } }", j, i], 'core', 'getd', &savedPSN) int32Value];
331 [node setParent:[PlaylistNode playlistNodeWithName:parent type:ITMTFolderNode index:parentIndex]];
333 [node setParent:sourceNode];
338 //Pass 2, nest each item under its proper parent. Once everything has been nested, delete the original from the main array.
339 NSEnumerator *enumerator = [[sourceNode children] objectEnumerator];
340 PlaylistNode *nextNode;
341 NSMutableArray *nested = [[NSMutableArray alloc] init];
343 while ( (nextNode = [enumerator nextObject]) ) {
344 PlaylistNode *pNode = [nextNode parent];
345 if ([pNode type] == ITMTFolderNode) {
346 PlaylistNode *newParent = nil;
348 for (k = 0; !newParent; k++) {
349 PlaylistNode *test = [[sourceNode children] objectAtIndex:k];
350 if ([test index] == [pNode index]) {
354 [nextNode setParent:newParent];
355 [[newParent children] addObject:nextNode];
356 [newParent setType:ITMTFolderNode];
357 [nested addObject:nextNode];
361 NSEnumerator *nestEnumerator = [nested objectEnumerator];
362 while ( (nextNode = [nestEnumerator nextObject]) ) {
363 [[sourceNode children] removeObject:nextNode];
367 //Move all the folders to the beginning of the list
368 //Move the podcasts playlist to the top
369 BOOL movedPodcasts = NO;
370 enumerator = [[sourceNode children] reverseObjectEnumerator];
371 while ( (nextNode = [enumerator nextObject]) ) {
372 if ([nextNode type] == ITMTPodcastsNode) {
374 [[sourceNode children] removeObject:nextNode];
375 [[sourceNode children] insertObject:nextNode atIndex:1];
377 } else if ([nextNode type] == ITMTFolderNode) {
379 [[sourceNode children] removeObject:nextNode];
380 [[sourceNode children] insertObject:nextNode atIndex:1 + movedPodcasts];
384 [sources addObject:sourceNode];
387 return [sources autorelease];
392 NSAppleEventDescriptor *rawr = ITSendAEWithString(@"'----':obj { form:'prop', want:type('prop'), seld:type('pArt'), from:obj { form:'indx', want:type('cTrk'), seld:abso($616C6C20$), from:obj { form:'indx', want:type('cPly'), seld:long(1), from:obj { form:'indx', want:type('cSrc'), seld:long(1), from:() } } } }", 'core', 'getd', &savedPSN);
394 NSMutableArray *array = [[NSMutableArray alloc] init];
395 NSArray *returnArray;
396 for (i = 1; i <= [rawr numberOfItems]; i++) {
397 NSString *artist = [[rawr descriptorAtIndex:i] stringValue];
398 if (artist && [artist length] && ![array containsObject:artist]) {
399 [array addObject:artist];
402 [array sortUsingSelector:@selector(caseInsensitiveCompare:)];
403 returnArray = [NSArray arrayWithArray:array];
410 NSAppleEventDescriptor *rawr = ITSendAEWithString(@"'----':obj { form:'prop', want:type('prop'), seld:type('pAlb'), from:obj { form:'indx', want:type('cTrk'), seld:abso($616C6C20$), from:obj { form:'indx', want:type('cPly'), seld:long(1), from:obj { form:'indx', want:type('cSrc'), seld:long(1), from:() } } } }", 'core', 'getd', &savedPSN);
412 NSMutableArray *array = [[NSMutableArray alloc] init];
413 NSArray *returnArray;
414 for (i = 1; i <= [rawr numberOfItems]; i++) {
415 NSString *album = [[rawr descriptorAtIndex:i] stringValue];
416 if (album && [album length] && ![array containsObject:album]) {
417 [array addObject:album];
420 [array sortUsingSelector:@selector(caseInsensitiveCompare:)];
421 returnArray = [NSArray arrayWithArray:array];
426 - (int)numberOfSongsInPlaylistAtIndex:(int)index
429 This method only returns the proper number if there's something playing.
430 This is because it gets the container of the current playlist so that it
431 gets the playlist index from the current source. Operating this way is fine,
432 since MT only ever calls this method when there is something playlist.
433 A working version of this that works in just the main source is in the
434 makePlaylistWithTerm:ofType: method.
437 NSAppleEventDescriptor *result;
438 ITDebugLog(@"Getting number of songs in playlist at index %i", index);
439 result = ITSendAEWithString([NSString stringWithFormat:@"kocl:type('cTrk'), '----':obj { form:'indx', want:type('cPly'), seld:long(%lu), from:obj { form:'prop', want:type('prop'), seld:type('ctnr'), from:obj { form:'prop', want:type('prop'), seld:type('pPla'), from:'null'() } } }", index], 'core', 'cnte', &savedPSN);
440 temp1 = (result == nil) ? -1 : (int)[result int32Value];
441 ITDebugLog(@"Getting number of songs in playlist at index %i done", index);
445 - (ITMTRemotePlayerSource)currentSource
449 ITDebugLog(@"Getting current source.");
451 fourcc = ([self isPlaying]) ? [ITSendAEWithString(@"'----':obj { form:'prop', want:type('prop'), seld:type('pKnd'), from:obj { form:'prop', want:type('prop'), seld:type('ctnr'), from:obj { form:'prop', want:type('prop'), seld:type('pPla'), from:'null'() } } }", 'core', 'getd', &savedPSN) typeCodeValue] : 'kLib';
455 ITDebugLog(@"Getting current source done. Source: Radio.");
456 return ITMTRemoteRadioSource;
459 ITDebugLog(@"Getting current source done. Source: Generic Device.");
460 return ITMTRemoteGenericDeviceSource;
462 ITDebugLog(@"Getting current source done. Source: iPod.");
463 return ITMTRemoteiPodSource; //this is stupid
467 ITDebugLog(@"Getting current source done. Source: CD.");
468 return ITMTRemoteCDSource;
471 ITDebugLog(@"Getting current source done. Source: Shared Library.");
472 return ITMTRemoteSharedLibrarySource;
477 ITDebugLog(@"Getting current source done. Source: Library.");
478 return ITMTRemoteLibrarySource;
483 - (int)currentSourceIndex
485 ITDebugLog(@"Getting current source.");
486 return [ITSendAEWithString(@"'----':obj { form:'prop', want:type('prop'), seld:type('pidx'), from:obj { form:'prop', want:type('prop'), seld:type('ctnr'), from:obj { form:'prop', want:type('prop'), seld:type('pPla'), from:'null'() } } }", 'core', 'getd', &savedPSN) int32Value];
489 - (ITMTRemotePlayerPlaylistClass)currentPlaylistClass
491 FourCharCode realResult;
492 ITDebugLog(@"Getting current playlist class");
493 realResult = [ITSendAEWithString(@"'----':obj { form:'prop', want:type('prop'), seld:type('pcls'), from:obj { form:'prop', want:type('prop'), seld:type('pPla'), from:'null'() } }", 'core', 'getd', &savedPSN) typeCodeValue];
497 ITDebugLog(@"Getting current playlist class done. Class: Library.");
498 return ITMTRemotePlayerLibraryPlaylist;
501 ITDebugLog(@"Getting current playlist class done. Class: Radio.");
502 return ITMTRemotePlayerRadioPlaylist;
505 ITDebugLog(@"Getting current playlist class done. Class: Standard playlist.");
506 return ITMTRemotePlayerPlaylist;
510 - (int)currentPlaylistIndex
513 ITDebugLog(@"Getting current playlist index.");
514 temp1 = ([self isPlaying] ? [ITSendAEWithString(@"'----':obj { form:'prop', want:type('prop'), seld:type('pidx'), from:obj { form:'prop', want:type('prop'), seld:type('pPla'), from:'null'() } }", 'core', 'getd', &savedPSN) int32Value] : -1);
515 ITDebugLog(@"Getting current playlist index done.");
519 - (NSString *)songTitleAtIndex:(int)index
522 ITDebugLog(@"Getting song title at index %i.", index);
523 temp1 = [ITSendAEWithString([NSString stringWithFormat:@"'----':obj { form:'prop', want:type('prop'), seld:type('pnam'), from:obj { form:'indx', want:type('cTrk'), seld:long(%lu), from:obj { form:'prop', want:type('prop'), seld:type('pPla'), from:'null'() } } }",index], 'core', 'getd', &savedPSN) stringValue];
524 ITDebugLog(@"Getting song title at index %i done.", index);
525 return ( ([temp1 length]) ? temp1 : nil ) ;
528 - (int)currentAlbumTrackCount
531 ITDebugLog(@"Getting current album track count.");
532 temp1 = [ITSendAEWithString(@"'----':obj { form:'prop', want:type('prop'), seld:type('pTrC'), from:obj { form:'prop', want:type('prop'), seld:type('pTrk'), from:'null'() } }", 'core', 'getd', &savedPSN) int32Value];
533 if ( [self currentPlaylistClass] == ITMTRemotePlayerRadioPlaylist ) { temp1 = 0; }
534 ITDebugLog(@"Getting current album track count done.");
538 - (int)currentSongTrack
541 ITDebugLog(@"Getting current song track.");
542 temp1 = [ITSendAEWithString(@"'----':obj { form:'prop', want:type('prop'), seld:type('pTrN'), from:obj { form:'prop', want:type('prop'), seld:type('pTrk'), from:'null'() } }", 'core', 'getd', &savedPSN) int32Value];
543 if ( [self currentPlaylistClass] == ITMTRemotePlayerRadioPlaylist ) { temp1 = 0; }
544 ITDebugLog(@"Getting current song track done.");
548 - (NSString *)playerStateUniqueIdentifier
551 ITDebugLog(@"Getting current unique identifier.");
552 NSAppleEventDescriptor *descriptor = ITSendAEWithString(@"'----':obj { form:'prop', want:type('prop'), seld:type('pcls'), from:obj { form:'prop', want:type('prop'), seld:type('pTrk'), from:'null'() } }", 'core', 'getd', &savedPSN);
553 if ([descriptor typeCodeValue] == 'prop') {
555 } else if (descriptor == nil) {
558 FourCharCode cls = [descriptor typeCodeValue];
559 if ( ([self currentPlaylistClass] == ITMTRemotePlayerRadioPlaylist) || (cls == 'cURT') ) {
560 NSString *bad = [NSString stringWithUTF8String:"浳湧"];
561 temp1 = [ITSendAEWithKey('pStT', 'core', 'getd', &savedPSN) stringValue];
562 if ([temp1 isEqualToString:bad]) {
563 temp1 = [ITSendAEWithString(@"'----':obj { form:'prop', want:type('prop'), seld:type('pnam'), from:obj { form:'prop', want:type('prop'), seld:type('pTrk'), from:'null'() } }", 'core', 'getd', &savedPSN) stringValue];
566 temp1 = [NSString stringWithFormat:@"%i-%i", [self currentPlaylistIndex], [ITSendAEWithString(@"'----':obj { form:'prop', want:type('prop'), seld:type('pDID'), from:obj { form:'prop', want:type('prop'), seld:type('pTrk'), from:'null'() } }", 'core', 'getd', &savedPSN) int32Value]];
568 ITDebugLog(@"Getting current unique identifier done.");
569 return ( ([temp1 length]) ? temp1 : nil ) ;
572 - (int)currentSongIndex
575 ITDebugLog(@"Getting current song index.");
576 temp1 = ([self isPlaying] ? [ITSendAEWithString(@"'----':obj { form:'prop', want:type('prop'), seld:type('pidx'), from:obj { form:'prop', want:type('prop'), seld:type('pTrk'), from:'null'() } }", 'core', 'getd', &savedPSN) int32Value] : -1);
577 ITDebugLog(@"Getting current song index done.");
581 - (NSString *)currentSongTitle
584 ITDebugLog(@"Getting current song title.");
585 FourCharCode result = [ITSendAEWithString(@"'----':obj { form:'prop', want:type('prop'), seld:type('pcls'), from:obj { form:'prop', want:type('prop'), seld:type('pTrk'), from:'null'() } }", 'core', 'getd', &savedPSN) typeCodeValue];
587 //If we're listening to the radio.
588 if (result == 'cURT') {
589 NSString *bad = [NSString stringWithUTF8String:"浳湧"];
590 temp1 = [ITSendAEWithKey('pStT', 'core', 'getd', &savedPSN) stringValue];
591 if ([temp1 isEqualToString:bad]) {
592 temp1 = [ITSendAEWithString(@"'----':obj { form:'prop', want:type('prop'), seld:type('pnam'), from:obj { form:'prop', want:type('prop'), seld:type('pTrk'), from:'null'() } }", 'core', 'getd', &savedPSN) stringValue];
594 temp1 = [temp1 stringByAppendingString:@" (Stream)"];
595 } else if (result == 'prop') {
598 temp1 = [ITSendAEWithString(@"'----':obj { form:'prop', want:type('prop'), seld:type('pnam'), from:obj { form:'prop', want:type('prop'), seld:type('pTrk'), from:'null'() } }", 'core', 'getd', &savedPSN) stringValue];
600 ITDebugLog(@"Getting current song title done.");
601 return ( ([temp1 length]) ? temp1 : nil ) ;
604 - (NSString *)currentSongArtist
607 ITDebugLog(@"Getting current song artist.");
608 if ( [self currentPlaylistClass] != ITMTRemotePlayerRadioPlaylist ) {
609 temp1 = [ITSendAEWithString(@"'----':obj { form:'prop', want:type('prop'), seld:type('pArt'), from:obj { form:'prop', want:type('prop'), seld:type('pTrk'), from:'null'() } }", 'core', 'getd', &savedPSN) stringValue];
613 ITDebugLog(@"Getting current song artist done.");
614 return ( ([temp1 length]) ? temp1 : nil ) ;
617 - (NSString *)currentSongComposer
620 ITDebugLog(@"Getting current song artist.");
621 if ( [self currentPlaylistClass] != ITMTRemotePlayerRadioPlaylist ) {
622 temp1 = [ITSendAEWithString(@"'----':obj { form:'prop', want:type('prop'), seld:type('pCmp'), from:obj { form:'prop', want:type('prop'), seld:type('pTrk'), from:'null'() } }", 'core', 'getd', &savedPSN) stringValue];
626 ITDebugLog(@"Getting current song artist done.");
627 return ( ([temp1 length]) ? temp1 : nil ) ;
630 - (NSString *)currentSongAlbum
633 ITDebugLog(@"Getting current song album.");
634 if ( [self currentPlaylistClass] != ITMTRemotePlayerRadioPlaylist ) {
635 temp1 = [ITSendAEWithString(@"'----':obj { form:'prop', want:type('prop'), seld:type('pAlb'), from:obj { form:'prop', want:type('prop'), seld:type('pTrk'), from:'null'() } }", 'core', 'getd', &savedPSN) stringValue];
639 ITDebugLog(@"Getting current song album done.");
640 return ( ([temp1 length]) ? temp1 : nil ) ;
643 - (NSString *)currentSongGenre
646 ITDebugLog(@"Getting current song genre.");
647 temp1 = [ITSendAEWithString(@"'----':obj { form:'prop', want:type('prop'), seld:type('pGen'), from:obj { form:'prop', want:type('prop'), seld:type('pTrk'), from:'null'() } }", 'core', 'getd', &savedPSN) stringValue];
648 ITDebugLog(@"Getting current song genre done.");
649 return ( ([temp1 length]) ? temp1 : nil ) ;
652 - (NSString *)currentSongLength
656 ITDebugLog(@"Getting current song length.");
657 temp1 = [ITSendAEWithString(@"'----':obj { form:'prop', want:type('prop'), seld:type('pcls'), from:obj { form:'prop', want:type('prop'), seld:type('pTrk'), from:'null'() } }", 'core', 'getd', &savedPSN) int32Value];
658 temp2 = [ITSendAEWithString(@"'----':obj { form:'prop', want:type('prop'), seld:type('pTim'), from:obj { form:'prop', want:type('prop'), seld:type('pTrk'), from:'null'() } }", 'core', 'getd', &savedPSN) stringValue];
659 if ( ([self currentPlaylistClass] == ITMTRemotePlayerRadioPlaylist) || (temp1 == 'cURT') ) { temp2 = @"Continuous"; }
660 ITDebugLog(@"Getting current song length done.");
664 - (NSString *)currentSongRemaining
666 SInt32 duration, current, final;
667 NSString *finalString;
669 ITDebugLog(@"Getting current song remaining time.");
671 duration = [ITSendAEWithString(@"'----':obj { form:'prop', want:type('prop'), seld:type('pDur'), from:obj { form:'prop', want:type('prop'), seld:type('pTrk'), from:'null'() } }", 'core', 'getd', &savedPSN) int32Value];
672 current = [ITSendAEWithString(@"'----':obj { form:'prop', want:type('prop'), seld:type('pPos'), from:obj { form:'prop', want:type('prop'), seld:type('pTrk'), from:'null'() } }", 'core', 'getd', &savedPSN) int32Value];
673 final = duration - current;
674 finalString = [self formatTimeInSeconds:final];
676 if ( [self currentPlaylistClass] == ITMTRemotePlayerRadioPlaylist ) { finalString = nil; }
678 ITDebugLog(@"Getting current song remaining time done.");
683 - (NSString *)currentSongElapsed
686 NSString *finalString;
688 ITDebugLog(@"Getting current song elapsed time.");
689 final = (long)[ITSendAEWithKey('pPos', 'core', 'getd', &savedPSN) int32Value];
690 finalString = [self formatTimeInSeconds:final];
691 ITDebugLog(@"Getting current song elapsed time done.");
695 - (NSImage *)currentSongAlbumArt
697 ITDebugLog(@"Getting current song album art.");
698 NSData *data = ([self isPlaying]) ? [ITSendAEWithString(@"'----':obj { form:'prop', want:type('prop'), seld:type('pPCT'), from:obj { form:'indx', want:type('cArt'), seld:long(1), from:obj { form:'prop', want:type('prop'), seld:type('pTrk'), from:'null'() } } }", 'core', 'getd', &savedPSN) data] : nil;
699 ITDebugLog(@"Getting current song album art done.");
701 return [[[NSImage alloc] initWithData:data] autorelease];
707 - (int)currentSongPlayCount
710 ITDebugLog(@"Getting current song play count.");
711 count = (int)[ITSendAEWithString(@"'----':obj { form:'prop', want:type('prop'), seld:type('pPlC'), from:obj { form:'prop', want:type('prop'), seld:type('pTrk'), from:'null'() } }", 'core', 'getd', &savedPSN) int32Value];
712 ITDebugLog(@"Getting current song play count done.");
716 - (float)currentSongRating
719 ITDebugLog(@"Getting current song rating.");
720 temp1 = (![self isPlaying] || ([self currentPlaylistClass] == ITMTRemotePlayerRadioPlaylist)) ? -1.0 : ((float)[ITSendAEWithString(@"'----':obj { form:'prop', want:type('prop'), seld:type('pRte'), from:obj { form:'prop', want:type('prop'), seld:type('pTrk'), from:'null'() } }", 'core', 'getd', &savedPSN) int32Value] / 100.0);
721 ITDebugLog(@"Getting current song rating done.");
725 - (BOOL)setCurrentSongRating:(float)rating
727 ITDebugLog(@"Setting current song rating to %f.", rating);
728 if ( [self currentPlaylistClass] == ITMTRemotePlayerRadioPlaylist ) { return NO; }
729 ITSendAEWithString([NSString stringWithFormat:@"data:long(%lu), '----':obj { form:'prop', want:type('prop'), seld:type('pRte'), from:obj { form:'indx', want:type('cTrk'), seld:long(%lu), from:obj { form:'prop', want:type('prop'), seld:type('pPla'), from:'null'() } } }",(long)(rating*100), [self currentSongIndex]], 'core', 'setd', &savedPSN);
730 ITDebugLog(@"Setting current song rating to %f done.", rating);
734 - (BOOL)currentSongShufflable
737 ITDebugLog(@"Getting current song shufflable status.");
738 temp1 = (![self isPlaying] || ([self currentPlaylistClass] == ITMTRemotePlayerRadioPlaylist)) ? NO : [ITSendAEWithString(@"'----':obj { form:'prop', want:type('prop'), seld:type('pSfa'), from:obj { form:'prop', want:type('prop'), seld:type('pTrk'), from:'null'() } }", 'core', 'getd', &savedPSN) booleanValue];
739 ITDebugLog(@"Getting current song shufflable status done.");
743 - (BOOL)setCurrentSongShufflable:(BOOL)shufflable
745 ITDebugLog(@"Setting current song shufflable status to %i.", shufflable);
746 if ([self currentPlaylistClass] == ITMTRemotePlayerRadioPlaylist) {
747 ITDebugLog(@"Not a valid track to set status to, returning.");
750 ITSendAEWithString([NSString stringWithFormat:@"data:long(%lu), '----':obj { form:'prop', want:type('prop'), seld:type('pSfa'), from:obj { form:'indx', want:type('cTrk'), seld:long(%lu), from:obj { form:'prop', want:type('prop'), seld:type('pPla'), from:'null'() } } }", !shufflable, [self currentSongIndex]], 'core', 'setd', &savedPSN);
751 ITDebugLog(@"Setting current song shufflable status to %i done.", shufflable);
755 - (BOOL)equalizerEnabled
757 ITDebugLog(@"Getting equalizer enabled status.");
758 int thingy = (int)[ITSendAEWithKey('pEQ ', 'core', 'getd', &savedPSN) int32Value];
759 ITDebugLog(@"Done getting equalizer enabled status.");
760 return (thingy != 0) ? YES : NO;
763 - (BOOL)setEqualizerEnabled:(BOOL)enabled
765 ITDebugLog(@"Setting equalizer enabled to %i.", enabled);
766 ITSendAEWithString([NSString stringWithFormat:@"data:long(%lu), '----':obj { form:'prop', want:type('prop'), seld:type('pEQ '), from:'null'() }", enabled], 'core', 'setd', &savedPSN);
767 ITDebugLog(@"Done setting equalizer enabled to %i.", enabled);
771 - (NSArray *)eqPresets
774 SInt32 numPresets = [ITSendAEWithString(@"kocl:type('cEQP'), '----':(), &subj:()", 'core', 'cnte', &savedPSN) int32Value];
775 NSMutableArray *presets = [[NSMutableArray alloc] initWithCapacity:numPresets];
776 ITDebugLog(@"Getting EQ presets");
777 for (i = 1; i <= numPresets; i++) {
778 NSString *theObj = [ITSendAEWithString([NSString stringWithFormat:@"'----':obj { form:'prop', want:type('prop'), seld:type('pnam'), from:obj { form:'indx', want:type('cEQP'), seld:long(%lu), from:'null'() } }", i], 'core', 'getd', &savedPSN) stringValue];
780 ITDebugLog(@"Adding preset %@", theObj);
781 [presets addObject:theObj];
784 ITDebugLog(@"Done getting EQ presets");
785 return [presets autorelease];
788 - (int)currentEQPresetIndex
791 ITDebugLog(@"Getting current EQ preset index.");
792 result = (int)[ITSendAEWithString(@"'----':obj { form:'prop', want:type('prop'), seld:type('pidx'), from:obj { form:'prop', want:type('prop'), seld:type('pEQP'), from:'null'() } }", 'core', 'getd', &savedPSN) int32Value];
793 ITDebugLog(@"Getting current EQ preset index done.");
799 ITDebugLog(@"Getting volume.");
800 ITDebugLog(@"Getting volume done.");
801 return (float)[ITSendAEWithKey('pVol', 'core', 'getd', &savedPSN) int32Value] / 100;
804 - (BOOL)setVolume:(float)volume
806 ITDebugLog(@"Setting volume to %f.", volume);
807 ITSendAEWithString([NSString stringWithFormat:@"data:long(%lu), '----':obj { form:'prop', want:type('prop'), seld:type('pVol'), from:'null'() }", (long)(volume * 100)], 'core', 'setd', &savedPSN);
808 ITDebugLog(@"Setting volume to %f done.", volume);
812 - (BOOL)shuffleEnabled
815 ITDebugLog(@"Getting shuffle enabled status.");
816 if (![self isPlaying]) {
817 ITDebugLog(@"No current playlist, getting shuffle status from visible playlist.");
818 result = (int)[ITSendAEWithString(@"'----':obj { form:'prop', want:type('prop'), seld:type('pShf'), from:obj { form:'prop', want:type('prop'), seld:type('pPly'), from:obj { form:'indx', want:type('cBrW'), seld:1, from:'null'() } } }", 'core', 'getd', &savedPSN) int32Value];
820 result = (int)[ITSendAEWithString(@"'----':obj { form:'prop', want:type('prop'), seld:type('pShf'), from:obj { form:'prop', want:type('prop'), seld:type('pPla'), from:'null'() } }", 'core', 'getd', &savedPSN) int32Value];
822 ITDebugLog(@"Getting shuffle enabled status done.");
823 return (result != 0);
826 - (BOOL)setShuffleEnabled:(BOOL)enabled
828 ITDebugLog(@"Set shuffle enabled to %i", enabled);
829 if (![self isPlaying]) {
830 ITDebugLog(@"No current playlist, setting shuffle status on visible playlist.");
831 ITSendAEWithString([NSString stringWithFormat:@"data:long(%lu), '----':obj { form:'prop', want:type('prop'), seld:type('pShf'), from:obj { form:'prop', want:type('prop'), seld:type('pPly'), from:obj { form:'indx', want:type('cBrW'), seld:1, from:'null'() } } }", (unsigned long)enabled], 'core', 'setd', &savedPSN);
833 ITSendAEWithString([NSString stringWithFormat:@"data:long(%lu), '----':obj { form:'prop', want:type('prop'), seld:type('pShf'), from:obj { form:'prop', want:type('prop'), seld:type('pPla'), from:'null'() } }", (unsigned long)enabled], 'core', 'setd', &savedPSN);
835 ITDebugLog(@"Set shuffle enabled to %i done", enabled);
839 - (ITMTRemotePlayerRepeatMode)repeatMode
841 FourCharCode m00f = 0;
843 ITDebugLog(@"Getting repeat mode.");
844 m00f = (FourCharCode)[ITSendAEWithString(@"'----':obj { form:'prop', want:type('prop'), seld:type('pRpt'), from:obj { form:'prop', want:type('prop'), seld:type('pPla'), from:'null'() } }", 'core', 'getd', &savedPSN) typeCodeValue];
847 ITDebugLog(@"No current playlist, getting repeat mode from visible playlist.");
848 m00f = (FourCharCode)[ITSendAEWithString(@"'----':obj { form:'prop', want:type('prop'), seld:type('pRpt'), from:obj { form:'prop', want:type('prop'), seld:type('pPly'), from:obj { form:'indx', want:type('cBrW'), seld:1, from:'null'() } } }", 'core', 'getd', &savedPSN) typeCodeValue];
855 ITDebugLog(@"Repeat off");
856 result = ITMTRemotePlayerRepeatOff;
859 ITDebugLog(@"Repeat one");
860 result = ITMTRemotePlayerRepeatOne;
863 ITDebugLog(@"Repeat all");
864 result = ITMTRemotePlayerRepeatAll;
867 ITDebugLog(@"Getting repeat mode done.");
871 - (BOOL)setRepeatMode:(ITMTRemotePlayerRepeatMode)repeatMode
874 ITDebugLog(@"Setting repeat mode to %i", repeatMode);
877 case ITMTRemotePlayerRepeatOne:
880 case ITMTRemotePlayerRepeatAll:
883 case ITMTRemotePlayerRepeatOff:
888 if (![self isPlaying]) {
889 ITDebugLog(@"No current playlist, setting repeat mode on visible playlist.");
890 ITSendAEWithString([NSString stringWithFormat:@"data:'%s', '----':obj { form:'prop', want:type('prop'), seld:type('pRpt'), from:obj { form:'prop', want:type('prop'), seld:type('pPly'), from:obj { form:'indx', want:type('cBrW'), seld:1, from:'null'() } } }", m00f], 'core', 'setd', &savedPSN);
892 ITSendAEWithString([NSString stringWithFormat:@"data:'%s', '----':obj { form:'prop', want:type('prop'), seld:type('pRpt'), from:obj { form:'prop', want:type('prop'), seld:type('pPla'), from:() } }", m00f], 'core', 'setd', &savedPSN);
894 ITDebugLog(@"Setting repeat mode to %c done", m00f);
901 ITSendAE('hook', 'Play', &savedPSN);
902 ITDebugLog(@"Play done");
908 ITDebugLog(@"Pause");
909 ITSendAE('hook', 'Paus', &savedPSN);
910 ITDebugLog(@"Pause done");
916 ITDebugLog(@"Go to next track");
917 ITSendAE('hook', 'Next', &savedPSN);
918 ITDebugLog(@"Go to next track done");
922 - (BOOL)goToPreviousSong
924 ITDebugLog(@"Go to previous track");
925 ITSendAE('hook', 'Back', &savedPSN);
926 ITDebugLog(@"Go to previous track done");
932 ITDebugLog(@"Fast forward action");
933 ITSendAE('hook', 'Fast', &savedPSN);
934 ITDebugLog(@"Fast forward action done");
940 ITDebugLog(@"Rewind action");
941 ITSendAE('hook', 'Rwnd', &savedPSN);
942 ITDebugLog(@"Rewind action done");
946 - (BOOL)switchToPlaylistAtIndex:(int)index
948 ITDebugLog(@"Switching to playlist at index %i", index);
949 ITSendAEWithString([NSString stringWithFormat:@"'----':obj { form:'indx', want:type('cPly'), seld:long(%lu), from:() }", index], 'hook', 'Play', &savedPSN);
950 ITDebugLog(@"Done switching to playlist at index %i", index);
954 - (BOOL)switchToPlaylistAtIndex:(int)index ofSourceAtIndex:(int)index2
956 ITDebugLog(@"Switching to playlist at index %i of source %i", index, index2);
957 ITSendAEWithString([NSString stringWithFormat:@"'----':obj { form:'indx', want:type('cPly'), seld:long(%lu), from: obj { form:'indx', want:type('cSrc'), seld:long(%lu), from:'null'() } }", index - 1, index2 + 1], 'hook', 'Play', &savedPSN);
958 ITDebugLog(@"Done switching to playlist at index %i of source %i", index, index2);
962 - (BOOL)switchToSongAtIndex:(int)index
964 ITDebugLog(@"Switching to track at index %i", index);
965 ITSendAEWithString([NSString stringWithFormat:@"'----':obj { form:'indx', want:type('cTrk'), seld:long(%lu), from:obj { form:'prop', want:type('prop'), seld:type('pPla'), from:() } }", index], 'hook' ,'Play', &savedPSN);
966 ITDebugLog(@"Done switching to track at index %i", index);
970 - (BOOL)switchToEQAtIndex:(int)index
972 ITDebugLog(@"Switching to EQ preset at index %i", index);
973 // index should count from 0, but itunes counts from 1, so let's add 1.
974 [self setEqualizerEnabled:YES];
975 ITSendAEWithString([NSString stringWithFormat:@"'----':obj { form:'prop', want:type('prop'), seld:type('pEQP'), from:'null'() }, data:obj { form:'indx', want:type('cEQP'), seld:long(%lu), from:'null'() }", (index+1)], 'core', 'setd', &savedPSN);
976 ITDebugLog(@"Done switching to EQ preset at index %i", index);
980 - (BOOL)makePlaylistWithTerm:(NSString *)term ofType:(int)type
984 //Get fixed indexing status
985 BOOL fixed = [ITSendAEWithString(@"'----':obj { form:'prop', want:type('prop'), seld:type('pFix'), from:'null'() }", 'core', 'getd', &savedPSN) booleanValue];
987 //Enabled fixed indexing
988 ITSendAEWithString(@"data:long(1), '----':obj { form:'prop', want:type('prop'), seld:type('pFix'), from:'null'() }", 'core', 'setd', &savedPSN);
990 //Search for the term
991 NSAppleEventDescriptor *searchResults = ITSendAEWithString([NSString stringWithFormat:@"pTrm:\"%@\", pAre:'%@', '----':obj { form:'indx', want:type('cPly'), seld:long(1), from:obj { form:'indx', want:type('cSrc'), seld:long(1), from:'null'() } }", term, ((type == 1) ? @"kSrR" : @"kSrL")], 'hook', 'Srch', &savedPSN);
993 //If MenuTunes playlist exists
994 if ([ITSendAEWithString(@"'----':obj { form:'name', want:type('cPly'), seld:\"MenuTunes\", from:'null'() }", 'core', 'doex', &savedPSN) booleanValue]) {
995 //Clear old MenuTunes playlist
996 int numSongs = [ITSendAEWithString(@"kocl:type('cTrk'), '----':obj { form:'name', want:type('cPly'), seld:\"MenuTunes\", from:'null'() }", 'core', 'cnte', &savedPSN) int32Value];
997 for (i = 1; i <= numSongs; i++) {
998 ITSendAEWithString(@"'----':obj { form:'indx', want:type('cTrk'), seld:long(1), from:obj { form:'name', want:type('cPly'), seld:\"MenuTunes\", from:'null'() } }", 'core', 'delo', &savedPSN);
1001 //Create MenuTunes playlist
1002 ITSendAEWithString(@"prdt:{ pnam:\"MenuTunes\" }, kocl:type('cPly'), &subj:()", 'core', 'crel', &savedPSN);
1005 //Duplicate search results to playlist
1006 for (i = 1; i <= [searchResults numberOfItems]; i++) {
1007 //NSLog(@"%@", ITSendAEWithStringAndParameter(@"'----':obj { form:'prop', want:type('prop'), seld:prop('pnam'), from:aevt(@) }", *[[searchResults descriptorAtIndex:i] aeDesc], 'core', 'getd', &savedPSN));
1009 ITSendAEWithStringAndObject(@"insh:obj { form:'name', want:type('cPly'), seld:\"MenuTunes\", from:'null'() }", [[searchResults descriptorAtIndex:i] aeDesc], 'core', 'clon', &savedPSN);
1011 //Reset fixed indexing
1012 ITSendAEWithString([NSString stringWithFormat:@"data:long(%i), '----':obj { form:'prop', want:type('prop'), seld:type('pFix'), from:'null'() }", fixed], 'core', 'setd', &savedPSN);
1014 //Play MenuTunes playlist
1015 ITSendAEWithString(@"'----':obj { form:'name', want:type('cPly'), seld:\"MenuTunes\", from:'null'() }", 'hook', 'Play', &savedPSN);
1022 return ([ITSendAEWithString(@"'----':obj { form:'prop', want:type('prop'), seld:type('pcls'), from:obj { form:'prop', want:type('prop'), seld:type('pTrk'), from:'null'() } }", 'core', 'getd', &savedPSN) typeCodeValue] != 'prop');
1025 - (void)notificationHandler:(NSNotification *)note
1027 ITDebugLog(@"Received notification: %@", note);
1028 [[NSNotificationCenter defaultCenter] postNotificationName:@"ITMTTrackChanged" object:self userInfo:[note userInfo]];
1029 ITDebugLog(@"Handled notification.");
1032 - (ProcessSerialNumber)iTunesPSN
1034 /*NSArray *apps = [[NSWorkspace sharedWorkspace] launchedApplications];
1035 ProcessSerialNumber number;
1037 int count = [apps count];
1039 number.highLongOfPSN = kNoProcess;
1041 for (i = 0; i < count; i++)
1043 NSDictionary *curApp = [apps objectAtIndex:i];
1045 if ([[curApp objectForKey:@"NSApplicationName"] isEqualToString:@"iTunes"])
1047 number.highLongOfPSN = [[curApp objectForKey:
1048 @"NSApplicationProcessSerialNumberHigh"] intValue];
1049 number.lowLongOfPSN = [[curApp objectForKey:
1050 @"NSApplicationProcessSerialNumberLow"] intValue];
1054 ProcessSerialNumber number;
1055 number.highLongOfPSN = kNoProcess;
1056 number.lowLongOfPSN = 0;
1057 ITDebugLog(@"Getting iTunes' PSN.");
1058 while ( (GetNextProcess(&number) == noErr) )
1061 if ( (CopyProcessName(&number, &name) == noErr) )
1063 if ([(NSString *)name isEqualToString:@"iTunes"])
1065 ITDebugLog(@"iTunes' highLPongOfPSN: %lu.", number.highLongOfPSN);
1066 ITDebugLog(@"iTunes' lowLongOfPSN: %lu.", number.lowLongOfPSN);
1067 ITDebugLog(@"Done getting iTunes' PSN.");
1070 [(NSString *)name release];
1073 ITDebugLog(@"Failed getting iTunes' PSN.");
1077 - (NSString*)formatTimeInSeconds:(long)seconds {
1078 long final = seconds;
1079 NSString *finalString;
1082 finalString = [NSString stringWithFormat:@"%i:%@:%@",(final / 3600),[self zeroSixty:(int)((final % 3600) / 60)],[self zeroSixty:(int)((final % 3600) % 60)]];
1084 finalString = [NSString stringWithFormat:@"%i:%@",(final / 60),[self zeroSixty:(int)(final % 60)]];
1087 finalString = [NSString stringWithFormat:@"0:%@",[self zeroSixty:(int)final]];
1091 - (NSString*)zeroSixty:(int)seconds {
1092 if ( (seconds < 10) && (seconds > 0) ) {
1093 return [NSString stringWithFormat:@"0%i",seconds];
1094 } else if ( (seconds == 0) ) {
1095 return [NSString stringWithFormat:@"00"];
1097 return [NSString stringWithFormat:@"%i",seconds];