Cannot convert value of type 'PlayParameters?' to expected argument type '[MPMusicPlayerPlayParameters]'

439 Views Asked by At

I am trying to create a music player with Swift and MusicKit, but I am getting this error when trying to load up the queue with the selected album from MusicKit. I don't get why the playparameters for the album and MPMusicPlayerPlayParametersQueueDescriptor are different.

let player = MPMusicPlayerController.applicationMusicPlayer
let queue  = MPMusicPlayerPlayParametersQueueDescriptor(playParametersQueue: heavyRotation[album].playParameters)
player.prepareToPlay()
player.play()

Error on let queue line:

Cannot convert value of type 'PlayParameters?' to expected argument type '[MPMusicPlayerPlayParameters]'

NEW EDIT

        var requestURLComponents = URLComponents()
        requestURLComponents.scheme = "https"
        requestURLComponents.host = "api.music.apple.com"
        requestURLComponents.path = "/v1/me/history/heavy-rotation"
        
        requestURLComponents.queryItems = [
            URLQueryItem(name: "limit", value: "5")
        ]
        
        guard let url = requestURLComponents.url else { return }
        
        let request = MusicDataRequest(urlRequest: URLRequest(url: url))
        do {
            let response = try await request.response()
            let decodedResponse = try JSONDecoder().decode(MusicItemCollection<Album>.self, from: response.data)
            heavyRotation = decodedResponse
//            print(response.debugDescription)
        } catch {
            print("error")
            print(error)
            print(error.localizedDescription)
        }

...

Button(action: {
    Task {
        guard let album = heavyRotation[album] as Album? else { return }
        print(album)
        let player = ApplicationMusicPlayer.shared
        player.queue = [album]
        try await player.prepareToPlay()
        try await player.play()
    }
}) {
    Image(systemName: "play.fill")
        .frame(width: 50, height: 50, alignment: .center)
        .fontSize(30)
        .foregroundColor(.white)
}
1

There are 1 best solutions below

7
Rudrank Riyam On BEST ANSWER

While MusicKit's PlayParameters is a structure and an opaque object, MPMusicPlayerPlayParameters initializers expect a [String: Any] dictionary. You'll have to encode and decode the PlayParameters to MPMusicPlayerParameters.

Here's your example:

guard let parameters = heavyRotation[album].playParameters else { return }

let data = try JSONEncoder().encode(parameters)
let playParameters = try JSONDecoder().decode(MPMusicPlayerPlayParameters.self, from: data)

let queue = MPMusicPlayerPlayParametersQueueDescriptor(playParametersQueue: [playParameters])

let player = MPMusicPlayerController.applicationMusicPlayer
player.setQueue(with: queue)
player.prepareToPlay()
player.play()

If you're using MusicKit for Swift and its music player, you can directly set the album to the queue like this:

guard let album = heavyRotation[album] else { return }

let player = ApplicationMusicPlayer.shared
player.queue = [album]
try await player.prepareToPlay()
try await player.play()

Update - If you're trying to play an album from the library, then I had problems with that as well. As a workaround, you can get the album's local ID and then make another request to the catalog. 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)
}