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 parent] children] removeObject:nextNode];
355 [nextNode setParent:newParent];
356 [[newParent children] addObject:nextNode];
357 [newParent setType:ITMTFolderNode];
358 [nested addObject:nextNode];
362 NSEnumerator *nestEnumerator = [nested objectEnumerator];
363 while ( (nextNode = [nestEnumerator nextObject]) ) {
364 [[sourceNode children] removeObject:nextNode];
365 [nested removeObject:nextNode];
369 //Move all the folders to the beginning of the list
370 //Move the podcasts playlist to the top
371 BOOL movedPodcasts = NO;
372 enumerator = [[sourceNode children] reverseObjectEnumerator];
373 while ( (nextNode = [enumerator nextObject]) ) {
374 if ([nextNode type] == ITMTPodcastsNode) {
375 [[sourceNode children] removeObject:nextNode];
376 [[sourceNode children] insertObject:nextNode atIndex:1];
378 } 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 = ITSendAEWithStringAndTimeout(@"'----':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, 600);
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 = ITSendAEWithStringAndTimeout(@"'----':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, 600);
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 - (BOOL)songEnabledAtIndex:(int)index
531 ITDebugLog(@"Getting song enabled at index %i.", index);
532 temp1 = [ITSendAEWithString([NSString stringWithFormat:@"'----':obj { form:'prop', want:type('prop'), seld:type('enbl'), 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) booleanValue];
533 ITDebugLog(@"Getting song enabled at index %i done.", index);
537 - (int)currentAlbumTrackCount
540 ITDebugLog(@"Getting current album track count.");
541 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];
542 if ( [self currentPlaylistClass] == ITMTRemotePlayerRadioPlaylist ) { temp1 = 0; }
543 ITDebugLog(@"Getting current album track count done.");
547 - (int)currentSongTrack
550 ITDebugLog(@"Getting current song track.");
551 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];
552 if ( [self currentPlaylistClass] == ITMTRemotePlayerRadioPlaylist ) { temp1 = 0; }
553 ITDebugLog(@"Getting current song track done.");
557 - (NSString *)playerStateUniqueIdentifier
560 ITDebugLog(@"Getting current unique identifier.");
561 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);
562 if ([descriptor typeCodeValue] == 'prop') {
564 } else if (descriptor == nil) {
567 FourCharCode cls = [descriptor typeCodeValue];
568 if ( ([self currentPlaylistClass] == ITMTRemotePlayerRadioPlaylist) || (cls == 'cURT') ) {
569 NSString *bad = [NSString stringWithUTF8String:"浳湧"];
570 temp1 = [ITSendAEWithKey('pStT', 'core', 'getd', &savedPSN) stringValue];
571 if ([temp1 isEqualToString:bad]) {
572 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];
575 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]];
577 ITDebugLog(@"Getting current unique identifier done.");
578 return ( ([temp1 length]) ? temp1 : nil ) ;
581 - (int)currentSongIndex
584 ITDebugLog(@"Getting current song index.");
585 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);
586 ITDebugLog(@"Getting current song index done.");
590 - (NSString *)currentSongTitle
593 ITDebugLog(@"Getting current song title.");
594 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];
596 //If we're listening to the radio.
597 if (result == 'cURT') {
598 NSString *bad = [NSString stringWithUTF8String:"浳湧"];
599 temp1 = [ITSendAEWithKey('pStT', 'core', 'getd', &savedPSN) stringValue];
600 if ([temp1 isEqualToString:bad]) {
601 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];
603 temp1 = [temp1 stringByAppendingString:@" (Stream)"];
604 } else if (result == 'prop') {
607 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];
609 ITDebugLog(@"Getting current song title done.");
610 return ( ([temp1 length]) ? temp1 : nil ) ;
613 - (NSString *)currentSongArtist
616 ITDebugLog(@"Getting current song artist.");
617 if ( [self currentPlaylistClass] != ITMTRemotePlayerRadioPlaylist ) {
618 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];
622 ITDebugLog(@"Getting current song artist done.");
623 return ( ([temp1 length]) ? temp1 : nil ) ;
626 - (NSString *)currentSongComposer
629 ITDebugLog(@"Getting current song artist.");
630 if ( [self currentPlaylistClass] != ITMTRemotePlayerRadioPlaylist ) {
631 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];
635 ITDebugLog(@"Getting current song artist done.");
636 return ( ([temp1 length]) ? temp1 : nil ) ;
639 - (NSString *)currentSongAlbum
642 ITDebugLog(@"Getting current song album.");
643 if ( [self currentPlaylistClass] != ITMTRemotePlayerRadioPlaylist ) {
644 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];
648 ITDebugLog(@"Getting current song album done.");
649 return ( ([temp1 length]) ? temp1 : nil ) ;
652 - (NSString *)currentSongGenre
655 ITDebugLog(@"Getting current song genre.");
656 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];
657 ITDebugLog(@"Getting current song genre done.");
658 return ( ([temp1 length]) ? temp1 : nil ) ;
661 - (NSString *)currentSongLength
665 ITDebugLog(@"Getting current song length.");
666 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];
667 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];
668 if ( ([self currentPlaylistClass] == ITMTRemotePlayerRadioPlaylist) || (temp1 == 'cURT') ) { temp2 = @"Continuous"; }
669 ITDebugLog(@"Getting current song length done.");
673 - (NSString *)currentSongRemaining
675 SInt32 duration, current, final;
676 NSString *finalString;
678 ITDebugLog(@"Getting current song remaining time.");
680 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];
681 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];
682 final = duration - current;
683 finalString = [self formatTimeInSeconds:final];
685 if ( [self currentPlaylistClass] == ITMTRemotePlayerRadioPlaylist ) { finalString = nil; }
687 ITDebugLog(@"Getting current song remaining time done.");
692 - (NSString *)currentSongElapsed
695 NSString *finalString;
697 ITDebugLog(@"Getting current song elapsed time.");
698 final = (long)[ITSendAEWithKey('pPos', 'core', 'getd', &savedPSN) int32Value];
699 finalString = [self formatTimeInSeconds:final];
700 ITDebugLog(@"Getting current song elapsed time done.");
704 - (NSImage *)currentSongAlbumArt
706 ITDebugLog(@"Getting current song album art.");
707 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;
708 ITDebugLog(@"Getting current song album art done.");
710 return [[[NSImage alloc] initWithData:data] autorelease];
716 - (int)currentSongPlayCount
719 ITDebugLog(@"Getting current song play count.");
720 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];
721 ITDebugLog(@"Getting current song play count done.");
725 - (float)currentSongRating
728 ITDebugLog(@"Getting current song rating.");
729 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);
730 ITDebugLog(@"Getting current song rating done.");
734 - (BOOL)setCurrentSongRating:(float)rating
736 ITDebugLog(@"Setting current song rating to %f.", rating);
737 if ( [self currentPlaylistClass] == ITMTRemotePlayerRadioPlaylist ) { return NO; }
738 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);
739 ITDebugLog(@"Setting current song rating to %f done.", rating);
743 - (BOOL)currentSongShufflable
746 ITDebugLog(@"Getting current song shufflable status.");
747 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];
748 ITDebugLog(@"Getting current song shufflable status done.");
752 - (BOOL)setCurrentSongShufflable:(BOOL)shufflable
754 ITDebugLog(@"Setting current song shufflable status to %i.", shufflable);
755 if ([self currentPlaylistClass] == ITMTRemotePlayerRadioPlaylist) {
756 ITDebugLog(@"Not a valid track to set status to, returning.");
759 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);
760 ITDebugLog(@"Setting current song shufflable status to %i done.", shufflable);
764 - (BOOL)equalizerEnabled
766 ITDebugLog(@"Getting equalizer enabled status.");
767 int thingy = (int)[ITSendAEWithKey('pEQ ', 'core', 'getd', &savedPSN) int32Value];
768 ITDebugLog(@"Done getting equalizer enabled status.");
769 return (thingy != 0) ? YES : NO;
772 - (BOOL)setEqualizerEnabled:(BOOL)enabled
774 ITDebugLog(@"Setting equalizer enabled to %i.", enabled);
775 ITSendAEWithString([NSString stringWithFormat:@"data:long(%lu), '----':obj { form:'prop', want:type('prop'), seld:type('pEQ '), from:'null'() }", enabled], 'core', 'setd', &savedPSN);
776 ITDebugLog(@"Done setting equalizer enabled to %i.", enabled);
780 - (NSArray *)eqPresets
783 SInt32 numPresets = [ITSendAEWithString(@"kocl:type('cEQP'), '----':(), &subj:()", 'core', 'cnte', &savedPSN) int32Value];
784 NSMutableArray *presets = [[NSMutableArray alloc] initWithCapacity:numPresets];
785 ITDebugLog(@"Getting EQ presets");
786 for (i = 1; i <= numPresets; i++) {
787 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];
789 ITDebugLog(@"Adding preset %@", theObj);
790 [presets addObject:theObj];
793 ITDebugLog(@"Done getting EQ presets");
794 return [presets autorelease];
797 - (int)currentEQPresetIndex
800 ITDebugLog(@"Getting current EQ preset index.");
801 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];
802 ITDebugLog(@"Getting current EQ preset index done.");
808 ITDebugLog(@"Getting volume.");
809 ITDebugLog(@"Getting volume done.");
810 return (float)[ITSendAEWithKey('pVol', 'core', 'getd', &savedPSN) int32Value] / 100;
813 - (BOOL)setVolume:(float)volume
815 ITDebugLog(@"Setting volume to %f.", volume);
816 ITSendAEWithString([NSString stringWithFormat:@"data:long(%lu), '----':obj { form:'prop', want:type('prop'), seld:type('pVol'), from:'null'() }", (long)(volume * 100)], 'core', 'setd', &savedPSN);
817 ITDebugLog(@"Setting volume to %f done.", volume);
821 - (BOOL)shuffleEnabled
824 ITDebugLog(@"Getting shuffle enabled status.");
825 if (![self isPlaying]) {
826 ITDebugLog(@"No current playlist, getting shuffle status from visible playlist.");
827 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];
829 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];
831 ITDebugLog(@"Getting shuffle enabled status done.");
832 return (result != 0);
835 - (BOOL)setShuffleEnabled:(BOOL)enabled
837 ITDebugLog(@"Set shuffle enabled to %i", enabled);
838 if (![self isPlaying]) {
839 ITDebugLog(@"No current playlist, setting shuffle status on visible playlist.");
840 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);
842 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);
844 ITDebugLog(@"Set shuffle enabled to %i done", enabled);
848 - (ITMTRemotePlayerRepeatMode)repeatMode
850 FourCharCode m00f = 0;
852 ITDebugLog(@"Getting repeat mode.");
853 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];
856 ITDebugLog(@"No current playlist, getting repeat mode from visible playlist.");
857 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];
864 ITDebugLog(@"Repeat off");
865 result = ITMTRemotePlayerRepeatOff;
868 ITDebugLog(@"Repeat one");
869 result = ITMTRemotePlayerRepeatOne;
872 ITDebugLog(@"Repeat all");
873 result = ITMTRemotePlayerRepeatAll;
876 ITDebugLog(@"Getting repeat mode done.");
880 - (BOOL)setRepeatMode:(ITMTRemotePlayerRepeatMode)repeatMode
883 ITDebugLog(@"Setting repeat mode to %i", repeatMode);
886 case ITMTRemotePlayerRepeatOne:
889 case ITMTRemotePlayerRepeatAll:
892 case ITMTRemotePlayerRepeatOff:
897 if (![self isPlaying]) {
898 ITDebugLog(@"No current playlist, setting repeat mode on visible playlist.");
899 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);
901 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);
903 ITDebugLog(@"Setting repeat mode to %c done", m00f);
910 ITSendAE('hook', 'Play', &savedPSN);
911 ITDebugLog(@"Play done");
917 ITDebugLog(@"Pause");
918 ITSendAE('hook', 'Paus', &savedPSN);
919 ITDebugLog(@"Pause done");
925 ITDebugLog(@"Go to next track");
926 ITSendAE('hook', 'Next', &savedPSN);
927 ITDebugLog(@"Go to next track done");
931 - (BOOL)goToPreviousSong
933 ITDebugLog(@"Go to previous track");
934 ITSendAE('hook', 'Back', &savedPSN);
935 ITDebugLog(@"Go to previous track done");
941 ITDebugLog(@"Fast forward action");
942 ITSendAE('hook', 'Fast', &savedPSN);
943 ITDebugLog(@"Fast forward action done");
949 ITDebugLog(@"Rewind action");
950 ITSendAE('hook', 'Rwnd', &savedPSN);
951 ITDebugLog(@"Rewind action done");
955 - (BOOL)switchToPlaylistAtIndex:(int)index
957 ITDebugLog(@"Switching to playlist at index %i", index);
958 ITSendAEWithString([NSString stringWithFormat:@"'----':obj { form:'indx', want:type('cPly'), seld:long(%lu), from:() }", index], 'hook', 'Play', &savedPSN);
959 ITDebugLog(@"Done switching to playlist at index %i", index);
963 - (BOOL)switchToPlaylistAtIndex:(int)index ofSourceAtIndex:(int)index2
965 ITDebugLog(@"Switching to playlist at index %i of source %i", index, index2);
966 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);
967 ITDebugLog(@"Done switching to playlist at index %i of source %i", index, index2);
971 - (BOOL)switchToSongAtIndex:(int)index
973 ITDebugLog(@"Switching to track at index %i", index);
974 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);
975 ITDebugLog(@"Done switching to track at index %i", index);
979 - (BOOL)switchToEQAtIndex:(int)index
981 ITDebugLog(@"Switching to EQ preset at index %i", index);
982 // index should count from 0, but itunes counts from 1, so let's add 1.
983 [self setEqualizerEnabled:YES];
984 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);
985 ITDebugLog(@"Done switching to EQ preset at index %i", index);
989 - (BOOL)makePlaylistWithTerm:(NSString *)term ofType:(int)type
993 //Get fixed indexing status
994 BOOL fixed = [ITSendAEWithString(@"'----':obj { form:'prop', want:type('prop'), seld:type('pFix'), from:'null'() }", 'core', 'getd', &savedPSN) booleanValue];
996 //Enabled fixed indexing
997 ITSendAEWithString(@"data:long(1), '----':obj { form:'prop', want:type('prop'), seld:type('pFix'), from:'null'() }", 'core', 'setd', &savedPSN);
999 //Search for the term
1000 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);
1002 //If MenuTunes playlist exists
1003 if ([ITSendAEWithString(@"'----':obj { form:'name', want:type('cPly'), seld:\"MenuTunes\", from:'null'() }", 'core', 'doex', &savedPSN) booleanValue]) {
1004 //Clear old MenuTunes playlist
1005 int numSongs = [ITSendAEWithString(@"kocl:type('cTrk'), '----':obj { form:'name', want:type('cPly'), seld:\"MenuTunes\", from:'null'() }", 'core', 'cnte', &savedPSN) int32Value];
1006 for (i = 1; i <= numSongs; i++) {
1007 ITSendAEWithString(@"'----':obj { form:'indx', want:type('cTrk'), seld:long(1), from:obj { form:'name', want:type('cPly'), seld:\"MenuTunes\", from:'null'() } }", 'core', 'delo', &savedPSN);
1010 //Create MenuTunes playlist
1011 ITSendAEWithString(@"prdt:{ pnam:\"MenuTunes\" }, kocl:type('cPly'), &subj:()", 'core', 'crel', &savedPSN);
1014 //Duplicate search results to playlist
1015 for (i = 1; i <= [searchResults numberOfItems]; i++) {
1016 //NSLog(@"%@", ITSendAEWithStringAndParameter(@"'----':obj { form:'prop', want:type('prop'), seld:prop('pnam'), from:aevt(@) }", *[[searchResults descriptorAtIndex:i] aeDesc], 'core', 'getd', &savedPSN));
1018 ITSendAEWithStringAndObject(@"insh:obj { form:'name', want:type('cPly'), seld:\"MenuTunes\", from:'null'() }", [[searchResults descriptorAtIndex:i] aeDesc], 'core', 'clon', &savedPSN);
1020 //Reset fixed indexing
1021 ITSendAEWithString([NSString stringWithFormat:@"data:long(%i), '----':obj { form:'prop', want:type('prop'), seld:type('pFix'), from:'null'() }", fixed], 'core', 'setd', &savedPSN);
1023 //Play MenuTunes playlist
1024 ITSendAEWithString(@"'----':obj { form:'name', want:type('cPly'), seld:\"MenuTunes\", from:'null'() }", 'hook', 'Play', &savedPSN);
1031 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');
1034 - (void)notificationHandler:(NSNotification *)note
1036 ITDebugLog(@"Received notification: %@", note);
1037 [[NSNotificationCenter defaultCenter] postNotificationName:@"ITMTTrackChanged" object:self userInfo:[note userInfo]];
1038 ITDebugLog(@"Handled notification.");
1041 - (ProcessSerialNumber)iTunesPSN
1043 /*NSArray *apps = [[NSWorkspace sharedWorkspace] launchedApplications];
1044 ProcessSerialNumber number;
1046 int count = [apps count];
1048 number.highLongOfPSN = kNoProcess;
1050 for (i = 0; i < count; i++)
1052 NSDictionary *curApp = [apps objectAtIndex:i];
1054 if ([[curApp objectForKey:@"NSApplicationName"] isEqualToString:@"iTunes"])
1056 number.highLongOfPSN = [[curApp objectForKey:
1057 @"NSApplicationProcessSerialNumberHigh"] intValue];
1058 number.lowLongOfPSN = [[curApp objectForKey:
1059 @"NSApplicationProcessSerialNumberLow"] intValue];
1063 ProcessSerialNumber number;
1064 number.highLongOfPSN = kNoProcess;
1065 number.lowLongOfPSN = 0;
1066 ITDebugLog(@"Getting iTunes' PSN.");
1067 while ( (GetNextProcess(&number) == noErr) )
1070 if ( (CopyProcessName(&number, &name) == noErr) )
1072 if ([(NSString *)name isEqualToString:@"iTunes"])
1074 ITDebugLog(@"iTunes' highLPongOfPSN: %lu.", number.highLongOfPSN);
1075 ITDebugLog(@"iTunes' lowLongOfPSN: %lu.", number.lowLongOfPSN);
1076 ITDebugLog(@"Done getting iTunes' PSN.");
1077 [(NSString *)name release];
1080 [(NSString *)name release];
1083 ITDebugLog(@"Failed getting iTunes' PSN.");
1087 - (NSString*)formatTimeInSeconds:(long)seconds {
1088 long final = seconds;
1089 NSString *finalString;
1092 finalString = [NSString stringWithFormat:@"%i:%@:%@",(final / 3600),[self zeroSixty:(int)((final % 3600) / 60)],[self zeroSixty:(int)((final % 3600) % 60)]];
1094 finalString = [NSString stringWithFormat:@"%i:%@",(final / 60),[self zeroSixty:(int)(final % 60)]];
1097 finalString = [NSString stringWithFormat:@"0:%@",[self zeroSixty:(int)final]];
1101 - (NSString*)zeroSixty:(int)seconds {
1102 if ( (seconds < 10) && (seconds > 0) ) {
1103 return [NSString stringWithFormat:@"0%i",seconds];
1104 } else if ( (seconds == 0) ) {
1105 return [NSString stringWithFormat:@"00"];
1107 return [NSString stringWithFormat:@"%i",seconds];