- Changes icon
- Improved state sync - Moved player to shared
|
@ -658,6 +658,10 @@ export default {
|
||||||
this.setFromObj()
|
this.setFromObj()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log("received metadata update", data);
|
||||||
|
|
||||||
|
if(data.currentRate && data.currentRate > 0) this.playbackSpeed = data.currentRate
|
||||||
|
|
||||||
this.timeupdate()
|
this.timeupdate()
|
||||||
},
|
},
|
||||||
async init() {
|
async init() {
|
||||||
|
|
|
@ -63,10 +63,19 @@
|
||||||
name = Frameworks;
|
name = Frameworks;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
3AC8248B27F2316900529205 /* Shared */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
3AFCB5E527EA232A00ECCC05 /* models */,
|
||||||
|
3AFCB5E627EA23F700ECCC05 /* util */,
|
||||||
|
3A200C1427D64D7E00CBF02E /* AudioPlayer.swift */,
|
||||||
|
);
|
||||||
|
path = Shared;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
3AFCB5E427EA231D00ECCC05 /* audio */ = {
|
3AFCB5E427EA231D00ECCC05 /* audio */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
3A200C1427D64D7E00CBF02E /* AudioPlayer.swift */,
|
|
||||||
4D8D410B26E17C3A00BA5F0D /* MyNativeAudio.swift */,
|
4D8D410B26E17C3A00BA5F0D /* MyNativeAudio.swift */,
|
||||||
4D8D412D26E187E500BA5F0D /* MyNativeAudio.m */,
|
4D8D412D26E187E500BA5F0D /* MyNativeAudio.m */,
|
||||||
);
|
);
|
||||||
|
@ -92,6 +101,7 @@
|
||||||
504EC2FB1FED79650016851F = {
|
504EC2FB1FED79650016851F = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
3AC8248B27F2316900529205 /* Shared */,
|
||||||
504EC3061FED79650016851F /* App */,
|
504EC3061FED79650016851F /* App */,
|
||||||
504EC3051FED79650016851F /* Products */,
|
504EC3051FED79650016851F /* Products */,
|
||||||
7F8756D8B27F46E3366F6CEA /* Pods */,
|
7F8756D8B27F46E3366F6CEA /* Pods */,
|
||||||
|
@ -110,8 +120,6 @@
|
||||||
504EC3061FED79650016851F /* App */ = {
|
504EC3061FED79650016851F /* App */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
3AFCB5E627EA23F700ECCC05 /* util */,
|
|
||||||
3AFCB5E527EA232A00ECCC05 /* models */,
|
|
||||||
3AFCB5E427EA231D00ECCC05 /* audio */,
|
3AFCB5E427EA231D00ECCC05 /* audio */,
|
||||||
50379B222058CBB4000EE86E /* capacitor.config.json */,
|
50379B222058CBB4000EE86E /* capacitor.config.json */,
|
||||||
504EC3071FED79650016851F /* AppDelegate.swift */,
|
504EC3071FED79650016851F /* AppDelegate.swift */,
|
||||||
|
@ -163,8 +171,8 @@
|
||||||
504EC2FC1FED79650016851F /* Project object */ = {
|
504EC2FC1FED79650016851F /* Project object */ = {
|
||||||
isa = PBXProject;
|
isa = PBXProject;
|
||||||
attributes = {
|
attributes = {
|
||||||
LastSwiftUpdateCheck = 0920;
|
LastSwiftUpdateCheck = 920;
|
||||||
LastUpgradeCheck = 0920;
|
LastUpgradeCheck = 920;
|
||||||
TargetAttributes = {
|
TargetAttributes = {
|
||||||
504EC3031FED79650016851F = {
|
504EC3031FED79650016851F = {
|
||||||
CreatedOnToolsVersion = 9.2;
|
CreatedOnToolsVersion = 9.2;
|
||||||
|
@ -390,7 +398,7 @@
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
baseConfigurationReference = FC68EB0AF532CFC21C3344DD /* Pods-App.debug.xcconfig */;
|
baseConfigurationReference = FC68EB0AF532CFC21C3344DD /* Pods-App.debug.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = Icons;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 3;
|
CURRENT_PROJECT_VERSION = 3;
|
||||||
|
@ -414,7 +422,7 @@
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
baseConfigurationReference = AF51FD2D460BCFE21FA515B2 /* Pods-App.release.xcconfig */;
|
baseConfigurationReference = AF51FD2D460BCFE21FA515B2 /* Pods-App.release.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = Icons;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 3;
|
CURRENT_PROJECT_VERSION = 3;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"info" : {
|
"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>
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
<string>en</string>
|
<string>en</string>
|
||||||
<key>CFBundleDisplayName</key>
|
<key>CFBundleDisplayName</key>
|
||||||
<string>audiobookshelf-app</string>
|
<string>Audiobookshelf</string>
|
||||||
<key>CFBundleExecutable</key>
|
<key>CFBundleExecutable</key>
|
||||||
<string>$(EXECUTABLE_NAME)</string>
|
<string>$(EXECUTABLE_NAME)</string>
|
||||||
<key>CFBundleIdentifier</key>
|
<key>CFBundleIdentifier</key>
|
||||||
|
@ -27,6 +27,10 @@
|
||||||
<key>NSAllowsArbitraryLoads</key>
|
<key>NSAllowsArbitraryLoads</key>
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
|
<key>NSUserActivityTypes</key>
|
||||||
|
<array>
|
||||||
|
<string>INPlayMediaIntent</string>
|
||||||
|
</array>
|
||||||
<key>UIBackgroundModes</key>
|
<key>UIBackgroundModes</key>
|
||||||
<array>
|
<array>
|
||||||
<string>audio</string>
|
<string>audio</string>
|
||||||
|
|
|
@ -9,8 +9,6 @@ func parseSleepTime(millis: String?) -> Double {
|
||||||
|
|
||||||
@objc(MyNativeAudio)
|
@objc(MyNativeAudio)
|
||||||
public class MyNativeAudio: CAPPlugin {
|
public class MyNativeAudio: CAPPlugin {
|
||||||
var currentPlayer: AudioPlayer?
|
|
||||||
|
|
||||||
var playerContext = 0
|
var playerContext = 0
|
||||||
|
|
||||||
var currentSleepTimer: Timer? = nil
|
var currentSleepTimer: Timer? = nil
|
||||||
|
@ -35,22 +33,27 @@ public class MyNativeAudio: CAPPlugin {
|
||||||
)
|
)
|
||||||
let playWhenReady = call.getBool("playWhenReady", false)
|
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 {
|
if playWhenReady {
|
||||||
self.currentPlayer?.play()
|
AudioPlayer.instance?.play()
|
||||||
}
|
}
|
||||||
|
|
||||||
call.resolve(["success": true])
|
call.resolve(["success": true])
|
||||||
return
|
return
|
||||||
} else if currentPlayer != nil && currentPlayer?.audiobook.streamId != audiobook.streamId {
|
} else if AudioPlayer.instance != nil && AudioPlayer.instance?.audiobook.streamId != audiobook.streamId {
|
||||||
stop()
|
stop()
|
||||||
}
|
}
|
||||||
|
|
||||||
currentPlayer = AudioPlayer(audiobook: audiobook, playWhenReady: playWhenReady)
|
AudioPlayer.instance = AudioPlayer(audiobook: audiobook, playWhenReady: playWhenReady)
|
||||||
currentPlayer!.addObserver(self, forKeyPath: #keyPath(AudioPlayer.status), options: .new, context: &playerContext)
|
AudioPlayer.instance!.addObserver(self, forKeyPath: #keyPath(AudioPlayer.status), options: .new, context: &playerContext)
|
||||||
|
|
||||||
call.resolve(["success": true])
|
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?) {
|
public override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
|
||||||
guard context == &playerContext else {
|
guard context == &playerContext else {
|
||||||
|
@ -58,37 +61,39 @@ public class MyNativeAudio: CAPPlugin {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if keyPath == #keyPath(AudioPlayer.status) {
|
NSLog("AudioPlayer state change: \(String(describing: keyPath))")
|
||||||
|
|
||||||
|
if keyPath == #keyPath(AudioPlayer.status) || keyPath == #keyPath(AudioPlayer.rate) {
|
||||||
sendMetadata()
|
sendMetadata()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func seekForward(_ call: CAPPluginCall) {
|
@objc func seekForward(_ call: CAPPluginCall) {
|
||||||
if self.currentPlayer == nil {
|
if AudioPlayer.instance == nil {
|
||||||
call.resolve()
|
call.resolve()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let amount = (Double(call.getString("amount", "0")) ?? 0) / 1000
|
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()
|
call.resolve()
|
||||||
}
|
}
|
||||||
@objc func seekBackward(_ call: CAPPluginCall) {
|
@objc func seekBackward(_ call: CAPPluginCall) {
|
||||||
if self.currentPlayer == nil {
|
if AudioPlayer.instance == nil {
|
||||||
call.resolve()
|
call.resolve()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let amount = (Double(call.getString("amount", "0")) ?? 0) / 1000
|
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()
|
call.resolve()
|
||||||
}
|
}
|
||||||
@objc func seekPlayer(_ call: CAPPluginCall) {
|
@objc func seekPlayer(_ call: CAPPluginCall) {
|
||||||
if self.currentPlayer == nil {
|
if AudioPlayer.instance == nil {
|
||||||
call.resolve()
|
call.resolve()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -96,28 +101,28 @@ public class MyNativeAudio: CAPPlugin {
|
||||||
let seekTime = (Double(call.getString("timeMs", "0")) ?? 0) / 1000
|
let seekTime = (Double(call.getString("timeMs", "0")) ?? 0) / 1000
|
||||||
NSLog("Seek Player \(seekTime)")
|
NSLog("Seek Player \(seekTime)")
|
||||||
|
|
||||||
self.currentPlayer!.seek(seekTime)
|
AudioPlayer.instance!.seek(seekTime)
|
||||||
call.resolve()
|
call.resolve()
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func pausePlayer(_ call: CAPPluginCall) {
|
@objc func pausePlayer(_ call: CAPPluginCall) {
|
||||||
if self.currentPlayer == nil {
|
if AudioPlayer.instance == nil {
|
||||||
call.resolve()
|
call.resolve()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
self.currentPlayer!.pause()
|
AudioPlayer.instance!.pause()
|
||||||
|
|
||||||
sendPlaybackStatusUpdate(false)
|
sendPlaybackStatusUpdate(false)
|
||||||
call.resolve()
|
call.resolve()
|
||||||
}
|
}
|
||||||
@objc func playPlayer(_ call: CAPPluginCall) {
|
@objc func playPlayer(_ call: CAPPluginCall) {
|
||||||
if self.currentPlayer == nil {
|
if AudioPlayer.instance == nil {
|
||||||
call.resolve()
|
call.resolve()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
self.currentPlayer!.play(allowSeekBack: true)
|
AudioPlayer.instance!.play(allowSeekBack: true)
|
||||||
|
|
||||||
sendPlaybackStatusUpdate(true)
|
sendPlaybackStatusUpdate(true)
|
||||||
call.resolve()
|
call.resolve()
|
||||||
|
@ -128,10 +133,10 @@ public class MyNativeAudio: CAPPlugin {
|
||||||
call.resolve()
|
call.resolve()
|
||||||
}
|
}
|
||||||
@objc func stop(_ call: CAPPluginCall? = nil) {
|
@objc func stop(_ call: CAPPluginCall? = nil) {
|
||||||
if self.currentPlayer != nil {
|
if AudioPlayer.instance != nil {
|
||||||
self.currentPlayer!.destroy()
|
AudioPlayer.instance!.destroy()
|
||||||
}
|
}
|
||||||
self.currentPlayer = nil
|
AudioPlayer.instance = nil
|
||||||
|
|
||||||
if call != nil {
|
if call != nil {
|
||||||
call!.resolve([ "result": true ])
|
call!.resolve([ "result": true ])
|
||||||
|
@ -139,37 +144,37 @@ public class MyNativeAudio: CAPPlugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func getCurrentTime(_ call: CAPPluginCall) {
|
@objc func getCurrentTime(_ call: CAPPluginCall) {
|
||||||
if self.currentPlayer == nil {
|
if AudioPlayer.instance == nil {
|
||||||
call.resolve()
|
call.resolve()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let currentTime = self.currentPlayer?.getCurrentTime() ?? 0
|
let currentTime = AudioPlayer.instance?.getCurrentTime() ?? 0
|
||||||
call.resolve([ "value": currentTime * 1000, "bufferedTime": currentTime * 1000 ])
|
call.resolve([ "value": currentTime * 1000, "bufferedTime": currentTime * 1000 ])
|
||||||
}
|
}
|
||||||
@objc func getStreamSyncData(_ call: CAPPluginCall) {
|
@objc func getStreamSyncData(_ call: CAPPluginCall) {
|
||||||
if self.currentPlayer == nil {
|
if AudioPlayer.instance == nil {
|
||||||
call.resolve([ "isPlaying": false, "lastPauseTime": 0, "id": nil ])
|
call.resolve([ "isPlaying": false, "lastPauseTime": 0, "id": nil ])
|
||||||
return
|
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) {
|
@objc func setPlaybackSpeed(_ call: CAPPluginCall) {
|
||||||
if self.currentPlayer == nil {
|
if AudioPlayer.instance == nil {
|
||||||
call.resolve()
|
call.resolve()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let speed = call.getFloat("speed") ?? 0
|
let speed = call.getFloat("speed") ?? 0
|
||||||
self.currentPlayer!.setPlaybackRate(speed)
|
AudioPlayer.instance!.setPlaybackRate(speed)
|
||||||
|
|
||||||
call.resolve()
|
call.resolve()
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func setSleepTimer(_ call: CAPPluginCall) {
|
@objc func setSleepTimer(_ call: CAPPluginCall) {
|
||||||
if self.currentPlayer == nil {
|
if AudioPlayer.instance == nil {
|
||||||
call.resolve()
|
call.resolve()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -180,14 +185,14 @@ public class MyNativeAudio: CAPPlugin {
|
||||||
call.resolve([ "success": true ])
|
call.resolve([ "success": true ])
|
||||||
}
|
}
|
||||||
@objc func increaseSleepTime(_ call: CAPPluginCall) {
|
@objc func increaseSleepTime(_ call: CAPPluginCall) {
|
||||||
if self.currentPlayer == nil {
|
if AudioPlayer.instance == nil {
|
||||||
call.resolve()
|
call.resolve()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var time = self.remainingSleepDuration + parseSleepTime(millis: call.getString("time"))
|
var time = self.remainingSleepDuration + parseSleepTime(millis: call.getString("time"))
|
||||||
if time > self.currentPlayer!.getDuration() {
|
if time > AudioPlayer.instance!.getDuration() {
|
||||||
time = self.currentPlayer!.getDuration()
|
time = AudioPlayer.instance!.getDuration()
|
||||||
}
|
}
|
||||||
|
|
||||||
setSleepTimer(seconds: time)
|
setSleepTimer(seconds: time)
|
||||||
|
@ -217,7 +222,7 @@ public class MyNativeAudio: CAPPlugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
func setSleepTimer(seconds: Double) {
|
func setSleepTimer(seconds: Double) {
|
||||||
if currentPlayer == nil {
|
if AudioPlayer.instance == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -239,7 +244,7 @@ public class MyNativeAudio: CAPPlugin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func updateSleepTime() {
|
func updateSleepTime() {
|
||||||
if currentPlayer == nil {
|
if AudioPlayer.instance == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,10 +253,10 @@ public class MyNativeAudio: CAPPlugin {
|
||||||
currentSleepTimer!.invalidate()
|
currentSleepTimer!.invalidate()
|
||||||
}
|
}
|
||||||
self.notifyListeners("onSleepTimerEnded", data: [
|
self.notifyListeners("onSleepTimerEnded", data: [
|
||||||
"value": currentPlayer!.getCurrentTime(),
|
"value": AudioPlayer.instance!.getCurrentTime(),
|
||||||
])
|
])
|
||||||
|
|
||||||
currentPlayer!.pause()
|
AudioPlayer.instance!.pause()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -261,16 +266,21 @@ public class MyNativeAudio: CAPPlugin {
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
func sendMetadata() {
|
@objc func sendMetadata() {
|
||||||
if self.currentPlayer == nil {
|
if AudioPlayer.instance == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NSLog("fired metadata update")
|
||||||
|
|
||||||
self.notifyListeners("onMetadata", data: [
|
self.notifyListeners("onMetadata", data: [
|
||||||
"duration": self.currentPlayer!.getDuration() * 1000,
|
"duration": AudioPlayer.instance!.getDuration() * 1000,
|
||||||
"currentTime": self.currentPlayer!.getCurrentTime() * 1000,
|
"currentTime": AudioPlayer.instance!.getCurrentTime() * 1000,
|
||||||
"stateName": "unknown"
|
"stateName": "unknown",
|
||||||
|
|
||||||
|
"currentRate": AudioPlayer.instance!.rate
|
||||||
])
|
])
|
||||||
|
sendPlaybackStatusUpdate(AudioPlayer.instance!.rate != 0.0)
|
||||||
}
|
}
|
||||||
func sendPlaybackStatusUpdate(_ playing: Bool) {
|
func sendPlaybackStatusUpdate(_ playing: Bool) {
|
||||||
self.notifyListeners("onPlayingUpdate", data: [
|
self.notifyListeners("onPlayingUpdate", data: [
|
||||||
|
|
|
@ -26,6 +26,7 @@ class AudioPlayer: NSObject {
|
||||||
private var audioPlayer: AVPlayer
|
private var audioPlayer: AVPlayer
|
||||||
public var audiobook: Audiobook
|
public var audiobook: Audiobook
|
||||||
|
|
||||||
|
// MARK: - Constructor
|
||||||
init(audiobook: Audiobook, playWhenReady: Bool = false) {
|
init(audiobook: Audiobook, playWhenReady: Bool = false) {
|
||||||
self.playWhenReady = playWhenReady
|
self.playWhenReady = playWhenReady
|
||||||
self.audiobook = audiobook
|
self.audiobook = audiobook
|
||||||
|
@ -54,7 +55,7 @@ class AudioPlayer: NSObject {
|
||||||
deinit {
|
deinit {
|
||||||
destroy()
|
destroy()
|
||||||
}
|
}
|
||||||
func destroy() {
|
public func destroy() {
|
||||||
pause()
|
pause()
|
||||||
audioPlayer.replaceCurrentItem(with: nil)
|
audioPlayer.replaceCurrentItem(with: nil)
|
||||||
|
|
||||||
|
@ -167,9 +168,8 @@ class AudioPlayer: NSObject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// MARK: - Now playing
|
// MARK: - Now playing
|
||||||
func setupRemoteTransportControls() {
|
private func setupRemoteTransportControls() {
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
UIApplication.shared.beginReceivingRemoteControlEvents()
|
UIApplication.shared.beginReceivingRemoteControlEvents()
|
||||||
}
|
}
|
||||||
|
@ -228,8 +228,7 @@ class AudioPlayer: NSObject {
|
||||||
return .success
|
return .success
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
private func updateNowPlaying() {
|
||||||
func updateNowPlaying() {
|
|
||||||
NowPlayingInfo.update(duration: getDuration(), currentTime: getCurrentTime(), rate: rate)
|
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 }
|
guard let playerStatus = AVPlayerItem.Status(rawValue: (change?[.newKey] as? Int ?? -1)) else { return }
|
||||||
|
|
||||||
if playerStatus == .readyToPlay {
|
if playerStatus == .readyToPlay {
|
||||||
updateNowPlaying()
|
self.updateNowPlaying()
|
||||||
|
|
||||||
self.status = 0
|
self.status = 0
|
||||||
if self.playWhenReady {
|
if self.playWhenReady {
|
||||||
|
@ -251,7 +250,7 @@ class AudioPlayer: NSObject {
|
||||||
}
|
}
|
||||||
} else if context == &playerContext {
|
} else if context == &playerContext {
|
||||||
if keyPath == #keyPath(AVPlayer.rate) {
|
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) {
|
} else if keyPath == #keyPath(AVPlayer.currentItem) {
|
||||||
NSLog("WARNING: Item ended")
|
NSLog("WARNING: Item ended")
|
||||||
}
|
}
|
||||||
|
@ -260,4 +259,7 @@ class AudioPlayer: NSObject {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - Factory
|
||||||
|
public static var instance: AudioPlayer?
|
||||||
}
|
}
|