- Changes icon
- Improved state sync - Moved player to shared
|
@ -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() {
|
||||
|
|
|
@ -63,10 +63,19 @@
|
|||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
3AC8248B27F2316900529205 /* Shared */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
3AFCB5E527EA232A00ECCC05 /* models */,
|
||||
3AFCB5E627EA23F700ECCC05 /* util */,
|
||||
3A200C1427D64D7E00CBF02E /* AudioPlayer.swift */,
|
||||
);
|
||||
path = Shared;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
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;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
300
ios/App/App/Assets.xcassets/Icons.appiconset/Contents.json
Normal file
|
@ -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
|
||||
}
|
||||
}
|
BIN
ios/App/App/Assets.xcassets/Icons.appiconset/icon-100.png
Normal file
After Width: | Height: | Size: 6.9 KiB |
BIN
ios/App/App/Assets.xcassets/Icons.appiconset/icon-1024.png
Normal file
After Width: | Height: | Size: 605 KiB |
BIN
ios/App/App/Assets.xcassets/Icons.appiconset/icon-120.png
Normal file
After Width: | Height: | Size: 8.8 KiB |
BIN
ios/App/App/Assets.xcassets/Icons.appiconset/icon-128.png
Normal file
After Width: | Height: | Size: 9.7 KiB |
BIN
ios/App/App/Assets.xcassets/Icons.appiconset/icon-152.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
ios/App/App/Assets.xcassets/Icons.appiconset/icon-16.png
Normal file
After Width: | Height: | Size: 743 B |
BIN
ios/App/App/Assets.xcassets/Icons.appiconset/icon-167.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
ios/App/App/Assets.xcassets/Icons.appiconset/icon-172.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
ios/App/App/Assets.xcassets/Icons.appiconset/icon-180.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
ios/App/App/Assets.xcassets/Icons.appiconset/icon-196.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
ios/App/App/Assets.xcassets/Icons.appiconset/icon-20.png
Normal file
After Width: | Height: | Size: 927 B |
BIN
ios/App/App/Assets.xcassets/Icons.appiconset/icon-216.png
Normal file
After Width: | Height: | Size: 23 KiB |
BIN
ios/App/App/Assets.xcassets/Icons.appiconset/icon-256.png
Normal file
After Width: | Height: | Size: 33 KiB |
BIN
ios/App/App/Assets.xcassets/Icons.appiconset/icon-29.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
ios/App/App/Assets.xcassets/Icons.appiconset/icon-32.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
ios/App/App/Assets.xcassets/Icons.appiconset/icon-40.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
ios/App/App/Assets.xcassets/Icons.appiconset/icon-48.png
Normal file
After Width: | Height: | Size: 2.6 KiB |
BIN
ios/App/App/Assets.xcassets/Icons.appiconset/icon-512.png
Normal file
After Width: | Height: | Size: 118 KiB |
BIN
ios/App/App/Assets.xcassets/Icons.appiconset/icon-55.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
ios/App/App/Assets.xcassets/Icons.appiconset/icon-58.png
Normal file
After Width: | Height: | Size: 3.3 KiB |
BIN
ios/App/App/Assets.xcassets/Icons.appiconset/icon-60.png
Normal file
After Width: | Height: | Size: 3.6 KiB |
BIN
ios/App/App/Assets.xcassets/Icons.appiconset/icon-64.png
Normal file
After Width: | Height: | Size: 3.7 KiB |
BIN
ios/App/App/Assets.xcassets/Icons.appiconset/icon-76.png
Normal file
After Width: | Height: | Size: 4.7 KiB |
BIN
ios/App/App/Assets.xcassets/Icons.appiconset/icon-80.png
Normal file
After Width: | Height: | Size: 5 KiB |
BIN
ios/App/App/Assets.xcassets/Icons.appiconset/icon-87.png
Normal file
After Width: | Height: | Size: 5.8 KiB |
BIN
ios/App/App/Assets.xcassets/Icons.appiconset/icon-88.png
Normal file
After Width: | Height: | Size: 5.8 KiB |
|
@ -5,7 +5,7 @@
|
|||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>audiobookshelf-app</string>
|
||||
<string>Audiobookshelf</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
|
@ -27,6 +27,10 @@
|
|||
<key>NSAllowsArbitraryLoads</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>NSUserActivityTypes</key>
|
||||
<array>
|
||||
<string>INPlayMediaIntent</string>
|
||||
</array>
|
||||
<key>UIBackgroundModes</key>
|
||||
<array>
|
||||
<string>audio</string>
|
||||
|
|
|
@ -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,22 +33,27 @@ 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 {
|
||||
|
@ -58,37 +61,39 @@ public class MyNativeAudio: CAPPlugin {
|
|||
return
|
||||
}
|
||||
|
||||
if keyPath == #keyPath(AudioPlayer.status) {
|
||||
NSLog("AudioPlayer state change: \(String(describing: keyPath))")
|
||||
|
||||
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: [
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
@ -167,9 +168,8 @@ class AudioPlayer: NSObject {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// 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?
|
||||
}
|