diff --git a/components/app/AudioPlayer.vue b/components/app/AudioPlayer.vue index 7a207f5d..69f5def9 100644 --- a/components/app/AudioPlayer.vue +++ b/components/app/AudioPlayer.vue @@ -658,6 +658,10 @@ export default { this.setFromObj() } + console.log("received metadata update", data); + + if(data.currentRate && data.currentRate > 0) this.playbackSpeed = data.currentRate + this.timeupdate() }, async init() { diff --git a/ios/App/App.xcodeproj/project.pbxproj b/ios/App/App.xcodeproj/project.pbxproj index e5de21af..609fd2ff 100644 --- a/ios/App/App.xcodeproj/project.pbxproj +++ b/ios/App/App.xcodeproj/project.pbxproj @@ -63,10 +63,19 @@ name = Frameworks; sourceTree = ""; }; + 3AC8248B27F2316900529205 /* Shared */ = { + isa = PBXGroup; + children = ( + 3AFCB5E527EA232A00ECCC05 /* models */, + 3AFCB5E627EA23F700ECCC05 /* util */, + 3A200C1427D64D7E00CBF02E /* AudioPlayer.swift */, + ); + path = Shared; + sourceTree = ""; + }; 3AFCB5E427EA231D00ECCC05 /* audio */ = { isa = PBXGroup; children = ( - 3A200C1427D64D7E00CBF02E /* AudioPlayer.swift */, 4D8D410B26E17C3A00BA5F0D /* MyNativeAudio.swift */, 4D8D412D26E187E500BA5F0D /* MyNativeAudio.m */, ); @@ -92,6 +101,7 @@ 504EC2FB1FED79650016851F = { isa = PBXGroup; children = ( + 3AC8248B27F2316900529205 /* Shared */, 504EC3061FED79650016851F /* App */, 504EC3051FED79650016851F /* Products */, 7F8756D8B27F46E3366F6CEA /* Pods */, @@ -110,8 +120,6 @@ 504EC3061FED79650016851F /* App */ = { isa = PBXGroup; children = ( - 3AFCB5E627EA23F700ECCC05 /* util */, - 3AFCB5E527EA232A00ECCC05 /* models */, 3AFCB5E427EA231D00ECCC05 /* audio */, 50379B222058CBB4000EE86E /* capacitor.config.json */, 504EC3071FED79650016851F /* AppDelegate.swift */, @@ -163,8 +171,8 @@ 504EC2FC1FED79650016851F /* Project object */ = { isa = PBXProject; attributes = { - LastSwiftUpdateCheck = 0920; - LastUpgradeCheck = 0920; + LastSwiftUpdateCheck = 920; + LastUpgradeCheck = 920; TargetAttributes = { 504EC3031FED79650016851F = { CreatedOnToolsVersion = 9.2; @@ -390,7 +398,7 @@ isa = XCBuildConfiguration; baseConfigurationReference = FC68EB0AF532CFC21C3344DD /* Pods-App.debug.xcconfig */; buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_APPICON_NAME = Icons; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 3; @@ -414,7 +422,7 @@ isa = XCBuildConfiguration; baseConfigurationReference = AF51FD2D460BCFE21FA515B2 /* Pods-App.release.xcconfig */; buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_APPICON_NAME = Icons; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 3; diff --git a/ios/App/App/Assets.xcassets/Contents.json b/ios/App/App/Assets.xcassets/Contents.json index da4a164c..73c00596 100644 --- a/ios/App/App/Assets.xcassets/Contents.json +++ b/ios/App/App/Assets.xcassets/Contents.json @@ -1,6 +1,6 @@ { "info" : { - "version" : 1, - "author" : "xcode" + "author" : "xcode", + "version" : 1 } -} \ No newline at end of file +} diff --git a/ios/App/App/Assets.xcassets/Icons.appiconset/Contents.json b/ios/App/App/Assets.xcassets/Icons.appiconset/Contents.json new file mode 100644 index 00000000..b6cf3532 --- /dev/null +++ b/ios/App/App/Assets.xcassets/Icons.appiconset/Contents.json @@ -0,0 +1,300 @@ +{ + "images" : [ + { + "filename" : "icon-40.png", + "idiom" : "iphone", + "scale" : "2x", + "size" : "20x20" + }, + { + "filename" : "icon-60.png", + "idiom" : "iphone", + "scale" : "3x", + "size" : "20x20" + }, + { + "filename" : "icon-58.png", + "idiom" : "iphone", + "scale" : "2x", + "size" : "29x29" + }, + { + "filename" : "icon-87.png", + "idiom" : "iphone", + "scale" : "3x", + "size" : "29x29" + }, + { + "filename" : "icon-80.png", + "idiom" : "iphone", + "scale" : "2x", + "size" : "40x40" + }, + { + "filename" : "icon-120.png", + "idiom" : "iphone", + "scale" : "3x", + "size" : "40x40" + }, + { + "filename" : "icon-120.png", + "idiom" : "iphone", + "scale" : "2x", + "size" : "60x60" + }, + { + "filename" : "icon-180.png", + "idiom" : "iphone", + "scale" : "3x", + "size" : "60x60" + }, + { + "filename" : "icon-20.png", + "idiom" : "ipad", + "scale" : "1x", + "size" : "20x20" + }, + { + "filename" : "icon-40.png", + "idiom" : "ipad", + "scale" : "2x", + "size" : "20x20" + }, + { + "filename" : "icon-29.png", + "idiom" : "ipad", + "scale" : "1x", + "size" : "29x29" + }, + { + "filename" : "icon-58.png", + "idiom" : "ipad", + "scale" : "2x", + "size" : "29x29" + }, + { + "filename" : "icon-40.png", + "idiom" : "ipad", + "scale" : "1x", + "size" : "40x40" + }, + { + "filename" : "icon-80.png", + "idiom" : "ipad", + "scale" : "2x", + "size" : "40x40" + }, + { + "filename" : "icon-76.png", + "idiom" : "ipad", + "scale" : "1x", + "size" : "76x76" + }, + { + "filename" : "icon-152.png", + "idiom" : "ipad", + "scale" : "2x", + "size" : "76x76" + }, + { + "filename" : "icon-167.png", + "idiom" : "ipad", + "scale" : "2x", + "size" : "83.5x83.5" + }, + { + "filename" : "icon-1024.png", + "idiom" : "ios-marketing", + "scale" : "1x", + "size" : "1024x1024" + }, + { + "filename" : "icon-120.png", + "idiom" : "car", + "scale" : "2x", + "size" : "60x60" + }, + { + "filename" : "icon-180.png", + "idiom" : "car", + "scale" : "3x", + "size" : "60x60" + }, + { + "filename" : "icon-48.png", + "idiom" : "watch", + "role" : "notificationCenter", + "scale" : "2x", + "size" : "24x24", + "subtype" : "38mm" + }, + { + "filename" : "icon-55.png", + "idiom" : "watch", + "role" : "notificationCenter", + "scale" : "2x", + "size" : "27.5x27.5", + "subtype" : "42mm" + }, + { + "filename" : "icon-58.png", + "idiom" : "watch", + "role" : "companionSettings", + "scale" : "2x", + "size" : "29x29" + }, + { + "filename" : "icon-87.png", + "idiom" : "watch", + "role" : "companionSettings", + "scale" : "3x", + "size" : "29x29" + }, + { + "idiom" : "watch", + "role" : "notificationCenter", + "scale" : "2x", + "size" : "33x33", + "subtype" : "45mm" + }, + { + "filename" : "icon-80.png", + "idiom" : "watch", + "role" : "appLauncher", + "scale" : "2x", + "size" : "40x40", + "subtype" : "38mm" + }, + { + "filename" : "icon-88.png", + "idiom" : "watch", + "role" : "appLauncher", + "scale" : "2x", + "size" : "44x44", + "subtype" : "40mm" + }, + { + "idiom" : "watch", + "role" : "appLauncher", + "scale" : "2x", + "size" : "46x46", + "subtype" : "41mm" + }, + { + "filename" : "icon-100.png", + "idiom" : "watch", + "role" : "appLauncher", + "scale" : "2x", + "size" : "50x50", + "subtype" : "44mm" + }, + { + "idiom" : "watch", + "role" : "appLauncher", + "scale" : "2x", + "size" : "51x51", + "subtype" : "45mm" + }, + { + "filename" : "icon-172.png", + "idiom" : "watch", + "role" : "quickLook", + "scale" : "2x", + "size" : "86x86", + "subtype" : "38mm" + }, + { + "filename" : "icon-196.png", + "idiom" : "watch", + "role" : "quickLook", + "scale" : "2x", + "size" : "98x98", + "subtype" : "42mm" + }, + { + "filename" : "icon-216.png", + "idiom" : "watch", + "role" : "quickLook", + "scale" : "2x", + "size" : "108x108", + "subtype" : "44mm" + }, + { + "idiom" : "watch", + "role" : "quickLook", + "scale" : "2x", + "size" : "117x117", + "subtype" : "45mm" + }, + { + "filename" : "icon-1024.png", + "idiom" : "watch-marketing", + "scale" : "1x", + "size" : "1024x1024" + }, + { + "filename" : "icon-16.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "16x16" + }, + { + "filename" : "icon-32.png", + "idiom" : "mac", + "scale" : "2x", + "size" : "16x16" + }, + { + "filename" : "icon-32.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "32x32" + }, + { + "filename" : "icon-64.png", + "idiom" : "mac", + "scale" : "2x", + "size" : "32x32" + }, + { + "filename" : "icon-128.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "128x128" + }, + { + "filename" : "icon-256.png", + "idiom" : "mac", + "scale" : "2x", + "size" : "128x128" + }, + { + "filename" : "icon-256.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "256x256" + }, + { + "filename" : "icon-512.png", + "idiom" : "mac", + "scale" : "2x", + "size" : "256x256" + }, + { + "filename" : "icon-512.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "512x512" + }, + { + "filename" : "icon-1024.png", + "idiom" : "mac", + "scale" : "2x", + "size" : "512x512" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ios/App/App/Assets.xcassets/Icons.appiconset/icon-100.png b/ios/App/App/Assets.xcassets/Icons.appiconset/icon-100.png new file mode 100644 index 00000000..a2012986 Binary files /dev/null and b/ios/App/App/Assets.xcassets/Icons.appiconset/icon-100.png differ diff --git a/ios/App/App/Assets.xcassets/Icons.appiconset/icon-1024.png b/ios/App/App/Assets.xcassets/Icons.appiconset/icon-1024.png new file mode 100644 index 00000000..39148ab5 Binary files /dev/null and b/ios/App/App/Assets.xcassets/Icons.appiconset/icon-1024.png differ diff --git a/ios/App/App/Assets.xcassets/Icons.appiconset/icon-120.png b/ios/App/App/Assets.xcassets/Icons.appiconset/icon-120.png new file mode 100644 index 00000000..092397d0 Binary files /dev/null and b/ios/App/App/Assets.xcassets/Icons.appiconset/icon-120.png differ diff --git a/ios/App/App/Assets.xcassets/Icons.appiconset/icon-128.png b/ios/App/App/Assets.xcassets/Icons.appiconset/icon-128.png new file mode 100644 index 00000000..cfdc5709 Binary files /dev/null and b/ios/App/App/Assets.xcassets/Icons.appiconset/icon-128.png differ diff --git a/ios/App/App/Assets.xcassets/Icons.appiconset/icon-152.png b/ios/App/App/Assets.xcassets/Icons.appiconset/icon-152.png new file mode 100644 index 00000000..98b1da72 Binary files /dev/null and b/ios/App/App/Assets.xcassets/Icons.appiconset/icon-152.png differ diff --git a/ios/App/App/Assets.xcassets/Icons.appiconset/icon-16.png b/ios/App/App/Assets.xcassets/Icons.appiconset/icon-16.png new file mode 100644 index 00000000..884017e8 Binary files /dev/null and b/ios/App/App/Assets.xcassets/Icons.appiconset/icon-16.png differ diff --git a/ios/App/App/Assets.xcassets/Icons.appiconset/icon-167.png b/ios/App/App/Assets.xcassets/Icons.appiconset/icon-167.png new file mode 100644 index 00000000..75c527d4 Binary files /dev/null and b/ios/App/App/Assets.xcassets/Icons.appiconset/icon-167.png differ diff --git a/ios/App/App/Assets.xcassets/Icons.appiconset/icon-172.png b/ios/App/App/Assets.xcassets/Icons.appiconset/icon-172.png new file mode 100644 index 00000000..f85dea75 Binary files /dev/null and b/ios/App/App/Assets.xcassets/Icons.appiconset/icon-172.png differ diff --git a/ios/App/App/Assets.xcassets/Icons.appiconset/icon-180.png b/ios/App/App/Assets.xcassets/Icons.appiconset/icon-180.png new file mode 100644 index 00000000..11dadab1 Binary files /dev/null and b/ios/App/App/Assets.xcassets/Icons.appiconset/icon-180.png differ diff --git a/ios/App/App/Assets.xcassets/Icons.appiconset/icon-196.png b/ios/App/App/Assets.xcassets/Icons.appiconset/icon-196.png new file mode 100644 index 00000000..4364981c Binary files /dev/null and b/ios/App/App/Assets.xcassets/Icons.appiconset/icon-196.png differ diff --git a/ios/App/App/Assets.xcassets/Icons.appiconset/icon-20.png b/ios/App/App/Assets.xcassets/Icons.appiconset/icon-20.png new file mode 100644 index 00000000..aab3e347 Binary files /dev/null and b/ios/App/App/Assets.xcassets/Icons.appiconset/icon-20.png differ diff --git a/ios/App/App/Assets.xcassets/Icons.appiconset/icon-216.png b/ios/App/App/Assets.xcassets/Icons.appiconset/icon-216.png new file mode 100644 index 00000000..3667e612 Binary files /dev/null and b/ios/App/App/Assets.xcassets/Icons.appiconset/icon-216.png differ diff --git a/ios/App/App/Assets.xcassets/Icons.appiconset/icon-256.png b/ios/App/App/Assets.xcassets/Icons.appiconset/icon-256.png new file mode 100644 index 00000000..4deb595b Binary files /dev/null and b/ios/App/App/Assets.xcassets/Icons.appiconset/icon-256.png differ diff --git a/ios/App/App/Assets.xcassets/Icons.appiconset/icon-29.png b/ios/App/App/Assets.xcassets/Icons.appiconset/icon-29.png new file mode 100644 index 00000000..5c185e61 Binary files /dev/null and b/ios/App/App/Assets.xcassets/Icons.appiconset/icon-29.png differ diff --git a/ios/App/App/Assets.xcassets/Icons.appiconset/icon-32.png b/ios/App/App/Assets.xcassets/Icons.appiconset/icon-32.png new file mode 100644 index 00000000..5154b101 Binary files /dev/null and b/ios/App/App/Assets.xcassets/Icons.appiconset/icon-32.png differ diff --git a/ios/App/App/Assets.xcassets/Icons.appiconset/icon-40.png b/ios/App/App/Assets.xcassets/Icons.appiconset/icon-40.png new file mode 100644 index 00000000..c5370e3e Binary files /dev/null and b/ios/App/App/Assets.xcassets/Icons.appiconset/icon-40.png differ diff --git a/ios/App/App/Assets.xcassets/Icons.appiconset/icon-48.png b/ios/App/App/Assets.xcassets/Icons.appiconset/icon-48.png new file mode 100644 index 00000000..17fe3e55 Binary files /dev/null and b/ios/App/App/Assets.xcassets/Icons.appiconset/icon-48.png differ diff --git a/ios/App/App/Assets.xcassets/Icons.appiconset/icon-512.png b/ios/App/App/Assets.xcassets/Icons.appiconset/icon-512.png new file mode 100644 index 00000000..8d63f211 Binary files /dev/null and b/ios/App/App/Assets.xcassets/Icons.appiconset/icon-512.png differ diff --git a/ios/App/App/Assets.xcassets/Icons.appiconset/icon-55.png b/ios/App/App/Assets.xcassets/Icons.appiconset/icon-55.png new file mode 100644 index 00000000..470f98b8 Binary files /dev/null and b/ios/App/App/Assets.xcassets/Icons.appiconset/icon-55.png differ diff --git a/ios/App/App/Assets.xcassets/Icons.appiconset/icon-58.png b/ios/App/App/Assets.xcassets/Icons.appiconset/icon-58.png new file mode 100644 index 00000000..c5b87735 Binary files /dev/null and b/ios/App/App/Assets.xcassets/Icons.appiconset/icon-58.png differ diff --git a/ios/App/App/Assets.xcassets/Icons.appiconset/icon-60.png b/ios/App/App/Assets.xcassets/Icons.appiconset/icon-60.png new file mode 100644 index 00000000..ee4d315e Binary files /dev/null and b/ios/App/App/Assets.xcassets/Icons.appiconset/icon-60.png differ diff --git a/ios/App/App/Assets.xcassets/Icons.appiconset/icon-64.png b/ios/App/App/Assets.xcassets/Icons.appiconset/icon-64.png new file mode 100644 index 00000000..9975fcff Binary files /dev/null and b/ios/App/App/Assets.xcassets/Icons.appiconset/icon-64.png differ diff --git a/ios/App/App/Assets.xcassets/Icons.appiconset/icon-76.png b/ios/App/App/Assets.xcassets/Icons.appiconset/icon-76.png new file mode 100644 index 00000000..2a65b66f Binary files /dev/null and b/ios/App/App/Assets.xcassets/Icons.appiconset/icon-76.png differ diff --git a/ios/App/App/Assets.xcassets/Icons.appiconset/icon-80.png b/ios/App/App/Assets.xcassets/Icons.appiconset/icon-80.png new file mode 100644 index 00000000..0902d017 Binary files /dev/null and b/ios/App/App/Assets.xcassets/Icons.appiconset/icon-80.png differ diff --git a/ios/App/App/Assets.xcassets/Icons.appiconset/icon-87.png b/ios/App/App/Assets.xcassets/Icons.appiconset/icon-87.png new file mode 100644 index 00000000..8db3dee9 Binary files /dev/null and b/ios/App/App/Assets.xcassets/Icons.appiconset/icon-87.png differ diff --git a/ios/App/App/Assets.xcassets/Icons.appiconset/icon-88.png b/ios/App/App/Assets.xcassets/Icons.appiconset/icon-88.png new file mode 100644 index 00000000..1599cca5 Binary files /dev/null and b/ios/App/App/Assets.xcassets/Icons.appiconset/icon-88.png differ diff --git a/ios/App/App/Info.plist b/ios/App/App/Info.plist index 8b5bcb77..80bdbcb0 100644 --- a/ios/App/App/Info.plist +++ b/ios/App/App/Info.plist @@ -5,7 +5,7 @@ CFBundleDevelopmentRegion en CFBundleDisplayName - audiobookshelf-app + Audiobookshelf CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier @@ -27,6 +27,10 @@ NSAllowsArbitraryLoads + NSUserActivityTypes + + INPlayMediaIntent + UIBackgroundModes audio diff --git a/ios/App/App/audio/MyNativeAudio.swift b/ios/App/App/audio/MyNativeAudio.swift index 760e8b01..a3286274 100644 --- a/ios/App/App/audio/MyNativeAudio.swift +++ b/ios/App/App/audio/MyNativeAudio.swift @@ -9,8 +9,6 @@ func parseSleepTime(millis: String?) -> Double { @objc(MyNativeAudio) public class MyNativeAudio: CAPPlugin { - var currentPlayer: AudioPlayer? - var playerContext = 0 var currentSleepTimer: Timer? = nil @@ -35,60 +33,67 @@ public class MyNativeAudio: CAPPlugin { ) let playWhenReady = call.getBool("playWhenReady", false) - if currentPlayer != nil && currentPlayer?.audiobook.streamId == audiobook.streamId { + if AudioPlayer.instance != nil && AudioPlayer.instance?.audiobook.streamId == audiobook.streamId { if playWhenReady { - self.currentPlayer?.play() + AudioPlayer.instance?.play() } call.resolve(["success": true]) return - } else if currentPlayer != nil && currentPlayer?.audiobook.streamId != audiobook.streamId { + } else if AudioPlayer.instance != nil && AudioPlayer.instance?.audiobook.streamId != audiobook.streamId { stop() } - currentPlayer = AudioPlayer(audiobook: audiobook, playWhenReady: playWhenReady) - currentPlayer!.addObserver(self, forKeyPath: #keyPath(AudioPlayer.status), options: .new, context: &playerContext) + AudioPlayer.instance = AudioPlayer(audiobook: audiobook, playWhenReady: playWhenReady) + AudioPlayer.instance!.addObserver(self, forKeyPath: #keyPath(AudioPlayer.status), options: .new, context: &playerContext) call.resolve(["success": true]) } + override public func load() { + NSLog("Load MyNativeAudio") + NotificationCenter.default.addObserver(self, selector: #selector(sendMetadata), name: UIApplication.willEnterForegroundNotification, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(sendMetadata), name: UIApplication.didBecomeActiveNotification, object: nil) + } public override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { guard context == &playerContext else { super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context) return } + + NSLog("AudioPlayer state change: \(String(describing: keyPath))") - if keyPath == #keyPath(AudioPlayer.status) { + if keyPath == #keyPath(AudioPlayer.status) || keyPath == #keyPath(AudioPlayer.rate) { sendMetadata() } } @objc func seekForward(_ call: CAPPluginCall) { - if self.currentPlayer == nil { + if AudioPlayer.instance == nil { call.resolve() return } let amount = (Double(call.getString("amount", "0")) ?? 0) / 1000 - let destinationTime = self.currentPlayer!.getCurrentTime() + amount + let destinationTime = AudioPlayer.instance!.getCurrentTime() + amount - self.currentPlayer!.seek(destinationTime) + AudioPlayer.instance!.seek(destinationTime) call.resolve() } @objc func seekBackward(_ call: CAPPluginCall) { - if self.currentPlayer == nil { + if AudioPlayer.instance == nil { call.resolve() return } let amount = (Double(call.getString("amount", "0")) ?? 0) / 1000 - let destinationTime = self.currentPlayer!.getCurrentTime() - amount + let destinationTime = AudioPlayer.instance!.getCurrentTime() - amount - self.currentPlayer!.seek(destinationTime) + AudioPlayer.instance!.seek(destinationTime) call.resolve() } @objc func seekPlayer(_ call: CAPPluginCall) { - if self.currentPlayer == nil { + if AudioPlayer.instance == nil { call.resolve() return } @@ -96,28 +101,28 @@ public class MyNativeAudio: CAPPlugin { let seekTime = (Double(call.getString("timeMs", "0")) ?? 0) / 1000 NSLog("Seek Player \(seekTime)") - self.currentPlayer!.seek(seekTime) + AudioPlayer.instance!.seek(seekTime) call.resolve() } @objc func pausePlayer(_ call: CAPPluginCall) { - if self.currentPlayer == nil { + if AudioPlayer.instance == nil { call.resolve() return } - self.currentPlayer!.pause() + AudioPlayer.instance!.pause() sendPlaybackStatusUpdate(false) call.resolve() } @objc func playPlayer(_ call: CAPPluginCall) { - if self.currentPlayer == nil { + if AudioPlayer.instance == nil { call.resolve() return } - self.currentPlayer!.play(allowSeekBack: true) + AudioPlayer.instance!.play(allowSeekBack: true) sendPlaybackStatusUpdate(true) call.resolve() @@ -128,10 +133,10 @@ public class MyNativeAudio: CAPPlugin { call.resolve() } @objc func stop(_ call: CAPPluginCall? = nil) { - if self.currentPlayer != nil { - self.currentPlayer!.destroy() + if AudioPlayer.instance != nil { + AudioPlayer.instance!.destroy() } - self.currentPlayer = nil + AudioPlayer.instance = nil if call != nil { call!.resolve([ "result": true ]) @@ -139,37 +144,37 @@ public class MyNativeAudio: CAPPlugin { } @objc func getCurrentTime(_ call: CAPPluginCall) { - if self.currentPlayer == nil { + if AudioPlayer.instance == nil { call.resolve() return } - let currentTime = self.currentPlayer?.getCurrentTime() ?? 0 + let currentTime = AudioPlayer.instance?.getCurrentTime() ?? 0 call.resolve([ "value": currentTime * 1000, "bufferedTime": currentTime * 1000 ]) } @objc func getStreamSyncData(_ call: CAPPluginCall) { - if self.currentPlayer == nil { + if AudioPlayer.instance == nil { call.resolve([ "isPlaying": false, "lastPauseTime": 0, "id": nil ]) return } - call.resolve([ "isPlaying": self.currentPlayer!.rate > 0.0, "lastPauseTime": 0, "id": self.currentPlayer?.audiobook.streamId as Any ]) + call.resolve([ "isPlaying": AudioPlayer.instance!.rate > 0.0, "lastPauseTime": 0, "id": AudioPlayer.instance?.audiobook.streamId as Any ]) } @objc func setPlaybackSpeed(_ call: CAPPluginCall) { - if self.currentPlayer == nil { + if AudioPlayer.instance == nil { call.resolve() return } let speed = call.getFloat("speed") ?? 0 - self.currentPlayer!.setPlaybackRate(speed) + AudioPlayer.instance!.setPlaybackRate(speed) call.resolve() } @objc func setSleepTimer(_ call: CAPPluginCall) { - if self.currentPlayer == nil { + if AudioPlayer.instance == nil { call.resolve() return } @@ -180,14 +185,14 @@ public class MyNativeAudio: CAPPlugin { call.resolve([ "success": true ]) } @objc func increaseSleepTime(_ call: CAPPluginCall) { - if self.currentPlayer == nil { + if AudioPlayer.instance == nil { call.resolve() return } var time = self.remainingSleepDuration + parseSleepTime(millis: call.getString("time")) - if time > self.currentPlayer!.getDuration() { - time = self.currentPlayer!.getDuration() + if time > AudioPlayer.instance!.getDuration() { + time = AudioPlayer.instance!.getDuration() } setSleepTimer(seconds: time) @@ -217,7 +222,7 @@ public class MyNativeAudio: CAPPlugin { } func setSleepTimer(seconds: Double) { - if currentPlayer == nil { + if AudioPlayer.instance == nil { return } @@ -239,7 +244,7 @@ public class MyNativeAudio: CAPPlugin { } } func updateSleepTime() { - if currentPlayer == nil { + if AudioPlayer.instance == nil { return } @@ -248,10 +253,10 @@ public class MyNativeAudio: CAPPlugin { currentSleepTimer!.invalidate() } self.notifyListeners("onSleepTimerEnded", data: [ - "value": currentPlayer!.getCurrentTime(), + "value": AudioPlayer.instance!.getCurrentTime(), ]) - currentPlayer!.pause() + AudioPlayer.instance!.pause() return } @@ -261,16 +266,21 @@ public class MyNativeAudio: CAPPlugin { ]) } - func sendMetadata() { - if self.currentPlayer == nil { + @objc func sendMetadata() { + if AudioPlayer.instance == nil { return } + NSLog("fired metadata update") + self.notifyListeners("onMetadata", data: [ - "duration": self.currentPlayer!.getDuration() * 1000, - "currentTime": self.currentPlayer!.getCurrentTime() * 1000, - "stateName": "unknown" + "duration": AudioPlayer.instance!.getDuration() * 1000, + "currentTime": AudioPlayer.instance!.getCurrentTime() * 1000, + "stateName": "unknown", + + "currentRate": AudioPlayer.instance!.rate ]) + sendPlaybackStatusUpdate(AudioPlayer.instance!.rate != 0.0) } func sendPlaybackStatusUpdate(_ playing: Bool) { self.notifyListeners("onPlayingUpdate", data: [ diff --git a/ios/App/App/audio/AudioPlayer.swift b/ios/App/Shared/AudioPlayer.swift similarity index 96% rename from ios/App/App/audio/AudioPlayer.swift rename to ios/App/Shared/AudioPlayer.swift index e8e995b1..1ae90ca9 100644 --- a/ios/App/App/audio/AudioPlayer.swift +++ b/ios/App/Shared/AudioPlayer.swift @@ -26,6 +26,7 @@ class AudioPlayer: NSObject { private var audioPlayer: AVPlayer public var audiobook: Audiobook + // MARK: - Constructor init(audiobook: Audiobook, playWhenReady: Bool = false) { self.playWhenReady = playWhenReady self.audiobook = audiobook @@ -54,7 +55,7 @@ class AudioPlayer: NSObject { deinit { destroy() } - func destroy() { + public func destroy() { pause() audioPlayer.replaceCurrentItem(with: nil) @@ -166,10 +167,9 @@ class AudioPlayer: NSObject { print(error) } } - // MARK: - Now playing - func setupRemoteTransportControls() { + private func setupRemoteTransportControls() { DispatchQueue.main.sync { UIApplication.shared.beginReceivingRemoteControlEvents() } @@ -228,8 +228,7 @@ class AudioPlayer: NSObject { return .success } } - - func updateNowPlaying() { + private func updateNowPlaying() { NowPlayingInfo.update(duration: getDuration(), currentTime: getCurrentTime(), rate: rate) } @@ -240,7 +239,7 @@ class AudioPlayer: NSObject { guard let playerStatus = AVPlayerItem.Status(rawValue: (change?[.newKey] as? Int ?? -1)) else { return } if playerStatus == .readyToPlay { - updateNowPlaying() + self.updateNowPlaying() self.status = 0 if self.playWhenReady { @@ -251,7 +250,7 @@ class AudioPlayer: NSObject { } } else if context == &playerContext { if keyPath == #keyPath(AVPlayer.rate) { - setPlaybackRate(change?[.newKey] as? Float ?? 1.0, observed: true) + self.setPlaybackRate(change?[.newKey] as? Float ?? 1.0, observed: true) } else if keyPath == #keyPath(AVPlayer.currentItem) { NSLog("WARNING: Item ended") } @@ -260,4 +259,7 @@ class AudioPlayer: NSObject { return } } + + // MARK: - Factory + public static var instance: AudioPlayer? } diff --git a/ios/App/App/models/Audiobook.swift b/ios/App/Shared/models/Audiobook.swift similarity index 100% rename from ios/App/App/models/Audiobook.swift rename to ios/App/Shared/models/Audiobook.swift diff --git a/ios/App/App/util/NowPlayingInfo.swift b/ios/App/Shared/util/NowPlayingInfo.swift similarity index 100% rename from ios/App/App/util/NowPlayingInfo.swift rename to ios/App/Shared/util/NowPlayingInfo.swift