So I think the playback time issue (audio being skipped) when I pause both the playerNode and the audio engine is that when resuming the playback...I call a helper method that does something like this:
-(void)resume
{
if (!self.playerNode.isPlaying)
{
[self _startAudioEngineIfNotRunningAndConnectPlayerNodeToMainMixer];
}
else
{
// Already playing.
}
}
Which has a check like
-(BOOL)_startAudioEngineIfNotRunningAndConnectPlayerNodeToMainMixer
if (!self.audioEngine.isRunning)
{
// connect the player node to the main mixer node and start the engine..
//code here...
}
else
{
// engine already running...
return YES;
}
If I modify the _startAudioEngineIfNotRunningAndConnectPlayerNodeToMainMixer to include this check:
NSArray<AVAudioConnectionPoint *> *connections = [engine outputConnectionPointsForNode:playerNode outputBus:0];
if (connections.count > 0) {
// player node already connected... only need to start the engine
}
else{
// connect the player node...
}
Playback position isn't lost on resume. So that's good. When I deactivated the audio session and got that AVAudioSessionErrorCodeIsBusy error perhaps the system paused the audio session and returned that error to tell me about my "incorrect API use."
In regards to my initial issue regarding the MPRemoteCommandCenter I think what I'm going to do is this:
Only pause the player node in my -pause method and keep the audio session running if my app is in the foreground.
When/if my app is moved to the background if my player node is paused I'll pause the audio engine as well and deactivate the audio session for the sake of getting the 'now playing center' to update the toggle play-pause button image. Since this is async and in a background task I have to hope it runs and updates the now playing center button before the user can see it
I'm still thinking about this: I don't think this is currently possible...but I'm not sure if there is ever a situation where my app can be on screen at the same time as the "Now Playing Center" in a multi-window situation. If so the play-pause toggle button will have the wrong image until my app is backgrounded. So there is that, if that's even possible but I don't think I have any other options?
--
Perhaps my thinking is naive but I think this could be a lot easier if the system just read the MPNowPlayingInfoCenter.playbackState property on iOS instead of inferring it from AVAudioSession. If I don't own the now playing center who cares what I set the .playbackState property to? Feels like the system is in a better position to make a decision of whether or not my audio session should be deactivated than I am. But I have to explicitly deactivate my audio session when my app is backgrounded every time (if my audio is paused).