Add disc title, format, streams to Disc::scan() — move logic from CLI to lib

- Disc.volume_id: UDF Volume ID from PVD (always present)
- Disc.meta_title: from META/DL/bdmt_eng.xml (falls back to other languages)
- Disc.format: UHD/BluRay/DVD detected from video codec
- Disc.capacity_bytes, Disc.layers
- Disc.jar_labels: extracted from BDMV/JAR
- Fixed MPLS STN parsing: 16-byte header (was 8), proper stream entry offsets
- Streams now include: HDR, color space, Dolby Vision EL, secondary audio/video
- parse_dstring() for UDF d-string fields
- wait_ready() polls TEST UNIT READY before unlock

Tested on 12 disc captures — all return correct titles, streams, format.
This commit is contained in:
MattJackson
2026-04-07 15:36:05 -07:00
parent 100e3b8126
commit dec258532f
5 changed files with 343 additions and 162 deletions
+19
View File
@@ -36,6 +36,7 @@ impl DriveSession {
/// for sector reads, disc scanning, and content extraction.
pub fn open(device: &Path) -> Result<Self> {
let mut session = Self::open_no_unlock(device)?;
session.wait_ready()?;
let _ = session.unlock(); // silently ignore — unencrypted discs don't need it
Ok(session)
}
@@ -85,6 +86,24 @@ impl DriveSession {
})
}
/// Wait for the drive to become ready (disc spun up).
/// Polls TEST UNIT READY up to 30 seconds.
pub fn wait_ready(&mut self) -> Result<()> {
let tur = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; // TEST UNIT READY
for _ in 0..60 {
let mut buf = [0u8; 0];
if self.scsi.as_mut().execute(
&tur, crate::scsi::DataDirection::None, &mut buf, 5000
).is_ok() {
return Ok(());
}
std::thread::sleep(std::time::Duration::from_millis(500));
}
Err(Error::DeviceNotFound {
path: format!("{}: drive not ready after 30s", self.device_path),
})
}
/// Device path this session was opened on.
pub fn device_path(&self) -> &str {
&self.device_path