1 #import "iTunesRemote.h"
3 @implementation iTunesRemote
7 return [[[iTunesRemote alloc] init] autorelease];
10 - (NSString *)remoteTitle
12 return @"iTunes Remote";
15 - (NSString *)remoteInformation
17 return @"Default MenuTunes plugin to control iTunes, by iThink Software.";
20 - (NSImage *)remoteIcon
27 ITDebugLog(@"iTunesRemote begun");
28 savedPSN = [self iTunesPSN];
34 ITDebugLog(@"iTunesRemote halted");
38 - (NSString *)playerFullName
43 - (NSString *)playerSimpleName
48 - (NSDictionary *)capabilities
50 return [NSDictionary dictionaryWithObjectsAndKeys:
51 [NSNumber numberWithBool: YES], @"Remote",
52 [NSNumber numberWithBool: YES], @"Basic Track Control",
53 [NSNumber numberWithBool: YES], @"Track Information",
54 [NSNumber numberWithBool: YES], @"Track Navigation",
55 [NSNumber numberWithBool: YES], @"Upcoming Songs",
56 [NSNumber numberWithBool: YES], @"Playlists",
57 [NSNumber numberWithBool: YES], @"Volume",
58 [NSNumber numberWithBool: YES], @"Shuffle",
59 [NSNumber numberWithBool: YES], @"Repeat Modes",
60 [NSNumber numberWithBool: YES], @"Equalizer",
61 [NSNumber numberWithBool: YES], @"Track Rating",
65 - (BOOL)showPrimaryInterface
67 ITDebugLog(@"Showing player primary interface.");
69 if ([self playerRunningState] == ITMTRemotePlayerRunning) {
70 ITDebugLog(@"Showing player interface.");
71 //If not minimized and visible
72 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) &&
73 ([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) &&
74 [[[[NSWorkspace sharedWorkspace] activeApplication] objectForKey:@"NSApplicationName"] isEqualToString:@"iTunes"] ) {
75 //set minimized of browser window 1 to true
76 ITSendAEWithString(@"data:long(1), '----':obj { form:'prop', want:type('prop'), seld:type('pMin'), from:obj { form:'indx', want:type('cBrW'), seld:1, from:'null'() } }", 'core', 'setd', &savedPSN);
78 //set minimized of browser window 1 to false
79 ITSendAEWithString(@"data:long(0), '----':obj { form:'prop', want:type('prop'), seld:type('pMin'), from:obj { form:'indx', want:type('cBrW'), seld:1, from:'null'() } }", 'core', 'setd', &savedPSN);
81 //set visible of browser window 1 to true
82 ITSendAEWithString(@"data:long(1), '----':obj { form:'prop', want:type('prop'), seld:type('pvis'), from:obj { form:'indx', want:type('cBrW'), seld:1, from:'null'() } }", 'core', 'setd', &savedPSN);
84 ITSendAEWithString(@"data:long(1), '----':obj { form:'prop', want:type('prop'), seld:type('pisf'), from:'null'() }", 'core', 'setd', &savedPSN);
85 ITDebugLog(@"Done showing player primary interface.");
89 ITDebugLog(@"Launching player.");
90 if ( (path = [[NSUserDefaults standardUserDefaults] stringForKey:@"CustomPlayerPath"]) ) {
92 path = [self playerFullName];
94 if (![[NSWorkspace sharedWorkspace] launchApplication:path]) {
95 ITDebugLog(@"Error Launching Player");
102 - (ITMTRemotePlayerRunningState)playerRunningState
104 NSArray *apps = [[NSWorkspace sharedWorkspace] launchedApplications];
106 int count = [apps count];
108 for (i = 0; i < count; i++) {
109 if ([[[apps objectAtIndex:i] objectForKey:@"NSApplicationName"] isEqualToString:@"iTunes"]) {
110 ITDebugLog(@"Player running state: 1");
111 return ITMTRemotePlayerRunning;
114 ITDebugLog(@"Player running state: 0");
115 return ITMTRemotePlayerNotRunning;
118 - (ITMTRemotePlayerPlayingState)playerPlayingState
122 ITDebugLog(@"Getting player playing state");
123 result = [ITSendAEWithString(@"'----':obj { form:'prop', want:type('prop'), seld:type('pPlS'), from:'null'() }", 'core', 'getd', &savedPSN) int32Value];
127 ITDebugLog(@"Getting player playing state done. Player state: Playing");
128 return ITMTRemotePlayerPlaying;
130 ITDebugLog(@"Getting player playing state done. Player state: Paused");
131 return ITMTRemotePlayerPaused;
133 ITDebugLog(@"Getting player playing state done. Player state: Rewinding");
134 return ITMTRemotePlayerRewinding;
136 ITDebugLog(@"Getting player playing state done. Player state: Forwarding");
137 return ITMTRemotePlayerForwarding;
140 ITDebugLog(@"Getting player playing state done. Player state: Stopped");
141 return ITMTRemotePlayerStopped;
143 ITDebugLog(@"Getting player playing state done. Player state: Stopped");
144 return ITMTRemotePlayerStopped;
147 /*- (NSArray *)playlists
150 const signed long numPlaylists = [[ITAppleEventCenter sharedCenter] sendAEWithSendStringForNumber:@"kocl:type('cPly'), '----':()" eventClass:@"core" eventID:@"cnte" appPSN:savedPSN];
151 NSMutableArray *playlists = [[NSMutableArray alloc] initWithCapacity:numPlaylists];
153 for (i = 1; i <= numPlaylists; i++) {
155 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];
156 NSString *theObj = [[ITAppleEventCenter sharedCenter] sendAEWithSendString:sendStr eventClass:@"core" eventID:@"getd" appPSN:savedPSN];
157 [playlists addObject:theObj];
159 return [playlists autorelease];
162 //Full source awareness
163 - (NSArray *)playlists
166 SInt32 numSources = [ITSendAEWithString(@"kocl:type('cSrc'), '----':()", 'core', 'cnte', &savedPSN) int32Value];
167 NSMutableArray *allSources = [[NSMutableArray alloc] init];
169 ITDebugLog(@"Getting playlists.");
170 if (numSources == 0) {
171 ITDebugLog(@"No sources.");
175 for (k = 1; k <= numSources ; k++) {
176 SInt32 numPlaylists = [ITSendAEWithString([NSString stringWithFormat:@"kocl:type('cPly'), '----':obj { form:'indx', want:type('cSrc'), seld:long(%u), from:() }",k], 'core', 'cnte', &savedPSN) int32Value];
177 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];
178 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];
179 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];
182 NSMutableArray *aSource = [[NSMutableArray alloc] init];
183 [aSource addObject:sourceName];
186 class = ITMTRemoteRadioSource;
189 class = ITMTRemoteGenericDeviceSource;
192 class = ITMTRemoteiPodSource;
196 class = ITMTRemoteCDSource;
199 class = ITMTRemoteSharedLibrarySource;
204 class = ITMTRemoteLibrarySource;
207 ITDebugLog(@"Adding source %@ of type %i at index %i", sourceName, class, index);
208 [aSource addObject:[NSNumber numberWithInt:class]];
209 [aSource addObject:[NSNumber numberWithInt:index]];
210 for (i = 1; i <= numPlaylists; i++) {
211 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];
212 NSString *theObj = [ITSendAEWithString(sendStr, 'core', 'getd', &savedPSN) stringValue];
213 ITDebugLog(@" - Adding playlist %@", theObj);
215 [aSource addObject:theObj];
218 [allSources addObject:[aSource autorelease]];
220 ITDebugLog(@"Source at index %i disappeared.", k);
223 ITDebugLog(@"Finished getting playlists.");
224 return [allSources autorelease];
229 NSAppleEventDescriptor *rawr = ITSendAEWithString(@"'----':obj { form:'prop', want:type('prop'), seld:type('pArt'), from:obj { form:'indx', want:type('cTrk'), seld:abso($616C6C20$), from:obj { form:'indx', want:type('cPly'), seld:long(1), from:obj { form:'indx', want:type('cSrc'), seld:long(1), from:() } } } }", 'core', 'getd', &savedPSN);
231 NSMutableArray *array = [[NSMutableArray alloc] init];
232 NSArray *returnArray;
233 for (i = 1; i <= [rawr numberOfItems]; i++) {
234 NSString *artist = [[rawr descriptorAtIndex:i] stringValue];
235 if (artist && [artist length] && ![array containsObject:artist]) {
236 [array addObject:artist];
239 [array sortUsingSelector:@selector(caseInsensitiveCompare:)];
240 returnArray = [NSArray arrayWithArray:array];
247 NSAppleEventDescriptor *rawr = ITSendAEWithString(@"'----':obj { form:'prop', want:type('prop'), seld:type('pAlb'), from:obj { form:'indx', want:type('cTrk'), seld:abso($616C6C20$), from:obj { form:'indx', want:type('cPly'), seld:long(1), from:obj { form:'indx', want:type('cSrc'), seld:long(1), from:() } } } }", 'core', 'getd', &savedPSN);
249 NSMutableArray *array = [[NSMutableArray alloc] init];
250 NSArray *returnArray;
251 for (i = 1; i <= [rawr numberOfItems]; i++) {
252 NSString *album = [[rawr descriptorAtIndex:i] stringValue];
253 if (album && [album length] && ![array containsObject:album]) {
254 [array addObject:album];
257 [array sortUsingSelector:@selector(caseInsensitiveCompare:)];
258 returnArray = [NSArray arrayWithArray:array];
263 - (int)numberOfSongsInPlaylistAtIndex:(int)index
266 ITDebugLog(@"Getting number of songs in playlist at index %i", index);
267 temp1 = [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', 'getd', &savedPSN) int32Value];
268 ITDebugLog(@"Getting number of songs in playlist at index %i done", index);
272 - (ITMTRemotePlayerSource)currentSource
276 ITDebugLog(@"Getting current source.");
278 fourcc = [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) int32Value];
282 ITDebugLog(@"Getting current source done. Source: Radio.");
283 return ITMTRemoteRadioSource;
286 ITDebugLog(@"Getting current source done. Source: Generic Device.");
287 return ITMTRemoteGenericDeviceSource;
289 ITDebugLog(@"Getting current source done. Source: iPod.");
290 return ITMTRemoteiPodSource; //this is stupid
294 ITDebugLog(@"Getting current source done. Source: CD.");
295 return ITMTRemoteCDSource;
298 ITDebugLog(@"Getting current source done. Source: Shared Library.");
299 return ITMTRemoteSharedLibrarySource;
304 ITDebugLog(@"Getting current source done. Source: Library.");
305 return ITMTRemoteLibrarySource;
310 - (int)currentSourceIndex
312 ITDebugLog(@"Getting current source.");
313 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];
316 - (ITMTRemotePlayerPlaylistClass)currentPlaylistClass
319 ITDebugLog(@"Getting current playlist class");
320 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) int32Value];
324 ITDebugLog(@"Getting current playlist class done. Class: Library.");
325 return ITMTRemotePlayerLibraryPlaylist;
328 ITDebugLog(@"Getting current playlist class done. Class: Radio.");
329 return ITMTRemotePlayerRadioPlaylist;
332 ITDebugLog(@"Getting current playlist class done. Class: Standard playlist.");
333 return ITMTRemotePlayerPlaylist;
337 - (int)currentPlaylistIndex
340 ITDebugLog(@"Getting current playlist index.");
341 temp1 = [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];
342 ITDebugLog(@"Getting current playlist index done.");
346 - (NSString *)songTitleAtIndex:(int)index
349 ITDebugLog(@"Getting song title at index %i.", index);
350 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];
351 ITDebugLog(@"Getting song title at index %i done.", index);
352 return ( ([temp1 length]) ? temp1 : nil ) ;
355 - (int)currentAlbumTrackCount
358 ITDebugLog(@"Getting current album track count.");
359 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];
360 if ( [self currentPlaylistClass] == ITMTRemotePlayerRadioPlaylist ) { temp1 = 0; }
361 ITDebugLog(@"Getting current album track count done.");
365 - (int)currentSongTrack
368 ITDebugLog(@"Getting current song track.");
369 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];
370 if ( [self currentPlaylistClass] == ITMTRemotePlayerRadioPlaylist ) { temp1 = 0; }
371 ITDebugLog(@"Getting current song track done.");
375 - (NSString *)playerStateUniqueIdentifier
378 ITDebugLog(@"Getting current unique identifier.");
379 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);
380 if (descriptor == nil) {
383 SInt32 cls = [descriptor int32Value];
384 if ( ([self currentPlaylistClass] == ITMTRemotePlayerRadioPlaylist) || (cls == 'cURT') ) {
385 NSString *bad = [NSString stringWithUTF8String:"浳湧"];
386 temp1 = [ITSendAEWithKey('pStT', 'core', 'getd', &savedPSN) stringValue];
387 if ([temp1 isEqualToString:bad]) {
388 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];
391 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]];
393 ITDebugLog(@"Getting current unique identifier done.");
394 return ( ([temp1 length]) ? temp1 : nil ) ;
397 - (int)currentSongIndex
400 ITDebugLog(@"Getting current song index.");
401 temp1 = [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];
402 ITDebugLog(@"Getting current song index done.");
406 - (NSString *)currentSongTitle
409 ITDebugLog(@"Getting current song title.");
411 //If we're listening to the radio.
412 if ([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] == 'cURT') {
413 NSString *bad = [NSString stringWithUTF8String:"浳湧"];
414 temp1 = [ITSendAEWithKey('pStT', 'core', 'getd', &savedPSN) stringValue];
415 if ([temp1 isEqualToString:bad]) {
416 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];
418 temp1 = [temp1 stringByAppendingString:@" (Stream)"];
420 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];
422 ITDebugLog(@"Getting current song title done.");
423 return ( ([temp1 length]) ? temp1 : nil ) ;
426 - (NSString *)currentSongArtist
429 ITDebugLog(@"Getting current song artist.");
430 if ( [self currentPlaylistClass] != ITMTRemotePlayerRadioPlaylist ) {
431 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];
435 ITDebugLog(@"Getting current song artist done.");
436 return ( ([temp1 length]) ? temp1 : nil ) ;
439 - (NSString *)currentSongComposer
442 ITDebugLog(@"Getting current song artist.");
443 if ( [self currentPlaylistClass] != ITMTRemotePlayerRadioPlaylist ) {
444 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];
448 ITDebugLog(@"Getting current song artist done.");
449 return ( ([temp1 length]) ? temp1 : nil ) ;
452 - (NSString *)currentSongAlbum
455 ITDebugLog(@"Getting current song album.");
456 if ( [self currentPlaylistClass] != ITMTRemotePlayerRadioPlaylist ) {
457 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];
461 ITDebugLog(@"Getting current song album done.");
462 return ( ([temp1 length]) ? temp1 : nil ) ;
465 - (NSString *)currentSongGenre
468 ITDebugLog(@"Getting current song genre.");
469 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];
470 ITDebugLog(@"Getting current song genre done.");
471 return ( ([temp1 length]) ? temp1 : nil ) ;
474 - (NSString *)currentSongLength
478 ITDebugLog(@"Getting current song length.");
479 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];
480 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];
481 if ( ([self currentPlaylistClass] == ITMTRemotePlayerRadioPlaylist) || (temp1 == 'cURT') ) { temp2 = @"Continuous"; }
482 ITDebugLog(@"Getting current song length done.");
486 - (NSString *)currentSongRemaining
488 SInt32 duration, current, final;
489 NSString *finalString;
491 ITDebugLog(@"Getting current song remaining time.");
493 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];
494 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];
495 final = duration - current;
496 finalString = [self formatTimeInSeconds:final];
498 if ( [self currentPlaylistClass] == ITMTRemotePlayerRadioPlaylist ) { finalString = nil; }
500 ITDebugLog(@"Getting current song remaining time done.");
505 - (NSString *)currentSongElapsed
508 NSString *finalString;
510 ITDebugLog(@"Getting current song elapsed time.");
511 final = (long)[ITSendAEWithKey('pPos', 'core', 'getd', &savedPSN) int32Value];
512 finalString = [self formatTimeInSeconds:final];
513 ITDebugLog(@"Getting current song elapsed time done.");
517 - (NSImage *)currentSongAlbumArt
519 ITDebugLog(@"Getting current song album art.");
520 NSData *data = [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];
521 ITDebugLog(@"Getting current song album art done.");
523 return [[[NSImage alloc] initWithData:data] autorelease];
529 - (int)currentSongPlayCount
532 ITDebugLog(@"Getting current song play count.");
533 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];
534 ITDebugLog(@"Getting current song play count done.");
538 - (float)currentSongRating
541 ITDebugLog(@"Getting current song rating.");
542 temp1 = ((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);
543 if ( [self currentPlaylistClass] == ITMTRemotePlayerRadioPlaylist ) { temp1 = -1.0; }
544 ITDebugLog(@"Getting current song rating done.");
548 - (BOOL)setCurrentSongRating:(float)rating
550 ITDebugLog(@"Setting current song rating to %f.", rating);
551 if ( [self currentPlaylistClass] == ITMTRemotePlayerRadioPlaylist ) { return NO; }
552 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);
553 ITDebugLog(@"Setting current song rating to %f done.", rating);
557 - (BOOL)equalizerEnabled
559 ITDebugLog(@"Getting equalizer enabled status.");
560 int thingy = (int)[ITSendAEWithKey('pEQ ', 'core', 'getd', &savedPSN) int32Value];
561 ITDebugLog(@"Done getting equalizer enabled status.");
562 return (thingy != 0) ? YES : NO;
565 - (BOOL)setEqualizerEnabled:(BOOL)enabled
567 ITDebugLog(@"Setting equalizer enabled to %i.", enabled);
568 ITSendAEWithString([NSString stringWithFormat:@"data:long(%lu), '----':obj { form:'prop', want:type('prop'), seld:type('pEQ '), from:'null'() }", enabled], 'core', 'setd', &savedPSN);
569 ITDebugLog(@"Done setting equalizer enabled to %i.", enabled);
573 - (NSArray *)eqPresets
576 SInt32 numPresets = [ITSendAEWithString(@"kocl:type('cEQP'), '----':(), &subj:()", 'core', 'cnte', &savedPSN) int32Value];
577 NSMutableArray *presets = [[NSMutableArray alloc] initWithCapacity:numPresets];
578 ITDebugLog(@"Getting EQ presets");
579 for (i = 1; i <= numPresets; i++) {
580 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];
582 ITDebugLog(@"Adding preset %@", theObj);
583 [presets addObject:theObj];
586 ITDebugLog(@"Done getting EQ presets");
587 return [presets autorelease];
590 - (int)currentEQPresetIndex
593 ITDebugLog(@"Getting current EQ preset index.");
594 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];
595 ITDebugLog(@"Getting current EQ preset index done.");
601 ITDebugLog(@"Getting volume.");
602 ITDebugLog(@"Getting volume done.");
603 return (float)[ITSendAEWithKey('pVol', 'core', 'getd', &savedPSN) int32Value] / 100;
606 - (BOOL)setVolume:(float)volume
608 ITDebugLog(@"Setting volume to %f.", volume);
609 ITSendAEWithString([NSString stringWithFormat:@"data:long(%lu), '----':obj { form:'prop', want:type('prop'), seld:type('pVol'), from:'null'() }", (long)(volume * 100)], 'core', 'setd', &savedPSN);
610 ITDebugLog(@"Setting volume to %f done.", volume);
614 - (BOOL)shuffleEnabled
616 ITDebugLog(@"Getting shuffle enabled status.");
618 int result = (int)[ITSendAEWithString(@"'----':obj { form:'prop', want:type('prop'), seld:type('pShf'), from:obj { form:'prop', want:type('pPla'), seld:type('pEQP'), from:'null'() } }", 'core', 'getd', &savedPSN) int32Value];
624 ITDebugLog(@"Getting shuffle enabled status done.");
628 - (BOOL)setShuffleEnabled:(BOOL)enabled
630 ITDebugLog(@"Set shuffle enabled to %i", enabled);
631 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);
632 ITDebugLog(@"Set shuffle enabled to %i done", enabled);
636 - (ITMTRemotePlayerRepeatMode)repeatMode
638 FourCharCode m00f = 0;
640 m00f = (FourCharCode)[ITSendAEWithString(@"'----':obj { form:'prop', want:type('prop'), seld:type('pRpt'), from:obj { form:'prop', want:type('pPla'), seld:type('pEQP'), from:'null'() } }", 'core', 'getd', &savedPSN) int32Value];
641 ITDebugLog(@"Getting repeat mode.");
646 ITDebugLog(@"Repeat off");
647 result = ITMTRemotePlayerRepeatOff;
650 ITDebugLog(@"Repeat one");
651 result = ITMTRemotePlayerRepeatOne;
654 ITDebugLog(@"Repeat all");
655 result = ITMTRemotePlayerRepeatAll;
658 ITDebugLog(@"Getting repeat mode done.");
662 - (BOOL)setRepeatMode:(ITMTRemotePlayerRepeatMode)repeatMode
665 ITDebugLog(@"Setting repeat mode to %i", repeatMode);
668 case ITMTRemotePlayerRepeatOne:
671 case ITMTRemotePlayerRepeatAll:
674 case ITMTRemotePlayerRepeatOff:
679 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);
680 ITDebugLog(@"Setting repeat mode to %c done", m00f);
687 ITSendAE('hook', 'Play', &savedPSN);
688 ITDebugLog(@"Play done");
694 ITDebugLog(@"Pause");
695 ITSendAE('hook', 'Paus', &savedPSN);
696 ITDebugLog(@"Pause done");
702 ITDebugLog(@"Go to next track");
703 ITSendAE('hook', 'Next', &savedPSN);
704 ITDebugLog(@"Go to next track done");
708 - (BOOL)goToPreviousSong
710 ITDebugLog(@"Go to previous track");
711 ITSendAE('hook', 'Prev', &savedPSN);
712 ITDebugLog(@"Go to previous track done");
718 ITDebugLog(@"Fast forward action");
719 ITSendAE('hook', 'Fast', &savedPSN);
720 ITDebugLog(@"Fast forward action done");
726 ITDebugLog(@"Rewind action");
727 ITSendAE('hook', 'Rwnd', &savedPSN);
728 ITDebugLog(@"Rewind action done");
732 - (BOOL)switchToPlaylistAtIndex:(int)index
734 ITDebugLog(@"Switching to playlist at index %i", index);
735 ITSendAEWithString([NSString stringWithFormat:@"'----':obj { form:'indx', want:type('cPly'), seld:long(%lu), from:() }", index], 'hook', 'Play', &savedPSN);
736 ITDebugLog(@"Done switching to playlist at index %i", index);
740 - (BOOL)switchToPlaylistAtIndex:(int)index ofSourceAtIndex:(int)index2
742 ITDebugLog(@"Switching to playlist at index %i of source %i", index, index2);
743 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);
744 ITDebugLog(@"Done switching to playlist at index %i of source %i", index, index2);
748 - (BOOL)switchToSongAtIndex:(int)index
750 ITDebugLog(@"Switching to track at index %i", index);
751 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);
752 ITDebugLog(@"Done switching to track at index %i", index);
756 - (BOOL)switchToEQAtIndex:(int)index
758 ITDebugLog(@"Switching to EQ preset at index %i", index);
759 // index should count from 0, but itunes counts from 1, so let's add 1.
760 [self setEqualizerEnabled:YES];
761 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);
762 ITDebugLog(@"Done switching to EQ preset at index %i", index);
766 - (BOOL)makePlaylistWithTerm:(NSString *)term ofType:(int)type
770 //Get fixed indexing status
771 BOOL fixed = [ITSendAEWithString(@"'----':obj { form:'prop', want:type('prop'), seld:type('pFix'), from:'null'() }", 'core', 'getd', &savedPSN) booleanValue];
773 //Enabled fixed indexing
774 ITSendAEWithString(@"data:long(1), '----':obj { form:'prop', want:type('prop'), seld:type('pFix'), from:'null'() }", 'core', 'setd', &savedPSN);
776 //Search for the term
777 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);
779 //If MenuTunes playlist exists
780 if ([ITSendAEWithString(@"'----':obj { form:'name', want:type('cPly'), seld:\"MenuTunes\", from:'null'() }", 'core', 'doex', &savedPSN) booleanValue]) {
781 //Clear old MenuTunes playlist
782 int numSongs = [ITSendAEWithString(@"kocl:type('cTrk'), '----':obj { form:'name', want:type('cPly'), seld:\"MenuTunes\", from:obj { form:'prop', want:type('prop'), seld:type('ctnr'), from:obj { form:'prop', want:type('prop'), seld:type('pPla'), from:'null'() } } }", 'core', 'cnte', &savedPSN) int32Value];
783 for (i = 1; i <= numSongs; i++) {
784 ITSendAEWithString(@"'----':obj { form:'indx', want:type('cTrk'), seld:long(1), from:obj { form:'name', want:type('cPly'), seld:\"MenuTunes\", from:'null'() } }", 'core', 'delo', &savedPSN);
787 //Create MenuTunes playlist
788 ITSendAEWithString(@"prdt:{ pnam:\"MenuTunes\" }, kocl:type('cPly'), &subj:()", 'core', 'crel', &savedPSN);
791 //Duplicate search results to playlist
792 for (i = 1; i <= [searchResults numberOfItems]; i++) {
793 ITSendAEWithStringAndObject(@"insh:obj { form:'name', want:type('cPly'), seld:\"MenuTunes\", from:'null'() }", [[searchResults descriptorAtIndex:i] aeDesc], 'core', 'clon', &savedPSN);
795 //Reset fixed indexing
796 ITSendAEWithString([NSString stringWithFormat:@"data:long(%i), '----':obj { form:'prop', want:type('prop'), seld:type('pFix'), from:'null'() }", fixed], 'core', 'setd', &savedPSN);
798 //Play MenuTunes playlist
799 ITSendAEWithString(@"'----':obj { form:'name', want:type('cPly'), seld:\"MenuTunes\", from:'null'() }", 'hook', 'Play', &savedPSN);
804 - (ProcessSerialNumber)iTunesPSN
806 /*NSArray *apps = [[NSWorkspace sharedWorkspace] launchedApplications];
807 ProcessSerialNumber number;
809 int count = [apps count];
811 number.highLongOfPSN = kNoProcess;
813 for (i = 0; i < count; i++)
815 NSDictionary *curApp = [apps objectAtIndex:i];
817 if ([[curApp objectForKey:@"NSApplicationName"] isEqualToString:@"iTunes"])
819 number.highLongOfPSN = [[curApp objectForKey:
820 @"NSApplicationProcessSerialNumberHigh"] intValue];
821 number.lowLongOfPSN = [[curApp objectForKey:
822 @"NSApplicationProcessSerialNumberLow"] intValue];
826 ProcessSerialNumber number;
827 number.highLongOfPSN = kNoProcess;
828 number.lowLongOfPSN = 0;
829 ITDebugLog(@"Getting iTunes' PSN.");
830 while ( (GetNextProcess(&number) == noErr) )
833 if ( (CopyProcessName(&number, &name) == noErr) )
835 if ([(NSString *)name isEqualToString:@"iTunes"])
837 ITDebugLog(@"iTunes' highLPongOfPSN: %lu.", number.highLongOfPSN);
838 ITDebugLog(@"iTunes' lowLongOfPSN: %lu.", number.lowLongOfPSN);
839 ITDebugLog(@"Done getting iTunes' PSN.");
842 [(NSString *)name release];
845 ITDebugLog(@"Failed getting iTunes' PSN.");
849 - (NSString*)formatTimeInSeconds:(long)seconds {
850 long final = seconds;
851 NSString *finalString;
854 finalString = [NSString stringWithFormat:@"%i:%@:%@",(final / 3600),[self zeroSixty:(int)((final % 3600) / 60)],[self zeroSixty:(int)((final % 3600) % 60)]];
856 finalString = [NSString stringWithFormat:@"%i:%@",(final / 60),[self zeroSixty:(int)(final % 60)]];
859 finalString = [NSString stringWithFormat:@"0:%@",[self zeroSixty:(int)final]];
863 - (NSString*)zeroSixty:(int)seconds {
864 if ( (seconds < 10) && (seconds > 0) ) {
865 return [NSString stringWithFormat:@"0%i",seconds];
866 } else if ( (seconds == 0) ) {
867 return [NSString stringWithFormat:@"00"];
869 return [NSString stringWithFormat:@"%i",seconds];