From a44cce462ad7e9c28814819e27644b4a76ab7634 Mon Sep 17 00:00:00 2001 From: Arkadiusz Fal Date: Thu, 10 Nov 2022 23:00:17 +0100 Subject: [PATCH] Preserve playback rate between restarts --- Model/Player/Backends/AVPlayerBackend.swift | 8 ++++---- Model/Player/Backends/MPVBackend.swift | 4 ++-- Model/Player/Backends/PlayerBackend.swift | 2 +- Model/Player/PlayerModel.swift | 13 ++++++++++--- Model/Player/PlayerTVMenu.swift | 2 +- Shared/Defaults.swift | 1 + 6 files changed, 19 insertions(+), 11 deletions(-) diff --git a/Model/Player/Backends/AVPlayerBackend.swift b/Model/Player/Backends/AVPlayerBackend.swift index 56f7a26a..22e36d5c 100644 --- a/Model/Player/Backends/AVPlayerBackend.swift +++ b/Model/Player/Backends/AVPlayerBackend.swift @@ -177,8 +177,8 @@ final class AVPlayerBackend: PlayerBackend { ) } - func setRate(_ rate: Float) { - avPlayer.rate = rate + func setRate(_ rate: Double) { + avPlayer.rate = Float(rate) } func closeItem() { @@ -616,8 +616,8 @@ final class AVPlayerBackend: PlayerBackend { if player.timeControlStatus == .playing { self.model.objectWillChange.send() - if player.rate != self.model.currentRate { - player.rate = self.model.currentRate + if player.rate != Float(self.model.currentRate) { + player.rate = Float(self.model.currentRate) } } diff --git a/Model/Player/Backends/MPVBackend.swift b/Model/Player/Backends/MPVBackend.swift index be9e53e4..6047f211 100644 --- a/Model/Player/Backends/MPVBackend.swift +++ b/Model/Player/Backends/MPVBackend.swift @@ -360,8 +360,8 @@ final class MPVBackend: PlayerBackend { } } - func setRate(_ rate: Float) { - client?.setDoubleAsync("speed", Double(rate)) + func setRate(_ rate: Double) { + client?.setDoubleAsync("speed", rate) } func closeItem() { diff --git a/Model/Player/Backends/PlayerBackend.swift b/Model/Player/Backends/PlayerBackend.swift index 6cd22927..118b0ea7 100644 --- a/Model/Player/Backends/PlayerBackend.swift +++ b/Model/Player/Backends/PlayerBackend.swift @@ -47,7 +47,7 @@ protocol PlayerBackend { func seek(to time: CMTime, seekType: SeekType, completionHandler: ((Bool) -> Void)?) func seek(to seconds: Double, seekType: SeekType, completionHandler: ((Bool) -> Void)?) - func setRate(_ rate: Float) + func setRate(_ rate: Double) func closeItem() diff --git a/Model/Player/PlayerModel.swift b/Model/Player/PlayerModel.swift index 0abdef50..4064451b 100644 --- a/Model/Player/PlayerModel.swift +++ b/Model/Player/PlayerModel.swift @@ -47,7 +47,7 @@ final class PlayerModel: ObservableObject { static var shared: PlayerModel! - static let availableRates: [Float] = [0.5, 0.67, 0.8, 1, 1.25, 1.5, 2] + static let availableRates: [Double] = [0.5, 0.67, 0.8, 1, 1.25, 1.5, 2] let logger = Logger(label: "stream.yattee.app") var avPlayerView = AppleAVPlayerView() @@ -86,7 +86,7 @@ final class PlayerModel: ObservableObject { }} @Published var aspectRatio = VideoPlayerView.defaultAspectRatio @Published var stream: Stream? - @Published var currentRate: Float = 1.0 { didSet { backend.setRate(currentRate) } } + @Published var currentRate: Double = 1.0 { didSet { handleCurrentRateChange() } } @Published var qualityProfileSelection: QualityProfile? { didSet { handleQualityProfileChange() } } @@ -162,6 +162,7 @@ final class PlayerModel: ObservableObject { @Default(.closePiPOnNavigation) var closePiPOnNavigation @Default(.closePiPOnOpeningPlayer) var closePiPOnOpeningPlayer @Default(.resetWatchedStatusOnPlaying) var resetWatchedStatusOnPlaying + @Default(.playerRate) var playerRate #if !os(macOS) @Default(.closePiPAndOpenPlayerOnEnteringForeground) var closePiPAndOpenPlayerOnEnteringForeground @@ -197,6 +198,7 @@ final class PlayerModel: ObservableObject { self.pipDelegate = pipDelegate pipController?.delegate = pipDelegate + currentRate = playerRate } func show() { @@ -540,6 +542,11 @@ final class PlayerModel: ObservableObject { } } + func handleCurrentRateChange() { + backend.setRate(currentRate) + playerRate = currentRate + } + func handleQualityProfileChange() { guard let profile = qualityProfile else { return } @@ -552,7 +559,7 @@ final class PlayerModel: ObservableObject { } } - func rateLabel(_ rate: Float) -> String { + func rateLabel(_ rate: Double) -> String { let formatter = NumberFormatter() formatter.minimumFractionDigits = 0 formatter.maximumFractionDigits = 2 diff --git a/Model/Player/PlayerTVMenu.swift b/Model/Player/PlayerTVMenu.swift index 352f00ca..cfd37c0a 100644 --- a/Model/Player/PlayerTVMenu.swift +++ b/Model/Player/PlayerTVMenu.swift @@ -60,7 +60,7 @@ extension PlayerModel { private var rateMenuActions: [UIAction] { PlayerModel.availableRates.map { rate in - let image = currentRate == Float(rate) ? UIImage(systemName: "checkmark") : nil + let image = currentRate == rate ? UIImage(systemName: "checkmark") : nil return UIAction(title: rateLabel(rate), image: image) { _ in DispatchQueue.main.async { diff --git a/Shared/Defaults.swift b/Shared/Defaults.swift index eea54a22..ecfbdae1 100644 --- a/Shared/Defaults.swift +++ b/Shared/Defaults.swift @@ -87,6 +87,7 @@ extension Defaults.Keys { static let chargingCellularProfileDefault = hd1080pMPVProfile.id static let chargingNonCellularProfileDefault = hd1080pMPVProfile.id #endif + static let playerRate = Key("playerRate", default: 1.0) static let qualityProfiles = Key<[QualityProfile]>("qualityProfiles", default: qualityProfilesDefault) static let batteryCellularProfile = Key("batteryCellularProfile", default: batteryCellularProfileDefault) static let batteryNonCellularProfile = Key("batteryNonCellularProfile", default: batteryNonCellularProfileDefault)