Model improvements

This commit is contained in:
Arkadiusz Fal
2022-09-02 01:05:31 +02:00
parent 7b48041165
commit f607e6e276
23 changed files with 194 additions and 270 deletions

View File

@@ -12,11 +12,11 @@ final class AVPlayerBackend: PlayerBackend {
private var logger = Logger(label: "avplayer-backend")
var model: PlayerModel!
var controls: PlayerControlsModel!
var playerTime: PlayerTimeModel!
var networkState: NetworkStateModel!
var seek: SeekModel!
var model: PlayerModel! { .shared }
var controls: PlayerControlsModel! { .shared }
var playerTime: PlayerTimeModel! { .shared }
var networkState: NetworkStateModel! { .shared }
var seek: SeekModel! { .shared }
var stream: Stream?
var video: Video?
@@ -76,11 +76,7 @@ final class AVPlayerBackend: PlayerBackend {
internal var controlsUpdates = false
init(model: PlayerModel, controls: PlayerControlsModel?, playerTime: PlayerTimeModel?) {
self.model = model
self.controls = controls
self.playerTime = playerTime ?? PlayerTimeModel.shared
init() {
addFrequentTimeObserver()
addInfrequentTimeObserver()
addPlayerTimeControlStatusObserver()

View File

@@ -13,11 +13,11 @@ final class MPVBackend: PlayerBackend {
private var logger = Logger(label: "mpv-backend")
var model: PlayerModel!
var controls: PlayerControlsModel!
var playerTime: PlayerTimeModel!
var networkState: NetworkStateModel!
var seek: SeekModel!
var model: PlayerModel! { .shared }
var controls: PlayerControlsModel! { .shared }
var playerTime: PlayerTimeModel! { .shared }
var networkState: NetworkStateModel! { .shared }
var seek: SeekModel! { .shared }
var stream: Stream?
var video: Video?
@@ -120,17 +120,7 @@ final class MPVBackend: PlayerBackend {
client?.cacheDuration ?? 0
}
init(
model: PlayerModel,
controls: PlayerControlsModel? = nil,
playerTime: PlayerTimeModel? = nil,
networkState: NetworkStateModel? = nil
) {
self.model = model
self.controls = controls
self.playerTime = playerTime ?? PlayerTimeModel.shared
self.networkState = networkState
init() {
clientTimer = .init(interval: .seconds(Self.timeUpdateInterval), mode: .infinite) { [weak self] _ in
self?.getTimeUpdates()
}

View File

@@ -6,11 +6,10 @@ import Foundation
#endif
protocol PlayerBackend {
var model: PlayerModel! { get set }
var controls: PlayerControlsModel! { get set }
var playerTime: PlayerTimeModel! { get set }
var seek: SeekModel! { get set }
var networkState: NetworkStateModel! { get set }
var model: PlayerModel! { get }
var controls: PlayerControlsModel! { get }
var playerTime: PlayerTimeModel! { get }
var networkState: NetworkStateModel! { get }
var stream: Stream? { get set }
var video: Video? { get set }
@@ -69,20 +68,20 @@ protocol PlayerBackend {
extension PlayerBackend {
func seek(to time: CMTime, seekType: SeekType, completionHandler: ((Bool) -> Void)? = nil) {
seek.registerSeek(at: time, type: seekType, restore: currentTime)
model.seek.registerSeek(at: time, type: seekType, restore: currentTime)
seek(to: time, seekType: seekType, completionHandler: completionHandler)
}
func seek(to seconds: Double, seekType: SeekType, completionHandler: ((Bool) -> Void)? = nil) {
let seconds = CMTime.secondsInDefaultTimescale(seconds)
seek.registerSeek(at: seconds, type: seekType, restore: currentTime)
model.seek.registerSeek(at: seconds, type: seekType, restore: currentTime)
seek(to: seconds, seekType: seekType, completionHandler: completionHandler)
}
func seek(relative time: CMTime, seekType: SeekType, completionHandler: ((Bool) -> Void)? = nil) {
if let currentTime = currentTime, let duration = playerItemDuration {
let seekTime = min(max(0, currentTime.seconds + time.seconds), duration.seconds)
seek.registerSeek(at: .secondsInDefaultTimescale(seekTime), type: seekType, restore: currentTime)
model.seek.registerSeek(at: .secondsInDefaultTimescale(seekTime), type: seekType, restore: currentTime)
seek(to: seekTime, seekType: seekType, completionHandler: completionHandler)
}
}

View File

@@ -0,0 +1,21 @@
import Defaults
import Foundation
import SwiftUI
final class ControlOverlaysModel: ObservableObject {
static let shared = ControlOverlaysModel()
@Published var presenting = false { didSet { handlePresentationChange() } }
private lazy var controls = PlayerControlsModel.shared
private lazy var player: PlayerModel! = PlayerModel.shared
func toggle() {
presenting.toggle()
controls.objectWillChange.send()
}
private func handlePresentationChange() {
guard let player = player else { return }
player.backend.setNeedsNetworkStateUpdates(presenting && Defaults[.showMPVPlaybackStats])
}
}

View File

@@ -10,7 +10,6 @@ final class PlayerControlsModel: ObservableObject {
@Published var isLoadingVideo = false
@Published var isPlaying = true
@Published var presentingControls = false { didSet { handlePresentationChange() } }
@Published var presentingControlsOverlay = false { didSet { handleSettingsOverlayPresentationChange() } }
@Published var presentingDetailsOverlay = false { didSet { handleDetailsOverlayPresentationChange() } }
var timer: Timer?
@@ -18,24 +17,21 @@ final class PlayerControlsModel: ObservableObject {
private(set) var reporter = PassthroughSubject<String, Never>()
#endif
var player: PlayerModel!
private var player: PlayerModel! { .shared }
private var controlsOverlayModel = ControlOverlaysModel.shared
init(
isLoadingVideo: Bool = false,
isPlaying: Bool = true,
presentingControls: Bool = false,
presentingControlsOverlay: Bool = false,
presentingDetailsOverlay: Bool = false,
timer: Timer? = nil,
player: PlayerModel? = nil
timer: Timer? = nil
) {
self.isLoadingVideo = isLoadingVideo
self.isPlaying = isPlaying
self.presentingControls = presentingControls
self.presentingControlsOverlay = presentingControlsOverlay
self.presentingDetailsOverlay = presentingDetailsOverlay
self.timer = timer
self.player = player ?? .shared
}
func handlePresentationChange() {
@@ -60,26 +56,22 @@ final class PlayerControlsModel: ObservableObject {
}
func handleSettingsOverlayPresentationChange() {
player?.backend.setNeedsNetworkStateUpdates(presentingControlsOverlay && Defaults[.showMPVPlaybackStats])
player?.backend.setNeedsNetworkStateUpdates(controlsOverlayModel.presenting && Defaults[.showMPVPlaybackStats])
}
func handleDetailsOverlayPresentationChange() {}
var presentingOverlays: Bool {
presentingDetailsOverlay || presentingControlsOverlay
presentingDetailsOverlay || controlsOverlayModel.presenting
}
func hideOverlays() {
presentingDetailsOverlay = false
presentingControlsOverlay = false
controlsOverlayModel.presenting = false
}
func show() {
guard !(player?.currentItem.isNil ?? true) else {
return
}
guard !presentingControls else {
guard !player.currentItem.isNil, !presentingControls else {
return
}
@@ -132,4 +124,8 @@ final class PlayerControlsModel: ObservableObject {
timer?.invalidate()
timer = nil
}
func update() {
player?.backend.updateControls()
}
}

View File

@@ -58,8 +58,8 @@ final class PlayerModel: ObservableObject {
@Published var presentingPlayer = false { didSet { handlePresentationChange() } }
@Published var activeBackend = PlayerBackendType.mpv
var avPlayerBackend: AVPlayerBackend!
var mpvBackend: MPVBackend!
var avPlayerBackend = AVPlayerBackend()
var mpvBackend = MPVBackend()
#if !os(macOS)
var mpvController = MPVViewController()
#endif
@@ -124,34 +124,10 @@ final class PlayerModel: ObservableObject {
var accounts: AccountsModel
var comments: CommentsModel
var controls: PlayerControlsModel { didSet {
backends.forEach { backend in
var backend = backend
backend.controls = controls
backend.controls.player = self
}
}}
var playerTime: PlayerTimeModel { didSet {
backends.forEach { backend in
var backend = backend
backend.playerTime = playerTime
backend.playerTime.player = self
}
}}
var networkState: NetworkStateModel { didSet {
backends.forEach { backend in
var backend = backend
backend.networkState = networkState
backend.networkState.player = self
}
}}
var seek: SeekModel { didSet {
backends.forEach { backend in
var backend = backend
backend.seek = seek
backend.seek.player = self
}
}}
var controls: PlayerControlsModel { .shared }
var playerTime: PlayerTimeModel { .shared }
var networkState: NetworkStateModel { .shared }
var seek: SeekModel { .shared }
var navigation: NavigationModel
var context: NSManagedObjectContext = PersistenceController.shared.container.viewContext
@@ -194,30 +170,11 @@ final class PlayerModel: ObservableObject {
init(
accounts: AccountsModel = AccountsModel(),
comments: CommentsModel = CommentsModel(),
controls: PlayerControlsModel = PlayerControlsModel(),
navigation: NavigationModel = NavigationModel(),
playerTime: PlayerTimeModel = PlayerTimeModel(),
networkState: NetworkStateModel = NetworkStateModel(),
seek: SeekModel = SeekModel()
navigation: NavigationModel = NavigationModel()
) {
self.accounts = accounts
self.comments = comments
self.controls = controls
self.navigation = navigation
self.playerTime = playerTime
self.networkState = networkState
self.seek = seek
self.avPlayerBackend = AVPlayerBackend(
model: self,
controls: controls,
playerTime: playerTime
)
self.mpvBackend = MPVBackend(
model: self,
playerTime: playerTime,
networkState: networkState
)
#if !os(macOS)
mpvBackend.controller = mpvController