ApplicationMusicPlayer / MediaPlayer Refuses to Play

We use BassDSDPlayer / SFBAudioEngine to play just about any file, but playing Apple Music is failing. All subscriptions are up to date. We stop the SFBAudioEngine and the BassDSDPlayer before playing Apple Music to no avail.

PRINTS:

Supported files in /Users/dorian/Music/Music/Media.localized/Music/4: 28364 Apple Music is authorized and can play catalog. Resetting default output device... Releasing BassDSDPlayer audio device... BassDSDPlayer: Audio device released. STOPPED sfbAudioDevice Default output device is ID: 76 applicationQueuePlayer _establishConnectionIfNeeded timeout [ping did not pong] applicationQueuePlayer _establishConnectionIfNeeded timeout [ping did not pong] Player State - After resetting output: Playback Status: stopped Queue Count: 0 No track is playing.

Music player reset successfully. BassDSDPlayer: Audio device released. Default output device set successfully: 76 Default output device is ID: 76 Default output device set successfully: 76 Default output device ID: 76 Validated PlayParameters for track: squabble up PlayParameters: PlayParameters(id: 1781270321, kind: "song", isLibrary: nil, catalogID: nil, libraryID: nil, deviceLocalID: nil, rawValues: [:]) Starting playback... Player State - After playback: Playback Status: stopped Queue Count: 1 No track is playing.

Notification BASS DSD NSConcreteNotification 0x600007ce2b00 {name = kUpdateSongInfo; object = { AlbumTitle = GNX; ArtistName = "Kendrick Lamar"; SongArtwork = "<NSImage 0x6000041b7ca0 Size={300, 300} RepProvider=<NSImageArrayRepProvider: 0x600003518770, reps:(\n "NSBitmapImageRep 0x600009ed9dc0 Size={300, 300} ColorSpace=(not yet loaded) BPS=8 BPP=(not yet loaded) Pixels=300x300 Alpha=NO Planar=NO Format=(not yet loaded) CurrentBacking=nil (faulting) CGImageSource=0x600007ce15c0"\n)>>"; SongLength = "157.992"; SongTitle = "squabble up"; Source = AppleMusic; }} Apple Music track loaded: squabble up by Kendrick Lamar Player State - Before play: Playback Status: stopped Queue Count: 1 No track is playing.

prepareToPlay failed [no target descriptor] NSError Code: 1, Domain: MPMusicPlayerControllerErrorDomain Player State - After play: Playback Status: stopped Queue Count: 1 No track is playing.

func playAppleMusicTracks(tracks: [Track]) {
    AppleMusicManager.shared.isAuthorizedAndReadyForPlayback { isAuthorized in
        guard isAuthorized else {
            print("Apple Music authorization or capabilities insufficient for playback.")
            return
        }

        print("Resetting default output device...")
        self.stopSFBAudioDevice()
        self.resetMusicPlayer()
        self.resetAudioSystem()
        self.ensureOutputDeviceReady()

        Task {
            for track in tracks {
                guard self.validatePlayParameters(for: track) else { continue }
                
                do {
                    try await ApplicationMusicPlayer.shared.queue.insert(track, position: .afterCurrentEntry)
                    
                    guard !ApplicationMusicPlayer.shared.queue.entries.isEmpty else {
                        print("Queue is empty after queuing. Playback cannot proceed.")
                        return
                    }
                    self.notifyAppleMusicTrackInfo(track)

                } catch {
                    print("Error starting playback: \(error)")
                    if let nsError = error as NSError? {
                        print("NSError Code: \(nsError.code), Domain: \(nsError.domain)")
                    }
                }
            }

            MusicKitWrapper.shared.logPlayerState(message: "After playback")
        }
    }
}

@objc public class MusicKitWrapper: NSObject {

@objc public static let shared = MusicKitWrapper()
private let player = ApplicationMusicPlayer.shared

// Play the current track
@objc public func play() {
    
    guard !player.queue.entries.isEmpty else {
        print("Queue is empty. Cannot start playback.")
        return
    }
    logPlayerState(message: "Before play")

    Task {
        do {
            try await player.prepareToPlay()
            try await player.play()
            print("Playback started successfully.")
        } catch {
            if let nsError = error as NSError? {
                print("NSError Code: \(nsError.code), Domain: \(nsError.domain)")
            }
        }
        logPlayerState(message: "After play")
    }
}

Any help would be appreciated.

Thanks!

This error is thrown if there is no queue. Its hard to tell which code is 3rd party vs native but you can start debugging at your queue level to ensure it's being passed to your player correctly.

ApplicationMusicPlayer.Queue usually takes an initializer, not an insert so I would start with the queue creation code to make sure it works, then compare vs a completely plain native app using on the Apple provided player to make sure your other players aren't interfering with your audio sessions (although less likely than a simple issue with your queue creation).

Hopefully this helps.

Rico


WWDR | DTS | Software Engineer

Queue cleared. Apple Music player reset successfully. Queued track: Uncle Salty with PlayParameters present. Play Parameters: PlayParameters(id: 1660109276, kind: "song", isLibrary: nil, catalogID: nil, libraryID: nil, deviceLocalID: nil, rawValues: [:]) Queue contains 1 entries. prepareToPlay failed [no target descriptor] Error during playback for Uncle Salty: The operation couldn’t be completed. (MPMusicPlayerControllerErrorDomain error 1.) Notification BASS DSD NSConcreteNotification 0x600003cd70e0 {name = kUpdateSongInfo; object = { AlbumTitle = "Toys In the Attic"; ArtistName = Aerosmith; SongArtwork = "<NSImage 0x60000873dd60 Size={300, 300} RepProvider=<NSImageArrayRepProvider: 0x6000034711c0, reps:(\n "NSBitmapImageRep 0x600001eace00 Size={300, 300} ColorSpace=(not yet loaded) BPS=8 BPP=(not yet loaded) Pixels=300x300 Alpha=NO Planar=NO Format=(not yet loaded) CurrentBacking=nil (faulting) CGImageSource=0x600003cb0040"\n)>>"; SongLength = "249.754"; SongTitle = "Uncle Salty"; Source = AppleMusic; }}

Changes to the code: private let player = ApplicationMusicPlayer.shared

// MARK: - Play Single Track
public func playTrack(_ track: Track) async {
    
    guard let playParameters = track.playParameters else {
        print("Error: Track \(track.title) is missing PlayParameters. Cannot play.")
        return
    }
    
    let status = await MusicAuthorization.request()
    if status != .authorized {
        print("Music authorization not granted.")
    }
    
    do {
        // Insert the track into the queue
        try await player.queue.insert(track, position: .afterCurrentEntry)
        print("Queued track: \(track.title) with PlayParameters present.")
        print("Play Parameters:", track.playParameters ?? "None")

        // Log the queue state
        if player.queue.entries.isEmpty {
            print("Queue is still empty after inserting track \(track.title).")
            return
        }
        print("Queue contains \(player.queue.entries.count) entries.")
        self.notifyAppleMusicTrackInfo(track)

        // Prepare and play
        try await player.prepareToPlay()
        try await player.play()
        print("Playback started for track: \(track.title)")
    } catch {
        print("Error during playback for \(track.title): \(error.localizedDescription)")
    }
}

Using your suggestion, the queue won't even accept the entry: Queue cleared. Apple Music player reset successfully. Track Details:

  • Title: Adam's Apple
  • Artist: Aerosmith
  • PlayParameters: PlayParameters(id: 1660109281, kind: "song", isLibrary: nil, catalogID: nil, libraryID: nil, deviceLocalID: nil, rawValues: [:])

Queue initialized with track: Adam's Apple Queue is empty after adding track Adam's Apple.

public func playTrack(_ track: Track) async {
    guard let playParameters = track.playParameters else {
        print("Error: Track \(track.title) is missing PlayParameters. Cannot play.")
        return
    }

    print("Track Details:")
    print(" - Title: \(track.title)")
    print(" - Artist: \(track.artistName)")
    print(" - PlayParameters: \(playParameters)")

    // Request Music Authorization
    let status = await MusicAuthorization.request()
    if status != .authorized {
        print("Music authorization not granted.")
        return
    }

    do {
        // Replace the queue with the track
        player.queue = [track]
        print("Queue initialized with track: \(track.title)")

        // Validate the queue state
        if player.queue.entries.isEmpty {
            print("Queue is empty after adding track \(track.title).")
            return
        }

        // Log queue details
        print("Queue contains \(player.queue.entries.count) entries.")
        for entry in player.queue.entries {
            print("Queue Entry: \(entry.title)")
        }

        // Notify about track info
        self.notifyAppleMusicTrackInfo(track)

        // Prepare and play
        try await player.prepareToPlay()
        try await player.play()
        print("Playback started for track: \(track.title)")
    } catch {
        print("Error during playback for \(track.title): \(error.localizedDescription)")
    }
}

I'm in Puerto Rico right now, is that a problem with Apple Music API?? applicationQueuePlayer _establishConnectionIfNeeded timeout [ping did not pong] Queue cleared. Apple Music player reset successfully. Queued track: Uncle Salty with PlayParameters present. Play Parameters: PlayParameters(id: 1660109276, kind: "song", isLibrary: nil, catalogID: nil, libraryID: nil, deviceLocalID: nil, rawValues: [:]) Queue contains 1 entries. prepareToPlay failed [no target descriptor] Error during playback for Uncle Salty: The operation couldn’t be completed. (MPMusicPlayerControllerErrorDomain error 1.) Notification BASS DSD NSConcreteNotification 0x6000032f1fc0 {name = kUpdateSongInfo; object = { AlbumTitle = "Toys In the Attic"; ArtistName = Aerosmith; SongArtwork = "<NSImage 0x6000088d0320 Size={300, 300} RepProvider=<NSImageArrayRepProvider: 0x600003b24b00, reps:(\n "NSBitmapImageRep 0x6000011c0460 Size={300, 300} ColorSpace=(not yet loaded) BPS=8 BPP=(not yet loaded) Pixels=300x300 Alpha=NO Planar=NO Format=(not yet loaded) CurrentBacking=nil (faulting) CGImageSource=0x6000032f4380"\n)>>"; SongLength = "249.754"; SongTitle = "Uncle Salty"; Source = AppleMusic; }} Apple Music track loaded: Uncle Salty by Aerosmith

I tried refreshing before playing, but same thing.

public func playTrack(_ track: Track) async { // Check for valid PlayParameters guard track.playParameters != nil else { print("Error: Track (track.title) is missing PlayParameters. Cannot play.") return }

    let status = await MusicAuthorization.request()
    if status != .authorized {
        print("Music authorization not granted.")
        return
    }

    do {
        // **Fetch updated track information if needed**
        let updatedTrack: Track
        if let appleTrack = AppleTrack(from: track) {
            if let refreshedTrack = await fetchTrackDetails(for: appleTrack.title) {
                print("Fetched updated track details for \(refreshedTrack.title).")
                updatedTrack = refreshedTrack
            } else {
                print("Failed to fetch updated track details. Proceeding with existing track.")
                updatedTrack = track
            }
        } else {
            updatedTrack = track
        }

        // Insert the track into the queue
        try await player.queue.insert(updatedTrack, position: .afterCurrentEntry)
        print("Queued track: \(updatedTrack.title) with PlayParameters present.")
        print("Play Parameters:", updatedTrack.playParameters ?? "None")

        // Log the queue state
        if player.queue.entries.isEmpty {
            print("Queue is still empty after inserting track \(updatedTrack.title).")
            return
        }
        print("Queue contains \(player.queue.entries.count) entries.")

        // Notify listeners of track info
        self.notifyAppleMusicTrackInfo(updatedTrack)

        // Prepare and play
        try await player.prepareToPlay()
        try await player.play()
        print("Playback started for track: \(updatedTrack.title)")

    } catch {
        print("Error during playback for \(track.title): \(error.localizedDescription)")
    }
}

private func fetchTrackDetails(for id: String) async -> Track? {
    do {
        // Create a search request for the specific track ID
        let searchRequest = MusicCatalogSearchRequest(term: id, types: [Song.self]) // Use Song.self
        let response = try await searchRequest.response()

        // Retrieve the first matching song and convert it to a Track
        if let song = response.songs.first {
            print("Fetched song: \(song.title) by \(song.artistName)")
            return .song(song) // Wrap the Song as a Track
        } else {
            print("No track found for ID \(id)")
            return nil
        }
    } catch {
        print("Error fetching track details for ID \(id): \(error.localizedDescription)")
        return nil
    }
}
ApplicationMusicPlayer / MediaPlayer Refuses to Play
 
 
Q