From d8d02984fd2ab418acf355c51c539e765be219fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rasmus=20Kr=C3=A4mer?= Date: Tue, 22 Mar 2022 15:38:31 +0100 Subject: [PATCH] Go pack a few seconds when resuming after a long time --- ios/App/App/AppDelegate.swift | 2 +- ios/App/App/AudioPlayer.swift | 46 ++++++++++++++++++++++++++++++--- ios/App/App/MyNativeAudio.swift | 28 ++++++++++---------- 3 files changed, 57 insertions(+), 19 deletions(-) diff --git a/ios/App/App/AppDelegate.swift b/ios/App/App/AppDelegate.swift index 5c86522d..c85fb2c2 100644 --- a/ios/App/App/AppDelegate.swift +++ b/ios/App/App/AppDelegate.swift @@ -7,7 +7,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { - UIApplication.shared.beginReceivingRemoteControlEvents() + // UIApplication.shared.beginReceivingRemoteControlEvents() // Override point for customization after application launch. return true } diff --git a/ios/App/App/AudioPlayer.swift b/ios/App/App/AudioPlayer.swift index 1a06fe1e..93cf05b2 100644 --- a/ios/App/App/AudioPlayer.swift +++ b/ios/App/App/AudioPlayer.swift @@ -22,7 +22,9 @@ class AudioPlayer: NSObject { // enums and @objc are not compatible @objc dynamic var status: Int @objc dynamic var rate: Float + private var tmpRate: Float = 1.0 + private var lastPlayTime: Double = 0.0 private var playerContext = 0 private var playerItemContext = 0 @@ -63,13 +65,34 @@ class AudioPlayer: NSObject { } func destroy() { pause() + audioPlayer.replaceCurrentItem(with: nil) - nowPlayingInfo = [:] - updateNowPlaying() + DispatchQueue.main.sync { + UIApplication.shared.endReceivingRemoteControlEvents() + } + + do { + try AVAudioSession.sharedInstance().setActive(false) + } catch { + NSLog("Failed to set AVAudioSession inactive") + print(error) + } + + nowPlayingInfo.removeAll() + nowPlayingInfo[MPMediaItemPropertyTitle] = "" + nowPlayingInfo[MPMediaItemPropertyArtist] = "" + MPNowPlayingInfoCenter.default().nowPlayingInfo = nowPlayingInfo } // MARK: - Methods - public func play() { + public func play(allowSeekBack: Bool = false) { + if allowSeekBack { + if lastPlayTime + 5 < Date.timeIntervalSinceReferenceDate { + seek(getCurrentTime() - 1.5) + } + } + lastPlayTime = Date.timeIntervalSinceReferenceDate + self.audioPlayer.play() self.status = 1 self.rate = self.tmpRate @@ -83,6 +106,7 @@ class AudioPlayer: NSObject { self.rate = 0.0 updateNowPlaying() + lastPlayTime = Date.timeIntervalSinceReferenceDate } public func seek(_ to: Double) { let continuePlaing = rate > 0.0 @@ -144,11 +168,14 @@ class AudioPlayer: NSObject { // MARK: - Now playing func setupRemoteTransportControls() { + DispatchQueue.main.sync { + UIApplication.shared.beginReceivingRemoteControlEvents() + } let commandCenter = MPRemoteCommandCenter.shared() commandCenter.playCommand.isEnabled = true commandCenter.playCommand.addTarget { [unowned self] event in - play() + play(allowSeekBack: true) return .success } commandCenter.pauseCommand.isEnabled = true @@ -187,6 +214,17 @@ class AudioPlayer: NSObject { self.seek(event.positionTime) return .success } + + commandCenter.changePlaybackRateCommand.isEnabled = true + commandCenter.changePlaybackRateCommand.supportedPlaybackRates = [0.5, 0.75, 0.9, 1, 1.2, 1.5, 2] + commandCenter.changePlaybackRateCommand.addTarget { event in + guard let event = event as? MPChangePlaybackRateCommandEvent else { + return .noSuchContent + } + + self.setPlaybackRate(event.playbackRate) + return .success + } } func invokeMetadataUpdate() { diff --git a/ios/App/App/MyNativeAudio.swift b/ios/App/App/MyNativeAudio.swift index 5c83bbb0..760e8b01 100644 --- a/ios/App/App/MyNativeAudio.swift +++ b/ios/App/App/MyNativeAudio.swift @@ -9,7 +9,6 @@ func parseSleepTime(millis: String?) -> Double { @objc(MyNativeAudio) public class MyNativeAudio: CAPPlugin { - var currentCall: CAPPluginCall? var currentPlayer: AudioPlayer? var playerContext = 0 @@ -36,17 +35,19 @@ public class MyNativeAudio: CAPPlugin { ) let playWhenReady = call.getBool("playWhenReady", false) - if self.currentPlayer != nil && self.currentPlayer?.audiobook.streamId == audiobook.streamId { + if currentPlayer != nil && currentPlayer?.audiobook.streamId == audiobook.streamId { if playWhenReady { self.currentPlayer?.play() } call.resolve(["success": true]) return + } else if currentPlayer != nil && currentPlayer?.audiobook.streamId != audiobook.streamId { + stop() } - self.currentPlayer = AudioPlayer(audiobook: audiobook, playWhenReady: playWhenReady) - self.currentPlayer!.addObserver(self, forKeyPath: #keyPath(AudioPlayer.status), options: .new, context: &playerContext) + currentPlayer = AudioPlayer(audiobook: audiobook, playWhenReady: playWhenReady) + currentPlayer!.addObserver(self, forKeyPath: #keyPath(AudioPlayer.status), options: .new, context: &playerContext) call.resolve(["success": true]) } @@ -116,7 +117,7 @@ public class MyNativeAudio: CAPPlugin { return } - self.currentPlayer!.play() + self.currentPlayer!.play(allowSeekBack: true) sendPlaybackStatusUpdate(true) call.resolve() @@ -126,15 +127,14 @@ public class MyNativeAudio: CAPPlugin { stop() call.resolve() } - @objc func stop() { - if let call = currentCall { - if self.currentPlayer != nil { - self.currentPlayer!.destroy() - } - - self.currentPlayer = nil - currentCall = nil; - call.resolve([ "result": true ]) + @objc func stop(_ call: CAPPluginCall? = nil) { + if self.currentPlayer != nil { + self.currentPlayer!.destroy() + } + self.currentPlayer = nil + + if call != nil { + call!.resolve([ "result": true ]) } }