Die Medientasten bedienen jetzt Flixy
Die App hat sich beim System nie als „läuft gerade" gemeldet — das MediaPlayer-Framework kam im ganzen Projekt nicht vor. macOS schickt die Medientasten aber genau dorthin: an das Programm, das sich gemeldet hat. Meldet sich keines, gewinnt irgendein anderes, und man pausiert etwas, das man gar nicht sieht. `NowPlaying` meldet Titel, Untertitel, Länge, Stelle und Tempo und nimmt entgegen: Abspielen, Anhalten, Umschalten, Vor- und Zurückspulen mit den **eingestellten** Weiten, und das Ziehen am Balken. Damit tun Medientasten, Kontrollzentrum, Sperrbildschirm und Kopfhörerknöpfe dasselbe wie die Knöpfe im Player — es ist eine Sache, nicht vier. Eine Anmeldung für die ganze App, nicht eine je Player: das System kennt ohnehin nur einen laufenden Titel. Abgemeldet wird nur vom Player, der auch angemeldet ist — sonst räumte einer, der spät zu Ende geht, dem längst gestarteten nächsten die Tasten weg. Die Rückrufe springen auf den Hauptakteur, statt ihn anzunehmen. Dass sie dort ankommen, ist nirgends zugesagt, und dieselbe Annahme hat die App im VLC-Engine schon einmal zum Absturz gebracht. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
fc812f5a25
commit
5d09836686
@@ -56,6 +56,15 @@ final class PlayerModel {
|
||||
private(set) var isOffline = false
|
||||
/// Ob ein laufender Sender abgespielt wird.
|
||||
private(set) var isLive = false
|
||||
|
||||
/// Die Spulweiten, wie sie eingestellt sind.
|
||||
///
|
||||
/// Nach außen sichtbar, weil die Systembedienung — Kontrollzentrum,
|
||||
/// Sperrbildschirm, Medientasten — dieselben Zahlen anbieten soll wie die
|
||||
/// Knöpfe im Player. Zwei Weiten, die auseinanderlaufen, sind schlimmer
|
||||
/// als eine, die nicht jedem gefällt.
|
||||
var rewindSeconds: Int { settings.rewindSeconds }
|
||||
var forwardSeconds: Int { settings.forwardSeconds }
|
||||
/// Die im Player gewählte Stufe. `automatic` folgt den Einstellungen.
|
||||
private(set) var quality: PlayerQuality = .automatic
|
||||
/// Ob gerade auf eine andere Stufe umgestellt wird.
|
||||
@@ -202,6 +211,10 @@ final class PlayerModel {
|
||||
func start() async {
|
||||
diagnostics.begin(title: request.title, connection: connectionDescription)
|
||||
|
||||
// Beim System anmelden, bevor das erste Bild kommt: ab hier gehören
|
||||
// die Medientasten diesem Titel und nicht mehr dem, was vorher lief.
|
||||
NowPlaying.shared.takeOver(self)
|
||||
|
||||
// Die lokale Datei hat immer Vorrang. Sie ist schneller, kostet kein
|
||||
// Datenvolumen und funktioniert auch dann, wenn der Server gerade
|
||||
// nicht erreichbar ist — der eigentliche Sinn des Herunterladens.
|
||||
@@ -583,6 +596,7 @@ final class PlayerModel {
|
||||
isPlaying = false
|
||||
isBuffering = false
|
||||
bufferWatchdog?.cancel()
|
||||
NowPlaying.shared.release(for: self)
|
||||
}
|
||||
|
||||
/// Meldet dem Server, dass Schluss ist. Darf dauern.
|
||||
@@ -767,6 +781,7 @@ final class PlayerModel {
|
||||
isPlaying = state == .playing
|
||||
isBuffering = state == .buffering || state == .loading
|
||||
watchBuffering(isBuffering)
|
||||
NowPlaying.shared.update(from: self)
|
||||
// Jeder Zustandswechsel mit Zeitstempel. Erst daran ist
|
||||
// abzulesen, ob die Engine hängt oder die Leitung.
|
||||
diagnostics.note("Zustand: \(state)")
|
||||
@@ -783,6 +798,9 @@ final class PlayerModel {
|
||||
}
|
||||
case .timeChanged(let time):
|
||||
currentTime = time
|
||||
// Gedrosselt in `NowPlaying`: zwischen zwei Meldungen
|
||||
// zählt das System selbst weiter, es kennt das Tempo.
|
||||
NowPlaying.shared.update(from: self)
|
||||
// Angekommen: ab hier zeigt das Bild wieder die Stelle,
|
||||
// an der man war.
|
||||
if let target = resumeTarget, time + .seconds(2) >= target {
|
||||
@@ -791,6 +809,7 @@ final class PlayerModel {
|
||||
updateActiveMarker()
|
||||
case .durationResolved(let value):
|
||||
duration = value
|
||||
NowPlaying.shared.update(from: self)
|
||||
case .reachedEnd:
|
||||
isPlaying = false
|
||||
hasReachedEnd = true
|
||||
|
||||
Reference in New Issue
Block a user