mirror of
https://github.com/yattee/yattee.git
synced 2024-12-22 21:43:41 +00:00
Better loading and handling streams
This commit is contained in:
parent
1fbb0cfa80
commit
cef0b2594a
@ -6,6 +6,14 @@ final class InstancesModel: ObservableObject {
|
|||||||
Defaults[.instances]
|
Defaults[.instances]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static var forPlayer: Instance? {
|
||||||
|
guard let id = Defaults[.playerInstanceID] else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return InstancesModel.find(id)
|
||||||
|
}
|
||||||
|
|
||||||
var lastUsed: Instance? {
|
var lastUsed: Instance? {
|
||||||
guard let id = Defaults[.lastInstanceID] else {
|
guard let id = Defaults[.lastInstanceID] else {
|
||||||
return nil
|
return nil
|
||||||
|
@ -27,15 +27,13 @@ final class InvidiousAPI: Service, ObservableObject, VideosAPI {
|
|||||||
self.account = account
|
self.account = account
|
||||||
signedIn = false
|
signedIn = false
|
||||||
|
|
||||||
if account.anonymous {
|
validInstance = account.anonymous
|
||||||
validInstance = true
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
validInstance = false
|
|
||||||
|
|
||||||
configure()
|
configure()
|
||||||
validate()
|
|
||||||
|
if !account.anonymous {
|
||||||
|
validate()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func validate() {
|
func validate() {
|
||||||
|
@ -26,7 +26,7 @@ final class PlayerModel: ObservableObject {
|
|||||||
@Published var stream: Stream?
|
@Published var stream: Stream?
|
||||||
@Published var currentRate: Float = 1.0 { didSet { player.rate = currentRate } }
|
@Published var currentRate: Float = 1.0 { didSet { player.rate = currentRate } }
|
||||||
|
|
||||||
@Published var availableStreams = [Stream]() { didSet { rebuildTVMenu() } }
|
@Published var availableStreams = [Stream]() { didSet { handleAvailableStreamsChange() }}
|
||||||
@Published var streamSelection: Stream? { didSet { rebuildTVMenu() } }
|
@Published var streamSelection: Stream? { didSet { rebuildTVMenu() } }
|
||||||
|
|
||||||
@Published var queue = [PlayerQueueItem]() { didSet { Defaults[.queue] = queue } }
|
@Published var queue = [PlayerQueueItem]() { didSet { Defaults[.queue] = queue } }
|
||||||
@ -171,10 +171,24 @@ final class PlayerModel: ObservableObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func pauseOnPlayerDismiss() {
|
private func handleAvailableStreamsChange() {
|
||||||
if !playingInPictureInPicture, !presentingPlayer {
|
rebuildTVMenu()
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
|
|
||||||
self.pause()
|
guard stream.isNil else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let stream = preferredStream(availableStreams) else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
streamSelection = stream
|
||||||
|
playStream(
|
||||||
|
stream,
|
||||||
|
of: currentVideo!,
|
||||||
|
preservingTime: !currentItem.playbackTime.isNil
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,21 +54,10 @@ extension PlayerModel {
|
|||||||
preservedTime = currentItem.playbackTime
|
preservedTime = currentItem.playbackTime
|
||||||
restoreLoadedChannel()
|
restoreLoadedChannel()
|
||||||
|
|
||||||
loadAvailableStreams(currentVideo!) { streams in
|
loadAvailableStreams(currentVideo!)
|
||||||
guard let stream = self.preferredStream(streams) else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
self.streamSelection = stream
|
|
||||||
self.playStream(
|
|
||||||
stream,
|
|
||||||
of: self.currentVideo!,
|
|
||||||
preservingTime: !self.currentItem.playbackTime.isNil
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func preferredStream(_ streams: [Stream]) -> Stream? {
|
func preferredStream(_ streams: [Stream]) -> Stream? {
|
||||||
let quality = Defaults[.quality]
|
let quality = Defaults[.quality]
|
||||||
var streams = streams
|
var streams = streams
|
||||||
|
|
||||||
|
@ -15,21 +15,20 @@ extension PlayerModel {
|
|||||||
availableStreams.sorted(by: streamsSorter)
|
availableStreams.sorted(by: streamsSorter)
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadAvailableStreams(
|
func loadAvailableStreams(_ video: Video) {
|
||||||
_ video: Video,
|
|
||||||
completionHandler: @escaping ([Stream]) -> Void = { _ in }
|
|
||||||
) {
|
|
||||||
availableStreams = []
|
availableStreams = []
|
||||||
var instancesWithLoadedStreams = [Instance]()
|
let playerInstance = InstancesModel.forPlayer ?? InstancesModel.all.first
|
||||||
|
|
||||||
InstancesModel.all.forEach { instance in
|
guard !playerInstance.isNil else {
|
||||||
fetchStreams(instance.anonymous.video(video.videoID), instance: instance, video: video) { _ in
|
return
|
||||||
self.completeIfAllInstancesLoaded(
|
}
|
||||||
instance: instance,
|
|
||||||
streams: self.availableStreams,
|
logger.info("loading streams from \(playerInstance!.description)")
|
||||||
instancesWithLoadedStreams: &instancesWithLoadedStreams,
|
|
||||||
completionHandler: completionHandler
|
fetchStreams(playerInstance!.anonymous.video(video.videoID), instance: playerInstance!, video: video) { _ in
|
||||||
)
|
InstancesModel.all.filter { $0 != playerInstance }.forEach { instance in
|
||||||
|
self.logger.info("loading streams from \(instance.description)")
|
||||||
|
self.fetchStreams(instance.anonymous.video(video.videoID), instance: instance, video: video)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -45,25 +44,13 @@ extension PlayerModel {
|
|||||||
.onSuccess { response in
|
.onSuccess { response in
|
||||||
if let video: Video = response.typedContent() {
|
if let video: Video = response.typedContent() {
|
||||||
self.availableStreams += self.streamsWithInstance(instance: instance, streams: video.streams)
|
self.availableStreams += self.streamsWithInstance(instance: instance, streams: video.streams)
|
||||||
|
} else {
|
||||||
|
self.logger.critical("no streams available from \(instance.description)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.onCompletion(onCompletion)
|
.onCompletion(onCompletion)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func completeIfAllInstancesLoaded(
|
|
||||||
instance: Instance,
|
|
||||||
streams: [Stream],
|
|
||||||
instancesWithLoadedStreams: inout [Instance],
|
|
||||||
completionHandler: @escaping ([Stream]) -> Void
|
|
||||||
) {
|
|
||||||
instancesWithLoadedStreams.append(instance)
|
|
||||||
rebuildTVMenu()
|
|
||||||
|
|
||||||
if InstancesModel.all.count == instancesWithLoadedStreams.count {
|
|
||||||
completionHandler(streams.sorted { $0.kind < $1.kind })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func streamsWithInstance(instance: Instance, streams: [Stream]) -> [Stream] {
|
func streamsWithInstance(instance: Instance, streams: [Stream]) -> [Stream] {
|
||||||
streams.map { stream in
|
streams.map { stream in
|
||||||
stream.instance = instance
|
stream.instance = instance
|
||||||
|
Loading…
Reference in New Issue
Block a user