+/* Copyright (c) 2002 - 2003 by iThink Software. All Rights Reserved. */
+
#import "iTunesRemote.h"
+
@implementation iTunesRemote
-+ (id)remote
-{
++ (id)remote {
return [[[iTunesRemote alloc] init] autorelease];
}
-- (NSString *)title
-{
- return @"iTunes Plug-in";
-}
-
-- (NSString *)information;
-{
- return @"Default MenuTunes plugin to control iTunes. Written by iThink Software.";
+- (id)valueOfProperty:(ITMTRemoteProperty)property {
+ // Get from Info.plist
+ return nil;
}
-- (NSImage *)icon
-{
+- (NSDictionary *)propertiesAndValues {
+ // Get from Info.plist
return nil;
}
-- (BOOL)begin
-{
- iTunesPSN = [self iTunesPSN];
-
- //We won't need this once we're pure AEs
- asComponent = OpenDefaultComponent(kOSAComponentType, kAppleScriptSubtype);
-
- //Register for application termination in NSWorkspace
- [[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:self selector:@selector(applicationLaunched:) name:NSWorkspaceDidLaunchApplicationNotification object:nil];
- [[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:self selector:@selector(applicationTerminated:) name:NSWorkspaceDidTerminateApplicationNotification object:nil];
-
- return YES;
+- (ITMTPlayerStyle)playerStyle {
+ return ITMTSinglePlayerStyle;
}
-- (BOOL)halt
-{
- iTunesPSN.highLongOfPSN = kNoProcess;
-
- //We won't need this once we're pure AEs
- CloseComponent(asComponent);
-
- //Unregister for application termination in NSWorkspace
- [[[NSWorkspace sharedWorkspace] notificationCenter] removeObserver:self];
-
- return YES;
-}
-
-- (BOOL)isAppRunning
-{
- NSArray *apps = [[NSWorkspace sharedWorkspace] launchedApplications];
- int i,count = [apps count];
-
- for (i = 0; i < count; i++) {
- if ([[[apps objectAtIndex:i] objectForKey:@"NSApplicationName"]
- isEqualToString:@"iTunes"]) {
+- (BOOL)activate {
+ if ( !_activated ) {
+ if ( [self iTunesIsRunning] ) {
+ _currentPSN = [self iTunesPSN];
+ } else {
+ if ( [self launchiTunes] ) {
+ _currentPSN = [self iTunesPSN];
+ } else {
+ return NO;
+ }
+ }
+ if ( ( _player = [iTunesPlayer sharedPlayerForRemote:self] ) ) {
+ _activated = YES;
return YES;
}
+ } else {
+ return NO;
}
- return NO;
}
-- (PlayerState)playerState
-{
- NSString *result = [self runScriptAndReturnResult:@"get player state"];
-
- if ([result isEqualToString:@"playing"]) {
- return playing;
- } else if ([result isEqualToString:@"paused"]) {
- return paused;
- } else if ([result isEqualToString:@"stopped"]) {
- return stopped;
- } else if ([result isEqualToString:@"rewinding"]) {
- return rewinding;
- } else if ([result isEqualToString:@"fast forwarding"]) {
- return forwarding;
+- (BOOL)deactivate {
+ if ( _activated ) {
+ _currentPSN = kNoProcess;
+ _player = nil;
+ _activated = NO;
+ return YES;
+ } else {
+ return NO;
}
-
- return stopped;
}
-- (NSArray *)playlists
-{
- int i;
- int numPresets = [[self runScriptAndReturnResult:@"get number of playlists"] intValue];
- NSMutableArray *presets = [[NSMutableArray alloc] init];
- for (i = 1; i <= numPresets; i++) {
- [presets addObject:[self runScriptAndReturnResult:[NSString stringWithFormat:@"get name of playlist %i", i]]];
+- (ITMTPlayer *)currentPlayer {
+ if (_activated) {
+ return _player;
+ } else {
+ return nil;
}
- return [presets autorelease];
-}
-
-- (int)numberOfSongsInPlaylistAtIndex:(int)index
-{
- NSString *result = [self runScriptAndReturnResult:[NSString stringWithFormat:@"get number of tracks in playlist %i", index]];
- return [result intValue];
-}
-
-- (NSString *)classOfPlaylistAtIndex:(int)index
-{
- //Not working yet. It returns the 4 character code instead of a name.
- int realResult = [[ITAppleEventCenter sharedCenter]
- sendTwoTierAEWithRequestedKeyForNumber:@"pcls"
- fromObjectByKey:@"pPla" eventClass:@"core" eventID:@"getd"
- appPSN:[self iTunesPSN]];
-
- //result = [self runScriptAndReturnResult:[NSString stringWithFormat:@"get class of playlist %i", index]];
- if (realResult == 'cRTP') return @"radio tuner playlist";
- else return @"playlist";
-}
-
-- (int)currentPlaylistIndex
-{
- int result;
- result = [[ITAppleEventCenter sharedCenter]
- sendTwoTierAEWithRequestedKeyForNumber:@"pidx"
- fromObjectByKey:@"pPla" eventClass:@"core" eventID:@"getd"
- appPSN:[self iTunesPSN]];
- return result;
-}
-
-- (NSString *)songTitleAtIndex:(int)index
-{
- NSString *result = [self runScriptAndReturnResult:[NSString stringWithFormat:@"get name of track %i of current playlist", index]];
- return result;
-}
-
-- (int)currentSongIndex
-{
- int result;
- result = [[ITAppleEventCenter sharedCenter]
- sendTwoTierAEWithRequestedKeyForNumber:@"pidx"
- fromObjectByKey:@"pTrk" eventClass:@"core" eventID:@"getd"
- appPSN:[self iTunesPSN]];
- return result;
-}
-
-- (NSString *)currentSongTitle
-{
- return [[ITAppleEventCenter sharedCenter] sendTwoTierAEWithRequestedKey:@"pnam"
- fromObjectByKey:@"pTrk" eventClass:@"core" eventID:@"getd"
- appPSN:[self iTunesPSN]];
-}
-
-- (NSString *)currentSongArtist
-{
- return [[ITAppleEventCenter sharedCenter] sendTwoTierAEWithRequestedKey:@"pArt"
- fromObjectByKey:@"pTrk" eventClass:@"core" eventID:@"getd"
- appPSN:[self iTunesPSN]];
-}
-
-- (NSString *)currentSongAlbum
-{
- return [[ITAppleEventCenter sharedCenter] sendTwoTierAEWithRequestedKey:@"pAlb"
- fromObjectByKey:@"pTrk" eventClass:@"core" eventID:@"getd"
- appPSN:[self iTunesPSN]];
-}
-
-- (NSString *)currentSongGenre
-{
- return [[ITAppleEventCenter sharedCenter] sendTwoTierAEWithRequestedKey:@"pGen"
- fromObjectByKey:@"pTrk" eventClass:@"core" eventID:@"getd"
- appPSN:[self iTunesPSN]];
-}
-
-- (NSString *)currentSongLength
-{
- return [[ITAppleEventCenter sharedCenter] sendTwoTierAEWithRequestedKey:@"pTim"
- fromObjectByKey:@"pTrk" eventClass:@"core" eventID:@"getd"
- appPSN:[self iTunesPSN]];
}
-- (NSString *)currentSongRemaining
-{
- long duration = [[ITAppleEventCenter sharedCenter]
- sendTwoTierAEWithRequestedKeyForNumber:@"pDur"
- fromObjectByKey:@"pTrk" eventClass:@"core" eventID:@"getd"
- appPSN:[self iTunesPSN]];
- long current = [[ITAppleEventCenter sharedCenter]
- sendAEWithRequestedKeyForNumber:@"pPos"
- eventClass:@"core" eventID:@"getd"
- appPSN:[self iTunesPSN]];
-
- return [[NSNumber numberWithLong:duration - current] stringValue];
-}
-
-- (NSArray *)eqPresets;
-{
- int i;
- int numPresets = [[self runScriptAndReturnResult:@"get number of EQ presets"] intValue];
- NSMutableArray *presets = [[NSMutableArray alloc] init];
-
- for (i = 1; i <= numPresets; i++) {
- [presets addObject:[self runScriptAndReturnResult:[NSString stringWithFormat:@"get name of EQ preset %i", i]]];
+- (NSArray *)players {
+ if (_activated) {
+ return [NSArray arrayWithObject:_player];
+ } else {
+ return nil;
}
-
- return [presets autorelease];
}
-- (int)currentEQPresetIndex
-{
- int result;
- result = [[ITAppleEventCenter sharedCenter]
- sendTwoTierAEWithRequestedKeyForNumber:@"pidx"
- fromObjectByKey:@"pEQP" eventClass:@"core" eventID:@"getd"
- appPSN:[self iTunesPSN]];
- return result;
-}
-
-- (BOOL)play
-{
- [[ITAppleEventCenter sharedCenter] sendAEWithEventClass:@"hook" eventID:@"Play"
- appPSN:[self iTunesPSN]];
- return YES;
-}
-
-- (BOOL)pause
-{
- [[ITAppleEventCenter sharedCenter] sendAEWithEventClass:@"hook" eventID:@"Paus"
- appPSN:[self iTunesPSN]];
- return YES;
-}
-
-- (BOOL)goToNextSong
-{
- [[ITAppleEventCenter sharedCenter] sendAEWithEventClass:@"hook" eventID:@"Next"
- appPSN:[self iTunesPSN]];
- return YES;
-}
-
-- (BOOL)goToPreviousSong
-{
- [[ITAppleEventCenter sharedCenter] sendAEWithEventClass:@"hook" eventID:@"Prev"
- appPSN:[self iTunesPSN]];
- return YES;
-}
-
-- (BOOL)fastForward
-{
- [[ITAppleEventCenter sharedCenter] sendAEWithEventClass:@"hook" eventID:@"Fast"
- appPSN:[self iTunesPSN]];
- return YES;
-}
-
-- (BOOL)rewind
-{
- [[ITAppleEventCenter sharedCenter] sendAEWithEventClass:@"hook" eventID:@"Rwnd"
- appPSN:[self iTunesPSN]];
- return YES;
-}
-
-
-- (BOOL)switchToPlaylistAtIndex:(int)index
-{
- [self runScriptAndReturnResult:[NSString stringWithFormat:
- @"play playlist %i", index]];
- return NO;
-}
+#pragma mark -
+#pragma mark INTERNAL METHODS
+#pragma mark -
-- (BOOL)switchToSongAtIndex:(int)index
-{
- [self runScriptAndReturnResult:[NSString stringWithFormat:
- @"play track %i of current playlist", index]];
+- (BOOL)launchiTunes {
return NO;
}
-- (BOOL)switchToEQAtIndex:(int)index
-{
- [self runScriptAndReturnResult:[NSString stringWithFormat:
- @"set current EQ preset to EQ preset %i", index]];
- [self runScriptAndReturnResult:@"set EQ enabled to 1"];
+- (BOOL)iTunesIsRunning {
return NO;
}
- (ProcessSerialNumber)iTunesPSN
{
- NSArray *apps = [[NSWorkspace sharedWorkspace] launchedApplications];
ProcessSerialNumber number;
- int i, count = [apps count];
-
number.highLongOfPSN = kNoProcess;
-
- for (i = 0; i < count; i++)
+ number.lowLongOfPSN = 0;
+
+ while ( (GetNextProcess(&number) == noErr) )
{
- NSDictionary *curApp = [apps objectAtIndex:i];
-
- if ([[curApp objectForKey:@"NSApplicationName"] isEqualToString:@"iTunes"])
+ CFStringRef name;
+ if ( (CopyProcessName(&number, &name) == noErr) )
{
- number.highLongOfPSN = [[curApp objectForKey:@"NSApplicationProcessSerialNumberHigh"] intValue];
- number.lowLongOfPSN = [[curApp objectForKey:@"NSApplicationProcessSerialNumberLow"] intValue];
+ if ([(NSString *)name isEqualToString:@"iTunes"])
+ {
+ return number;
+ }
+ [(NSString *)name release];
}
}
return number;
}
-- (void)applicationLaunched:(NSNotification *)note
-{
- NSDictionary *info = [note userInfo];
-
- if ([[info objectForKey:@"NSApplicationName"] isEqualToString:@"iTunes"]) {
- iTunesPSN.highLongOfPSN = [[info objectForKey:@"NSApplicationProcessSerialNumberHigh"] longValue];
- iTunesPSN.lowLongOfPSN = [[info objectForKey:@"NSApplicationProcessSerialNumberLow"] longValue];
-
- [[NSNotificationCenter defaultCenter] postNotificationName:@"ITMTRemoteAppDidLaunchNotification" object:nil];
- }
-}
-
-- (void)applicationTerminated:(NSNotification *)note
-{
- NSDictionary *info = [note userInfo];
-
- if ([[info objectForKey:@"NSApplicationName"] isEqualToString:@"iTunes"]) {
- iTunesPSN.highLongOfPSN = kNoProcess;
- [[NSNotificationCenter defaultCenter] postNotificationName:@"ITMTRemoteAppDidTerminateNotification" object:nil];
- }
-}
-
-//This is just temporary
-- (NSString *)runScriptAndReturnResult:(NSString *)script
-{
- AEDesc scriptDesc, resultDesc;
- Size length;
- NSString *result;
- Ptr buffer;
-
- script = [NSString stringWithFormat:@"tell application \"iTunes\"\n%@\nend tell", script];
-
- //NSLog(@"I say \"%@\"",script);
-
- AECreateDesc(typeChar, [script cString], [script cStringLength],
- &scriptDesc);
-
- OSADoScript(asComponent, &scriptDesc, kOSANullScript, typeChar, kOSAModeCanInteract, &resultDesc);
-
- length = AEGetDescDataSize(&resultDesc);
- buffer = malloc(length);
-
- AEGetDescData(&resultDesc, buffer, length);
- AEDisposeDesc(&scriptDesc);
- AEDisposeDesc(&resultDesc);
- result = [NSString stringWithCString:buffer length:length];
- if ( (! [result isEqualToString:@""]) &&
- ([result characterAtIndex:0] == '\"') &&
- ([result characterAtIndex:[result length] - 1] == '\"') ) {
- result = [result substringWithRange:NSMakeRange(1, [result length] - 2)];
- }
- free(buffer);
- buffer = nil;
- //NSLog(@"You say \"%@\"",result);
- return result;
-}
-
@end