#import "iTunesRemote.h"
+#import "PlaylistNode.h"
@implementation iTunesRemote
{
ITDebugLog(@"iTunesRemote begun");
savedPSN = [self iTunesPSN];
+ [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(notificationHandler:) name:@"com.apple.iTunes.playerInfo" object:@"com.apple.iTunes.player"];
+
+ NSString *iTunesPath = [[NSUserDefaults standardUserDefaults] stringForKey:@"CustomPlayerPath"];
+ NSDictionary *iTunesInfoPlist;
+ float iTunesVersion;
+
+ //Check if iTunes 5.0 or later is installed
+ if (!iTunesPath) {
+ iTunesPath = [[NSWorkspace sharedWorkspace] fullPathForApplication:@"iTunes.app"];
+ }
+ iTunesInfoPlist = [[NSBundle bundleWithPath:iTunesPath] infoDictionary];
+ iTunesVersion = [[iTunesInfoPlist objectForKey:@"CFBundleVersion"] floatValue];
+ ITDebugLog(@"iTunes version found: %f.", iTunesVersion);
+ _iTunesVersion = iTunesVersion;
+
return YES;
}
- (BOOL)halt
{
ITDebugLog(@"iTunesRemote halted");
+ [[NSDistributedNotificationCenter defaultCenter] removeObserver:self];
return YES;
}
([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) &&
[[[[NSWorkspace sharedWorkspace] activeApplication] objectForKey:@"NSApplicationName"] isEqualToString:@"iTunes"] ) {
//set minimized of browser window 1 to true
- 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);
+ 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);
} else {
//set minimized of browser window 1 to false
- 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);
+ 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);
}
//set visible of browser window 1 to true
- 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);
+ 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);
//active iTunes
ITSendAEWithString(@"data:long(1), '----':obj { form:'prop', want:type('prop'), seld:type('pisf'), from:'null'() }", 'core', 'setd', &savedPSN);
ITDebugLog(@"Done showing player primary interface.");
SInt32 result;
ITDebugLog(@"Getting player playing state");
- result = [ITSendAEWithString(@"'----':obj { form:'prop', want:type('prop'), seld:type('pPlS'), from:'null'() }", 'core', 'getd', &savedPSN) int32Value];
+ result = [ITSendAEWithString(@"'----':obj { form:'prop', want:type('prop'), seld:type('pPlS'), from:'null'() }", 'core', 'getd', &savedPSN) typeCodeValue];
switch (result)
{
case 'kPSP':
}*/
//Full source awareness
-- (NSArray *)playlists
+/*- (NSArray *)playlists
{
unsigned long i, k;
SInt32 numSources = [ITSendAEWithString(@"kocl:type('cSrc'), '----':()", 'core', 'cnte', &savedPSN) int32Value];
ITDebugLog(@"Source at index %i disappeared.", k);
}
}
+ NSLog(@"playlists: %@", allSources);
ITDebugLog(@"Finished getting playlists.");
return [allSources autorelease];
+}*/
+
+- (NSArray *)playlists
+{
+ SInt32 numSources = [ITSendAEWithString(@"kocl:type('cSrc'), '----':()", 'core', 'cnte', &savedPSN) int32Value];
+ NSMutableArray *sources = [[NSMutableArray alloc] init];
+ int i;
+
+ ITDebugLog(@"Getting playlists.");
+ if (numSources == 0) {
+ [sources release];
+ ITDebugLog(@"No sources.");
+ return nil;
+ }
+
+ //Loop through each source
+ for (i = 1; i <= numSources; i++) {
+ SInt32 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) int32Value]; //Type of the current source
+ 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
+ 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
+ ITMTRemotePlayerSource class; //The class of the current source
+
+ //Make a new PlaylistNode for this source
+ PlaylistNode *sourceNode = [PlaylistNode playlistNodeWithName:sourceName type:ITMTSourceNode index:index];
+
+ switch (fourcc) {
+ case 'kTun':
+ class = ITMTRemoteRadioSource;
+ break;
+ case 'kDev':
+ class = ITMTRemoteGenericDeviceSource;
+ break;
+ case 'kPod':
+ class = ITMTRemoteiPodSource;
+ break;
+ case 'kMCD':
+ case 'kACD':
+ class = ITMTRemoteCDSource;
+ break;
+ case 'kShd':
+ class = ITMTRemoteSharedLibrarySource;
+ break;
+ case 'kUnk':
+ case 'kLib':
+ default:
+ class = ITMTRemoteLibrarySource;
+ break;
+ }
+ [sourceNode setSourceType:class];
+ ITDebugLog(@"New source %@ of type %i at index %i", sourceName, class, index);
+
+ int j;
+ 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
+
+ //Pass 1, add all the playlists into the main array
+ for (j = 1; j <= numPlaylists; j++) {
+ 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];
+ 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];
+ NSString *theObj = [ITSendAEWithString(sendStr, 'core', 'getd', &savedPSN) stringValue], *parent = [ITSendAEWithString(parentSendStr, 'core', 'getd', &savedPSN) stringValue];
+ ITDebugLog(@" - Adding playlist %@", theObj);
+ if (theObj) {
+ 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];
+ ITMTNodeType type;
+ switch (code) {
+ case 'kSpN':
+ type = ITMTPlaylistNode;
+ break;
+ case 'kSpF':
+ type = ITMTFolderNode;
+ break;
+ case 'kSpS':
+ type = ITMTPartyShuffleNode;
+ break;
+ case 'kSpP':
+ type = ITMTPodcastsNode;
+ break;
+ case 'kSpM':
+ type = ITMTPurchasedMusicNode;
+ break;
+ case 'kSpV':
+ type = ITMTVideosNode;
+ break;
+ }
+ PlaylistNode *node = [PlaylistNode playlistNodeWithName:theObj type:type index:j];
+ [[sourceNode children] addObject:node];
+ if (parent) {
+ 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];
+ [node setParent:[PlaylistNode playlistNodeWithName:parent type:ITMTFolderNode index:parentIndex]];
+ } else {
+ [node setParent:sourceNode];
+ }
+ }
+ }
+
+ //Pass 2, nest each item under its proper parent. Once everything has been nested, delete the original from the main array.
+ NSEnumerator *enumerator = [[sourceNode children] objectEnumerator];
+ PlaylistNode *nextNode;
+ NSMutableArray *nested = [[NSMutableArray alloc] init];
+
+ while ( (nextNode = [enumerator nextObject]) ) {
+ PlaylistNode *pNode = [nextNode parent];
+ if ([pNode type] == ITMTFolderNode) {
+ PlaylistNode *newParent = nil;
+ int k;
+ for (k = 0; !newParent; k++) {
+ PlaylistNode *test = [[sourceNode children] objectAtIndex:k];
+ if ([test index] == [pNode index]) {
+ newParent = test;
+ }
+ }
+ [nextNode setParent:newParent];
+ [[newParent children] addObject:nextNode];
+ [newParent setType:ITMTFolderNode];
+ [nested addObject:nextNode];
+ }
+ }
+
+ NSEnumerator *nestEnumerator = [nested objectEnumerator];
+ while ( (nextNode = [nestEnumerator nextObject]) ) {
+ [[sourceNode children] removeObject:nextNode];
+ }
+ [nested release];
+
+ //Move all the folders to the beginning of the list
+ //Move the podcasts playlist to the top
+ BOOL movedPodcasts = NO;
+ enumerator = [[sourceNode children] reverseObjectEnumerator];
+ while ( (nextNode = [enumerator nextObject]) ) {
+ if ([nextNode type] == ITMTPodcastsNode) {
+ [nextNode retain];
+ [[sourceNode children] removeObject:nextNode];
+ [[sourceNode children] insertObject:nextNode atIndex:1];
+ movedPodcasts = YES;
+ } else if ([nextNode type] == ITMTFolderNode) {
+ [nextNode retain];
+ [[sourceNode children] removeObject:nextNode];
+ [[sourceNode children] insertObject:nextNode atIndex:1 + movedPodcasts];
+ }
+ }
+
+ [sources addObject:sourceNode];
+ }
+
+ return [sources autorelease];
}
- (NSArray *)artists
ITDebugLog(@"Getting current source.");
- 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];
+ 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) int32Value] : 'kLib';
switch (fourcc) {
case 'kTun':
{
int temp1;
ITDebugLog(@"Getting current playlist index.");
- 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];
+ 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);
ITDebugLog(@"Getting current playlist index done.");
return temp1;
}
NSString *temp1;
ITDebugLog(@"Getting current unique identifier.");
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);
- if (descriptor == nil) {
+ if ([descriptor int32Value] == 'prop') {
+ return @"0-0";
+ } else if (descriptor == nil) {
return nil;
}
SInt32 cls = [descriptor int32Value];
{
int temp1;
ITDebugLog(@"Getting current song index.");
- 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];
+ 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);
ITDebugLog(@"Getting current song index done.");
return temp1;
}
{
NSString *temp1;
ITDebugLog(@"Getting current song title.");
-
+ SInt32 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) int32Value];
+
//If we're listening to the radio.
- 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') {
+ if (result == 'cURT') {
NSString *bad = [NSString stringWithUTF8String:"浳湧"];
temp1 = [ITSendAEWithKey('pStT', 'core', 'getd', &savedPSN) stringValue];
if ([temp1 isEqualToString:bad]) {
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];
}
temp1 = [temp1 stringByAppendingString:@" (Stream)"];
- } else {
+ } else if (result == 'prop') {
+ temp1 = nil;
+ } else {
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];
}
ITDebugLog(@"Getting current song title done.");
- (NSImage *)currentSongAlbumArt
{
ITDebugLog(@"Getting current song album art.");
- 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];
+ 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;
ITDebugLog(@"Getting current song album art done.");
if (data) {
return [[[NSImage alloc] initWithData:data] autorelease];
{
float temp1;
ITDebugLog(@"Getting current song rating.");
- 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);
- if ( [self currentPlaylistClass] == ITMTRemotePlayerRadioPlaylist ) { temp1 = -1.0; }
+ 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);
ITDebugLog(@"Getting current song rating done.");
return temp1;
}
- (BOOL)shuffleEnabled
{
+ int result;
ITDebugLog(@"Getting shuffle enabled status.");
- BOOL final;
- 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];
- if (result != 0) {
- final = YES;
- } else {
- final = NO;
- }
+ if (![self isPlaying]) {
+ ITDebugLog(@"No current playlist, getting shuffle status from visible playlist.");
+ 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];
+ } else {
+ 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];
+ }
ITDebugLog(@"Getting shuffle enabled status done.");
- return final;
+ return (result != 0);
}
- (BOOL)setShuffleEnabled:(BOOL)enabled
{
ITDebugLog(@"Set shuffle enabled to %i", enabled);
- 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);
+ if (![self isPlaying]) {
+ ITDebugLog(@"No current playlist, setting shuffle status on visible playlist.");
+ 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);
+ } else {
+ 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);
+ }
ITDebugLog(@"Set shuffle enabled to %i done", enabled);
return YES;
}
{
FourCharCode m00f = 0;
int result = 0;
- 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];
- ITDebugLog(@"Getting repeat mode.");
+ ITDebugLog(@"Getting repeat mode.");
+ 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];
+
+ if (m00f == 0) {
+ ITDebugLog(@"No current playlist, getting repeat mode from visible playlist.");
+ 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];
+ }
+
switch (m00f)
{
//case 'kRp0':
m00f = "kRp0";
break;
}
- 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);
+ if (![self isPlaying]) {
+ ITDebugLog(@"No current playlist, setting repeat mode on visible playlist.");
+ 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);
+ } else {
+ 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);
+ }
ITDebugLog(@"Setting repeat mode to %c done", m00f);
return YES;
}
- (BOOL)goToPreviousSong
{
ITDebugLog(@"Go to previous track");
- ITSendAE('hook', 'Prev', &savedPSN);
+ ITSendAE('hook', 'Back', &savedPSN);
ITDebugLog(@"Go to previous track done");
return YES;
}
//Duplicate search results to playlist
for (i = 1; i <= [searchResults numberOfItems]; i++) {
+ //NSLog(@"%@", ITSendAEWithStringAndParameter(@"'----':obj { form:'prop', want:type('prop'), seld:prop('pnam'), from:aevt(@) }", *[[searchResults descriptorAtIndex:i] aeDesc], 'core', 'getd', &savedPSN));
+
ITSendAEWithStringAndObject(@"insh:obj { form:'name', want:type('cPly'), seld:\"MenuTunes\", from:'null'() }", [[searchResults descriptorAtIndex:i] aeDesc], 'core', 'clon', &savedPSN);
}
//Reset fixed indexing
return YES;
}
+- (BOOL)isPlaying
+{
+ 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) int32Value] != 'prop');
+}
+
+- (void)notificationHandler:(NSNotification *)note
+{
+ ITDebugLog(@"Received notification: %@", note);
+ [[NSNotificationCenter defaultCenter] postNotificationName:@"ITMTTrackChanged" object:self userInfo:[note userInfo]];
+ ITDebugLog(@"Handled notification.");
+}
+
- (ProcessSerialNumber)iTunesPSN
{
/*NSArray *apps = [[NSWorkspace sharedWorkspace] launchedApplications];