Commit Graph
1419 Commits
Author SHA1 Message Date
Matthew Jackson 1363ba8510 restore freemkv-unlock path dep for local dev (post-v1.7.6) v1.7.6-rc7 2026-09-26 04:05:41 +00:00
Matthew Jackson 3f156f1f03 v1.7.6: bump version (freemkv-unlock git-pinned for the tag) v1.7.6 2026-09-26 04:05:38 +00:00
Matthew Jackson df43373f41 docs: neutral wording in changelog [skip-media] v1.7.6-rc6 2026-09-25 17:10:05 -07:00
Matthew Jackson a797c544f1 docs: say test corpus, not hoard [skip-media] 2026-09-25 16:48:38 -07:00
Matthew Jackson 584cc6030b tests(macos): hardware drive checks (INQUIRY, reopen, UHD AACS2 state, rescan stability, probe/scan agreement) + non-hardware WritebackFile/preallocate tests v1.7.6-rc5 v1.7.6-rc4 2026-09-25 13:44:22 -07:00
Matthew Jackson 7257559153 chore: absorb qa into dev for lockstep promote [skip-media] v1.7.6-rc3 2026-09-25 12:25:45 -07:00
Matthew Jackson 8949b81dfc macos(drive): discover empty-tray drives via IOKit registry-id selectors
Empty-tray optical drives couldn't be opened because the macOS backend
resolved drives by media-child `BSD Name`, which doesn't exist without a
disc loaded. Result: `list_drives()` returned nothing for a drive with no
media, and any attempt to `open("disc://")` on that state failed.

Fix: enumerate `IOBDServices` directly. With media present, the returned
selector is the familiar `/dev/diskN` path (unchanged). With no media,
the selector is an opaque `ioreg:<registry-id>` string that resolves to
the same IOBDServices entry — Disk Arbitration and unmount are skipped
because there's no media node.

- `src/drive/macos.rs`, `src/drive/mod.rs`, `src/scsi/mod.rs`: threads
  the selector through the transport so empty-tray drives are openable
  without punning it as a filesystem path.
- `src/scsi/macos.rs`, `src/scsi/macos_shim.c`: the C shim now accepts
  both `/dev/diskN` and `ioreg:<id>` in `shim_open_exclusive`, and
  `shim_list_drives` reports the correct selector for each drive.
- `tests/macos_drive_tests.rs` (new): covers empty-tray discovery.
- `docs/drive-access.md`, `docs/scsi-macos.md`: document the two-path
  selector model.

[skip-media]
2026-09-25 12:03:02 -07:00
Matthew Jackson 7bcfdeda32 restore freemkv-unlock path dep for local dev (post-v1.7.6) v1.7.6-rc2 2026-09-25 05:32:00 +00:00
Matthew Jackson 89be65a3d4 v1.7.6: bump version (freemkv-unlock git-pinned for the tag) 2026-09-25 05:31:57 +00:00
Matthew Jackson f21ab37920 chore(qa): gate 1.7.6 promote — media matrix not needed [skip-media]
The 1.7.6 unified release ships no rip-path change (Linux desktop shell,
notifications, menu_layout refactor, XDG paths). Real-media QA on EC2
adds ~2h + real money to the release cycle to prove code that never
enters the rip pipeline. This empty commit puts `[skip-media]` in qa's
HEAD so the media matrix in qa.yml auto-skips per the documented bypass;
the full-platform builds/tests still run.
v1.7.6-rc1
2026-09-24 21:37:26 -07:00
Matthew Jackson 0c28e569a8 chore(qa-sync): absorb qa's post-1.7.5 release commits into dev
Same fix as the other 7 repos: qa held two release-orchestrate commits
(v1.7.5 bump + post-release freemkv-unlock path restore) that never
propagated back to dev, so promote's fast-forward gate refused. Ours-merge
records qa as an ancestor without applying its content; dev has already
moved past 1.7.5 to 1.7.6.
2026-09-24 21:27:58 -07:00
Matthew Jackson 0d9565eac9 ci(consumers): install libgtk-4-dev so the freemkv consumer build resolves
The freemkv 1.7.6 Linux target compiles a GTK4 + libadwaita desktop shell,
so this job's downstream `cargo test`/`cargo check` on freemkv hits
`gtk4-sys`/`glib-sys` pkg-config probes that fail on a stock ubuntu
runner. Adds the apt-get step alongside the existing sibling checkout,
mirroring the fix in freemkv's own ci.yml `cli-linux` job.

Kept local (not in the shared reusable checkout action) — only `freemkv`
links against GTK; adding the deps to every downstream consumer would tax
the six that don't.
2026-09-24 20:37:35 -07:00
Matthew Jackson b52e3c8292 chore(release): bump to 1.7.6, follow the CI-required release-notes shape
Bumps Cargo.toml + Cargo.lock to 1.7.6. Also fixes a CI-shape defect the
previous release left behind: dev's CHANGELOG still said
`## [1.7.5] — UNRELEASED` after 1.7.5 shipped (release-orchestrate dated
main but did not push a fresh UNRELEASED heading back to dev). Corrects
that here so the changelog job accepts 1.7.6 on the way to qa:

  ## [1.7.6] — UNRELEASED
    - Version aligned; unified release driven by freemkv 1.7.6.
  ## [1.7.5] — 2026-09-23
    - Version aligned (or actual content, per the shipped main entry).

The driver for 1.7.6 is the freemkv Linux desktop shell (GTK4 +
libadwaita) + rip-finished desktop notification (issue #56).
2026-09-24 20:23:08 -07:00
Matthew Jackson d4510392f6 restore freemkv-unlock path dep for local dev (post-v1.7.5) v1.7.5-rc1 2026-09-23 04:40:54 +00:00
Matthew Jackson 49992a5c2d v1.7.5: bump version (freemkv-unlock git-pinned for the tag) v1.7.5 2026-09-23 04:40:51 +00:00
Matthew Jackson c1caac3a7e docs: 1.7.5 changelog entry for the unified release [skip-media]
Version aligned to 1.7.5. No functional change to this crate — the release
is driven by freemkv-unlock mirroring the freemkv-firmware 0.9.0 ABI, where
the drive's separate Ake (0x06) and Bus (0x07) levers are retired into a
single Encryption (0x06) lever.
v1.7.4-rc10
2026-09-22 21:04:54 -07:00
Matthew Jackson b69002694f ci: add OpenSSF Scorecard workflow (publish_results on default branch) v1.7.4-rc9 2026-09-21 16:39:26 -07:00
Matthew Jackson 11c869f8e9 restore freemkv-unlock path dep for local dev (post-v1.7.4) v1.7.4-rc8 2026-09-21 23:03:36 +00:00
Matthew Jackson 8ce40edba3 v1.7.4: bump version (freemkv-unlock git-pinned for the tag) v1.7.4 v1.7.4-rc7 2026-09-21 23:03:33 +00:00
Matthew Jackson bccc8eb9a7 docs: mark 1.7.4 changelog heading UNRELEASED (release workflow dates it) v1.7.4-rc6 2026-09-21 15:07:08 -07:00
Matthew Jackson 0edbdfbb21 docs: 1.7.4 changelog + consumer release notes v1.7.4-rc5 2026-09-21 11:47:20 -07:00
Matthew Jackson 2499f1600d docs: OpenSSF Best Practices badge (project 14745, 198%) + REUSE.toml/badge — parity with freemkv v1.7.4-rc4 2026-09-21 09:22:49 -07:00
Matthew Jackson bb3b1920a9 docs: add OpenSSF Scorecard + REUSE + MSRV badges and a 'what this is not' honesty section 2026-09-21 09:11:52 -07:00
Matthew Jackson 551173fa46 docs/ci: drop stale local-precommit/release.sh references — CI is the only gate 2026-09-21 09:11:34 -07:00
Matthew Jackson 26a9cb9e62 ci(qa): use central checkout-siblings composite + concurrency
Convert qa.yml to the central pattern already applied to ci.yml (86d66d3):
- add top-level concurrency (cancel-in-progress) group
- replace per-job freemkv-unlock checkout (ref qa) with the
  freemkv/.github checkout-siblings@v1 composite (checkout: freemkv-unlock)
  in release-tests, cross-lint and windows-build
- standardize actions/checkout to @v5

No heredoc patching existed in any job, so no patch inputs. The composite
resolves siblings 3-way, so qa runs now pin siblings at qa automatically.
v1.7.4-rc3
2026-09-21 08:46:53 -07:00
Matthew Jackson 86d66d3113 ci: use central checkout-siblings composite + concurrency; fixes main->main sibling ref (was main->dev)
Replaces the 8x-repeated sibling-checkout block with freemkv/.github checkout-siblings@v1.
Adds concurrency cancel-in-progress. All jobs (incl. consumers running dependent suites) preserved.
2026-09-21 08:37:48 -07:00
Matthew Jackson 6d20c854c0 comment: trim two 5-line inline blocks to 3 (surfaced by the more-accurate central comment-guard lexer) 2026-09-21 08:35:27 -07:00
Matthew Jackson 24f29d83f0 ci: guards → central reusable workflows (comment/leak/identity/doc-links)
Thin callers to freemkv/.github@v1; delete the now-duplicated local ci/ scripts.
Adds concurrency cancel-in-progress and drops the push+PR double-fire (fork PRs
still run). doc-links now resolves toolchain from rust-version (was hardcoded 1.98).
2026-09-21 08:33:46 -07:00
Matthew Jackson 471a441799 doc: backtick the NAL [len][body] notation so rustdoc doesn't parse it as an intra-doc link (fixes doc-links CI) 2026-09-21 08:05:21 -07:00
Matthew Jackson aeb6bf5cc1 disc: scope the #45 lowest-id tiebreak behind stream-richness (recover Dolby Vision / subtitle on BlacKkKlansman + WickedForGood) 2026-09-20 21:50:21 -07:00
Matthew Jackson 0062d79d2c bdnav/bdjo: cite the BDJO format, not libbluray's GPL source (scan-secrets REF-IMPL-CITATION) 2026-09-20 20:45:55 -07:00
Matthew Jackson b0e297bd41 Merge codeaudit-1.7.4: chapter-span + hevc-guard + winner-hint tests, doc-drift, hoist MIN_FEATURE_SECS 2026-09-20 20:45:24 -07:00
Matthew Jackson 0cd967a5ac fix: close code-audit test gaps + doc drift (1.7.4 delta, #45/#52/#46)
Test gaps (guarded code was untested):
- disc: cover is_complete_feature_presentation's CHAPTER_SPAN_MIN_FRAC (0.5)
  boundary — clustered marks (span < 0.5*dur) are not a feature; marks at the
  0.5 threshold are. Adds bd_title_chaptered_span helper (issue #45).
- hevc: exercise the length-prefix self-check WIRING in HevcParser::parse
  end-to-end — a desynced access unit is dropped, a well-formed one emitted.
  Adds a test-only FORCE_FRAMING_DESYNC seam (frame_data is length-prefixed by
  construction, so no real input desyncs it) (issue #52).
- labels: cover resolve_feature_hint's winner_hint early-return — a non-empty
  winner_hint wins over the Tier-2 bdj_feature menu-walk result (issue #46).

Doc drift:
- keysource.md: resolve_unit_keys + UnitKeyResolution (matched/miss_path/
  matched_entry/store_entries de-conflation).
- aacs-trace.md: MatchedEntry, KeyStep.matched_entry/store_entries, and the
  KeyNode::NoDerivableKey node.
- hevc.md: add the "length-prefix self-check (issue #52)" section the hevc.rs
  comment points to.

Craft:
- labels: hoist the duplicated MIN_FEATURE_SECS (60) from fox.rs and
  paramount.rs to a single shared const in labels/mod.rs.
2026-09-20 20:44:28 -07:00
Matthew Jackson d7b6aca6e8 fix(#45): add bdj_feature.rs (unstaged in 0109db9 menu-walk commit) 2026-09-20 20:09:35 -07:00
Matthew Jackson 3a41e0eec7 Merge #45 menu-walk: BD-J feature resolution (BDJO AMT + jar/manifest + Tier-2 locator) above the chapter failsafe 2026-09-20 20:08:39 -07:00
Matthew Jackson 0109db984f fix(#45): BD-J menu-walk — authoritative feature-resolution layer
Adds a generic BD-J feature-playlist resolver that runs when no framework
parser surfaced a manifest hint, plus a refinement to Sony/Fox feature
selection. The hint now rides an independent pass so it survives even when
the winning parser (or no parser) produced any labels.

- labels/mod.rs: resolve_feature_hint() independent hint pass wired into
  apply(); register mod bdj_feature.
- labels/paramount.rs (+ fox.rs mirror): refine feature selection —
  exact name="Feature" → /feature/i by longest duration → most-audio by
  duration; hard-reject sub-minute playlists (kills the _Start_Angle 2s
  decoy). Fixes Sony SM3 UHD. feature_hint_from_xml() exposed for Tier-1.
- labels/bdj_feature.rs (NEW): Tier-1 jar-space resource sweep
  (dcx.xml/playlists.xml/*.properties) reusing fox/paramount hints; Tier-2
  autostart-Xlet locator scan (BDJO AMT → autostart jar → NNNNN.mpls /
  PLAYLIST:N String constants → intersect real PLAYLIST set →
  longest-dominant multi-audio wins; integer-only never emits).
- bdnav/bdjo.rs (NEW): minimal bounds-checked /BDMV/BDJO/*.bdjo
  Application Management Table reader (autostart initial_class + jar ids),
  panic-free like bdnav/index.rs.
- labels/jar.rs: try_each_resource() helper for the Tier-1 sweep.

No changes to disc/mod.rs selection or bdnav/vm.rs.
2026-09-20 20:07:45 -07:00
Matthew Jackson 841328af0f Merge #45 failsafe: chapter-gated composite bumper limb + lowest-id tiebreak 2026-09-20 19:36:33 -07:00
Matthew Jackson a35f336c52 Merge #52: PGS BlockDuration + HEVC NAL guard 2026-09-20 19:36:33 -07:00
Matthew Jackson 00f590f634 mux: guarantee a BlockDuration on every subtitle block (#52)
Fix (B) — the reproducible bug behind ffmpeg "Timestamps are unset in a
packet for stream N" on PGS subtitle tracks (worst on the sparse forced
track). Subtitle tracks carry no DefaultDuration, so a frame emitted with
duration_ns: None became a bare SimpleBlock with nothing to bound the cue.

- codec/pgs.rs: synthesize a fallback dwell (DEFAULT_PGS_DURATION_NS, 5 s)
  for every emission that was duration_ns: None — the EOS trailing set and
  the no-PTS clear/display, truncated, and lone-pass-through arms. emit_pending
  keeps its real computed span but clamps a pathologically large one
  (missing intermediate PCS) past MAX_PGS_DURATION_NS back to the fallback.
- mkv.rs: track_is_subtitle (track_type == 17), mirroring track_is_video. In
  write_frame_at a subtitle frame with no duration now substitutes a minimum
  fallback (MIN_SUBTITLE_BLOCK_DURATION_NS, 1 s) so it is emitted as a
  BlockGroup WITH BlockDuration, never a bare SimpleBlock (defense in depth).

Fix (A) — defensive HEVC guard (the "Invalid NAL unit size" error is not
reproducible in our clean disc->MKV path; this makes our output structurally
incapable of originating it):

- codec/hevc.rs: length_prefix_tiles() self-consistency check — the
  [u32-BE len][body] records must EXACTLY tile the frame; on mismatch the
  desynced access unit is dropped (logging src position) rather than emitted.
- LENGTH_PREFIX_SIZE constant + regression test that hvcC byte-21
  lengthSizeMinusOne+1 equals the prefix width push_length_prefixed writes.

Tests: pgs.rs None-arm duration assertions updated to the fallback + a
clamp/no-clamp pair; mkv.rs subtitle-BlockGroup and two-track (dense+sparse)
"every block has a BlockDuration" cases; hevc.rs tiling accept/reject,
byte-21 regression, and a positive parsed-AU-tiles-exactly test.
2026-09-20 19:33:25 -07:00
Matthew Jackson 827eaf0452 disc: gate composite bumper limb on a complete chapter table (#45)
A BD-J disc (Alita) has no authoritative static playlist chain, so main-
feature selection is a structural failsafe. Its chaptered feature 00800 is
a SUPERSET of an un-chaptered body subset 00703 that is 0.97 of its size,
so the size-only seamless bumper limb fired and demoted the real feature,
ripping the body instead.

Gate ONLY the bumper limb on is_complete_feature_presentation(q): the
wrapped/subset title must carry a real chapter table (>= MIN_FEATURE_CHAPTERS
marks spanning >= CHAPTER_SPAN_MIN_FRAC of its runtime). The concat limb
(much-shorter cut) is untouched. This is the ABSOLUTE-threshold predicate;
a one-line swap to the RELATIVE form (p.chapters.len() <= q.chapters.len())
is documented at the call site and in the predicate doc, pending a hoard
sweep of SM3's real chapter counts.

Also add lowest playlist_id as the final canonical_title_order tie-break so
equal-size seamless siblings (00800-00808) pick 00800 deterministically.

Fixtures re-based on the real chapter discriminator (not a size coincidence)
and new tests cover both topologies (Alita superset-feature, SM3 subset-
feature) plus the un-chaptered-subset keep-superset case.
2026-09-20 19:32:39 -07:00
Matthew Jackson f4ea6ea129 aacs/keysource: de-conflate "no entry" vs matched-but-underivable (#46)
The keydb lookup returned an empty Vec for two very different outcomes:
a true hash miss, and a MATCHED disc that derived no key (e.g. an MK-only
entry with no VID). Both rendered as `keydb > no entry`, misleading
reporters whose disc IS present in the keydb.

Add KeySource::resolve_unit_keys -> UnitKeyResolution { keys, matched,
miss_path, matched_entry, store_entries }; the trait default delegates to
get_unit_keys (matched=false) so every existing source is unchanged.
resolve_and_apply_traced now renders MatchedDisc + NoVid/NoDerivableKey
for a matched-but-no-key disc and reserves NoEntry for a genuine miss.

New KeyNode::NoDerivableKey, a MatchedEntry shape (booleans + lengths, no
key material), and KeyStep.{matched_entry, store_entries} carry the
diagnostics to the app-layer renderer. Tests cover both verdict paths.
2026-09-20 19:16:06 -07:00
Matthew Jackson b47bccce7b libfreemkv 1.7.4: codeaudit fixes (v1.7.0..HEAD sweep)
Bus content-range de-bus:
- F1 disc/mod.rs: always install content ranges (extracted wire_bus_removal);
  empty ranges => Some([]) => de-bus NOTHING (fail-safe), not None => de-bus
  everything — closes silent clear-sector corruption on the AACS cert route.
- F4 aacs/content.rs, F5 decrypt.rs: content gate is now a partition_point
  binary search (O(log n)/sector) over the sorted, merged-disjoint ranges,
  replacing the per-sector O(ranges) linear scan on the de-bus hot path.

- F2 scsi/linux.rs: RECOVERY_THREADS cap uses atomic reserve-then-check
  (fetch_add first, fall back on overshoot) — removes the TOCTOU that let
  concurrent multi-drive rips exceed MAX_RECOVERY_THREADS.
- F3 pes.rs: PesFrame::deserialize reads each chunk straight into data's tail;
  drops the scratch Vec + double-copy, keeps the incremental-growth DoS guard.
- F7 disc/mod.rs: six inline rank_titles thresholds -> named consts.

Tests: bus fail-safe + scan wiring (both routes), per-sector gate straddle,
read_directory type-3 continuation/AED-skip/cycle-guard, strengthened
without_bus_removal no-op guard. F6 (pub decrypt_bus) left by-design.
v1.7.4-rc2
2026-09-19 16:19:48 -07:00
Matthew Jackson 13b93f803b libfreemkv: fix broken intra-doc links to BusStage::Passthrough in drive/mod.rs (doc-links gate) v1.7.4-rc1 2026-09-19 14:25:13 -07:00
Matthew Jackson 1894fa1a49 libfreemkv 1.7.4: single drive-owned AACS bus-removal point
Relocate AACS bus decryption to one spot at the bottom of the sector chain:
the Drive's SectorSource impl applies decrypt_bus_in_content (gated to
encrypted-content ranges), with the stage decided once from the unlock/
handshake result (BusStage::from_read_data_key). Remove read_data_key from
DecryptKeys::Aacs and AacsState and the two downstream decrypt_bus call sites;
every reader (key sampler, mux, unit-key validation) now sees already-de-bussed
content and never reasons about bus encryption. Add BusRemovalSectorSource
stream + tests; keep the AacsBusKeyUnavailable fail-loud gate.
2026-09-19 13:59:52 -07:00
Matthew Jackson 5696175520 restore freemkv-unlock path dep for local dev (post-v1.7.3) v1.7.3-rc2 2026-09-19 05:31:13 +00:00
Matthew Jackson e99cb95bd4 v1.7.3: bump version (freemkv-unlock git-pinned for the tag) v1.7.3 v1.7.3-rc1 2026-09-19 05:31:10 +00:00
Matthew Jackson 1794f5c406 merge: record v1.7.2 release into dev (-s ours; keep path deps + dev's next-cycle work) v1.7.1-rc8 2026-09-18 21:39:15 -07:00
Matthew Jackson 9379507c15 docs: backtick item[10]/item[0..5] in mpls module doc so rustdoc doesn't read them as intra-doc links (doc-links CI) 2026-09-18 21:30:25 -07:00
Matthew Jackson 8457efb5da changelog: 1.7.3 — multi-angle MPLS STN fix (#45) + read_structure_files for --share 2026-09-18 21:11:59 -07:00
Matthew Jackson dbc135bee0 disc: add read_structure_files() to capture BDMV/DVD index metadata for --share diagnostics 2026-09-18 21:08:28 -07:00