src/labels/ with 4 parsers tried in order: 1. language_streams.txt (Warner CTRM CSV) 2. menu_base.prop (Warner CTRM properties) 3. streamproperties.xml + playbackconfig.xml (Criterion XML) 4. bluray_project.bin (Pixelogic binary tokens) Disc::scan() calls labels::extract() → apply_disc_labels(). If no disc files found, streams keep MPLS data as-is. No JAR fallback — disc files or nothing. Covers 4/8 discs with JARs (Dunkirk UHD, V for Vendetta BD, Being There, Barbie). Remaining 3 (Civil War, Dune, V for Vendetta UHD) have no disc config files.
89 lines
2.4 KiB
Rust
89 lines
2.4 KiB
Rust
//! Stream label extraction from BD-J disc files.
|
|
//!
|
|
//! Searches the disc UDF filesystem for known config files that contain
|
|
//! stream labels (language, purpose, codec, forced flags). Four formats
|
|
//! supported, tried in order:
|
|
//!
|
|
//! 1. `language_streams.txt` — Warner CTRM CSV format
|
|
//! 2. `menu_base.prop` — Warner CTRM properties format
|
|
//! 3. `streamproperties.xml` + `playbackconfig.xml` — Criterion XML format
|
|
//! 4. `bluray_project.bin` — Pixelogic binary format
|
|
|
|
mod language_streams;
|
|
mod menu_base;
|
|
mod stream_properties;
|
|
mod bluray_project;
|
|
|
|
use crate::drive::DriveSession;
|
|
use crate::udf::UdfFs;
|
|
|
|
/// A stream label extracted from disc config files.
|
|
#[derive(Debug, Clone)]
|
|
pub struct StreamLabel {
|
|
/// STN index (1-based)
|
|
pub stream_number: u16,
|
|
/// Audio or Subtitle
|
|
pub stream_type: StreamLabelType,
|
|
/// ISO 639-2 language code
|
|
pub language: String,
|
|
/// Display name (e.g. "AudioEnglishDolby", "English Dolby Atmos")
|
|
pub name: String,
|
|
/// Stream purpose
|
|
pub purpose: LabelPurpose,
|
|
/// Additional qualifier
|
|
pub qualifier: LabelQualifier,
|
|
/// Codec hint from config (e.g. "MLP", "AC3", "atmos")
|
|
pub codec_hint: String,
|
|
/// Regional variant (e.g. "US", "UK", "CF", "CS")
|
|
pub region: String,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
|
pub enum StreamLabelType {
|
|
Audio,
|
|
Subtitle,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
|
pub enum LabelPurpose {
|
|
/// Normal dialogue track
|
|
Normal,
|
|
/// Audio commentary
|
|
Commentary,
|
|
/// Descriptive audio (visually impaired)
|
|
Descriptive,
|
|
/// Music score only
|
|
Score,
|
|
/// In-movie experience
|
|
Ime,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
|
pub enum LabelQualifier {
|
|
None,
|
|
/// Subtitles for deaf and hard of hearing
|
|
Sdh,
|
|
/// Descriptive service
|
|
DescriptiveService,
|
|
/// Forced/narrative subtitle
|
|
Forced,
|
|
}
|
|
|
|
/// Try all parsers in order, return first successful result.
|
|
pub fn extract(session: &mut DriveSession, udf: &UdfFs) -> Vec<StreamLabel> {
|
|
// Try each format in order
|
|
if let Some(labels) = language_streams::parse(session, udf) {
|
|
return labels;
|
|
}
|
|
if let Some(labels) = menu_base::parse(session, udf) {
|
|
return labels;
|
|
}
|
|
if let Some(labels) = stream_properties::parse(session, udf) {
|
|
return labels;
|
|
}
|
|
if let Some(labels) = bluray_project::parse(session, udf) {
|
|
return labels;
|
|
}
|
|
Vec::new()
|
|
}
|