Skip to main content

libfreemkv/
lib.rs

1//! libfreemkv -- Open source optical drive library for 4K UHD / Blu-ray / DVD.
2//!
3//! Handles drive access, disc structure parsing, AACS decryption, and raw
4//! sector reading. 206 bundled drive profiles. No external files needed.
5//!
6//! # Quick Start
7//!
8//! ```no_run
9//! use libfreemkv::{Drive, Disc, ScanOptions, find_drive};
10//!
11//! let mut drive = find_drive().expect("no optical drive found");
12//! drive.wait_ready().unwrap();
13//! drive.init().unwrap();
14//! let disc = Disc::scan(&mut drive, &ScanOptions::default()).unwrap();
15//!
16//! for title in &disc.titles {
17//!     println!("{} -- {} streams", title.duration_display(), title.streams.len());
18//! }
19//!
20//! // Stream via PES pipeline
21//! let opts = libfreemkv::InputOptions::default();
22//! let mut input = libfreemkv::input("disc://", &opts).unwrap();
23//! let title = input.info().clone();
24//! let mut output = libfreemkv::output("mkv://Movie.mkv", &title).unwrap();
25//! while let Ok(Some(frame)) = input.read() {
26//!     output.write(&frame).unwrap();
27//! }
28//! output.finish().unwrap();
29//! ```
30//!
31//! # Architecture
32//!
33//! ```text
34//! Drive           -- open, identify, unlock, read sectors
35//!   ├── ScsiTransport    -- SG_IO (Linux), IOKit (macOS)
36//!   ├── DriveProfile     -- per-drive unlock parameters (206 bundled)
37//!   ├── DriveId          -- INQUIRY + GET_CONFIG identification
38//!   └── Platform
39//!       └── Mt1959       -- MediaTek unlock/read (Renesas planned)
40//!
41//! Disc                   -- scan titles, streams, AACS state
42//!   ├── UDF reader       -- Blu-ray UDF 2.50 with metadata partitions
43//!   ├── MPLS parser      -- playlists → titles + clips + STN streams
44//!   ├── CLPI parser      -- clip info → EP map → sector extents
45//!   ├── JAR parser       -- BD-J audio track labels
46//!   └── AACS             -- encryption: key resolution + content decrypt
47//!       ├── aacs         -- KEYDB, VUK, MKB, unit decrypt
48//!       └── handshake    -- SCSI auth, ECDH, bus key
49//! ```
50//!
51//! # AACS Encryption
52//!
53//! Disc scanning automatically detects and handles AACS encryption.
54//! If a KEYDB.cfg is available (via `ScanOptions` or standard paths),
55//! the library resolves keys and decrypts content transparently.
56//!
57//! Supports AACS 1.0 (Blu-ray) and AACS 2.0 (UHD, with fallback).
58//!
59//! # Error Codes
60//!
61//! All errors are structured with numeric codes. No user-facing English
62//! text -- applications format their own messages.
63//!
64//! | Range | Category |
65//! |-------|----------|
66//! | E1xxx | Device errors (not found, permission) |
67//! | E2xxx | Profile errors (unsupported drive) |
68//! | E3xxx | Unlock errors (failed, signature) |
69//! | E4xxx | SCSI errors (command failed, timeout) |
70//! | E5xxx | I/O errors |
71//! | E6xxx | Disc format errors |
72//! | E7xxx | AACS errors |
73
74pub mod aacs;
75pub(crate) mod clpi;
76pub mod css;
77pub mod decrypt;
78pub mod disc;
79pub mod drive;
80pub mod error;
81pub mod event;
82pub(crate) mod identity;
83pub(crate) mod ifo;
84pub mod keydb;
85pub(crate) mod labels;
86pub(crate) mod mpls;
87pub mod mux;
88pub mod pes;
89pub(crate) mod platform;
90pub mod profile;
91pub mod progress;
92pub mod scsi;
93pub mod sector;
94pub(crate) mod speed;
95pub(crate) mod udf;
96pub mod verify;
97
98// ─── Drive lifecycle ────────────────────────────────────────────────────────
99//
100// `Drive::open(path)` → `wait_ready()` → `init()` → `Disc::scan()`. `Drive`
101// owns the SCSI session; `DriveCapture` etc. let advanced callers introspect
102// drive identity / profile data for sharing.
103pub use drive::capture::{
104    CapturedFeature, DriveCapture, capture_drive_data, mask_bytes, mask_string,
105};
106pub use drive::{Drive, DriveStatus, find_drive};
107
108// ─── Errors ─────────────────────────────────────────────────────────────────
109//
110// All fallible APIs return `Result<T, Error>`. `Error` is a typed enum with a
111// numeric `code()`; **no English text in the library** — applications map
112// codes to localized messages. See `error.rs` for the full taxonomy.
113pub use error::{Error, Result};
114
115// ─── Drive events (low-level callbacks) ─────────────────────────────────────
116pub use event::{Event, EventKind};
117pub use identity::DriveId;
118pub use profile::DriveProfile;
119// Platform trait is pub(crate) — callers use Drive, not Platform directly.
120
121// ─── Decryption (AACS / CSS) ────────────────────────────────────────────────
122//
123// `Disc::scan()` resolves keys and stores them on `Disc`; in most flows you
124// don't touch `DecryptKeys` directly — `DiscStream::new(reader, title, keys, …)`
125// accepts whatever `Disc::decrypt_keys()` returned. `decrypt_sectors()` is
126// for callers that operate on raw sector buffers (e.g. ISO patching).
127pub use decrypt::{DecryptKeys, decrypt_sectors};
128
129// ─── Disc structure ─────────────────────────────────────────────────────────
130//
131// `Disc::scan()` produces a fully-populated `Disc` (titles, streams, AACS
132// state). `Disc::identify()` is the fast path — UDF only, no playlist parse,
133// for displaying disc name + format quickly while a full scan runs in the
134// background. The codec / channel / resolution enums are the canonical
135// structured representation; never compare against display strings.
136pub use disc::{
137    AacsState, AudioChannels, AudioStream, Clip, Codec, ColorSpace, ContentFormat,
138    DamageSeverity, Disc, DiscFormat, DiscId, DiscTitle, Extent, FrameRate, HdrFormat,
139    KeySource, LabelPurpose, LabelQualifier, Resolution, SampleRate, ScanOptions, Stream,
140    SubtitleStream, VideoStream, classify_damage,
141};
142
143// ─── Streams ────────────────────────────────────────────────────────────────
144//
145// All stream types implement `pes::Stream` — read PES frames from a source,
146// write PES frames to a sink. Pick the right type at construction:
147//
148// - `DiscStream` — physical drive or ISO (any `SectorReader`). Always read.
149// - `MkvStream`  — Matroska container. Read on `open()`, write on `create()`.
150// - `M2tsStream` — Blu-ray Transport Stream. Read on `open()`, write on `create()`.
151// - `NetworkStream` — TCP. Read on `listen()`, write on `connect()`.
152// - `NullStream` — write-only black-hole sink. Useful for benchmarks.
153// - `StdioStream` — pipe to/from stdin/stdout. Read or write.
154//
155// Most consumers use the URL resolvers (`input()` / `output()`) which pick
156// the right type from a scheme:// URL. Direct construction is for callers
157// that need to wire custom readers (e.g. autorip's drive-session reuse).
158pub use mux::DiscStream;
159pub use mux::M2tsStream;
160pub use mux::MkvStream;
161pub use mux::NetworkStream;
162pub use mux::NullStream;
163pub use mux::StdioStream;
164pub use mux::{InputOptions, StreamUrl, input, output, parse_url};
165
166// ─── Lower-level surfaces ───────────────────────────────────────────────────
167//
168// `ScsiTransport` is the platform-abstraction trait Drive uses; expose for
169// out-of-tree platform backends. `SectorReader` lets callers feed any byte
170// source (test harness, network image, SMB share) into the disc scan
171// pipeline; `FileSectorReader` is the standard ISO-on-disk implementation.
172pub use scsi::{DriveInfo, ScsiTransport, drive_has_disc, list_drives};
173pub use sector::{FileSectorReader, SectorReader};
174pub use speed::DriveSpeed;
175pub use udf::{UdfFs, read_filesystem};