feat: retain streaming media and add opt-in automatic quality
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
import AppKit
|
||||
|
||||
@MainActor
|
||||
private final class FixedQualityClock { var now = 1000.0 }
|
||||
|
||||
@main
|
||||
@MainActor
|
||||
struct AutomaticQualityPlaybackChecks {
|
||||
static func require(_ condition: @autoclosure () -> Bool, _ message: String) {
|
||||
if !condition() {
|
||||
FileHandle.standardError.write(Data(("FAIL: " + message + "\n").utf8))
|
||||
exit(1)
|
||||
}
|
||||
}
|
||||
// Only the infrastructure watchdog uses elapsed time. Adaptation uses an injected clock;
|
||||
// playback readiness and network stalls are observable media events, not sleeps.
|
||||
static func until(_ model: PlayerModel, _ message: String, _ condition: () -> Bool) {
|
||||
let deadline = ContinuousClock.now.advanced(by: .seconds(20))
|
||||
while !condition(), ContinuousClock.now < deadline {
|
||||
RunLoop.main.run(until: Date(timeIntervalSinceNow: 0.01))
|
||||
}
|
||||
require(condition(), message + " (height=\(model.youtubeHeight ?? 0), status=\(model.state.status), error=\(model.errorText ?? "none"))")
|
||||
}
|
||||
static func polled(_ model: PlayerModel) {
|
||||
let revision = model.state.revision
|
||||
until(model, "native model processes a fresh playback snapshot") { model.state.revision != revision }
|
||||
}
|
||||
static func main() {
|
||||
_ = NSApplication.shared
|
||||
NSApp.setActivationPolicy(.prohibited)
|
||||
let suite = "terebi.automatic-quality-playback-check.\(UUID().uuidString)"
|
||||
let defaults = UserDefaults(suiteName: suite)!
|
||||
defer { defaults.removePersistentDomain(forName: suite) }
|
||||
let clock = FixedQualityClock()
|
||||
let model = PlayerModel(defaults: defaults, qualityClock: { clock.now })
|
||||
defer { model.shutdown() }
|
||||
model.setVolume(0)
|
||||
require(!model.automaticYouTubeQuality, "automatic quality is opt-in")
|
||||
model.openYouTube("https://www.youtube.com/watch?v=aqz-KE-bpKQ")
|
||||
until(model, "default selects real 1080p and runs out of the gated network prefix") {
|
||||
model.youtubeHeight == 1080 && model.canTogglePlayback &&
|
||||
model.state.status == PLAYER_PLAYING && model.state.position > 0.5 && model.state.buffering
|
||||
}
|
||||
clock.now = 2000
|
||||
polled(model)
|
||||
require(model.youtubeHeight == 1080 && !model.resolvingYouTube,
|
||||
"disabled automatic quality leaves a stalled manual/default stream alone")
|
||||
model.setAutomaticYouTubeQuality(true)
|
||||
polled(model)
|
||||
let position = model.state.position
|
||||
clock.now = 2003
|
||||
until(model, "persistent stall automatically reopens actual 720p media") {
|
||||
model.youtubeHeight == 720 && model.canTogglePlayback && model.state.status == PLAYER_PLAYING &&
|
||||
!model.state.seek_pending && (model.bufferedRange.map { $0.upperBound - model.state.position >= 20 } ?? false)
|
||||
}
|
||||
require(model.state.position >= position && model.state.position < position + 3,
|
||||
"automatic quality reopening preserves current playback progress")
|
||||
polled(model)
|
||||
clock.now = 2063
|
||||
until(model, "sustained health automatically restores actual 1080p media") {
|
||||
model.youtubeHeight == 1080 && model.canTogglePlayback && model.state.status == PLAYER_PLAYING && !model.state.seek_pending
|
||||
}
|
||||
model.setYouTubeQuality(model.youtubeHeight)
|
||||
require(!model.automaticYouTubeQuality && !model.isBusy && model.state.status == PLAYER_PLAYING,
|
||||
"reselecting the current manual resolution disables auto without disrupting playback")
|
||||
model.setAutomaticYouTubeQuality(true)
|
||||
let reopened = PlayerModel(defaults: defaults, qualityClock: { clock.now })
|
||||
require(reopened.automaticYouTubeQuality, "explicit opt-in survives player restart")
|
||||
reopened.shutdown()
|
||||
model.setYouTubeQuality(nil)
|
||||
require(!model.automaticYouTubeQuality && model.youtubeQuality == nil,
|
||||
"default quality is also a manual override")
|
||||
let manual = PlayerModel(defaults: defaults, qualityClock: { clock.now })
|
||||
require(!manual.automaticYouTubeQuality, "manual override persists after restart")
|
||||
manual.shutdown()
|
||||
model.closeFile()
|
||||
print("PASS native adaptive playback: default-off/stalled downshift/healthy upshift/progress preservation/current+default manual override/opt-in persistence")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user