MediaKeyHandler.swift 3.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. import Foundation
  2. import MediaPlayer
  3. /// Handles iOS Now Playing info center and remote command center for lock screen / Control Center controls.
  4. @MainActor
  5. final class MediaKeyHandler {
  6. static let shared = MediaKeyHandler()
  7. private weak var playerVM: PlayerViewModel?
  8. func register(playerVM: PlayerViewModel) {
  9. self.playerVM = playerVM
  10. setupRemoteCommands()
  11. }
  12. private func setupRemoteCommands() {
  13. let center = MPRemoteCommandCenter.shared()
  14. center.playCommand.isEnabled = true
  15. center.playCommand.addTarget { [weak self] _ in
  16. self?.playerVM?.togglePlayPause()
  17. return .success
  18. }
  19. center.pauseCommand.isEnabled = true
  20. center.pauseCommand.addTarget { [weak self] _ in
  21. self?.playerVM?.togglePlayPause()
  22. return .success
  23. }
  24. center.togglePlayPauseCommand.isEnabled = true
  25. center.togglePlayPauseCommand.addTarget { [weak self] _ in
  26. self?.playerVM?.togglePlayPause()
  27. return .success
  28. }
  29. center.nextTrackCommand.isEnabled = true
  30. center.nextTrackCommand.addTarget { [weak self] _ in
  31. self?.playerVM?.playNext()
  32. return .success
  33. }
  34. center.previousTrackCommand.isEnabled = true
  35. center.previousTrackCommand.addTarget { [weak self] _ in
  36. self?.playerVM?.playPrevious()
  37. return .success
  38. }
  39. center.changePlaybackPositionCommand.isEnabled = true
  40. center.changePlaybackPositionCommand.addTarget { [weak self] event in
  41. guard let event = event as? MPChangePlaybackPositionCommandEvent else { return .commandFailed }
  42. self?.playerVM?.seek(to: event.positionTime)
  43. return .success
  44. }
  45. center.skipForwardCommand.isEnabled = true
  46. center.skipForwardCommand.preferredIntervals = [10]
  47. center.skipForwardCommand.addTarget { [weak self] event in
  48. guard let event = event as? MPSkipIntervalCommandEvent else { return .commandFailed }
  49. self?.playerVM?.skipForward(event.interval)
  50. return .success
  51. }
  52. center.skipBackwardCommand.isEnabled = true
  53. center.skipBackwardCommand.preferredIntervals = [10]
  54. center.skipBackwardCommand.addTarget { [weak self] event in
  55. guard let event = event as? MPSkipIntervalCommandEvent else { return .commandFailed }
  56. self?.playerVM?.skipBackward(event.interval)
  57. return .success
  58. }
  59. }
  60. func updateNowPlaying(track: Track?, isPlaying: Bool, currentTime: TimeInterval, duration: TimeInterval) {
  61. var info = [String: Any]()
  62. info[MPMediaItemPropertyTitle] = track?.title ?? "MixBoard"
  63. info[MPMediaItemPropertyArtist] = track?.artist ?? ""
  64. info[MPMediaItemPropertyAlbumTitle] = track?.album ?? ""
  65. info[MPMediaItemPropertyPlaybackDuration] = duration
  66. info[MPNowPlayingInfoPropertyElapsedPlaybackTime] = currentTime
  67. info[MPNowPlayingInfoPropertyPlaybackRate] = isPlaying ? 1.0 : 0.0
  68. if let bpm = track?.bpm {
  69. info[MPMediaItemPropertyBeatsPerMinute] = Int(bpm)
  70. }
  71. MPNowPlayingInfoCenter.default().nowPlayingInfo = info
  72. }
  73. }