I am currently writing an app extension for Spotify that allows me to control the playback. I am using the Spotify AppleScript API in combination with the Scripting Bridge in Objective-C. The first thing I would like to ask,does the Scripting API support Key Value Observing? Because when I add an observer I don't get any notifications from the API and when I try to get data manually from the Scripting API I always get nil values,why? I have the following code:
-(id)init
{
self=[super init];
if(self)
{
spotify=[SBApplication applicationWithBundleIdentifier:@"com.spotify.client"];
//Not sure if KVO is implemented,so I use this to get data from the API
timer=[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(observeValueForKeyPath) userInfo:nil repeats:YES];
if([self isSpotifyRunning])
{
//Useless?
[spotify addObserver:self forKeyPath:@"currentTrack" options:NSKeyValueObservingOptionNew context:nil];
[spotify addObserver:self forKeyPath:@"playerPosition" options:NSKeyValueObservingOptionNew context:nil];
[spotify addObserver:self forKeyPath:@"playerState" options:NSKeyValueObservingOptionNew context:nil];
[self.playBackSlider setTarget:self];
[self.playBackSlider setAction:@selector(sliderDidMove:)];
if(spotify.playerState==SpotifyEPlSPaused||spotify.playerState==SpotifyEPlSStopped)
{
[self.playButton setStringValue:@"Play"];
}
else
{
[self.playButton setStringValue:@"Stop"];
}
}
}
return self;
}
-(void)observeValueForKeyPath
{
[self.titleTextField setStringValue:spotify.currentTrack.name];
[self.artistTextField setStringValue:spotify.currentTrack.artist];
[self.currentPlayBackPositionTextField setStringValue:[self formatTime:spotify.playerPosition]];
[self.remainingTimeTextField setStringValue:[self formatTime:spotify.currentTrack.duration]];
[self.playBackSlider setMaxValue:spotify.currentTrack.duration];
[self.playBackSlider setDoubleValue:spotify.playerPosition];
[self.playBackSlider setDoubleValue:spotify.playerPosition];
[self.currentPlayBackPositionTextField setStringValue:[self formatTime:spotify.playerPosition]];
if(spotify.playerState==SpotifyEPlSPaused||spotify.playerState==SpotifyEPlSStopped)
{
[self.playButton setStringValue:@"Play"];
}
else
{
[self.playButton setStringValue:@"Stop"];
}
}
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context
{
if([keyPath isEqualToString:@"currentTrack"])
{
[self.titleTextField setStringValue:spotify.currentTrack.name];
[self.artistTextField setStringValue:spotify.currentTrack.artist];
[self.currentPlayBackPositionTextField setStringValue:[self formatTime:spotify.playerPosition]];
[self.remainingTimeTextField setStringValue:[self formatTime:spotify.currentTrack.duration]];
[self.playBackSlider setMaxValue:spotify.currentTrack.duration];
[self.playBackSlider setDoubleValue:spotify.playerPosition];
}
else if([keyPath isEqualToString:@"playerPosition"])
{
[self.playBackSlider setDoubleValue:spotify.playerPosition];
[self.currentPlayBackPositionTextField setStringValue:[self formatTime:spotify.playerPosition]];
}
else if([keyPath isEqualToString:@"playerState"])
{
if(spotify.playerState==SpotifyEPlSPaused||spotify.playerState==SpotifyEPlSStopped)
{
[self.playButton setStringValue:@"Stop"];
}
else
{
[self.playButton setStringValue:@"Play"];
}
}
}
EDIT: I have set a delegate for the SBApplication Object and I get the following error:
Error Domain=NSOSStatusErrorDomain Code=-600 "procNotFound: no eligible process with specified descriptor" UserInfo={ErrorNumber=-600}
What exactly does that mean? Spotify starts when the SBApplication is created,so why is the SBApplication telling me that it didn't found the process? I also took a look at Info.plist in the Spotify Bundle and it is scriptable, so why is it not working?
Thank you in advance for any help!
The AppleScript scripting dictionary of any application – what you're calling AppleScript API - doesn't support KVO.
Regarding to use the scripting dictionary in Cocoa apps forget ScriptingBridge
.
AppleScriptObjC
(introduced in 10.6 Snow Leopard) provides a much easier way to interact with AppleScript. You can even write a Cocoa application completely in AppleScriptObjC using AppleScript and a Objective-C like terminology in the same file.