1
0
mirror of https://github.com/yattee/yattee.git synced 2024-12-14 06:10:32 +05:30
yattee/Model/Player/Backends/PlayerBackend.swift

155 lines
4.7 KiB
Swift
Raw Normal View History

2022-02-17 01:53:11 +05:30
import CoreMedia
import Defaults
import Foundation
#if !os(macOS)
import UIKit
#endif
2022-02-17 01:53:11 +05:30
protocol PlayerBackend {
2022-11-11 03:49:34 +05:30
var suggestedPlaybackRates: [Double] { get }
var model: PlayerModel { get }
var controls: PlayerControlsModel { get }
var playerTime: PlayerTimeModel { get }
var networkState: NetworkStateModel { get }
2022-02-17 01:53:11 +05:30
var stream: Stream? { get set }
var video: Video? { get set }
var currentTime: CMTime? { get }
var loadedVideo: Bool { get }
var isLoadingVideo: Bool { get }
var isPlaying: Bool { get }
var isSeeking: Bool { get }
2022-02-17 01:53:11 +05:30
var playerItemDuration: CMTime? { get }
2022-07-09 05:51:04 +05:30
var aspectRatio: Double { get }
2022-08-24 02:59:50 +05:30
var controlsUpdates: Bool { get }
2022-07-09 05:51:04 +05:30
2022-11-10 22:41:28 +05:30
var videoWidth: Double? { get }
var videoHeight: Double? { get }
2022-03-28 00:29:22 +05:30
func bestPlayable(_ streams: [Stream], maxResolution: ResolutionSetting) -> Stream?
2022-02-17 01:53:11 +05:30
func canPlay(_ stream: Stream) -> Bool
2022-11-11 03:49:34 +05:30
func canPlayAtRate(_ rate: Double) -> Bool
2022-02-17 01:53:11 +05:30
func playStream(
_ stream: Stream,
of video: Video,
preservingTime: Bool,
upgrading: Bool
)
func play()
func pause()
func togglePlay()
func stop()
2022-08-29 17:25:23 +05:30
func seek(to time: CMTime, seekType: SeekType, completionHandler: ((Bool) -> Void)?)
func seek(to seconds: Double, seekType: SeekType, completionHandler: ((Bool) -> Void)?)
2022-02-17 01:53:11 +05:30
func setRate(_ rate: Double)
2022-02-17 01:53:11 +05:30
func closeItem()
2022-08-19 04:10:46 +05:30
func closePiP()
2022-02-17 01:53:11 +05:30
2022-08-21 02:01:03 +05:30
func startMusicMode()
func stopMusicMode()
func getTimeUpdates()
func updateControls(completionHandler: (() -> Void)?)
2022-02-17 01:53:11 +05:30
func startControlsUpdates()
func stopControlsUpdates()
2022-08-21 02:01:03 +05:30
func didChangeTo()
2022-06-25 05:09:29 +05:30
func setNeedsNetworkStateUpdates(_ needsUpdates: Bool)
2022-02-17 01:53:11 +05:30
func setNeedsDrawing(_ needsDrawing: Bool)
2022-03-27 17:12:20 +05:30
func setSize(_ width: Double, _ height: Double)
func cancelLoads()
2022-02-17 01:53:11 +05:30
}
extension PlayerBackend {
2022-08-29 17:25:23 +05:30
func seek(to time: CMTime, seekType: SeekType, completionHandler: ((Bool) -> Void)? = nil) {
2022-09-02 04:35:31 +05:30
model.seek.registerSeek(at: time, type: seekType, restore: currentTime)
seek(to: time, seekType: seekType, completionHandler: completionHandler)
2022-02-17 01:53:11 +05:30
}
2022-08-29 17:25:23 +05:30
func seek(to seconds: Double, seekType: SeekType, completionHandler: ((Bool) -> Void)? = nil) {
let seconds = CMTime.secondsInDefaultTimescale(seconds)
2022-09-02 04:35:31 +05:30
model.seek.registerSeek(at: seconds, type: seekType, restore: currentTime)
seek(to: seconds, seekType: seekType, completionHandler: completionHandler)
2022-02-17 01:53:11 +05:30
}
2022-08-29 17:25:23 +05:30
func seek(relative time: CMTime, seekType: SeekType, completionHandler: ((Bool) -> Void)? = nil) {
2022-09-28 19:57:01 +05:30
if let currentTime, let duration = playerItemDuration {
let seekTime = min(max(0, currentTime.seconds + time.seconds), duration.seconds)
2022-09-02 04:35:31 +05:30
model.seek.registerSeek(at: .secondsInDefaultTimescale(seekTime), type: seekType, restore: currentTime)
seek(to: seekTime, seekType: seekType, completionHandler: completionHandler)
}
2022-02-17 01:53:11 +05:30
}
2022-07-11 03:54:56 +05:30
func eofPlaybackModeAction() {
2022-12-19 00:09:03 +05:30
let loopAction = {
model.backend.seek(to: .zero, seekType: .loopRestart) { _ in
self.model.play()
}
}
guard model.playbackMode != .loopOne else {
loopAction()
return
}
2023-04-22 17:26:25 +05:30
switch model.playbackMode {
case .queue, .shuffle:
model.prepareCurrentItemForHistory(finished: true)
if model.queue.isEmpty {
#if os(tvOS)
if model.activeBackend == .appleAVPlayer {
model.avPlayerBackend.controller?.dismiss(animated: false)
}
#endif
model.resetQueue()
model.hide()
2022-12-19 00:09:03 +05:30
} else {
2023-04-22 17:26:25 +05:30
model.advanceToNextItem()
2022-12-19 00:09:03 +05:30
}
2023-04-22 17:26:25 +05:30
case .loopOne:
loopAction()
case .related:
guard let item = model.autoplayItem else { return }
model.resetAutoplay()
model.advanceToItem(item)
2022-12-19 00:09:03 +05:30
}
2022-07-11 03:54:56 +05:30
}
func updateControls(completionHandler: (() -> Void)? = nil) {
print("updating controls")
guard model.presentingPlayer, !model.controls.presentingOverlays else {
print("ignored controls update")
completionHandler?()
return
}
DispatchQueue.main.async(qos: .userInteractive) {
#if !os(macOS)
guard UIApplication.shared.applicationState != .background else {
print("not performing controls updates in background")
completionHandler?()
return
}
#endif
2022-09-01 00:54:46 +05:30
PlayerTimeModel.shared.currentTime = self.currentTime ?? .zero
PlayerTimeModel.shared.duration = self.playerItemDuration ?? .zero
completionHandler?()
}
}
2022-02-17 01:53:11 +05:30
}