yattee/Model/Player/PlayerStreams.swift

81 lines
2.7 KiB
Swift
Raw Normal View History

2021-10-16 22:48:58 +00:00
import Foundation
import Siesta
2021-10-18 21:53:02 +00:00
import SwiftUI
2021-10-16 22:48:58 +00:00
extension PlayerModel {
var isLoadingAvailableStreams: Bool {
streamSelection.isNil || availableStreams.isEmpty
}
var isLoadingStream: Bool {
!stream.isNil && stream != streamSelection
}
2021-10-17 21:49:56 +00:00
var availableStreamsSorted: [Stream] {
availableStreams.sorted(by: streamsSorter)
}
2021-12-19 16:56:47 +00:00
func loadAvailableStreams(_ video: Video) {
2021-10-16 22:48:58 +00:00
availableStreams = []
2021-12-19 16:56:47 +00:00
guard let playerInstance = InstancesModel.forPlayer ?? InstancesModel.all.first else {
2021-12-19 16:56:47 +00:00
return
}
2021-10-16 22:48:58 +00:00
logger.info("loading streams from \(playerInstance.description)")
2021-12-19 16:56:47 +00:00
fetchStreams(playerInstance.anonymous.video(video.videoID), instance: playerInstance, video: video)
2021-10-16 22:48:58 +00:00
}
2021-10-20 22:21:50 +00:00
private func fetchStreams(
_ resource: Resource,
instance: Instance,
2021-10-16 22:48:58 +00:00
video: Video,
onCompletion: @escaping (ResponseInfo) -> Void = { _ in }
) {
2021-10-20 22:21:50 +00:00
resource
2021-10-16 22:48:58 +00:00
.load()
.onSuccess { response in
if let video: Video = response.typedContent() {
guard video == self.currentVideo else {
self.logger.info("ignoring loaded streams from \(instance.description) as current video has changed")
return
}
2021-10-20 22:21:50 +00:00
self.availableStreams += self.streamsWithInstance(instance: instance, streams: video.streams)
2021-12-19 16:56:47 +00:00
} else {
self.logger.critical("no streams available from \(instance.description)")
2021-10-16 22:48:58 +00:00
}
}
.onCompletion(onCompletion)
2022-06-29 22:44:32 +00:00
.onFailure { [weak self] responseError in
self?.navigation.presentAlert(title: "Could not load streams", message: responseError.userMessage)
self?.videoBeingOpened = nil
}
2021-10-16 22:48:58 +00:00
}
func streamsWithInstance(instance: Instance, streams: [Stream]) -> [Stream] {
streams.map { stream in
stream.instance = instance
if instance.app == .invidious {
if let audio = stream.audioAsset {
stream.audioAsset = InvidiousAPI.proxiedAsset(instance: instance, asset: audio)
}
if let video = stream.videoAsset {
stream.videoAsset = InvidiousAPI.proxiedAsset(instance: instance, asset: video)
}
}
2021-10-22 15:00:09 +00:00
2021-10-16 22:48:58 +00:00
return stream
}
}
2021-10-17 21:49:56 +00:00
func streamsSorter(_ lhs: Stream, _ rhs: Stream) -> Bool {
if lhs.resolution.isNil || rhs.resolution.isNil {
return lhs.kind < rhs.kind
}
return lhs.kind == rhs.kind ? (lhs.resolution.height > rhs.resolution.height) : (lhs.kind < rhs.kind)
2021-10-17 21:49:56 +00:00
}
2021-10-16 22:48:58 +00:00
}