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 SInt32 cls = [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];
380 if ( ([self currentPlaylistClass] == ITMTRemotePlayerRadioPlaylist) || (cls == 'cURT') ) {
381 temp1 = [ITSendAEWithKey('pStT', 'core', 'getd', &savedPSN) stringValue];
384 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]];
386 ITDebugLog(@"Getting current unique identifier done.");
387 return ( ([temp1 length]) ? temp1 : nil ) ;
390 - (int)currentSongIndex
393 ITDebugLog(@"Getting current song index.");
394 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];
395 ITDebugLog(@"Getting current song index done.");
399 - (NSString *)currentSongTitle
402 ITDebugLog(@"Getting current song title.");
404 //If we're listening to the radio.
405 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') {
406 NSString *bad = [NSString stringWithUTF8String:"浳湧"];
407 temp1 = [ITSendAEWithKey('pStT', 'core', 'getd', &savedPSN) stringValue];
408 if ([temp1 isEqualToString:bad]) {
410 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];
412 temp1 = [temp1 stringByAppendingString:@" (Stream)"];
414 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];
416 ITDebugLog(@"Getting current song title done.");
417 return ( ([temp1 length]) ? temp1 : nil ) ;
420 - (NSString *)currentSongArtist
423 ITDebugLog(@"Getting current song artist.");
424 if ( [self currentPlaylistClass] != ITMTRemotePlayerRadioPlaylist ) {
425 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];
429 ITDebugLog(@"Getting current song artist done.");
430 return ( ([temp1 length]) ? temp1 : nil ) ;
433 - (NSString *)currentSongComposer
436 ITDebugLog(@"Getting current song artist.");
437 if ( [self currentPlaylistClass] != ITMTRemotePlayerRadioPlaylist ) {
438 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];
442 ITDebugLog(@"Getting current song artist done.");
443 return ( ([temp1 length]) ? temp1 : nil ) ;
446 - (NSString *)currentSongAlbum
449 ITDebugLog(@"Getting current song album.");
450 if ( [self currentPlaylistClass] != ITMTRemotePlayerRadioPlaylist ) {
451 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];
455 ITDebugLog(@"Getting current song album done.");
456 return ( ([temp1 length]) ? temp1 : nil ) ;
459 - (NSString *)currentSongGenre
462 ITDebugLog(@"Getting current song genre.");
463 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];
464 ITDebugLog(@"Getting current song genre done.");
465 return ( ([temp1 length]) ? temp1 : nil ) ;
468 - (NSString *)currentSongLength
472 ITDebugLog(@"Getting current song length.");
473 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];
474 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];
475 if ( ([self currentPlaylistClass] == ITMTRemotePlayerRadioPlaylist) || (temp1 == 'cURT') ) { temp2 = @"Continuous"; }
476 ITDebugLog(@"Getting current song length done.");
480 - (NSString *)currentSongRemaining
482 SInt32 duration, current, final;
483 NSString *finalString;
485 ITDebugLog(@"Getting current song remaining time.");
487 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];
488 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];
489 final = duration - current;
490 finalString = [self formatTimeInSeconds:final];
492 if ( [self currentPlaylistClass] == ITMTRemotePlayerRadioPlaylist ) { finalString = nil; }
494 ITDebugLog(@"Getting current song remaining time done.");
499 - (NSString *)currentSongElapsed
502 NSString *finalString;
504 ITDebugLog(@"Getting current song elapsed time.");
505 final = (long)[ITSendAEWithString(@"'----':obj { form:'prop', want:type('prop'), seld:type('pPos'), from:'null'() }", 'core', 'getd', &savedPSN) int32Value];
506 finalString = [self formatTimeInSeconds:final];
507 ITDebugLog(@"Getting current song elapsed time done.");
511 - (NSImage *)currentSongAlbumArt
513 ITDebugLog(@"Getting current song album art.");
514 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];
515 ITDebugLog(@"Getting current song album art done.");
517 return [[[NSImage alloc] initWithData:data] autorelease];
523 - (int)currentSongPlayCount
526 ITDebugLog(@"Getting current song play count.");
527 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];
528 ITDebugLog(@"Getting current song play count done.");
532 - (float)currentSongRating
535 ITDebugLog(@"Getting current song rating.");
536 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);
537 if ( [self currentPlaylistClass] == ITMTRemotePlayerRadioPlaylist ) { temp1 = -1.0; }
538 ITDebugLog(@"Getting current song rating done.");
542 - (BOOL)setCurrentSongRating:(float)rating
544 ITDebugLog(@"Setting current song rating to %f.", rating);
545 if ( [self currentPlaylistClass] == ITMTRemotePlayerRadioPlaylist ) { return NO; }
546 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);
547 ITDebugLog(@"Setting current song rating to %f done.", rating);
551 - (BOOL)equalizerEnabled
553 ITDebugLog(@"Getting equalizer enabled status.");
554 int thingy = (int)[ITSendAEWithKey('pEQ ', 'core', 'getd', &savedPSN) int32Value];
555 ITDebugLog(@"Done getting equalizer enabled status.");
556 return (thingy != 0) ? YES : NO;
559 - (BOOL)setEqualizerEnabled:(BOOL)enabled
561 ITDebugLog(@"Setting equalizer enabled to %i.", enabled);
562 ITSendAEWithString([NSString stringWithFormat:@"data:long(%lu), '----':obj { form:'prop', want:type('prop'), seld:type('pEQ '), from:'null'() }", enabled], 'core', 'setd', &savedPSN);
563 ITDebugLog(@"Done setting equalizer enabled to %i.", enabled);
567 - (NSArray *)eqPresets
570 SInt32 numPresets = [ITSendAEWithString(@"kocl:type('cEQP'), '----':(), &subj:()", 'core', 'cnte', &savedPSN) int32Value];
571 NSMutableArray *presets = [[NSMutableArray alloc] initWithCapacity:numPresets];
572 ITDebugLog(@"Getting EQ presets");
573 for (i = 1; i <= numPresets; i++) {
574 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];
576 ITDebugLog(@"Adding preset %@", theObj);
577 [presets addObject:theObj];
580 ITDebugLog(@"Done getting EQ presets");
581 return [presets autorelease];
584 - (int)currentEQPresetIndex
587 ITDebugLog(@"Getting current EQ preset index.");
588 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];
589 ITDebugLog(@"Getting current EQ preset index done.");
595 ITDebugLog(@"Getting volume.");
596 ITDebugLog(@"Getting volume done.");
597 return (float)[ITSendAEWithKey('pVol', 'core', 'getd', &savedPSN) int32Value] / 100;
600 - (BOOL)setVolume:(float)volume
602 ITDebugLog(@"Setting volume to %f.", volume);
603 ITSendAEWithString([NSString stringWithFormat:@"data:long(%lu), '----':obj { form:'prop', want:type('prop'), seld:type('pVol'), from:'null'() }", (long)(volume * 100)], 'core', 'setd', &savedPSN);
604 ITDebugLog(@"Setting volume to %f done.", volume);
608 - (BOOL)shuffleEnabled
610 ITDebugLog(@"Getting shuffle enabled status.");
612 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];
618 ITDebugLog(@"Getting shuffle enabled status done.");
622 - (BOOL)setShuffleEnabled:(BOOL)enabled
624 ITDebugLog(@"Set shuffle enabled to %i", enabled);
625 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);
626 ITDebugLog(@"Set shuffle enabled to %i done", enabled);
630 - (ITMTRemotePlayerRepeatMode)repeatMode
632 FourCharCode m00f = 0;
634 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];
635 ITDebugLog(@"Getting repeat mode.");
640 ITDebugLog(@"Repeat off");
641 result = ITMTRemotePlayerRepeatOff;
644 ITDebugLog(@"Repeat one");
645 result = ITMTRemotePlayerRepeatOne;
648 ITDebugLog(@"Repeat all");
649 result = ITMTRemotePlayerRepeatAll;
652 ITDebugLog(@"Getting repeat mode done.");
656 - (BOOL)setRepeatMode:(ITMTRemotePlayerRepeatMode)repeatMode
659 ITDebugLog(@"Setting repeat mode to %i", repeatMode);
662 case ITMTRemotePlayerRepeatOne:
665 case ITMTRemotePlayerRepeatAll:
668 case ITMTRemotePlayerRepeatOff:
673 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);
674 ITDebugLog(@"Setting repeat mode to %c done", m00f);
681 ITSendAE('hook', 'Play', &savedPSN);
682 ITDebugLog(@"Play done");
688 ITDebugLog(@"Pause");
689 ITSendAE('hook', 'Paus', &savedPSN);
690 ITDebugLog(@"Pause done");
696 ITDebugLog(@"Go to next track");
697 ITSendAE('hook', 'Next', &savedPSN);
698 ITDebugLog(@"Go to next track done");
702 - (BOOL)goToPreviousSong
704 ITDebugLog(@"Go to previous track");
705 ITSendAE('hook', 'Prev', &savedPSN);
706 ITDebugLog(@"Go to previous track done");
712 ITDebugLog(@"Fast forward action");
713 ITSendAE('hook', 'Fast', &savedPSN);
714 ITDebugLog(@"Fast forward action done");
720 ITDebugLog(@"Rewind action");
721 ITSendAE('hook', 'Rwnd', &savedPSN);
722 ITDebugLog(@"Rewind action done");
726 - (BOOL)switchToPlaylistAtIndex:(int)index
728 ITDebugLog(@"Switching to playlist at index %i", index);
729 ITSendAEWithString([NSString stringWithFormat:@"'----':obj { form:'indx', want:type('cPly'), seld:long(%lu), from:() }", index], 'hook', 'Play', &savedPSN);
730 ITDebugLog(@"Done switching to playlist at index %i", index);
734 - (BOOL)switchToPlaylistAtIndex:(int)index ofSourceAtIndex:(int)index2
736 ITDebugLog(@"Switching to playlist at index %i of source %i", index, index2);
737 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);
738 ITDebugLog(@"Done switching to playlist at index %i of source %i", index, index2);
742 - (BOOL)switchToSongAtIndex:(int)index
744 ITDebugLog(@"Switching to track at index %i", index);
745 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);
746 ITDebugLog(@"Done switching to track at index %i", index);
750 - (BOOL)switchToEQAtIndex:(int)index
752 ITDebugLog(@"Switching to EQ preset at index %i", index);
753 // index should count from 0, but itunes counts from 1, so let's add 1.
754 [self setEqualizerEnabled:YES];
755 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);
756 ITDebugLog(@"Done switching to EQ preset at index %i", index);
760 - (BOOL)makePlaylistWithTerm:(NSString *)term ofType:(int)type
764 //Get fixed indexing status
765 BOOL fixed = [ITSendAEWithString(@"'----':obj { form:'prop', want:type('prop'), seld:type('pFix'), from:'null'() }", 'core', 'getd', &savedPSN) booleanValue];
767 //Enabled fixed indexing
768 ITSendAEWithString(@"data:long(1), '----':obj { form:'prop', want:type('prop'), seld:type('pFix'), from:'null'() }", 'core', 'setd', &savedPSN);
770 //Search for the term
771 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);
773 //If MenuTunes playlist exists
774 if ([ITSendAEWithString(@"'----':obj { form:'name', want:type('cPly'), seld:\"MenuTunes\", from:'null'() }", 'core', 'doex', &savedPSN) booleanValue]) {
775 //Clear old MenuTunes playlist
776 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];
777 for (i = 1; i <= numSongs; i++) {
778 ITSendAEWithString(@"'----':obj { form:'indx', want:type('cTrk'), seld:long(1), from:obj { form:'name', want:type('cPly'), seld:\"MenuTunes\", from:'null'() } }", 'core', 'delo', &savedPSN);
781 //Create MenuTunes playlist
782 ITSendAEWithString(@"prdt:{ pnam:\"MenuTunes\" }, kocl:type('cPly'), &subj:()", 'core', 'crel', &savedPSN);
785 //Duplicate search results to playlist
786 for (i = 1; i <= [searchResults numberOfItems]; i++) {
787 ITSendAEWithStringAndObject(@"insh:obj { form:'name', want:type('cPly'), seld:\"MenuTunes\", from:'null'() }", [[searchResults descriptorAtIndex:i] aeDesc], 'core', 'clon', &savedPSN);
789 //Reset fixed indexing
790 ITSendAEWithString([NSString stringWithFormat:@"data:long(%i), '----':obj { form:'prop', want:type('prop'), seld:type('pFix'), from:'null'() }", fixed], 'core', 'setd', &savedPSN);
792 //Play MenuTunes playlist
793 ITSendAEWithString(@"'----':obj { form:'name', want:type('cPly'), seld:\"MenuTunes\", from:'null'() }", 'hook', 'Play', &savedPSN);
798 - (ProcessSerialNumber)iTunesPSN
800 /*NSArray *apps = [[NSWorkspace sharedWorkspace] launchedApplications];
801 ProcessSerialNumber number;
803 int count = [apps count];
805 number.highLongOfPSN = kNoProcess;
807 for (i = 0; i < count; i++)
809 NSDictionary *curApp = [apps objectAtIndex:i];
811 if ([[curApp objectForKey:@"NSApplicationName"] isEqualToString:@"iTunes"])
813 number.highLongOfPSN = [[curApp objectForKey:
814 @"NSApplicationProcessSerialNumberHigh"] intValue];
815 number.lowLongOfPSN = [[curApp objectForKey:
816 @"NSApplicationProcessSerialNumberLow"] intValue];
820 ProcessSerialNumber number;
821 number.highLongOfPSN = kNoProcess;
822 number.lowLongOfPSN = 0;
823 ITDebugLog(@"Getting iTunes' PSN.");
824 while ( (GetNextProcess(&number) == noErr) )
827 if ( (CopyProcessName(&number, &name) == noErr) )
829 if ([(NSString *)name isEqualToString:@"iTunes"])
831 ITDebugLog(@"iTunes' highLPongOfPSN: %lu.", number.highLongOfPSN);
832 ITDebugLog(@"iTunes' lowLongOfPSN: %lu.", number.lowLongOfPSN);
833 ITDebugLog(@"Done getting iTunes' PSN.");
836 [(NSString *)name release];
839 ITDebugLog(@"Failed getting iTunes' PSN.");
843 - (NSString*)formatTimeInSeconds:(long)seconds {
844 long final = seconds;
845 NSString *finalString;
848 finalString = [NSString stringWithFormat:@"%i:%@:%@",(final / 3600),[self zeroSixty:(int)((final % 3600) / 60)],[self zeroSixty:(int)((final % 3600) % 60)]];
850 finalString = [NSString stringWithFormat:@"%i:%@",(final / 60),[self zeroSixty:(int)(final % 60)]];
853 finalString = [NSString stringWithFormat:@"0:%@",[self zeroSixty:(int)final]];
857 - (NSString*)zeroSixty:(int)seconds {
858 if ( (seconds < 10) && (seconds > 0) ) {
859 return [NSString stringWithFormat:@"0%i",seconds];
860 } else if ( (seconds == 0) ) {
861 return [NSString stringWithFormat:@"00"];
863 return [NSString stringWithFormat:@"%i",seconds];