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 - (int)currentSongPlayed
676 ITDebugLog(@"Getting current song played time.");
677 final = [ITSendAEWithKey('pPos', 'core', 'getd', &savedPSN) int32Value];
678 ITDebugLog(@"Getting current song played time done.");
682 - (int)currentSongDuration
685 ITDebugLog(@"Getting current song duration.");
686 temp1 = [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];
687 ITDebugLog(@"Getting current song duration done.");
691 - (NSString *)currentSongRemaining
693 SInt32 duration, current, final;
694 NSString *finalString;
696 ITDebugLog(@"Getting current song remaining time.");
698 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];
699 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];
700 final = duration - current;
701 finalString = [self formatTimeInSeconds:final];
703 if ( [self currentPlaylistClass] == ITMTRemotePlayerRadioPlaylist ) { finalString = nil; }
705 ITDebugLog(@"Getting current song remaining time done.");
710 - (NSString *)currentSongElapsed
713 NSString *finalString;
715 ITDebugLog(@"Getting current song elapsed time.");
716 final = (long)[ITSendAEWithKey('pPos', 'core', 'getd', &savedPSN) int32Value];
717 finalString = [self formatTimeInSeconds:final];
718 ITDebugLog(@"Getting current song elapsed time done.");
722 - (NSImage *)currentSongAlbumArt
724 ITDebugLog(@"Getting current song album art.");
725 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;
726 ITDebugLog(@"Getting current song album art done.");
728 return [[[NSImage alloc] initWithData:data] autorelease];
734 - (int)currentSongPlayCount
737 ITDebugLog(@"Getting current song play count.");
738 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];
739 ITDebugLog(@"Getting current song play count done.");
743 - (float)currentSongRating
746 ITDebugLog(@"Getting current song rating.");
747 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);
748 ITDebugLog(@"Getting current song rating done.");
752 - (BOOL)setCurrentSongRating:(float)rating
754 ITDebugLog(@"Setting current song rating to %f.", rating);
755 if ( [self currentPlaylistClass] == ITMTRemotePlayerRadioPlaylist ) { return NO; }
756 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);
757 ITDebugLog(@"Setting current song rating to %f done.", rating);
761 - (BOOL)currentSongShufflable
764 ITDebugLog(@"Getting current song shufflable status.");
765 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];
766 ITDebugLog(@"Getting current song shufflable status done.");
770 - (BOOL)setCurrentSongShufflable:(BOOL)shufflable
772 ITDebugLog(@"Setting current song shufflable status to %i.", shufflable);
773 if ([self currentPlaylistClass] == ITMTRemotePlayerRadioPlaylist) {
774 ITDebugLog(@"Not a valid track to set status to, returning.");
777 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);
778 ITDebugLog(@"Setting current song shufflable status to %i done.", shufflable);
782 - (BOOL)equalizerEnabled
784 ITDebugLog(@"Getting equalizer enabled status.");
785 int thingy = (int)[ITSendAEWithKey('pEQ ', 'core', 'getd', &savedPSN) int32Value];
786 ITDebugLog(@"Done getting equalizer enabled status.");
787 return (thingy != 0) ? YES : NO;
790 - (BOOL)setEqualizerEnabled:(BOOL)enabled
792 ITDebugLog(@"Setting equalizer enabled to %i.", enabled);
793 ITSendAEWithString([NSString stringWithFormat:@"data:long(%lu), '----':obj { form:'prop', want:type('prop'), seld:type('pEQ '), from:'null'() }", enabled], 'core', 'setd', &savedPSN);
794 ITDebugLog(@"Done setting equalizer enabled to %i.", enabled);
798 - (NSArray *)eqPresets
801 SInt32 numPresets = [ITSendAEWithString(@"kocl:type('cEQP'), '----':(), &subj:()", 'core', 'cnte', &savedPSN) int32Value];
802 NSMutableArray *presets = [[NSMutableArray alloc] initWithCapacity:numPresets];
803 ITDebugLog(@"Getting EQ presets");
804 for (i = 1; i <= numPresets; i++) {
805 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];
807 ITDebugLog(@"Adding preset %@", theObj);
808 [presets addObject:theObj];
811 ITDebugLog(@"Done getting EQ presets");
812 return [presets autorelease];
815 - (int)currentEQPresetIndex
818 ITDebugLog(@"Getting current EQ preset index.");
819 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];
820 ITDebugLog(@"Getting current EQ preset index done.");
826 ITDebugLog(@"Getting volume.");
827 ITDebugLog(@"Getting volume done.");
828 return (float)[ITSendAEWithKey('pVol', 'core', 'getd', &savedPSN) int32Value] / 100;
831 - (BOOL)setVolume:(float)volume
833 ITDebugLog(@"Setting volume to %f.", volume);
834 ITSendAEWithString([NSString stringWithFormat:@"data:long(%lu), '----':obj { form:'prop', want:type('prop'), seld:type('pVol'), from:'null'() }", (long)(volume * 100)], 'core', 'setd', &savedPSN);
835 ITDebugLog(@"Setting volume to %f done.", volume);
839 - (BOOL)shuffleEnabled
842 ITDebugLog(@"Getting shuffle enabled status.");
843 if (![self isPlaying]) {
844 ITDebugLog(@"No current playlist, getting shuffle status from visible playlist.");
845 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];
847 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];
849 ITDebugLog(@"Getting shuffle enabled status done.");
850 return (result != 0);
853 - (BOOL)setShuffleEnabled:(BOOL)enabled
855 ITDebugLog(@"Set shuffle enabled to %i", enabled);
856 if (![self isPlaying]) {
857 ITDebugLog(@"No current playlist, setting shuffle status on visible playlist.");
858 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);
860 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);
862 ITDebugLog(@"Set shuffle enabled to %i done", enabled);
866 - (ITMTRemotePlayerRepeatMode)repeatMode
868 FourCharCode m00f = 0;
870 ITDebugLog(@"Getting repeat mode.");
871 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];
874 ITDebugLog(@"No current playlist, getting repeat mode from visible playlist.");
875 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];
882 ITDebugLog(@"Repeat off");
883 result = ITMTRemotePlayerRepeatOff;
886 ITDebugLog(@"Repeat one");
887 result = ITMTRemotePlayerRepeatOne;
890 ITDebugLog(@"Repeat all");
891 result = ITMTRemotePlayerRepeatAll;
894 ITDebugLog(@"Getting repeat mode done.");
898 - (BOOL)setRepeatMode:(ITMTRemotePlayerRepeatMode)repeatMode
901 ITDebugLog(@"Setting repeat mode to %i", repeatMode);
904 case ITMTRemotePlayerRepeatOne:
907 case ITMTRemotePlayerRepeatAll:
910 case ITMTRemotePlayerRepeatOff:
915 if (![self isPlaying]) {
916 ITDebugLog(@"No current playlist, setting repeat mode on visible playlist.");
917 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);
919 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);
921 ITDebugLog(@"Setting repeat mode to %c done", m00f);
928 ITSendAE('hook', 'Play', &savedPSN);
929 ITDebugLog(@"Play done");
935 ITDebugLog(@"Pause");
936 ITSendAE('hook', 'Paus', &savedPSN);
937 ITDebugLog(@"Pause done");
943 ITDebugLog(@"Go to next track");
944 ITSendAE('hook', 'Next', &savedPSN);
945 ITDebugLog(@"Go to next track done");
949 - (BOOL)goToPreviousSong
951 ITDebugLog(@"Go to previous track");
952 ITSendAE('hook', 'Back', &savedPSN);
953 ITDebugLog(@"Go to previous track done");
959 ITDebugLog(@"Fast forward action");
960 ITSendAE('hook', 'Fast', &savedPSN);
961 ITDebugLog(@"Fast forward action done");
967 ITDebugLog(@"Rewind action");
968 ITSendAE('hook', 'Rwnd', &savedPSN);
969 ITDebugLog(@"Rewind action done");
973 - (BOOL)switchToPlaylistAtIndex:(int)index
975 ITDebugLog(@"Switching to playlist at index %i", index);
976 ITSendAEWithString([NSString stringWithFormat:@"'----':obj { form:'indx', want:type('cPly'), seld:long(%lu), from:() }", index], 'hook', 'Play', &savedPSN);
977 ITDebugLog(@"Done switching to playlist at index %i", index);
981 - (BOOL)switchToPlaylistAtIndex:(int)index ofSourceAtIndex:(int)index2
983 ITDebugLog(@"Switching to playlist at index %i of source %i", index, index2);
984 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);
985 ITDebugLog(@"Done switching to playlist at index %i of source %i", index, index2);
989 - (BOOL)switchToSongAtIndex:(int)index
991 ITDebugLog(@"Switching to track at index %i", index);
992 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);
993 ITDebugLog(@"Done switching to track at index %i", index);
997 - (BOOL)switchToEQAtIndex:(int)index
999 ITDebugLog(@"Switching to EQ preset at index %i", index);
1000 // index should count from 0, but itunes counts from 1, so let's add 1.
1001 [self setEqualizerEnabled:YES];
1002 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);
1003 ITDebugLog(@"Done switching to EQ preset at index %i", index);
1007 - (BOOL)makePlaylistWithTerm:(NSString *)term ofType:(int)type
1011 //Get fixed indexing status
1012 BOOL fixed = [ITSendAEWithString(@"'----':obj { form:'prop', want:type('prop'), seld:type('pFix'), from:'null'() }", 'core', 'getd', &savedPSN) booleanValue];
1014 //Enabled fixed indexing
1015 ITSendAEWithString(@"data:long(1), '----':obj { form:'prop', want:type('prop'), seld:type('pFix'), from:'null'() }", 'core', 'setd', &savedPSN);
1017 //Search for the term
1018 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);
1020 //If MenuTunes playlist exists
1021 if ([ITSendAEWithString(@"'----':obj { form:'name', want:type('cPly'), seld:\"MenuTunes\", from:'null'() }", 'core', 'doex', &savedPSN) booleanValue]) {
1022 //Clear old MenuTunes playlist
1023 int numSongs = [ITSendAEWithString(@"kocl:type('cTrk'), '----':obj { form:'name', want:type('cPly'), seld:\"MenuTunes\", from:'null'() }", 'core', 'cnte', &savedPSN) int32Value];
1024 for (i = 1; i <= numSongs; i++) {
1025 ITSendAEWithString(@"'----':obj { form:'indx', want:type('cTrk'), seld:long(1), from:obj { form:'name', want:type('cPly'), seld:\"MenuTunes\", from:'null'() } }", 'core', 'delo', &savedPSN);
1028 //Create MenuTunes playlist
1029 ITSendAEWithString(@"prdt:{ pnam:\"MenuTunes\" }, kocl:type('cPly'), &subj:()", 'core', 'crel', &savedPSN);
1032 //Duplicate search results to playlist
1033 for (i = 1; i <= [searchResults numberOfItems]; i++) {
1034 //NSLog(@"%@", ITSendAEWithStringAndParameter(@"'----':obj { form:'prop', want:type('prop'), seld:prop('pnam'), from:aevt(@) }", *[[searchResults descriptorAtIndex:i] aeDesc], 'core', 'getd', &savedPSN));
1036 ITSendAEWithStringAndObject(@"insh:obj { form:'name', want:type('cPly'), seld:\"MenuTunes\", from:'null'() }", [[searchResults descriptorAtIndex:i] aeDesc], 'core', 'clon', &savedPSN);
1038 //Reset fixed indexing
1039 ITSendAEWithString([NSString stringWithFormat:@"data:long(%i), '----':obj { form:'prop', want:type('prop'), seld:type('pFix'), from:'null'() }", fixed], 'core', 'setd', &savedPSN);
1041 //Play MenuTunes playlist
1042 ITSendAEWithString(@"'----':obj { form:'name', want:type('cPly'), seld:\"MenuTunes\", from:'null'() }", 'hook', 'Play', &savedPSN);
1049 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');
1052 - (void)notificationHandler:(NSNotification *)note
1054 ITDebugLog(@"Received notification: %@", note);
1055 [[NSNotificationCenter defaultCenter] postNotificationName:@"ITMTTrackChanged" object:self userInfo:[note userInfo]];
1056 ITDebugLog(@"Handled notification.");
1059 - (ProcessSerialNumber)iTunesPSN
1061 /*NSArray *apps = [[NSWorkspace sharedWorkspace] launchedApplications];
1062 ProcessSerialNumber number;
1064 int count = [apps count];
1066 number.highLongOfPSN = kNoProcess;
1068 for (i = 0; i < count; i++)
1070 NSDictionary *curApp = [apps objectAtIndex:i];
1072 if ([[curApp objectForKey:@"NSApplicationName"] isEqualToString:@"iTunes"])
1074 number.highLongOfPSN = [[curApp objectForKey:
1075 @"NSApplicationProcessSerialNumberHigh"] intValue];
1076 number.lowLongOfPSN = [[curApp objectForKey:
1077 @"NSApplicationProcessSerialNumberLow"] intValue];
1081 ProcessSerialNumber number;
1082 number.highLongOfPSN = kNoProcess;
1083 number.lowLongOfPSN = 0;
1084 ITDebugLog(@"Getting iTunes' PSN.");
1085 while ( (GetNextProcess(&number) == noErr) )
1088 if ( (CopyProcessName(&number, &name) == noErr) )
1090 if ([(NSString *)name isEqualToString:@"iTunes"])
1092 ITDebugLog(@"iTunes' highLPongOfPSN: %lu.", number.highLongOfPSN);
1093 ITDebugLog(@"iTunes' lowLongOfPSN: %lu.", number.lowLongOfPSN);
1094 ITDebugLog(@"Done getting iTunes' PSN.");
1095 [(NSString *)name release];
1098 [(NSString *)name release];
1101 ITDebugLog(@"Failed getting iTunes' PSN.");
1105 - (NSString*)formatTimeInSeconds:(long)seconds {
1106 long final = seconds;
1107 NSString *finalString;
1110 finalString = [NSString stringWithFormat:@"%i:%@:%@",(final / 3600),[self zeroSixty:(int)((final % 3600) / 60)],[self zeroSixty:(int)((final % 3600) % 60)]];
1112 finalString = [NSString stringWithFormat:@"%i:%@",(final / 60),[self zeroSixty:(int)(final % 60)]];
1115 finalString = [NSString stringWithFormat:@"0:%@",[self zeroSixty:(int)final]];
1119 - (NSString*)zeroSixty:(int)seconds {
1120 if ( (seconds < 10) && (seconds > 0) ) {
1121 return [NSString stringWithFormat:@"0%i",seconds];
1122 } else if ( (seconds == 0) ) {
1123 return [NSString stringWithFormat:@"00"];
1125 return [NSString stringWithFormat:@"%i",seconds];