mirror of
https://github.com/advplyr/audiobookshelf-app.git
synced 2025-07-13 07:24:55 +02:00
Added realm
This commit is contained in:
parent
2f4b3050fd
commit
c0ac3b7bb5
14 changed files with 19001 additions and 377 deletions
7
ionic.config.json
Normal file
7
ionic.config.json
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"name": "audiobookshelf-app",
|
||||||
|
"integrations": {
|
||||||
|
"capacitor": {}
|
||||||
|
},
|
||||||
|
"type": "custom"
|
||||||
|
}
|
|
@ -9,10 +9,14 @@
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
2FAD9763203C412B000D30F8 /* config.xml in Resources */ = {isa = PBXBuildFile; fileRef = 2FAD9762203C412B000D30F8 /* config.xml */; };
|
2FAD9763203C412B000D30F8 /* config.xml in Resources */ = {isa = PBXBuildFile; fileRef = 2FAD9762203C412B000D30F8 /* config.xml */; };
|
||||||
3A200C1527D64D7E00CBF02E /* AudioPlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A200C1427D64D7E00CBF02E /* AudioPlayer.swift */; };
|
3A200C1527D64D7E00CBF02E /* AudioPlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A200C1427D64D7E00CBF02E /* AudioPlayer.swift */; };
|
||||||
3A200C1727D64E0D00CBF02E /* Audiobook.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A200C1627D64E0D00CBF02E /* Audiobook.swift */; };
|
3ABF618F2804325C0070250E /* PlayerHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ABF618E2804325C0070250E /* PlayerHandler.swift */; };
|
||||||
|
3AD4FCE528043E50006DB301 /* AbsDatabase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AD4FCE428043E50006DB301 /* AbsDatabase.swift */; };
|
||||||
|
3AD4FCE728043E72006DB301 /* AbsDatabase.m in Sources */ = {isa = PBXBuildFile; fileRef = 3AD4FCE628043E72006DB301 /* AbsDatabase.m */; };
|
||||||
|
3AD4FCE928043FD7006DB301 /* ServerConnectionConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AD4FCE828043FD7006DB301 /* ServerConnectionConfig.swift */; };
|
||||||
|
3AD4FCEB280443DD006DB301 /* Database.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AD4FCEA280443DD006DB301 /* Database.swift */; };
|
||||||
|
3AD4FCED28044E6C006DB301 /* Store.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AD4FCEC28044E6C006DB301 /* Store.swift */; };
|
||||||
|
3AD4FCEF28045D7C006DB301 /* Audiobook.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AD4FCEE28045D7C006DB301 /* Audiobook.swift */; };
|
||||||
3AFCB5E827EA240D00ECCC05 /* NowPlayingInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AFCB5E727EA240D00ECCC05 /* NowPlayingInfo.swift */; };
|
3AFCB5E827EA240D00ECCC05 /* NowPlayingInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AFCB5E727EA240D00ECCC05 /* NowPlayingInfo.swift */; };
|
||||||
4D8D410C26E17C3A00BA5F0D /* MyNativeAudio.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D8D410B26E17C3A00BA5F0D /* MyNativeAudio.swift */; };
|
|
||||||
4D8D412E26E187E500BA5F0D /* MyNativeAudio.m in Sources */ = {isa = PBXBuildFile; fileRef = 4D8D412D26E187E500BA5F0D /* MyNativeAudio.m */; };
|
|
||||||
50379B232058CBB4000EE86E /* capacitor.config.json in Resources */ = {isa = PBXBuildFile; fileRef = 50379B222058CBB4000EE86E /* capacitor.config.json */; };
|
50379B232058CBB4000EE86E /* capacitor.config.json in Resources */ = {isa = PBXBuildFile; fileRef = 50379B222058CBB4000EE86E /* capacitor.config.json */; };
|
||||||
504EC3081FED79650016851F /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 504EC3071FED79650016851F /* AppDelegate.swift */; };
|
504EC3081FED79650016851F /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 504EC3071FED79650016851F /* AppDelegate.swift */; };
|
||||||
504EC30D1FED79650016851F /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 504EC30B1FED79650016851F /* Main.storyboard */; };
|
504EC30D1FED79650016851F /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 504EC30B1FED79650016851F /* Main.storyboard */; };
|
||||||
|
@ -25,11 +29,15 @@
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
2FAD9762203C412B000D30F8 /* config.xml */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = config.xml; sourceTree = "<group>"; };
|
2FAD9762203C412B000D30F8 /* config.xml */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = config.xml; sourceTree = "<group>"; };
|
||||||
3A200C1427D64D7E00CBF02E /* AudioPlayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioPlayer.swift; sourceTree = "<group>"; };
|
3A200C1427D64D7E00CBF02E /* AudioPlayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioPlayer.swift; sourceTree = "<group>"; };
|
||||||
3A200C1627D64E0D00CBF02E /* Audiobook.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Audiobook.swift; sourceTree = "<group>"; };
|
3ABF618E2804325C0070250E /* PlayerHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerHandler.swift; sourceTree = "<group>"; };
|
||||||
|
3AD4FCE428043E50006DB301 /* AbsDatabase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AbsDatabase.swift; sourceTree = "<group>"; };
|
||||||
|
3AD4FCE628043E72006DB301 /* AbsDatabase.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AbsDatabase.m; sourceTree = "<group>"; };
|
||||||
|
3AD4FCE828043FD7006DB301 /* ServerConnectionConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerConnectionConfig.swift; sourceTree = "<group>"; };
|
||||||
|
3AD4FCEA280443DD006DB301 /* Database.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Database.swift; sourceTree = "<group>"; };
|
||||||
|
3AD4FCEC28044E6C006DB301 /* Store.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Store.swift; sourceTree = "<group>"; };
|
||||||
|
3AD4FCEE28045D7C006DB301 /* Audiobook.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Audiobook.swift; sourceTree = "<group>"; };
|
||||||
3AFCB5E727EA240D00ECCC05 /* NowPlayingInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NowPlayingInfo.swift; sourceTree = "<group>"; };
|
3AFCB5E727EA240D00ECCC05 /* NowPlayingInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NowPlayingInfo.swift; sourceTree = "<group>"; };
|
||||||
4D8D410B26E17C3A00BA5F0D /* MyNativeAudio.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyNativeAudio.swift; sourceTree = "<group>"; };
|
|
||||||
4D8D412C26E187E400BA5F0D /* App-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "App-Bridging-Header.h"; sourceTree = "<group>"; };
|
4D8D412C26E187E400BA5F0D /* App-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "App-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||||
4D8D412D26E187E500BA5F0D /* MyNativeAudio.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MyNativeAudio.m; sourceTree = "<group>"; };
|
|
||||||
50379B222058CBB4000EE86E /* capacitor.config.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = capacitor.config.json; sourceTree = "<group>"; };
|
50379B222058CBB4000EE86E /* capacitor.config.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = capacitor.config.json; sourceTree = "<group>"; };
|
||||||
504EC3041FED79650016851F /* App.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = App.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
504EC3041FED79650016851F /* App.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = App.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
504EC3071FED79650016851F /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
504EC3071FED79650016851F /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||||
|
@ -63,29 +71,39 @@
|
||||||
name = Frameworks;
|
name = Frameworks;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
3ABF6190280432610070250E /* player */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
3A200C1427D64D7E00CBF02E /* AudioPlayer.swift */,
|
||||||
|
3ABF618E2804325C0070250E /* PlayerHandler.swift */,
|
||||||
|
);
|
||||||
|
path = player;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
3AC8248B27F2316900529205 /* Shared */ = {
|
3AC8248B27F2316900529205 /* Shared */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
3AFCB5E527EA232A00ECCC05 /* models */,
|
3AFCB5E527EA232A00ECCC05 /* models */,
|
||||||
3AFCB5E627EA23F700ECCC05 /* util */,
|
3AFCB5E627EA23F700ECCC05 /* util */,
|
||||||
3A200C1427D64D7E00CBF02E /* AudioPlayer.swift */,
|
3ABF6190280432610070250E /* player */,
|
||||||
);
|
);
|
||||||
path = Shared;
|
path = Shared;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
3AFCB5E427EA231D00ECCC05 /* audio */ = {
|
3AFCB5E427EA231D00ECCC05 /* plugins */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
4D8D410B26E17C3A00BA5F0D /* MyNativeAudio.swift */,
|
3AD4FCE428043E50006DB301 /* AbsDatabase.swift */,
|
||||||
4D8D412D26E187E500BA5F0D /* MyNativeAudio.m */,
|
3AD4FCE628043E72006DB301 /* AbsDatabase.m */,
|
||||||
);
|
);
|
||||||
path = audio;
|
path = plugins;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
3AFCB5E527EA232A00ECCC05 /* models */ = {
|
3AFCB5E527EA232A00ECCC05 /* models */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
3A200C1627D64E0D00CBF02E /* Audiobook.swift */,
|
3AD4FCEE28045D7C006DB301 /* Audiobook.swift */,
|
||||||
|
3AD4FCE828043FD7006DB301 /* ServerConnectionConfig.swift */,
|
||||||
);
|
);
|
||||||
path = models;
|
path = models;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -94,6 +112,8 @@
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
3AFCB5E727EA240D00ECCC05 /* NowPlayingInfo.swift */,
|
3AFCB5E727EA240D00ECCC05 /* NowPlayingInfo.swift */,
|
||||||
|
3AD4FCEA280443DD006DB301 /* Database.swift */,
|
||||||
|
3AD4FCEC28044E6C006DB301 /* Store.swift */,
|
||||||
);
|
);
|
||||||
path = util;
|
path = util;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -120,7 +140,7 @@
|
||||||
504EC3061FED79650016851F /* App */ = {
|
504EC3061FED79650016851F /* App */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
3AFCB5E427EA231D00ECCC05 /* audio */,
|
3AFCB5E427EA231D00ECCC05 /* plugins */,
|
||||||
50379B222058CBB4000EE86E /* capacitor.config.json */,
|
50379B222058CBB4000EE86E /* capacitor.config.json */,
|
||||||
504EC3071FED79650016851F /* AppDelegate.swift */,
|
504EC3071FED79650016851F /* AppDelegate.swift */,
|
||||||
504EC30B1FED79650016851F /* Main.storyboard */,
|
504EC30B1FED79650016851F /* Main.storyboard */,
|
||||||
|
@ -256,12 +276,16 @@
|
||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
4D8D412E26E187E500BA5F0D /* MyNativeAudio.m in Sources */,
|
3AD4FCE728043E72006DB301 /* AbsDatabase.m in Sources */,
|
||||||
504EC3081FED79650016851F /* AppDelegate.swift in Sources */,
|
504EC3081FED79650016851F /* AppDelegate.swift in Sources */,
|
||||||
4D8D410C26E17C3A00BA5F0D /* MyNativeAudio.swift in Sources */,
|
3ABF618F2804325C0070250E /* PlayerHandler.swift in Sources */,
|
||||||
3A200C1727D64E0D00CBF02E /* Audiobook.swift in Sources */,
|
3AD4FCED28044E6C006DB301 /* Store.swift in Sources */,
|
||||||
|
3AD4FCE928043FD7006DB301 /* ServerConnectionConfig.swift in Sources */,
|
||||||
|
3AD4FCEF28045D7C006DB301 /* Audiobook.swift in Sources */,
|
||||||
3A200C1527D64D7E00CBF02E /* AudioPlayer.swift in Sources */,
|
3A200C1527D64D7E00CBF02E /* AudioPlayer.swift in Sources */,
|
||||||
3AFCB5E827EA240D00ECCC05 /* NowPlayingInfo.swift in Sources */,
|
3AFCB5E827EA240D00ECCC05 /* NowPlayingInfo.swift in Sources */,
|
||||||
|
3AD4FCEB280443DD006DB301 /* Database.swift in Sources */,
|
||||||
|
3AD4FCE528043E50006DB301 /* AbsDatabase.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
@ -402,7 +426,7 @@
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 3;
|
CURRENT_PROJECT_VERSION = 3;
|
||||||
DEVELOPMENT_TEAM = 7UFJ7D8V6A;
|
DEVELOPMENT_TEAM = N8AA4S3S96;
|
||||||
INFOPLIST_FILE = App/Info.plist;
|
INFOPLIST_FILE = App/Info.plist;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||||
|
@ -426,7 +450,7 @@
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 3;
|
CURRENT_PROJECT_VERSION = 3;
|
||||||
DEVELOPMENT_TEAM = 7UFJ7D8V6A;
|
DEVELOPMENT_TEAM = N8AA4S3S96;
|
||||||
INFOPLIST_FILE = App/Info.plist;
|
INFOPLIST_FILE = App/Info.plist;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
#import <Foundation/Foundation.h>
|
|
||||||
#import <Capacitor/Capacitor.h>
|
|
||||||
|
|
||||||
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(setSleepTimer, CAPPluginReturnPromise);
|
|
||||||
CAP_PLUGIN_METHOD(increaseSleepTime, CAPPluginReturnPromise);
|
|
||||||
CAP_PLUGIN_METHOD(decreaseSleepTime, CAPPluginReturnPromise);
|
|
||||||
CAP_PLUGIN_METHOD(cancelSleepTimer, CAPPluginReturnPromise);
|
|
||||||
)
|
|
|
@ -1,290 +0,0 @@
|
||||||
import Foundation
|
|
||||||
import Capacitor
|
|
||||||
import MediaPlayer
|
|
||||||
import AVKit
|
|
||||||
|
|
||||||
func parseSleepTime(millis: String?) -> Double {
|
|
||||||
(Double(millis ?? "0") ?? 0) / 1000
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc(MyNativeAudio)
|
|
||||||
public class MyNativeAudio: CAPPlugin {
|
|
||||||
var playerContext = 0
|
|
||||||
|
|
||||||
var currentSleepTimer: Timer? = nil
|
|
||||||
var remainingSleepDuration: Double = 0
|
|
||||||
|
|
||||||
@objc func initPlayer(_ call: CAPPluginCall) {
|
|
||||||
NSLog("Init Player")
|
|
||||||
let audiobook = Audiobook(
|
|
||||||
streamId: call.getString("id")!,
|
|
||||||
audiobookId: call.getString("audiobookId")!,
|
|
||||||
playlistUrl: call.getString("playlistUrl")!,
|
|
||||||
|
|
||||||
startTime: (Double(call.getString("startTime") ?? "0") ?? 0.0) / 1000,
|
|
||||||
duration: call.getDouble("duration") ?? 0,
|
|
||||||
|
|
||||||
title: call.getString("title") ?? "No Title",
|
|
||||||
series: call.getString("series"),
|
|
||||||
author: call.getString("author"),
|
|
||||||
artworkUrl: call.getString("cover"),
|
|
||||||
|
|
||||||
token: call.getString("token") ?? ""
|
|
||||||
)
|
|
||||||
let playWhenReady = call.getBool("playWhenReady", false)
|
|
||||||
|
|
||||||
if AudioPlayer.instance != nil && AudioPlayer.instance?.audiobook.streamId == audiobook.streamId {
|
|
||||||
if playWhenReady {
|
|
||||||
AudioPlayer.instance?.play()
|
|
||||||
}
|
|
||||||
|
|
||||||
call.resolve(["success": true])
|
|
||||||
return
|
|
||||||
} else if AudioPlayer.instance != nil && AudioPlayer.instance?.audiobook.streamId != audiobook.streamId {
|
|
||||||
stop()
|
|
||||||
}
|
|
||||||
|
|
||||||
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) || keyPath == #keyPath(AudioPlayer.rate) {
|
|
||||||
sendMetadata()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc func seekForward(_ call: CAPPluginCall) {
|
|
||||||
if AudioPlayer.instance == nil {
|
|
||||||
call.resolve()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let amount = (Double(call.getString("amount", "0")) ?? 0) / 1000
|
|
||||||
let destinationTime = AudioPlayer.instance!.getCurrentTime() + amount
|
|
||||||
|
|
||||||
AudioPlayer.instance!.seek(destinationTime)
|
|
||||||
call.resolve()
|
|
||||||
}
|
|
||||||
@objc func seekBackward(_ call: CAPPluginCall) {
|
|
||||||
if AudioPlayer.instance == nil {
|
|
||||||
call.resolve()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let amount = (Double(call.getString("amount", "0")) ?? 0) / 1000
|
|
||||||
let destinationTime = AudioPlayer.instance!.getCurrentTime() - amount
|
|
||||||
|
|
||||||
AudioPlayer.instance!.seek(destinationTime)
|
|
||||||
call.resolve()
|
|
||||||
}
|
|
||||||
@objc func seekPlayer(_ call: CAPPluginCall) {
|
|
||||||
if AudioPlayer.instance == nil {
|
|
||||||
call.resolve()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let seekTime = (Double(call.getString("timeMs", "0")) ?? 0) / 1000
|
|
||||||
NSLog("Seek Player \(seekTime)")
|
|
||||||
|
|
||||||
AudioPlayer.instance!.seek(seekTime)
|
|
||||||
call.resolve()
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc func pausePlayer(_ call: CAPPluginCall) {
|
|
||||||
if AudioPlayer.instance == nil {
|
|
||||||
call.resolve()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
AudioPlayer.instance!.pause()
|
|
||||||
|
|
||||||
sendPlaybackStatusUpdate(false)
|
|
||||||
call.resolve()
|
|
||||||
}
|
|
||||||
@objc func playPlayer(_ call: CAPPluginCall) {
|
|
||||||
if AudioPlayer.instance == nil {
|
|
||||||
call.resolve()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
AudioPlayer.instance!.play(allowSeekBack: true)
|
|
||||||
|
|
||||||
sendPlaybackStatusUpdate(true)
|
|
||||||
call.resolve()
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc func terminateStream(_ call: CAPPluginCall) {
|
|
||||||
stop()
|
|
||||||
call.resolve()
|
|
||||||
}
|
|
||||||
@objc func stop(_ call: CAPPluginCall? = nil) {
|
|
||||||
if AudioPlayer.instance != nil {
|
|
||||||
AudioPlayer.instance!.destroy()
|
|
||||||
}
|
|
||||||
AudioPlayer.instance = nil
|
|
||||||
|
|
||||||
if call != nil {
|
|
||||||
call!.resolve([ "result": true ])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc func getCurrentTime(_ call: CAPPluginCall) {
|
|
||||||
if AudioPlayer.instance == nil {
|
|
||||||
call.resolve()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let currentTime = AudioPlayer.instance?.getCurrentTime() ?? 0
|
|
||||||
call.resolve([ "value": currentTime * 1000, "bufferedTime": currentTime * 1000 ])
|
|
||||||
}
|
|
||||||
@objc func getStreamSyncData(_ call: CAPPluginCall) {
|
|
||||||
if AudioPlayer.instance == nil {
|
|
||||||
call.resolve([ "isPlaying": false, "lastPauseTime": 0, "id": nil ])
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
call.resolve([ "isPlaying": AudioPlayer.instance!.rate > 0.0, "lastPauseTime": 0, "id": AudioPlayer.instance?.audiobook.streamId as Any ])
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc func setPlaybackSpeed(_ call: CAPPluginCall) {
|
|
||||||
if AudioPlayer.instance == nil {
|
|
||||||
call.resolve()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let speed = call.getFloat("speed") ?? 0
|
|
||||||
AudioPlayer.instance!.setPlaybackRate(speed)
|
|
||||||
|
|
||||||
call.resolve()
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc func setSleepTimer(_ call: CAPPluginCall) {
|
|
||||||
if AudioPlayer.instance == nil {
|
|
||||||
call.resolve()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let time = parseSleepTime(millis: call.getString("time"))
|
|
||||||
setSleepTimer(seconds: time)
|
|
||||||
|
|
||||||
call.resolve([ "success": true ])
|
|
||||||
}
|
|
||||||
@objc func increaseSleepTime(_ call: CAPPluginCall) {
|
|
||||||
if AudioPlayer.instance == nil {
|
|
||||||
call.resolve()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var time = self.remainingSleepDuration + parseSleepTime(millis: call.getString("time"))
|
|
||||||
if time > AudioPlayer.instance!.getDuration() {
|
|
||||||
time = AudioPlayer.instance!.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 AudioPlayer.instance == 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 AudioPlayer.instance == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.remainingSleepDuration <= 0 {
|
|
||||||
if currentSleepTimer != nil {
|
|
||||||
currentSleepTimer!.invalidate()
|
|
||||||
}
|
|
||||||
self.notifyListeners("onSleepTimerEnded", data: [
|
|
||||||
"value": AudioPlayer.instance!.getCurrentTime(),
|
|
||||||
])
|
|
||||||
|
|
||||||
AudioPlayer.instance!.pause()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
remainingSleepDuration -= 1
|
|
||||||
self.notifyListeners("onSleepTimerSet", data: [
|
|
||||||
"value": self.remainingSleepDuration,
|
|
||||||
])
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc func sendMetadata() {
|
|
||||||
if AudioPlayer.instance == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
NSLog("fired metadata update")
|
|
||||||
|
|
||||||
self.notifyListeners("onMetadata", data: [
|
|
||||||
"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: [
|
|
||||||
"value": playing
|
|
||||||
])
|
|
||||||
}
|
|
||||||
}
|
|
15
ios/App/App/plugins/AbsDatabase.m
Normal file
15
ios/App/App/plugins/AbsDatabase.m
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
//
|
||||||
|
// AbsDatabase.m
|
||||||
|
// App
|
||||||
|
//
|
||||||
|
// Created by Rasmus Krämer on 11.04.22.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import <Capacitor/Capacitor.h>
|
||||||
|
|
||||||
|
CAP_PLUGIN(AbsDatabase, "AbsDatabase",
|
||||||
|
CAP_PLUGIN_METHOD(setCurrentServerConnectionConfig, CAPPluginReturnPromise);
|
||||||
|
CAP_PLUGIN_METHOD(getDeviceData, CAPPluginReturnPromise);
|
||||||
|
)
|
||||||
|
|
61
ios/App/App/plugins/AbsDatabase.swift
Normal file
61
ios/App/App/plugins/AbsDatabase.swift
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
//
|
||||||
|
// AbsDatabase.swift
|
||||||
|
// App
|
||||||
|
//
|
||||||
|
// Created by Rasmus Krämer on 11.04.22.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import Capacitor
|
||||||
|
import RealmSwift
|
||||||
|
|
||||||
|
extension String {
|
||||||
|
|
||||||
|
func fromBase64() -> String? {
|
||||||
|
guard let data = Data(base64Encoded: self) else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return String(data: data, encoding: .utf8)
|
||||||
|
}
|
||||||
|
|
||||||
|
func toBase64() -> String {
|
||||||
|
return Data(self.utf8).base64EncodedString()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc(AbsDatabase)
|
||||||
|
public class AbsDatabase: CAPPlugin {
|
||||||
|
@objc func setCurrentServerConnectionConfig(_ call: CAPPluginCall) {
|
||||||
|
Database.realmQueue.sync {
|
||||||
|
var id = call.getString("id")
|
||||||
|
let address = call.getString("address", "")
|
||||||
|
let userId = call.getString("userId", "")
|
||||||
|
let username = call.getString("username", "")
|
||||||
|
let token = call.getString("token", "")
|
||||||
|
|
||||||
|
let name = "\(address) (\(username))"
|
||||||
|
let config = ServerConnectionConfig()
|
||||||
|
|
||||||
|
if id == nil {
|
||||||
|
id = "\(address)@\(username)".toBase64()
|
||||||
|
}
|
||||||
|
|
||||||
|
config.id = id!
|
||||||
|
config.name = name
|
||||||
|
config.address = address
|
||||||
|
config.userId = userId
|
||||||
|
config.username = username
|
||||||
|
config.token = token
|
||||||
|
|
||||||
|
Store.serverConfig = config
|
||||||
|
call.resolve(serverConnectionConfigToJSON(config: config))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@objc func getDeviceData(_ call: CAPPluginCall) {
|
||||||
|
Database.realmQueue.sync {
|
||||||
|
call.resolve(serverConnectionConfigToJSON(config: Store.serverConfig))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,16 +9,18 @@ install! 'cocoapods', :disable_input_output_paths => true
|
||||||
def capacitor_pods
|
def capacitor_pods
|
||||||
pod 'Capacitor', :path => '../../node_modules/@capacitor/ios'
|
pod 'Capacitor', :path => '../../node_modules/@capacitor/ios'
|
||||||
pod 'CapacitorCordova', :path => '../../node_modules/@capacitor/ios'
|
pod 'CapacitorCordova', :path => '../../node_modules/@capacitor/ios'
|
||||||
pod 'CapacitorApp', :path => '..\..\node_modules\@capacitor\app'
|
pod 'CapacitorApp', :path => '../../node_modules/@capacitor/app'
|
||||||
pod 'CapacitorDialog', :path => '..\..\node_modules\@capacitor\dialog'
|
pod 'CapacitorDialog', :path => '../../node_modules/@capacitor/dialog'
|
||||||
pod 'CapacitorHaptics', :path => '..\..\node_modules\@capacitor\haptics'
|
pod 'CapacitorHaptics', :path => '../../node_modules/@capacitor/haptics'
|
||||||
pod 'CapacitorNetwork', :path => '..\..\node_modules\@capacitor\network'
|
pod 'CapacitorNetwork', :path => '../../node_modules/@capacitor/network'
|
||||||
pod 'CapacitorStatusBar', :path => '..\..\node_modules\@capacitor\status-bar'
|
pod 'CapacitorStatusBar', :path => '../../node_modules/@capacitor/status-bar'
|
||||||
pod 'CapacitorStorage', :path => '..\..\node_modules\@capacitor\storage'
|
pod 'CapacitorStorage', :path => '../../node_modules/@capacitor/storage'
|
||||||
pod 'RobingenzCapacitorAppUpdate', :path => '..\..\node_modules\@robingenz\capacitor-app-update'
|
pod 'RobingenzCapacitorAppUpdate', :path => '../../node_modules/@robingenz/capacitor-app-update'
|
||||||
end
|
end
|
||||||
|
|
||||||
target 'App' do
|
target 'App' do
|
||||||
capacitor_pods
|
capacitor_pods
|
||||||
# Add your Pods here
|
# Add your Pods here
|
||||||
|
|
||||||
|
pod 'RealmSwift', '~>10'
|
||||||
end
|
end
|
||||||
|
|
31
ios/App/Shared/models/ServerConnectionConfig.swift
Normal file
31
ios/App/Shared/models/ServerConnectionConfig.swift
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
//
|
||||||
|
// ServerConnectionConfig.swift
|
||||||
|
// App
|
||||||
|
//
|
||||||
|
// Created by Rasmus Krämer on 11.04.22.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import RealmSwift
|
||||||
|
|
||||||
|
class ServerConnectionConfig: Object {
|
||||||
|
@Persisted var id: String
|
||||||
|
@Persisted var index: Int = 0
|
||||||
|
@Persisted var name: String
|
||||||
|
@Persisted var address: String
|
||||||
|
@Persisted var userId: String
|
||||||
|
@Persisted var username: String
|
||||||
|
@Persisted var token: String
|
||||||
|
}
|
||||||
|
|
||||||
|
func serverConnectionConfigToJSON(config: ServerConnectionConfig) -> Dictionary<String, Any> {
|
||||||
|
return [
|
||||||
|
"id": config.id,
|
||||||
|
"name": config.name,
|
||||||
|
"index": config.index,
|
||||||
|
"address": config.address,
|
||||||
|
"userId": config.userId,
|
||||||
|
"username": config.username,
|
||||||
|
"token": config.token,
|
||||||
|
]
|
||||||
|
}
|
17
ios/App/Shared/player/PlayerHandler.swift
Normal file
17
ios/App/Shared/player/PlayerHandler.swift
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
//
|
||||||
|
// PlayerHandler.swift
|
||||||
|
// App
|
||||||
|
//
|
||||||
|
// Created by Rasmus Krämer on 11.04.22.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
class PlayerHandler {
|
||||||
|
private static var player: AudioPlayer?
|
||||||
|
// private static var item: any
|
||||||
|
|
||||||
|
public static func setItem() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
32
ios/App/Shared/util/Database.swift
Normal file
32
ios/App/Shared/util/Database.swift
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
//
|
||||||
|
// Database.swift
|
||||||
|
// App
|
||||||
|
//
|
||||||
|
// Created by Rasmus Krämer on 11.04.22.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import RealmSwift
|
||||||
|
|
||||||
|
class Database {
|
||||||
|
public static let realmQueue = DispatchQueue(label: "realm-queue")
|
||||||
|
|
||||||
|
public static func setServerConnectionConfig(config: ServerConnectionConfig) {
|
||||||
|
let realm = try! Realm(queue: realmQueue)
|
||||||
|
let existing = realm.objects(ServerConnectionConfig.self)
|
||||||
|
|
||||||
|
try! realm.write {
|
||||||
|
realm.delete(existing)
|
||||||
|
realm.add(config)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static func getServerConnectionConfig() -> ServerConnectionConfig {
|
||||||
|
let realm = try! Realm(queue: realmQueue)
|
||||||
|
guard let config = realm.objects(ServerConnectionConfig.self).first else {
|
||||||
|
let fallback = ServerConnectionConfig()
|
||||||
|
return fallback
|
||||||
|
}
|
||||||
|
|
||||||
|
return config
|
||||||
|
}
|
||||||
|
}
|
20
ios/App/Shared/util/Store.swift
Normal file
20
ios/App/Shared/util/Store.swift
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
//
|
||||||
|
// Store.swift
|
||||||
|
// App
|
||||||
|
//
|
||||||
|
// Created by Rasmus Krämer on 11.04.22.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import RealmSwift
|
||||||
|
|
||||||
|
class Store {
|
||||||
|
public static var serverConfig: ServerConnectionConfig {
|
||||||
|
get {
|
||||||
|
return Database.getServerConnectionConfig()
|
||||||
|
}
|
||||||
|
set(updated) {
|
||||||
|
Database.setServerConnectionConfig(config: updated)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
18803
package-lock.json
generated
18803
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -7,7 +7,9 @@
|
||||||
"build": "nuxt build",
|
"build": "nuxt build",
|
||||||
"start": "nuxt start",
|
"start": "nuxt start",
|
||||||
"generate": "nuxt generate",
|
"generate": "nuxt generate",
|
||||||
"icons-android": "cordova-res android --skip-config --copy"
|
"icons-android": "cordova-res android --skip-config --copy",
|
||||||
|
"ionic:build": "npm run build",
|
||||||
|
"ionic:serve": "npm run start"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@capacitor/android": "^3.2.2",
|
"@capacitor/android": "^3.2.2",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue