Skip to content

feat(subtitles): prepare and commit external selections transactionally - #829

Merged
superuser404notfound merged 2 commits into
superuser404notfound:mainfrom
orut34iop:codex/feat-external-subtitle-transactions
Oct 21, 2026
Merged

superuser404notfound merged 2 commits into
superuser404notfound:mainfrom
orut34iop:codex/feat-external-subtitle-transactions

Conversation

@orut34iop

Copy link
Copy Markdown
Contributor

An external-subtitle picker currently has to change the active selection before it knows whether a downloaded file can be decoded. Add an opt-in prepare/commit/discard API: prepare a bounded local text sidecar without touching either channel, then synchronously publish the decoded candidate once. A failed preparation leaves the prior selection in place; commit does not reopen the file.

Candidates are bound to an engine, load/stop generation and shared primary/secondary selection intent. A newer selection, clear, removal or successful commit invalidates older candidates. Consumption precedes track-list publication, so a synchronous observer cannot consume the same handle twice. The same registered track can still occupy both channels; no host-specific exclusivity rule is added.

File validation and decoding run on the existing blocking worker. SRT/WebVTT/ASS/SSA input is forced by local extension, with configurable positive file/cue/text limits and no network protocols. Ordinary selection keeps its existing behavior. Prepared registry entries retain their preparation policy for reselection, and ASS uses the existing preserveASSMarkup choice.

Dependency: this branch includes #826 (58cc7eeb45b2f6e3d0bc47f68c1f53285adbfff9) because a prepared secondary ASS selection must publish its script header. After #826 merges, this PR's remaining diff is the transaction API. Other first/second-batch PRs are not included. Existing #239/#267 parsing and style support is reused; downloading and rendering remain host responsibilities.

Tests cover unchanged old selection on failure, owner/discard/duplicate-commit checks, stop/load/selection invalidation, exact registered IDs, shared intent, cancellation, size/cue limits, symlinks, off-main metadata admission, commit after deleting the source file, same-track dual selection and ASS header/style preservation.

Validation on Apple Silicon (Mac17,3), macOS 26.7.1 / Swift 6.4:

  • swift build --build-tests passed; valid Apple Development signing/verification for test executables.
  • Strict cooperative-pool focused run: 19 tests / 2 suites passed, including real stop() invalidation and the documented default-limit contract.
  • Full default-traits suite, serial: 795 XCTest (one pre-existing skip) and 4,633 Swift Testing tests / 635 suites passed.
  • Documentation links and git diff --check passed.

Platform/optional-trait validation remains subject to upstream CI. No physical playback/device acceptance is claimed.

@superuser404notfound
superuser404notfound merged commit f301c79 into superuser404notfound:main Oct 21, 2026
4 checks passed
superuser404notfound pushed a commit that referenced this pull request Oct 21, 2026
…changelog for #829

A prepared commit rebuilt the primary takeover by hand and skipped three things the ordinary
external select does: it left a running OCR worker armed, logged nothing (a commit was invisible
in the diagnostic log), and did not re-assert the native rendition while the picture is off this
device (Sodalite#156). Preparation and commit also refused a session mid-seek as stale, although
`loadGeneration` already catches teardown; `.seeking` now counts as the same session.

The AVERROR_EOF literals read `FFmpegErr.eof`, and the intent counter no longer sits between
`loadGeneration` and its doc comment. The #819 and #827 changelog entries had landed under
7.40.0 and move to Unreleased with the #829 one, now in house style.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WJcXkGQrMiBPixVEFTSBJS
@superuser404notfound

Copy link
Copy Markdown
Owner

Merged in f301c79, thanks @orut34iop. The branch still carried the pre-merge #826 commit, so three small conflicts (CHANGELOG, docs/api.md, one line next to the #824 sessionGeneration guard) were resolved in the merge; full suite green on the merged state (780 XCTest, 4,730 Swift Testing).

Follow-up in cb7c6fb:

  • The primary commit now does what the ordinary external select does: it disarms a running OCR worker, logs an overlay fed by prepared sidecar line (a commit was invisible in the diagnostic log), and re-asserts the native rendition while the picture is off-device (Sodalite#156).
  • .seeking counts as the same session for prepare and commit; loadGeneration already covers teardown, so a commit landing mid-seek no longer comes back stale. New test aSeekInFlightIsStillTheSameSession.
  • FFmpegErr.eof instead of the -541478725 literals, and externalSubtitleIntentGeneration no longer sits between loadGeneration and its doc comment.
  • CHANGELOG entry in house style. It ships with the next engine release.

superuser404notfound pushed a commit that referenced this pull request Oct 21, 2026
Conflicts against #827 (packet store factory), #829 and #348 resolved:
the requested byte budget now reaches makePacketStore's disk branch,
and the AE#348 prepare/serve split stops with .loadFailed like start().
@superuser404notfound

Copy link
Copy Markdown
Owner

Released in 7.45.0 (52802af).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants