Added checking to prevent cascading threads and server checks.
[MenuTunes.git] / iTunesRemote.m
index 46a01f3..b4a745c 100755 (executable)
 - (BOOL)showPrimaryInterface
 {
     ITDebugLog(@"Showing player primary interface.");
 - (BOOL)showPrimaryInterface
 {
     ITDebugLog(@"Showing player primary interface.");
-    //If not minimized and visible
-    if ( ([[ITAppleEventCenter sharedCenter] sendAEWithSendStringForNumber:@"'----':obj { form:'prop', want:type('prop'), seld:type('pMin'), from:obj { form:'indx', want:type('cBrW'), seld:1, from:'null'() } }" eventClass:@"core" eventID:@"getd" appPSN:savedPSN] == 0) &&
-         ([[ITAppleEventCenter sharedCenter] sendAEWithSendStringForNumber:@"'----':obj { form:'prop', want:type('prop'), seld:type('pvis'), from:obj { form:'indx', want:type('cBrW'), seld:1, from:'null'() } }" eventClass:@"core" eventID:@"getd" appPSN:savedPSN] != 0) &&
-         [[[[NSWorkspace sharedWorkspace] activeApplication] objectForKey:@"NSApplicationName"] isEqualToString:@"iTunes"] ) {
-        //set minimized of browser window 1 to true
-        [[ITAppleEventCenter sharedCenter] sendAEWithSendString:@"data:long(1), '----':obj { form:'prop', want:type('prop'), seld:type('pMin'), from:obj { form:'indx', want:type('cBrW'), seld:1, from:'null'() } }" eventClass:@"core" eventID:@"setd" appPSN:savedPSN];
+    
+    if ([self playerRunningState] == ITMTRemotePlayerRunning) {
+        ITDebugLog(@"Showing player interface.");
+        //If not minimized and visible
+        if ( ([[ITAppleEventCenter sharedCenter] sendAEWithSendStringForNumber:@"'----':obj { form:'prop', want:type('prop'), seld:type('pMin'), from:obj { form:'indx', want:type('cBrW'), seld:1, from:'null'() } }" eventClass:@"core" eventID:@"getd" appPSN:savedPSN] == 0) &&
+             ([[ITAppleEventCenter sharedCenter] sendAEWithSendStringForNumber:@"'----':obj { form:'prop', want:type('prop'), seld:type('pvis'), from:obj { form:'indx', want:type('cBrW'), seld:1, from:'null'() } }" eventClass:@"core" eventID:@"getd" appPSN:savedPSN] != 0) &&
+             [[[[NSWorkspace sharedWorkspace] activeApplication] objectForKey:@"NSApplicationName"] isEqualToString:@"iTunes"] ) {
+            //set minimized of browser window 1 to true
+            [[ITAppleEventCenter sharedCenter] sendAEWithSendString:@"data:long(1), '----':obj { form:'prop', want:type('prop'), seld:type('pMin'), from:obj { form:'indx', want:type('cBrW'), seld:1, from:'null'() } }" eventClass:@"core" eventID:@"setd" appPSN:savedPSN];
+        } else {
+            //set minimized of browser window 1 to false
+            [[ITAppleEventCenter sharedCenter] sendAEWithSendString:@"data:long(0), '----':obj { form:'prop', want:type('prop'), seld:type('pMin'), from:obj { form:'indx', want:type('cBrW'), seld:1, from:'null'() } }" eventClass:@"core" eventID:@"setd" appPSN:savedPSN];
+        }
+        //set visible of browser window 1 to true
+        [[ITAppleEventCenter sharedCenter] sendAEWithSendString:@"data:long(1), '----':obj { form:'prop', want:type('prop'), seld:type('pvis'), from:obj { form:'indx', want:type('cBrW'), seld:1, from:'null'() } }" eventClass:@"core" eventID:@"setd" appPSN:savedPSN];
+        //active iTunes
+        [[ITAppleEventCenter sharedCenter] sendAEWithSendString:@"data:long(1), '----':obj { form:'prop', want:type('prop'), seld:type('pisf'), from:'null'() }" eventClass:@"core" eventID:@"setd" appPSN:savedPSN];
+        ITDebugLog(@"Done showing player primary interface.");
+        return YES;
     } else {
     } else {
-        //set minimized of browser window 1 to false
-        [[ITAppleEventCenter sharedCenter] sendAEWithSendString:@"data:long(0), '----':obj { form:'prop', want:type('prop'), seld:type('pMin'), from:obj { form:'indx', want:type('cBrW'), seld:1, from:'null'() } }" eventClass:@"core" eventID:@"setd" appPSN:savedPSN];
+        NSString *path;
+        ITDebugLog(@"Launching player.");
+        if ( (path = [[NSUserDefaults standardUserDefaults] stringForKey:@"CustomPlayerPath"]) ) {
+        } else {
+            path = [self playerFullName];
+        }
+        if (![[NSWorkspace sharedWorkspace] launchApplication:path]) {
+            ITDebugLog(@"Error Launching Player");
+            return NO;
+        }
+        return YES;
     }
     }
-    //set visible of browser window 1 to true
-    [[ITAppleEventCenter sharedCenter] sendAEWithSendString:@"data:long(1), '----':obj { form:'prop', want:type('prop'), seld:type('pvis'), from:obj { form:'indx', want:type('cBrW'), seld:1, from:'null'() } }" eventClass:@"core" eventID:@"setd" appPSN:savedPSN];
-    //active iTunes
-    [[ITAppleEventCenter sharedCenter] sendAEWithSendString:@"data:long(1), '----':obj { form:'prop', want:type('prop'), seld:type('pisf'), from:'null'() }" eventClass:@"core" eventID:@"setd" appPSN:savedPSN];
-    ITDebugLog(@"Done showing player primary interface.");
-    return YES;
 }
 
 - (ITMTRemotePlayerRunningState)playerRunningState
 }
 
 - (ITMTRemotePlayerRunningState)playerRunningState
 
 //Full source awareness
 - (NSArray *)playlists
 
 //Full source awareness
 - (NSArray *)playlists
-{   unsigned long i,k;
+{
+    unsigned long i, k;
     const signed long numSources = [[ITAppleEventCenter sharedCenter] sendAEWithSendStringForNumber:@"kocl:type('cSrc'), '----':()" eventClass:@"core" eventID:@"cnte" appPSN:savedPSN];
     NSMutableArray *allSources = [[NSMutableArray alloc] init];
     
     ITDebugLog(@"Getting playlists.");
     const signed long numSources = [[ITAppleEventCenter sharedCenter] sendAEWithSendStringForNumber:@"kocl:type('cSrc'), '----':()" eventClass:@"core" eventID:@"cnte" appPSN:savedPSN];
     NSMutableArray *allSources = [[NSMutableArray alloc] init];
     
     ITDebugLog(@"Getting playlists.");
+    if (numSources == 0) {
+        ITDebugLog(@"No sources.");
+        return nil;
+    }
+    
     for (k = 1; k <= numSources ; k++) {
         const signed long numPlaylists = [[ITAppleEventCenter sharedCenter] sendAEWithSendStringForNumber:[NSString stringWithFormat:@"kocl:type('cPly'), '----':obj { form:'indx', want:type('cSrc'), seld:long(%u), from:() }",k] eventClass:@"core" eventID:@"cnte" appPSN:savedPSN];
         unsigned long fourcc = [[ITAppleEventCenter sharedCenter] sendAEWithSendStringForNumber:[NSString stringWithFormat:@"'----':obj { form:'prop', want:type('prop'), seld:type('pKnd'), from:obj { form:'indx', want:type('cSrc'), seld:long(%u), from:() } }",k] eventClass:@"core" eventID:@"getd" appPSN:savedPSN];
         NSString *sourceName = [[ITAppleEventCenter sharedCenter] sendAEWithSendString:[NSString stringWithFormat:@"'----':obj { form:'prop', want:type('prop'), seld:type('pnam'), from:obj { form:'indx', want:type('cSrc'), seld:long(%u), from:() } }",k] eventClass:@"core" eventID:@"getd" appPSN:savedPSN];
     for (k = 1; k <= numSources ; k++) {
         const signed long numPlaylists = [[ITAppleEventCenter sharedCenter] sendAEWithSendStringForNumber:[NSString stringWithFormat:@"kocl:type('cPly'), '----':obj { form:'indx', want:type('cSrc'), seld:long(%u), from:() }",k] eventClass:@"core" eventID:@"cnte" appPSN:savedPSN];
         unsigned long fourcc = [[ITAppleEventCenter sharedCenter] sendAEWithSendStringForNumber:[NSString stringWithFormat:@"'----':obj { form:'prop', want:type('prop'), seld:type('pKnd'), from:obj { form:'indx', want:type('cSrc'), seld:long(%u), from:() } }",k] eventClass:@"core" eventID:@"getd" appPSN:savedPSN];
         NSString *sourceName = [[ITAppleEventCenter sharedCenter] sendAEWithSendString:[NSString stringWithFormat:@"'----':obj { form:'prop', want:type('prop'), seld:type('pnam'), from:obj { form:'indx', want:type('cSrc'), seld:long(%u), from:() } }",k] eventClass:@"core" eventID:@"getd" appPSN:savedPSN];
-        NSNumber *sourceClass;
-        NSMutableArray *aSource = [[NSMutableArray alloc] init];
-        [aSource addObject:sourceName];
-        switch (fourcc) {
-            case 'kTun':
-                sourceClass = [NSNumber numberWithInt:ITMTRemoteRadioSource];
-                break;
-            case 'kDev':
-                sourceClass = [NSNumber numberWithInt:ITMTRemoteGenericDeviceSource];
-                break;
-            case 'kPod':
-                sourceClass = [NSNumber numberWithInt:ITMTRemoteiPodSource];
-                break;
-            case 'kMCD':
-            case 'kACD':
-                sourceClass = [NSNumber numberWithInt:ITMTRemoteCDSource];
-                break;
-            case 'kShd':
-                sourceClass = [NSNumber numberWithInt:ITMTRemoteSharedLibrarySource];
-                break;
-            case 'kUnk':
-            case 'kLib':
-            default:
-                sourceClass = [NSNumber numberWithInt:ITMTRemoteLibrarySource];
-                break;
-        }
-        ITDebugLog(@"Adding source %@ of type %i", sourceName, [sourceClass intValue]);
-        [aSource addObject:sourceClass];
-        for (i = 1; i <= numPlaylists; i++) {
-            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];
-            NSString *theObj = [[ITAppleEventCenter sharedCenter] sendAEWithSendString:sendStr eventClass:@"core" eventID:@"getd" appPSN:savedPSN];
-            ITDebugLog(@" - Adding playlist %@", theObj);
-            [aSource addObject:theObj];
+        unsigned long index = [[ITAppleEventCenter sharedCenter] sendAEWithSendStringForNumber:[NSString stringWithFormat:@"'----':obj { form:'prop', want:type('prop'), seld:type('pidx'), from:obj { form:'indx', want:type('cSrc'), seld:long(%u), from:() } }",k] eventClass:@"core" eventID:@"getd" appPSN:savedPSN];
+        unsigned long class;
+        if (sourceName) {
+            NSMutableArray *aSource = [[NSMutableArray alloc] init];
+            [aSource addObject:sourceName];
+            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;
+            }
+            ITDebugLog(@"Adding source %@ of type %i at index %i", sourceName, class, index);
+            [aSource addObject:[NSNumber numberWithInt:class]];
+            [aSource addObject:[NSNumber numberWithInt:index]];
+            for (i = 1; i <= numPlaylists; i++) {
+                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];
+                NSString *theObj = [[ITAppleEventCenter sharedCenter] sendAEWithSendString:sendStr eventClass:@"core" eventID:@"getd" appPSN:savedPSN];
+                ITDebugLog(@" - Adding playlist %@", theObj);
+                if (theObj) {
+                    [aSource addObject:theObj];
+                }
+            }
+            [allSources addObject:[aSource autorelease]];
+        } else {
+            ITDebugLog(@"Source at index %i disappeared.", k);
         }
         }
-        [allSources addObject:aSource];
-        [aSource release];
     }
     ITDebugLog(@"Finished getting playlists.");
     return [allSources autorelease];
     }
     ITDebugLog(@"Finished getting playlists.");
     return [allSources autorelease];
 
 - (ITMTRemotePlayerPlaylistClass)currentPlaylistClass
 {
 
 - (ITMTRemotePlayerPlaylistClass)currentPlaylistClass
 {
-    int realResult = [[ITAppleEventCenter sharedCenter] sendTwoTierAEWithRequestedKeyForNumber:@"pcls" fromObjectByKey:@"pPla" eventClass:@"core" eventID:@"getd" appPSN:savedPSN];
-    
+    int realResult;
     ITDebugLog(@"Getting current playlist class");
     ITDebugLog(@"Getting current playlist class");
+    realResult = [[ITAppleEventCenter sharedCenter] sendTwoTierAEWithRequestedKeyForNumber:@"pcls" fromObjectByKey:@"pPla" eventClass:@"core" eventID:@"getd" appPSN:savedPSN];
     switch (realResult)
           {
           case 'cLiP':
     switch (realResult)
           {
           case 'cLiP':
 {
     int temp1;
     ITDebugLog(@"Getting current song index.");
 {
     int temp1;
     ITDebugLog(@"Getting current song index.");
-    
-    if ([self currentSource] == ITMTRemoteRadioSource)
-    
     temp1 = [[ITAppleEventCenter sharedCenter] sendTwoTierAEWithRequestedKeyForNumber:@"pidx" fromObjectByKey:@"pTrk" eventClass:@"core" eventID:@"getd" appPSN:savedPSN];
     ITDebugLog(@"Getting current song index done.");
     return temp1;
     temp1 = [[ITAppleEventCenter sharedCenter] sendTwoTierAEWithRequestedKeyForNumber:@"pidx" fromObjectByKey:@"pTrk" eventClass:@"core" eventID:@"getd" appPSN:savedPSN];
     ITDebugLog(@"Getting current song index done.");
     return temp1;
     
     //If we're listening to the radio.
     if ([[ITAppleEventCenter sharedCenter] sendTwoTierAEWithRequestedKeyForNumber:@"pcls" fromObjectByKey:@"pTrk" eventClass:@"core" eventID:@"getd" appPSN:savedPSN] == 'cURT') {
     
     //If we're listening to the radio.
     if ([[ITAppleEventCenter sharedCenter] sendTwoTierAEWithRequestedKeyForNumber:@"pcls" fromObjectByKey:@"pTrk" eventClass:@"core" eventID:@"getd" appPSN:savedPSN] == 'cURT') {
-        temp1 = [[[ITAppleEventCenter sharedCenter] sendAEWithRequestedKey:@"pStT" eventClass:@"core" eventID:@"getd" appPSN:savedPSN] stringByAppendingString:@" (Stream)"];
+        NSString *bad = [NSString stringWithUTF8String:"浳湧"];
+        temp1 = [[ITAppleEventCenter sharedCenter] sendAEWithRequestedKey:@"pStT" eventClass:@"core" eventID:@"getd" appPSN:savedPSN];
+        if ([temp1 isEqualToString:bad]) {
+            temp1 = [[ITAppleEventCenter sharedCenter] sendTwoTierAEWithRequestedKey:@"pnam" fromObjectByKey:@"pTrk" eventClass:@"core" eventID:@"getd" appPSN:savedPSN];
+        }
+        temp1 = [temp1 stringByAppendingString:@" (Stream)"];
     } else {
         temp1 = [[ITAppleEventCenter sharedCenter] sendTwoTierAEWithRequestedKey:@"pnam" fromObjectByKey:@"pTrk" eventClass:@"core" eventID:@"getd" appPSN:savedPSN];
     }
     } else {
         temp1 = [[ITAppleEventCenter sharedCenter] sendTwoTierAEWithRequestedKey:@"pnam" fromObjectByKey:@"pTrk" eventClass:@"core" eventID:@"getd" appPSN:savedPSN];
     }
     return ( ([temp1 length]) ? temp1 : nil ) ;
 }
 
     return ( ([temp1 length]) ? temp1 : nil ) ;
 }
 
+- (NSString *)currentSongComposer
+{
+    NSString *temp1;
+    ITDebugLog(@"Getting current song artist.");
+    if ( [self currentPlaylistClass] != ITMTRemotePlayerRadioPlaylist ) {
+        temp1 = [[ITAppleEventCenter sharedCenter] sendTwoTierAEWithRequestedKey:@"pCmp" fromObjectByKey:@"pTrk" eventClass:@"core" eventID:@"getd" appPSN:savedPSN];
+    } else {
+        temp1 = @"";
+    }
+    ITDebugLog(@"Getting current song artist done.");
+    return ( ([temp1 length]) ? temp1 : nil ) ;
+}
+
 - (NSString *)currentSongAlbum
 {
     NSString *temp1;
 - (NSString *)currentSongAlbum
 {
     NSString *temp1;
     ITDebugLog(@"Getting equalizer enabled status.");
     int thingy = [[ITAppleEventCenter sharedCenter] sendAEWithSendStringForNumber:@"'----':obj { form:type('prop'), want:type('prop'), seld:type('pEQ '), from:() }" eventClass:@"core" eventID:@"getd" appPSN:savedPSN];
     ITDebugLog(@"Done getting equalizer enabled status.");
     ITDebugLog(@"Getting equalizer enabled status.");
     int thingy = [[ITAppleEventCenter sharedCenter] sendAEWithSendStringForNumber:@"'----':obj { form:type('prop'), want:type('prop'), seld:type('pEQ '), from:() }" eventClass:@"core" eventID:@"getd" appPSN:savedPSN];
     ITDebugLog(@"Done getting equalizer enabled status.");
-    return thingy;
+    return (thingy != 0) ? YES : NO;
 }
 
 - (BOOL)setEqualizerEnabled:(BOOL)enabled
 }
 
 - (BOOL)setEqualizerEnabled:(BOOL)enabled
     return YES;
 }
 
     return YES;
 }
 
-/*- (BOOL)switchToPlaylistAtIndex:(int)index ofSourceAtIndex:(int)index2
+- (BOOL)switchToPlaylistAtIndex:(int)index ofSourceAtIndex:(int)index2
 {
     ITDebugLog(@"Switching to playlist at index %i of source %i", index, index2);
     [[ITAppleEventCenter sharedCenter] sendAEWithSendString:[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] eventClass:@"hook" eventID:@"Play" appPSN:savedPSN];
     //{ form:'indx', want:type('cPly'), seld:long(%lu), from:obj { form:'indx', want:type('cSrc'), seld:long('%lu'), from:'null'() } } -- obj { form:'indx', want:type('cSrc'), seld:long(1), from:'null'() }
     ITDebugLog(@"Done switching to playlist at index %i of source %i", index, index2);
     return YES;
 {
     ITDebugLog(@"Switching to playlist at index %i of source %i", index, index2);
     [[ITAppleEventCenter sharedCenter] sendAEWithSendString:[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] eventClass:@"hook" eventID:@"Play" appPSN:savedPSN];
     //{ form:'indx', want:type('cPly'), seld:long(%lu), from:obj { form:'indx', want:type('cSrc'), seld:long('%lu'), from:'null'() } } -- obj { form:'indx', want:type('cSrc'), seld:long(1), from:'null'() }
     ITDebugLog(@"Done switching to playlist at index %i of source %i", index, index2);
     return YES;
-}*/
+}
 
 - (BOOL)switchToSongAtIndex:(int)index
 {
 
 - (BOOL)switchToSongAtIndex:(int)index
 {
         {
             if ([(NSString *)name isEqualToString:@"iTunes"])
             {
         {
             if ([(NSString *)name isEqualToString:@"iTunes"])
             {
-                ITDebugLog(@"iTunes' highLongOfPSN: %lu.", number.highLongOfPSN);
+                ITDebugLog(@"iTunes' highLPongOfPSN: %lu.", number.highLongOfPSN);
                 ITDebugLog(@"iTunes' lowLongOfPSN: %lu.", number.lowLongOfPSN);
                 ITDebugLog(@"Done getting iTunes' PSN.");
                 return number;
                 ITDebugLog(@"iTunes' lowLongOfPSN: %lu.", number.lowLongOfPSN);
                 ITDebugLog(@"Done getting iTunes' PSN.");
                 return number;