From 9701c767b226dfbe3835afa02b90a1f244477588 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rasmus=20Kr=C3=A4mer?= Date: Tue, 3 May 2022 12:55:13 +0200 Subject: [PATCH] Small improvements --- ios/App/App/plugins/AbsDatabase.swift | 9 +++--- ios/App/Shared/player/AudioPlayer.swift | 15 +++++----- ios/App/Shared/player/PlayerHandler.swift | 33 +++++++++++---------- ios/App/Shared/util/ApiClient.swift | 9 +++++- ios/App/Shared/util/Database.swift | 35 ++++++++++++++-------- ios/App/Shared/util/Extensions.swift | 11 +++++++ ios/App/Shared/util/NowPlayingInfo.swift | 36 +++++++++-------------- ios/App/Shared/util/Store.swift | 4 +-- 8 files changed, 86 insertions(+), 66 deletions(-) diff --git a/ios/App/App/plugins/AbsDatabase.swift b/ios/App/App/plugins/AbsDatabase.swift index de9c5c89..99a403e9 100644 --- a/ios/App/App/plugins/AbsDatabase.swift +++ b/ios/App/App/plugins/AbsDatabase.swift @@ -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, ]) } diff --git a/ios/App/Shared/player/AudioPlayer.swift b/ios/App/Shared/player/AudioPlayer.swift index 52e2b886..29156d40 100644 --- a/ios/App/Shared/player/AudioPlayer.swift +++ b/ios/App/Shared/player/AudioPlayer.swift @@ -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 diff --git a/ios/App/Shared/player/PlayerHandler.swift b/ios/App/Shared/player/PlayerHandler.swift index c2009e7b..b7554139 100644 --- a/ios/App/Shared/player/PlayerHandler.swift +++ b/ios/App/Shared/player/PlayerHandler.swift @@ -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 diff --git a/ios/App/Shared/util/ApiClient.swift b/ios/App/Shared/util/ApiClient.swift index 2b3f06bd..3a0404cc 100644 --- a/ios/App/Shared/util/ApiClient.swift +++ b/ios/App/Shared/util/ApiClient.swift @@ -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(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!)" diff --git a/ios/App/Shared/util/Database.swift b/ios/App/Shared/util/Database.swift index d9e0b63a..1c528dfe 100644 --- a/ios/App/Shared/util/Database.swift +++ b/ios/App/Shared/util/Database.swift @@ -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? 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] = [] - 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 } } diff --git a/ios/App/Shared/util/Extensions.swift b/ios/App/Shared/util/Extensions.swift index 22afddd2..e4badb99 100644 --- a/ios/App/Shared/util/Extensions.swift +++ b/ios/App/Shared/util/Extensions.swift @@ -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() + } + } + } +} diff --git a/ios/App/Shared/util/NowPlayingInfo.swift b/ios/App/Shared/util/NowPlayingInfo.swift index e268ec4c..71e0528a 100644 --- a/ios/App/Shared/util/NowPlayingInfo.swift +++ b/ios/App/Shared/util/NowPlayingInfo.swift @@ -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 } } diff --git a/ios/App/Shared/util/Store.swift b/ios/App/Shared/util/Store.swift index a4ae9863..52fbd059 100644 --- a/ios/App/Shared/util/Store.swift +++ b/ios/App/Shared/util/Store.swift @@ -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 {