From f76128c2b3fec4623b5c51b19e352d92a23557de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rasmus=20Kr=C3=A4mer?= Date: Wed, 9 Mar 2022 20:20:47 +0100 Subject: [PATCH 1/3] Small fixes --- ios/App/App/AudioPlayer.swift | 3 +-- ios/App/App/MyNativeAudio.swift | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/ios/App/App/AudioPlayer.swift b/ios/App/App/AudioPlayer.swift index 76bb3453..acab12fa 100644 --- a/ios/App/App/AudioPlayer.swift +++ b/ios/App/App/AudioPlayer.swift @@ -183,7 +183,7 @@ class AudioPlayer: NSObject { } func invokeMetadataUpdate() { - if !shouldFetchCover() && audiobook.artworkUrl != nil { + if !shouldFetchCover() || audiobook.artworkUrl == nil { setMetadata(nil) return } @@ -234,7 +234,6 @@ class AudioPlayer: NSObject { guard let playerStatus = AVPlayerItem.Status(rawValue: (change?[.newKey] as? Int ?? -1)) else { return } if playerStatus == .readyToPlay { - NSLog("pain \(self.audiobook.startTime)") updateNowPlaying() self.status = 0 diff --git a/ios/App/App/MyNativeAudio.swift b/ios/App/App/MyNativeAudio.swift index 832fc3bd..e4c6232b 100644 --- a/ios/App/App/MyNativeAudio.swift +++ b/ios/App/App/MyNativeAudio.swift @@ -142,7 +142,7 @@ public class MyNativeAudio: CAPPlugin { } @objc func getStreamSyncData(_ call: CAPPluginCall) { if self.currentPlayer == nil { - call.resolve([ "isPlaying": false as Any, "lastPauseTime": 0, "id": nil ]) + call.resolve([ "isPlaying": false, "lastPauseTime": 0, "id": nil ]) return } From 926c17543fae0cea34f2d89f148aa66448b2d15b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rasmus=20Kr=C3=A4mer?= Date: Wed, 9 Mar 2022 22:10:15 +0100 Subject: [PATCH 2/3] Memorize playback rate --- ios/App/App/AudioPlayer.swift | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/ios/App/App/AudioPlayer.swift b/ios/App/App/AudioPlayer.swift index acab12fa..4413c147 100644 --- a/ios/App/App/AudioPlayer.swift +++ b/ios/App/App/AudioPlayer.swift @@ -22,6 +22,7 @@ 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 playerContext = 0 private var playerItemContext = 0 @@ -71,7 +72,10 @@ class AudioPlayer: NSObject { public func play() { self.audioPlayer.play() self.status = 1 - self.rate = 1.0 + self.rate = self.tmpRate + self.audioPlayer.rate = self.tmpRate + + print("oof", self.rate, self.tmpRate) updateNowPlaying() } @@ -97,10 +101,17 @@ class AudioPlayer: NSObject { self.updateNowPlaying() } } - public func setPlaybackRate(_ rate: Float) { - if(self.audioPlayer.rate != rate) { + + public func setPlaybackRate(_ rate: Float, observed: Bool = false) { + if self.audioPlayer.rate != rate { self.audioPlayer.rate = rate } + if rate > 0.0 && !(observed && rate == 1) { + + print("yikes", self.rate, self.tmpRate) + self.tmpRate = rate + } + self.rate = rate self.updateNowPlaying() @@ -245,7 +256,7 @@ class AudioPlayer: NSObject { } } else if context == &playerContext { if keyPath == #keyPath(AVPlayer.rate) { - setPlaybackRate(change?[.newKey] as? Float ?? 1.0) + setPlaybackRate(change?[.newKey] as? Float ?? 1.0, observed: true) } else if keyPath == #keyPath(AVPlayer.currentItem) { NSLog("WARNING: Item ended") } From 61433ef678e33f93872f7ee3833fc10cef8c2ecf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rasmus=20Kr=C3=A4mer?= Date: Wed, 9 Mar 2022 22:13:07 +0100 Subject: [PATCH 3/3] Added sleep timer --- ios/App/App/AudioPlayer.swift | 4 -- ios/App/App/MyNativeAudio.m | 28 ++++---- ios/App/App/MyNativeAudio.swift | 113 ++++++++++++++++++++++++++++++-- 3 files changed, 123 insertions(+), 22 deletions(-) diff --git a/ios/App/App/AudioPlayer.swift b/ios/App/App/AudioPlayer.swift index 4413c147..1a06fe1e 100644 --- a/ios/App/App/AudioPlayer.swift +++ b/ios/App/App/AudioPlayer.swift @@ -75,8 +75,6 @@ class AudioPlayer: NSObject { self.rate = self.tmpRate self.audioPlayer.rate = self.tmpRate - print("oof", self.rate, self.tmpRate) - updateNowPlaying() } public func pause() { @@ -107,8 +105,6 @@ class AudioPlayer: NSObject { self.audioPlayer.rate = rate } if rate > 0.0 && !(observed && rate == 1) { - - print("yikes", self.rate, self.tmpRate) self.tmpRate = rate } diff --git a/ios/App/App/MyNativeAudio.m b/ios/App/App/MyNativeAudio.m index b6dde25e..d0fc3a73 100644 --- a/ios/App/App/MyNativeAudio.m +++ b/ios/App/App/MyNativeAudio.m @@ -1,16 +1,20 @@ - #import #import CAP_PLUGIN(MyNativeAudio, "MyNativeAudio", - CAP_PLUGIN_METHOD(initPlayer, CAPPluginReturnPromise); - CAP_PLUGIN_METHOD(playPlayer, CAPPluginReturnPromise); - CAP_PLUGIN_METHOD(pausePlayer, CAPPluginReturnPromise); - CAP_PLUGIN_METHOD(seekForward, CAPPluginReturnPromise); - CAP_PLUGIN_METHOD(seekBackward, CAPPluginReturnPromise); - CAP_PLUGIN_METHOD(seekPlayer, CAPPluginReturnPromise); - CAP_PLUGIN_METHOD(terminateStream, CAPPluginReturnPromise); - CAP_PLUGIN_METHOD(getStreamSyncData, CAPPluginReturnPromise); - CAP_PLUGIN_METHOD(getCurrentTime, CAPPluginReturnPromise); - CAP_PLUGIN_METHOD(setPlaybackSpeed, CAPPluginReturnPromise); -) + CAP_PLUGIN_METHOD(initPlayer, CAPPluginReturnPromise); + CAP_PLUGIN_METHOD(playPlayer, CAPPluginReturnPromise); + CAP_PLUGIN_METHOD(pausePlayer, CAPPluginReturnPromise); + CAP_PLUGIN_METHOD(seekForward, CAPPluginReturnPromise); + CAP_PLUGIN_METHOD(seekBackward, CAPPluginReturnPromise); + CAP_PLUGIN_METHOD(seekPlayer, CAPPluginReturnPromise); + CAP_PLUGIN_METHOD(terminateStream, CAPPluginReturnPromise); + CAP_PLUGIN_METHOD(getStreamSyncData, CAPPluginReturnPromise); + CAP_PLUGIN_METHOD(getCurrentTime, CAPPluginReturnPromise); + CAP_PLUGIN_METHOD(setPlaybackSpeed, CAPPluginReturnPromise); + + CAP_PLUGIN_METHOD(setSleepTimer, CAPPluginReturnPromise); + CAP_PLUGIN_METHOD(increaseSleepTime, CAPPluginReturnPromise); + CAP_PLUGIN_METHOD(decreaseSleepTime, CAPPluginReturnPromise); + CAP_PLUGIN_METHOD(cancelSleepTimer, CAPPluginReturnPromise); + ) diff --git a/ios/App/App/MyNativeAudio.swift b/ios/App/App/MyNativeAudio.swift index e4c6232b..5c83bbb0 100644 --- a/ios/App/App/MyNativeAudio.swift +++ b/ios/App/App/MyNativeAudio.swift @@ -3,6 +3,10 @@ import Capacitor import MediaPlayer import AVKit +func parseSleepTime(millis: String?) -> Double { + (Double(millis ?? "0") ?? 0) / 1000 +} + @objc(MyNativeAudio) public class MyNativeAudio: CAPPlugin { var currentCall: CAPPluginCall? @@ -10,10 +14,8 @@ public class MyNativeAudio: CAPPlugin { var playerContext = 0 - override public func load() { - NSLog("Load MyNativeAudio") - // NotificationCenter.default.addObserver(self, selector: #selector(stop), name: Notification.Name.AVPlayerItemDidPlayToEndTime, object: nil) - } + var currentSleepTimer: Timer? = nil + var remainingSleepDuration: Double = 0 @objc func initPlayer(_ call: CAPPluginCall) { NSLog("Init Player") @@ -32,13 +34,18 @@ public class MyNativeAudio: CAPPlugin { token: call.getString("token") ?? "" ) + let playWhenReady = call.getBool("playWhenReady", false) if self.currentPlayer != nil && self.currentPlayer?.audiobook.streamId == audiobook.streamId { + if playWhenReady { + self.currentPlayer?.play() + } + call.resolve(["success": true]) return } - self.currentPlayer = AudioPlayer(audiobook: audiobook, playWhenReady: call.getBool("playWhenReady", false)) + self.currentPlayer = AudioPlayer(audiobook: audiobook, playWhenReady: playWhenReady) self.currentPlayer!.addObserver(self, forKeyPath: #keyPath(AudioPlayer.status), options: .new, context: &playerContext) call.resolve(["success": true]) @@ -148,6 +155,7 @@ public class MyNativeAudio: CAPPlugin { call.resolve([ "isPlaying": self.currentPlayer!.rate > 0.0, "lastPauseTime": 0, "id": self.currentPlayer?.audiobook.streamId as Any ]) } + @objc func setPlaybackSpeed(_ call: CAPPluginCall) { if self.currentPlayer == nil { call.resolve() @@ -160,11 +168,104 @@ public class MyNativeAudio: CAPPlugin { call.resolve() } + @objc func setSleepTimer(_ call: CAPPluginCall) { + if self.currentPlayer == nil { + call.resolve() + return + } + + let time = parseSleepTime(millis: call.getString("time")) + setSleepTimer(seconds: time) + + call.resolve([ "success": true ]) + } + @objc func increaseSleepTime(_ call: CAPPluginCall) { + if self.currentPlayer == nil { + call.resolve() + return + } + + var time = self.remainingSleepDuration + parseSleepTime(millis: call.getString("time")) + if time > self.currentPlayer!.getDuration() { + time = self.currentPlayer!.getDuration() + } + + setSleepTimer(seconds: time) + call.resolve([ "success": true ]) + } + @objc func decreaseSleepTime(_ call: CAPPluginCall) { + if self.currentSleepTimer == nil { + call.resolve() + return + } + + var time = parseSleepTime(millis: call.getString("time")) + if time < 0 { + time = 0 + } + + setSleepTimer(seconds: time) + call.resolve([ + "success": true, + ]) + } + @objc func cancelSleepTimer(_ call: CAPPluginCall) { + setSleepTimer(seconds: 0) + call.resolve([ + "success": true, + ]) + } + + func setSleepTimer(seconds: Double) { + if currentPlayer == nil { + return + } + + remainingSleepDuration = seconds + currentSleepTimer?.invalidate() + + self.notifyListeners("onSleepTimerSet", data: [ + "value": self.remainingSleepDuration, + ]) + + if seconds == 0 { + return + } + + DispatchQueue.main.async { + self.currentSleepTimer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { timer in + self.updateSleepTime() + } + } + } + func updateSleepTime() { + if currentPlayer == nil { + return + } + + if self.remainingSleepDuration <= 0 { + if currentSleepTimer != nil { + currentSleepTimer!.invalidate() + } + self.notifyListeners("onSleepTimerEnded", data: [ + "value": currentPlayer!.getCurrentTime(), + ]) + + currentPlayer!.pause() + return + } + + remainingSleepDuration -= 1 + self.notifyListeners("onSleepTimerSet", data: [ + "value": self.remainingSleepDuration, + ]) + } + func sendMetadata() { if self.currentPlayer == nil { return } - + self.notifyListeners("onMetadata", data: [ "duration": self.currentPlayer!.getDuration() * 1000, "currentTime": self.currentPlayer!.getCurrentTime() * 1000,