From e998a03571fb5b6f7ebcbb76bd5a47499b61acf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rasmus=20Kr=C3=A4mer?= Date: Tue, 22 Mar 2022 16:56:59 +0100 Subject: [PATCH] Moved NowPlaingInfo to its own class --- ios/App/App/{ => audio}/AudioPlayer.swift | 72 ++----------------- ios/App/App/{ => audio}/MyNativeAudio.m | 0 ios/App/App/{ => audio}/MyNativeAudio.swift | 0 ios/App/App/{ => models}/Audiobook.swift | 0 ios/App/App/util/NowPlayingInfo.swift | 79 +++++++++++++++++++++ 5 files changed, 86 insertions(+), 65 deletions(-) rename ios/App/App/{ => audio}/AudioPlayer.swift (74%) rename ios/App/App/{ => audio}/MyNativeAudio.m (100%) rename ios/App/App/{ => audio}/MyNativeAudio.swift (100%) rename ios/App/App/{ => models}/Audiobook.swift (100%) create mode 100644 ios/App/App/util/NowPlayingInfo.swift diff --git a/ios/App/App/AudioPlayer.swift b/ios/App/App/audio/AudioPlayer.swift similarity index 74% rename from ios/App/App/AudioPlayer.swift rename to ios/App/App/audio/AudioPlayer.swift index 93cf05b2..0b3b3380 100644 --- a/ios/App/App/AudioPlayer.swift +++ b/ios/App/App/audio/AudioPlayer.swift @@ -10,14 +10,6 @@ import AVFoundation import UIKit import MediaPlayer -func getData(from url: URL, completion: @escaping (UIImage?) -> Void) { - URLSession.shared.dataTask(with: url, completionHandler: {(data, response, error) in - if let data = data { - completion(UIImage(data:data)) - } - }).resume() -} - class AudioPlayer: NSObject { // enums and @objc are not compatible @objc dynamic var status: Int @@ -28,7 +20,6 @@ class AudioPlayer: NSObject { private var playerContext = 0 private var playerItemContext = 0 - private var nowPlayingInfo: [String: Any] = [:] private var playWhenReady: Bool @@ -46,7 +37,7 @@ class AudioPlayer: NSObject { initAudioSession() setupRemoteTransportControls() - invokeMetadataUpdate() + NowPlayingInfo.setAudiobook(audiobook: audiobook) // Listen to player events self.audioPlayer.addObserver(self, forKeyPath: #keyPath(AVPlayer.rate), options: .new, context: &playerContext) @@ -67,10 +58,6 @@ class AudioPlayer: NSObject { pause() audioPlayer.replaceCurrentItem(with: nil) - DispatchQueue.main.sync { - UIApplication.shared.endReceivingRemoteControlEvents() - } - do { try AVAudioSession.sharedInstance().setActive(false) } catch { @@ -78,10 +65,9 @@ class AudioPlayer: NSObject { print(error) } - nowPlayingInfo.removeAll() - nowPlayingInfo[MPMediaItemPropertyTitle] = "" - nowPlayingInfo[MPMediaItemPropertyArtist] = "" - MPNowPlayingInfoCenter.default().nowPlayingInfo = nowPlayingInfo + DispatchQueue.main.sync { + UIApplication.shared.endReceivingRemoteControlEvents() + } } // MARK: - Methods @@ -161,10 +147,7 @@ class AudioPlayer: NSObject { print(error) } } - - private func shouldFetchCover() -> Bool { - nowPlayingInfo[MPNowPlayingInfoPropertyExternalContentIdentifier] as? String != audiobook.streamId || nowPlayingInfo[MPMediaItemPropertyArtwork] == nil - } + // MARK: - Now playing func setupRemoteTransportControls() { @@ -216,7 +199,7 @@ class AudioPlayer: NSObject { } commandCenter.changePlaybackRateCommand.isEnabled = true - commandCenter.changePlaybackRateCommand.supportedPlaybackRates = [0.5, 0.75, 0.9, 1, 1.2, 1.5, 2] + commandCenter.changePlaybackRateCommand.supportedPlaybackRates = [0.5, 0.75, 1.0, 1.25, 1.5, 2] commandCenter.changePlaybackRateCommand.addTarget { event in guard let event = event as? MPChangePlaybackRateCommandEvent else { return .noSuchContent @@ -227,49 +210,8 @@ class AudioPlayer: NSObject { } } - func invokeMetadataUpdate() { - if !shouldFetchCover() || audiobook.artworkUrl == nil { - setMetadata(nil) - return - } - - guard let url = URL(string: audiobook.artworkUrl!) else { return } - getData(from: url) { [weak self] image in - guard let self = self, - let downloadedImage = image else { - return - } - let artwork = MPMediaItemArtwork.init(boundsSize: downloadedImage.size, requestHandler: { _ -> UIImage in - return downloadedImage - }) - - self.setMetadata(artwork) - } - } - func setMetadata(_ artwork: MPMediaItemArtwork?) { - if artwork != nil { - nowPlayingInfo[MPMediaItemPropertyArtwork] = artwork - } else if shouldFetchCover() { - nowPlayingInfo[MPMediaItemPropertyArtwork] = nil - } - - nowPlayingInfo[MPNowPlayingInfoPropertyExternalContentIdentifier] = audiobook.streamId - nowPlayingInfo[MPNowPlayingInfoPropertyAssetURL] = URL(string: audiobook.playlistUrl) - nowPlayingInfo[MPNowPlayingInfoPropertyIsLiveStream] = false - nowPlayingInfo[MPNowPlayingInfoPropertyMediaType] = "hls" - - nowPlayingInfo[MPMediaItemPropertyTitle] = audiobook.title - nowPlayingInfo[MPMediaItemPropertyArtist] = audiobook.author ?? "unknown" - nowPlayingInfo[MPMediaItemPropertyAlbumTitle] = audiobook.series - } - func updateNowPlaying() { - nowPlayingInfo[MPMediaItemPropertyPlaybackDuration] = getDuration() - nowPlayingInfo[MPNowPlayingInfoPropertyElapsedPlaybackTime] = getCurrentTime() - nowPlayingInfo[MPNowPlayingInfoPropertyPlaybackRate] = rate - nowPlayingInfo[MPNowPlayingInfoPropertyDefaultPlaybackRate] = 1.0 - - MPNowPlayingInfoCenter.default().nowPlayingInfo = nowPlayingInfo + NowPlayingInfo.update(duration: getDuration(), currentTime: getCurrentTime(), rate: rate) } // MARK: - Observer diff --git a/ios/App/App/MyNativeAudio.m b/ios/App/App/audio/MyNativeAudio.m similarity index 100% rename from ios/App/App/MyNativeAudio.m rename to ios/App/App/audio/MyNativeAudio.m diff --git a/ios/App/App/MyNativeAudio.swift b/ios/App/App/audio/MyNativeAudio.swift similarity index 100% rename from ios/App/App/MyNativeAudio.swift rename to ios/App/App/audio/MyNativeAudio.swift diff --git a/ios/App/App/Audiobook.swift b/ios/App/App/models/Audiobook.swift similarity index 100% rename from ios/App/App/Audiobook.swift rename to ios/App/App/models/Audiobook.swift diff --git a/ios/App/App/util/NowPlayingInfo.swift b/ios/App/App/util/NowPlayingInfo.swift new file mode 100644 index 00000000..3af49275 --- /dev/null +++ b/ios/App/App/util/NowPlayingInfo.swift @@ -0,0 +1,79 @@ +// +// NowPlaying.swift +// App +// +// Created by Rasmus Krämer on 22.03.22. +// + +import Foundation +import MediaPlayer + +func getData(from url: URL, completion: @escaping (UIImage?) -> Void) { + URLSession.shared.dataTask(with: url, completionHandler: {(data, response, error) in + if let data = data { + completion(UIImage(data:data)) + } + }).resume() +} + +class NowPlayingInfo { + private static var nowPlayingInfo: [String: Any] = [:] + private static var audiobook: Audiobook? + + public static func setAudiobook(audiobook: Audiobook) { + self.audiobook = audiobook + setMetadata(nil) + + if !shouldFetchCover() || audiobook.artworkUrl == nil { + return + } + + guard let url = URL(string: audiobook.artworkUrl!) else { return } + getData(from: url) { [self] image in + guard let downloadedImage = image else { + return + } + let artwork = MPMediaItemArtwork.init(boundsSize: downloadedImage.size, requestHandler: { _ -> UIImage in + return downloadedImage + }) + + self.setMetadata(artwork) + } + } + public static func update(duration: Double, currentTime: Double, rate: Float) { + nowPlayingInfo[MPMediaItemPropertyPlaybackDuration] = duration + nowPlayingInfo[MPNowPlayingInfoPropertyElapsedPlaybackTime] = currentTime + nowPlayingInfo[MPNowPlayingInfoPropertyPlaybackRate] = rate + nowPlayingInfo[MPNowPlayingInfoPropertyDefaultPlaybackRate] = 1.0 + + MPNowPlayingInfoCenter.default().nowPlayingInfo = nowPlayingInfo + } + public static func reset() { + audiobook = nil + MPNowPlayingInfoCenter.default().nowPlayingInfo = nil + } + + private static func setMetadata(_ artwork: MPMediaItemArtwork?) { + if self.audiobook == nil { + return + } + + if artwork != nil { + nowPlayingInfo[MPMediaItemPropertyArtwork] = artwork + } else if shouldFetchCover() { + nowPlayingInfo[MPMediaItemPropertyArtwork] = nil + } + + nowPlayingInfo[MPNowPlayingInfoPropertyExternalContentIdentifier] = audiobook!.streamId + nowPlayingInfo[MPNowPlayingInfoPropertyAssetURL] = URL(string: audiobook!.playlistUrl) + nowPlayingInfo[MPNowPlayingInfoPropertyIsLiveStream] = false + nowPlayingInfo[MPNowPlayingInfoPropertyMediaType] = "hls" + + nowPlayingInfo[MPMediaItemPropertyTitle] = audiobook!.title + nowPlayingInfo[MPMediaItemPropertyArtist] = audiobook!.author ?? "unknown" + nowPlayingInfo[MPMediaItemPropertyAlbumTitle] = audiobook!.series + } + private static func shouldFetchCover() -> Bool { + audiobook != nil && (nowPlayingInfo[MPNowPlayingInfoPropertyExternalContentIdentifier] as? String != audiobook!.streamId || nowPlayingInfo[MPMediaItemPropertyArtwork] == nil) + } +}