Detect the end of queue in MPMusicPlayerController

Hello, this is building off of another post in which several other posters and I had already attempted solving the issue in hacky ways. I am using MPMusicPlayerController.applicationQueuePlayer.

My end goal here is to dynamically add items to the queue when it has ended based on my application's business logic. There is no way for me to know what these items will be when I am initially setting the queue.

I have an updated implementation that seems to cover most edge cases, except for a glaringly obvious one – if there is just one item in the queue, and the user skips the track via MPRemoteCommandCenter (eg. lock screen), then it does not work.

Currently, when I receive a MPMusicPlayerControllerPlaybackStateDidChange notification, I run this block:

        if player.playbackState == .paused,
           player.currentPlaybackTime == 0,
           player.indexOfNowPlayingItem == 0 {
            EndOfQueueManager.handle()
        }

In the absence of a mechanism to detect the end of the queue from the framework, I would love to add the ability to add a target to MPRemoteCommand, like you can do for AVPlayer. I have tried to do exactly that, but it does not work:

MPRemoteCommandCenter.shared().nextTrackCommand.addTarget { (event) -> MPRemoteCommandHandlerStatus in
        if queue.count == 1 {
            EndOfQueueManager.handle()
        }
        return .success
}

I already have a functioning AVPlayer implementation that achieves my goal without any compromises or edge cases. I would be very disappointed if there is no way to do this with MPMusicPlayerController – being notified about the queue ending feels like a fairly rudimentary API hook.

Boosting this. I'm using MusicKit and need to detect the end of the queue.

Trying to find a pattern to work around it, I'm observing changes in ApplicationMusicPlayer's state and I see that when the queue ends, queue.currentEntry matches the last entry in the queue and playbackTime is nearly zero, say less than 0.01.

But it gets more complicated, because when first playing the queue it also for a moment gets into paused state for the first track with playbackTime 0, and it could happen that I have a 1-track queue so that is also the last track in the queue. Which means by the pattern described above I'd wrongfully assume the queue has ended.

Looking for a solution to that, I found that this initial paused state is a transition from a stopped state, so if I only apply the logic above when the transition is from playing to paused, I should be good.

I'm not sure yet this is going to work OK in different platforms, right now I'm testing on Mac OS 14.5.

But we shouldn't have to deal with this. We simply need to be notified somehow that the queue has ended.

Detect the end of queue in MPMusicPlayerController
 
 
Q