mirror of
https://github.com/advplyr/audiobookshelf-app.git
synced 2025-08-23 11:08:18 +02:00
Added PlaybackSession
This commit is contained in:
parent
782f11ff28
commit
239938e069
9 changed files with 121 additions and 60 deletions
|
@ -24,8 +24,8 @@ class AbsAudioPlayer : Plugin() {
|
||||||
|
|
||||||
lateinit var mainActivity: MainActivity
|
lateinit var mainActivity: MainActivity
|
||||||
lateinit var apiHandler:ApiHandler
|
lateinit var apiHandler:ApiHandler
|
||||||
lateinit var playerNotificationService: PlayerNotificationService
|
|
||||||
|
|
||||||
|
lateinit var playerNotificationService: PlayerNotificationService
|
||||||
override fun load() {
|
override fun load() {
|
||||||
mainActivity = (activity as MainActivity)
|
mainActivity = (activity as MainActivity)
|
||||||
apiHandler = ApiHandler(mainActivity)
|
apiHandler = ApiHandler(mainActivity)
|
||||||
|
|
|
@ -9,13 +9,13 @@
|
||||||
/* 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 */; };
|
||||||
|
3ABF580928059BAE005DFBE5 /* PlaybackSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ABF580828059BAE005DFBE5 /* PlaybackSession.swift */; };
|
||||||
3ABF618F2804325C0070250E /* PlayerHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ABF618E2804325C0070250E /* PlayerHandler.swift */; };
|
3ABF618F2804325C0070250E /* PlayerHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ABF618E2804325C0070250E /* PlayerHandler.swift */; };
|
||||||
3AD4FCE528043E50006DB301 /* AbsDatabase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AD4FCE428043E50006DB301 /* AbsDatabase.swift */; };
|
3AD4FCE528043E50006DB301 /* AbsDatabase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AD4FCE428043E50006DB301 /* AbsDatabase.swift */; };
|
||||||
3AD4FCE728043E72006DB301 /* AbsDatabase.m in Sources */ = {isa = PBXBuildFile; fileRef = 3AD4FCE628043E72006DB301 /* AbsDatabase.m */; };
|
3AD4FCE728043E72006DB301 /* AbsDatabase.m in Sources */ = {isa = PBXBuildFile; fileRef = 3AD4FCE628043E72006DB301 /* AbsDatabase.m */; };
|
||||||
3AD4FCE928043FD7006DB301 /* ServerConnectionConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AD4FCE828043FD7006DB301 /* ServerConnectionConfig.swift */; };
|
3AD4FCE928043FD7006DB301 /* ServerConnectionConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AD4FCE828043FD7006DB301 /* ServerConnectionConfig.swift */; };
|
||||||
3AD4FCEB280443DD006DB301 /* Database.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AD4FCEA280443DD006DB301 /* Database.swift */; };
|
3AD4FCEB280443DD006DB301 /* Database.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AD4FCEA280443DD006DB301 /* Database.swift */; };
|
||||||
3AD4FCED28044E6C006DB301 /* Store.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AD4FCEC28044E6C006DB301 /* Store.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 */; };
|
||||||
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 */; };
|
||||||
|
@ -29,13 +29,13 @@
|
||||||
/* 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>"; };
|
||||||
|
3ABF580828059BAE005DFBE5 /* PlaybackSession.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlaybackSession.swift; sourceTree = "<group>"; };
|
||||||
3ABF618E2804325C0070250E /* PlayerHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerHandler.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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
||||||
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>"; };
|
||||||
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>"; };
|
||||||
|
@ -102,8 +102,8 @@
|
||||||
3AFCB5E527EA232A00ECCC05 /* models */ = {
|
3AFCB5E527EA232A00ECCC05 /* models */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
3AD4FCEE28045D7C006DB301 /* Audiobook.swift */,
|
|
||||||
3AD4FCE828043FD7006DB301 /* ServerConnectionConfig.swift */,
|
3AD4FCE828043FD7006DB301 /* ServerConnectionConfig.swift */,
|
||||||
|
3ABF580828059BAE005DFBE5 /* PlaybackSession.swift */,
|
||||||
);
|
);
|
||||||
path = models;
|
path = models;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -278,10 +278,10 @@
|
||||||
files = (
|
files = (
|
||||||
3AD4FCE728043E72006DB301 /* AbsDatabase.m in Sources */,
|
3AD4FCE728043E72006DB301 /* AbsDatabase.m in Sources */,
|
||||||
504EC3081FED79650016851F /* AppDelegate.swift in Sources */,
|
504EC3081FED79650016851F /* AppDelegate.swift in Sources */,
|
||||||
|
3ABF580928059BAE005DFBE5 /* PlaybackSession.swift in Sources */,
|
||||||
3ABF618F2804325C0070250E /* PlayerHandler.swift in Sources */,
|
3ABF618F2804325C0070250E /* PlayerHandler.swift in Sources */,
|
||||||
3AD4FCED28044E6C006DB301 /* Store.swift in Sources */,
|
3AD4FCED28044E6C006DB301 /* Store.swift in Sources */,
|
||||||
3AD4FCE928043FD7006DB301 /* ServerConnectionConfig.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 */,
|
3AD4FCEB280443DD006DB301 /* Database.swift in Sources */,
|
||||||
|
|
|
@ -62,7 +62,10 @@ public class AbsDatabase: CAPPlugin {
|
||||||
"serverConnectionConfigs": configs.map { config in
|
"serverConnectionConfigs": configs.map { config in
|
||||||
return convertServerConnectionConfigToJSON(config: config)
|
return convertServerConnectionConfigToJSON(config: config)
|
||||||
},
|
},
|
||||||
"lastServerConnectionConfigId": index < 0 ? -1 : configs[index].id,
|
"lastServerConnectionConfigId": index < 0 ? -1 : configs.first(where: {
|
||||||
|
(config: ServerConnectionConfig) -> Bool in
|
||||||
|
return config.index == index
|
||||||
|
})!.id,
|
||||||
"currentLocalPlaybackSession": nil, // Luckily this isn't implemented yet
|
"currentLocalPlaybackSession": nil, // Luckily this isn't implemented yet
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
//
|
|
||||||
// AudioBook.swift
|
|
||||||
// App
|
|
||||||
//
|
|
||||||
// Created by Rasmus Krämer on 07.03.22.
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
struct Audiobook {
|
|
||||||
var streamId: String
|
|
||||||
var audiobookId: String
|
|
||||||
var playlistUrl: String
|
|
||||||
|
|
||||||
var startTime: Double = 0.0
|
|
||||||
var duration: Double
|
|
||||||
|
|
||||||
var title: String
|
|
||||||
var series: String?
|
|
||||||
var author: String?
|
|
||||||
var artworkUrl: String?
|
|
||||||
|
|
||||||
var token: String
|
|
||||||
}
|
|
57
ios/App/Shared/models/PlaybackSession.swift
Normal file
57
ios/App/Shared/models/PlaybackSession.swift
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
//
|
||||||
|
// PlaybackSession.swift
|
||||||
|
// App
|
||||||
|
//
|
||||||
|
// Created by Rasmus Krämer on 12.04.22.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
struct PlaybackSession {
|
||||||
|
var id: String
|
||||||
|
var userId: String?
|
||||||
|
var libraryItemId: String?
|
||||||
|
var episodeId: String?
|
||||||
|
var mediaType: String
|
||||||
|
// var mediaMetadata: MediaTypeMetadata - It is not implemented in android?
|
||||||
|
var chapters: [Chapter]
|
||||||
|
var displayTitle: String?
|
||||||
|
var displayAuthor: String?
|
||||||
|
var coverPath: String?
|
||||||
|
var duration: Double
|
||||||
|
var playMethod: Int
|
||||||
|
var startedAt: Double
|
||||||
|
var updatedAt: Double
|
||||||
|
var timeListening: Double
|
||||||
|
var audioTracks: [AudioTrack]
|
||||||
|
var currentTime: Double
|
||||||
|
// var libraryItem: LibraryItem?
|
||||||
|
// var localLibraryItem: LocalLibraryItem?
|
||||||
|
var serverConnectionConfigId: String?
|
||||||
|
var serverAddress: String?
|
||||||
|
}
|
||||||
|
struct Chapter {
|
||||||
|
var id: Int
|
||||||
|
var start: Double
|
||||||
|
var end: Double
|
||||||
|
var title: String?
|
||||||
|
}
|
||||||
|
struct AudioTrack {
|
||||||
|
var index: Int
|
||||||
|
var startOffset: Double
|
||||||
|
var duration: Double
|
||||||
|
var title: String
|
||||||
|
var contentUrl: String
|
||||||
|
var mimeType: String
|
||||||
|
var metadata: FileMetadata?
|
||||||
|
// var isLocal: Bool
|
||||||
|
// var localFileId: String?
|
||||||
|
// var audioProbeResult: AudioProbeResult? Need for local playback
|
||||||
|
var serverIndex: Int?
|
||||||
|
}
|
||||||
|
struct FileMetadata {
|
||||||
|
var filename: String
|
||||||
|
var ext: String
|
||||||
|
var path: String
|
||||||
|
var relPath: String
|
||||||
|
}
|
|
@ -24,21 +24,30 @@ class AudioPlayer: NSObject {
|
||||||
private var playWhenReady: Bool
|
private var playWhenReady: Bool
|
||||||
|
|
||||||
private var audioPlayer: AVPlayer
|
private var audioPlayer: AVPlayer
|
||||||
public var audiobook: Audiobook
|
private var playbackSession: PlaybackSession
|
||||||
|
private var activeAudioTrack: AudioTrack
|
||||||
|
|
||||||
// MARK: - Constructor
|
// MARK: - Constructor
|
||||||
init(audiobook: Audiobook, playWhenReady: Bool = false) {
|
init(playbackSession: PlaybackSession, playWhenReady: Bool = false) {
|
||||||
self.playWhenReady = playWhenReady
|
self.playWhenReady = playWhenReady
|
||||||
self.audiobook = audiobook
|
|
||||||
self.audioPlayer = AVPlayer()
|
self.audioPlayer = AVPlayer()
|
||||||
|
self.playbackSession = playbackSession
|
||||||
self.status = -1
|
self.status = -1
|
||||||
self.rate = 0.0
|
self.rate = 0.0
|
||||||
|
|
||||||
|
if playbackSession.audioTracks.count != 1 || playbackSession.audioTracks[0].mimeType != "application/vnd.apple.mpegurl" {
|
||||||
|
NSLog("The player only support HLS streams right now")
|
||||||
|
self.activeAudioTrack = AudioTrack(index: 0, startOffset: -1, duration: -1, title: "", contentUrl: "", mimeType: "")
|
||||||
|
|
||||||
|
super.init()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
self.activeAudioTrack = playbackSession.audioTracks[0]
|
||||||
|
|
||||||
super.init()
|
super.init()
|
||||||
|
|
||||||
initAudioSession()
|
initAudioSession()
|
||||||
setupRemoteTransportControls()
|
setupRemoteTransportControls()
|
||||||
NowPlayingInfo.setAudiobook(audiobook: audiobook)
|
|
||||||
|
|
||||||
// Listen to player events
|
// Listen to player events
|
||||||
self.audioPlayer.addObserver(self, forKeyPath: #keyPath(AVPlayer.rate), options: .new, context: &playerContext)
|
self.audioPlayer.addObserver(self, forKeyPath: #keyPath(AVPlayer.rate), options: .new, context: &playerContext)
|
||||||
|
@ -48,7 +57,7 @@ class AudioPlayer: NSObject {
|
||||||
playerItem.addObserver(self, forKeyPath: #keyPath(AVPlayerItem.status), options: .new, context: &playerItemContext)
|
playerItem.addObserver(self, forKeyPath: #keyPath(AVPlayerItem.status), options: .new, context: &playerItemContext)
|
||||||
|
|
||||||
self.audioPlayer.replaceCurrentItem(with: playerItem)
|
self.audioPlayer.replaceCurrentItem(with: playerItem)
|
||||||
seek(self.audiobook.startTime)
|
seek(self.playbackSession.currentTime)
|
||||||
|
|
||||||
NSLog("Audioplayer ready")
|
NSLog("Audioplayer ready")
|
||||||
}
|
}
|
||||||
|
@ -153,10 +162,10 @@ class AudioPlayer: NSObject {
|
||||||
// MARK: - Private
|
// MARK: - Private
|
||||||
private func createAsset() -> AVAsset {
|
private func createAsset() -> AVAsset {
|
||||||
let headers: [String: String] = [
|
let headers: [String: String] = [
|
||||||
"Authorization": "Bearer \(audiobook.token)"
|
"Authorization": "Bearer \(Store.serverConfig.token)"
|
||||||
]
|
]
|
||||||
|
|
||||||
return AVURLAsset(url: URL(string: audiobook.playlistUrl)!, options: ["AVURLAssetHTTPHeaderFieldsKey": headers])
|
return AVURLAsset(url: URL(string: activeAudioTrack.contentUrl)!, options: ["AVURLAssetHTTPHeaderFieldsKey": headers])
|
||||||
}
|
}
|
||||||
private func initAudioSession() {
|
private func initAudioSession() {
|
||||||
do {
|
do {
|
||||||
|
|
|
@ -9,9 +9,12 @@ import Foundation
|
||||||
|
|
||||||
class PlayerHandler {
|
class PlayerHandler {
|
||||||
private static var player: AudioPlayer?
|
private static var player: AudioPlayer?
|
||||||
// private static var item: any
|
private static var session: PlaybackSession?
|
||||||
|
|
||||||
public static func setItem() {
|
|
||||||
|
|
||||||
|
public static func startPlayback(session: PlaybackSession) {
|
||||||
|
if player != nil {
|
||||||
|
player?.destroy()
|
||||||
|
player = nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,19 +16,25 @@ func getData(from url: URL, completion: @escaping (UIImage?) -> Void) {
|
||||||
}).resume()
|
}).resume()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct NowPlayingMetadata {
|
||||||
|
var id: String
|
||||||
|
var artworkUrl: String?
|
||||||
|
var title: String
|
||||||
|
var author: String?
|
||||||
|
var series: String?
|
||||||
|
}
|
||||||
|
|
||||||
class NowPlayingInfo {
|
class NowPlayingInfo {
|
||||||
private static var nowPlayingInfo: [String: Any] = [:]
|
private static var nowPlayingInfo: [String: Any] = [:]
|
||||||
private static var audiobook: Audiobook?
|
|
||||||
|
|
||||||
public static func setAudiobook(audiobook: Audiobook) {
|
public static func setAudiobook(metadata: NowPlayingMetadata) {
|
||||||
self.audiobook = audiobook
|
setMetadata(artwork: nil, metadata: nil)
|
||||||
setMetadata(nil)
|
|
||||||
|
|
||||||
if !shouldFetchCover() || audiobook.artworkUrl == nil {
|
if !shouldFetchCover(id: metadata.id) || metadata.artworkUrl == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
guard let url = URL(string: audiobook.artworkUrl!) else { return }
|
guard let url = URL(string: metadata.artworkUrl!) else { return }
|
||||||
getData(from: url) { [self] image in
|
getData(from: url) { [self] image in
|
||||||
guard let downloadedImage = image else {
|
guard let downloadedImage = image else {
|
||||||
return
|
return
|
||||||
|
@ -37,7 +43,7 @@ class NowPlayingInfo {
|
||||||
return downloadedImage
|
return downloadedImage
|
||||||
})
|
})
|
||||||
|
|
||||||
self.setMetadata(artwork)
|
self.setMetadata(artwork: artwork, metadata: metadata)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public static func update(duration: Double, currentTime: Double, rate: Float) {
|
public static func update(duration: Double, currentTime: Double, rate: Float) {
|
||||||
|
@ -49,31 +55,29 @@ class NowPlayingInfo {
|
||||||
MPNowPlayingInfoCenter.default().nowPlayingInfo = nowPlayingInfo
|
MPNowPlayingInfoCenter.default().nowPlayingInfo = nowPlayingInfo
|
||||||
}
|
}
|
||||||
public static func reset() {
|
public static func reset() {
|
||||||
audiobook = nil
|
|
||||||
MPNowPlayingInfoCenter.default().nowPlayingInfo = nil
|
MPNowPlayingInfoCenter.default().nowPlayingInfo = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
private static func setMetadata(_ artwork: MPMediaItemArtwork?) {
|
private static func setMetadata(artwork: MPMediaItemArtwork?, metadata: NowPlayingMetadata?) {
|
||||||
if self.audiobook == nil {
|
if metadata == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if artwork != nil {
|
if artwork != nil {
|
||||||
nowPlayingInfo[MPMediaItemPropertyArtwork] = artwork
|
nowPlayingInfo[MPMediaItemPropertyArtwork] = artwork
|
||||||
} else if shouldFetchCover() {
|
} else if shouldFetchCover(id: metadata!.id) {
|
||||||
nowPlayingInfo[MPMediaItemPropertyArtwork] = nil
|
nowPlayingInfo[MPMediaItemPropertyArtwork] = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
nowPlayingInfo[MPNowPlayingInfoPropertyExternalContentIdentifier] = audiobook!.streamId
|
nowPlayingInfo[MPNowPlayingInfoPropertyExternalContentIdentifier] = metadata!.id
|
||||||
nowPlayingInfo[MPNowPlayingInfoPropertyAssetURL] = URL(string: audiobook!.playlistUrl)
|
|
||||||
nowPlayingInfo[MPNowPlayingInfoPropertyIsLiveStream] = false
|
nowPlayingInfo[MPNowPlayingInfoPropertyIsLiveStream] = false
|
||||||
nowPlayingInfo[MPNowPlayingInfoPropertyMediaType] = "hls"
|
nowPlayingInfo[MPNowPlayingInfoPropertyMediaType] = "hls"
|
||||||
|
|
||||||
nowPlayingInfo[MPMediaItemPropertyTitle] = audiobook!.title
|
nowPlayingInfo[MPMediaItemPropertyTitle] = metadata!.title
|
||||||
nowPlayingInfo[MPMediaItemPropertyArtist] = audiobook!.author ?? "unknown"
|
nowPlayingInfo[MPMediaItemPropertyArtist] = metadata!.author ?? "unknown"
|
||||||
nowPlayingInfo[MPMediaItemPropertyAlbumTitle] = audiobook!.series
|
nowPlayingInfo[MPMediaItemPropertyAlbumTitle] = metadata!.series
|
||||||
}
|
}
|
||||||
private static func shouldFetchCover() -> Bool {
|
private static func shouldFetchCover(id: String) -> Bool {
|
||||||
audiobook != nil && (nowPlayingInfo[MPNowPlayingInfoPropertyExternalContentIdentifier] as? String != audiobook!.streamId || nowPlayingInfo[MPMediaItemPropertyArtwork] == nil)
|
nowPlayingInfo[MPNowPlayingInfoPropertyExternalContentIdentifier] as? String != id || nowPlayingInfo[MPMediaItemPropertyArtwork] == nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,14 +9,23 @@ import Foundation
|
||||||
import RealmSwift
|
import RealmSwift
|
||||||
|
|
||||||
class Store {
|
class Store {
|
||||||
|
private static var _serverConfig: ServerConnectionConfig?
|
||||||
// ONLY USE REALM IN Database.realmQueue OR ELSE THE APP WILL CRASH
|
// ONLY USE REALM IN Database.realmQueue OR ELSE THE APP WILL CRASH
|
||||||
public static var serverConfig: ServerConnectionConfig {
|
public static var serverConfig: ServerConnectionConfig {
|
||||||
get {
|
get {
|
||||||
|
if _serverConfig == nil {
|
||||||
|
let index = Database.getActiveServerConfigIndex()
|
||||||
// TODO: change this when multiple configs are possible
|
// TODO: change this when multiple configs are possible
|
||||||
Database.getServerConnectionConfigs()[Database.getActiveServerConfigIndex()]
|
_serverConfig = Database.getServerConnectionConfigs().first { config in
|
||||||
|
return config.index == index
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return _serverConfig ?? ServerConnectionConfig()
|
||||||
}
|
}
|
||||||
set(updated) {
|
set(updated) {
|
||||||
Database.setServerConnectionConfig(config: updated)
|
Database.setServerConnectionConfig(config: updated)
|
||||||
|
_serverConfig = updated
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue