3

I've created a button which takes a selected album's store id and puts it in a queue for the music player, but for some reason, it does not play and returns the following error:

Failed to prepareToPlay error: Error Domain=MPMusicPlayerControllerErrorDomain Code=6

Here is the code for the button (I put the player vars in there to be easier for here)

var storeIds: [String] = [ "ID" ]
Button(action: {
    let player = MPMusicPlayerController.applicationQueuePlayer
    let queue  = MPMusicPlayerStoreQueueDescriptor(storeIDs: storeIds)
    storeIds = ["\(album.id)".replacingOccurrences(of: "l.", with: "")]
    
    print("ID: ", storeIds) // Example ID:  ["Qn4Bnha"]
    player.setQueue(with: storeIds)
    player.play()
})

Also, I remove the "l." from the id because every album starts with that which is not needed.

Papi
  • 255
  • 1
  • 2
  • 13
  • Do any of the answers to [this question](https://stackoverflow.com/questions/60887368/mpmusicplayercontroller-applicationqueueplayer-bugs-in-ios-13-4) help? – Coder-256 Jan 09 '22 at 13:40
  • Is your simulator iOS version later than `10.1`? If not, you need to use `player.setQueue(with: MPMusicPlayerStoreQueueDescriptor(query:))` and then call `player.prepareToPlay{ (error) in ...}` before calling `player.play()` – Pierre Janineh Jan 10 '22 at 09:10
  • I am using a physical device (my own iPhone) to test it – Papi Jan 10 '22 at 16:58

1 Answers1

4

If you're trying to play an album from the library, then I had problems with that as well.

From what I've noticed, the MusicItemID of a library song is different from an album song, and the player cannot play it. The same goes in the case of a library album. If I get the id of the library song and send another request to - https://api.music.apple.com/v1/me/library/albums/{id}/catalog, And then set it to the queue; it works fine.

You can get the album's local ID and then make another request to the catalog as a workaround. If there's an album on Apple Music, then it should work.

Here's an example that works fine for me:

do {
  /// First request to get the heavy rotation albums
  guard let url = URL(string: "https://api.music.apple.com/v1/me/history/heavy-rotation") else { return }
  
  let request = MusicDataRequest(urlRequest: URLRequest(url: url))
  let response = try await request.response()
  
  let heavyRotationAlbums = try JSONDecoder().decode(MusicItemCollection<Album>.self, from: response.data)
  
  /// Get the first album
  guard let album = heavyRotationAlbums.first else { return }
  
  /// Get the local album ID
  let albumID = album.id

  /// Another request to get the album from Apple Music Catalog
  guard let catalogURL = URL(string: "https://api.music.apple.com/v1/me/library/albums/\(albumID)/catalog") else { return }

  let catalogRequest = MusicDataRequest(urlRequest: URLRequest(url: catalogURL))
  let catalogResponse = try await catalogRequest.response()

  let albums = try JSONDecoder().decode(MusicItemCollection<Album>.self, from: catalogResponse.data)

  /// Get the same album, but with the catalog ID
  guard let catalogAlbum = albums.first else { return }

  /// Encode the parameters 
  let data = try JSONEncoder().encode(catalogAlbum.playParameters)

  /// Decode the parameters to `MPMusicPlayerPlayParameters`
  let playParameters = try JSONDecoder().decode(MPMusicPlayerPlayParameters.self, from: data)
  
  // Create the queue
  let queue = MPMusicPlayerPlayParametersQueueDescriptor(playParametersQueue: [playParameters])
  
  let player = MPMusicPlayerController.applicationMusicPlayer

  /// Set the queue
  player.setQueue(with: queue)
  try await player.prepareToPlay()

  /// Finally, play the album!
  player.play()
} catch {
  print(error)
}
Rudrank Riyam
  • 588
  • 5
  • 13