Hello,
I'm working with the new MusicKit API, I'm trying to get a list of songs be played from a list IDs.
// List if Songs IDs let songIds = [MusicItemID("560097694"), MusicItemID("560097715")] // Defines requests let requests = songIds.map { songId in MusicCatalogResourceRequest<Song>(matching: \.id, equalTo: songId) } // Responses let response = try? await requests[0].response() guard let song = response?.items.first else { return } let response1 = try? await requests[1].response() guard let song1 = response1?.items.first else { return }
Then if I perform this code :
// Queue Songs let songs: ApplicationMusicPlayer.Queue = [] try? await songs.insert(song, position: .tail) try? await songs.insert(song1, position: .tail) let appPlayer = ApplicationMusicPlayer.shared appPlayer.queue = songs try? await appPlayer.play()
I have the following errors :
[SDKPlayback] applicationQueuePlayer _establishConnectionIfNeeded timeout [ping did not pong] [SDKPlayback] Failed to prepareToPlay error: Error Domain=MPMusicPlayerControllerErrorDomain Code=6 "Failed to prepare to play" UserInfo={NSDebugDescription=Failed to prepare to play} [SDKPlayback] Failed to prepareToPlay error: Error Domain=MPMusicPlayerControllerErrorDomain Code=6 "Failed to prepare to play" UserInfo={NSDebugDescription=Failed to prepare to play}
But if I do This :
let appPlayer = ApplicationMusicPlayer.shared appPlayer.queue = [song, song1] try? await appPlayer.play()
It works perfectly
Is it possible to create a dynamic Queue ? And what is the recommended approach ?
Xcode Version 13.1 (13A1030d)
Hello @Hikosei,
When using MusicKit's ApplicationMusicPlayer, you should always aim to set the queue initially as completely as you can, using the setter for the queue property.
The correct approach for the specific example you're showing here is:
let request = MusicCatalogResourceRequest<Song>(matching: \.id, memberOf: ["560097694", "560097715"]) let response = try await request.response() let musicPlayer = ApplicationMusicPlayer.shared musicPlayer.queue = ApplicationMusicPlayer.Queue(for: response.items) try await musicPlayer.play()
As you can see, you don't even need to load these songs one at a time. You can setup a single MusicCatalogResourceRequest with init(matching:memberOf:), and pass both of those IDs. This is much more efficient than what you were trying to do.
Once the queue has been set correctly, and the player is already playing (or is at least correctly prepared to play), then you can use the Queue's insertion methods, such as insert(_:position:).
I hope this helps.
Best regards,