mirror of
https://github.com/advplyr/audiobookshelf-app.git
synced 2026-08-07 12:28:50 +02:00
Small improvements
This commit is contained in:
@@ -53,7 +53,7 @@ public class AbsDatabase: CAPPlugin {
|
||||
}
|
||||
@objc func removeServerConnectionConfig(_ call: CAPPluginCall) {
|
||||
let id = call.getString("serverConnectionConfigId", "")
|
||||
Database.deleteServerConnectionConfig(id: id)
|
||||
Database.shared.deleteServerConnectionConfig(id: id)
|
||||
|
||||
call.resolve()
|
||||
}
|
||||
@@ -63,13 +63,12 @@ public class AbsDatabase: CAPPlugin {
|
||||
}
|
||||
|
||||
@objc func getDeviceData(_ call: CAPPluginCall) {
|
||||
let configs = Database.getServerConnectionConfigs()
|
||||
let index = Database.getLastActiveConfigIndex()
|
||||
let configs = Database.shared.getServerConnectionConfigs()
|
||||
let index = Database.shared.getLastActiveConfigIndex()
|
||||
|
||||
call.resolve([
|
||||
"serverConnectionConfigs": configs.map { config in convertServerConnectionConfigToJSON(config: config) },
|
||||
"lastServerConnectionConfigId": configs.first { config in config.index == index }?.id,
|
||||
// Luckily this isn't implemented yet
|
||||
"lastServerConnectionConfigId": configs.first { config in config.index == index }?.id as Any,
|
||||
// "currentLocalPlaybackSession": nil,
|
||||
])
|
||||
}
|
||||
|
||||
@@ -70,6 +70,7 @@ class AudioPlayer: NSObject {
|
||||
public func destroy() {
|
||||
// Pause is not synchronous causing this error on below lines:
|
||||
// AVAudioSession_iOS.mm:1206 Deactivating an audio session that has running I/O. All I/O should be stopped or paused prior to deactivating the audio session
|
||||
// It is related to L79 `AVAudioSession.sharedInstance().setActive(false)`
|
||||
pause()
|
||||
audioPlayer.replaceCurrentItem(with: nil)
|
||||
|
||||
@@ -80,11 +81,9 @@ class AudioPlayer: NSObject {
|
||||
print(error)
|
||||
}
|
||||
|
||||
// Throws error Possibly related to the error above
|
||||
// DispatchQueue.main.sync {
|
||||
// UIApplication.shared.endReceivingRemoteControlEvents()
|
||||
// }
|
||||
|
||||
DispatchQueue.runOnMainQueue {
|
||||
UIApplication.shared.endReceivingRemoteControlEvents()
|
||||
}
|
||||
NotificationCenter.default.post(name: NSNotification.Name(PlayerEvents.closed.rawValue), object: nil)
|
||||
}
|
||||
|
||||
@@ -186,9 +185,9 @@ class AudioPlayer: NSObject {
|
||||
|
||||
// MARK: - Now playing
|
||||
private func setupRemoteTransportControls() {
|
||||
// DispatchQueue.main.sync {
|
||||
DispatchQueue.runOnMainQueue {
|
||||
UIApplication.shared.beginReceivingRemoteControlEvents()
|
||||
// }
|
||||
}
|
||||
let commandCenter = MPRemoteCommandCenter.shared()
|
||||
|
||||
commandCenter.playCommand.isEnabled = true
|
||||
@@ -246,7 +245,7 @@ class AudioPlayer: NSObject {
|
||||
}
|
||||
private func updateNowPlaying() {
|
||||
NotificationCenter.default.post(name: NSNotification.Name(PlayerEvents.update.rawValue), object: nil)
|
||||
NowPlayingInfo.update(duration: getDuration(), currentTime: getCurrentTime(), rate: rate)
|
||||
NowPlayingInfo.shared.update(duration: getDuration(), currentTime: getCurrentTime(), rate: rate)
|
||||
}
|
||||
|
||||
// MARK: - Observer
|
||||
|
||||
@@ -20,16 +20,16 @@ class PlayerHandler {
|
||||
player = nil
|
||||
}
|
||||
|
||||
NowPlayingInfo.setSessionMetadata(metadata: NowPlayingMetadata(id: session.id, itemId: session.libraryItemId!, artworkUrl: session.coverPath, title: session.displayTitle ?? "Unknown title", author: session.displayAuthor, series: nil))
|
||||
NowPlayingInfo.shared.setSessionMetadata(metadata: NowPlayingMetadata(id: session.id, itemId: session.libraryItemId!, artworkUrl: session.coverPath, title: session.displayTitle ?? "Unknown title", author: session.displayAuthor, series: nil))
|
||||
|
||||
self.session = session
|
||||
player = AudioPlayer(playbackSession: session, playWhenReady: playWhenReady, playbackRate: playbackRate)
|
||||
|
||||
// DispatchQueue.main.sync {
|
||||
timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { _ in
|
||||
self.tick()
|
||||
DispatchQueue.runOnMainQueue {
|
||||
timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { _ in
|
||||
self.tick()
|
||||
}
|
||||
}
|
||||
// }
|
||||
}
|
||||
public static func stopPlayback() {
|
||||
player?.destroy()
|
||||
@@ -38,7 +38,7 @@ class PlayerHandler {
|
||||
timer?.invalidate()
|
||||
timer = nil
|
||||
|
||||
NowPlayingInfo.reset()
|
||||
NowPlayingInfo.shared.reset()
|
||||
}
|
||||
|
||||
public static func getCurrentTime() -> Double? {
|
||||
@@ -63,20 +63,20 @@ class PlayerHandler {
|
||||
}
|
||||
|
||||
public static func seekForward(amount: Double) {
|
||||
if player == nil {
|
||||
guard let player = player else {
|
||||
return
|
||||
}
|
||||
|
||||
let destinationTime = player!.getCurrentTime() + amount
|
||||
player!.seek(destinationTime)
|
||||
let destinationTime = player.getCurrentTime() + amount
|
||||
player.seek(destinationTime)
|
||||
}
|
||||
public static func seekBackward(amount: Double) {
|
||||
if player == nil {
|
||||
guard let player = player else {
|
||||
return
|
||||
}
|
||||
|
||||
let destinationTime = player!.getCurrentTime() - amount
|
||||
player!.seek(destinationTime)
|
||||
let destinationTime = player.getCurrentTime() - amount
|
||||
player.seek(destinationTime)
|
||||
}
|
||||
public static func seek(amount: Double) {
|
||||
player?.seek(amount)
|
||||
@@ -109,13 +109,16 @@ class PlayerHandler {
|
||||
}
|
||||
}
|
||||
public static func syncProgress() {
|
||||
if player == nil || session == nil {
|
||||
if session == nil {
|
||||
return
|
||||
}
|
||||
guard let player = player else {
|
||||
return
|
||||
}
|
||||
|
||||
let report = PlaybackReport(currentTime: player!.getCurrentTime(), duration: player!.getDuration(), timeListened: listeningTimePassedSinceLastSync)
|
||||
let report = PlaybackReport(currentTime: player.getCurrentTime(), duration: player.getDuration(), timeListened: listeningTimePassedSinceLastSync)
|
||||
|
||||
session!.currentTime = player!.getCurrentTime()
|
||||
session!.currentTime = player.getCurrentTime()
|
||||
listeningTimePassedSinceLastSync = 0
|
||||
|
||||
// TODO: check if online
|
||||
|
||||
@@ -9,6 +9,14 @@ import Foundation
|
||||
import Alamofire
|
||||
|
||||
class ApiClient {
|
||||
public static func getData(from url: URL, completion: @escaping (UIImage?) -> Void) {
|
||||
URLSession.shared.dataTask(with: url, completionHandler: {(data, response, error) in
|
||||
if let data = data {
|
||||
completion(UIImage(data:data))
|
||||
}
|
||||
}).resume()
|
||||
}
|
||||
|
||||
public static func postResource<T: Decodable>(endpoint: String, parameters: [String: String], decodable: T.Type = T.self, callback: ((_ param: T) -> Void)?) {
|
||||
if (Store.serverConfig == nil) {
|
||||
NSLog("Server config not set")
|
||||
@@ -54,7 +62,6 @@ class ApiClient {
|
||||
}
|
||||
|
||||
public static func startPlaybackSession(libraryItemId: String, episodeId: String?, callback: @escaping (_ param: PlaybackSession) -> Void) {
|
||||
|
||||
var endpoint = "api/items/\(libraryItemId)/play"
|
||||
if episodeId != nil {
|
||||
endpoint += "/\(episodeId!)"
|
||||
|
||||
@@ -10,16 +10,25 @@ import RealmSwift
|
||||
|
||||
class Database {
|
||||
// All DB releated actions must be executed on "realm-queue"
|
||||
public static let realmQueue = DispatchQueue(label: "realm-queue")
|
||||
private static var instance: Realm = try! Realm(queue: realmQueue)
|
||||
public static let realmQueue: DispatchQueue = DispatchQueue(label: "realm-queue")
|
||||
public static var shared = {
|
||||
realmQueue.sync {
|
||||
return Database()
|
||||
}
|
||||
}()
|
||||
|
||||
private var instance: Realm
|
||||
private init() {
|
||||
self.instance = try! Realm(queue: Database.realmQueue)
|
||||
}
|
||||
|
||||
public static func setServerConnectionConfig(config: ServerConnectionConfig) {
|
||||
public func setServerConnectionConfig(config: ServerConnectionConfig) {
|
||||
var refrence: ThreadSafeReference<ServerConnectionConfig>?
|
||||
if config.realm != nil {
|
||||
refrence = ThreadSafeReference(to: config)
|
||||
}
|
||||
|
||||
realmQueue.sync {
|
||||
Database.realmQueue.sync {
|
||||
let existing: ServerConnectionConfig? = instance.object(ofType: ServerConnectionConfig.self, forPrimaryKey: config.id)
|
||||
|
||||
if config.index == 0 {
|
||||
@@ -55,8 +64,8 @@ class Database {
|
||||
setLastActiveConfigIndex(index: config.index)
|
||||
}
|
||||
}
|
||||
public static func deleteServerConnectionConfig(id: String) {
|
||||
realmQueue.sync {
|
||||
public func deleteServerConnectionConfig(id: String) {
|
||||
Database.realmQueue.sync {
|
||||
let config = instance.object(ofType: ServerConnectionConfig.self, forPrimaryKey: id)
|
||||
|
||||
do {
|
||||
@@ -71,10 +80,10 @@ class Database {
|
||||
}
|
||||
}
|
||||
}
|
||||
public static func getServerConnectionConfigs() -> [ServerConnectionConfig] {
|
||||
public func getServerConnectionConfigs() -> [ServerConnectionConfig] {
|
||||
var refrences: [ThreadSafeReference<ServerConnectionConfig>] = []
|
||||
|
||||
realmQueue.sync {
|
||||
Database.realmQueue.sync {
|
||||
let configs = instance.objects(ServerConnectionConfig.self)
|
||||
refrences = configs.map { config in
|
||||
return ThreadSafeReference(to: config)
|
||||
@@ -94,12 +103,12 @@ class Database {
|
||||
}
|
||||
}
|
||||
|
||||
public static func setLastActiveConfigIndexToNil() {
|
||||
realmQueue.sync {
|
||||
public func setLastActiveConfigIndexToNil() {
|
||||
Database.realmQueue.sync {
|
||||
setLastActiveConfigIndex(index: nil)
|
||||
}
|
||||
}
|
||||
public static func setLastActiveConfigIndex(index: Int?) {
|
||||
public func setLastActiveConfigIndex(index: Int?) {
|
||||
let existing = instance.objects(ServerConnectionConfigActiveIndex.self)
|
||||
let obj = ServerConnectionConfigActiveIndex()
|
||||
obj.index = index
|
||||
@@ -114,8 +123,8 @@ class Database {
|
||||
debugPrint(exception)
|
||||
}
|
||||
}
|
||||
public static func getLastActiveConfigIndex() -> Int? {
|
||||
return realmQueue.sync {
|
||||
public func getLastActiveConfigIndex() -> Int? {
|
||||
return Database.realmQueue.sync {
|
||||
return instance.objects(ServerConnectionConfigActiveIndex.self).first?.index ?? nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,3 +18,14 @@ extension Encodable {
|
||||
return dictionary
|
||||
}
|
||||
}
|
||||
extension DispatchQueue {
|
||||
static func runOnMainQueue(callback: @escaping (() -> Void)) {
|
||||
if Thread.isMainThread {
|
||||
callback()
|
||||
} else {
|
||||
DispatchQueue.main.sync {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,14 +8,6 @@
|
||||
import Foundation
|
||||
import MediaPlayer
|
||||
|
||||
func getData(from url: URL, completion: @escaping (UIImage?) -> Void) {
|
||||
URLSession.shared.dataTask(with: url, completionHandler: {(data, response, error) in
|
||||
if let data = data {
|
||||
completion(UIImage(data:data))
|
||||
}
|
||||
}).resume()
|
||||
}
|
||||
|
||||
struct NowPlayingMetadata {
|
||||
var id: String
|
||||
var itemId: String
|
||||
@@ -26,22 +18,22 @@ struct NowPlayingMetadata {
|
||||
}
|
||||
|
||||
class NowPlayingInfo {
|
||||
private static var nowPlayingInfo: [String: Any] = [:]
|
||||
static var shared = {
|
||||
return NowPlayingInfo()
|
||||
}()
|
||||
|
||||
public static func setSessionMetadata(metadata: NowPlayingMetadata) {
|
||||
private var nowPlayingInfo: [String: Any]
|
||||
private init() {
|
||||
self.nowPlayingInfo = [:]
|
||||
}
|
||||
|
||||
public func setSessionMetadata(metadata: NowPlayingMetadata) {
|
||||
setMetadata(artwork: nil, metadata: metadata)
|
||||
|
||||
/*
|
||||
if !shouldFetchCover(id: metadata.id) || metadata.artworkUrl == nil {
|
||||
return
|
||||
}
|
||||
*/
|
||||
|
||||
guard let url = URL(string: "\(Store.serverConfig!.address)/api/items/\(metadata.itemId)/cover?token=\(Store.serverConfig!.token)") else {
|
||||
return
|
||||
}
|
||||
|
||||
getData(from: url) { [self] image in
|
||||
ApiClient.getData(from: url) { [self] image in
|
||||
guard let downloadedImage = image else {
|
||||
return
|
||||
}
|
||||
@@ -52,7 +44,7 @@ class NowPlayingInfo {
|
||||
self.setMetadata(artwork: artwork, metadata: metadata)
|
||||
}
|
||||
}
|
||||
public static func update(duration: Double, currentTime: Double, rate: Float) {
|
||||
public func update(duration: Double, currentTime: Double, rate: Float) {
|
||||
nowPlayingInfo[MPMediaItemPropertyPlaybackDuration] = duration
|
||||
nowPlayingInfo[MPNowPlayingInfoPropertyElapsedPlaybackTime] = currentTime
|
||||
nowPlayingInfo[MPNowPlayingInfoPropertyPlaybackRate] = rate
|
||||
@@ -60,12 +52,12 @@ class NowPlayingInfo {
|
||||
|
||||
MPNowPlayingInfoCenter.default().nowPlayingInfo = nowPlayingInfo
|
||||
}
|
||||
public static func reset() {
|
||||
public func reset() {
|
||||
nowPlayingInfo = [:]
|
||||
MPNowPlayingInfoCenter.default().nowPlayingInfo = nil
|
||||
}
|
||||
|
||||
private static func setMetadata(artwork: MPMediaItemArtwork?, metadata: NowPlayingMetadata?) {
|
||||
private func setMetadata(artwork: MPMediaItemArtwork?, metadata: NowPlayingMetadata?) {
|
||||
if metadata == nil {
|
||||
return
|
||||
}
|
||||
@@ -84,7 +76,7 @@ class NowPlayingInfo {
|
||||
nowPlayingInfo[MPMediaItemPropertyArtist] = metadata!.author ?? "unknown"
|
||||
nowPlayingInfo[MPMediaItemPropertyAlbumTitle] = metadata!.series
|
||||
}
|
||||
private static func shouldFetchCover(id: String) -> Bool {
|
||||
private func shouldFetchCover(id: String) -> Bool {
|
||||
nowPlayingInfo[MPNowPlayingInfoPropertyExternalContentIdentifier] as? String != id || nowPlayingInfo[MPMediaItemPropertyArtwork] == nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,9 +16,9 @@ class Store {
|
||||
}
|
||||
set(updated) {
|
||||
if updated != nil {
|
||||
Database.setServerConnectionConfig(config: updated!)
|
||||
Database.shared.setServerConnectionConfig(config: updated!)
|
||||
} else {
|
||||
Database.setLastActiveConfigIndexToNil()
|
||||
Database.shared.setLastActiveConfigIndexToNil()
|
||||
}
|
||||
|
||||
Database.realmQueue.sync {
|
||||
|
||||
Reference in New Issue
Block a user