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 scsi;
92pub mod sector;
93pub(crate) mod speed;
94pub(crate) mod udf;
95pub mod verify;
96
97// ─── Drive lifecycle ────────────────────────────────────────────────────────
98//
99// `Drive::open(path)` → `wait_ready()` → `init()` → `Disc::scan()`. `Drive`
100// owns the SCSI session; `DriveCapture` etc. let advanced callers introspect
101// drive identity / profile data for sharing.
102pub use drive::capture::{
103    CapturedFeature, DriveCapture, capture_drive_data, mask_bytes, mask_string,
104};
105pub use drive::{Drive, DriveStatus, find_drive, find_drives};
106
107// ─── Errors ─────────────────────────────────────────────────────────────────
108//
109// All fallible APIs return `Result<T, Error>`. `Error` is a typed enum with a
110// numeric `code()`; **no English text in the library** — applications map
111// codes to localized messages. See `error.rs` for the full taxonomy.
112pub use error::{Error, Result};
113
114// ─── Drive events (low-level callbacks) ─────────────────────────────────────
115pub use event::{Event, EventKind};
116pub use identity::DriveId;
117pub use profile::DriveProfile;
118// Platform trait is pub(crate) — callers use Drive, not Platform directly.
119
120// ─── Decryption (AACS / CSS) ────────────────────────────────────────────────
121//
122// `Disc::scan()` resolves keys and stores them on `Disc`; in most flows you
123// don't touch `DecryptKeys` directly — `DiscStream::new(reader, title, keys, …)`
124// accepts whatever `Disc::decrypt_keys()` returned. `decrypt_sectors()` is
125// for callers that operate on raw sector buffers (e.g. ISO patching).
126pub use decrypt::{DecryptKeys, decrypt_sectors};
127
128// ─── Disc structure ─────────────────────────────────────────────────────────
129//
130// `Disc::scan()` produces a fully-populated `Disc` (titles, streams, AACS
131// state). `Disc::identify()` is the fast path — UDF only, no playlist parse,
132// for displaying disc name + format quickly while a full scan runs in the
133// background. The codec / channel / resolution enums are the canonical
134// structured representation; never compare against display strings.
135pub use disc::{
136    AacsState, AudioChannels, AudioStream, Clip, Codec, ColorSpace, ContentFormat, Disc,
137    DiscFormat, DiscId, DiscTitle, Extent, FrameRate, HdrFormat, KeySource, LabelPurpose,
138    LabelQualifier, Resolution, SampleRate, ScanOptions, Stream, SubtitleStream, VideoStream,
139};
140
141// ─── Streams ────────────────────────────────────────────────────────────────
142//
143// All stream types implement `pes::Stream` — read PES frames from a source,
144// write PES frames to a sink. Pick the right type at construction:
145//
146// - `DiscStream` — physical drive or ISO (any `SectorReader`). Always read.
147// - `MkvStream`  — Matroska container. Read on `open()`, write on `create()`.
148// - `M2tsStream` — Blu-ray Transport Stream. Read on `open()`, write on `create()`.
149// - `NetworkStream` — TCP. Read on `listen()`, write on `connect()`.
150// - `NullStream` — write-only black-hole sink. Useful for benchmarks.
151// - `StdioStream` — pipe to/from stdin/stdout. Read or write.
152//
153// Most consumers use the URL resolvers (`input()` / `output()`) which pick
154// the right type from a scheme:// URL. Direct construction is for callers
155// that need to wire custom readers (e.g. autorip's drive-session reuse).
156pub use mux::DiscStream;
157pub use mux::M2tsStream;
158pub use mux::MkvStream;
159pub use mux::NetworkStream;
160pub use mux::NullStream;
161pub use mux::StdioStream;
162pub use mux::{InputOptions, StreamUrl, input, output, parse_url};
163
164// ─── Lower-level surfaces ───────────────────────────────────────────────────
165//
166// `ScsiTransport` is the platform-abstraction trait Drive uses; expose for
167// out-of-tree platform backends. `SectorReader` lets callers feed any byte
168// source (test harness, network image, SMB share) into the disc scan
169// pipeline; `FileSectorReader` is the standard ISO-on-disk implementation.
170pub use scsi::{DriveInfo, ScsiTransport, drive_has_disc, list_drives};
171pub use sector::{FileSectorReader, SectorReader};
172pub use speed::DriveSpeed;
173pub use udf::{UdfFs, read_filesystem};