import Foundation import MediaPlayer /// Handles iOS Now Playing info center and remote command center for lock screen / Control Center controls. @MainActor final class MediaKeyHandler { static let shared = MediaKeyHandler() private weak var playerVM: PlayerViewModel? func register(playerVM: PlayerViewModel) { self.playerVM = playerVM setupRemoteCommands() } private func setupRemoteCommands() { let center = MPRemoteCommandCenter.shared() center.playCommand.isEnabled = true center.playCommand.addTarget { [weak self] _ in self?.playerVM?.togglePlayPause() return .success } center.pauseCommand.isEnabled = true center.pauseCommand.addTarget { [weak self] _ in self?.playerVM?.togglePlayPause() return .success } center.togglePlayPauseCommand.isEnabled = true center.togglePlayPauseCommand.addTarget { [weak self] _ in self?.playerVM?.togglePlayPause() return .success } center.nextTrackCommand.isEnabled = true center.nextTrackCommand.addTarget { [weak self] _ in self?.playerVM?.playNext() return .success } center.previousTrackCommand.isEnabled = true center.previousTrackCommand.addTarget { [weak self] _ in self?.playerVM?.playPrevious() return .success } center.changePlaybackPositionCommand.isEnabled = true center.changePlaybackPositionCommand.addTarget { [weak self] event in guard let event = event as? MPChangePlaybackPositionCommandEvent else { return .commandFailed } self?.playerVM?.seek(to: event.positionTime) return .success } center.skipForwardCommand.isEnabled = true center.skipForwardCommand.preferredIntervals = [10] center.skipForwardCommand.addTarget { [weak self] event in guard let event = event as? MPSkipIntervalCommandEvent else { return .commandFailed } self?.playerVM?.skipForward(event.interval) return .success } center.skipBackwardCommand.isEnabled = true center.skipBackwardCommand.preferredIntervals = [10] center.skipBackwardCommand.addTarget { [weak self] event in guard let event = event as? MPSkipIntervalCommandEvent else { return .commandFailed } self?.playerVM?.skipBackward(event.interval) return .success } } func updateNowPlaying(track: Track?, isPlaying: Bool, currentTime: TimeInterval, duration: TimeInterval) { var info = [String: Any]() info[MPMediaItemPropertyTitle] = track?.title ?? "MixBoard" info[MPMediaItemPropertyArtist] = track?.artist ?? "" info[MPMediaItemPropertyAlbumTitle] = track?.album ?? "" info[MPMediaItemPropertyPlaybackDuration] = duration info[MPNowPlayingInfoPropertyElapsedPlaybackTime] = currentTime info[MPNowPlayingInfoPropertyPlaybackRate] = isPlaying ? 1.0 : 0.0 if let bpm = track?.bpm { info[MPMediaItemPropertyBeatsPerMinute] = Int(bpm) } MPNowPlayingInfoCenter.default().nowPlayingInfo = info } }