refactor: concentrate playback transition ownership

This commit is contained in:
2026-10-11 23:20:26 +02:00
parent cc99a2a4f8
commit 8eba97579f
6 changed files with 559 additions and 238 deletions
+71 -2
View File
@@ -63,13 +63,24 @@ struct SystemPlaybackChecks {
require(center.nowPlayingInfo?[MPNowPlayingInfoPropertyPlaybackRate] as? Double == 0,
"paused system timeline does not extrapolate")
let playbackKey = try! KeyChord("space")
let oppositeIntentRevision = model.state.revision
require(model.handleKey(playbackKey) && model.effectivePlaying,
"play binding records intent before backend acknowledgement")
require(model.handleKey(playbackKey) && !model.effectivePlaying,
"same binding resolves pause against pending play intent")
require(model.handleKey(playbackKey, isRepeat: true) && !model.effectivePlaying,
"held paired shortcut is consumed without oscillating")
until("rapid opposite intents settle to paused") { model.state.status == PLAYER_PAUSED }
until("rapid opposite intents acknowledge play before the final pause") {
model.state.revision != oppositeIntentRevision && model.state.status == PLAYER_PLAYING
}
let playingRevision = model.state.revision
until("rapid opposite intents settle to an acknowledged native pause") {
model.state.revision != playingRevision && model.state.status == PLAYER_PAUSED &&
!model.effectivePlaying && center.playbackState == .paused
}
require(center.nowPlayingInfo?[MPNowPlayingInfoPropertyPlaybackRate] as? Double == 0,
"latest pause intent stops the system timeline after native acknowledgement")
let settledPosition = model.state.position
require(!model.perform(.pause) && !model.effectivePlaying,
"explicit pause cannot resume an already paused player")
@@ -87,7 +98,7 @@ struct SystemPlaybackChecks {
require(model.seekRelative(1), "relative seek accepted")
until("paused seek acknowledged") {
model.state.status == PLAYER_PAUSED && !model.state.seek_pending &&
abs(model.state.position - pausedPosition - 1) < 0.05
abs(model.state.position - settledPosition - 1) < 0.05
}
require(model.seekRelative(-100), "backward boundary seek accepted")
until("backward seek clamps at start") { !model.state.seek_pending && model.state.position == 0 }
@@ -114,6 +125,64 @@ struct SystemPlaybackChecks {
"accepted close releases system playback immediately")
require(!commands.togglePlayPauseCommand.isEnabled && !commands.nextTrackCommand.isEnabled,
"closed source cannot receive system playback or seek commands")
let localURL = directory.appendingPathComponent("av.mp4")
let progress = PlaybackProgress(defaults: defaults)
let savedPosition = seekableState.duration / 2
progress.save(savedPosition, for: localURL)
var openRevision = model.state.revision
model.open(localURL)
until("local saved position is restored before native autoplay") {
guard model.state.revision != openRevision else { return false }
if model.state.status == PLAYER_PLAYING && !model.state.seek_pending {
require(model.state.position >= savedPosition,
"local autoplay never acknowledges playback before the saved position")
return model.state.position < savedPosition + 0.5
}
require(progress.position(for: localURL) == savedPosition,
"pre-restoration snapshots cannot overwrite saved history")
return false
}
require(model.setPlayback(playing: false), "restored local playback can pause")
until("restored local pause acknowledged") { model.state.status == PLAYER_PAUSED && !model.state.seek_pending }
let restoredPosition = model.state.position
model.closeFile()
require(progress.position(for: localURL) == restoredPosition,
"close persists acknowledged restored position")
openRevision = model.state.revision
model.open(localURL)
until("close and reopen resumes the persisted native position") {
guard model.state.revision != openRevision && model.state.status == PLAYER_PLAYING &&
!model.state.seek_pending else { return false }
require(model.state.position >= restoredPosition,
"reopened local autoplay starts at acknowledged persisted progress")
return model.state.position < restoredPosition + 0.5
}
model.closeFile()
let invalidPosition = seekableState.duration + 1
progress.save(invalidPosition, for: localURL)
openRevision = model.state.revision
model.open(localURL)
until("duration-exceeded bookmark is discarded and native playback advances") {
model.state.revision != openRevision && model.state.status == PLAYER_PLAYING &&
!model.state.seek_pending && model.state.position > 0.1 && model.state.position < savedPosition
}
require((progress.position(for: localURL) ?? 0) < seekableState.duration,
"duration-exceeded bookmark is removed from exposed history")
model.closeFile()
let replacementPosition = progress.position(for: localURL)!
require(replacementPosition > 0 && replacementPosition < savedPosition,
"close replaces invalid history with acknowledged playback progress")
openRevision = model.state.revision
model.open(localURL)
until("reopening no longer repeats a duration-exceeded restoration") {
guard model.state.revision != openRevision && model.state.status == PLAYER_PLAYING &&
!model.state.seek_pending else { return false }
require(model.state.position >= replacementPosition,
"replacement bookmark restores before reopened autoplay")
return model.state.position < replacementPosition + 0.5
}
model.closeFile()
model.open(directory.appendingPathComponent("hdr.mkv"))
until("decode error acknowledged") { model.state.status == PLAYER_ERROR && !model.isBusy }
require(center.nowPlayingInfo == nil && !commands.playCommand.isEnabled,