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)currentSongDuration
676 ITDebugLog(@"Getting current song duration.");
677 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];
678 ITDebugLog(@"Getting current song duration done.");
682 - (NSString *)currentSongRemaining
684 SInt32 duration, current, final;
685 NSString *finalString;
687 ITDebugLog(@"Getting current song remaining time.");
689 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];
690 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];
691 final = duration - current;
692 finalString = [self formatTimeInSeconds:final];
694 if ( [self currentPlaylistClass] == ITMTRemotePlayerRadioPlaylist ) { finalString = nil; }
696 ITDebugLog(@"Getting current song remaining time done.");
701 - (NSString *)currentSongElapsed
704 NSString *finalString;
706 ITDebugLog(@"Getting current song elapsed time.");
707 final = (long)[ITSendAEWithKey('pPos', 'core', 'getd', &savedPSN) int32Value];
708 finalString = [self formatTimeInSeconds:final];
709 ITDebugLog(@"Getting current song elapsed time done.");
713 - (NSImage *)currentSongAlbumArt
715 ITDebugLog(@"Getting current song album art.");
716 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;
717 ITDebugLog(@"Getting current song album art done.");
719 return [[[NSImage alloc] initWithData:data] autorelease];
725 - (int)currentSongPlayCount
728 ITDebugLog(@"Getting current song play count.");
729 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];
730 ITDebugLog(@"Getting current song play count done.");
734 - (float)currentSongRating
737 ITDebugLog(@"Getting current song rating.");
738 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);
739 ITDebugLog(@"Getting current song rating done.");
743 - (BOOL)setCurrentSongRating:(float)rating
745 ITDebugLog(@"Setting current song rating to %f.", rating);
746 if ( [self currentPlaylistClass] == ITMTRemotePlayerRadioPlaylist ) { return NO; }
747 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);
748 ITDebugLog(@"Setting current song rating to %f done.", rating);
752 - (BOOL)currentSongShufflable
755 ITDebugLog(@"Getting current song shufflable status.");
756 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];
757 ITDebugLog(@"Getting current song shufflable status done.");
761 - (BOOL)setCurrentSongShufflable:(BOOL)shufflable
763 ITDebugLog(@"Setting current song shufflable status to %i.", shufflable);
764 if ([self currentPlaylistClass] == ITMTRemotePlayerRadioPlaylist) {
765 ITDebugLog(@"Not a valid track to set status to, returning.");
768 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);
769 ITDebugLog(@"Setting current song shufflable status to %i done.", shufflable);
773 - (BOOL)equalizerEnabled
775 ITDebugLog(@"Getting equalizer enabled status.");
776 int thingy = (int)[ITSendAEWithKey('pEQ ', 'core', 'getd', &savedPSN) int32Value];
777 ITDebugLog(@"Done getting equalizer enabled status.");
778 return (thingy != 0) ? YES : NO;
781 - (BOOL)setEqualizerEnabled:(BOOL)enabled
783 ITDebugLog(@"Setting equalizer enabled to %i.", enabled);
784 ITSendAEWithString([NSString stringWithFormat:@"data:long(%lu), '----':obj { form:'prop', want:type('prop'), seld:type('pEQ '), from:'null'() }", enabled], 'core', 'setd', &savedPSN);
785 ITDebugLog(@"Done setting equalizer enabled to %i.", enabled);
789 - (NSArray *)eqPresets
792 SInt32 numPresets = [ITSendAEWithString(@"kocl:type('cEQP'), '----':(), &subj:()", 'core', 'cnte', &savedPSN) int32Value];
793 NSMutableArray *presets = [[NSMutableArray alloc] initWithCapacity:numPresets];
794 ITDebugLog(@"Getting EQ presets");
795 for (i = 1; i <= numPresets; i++) {
796 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];
798 ITDebugLog(@"Adding preset %@", theObj);
799 [presets addObject:theObj];
802 ITDebugLog(@"Done getting EQ presets");
803 return [presets autorelease];
806 - (int)currentEQPresetIndex
809 ITDebugLog(@"Getting current EQ preset index.");
810 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];
811 ITDebugLog(@"Getting current EQ preset index done.");
817 ITDebugLog(@"Getting volume.");
818 ITDebugLog(@"Getting volume done.");
819 return (float)[ITSendAEWithKey('pVol', 'core', 'getd', &savedPSN) int32Value] / 100;
822 - (BOOL)setVolume:(float)volume
824 ITDebugLog(@"Setting volume to %f.", volume);
825 ITSendAEWithString([NSString stringWithFormat:@"data:long(%lu), '----':obj { form:'prop', want:type('prop'), seld:type('pVol'), from:'null'() }", (long)(volume * 100)], 'core', 'setd', &savedPSN);
826 ITDebugLog(@"Setting volume to %f done.", volume);
830 - (BOOL)shuffleEnabled
833 ITDebugLog(@"Getting shuffle enabled status.");
834 if (![self isPlaying]) {
835 ITDebugLog(@"No current playlist, getting shuffle status from visible playlist.");
836 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];
838 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];
840 ITDebugLog(@"Getting shuffle enabled status done.");
841 return (result != 0);
844 - (BOOL)setShuffleEnabled:(BOOL)enabled
846 ITDebugLog(@"Set shuffle enabled to %i", enabled);
847 if (![self isPlaying]) {
848 ITDebugLog(@"No current playlist, setting shuffle status on visible playlist.");
849 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);
851 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);
853 ITDebugLog(@"Set shuffle enabled to %i done", enabled);
857 - (ITMTRemotePlayerRepeatMode)repeatMode
859 FourCharCode m00f = 0;
861 ITDebugLog(@"Getting repeat mode.");
862 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];
865 ITDebugLog(@"No current playlist, getting repeat mode from visible playlist.");
866 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];
873 ITDebugLog(@"Repeat off");
874 result = ITMTRemotePlayerRepeatOff;
877 ITDebugLog(@"Repeat one");
878 result = ITMTRemotePlayerRepeatOne;
881 ITDebugLog(@"Repeat all");
882 result = ITMTRemotePlayerRepeatAll;
885 ITDebugLog(@"Getting repeat mode done.");
889 - (BOOL)setRepeatMode:(ITMTRemotePlayerRepeatMode)repeatMode
892 ITDebugLog(@"Setting repeat mode to %i", repeatMode);
895 case ITMTRemotePlayerRepeatOne:
898 case ITMTRemotePlayerRepeatAll:
901 case ITMTRemotePlayerRepeatOff:
906 if (![self isPlaying]) {
907 ITDebugLog(@"No current playlist, setting repeat mode on visible playlist.");
908 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);
910 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);
912 ITDebugLog(@"Setting repeat mode to %c done", m00f);
919 ITSendAE('hook', 'Play', &savedPSN);
920 ITDebugLog(@"Play done");
926 ITDebugLog(@"Pause");
927 ITSendAE('hook', 'Paus', &savedPSN);
928 ITDebugLog(@"Pause done");
934 ITDebugLog(@"Go to next track");
935 ITSendAE('hook', 'Next', &savedPSN);
936 ITDebugLog(@"Go to next track done");
940 - (BOOL)goToPreviousSong
942 ITDebugLog(@"Go to previous track");
943 ITSendAE('hook', 'Back', &savedPSN);
944 ITDebugLog(@"Go to previous track done");
950 ITDebugLog(@"Fast forward action");
951 ITSendAE('hook', 'Fast', &savedPSN);
952 ITDebugLog(@"Fast forward action done");
958 ITDebugLog(@"Rewind action");
959 ITSendAE('hook', 'Rwnd', &savedPSN);
960 ITDebugLog(@"Rewind action done");
964 - (BOOL)switchToPlaylistAtIndex:(int)index
966 ITDebugLog(@"Switching to playlist at index %i", index);
967 ITSendAEWithString([NSString stringWithFormat:@"'----':obj { form:'indx', want:type('cPly'), seld:long(%lu), from:() }", index], 'hook', 'Play', &savedPSN);
968 ITDebugLog(@"Done switching to playlist at index %i", index);
972 - (BOOL)switchToPlaylistAtIndex:(int)index ofSourceAtIndex:(int)index2
974 ITDebugLog(@"Switching to playlist at index %i of source %i", index, index2);
975 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);
976 ITDebugLog(@"Done switching to playlist at index %i of source %i", index, index2);
980 - (BOOL)switchToSongAtIndex:(int)index
982 ITDebugLog(@"Switching to track at index %i", index);
983 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);
984 ITDebugLog(@"Done switching to track at index %i", index);
988 - (BOOL)switchToEQAtIndex:(int)index
990 ITDebugLog(@"Switching to EQ preset at index %i", index);
991 // index should count from 0, but itunes counts from 1, so let's add 1.
992 [self setEqualizerEnabled:YES];
993 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);
994 ITDebugLog(@"Done switching to EQ preset at index %i", index);
998 - (BOOL)makePlaylistWithTerm:(NSString *)term ofType:(int)type
1002 //Get fixed indexing status
1003 BOOL fixed = [ITSendAEWithString(@"'----':obj { form:'prop', want:type('prop'), seld:type('pFix'), from:'null'() }", 'core', 'getd', &savedPSN) booleanValue];
1005 //Enabled fixed indexing
1006 ITSendAEWithString(@"data:long(1), '----':obj { form:'prop', want:type('prop'), seld:type('pFix'), from:'null'() }", 'core', 'setd', &savedPSN);
1008 //Search for the term
1009 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);
1011 //If MenuTunes playlist exists
1012 if ([ITSendAEWithString(@"'----':obj { form:'name', want:type('cPly'), seld:\"MenuTunes\", from:'null'() }", 'core', 'doex', &savedPSN) booleanValue]) {
1013 //Clear old MenuTunes playlist
1014 int numSongs = [ITSendAEWithString(@"kocl:type('cTrk'), '----':obj { form:'name', want:type('cPly'), seld:\"MenuTunes\", from:'null'() }", 'core', 'cnte', &savedPSN) int32Value];
1015 for (i = 1; i <= numSongs; i++) {
1016 ITSendAEWithString(@"'----':obj { form:'indx', want:type('cTrk'), seld:long(1), from:obj { form:'name', want:type('cPly'), seld:\"MenuTunes\", from:'null'() } }", 'core', 'delo', &savedPSN);
1019 //Create MenuTunes playlist
1020 ITSendAEWithString(@"prdt:{ pnam:\"MenuTunes\" }, kocl:type('cPly'), &subj:()", 'core', 'crel', &savedPSN);
1023 //Duplicate search results to playlist
1024 for (i = 1; i <= [searchResults numberOfItems]; i++) {
1025 //NSLog(@"%@", ITSendAEWithStringAndParameter(@"'----':obj { form:'prop', want:type('prop'), seld:prop('pnam'), from:aevt(@) }", *[[searchResults descriptorAtIndex:i] aeDesc], 'core', 'getd', &savedPSN));
1027 ITSendAEWithStringAndObject(@"insh:obj { form:'name', want:type('cPly'), seld:\"MenuTunes\", from:'null'() }", [[searchResults descriptorAtIndex:i] aeDesc], 'core', 'clon', &savedPSN);
1029 //Reset fixed indexing
1030 ITSendAEWithString([NSString stringWithFormat:@"data:long(%i), '----':obj { form:'prop', want:type('prop'), seld:type('pFix'), from:'null'() }", fixed], 'core', 'setd', &savedPSN);
1032 //Play MenuTunes playlist
1033 ITSendAEWithString(@"'----':obj { form:'name', want:type('cPly'), seld:\"MenuTunes\", from:'null'() }", 'hook', 'Play', &savedPSN);
1040 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');
1043 - (void)notificationHandler:(NSNotification *)note
1045 ITDebugLog(@"Received notification: %@", note);
1046 [[NSNotificationCenter defaultCenter] postNotificationName:@"ITMTTrackChanged" object:self userInfo:[note userInfo]];
1047 ITDebugLog(@"Handled notification.");
1050 - (ProcessSerialNumber)iTunesPSN
1052 /*NSArray *apps = [[NSWorkspace sharedWorkspace] launchedApplications];
1053 ProcessSerialNumber number;
1055 int count = [apps count];
1057 number.highLongOfPSN = kNoProcess;
1059 for (i = 0; i < count; i++)
1061 NSDictionary *curApp = [apps objectAtIndex:i];
1063 if ([[curApp objectForKey:@"NSApplicationName"] isEqualToString:@"iTunes"])
1065 number.highLongOfPSN = [[curApp objectForKey:
1066 @"NSApplicationProcessSerialNumberHigh"] intValue];
1067 number.lowLongOfPSN = [[curApp objectForKey:
1068 @"NSApplicationProcessSerialNumberLow"] intValue];
1072 ProcessSerialNumber number;
1073 number.highLongOfPSN = kNoProcess;
1074 number.lowLongOfPSN = 0;
1075 ITDebugLog(@"Getting iTunes' PSN.");
1076 while ( (GetNextProcess(&number) == noErr) )
1079 if ( (CopyProcessName(&number, &name) == noErr) )
1081 if ([(NSString *)name isEqualToString:@"iTunes"])
1083 ITDebugLog(@"iTunes' highLPongOfPSN: %lu.", number.highLongOfPSN);
1084 ITDebugLog(@"iTunes' lowLongOfPSN: %lu.", number.lowLongOfPSN);
1085 ITDebugLog(@"Done getting iTunes' PSN.");
1086 [(NSString *)name release];
1089 [(NSString *)name release];
1092 ITDebugLog(@"Failed getting iTunes' PSN.");
1096 - (NSString*)formatTimeInSeconds:(long)seconds {
1097 long final = seconds;
1098 NSString *finalString;
1101 finalString = [NSString stringWithFormat:@"%i:%@:%@",(final / 3600),[self zeroSixty:(int)((final % 3600) / 60)],[self zeroSixty:(int)((final % 3600) % 60)]];
1103 finalString = [NSString stringWithFormat:@"%i:%@",(final / 60),[self zeroSixty:(int)(final % 60)]];
1106 finalString = [NSString stringWithFormat:@"0:%@",[self zeroSixty:(int)final]];
1110 - (NSString*)zeroSixty:(int)seconds {
1111 if ( (seconds < 10) && (seconds > 0) ) {
1112 return [NSString stringWithFormat:@"0%i",seconds];
1113 } else if ( (seconds == 0) ) {
1114 return [NSString stringWithFormat:@"00"];
1116 return [NSString stringWithFormat:@"%i",seconds];