Three new modules in the labels platform, all layered so framework- specific parsers (paramount, criterion, pixelogic, ctrm, dbp, deluxe) always take precedence over the universal layer. **mpls_universal.rs** (~600 LOC, 9 tests): consumes the already-parsed `crate::mpls::Playlist::streams` and emits StreamLabel entries with language + codec_hint per stream. Returns `Confidence::Low` (new variant) so framework parsers' Medium/High always win the registry's max-by-confidence tiebreaker; MPLS only gets picked when no framework matched. Closes the "no BD-J disc" case (HDMV-only navigation) that previously produced zero labels — language and base codec are spec-mandated in MPLS STN tables on every Blu-ray ever made. **bdmt.rs** (~350 LOC, 10 tests): reads `/BDMV/META/DL/bdmt_<lang>.xml` files into a new `DiscMetadata` struct (localized title names per ISO 639-2 code, descriptions, optional box-set position). Runs independently of the parser registry — disc-level metadata, not per-stream, so the registry's confidence selection doesn't apply. Surfaced on a new `LabelAnalysis::disc_metadata` field. **png_filenames.rs** (noop stub): pattern documentation + dead-code detect/parse for future reactivation. Deferred because MPLS already delivers per-stream lang/codec/type on every disc; PNG filename language tokens only add studio variant disambiguation (FRC vs FRP, LAS vs CSP) — niche enough to not justify the implementation cost right now. Wiring changes in `mod.rs`: - New `Confidence::Low` variant (PartialOrd places it below Medium/High) - New `ParseResult::low()` constructor - `mpls_universal` appended last to `PARSERS` registry - `LabelAnalysis::disc_metadata: Option<DiscMetadata>` field - `analyze()` runs `bdmt::parse` independently and surfaces result - `pub use bdmt::DiscMetadata` re-export so the labels-analyze tool in freemkv-tools can construct the JSON payload Total: 151 of 151 labels tests passing (was 132 — added 19 new).
73 lines
3.3 KiB
Rust
73 lines
3.3 KiB
Rust
//! PNG-filename language token parser — stubbed (noop) pending need.
|
|
//!
|
|
//! ## What this would do
|
|
//!
|
|
//! Some discs encode per-language menu localization as pre-rendered PNG
|
|
//! menu buttons, one per language, with the language token embedded in
|
|
//! the filename. Examples observed in the 2026-05-10 corpus:
|
|
//!
|
|
//! - **disc-01 (The Amateur)** — `<region>_<lang>_<context>_<format>.png`
|
|
//! Region prefix: `USA` / `UK` / `JPN` / etc.
|
|
//! Lang tokens (3-char, uppercase): `ENG`, `FRC`, `FRP`, `DEU`, `DUT`,
|
|
//! `ITA`, `JPN`, `LAS`, `CSP`, `POL`, `CZE` (11 languages)
|
|
//!
|
|
//! - **disc-09 (Dune orig)** — `<title>_<variant>_<lang>_Composite<N>.png`
|
|
//! Lang tokens (3-char, mixed-case): `Eng`, `Ger` (2 languages)
|
|
//!
|
|
//! ## Why stubbed
|
|
//!
|
|
//! MPLS already gives per-stream `language` + `coding_type` + stream-type
|
|
//! (audio vs subtitle) on every disc. For the 2 unknown-framework discs
|
|
//! that PNG filenames would close (disc-01, disc-09), MPLS will produce
|
|
//! a strict superset of what filenames could give us, because MPLS knows
|
|
//! per-stream attribution while filenames only know "the disc offers
|
|
//! these N language buttons."
|
|
//!
|
|
//! The **only** thing PNG filenames give us that MPLS doesn't is **studio
|
|
//! variant disambiguation**:
|
|
//! - `FRC` (French Canadian) vs `FRP` (French Parisian) — MPLS just says `fra`
|
|
//! - `LAS` (Latin American Spanish) vs `CSP` (Castilian Spanish) — MPLS just says `spa`
|
|
//!
|
|
//! That's niche enough that it doesn't justify implementing right now.
|
|
//! Reactivate this parser only when:
|
|
//! 1. We hit a disc where MPLS is malformed/empty AND PNG filenames are
|
|
//! the only language hint, OR
|
|
//! 2. A downstream consumer needs the studio variant suffix for output
|
|
//! naming (e.g. `Title (French Canadian).mkv` vs `Title (French).mkv`).
|
|
//!
|
|
//! ## When reactivating
|
|
//!
|
|
//! Implement `parse` to:
|
|
//! 1. Iterate top-level PNG paths in `/BDMV/JAR/` (and `<id>/` subdirs).
|
|
//! 2. Tokenize each filename on `_` / `-` / `.`
|
|
//! 3. Match each token against an alias table:
|
|
//! - ISO 639-1 / 639-2 standard codes
|
|
//! - Studio variants: `FRC`/`FRP` → `fra-CA`/`fra-FR`,
|
|
//! `LAS`/`CSP` → `spa-419`/`spa-ES`,
|
|
//! mixed-case shortforms `Eng`/`Ger`/`Fra`/`Spa`/`Jpn` → ISO 639-2
|
|
//! - Country prefix filter: drop `USA`/`UK`/`JPN`/`AUS`/`GER`/`FR` when
|
|
//! they appear in position 0 (those are region markers, not langs).
|
|
//! 4. Deduplicate. Confidence stays `Low` because we still don't know
|
|
//! per-stream codec or audio/subtitle attribution.
|
|
//!
|
|
//! Wire as ENRICHMENT after MPLS in `mod.rs::analyze`, not as a primary
|
|
//! parser: PNG filenames upgrade `lang=fra` to `lang=fra-CA` when both
|
|
//! sources agree on the disc; they should never overwrite MPLS data.
|
|
|
|
use super::ParseResult;
|
|
use crate::sector::SectorReader;
|
|
use crate::udf::UdfFs;
|
|
|
|
/// Stub: returns false so the dispatcher never calls `parse`. Reactivate
|
|
/// by checking for the patterns described in the module docs.
|
|
#[allow(dead_code)] // module-level noop, not wired into PARSERS until needed
|
|
pub fn detect(_udf: &UdfFs) -> bool {
|
|
false
|
|
}
|
|
|
|
/// Stub: returns None. See module docs for the implementation sketch.
|
|
#[allow(dead_code)] // module-level noop, not wired into PARSERS until needed
|
|
pub fn parse(_reader: &mut dyn SectorReader, _udf: &UdfFs) -> Option<ParseResult> {
|
|
None
|
|
}
|