Stillstand ohne Absicht ist kein Pausieren
`timeControlStatus` meldet zwei verschiedene Dinge als `.paused`: das Anhalten durch den Nutzer und den Fall, dass `play()` gerufen wurde, der Player aber nicht losläuft — weil die Quelle nicht bereit ist oder weil nichts ankommt. Die Engine hat beides als „pausiert" weitergegeben. Sichtbar war das als Player mit Abspieldreieck und Scrubber auf 0:00, während in Wahrheit auf Daten gewartet wurde. Wer dann tippte, drückte auf Play bei etwas, das längst laufen sollte. Die Engine führt jetzt mit, ob überhaupt jemand spielen wollte. Stillstand mit Absicht ist Pause, Stillstand ohne Absicht ist Warten. Dazu die Anzeigeregel, wie gewünscht: **der Kreisel gilt immer**, mit oder ohne eingeblendete Bedienung. Er ist keine Verzierung der Knöpfe, sondern die Auskunft „es kommt gleich weiter" — und die braucht man gerade dann, wenn nichts eingeblendet ist und man vor einem stehenden Bild sitzt. Das Play-Pause-Symbol erscheint dagegen nur mit der übrigen Bedienung, und an seiner Stelle bleibt beim Laden eine Lücke, damit der Kreisel hindurchscheint statt zwei Anzeigen übereinanderzulegen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
baa542690c
commit
ab597ee2f0
@@ -60,6 +60,18 @@ public final class AVPlayerEngine: VideoPlayerEngine {
|
||||
/// `statistics` später „keine Leiter" von „eine Stufe".
|
||||
private var variantBitrates: [Int] = []
|
||||
|
||||
/// Ob überhaupt jemand spielen wollte.
|
||||
///
|
||||
/// **Der Unterschied zwischen „pausiert" und „kommt nicht voran".**
|
||||
/// `timeControlStatus` meldet beides als `.paused`: das Anhalten durch
|
||||
/// den Nutzer und den Fall, dass `play()` gerufen wurde, der Player aber
|
||||
/// nicht losläuft — weil die Quelle noch nicht bereit ist oder weil nichts
|
||||
/// ankommt. Ohne diese Unterscheidung zeigte der Player ein
|
||||
/// Abspielsymbol, als hätte man selbst angehalten, während in Wahrheit
|
||||
/// auf Daten gewartet wurde. Wer dann tippte, drückte auf Play bei etwas,
|
||||
/// das längst laufen sollte.
|
||||
private var wantsToPlay = false
|
||||
|
||||
/// Wie oft es gestockt hat, seit diese Quelle läuft.
|
||||
///
|
||||
/// Aus `playbackStalledNotification` und **nicht** aus dem
|
||||
@@ -81,6 +93,7 @@ public final class AVPlayerEngine: VideoPlayerEngine {
|
||||
// Die Buchführung gehört zur Quelle, nicht zum Motor: ein neuer Titel
|
||||
// fängt bei null an, sonst schleppte die Zahl den vorigen Film mit.
|
||||
variantBitrates = []
|
||||
wantsToPlay = false
|
||||
stallCount = 0
|
||||
accumulatedStall = .zero
|
||||
bufferingSince = nil
|
||||
@@ -170,10 +183,12 @@ public final class AVPlayerEngine: VideoPlayerEngine {
|
||||
}
|
||||
|
||||
public func play() {
|
||||
wantsToPlay = true
|
||||
player.play()
|
||||
}
|
||||
|
||||
public func pause() {
|
||||
wantsToPlay = false
|
||||
player.pause()
|
||||
}
|
||||
|
||||
@@ -342,7 +357,12 @@ public final class AVPlayerEngine: VideoPlayerEngine {
|
||||
guard let self else { return }
|
||||
switch player.timeControlStatus {
|
||||
case .playing: self.state = .playing
|
||||
case .paused: if self.state != .ended { self.state = .paused }
|
||||
case .paused:
|
||||
guard self.state != .ended else { break }
|
||||
// Stillstand mit Absicht ist Pause. Stillstand ohne
|
||||
// Absicht ist Warten — und gehört als solches
|
||||
// gemeldet, nicht als Pause.
|
||||
self.state = self.wantsToPlay ? .buffering : .paused
|
||||
case .waitingToPlayAtSpecifiedRate: self.state = .buffering
|
||||
@unknown default: break
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user