I'm playing library items (MPMediaItem) and apple music tracks (Track) in MPMusicPlayerApplicationController.applicationQueuePlayer, but I can't use the actual Queue functionality because I can't figure out how to get both media types into the same queue. If there's a way to get both types in a single queue, that would solve my problem, but I've given up on that one.
Because I can't use a queue, I have to be able to detect when a song ends so that I can put the next song in the queue and play it. The only way I can figure out to detect when a song ends is by watching the playBackState, and I've actually got that pretty much working, but it's really ugly, because you get playBackState of paused when a song ends, and when a bluetooth speaker disconnects, etc.
The only answer I've been able to find on the internet is to watch the MPMusicPlayerControllerNowPlayingItemDidChange, and when that fires, and the nowPlayingItem is NIL, a song ends.. but that's not the case. When a song ends, the nowPlayingItem remains the same. There's got to be an answer to this problem, right?
Hello @samhall,
Thank you for your feedback about using both MusicKit and MediaPlayer frameworks.
If you really need to play both library items represented as MPMediaItem and catalog items represented by Track in the same queue, you can actually achieve that using a single player, the one from MediaPlayer, by converting the Track's playParameters into MPMusicPlayerPlayParameters. You can achieve this by leveraging the fact that both of these types conform to Codable.
Assuming you have a local variable named tracks
which is an array of Track objects from MusicKit, you can append them to the end of MPMusicPlayerController's applicationQueuePlayer's queue as follows:
let tracksPlayParametersQueue = try tracks.compactMap { track -> MPMusicPlayerPlayParameters? in
var playParameters: MPMusicPlayerPlayParameters?
if let trackPlayParameters = track.playParameters {
let encoder = JSONEncoder()
let trackPlayParametersData = try encoder.encode(trackPlayParameters)
let decoder = JSONDecoder()
playParameters = try decoder.decode(MPMusicPlayerPlayParameters.self, from: trackPlayParametersData)
}
return playParameters
}
let tracksQueueDescriptor = MPMusicPlayerPlayParametersQueueDescriptor(playParametersQueue: tracksPlayParametersQueue)
MPMusicPlayerController.applicationQueuePlayer.append(tracksQueueDescriptor)
I hope this helps.
Best regards,