Skip to main content

read_toc/
read_toc.rs

1/// Opens the default CD drive and prints the Table of Contents.
2use cd_da_reader::CdReader;
3
4fn main() -> Result<(), Box<dyn std::error::Error>> {
5    let reader = CdReader::open_default()?;
6    let toc = reader.read_toc()?;
7
8    println!("Table of Contents\n");
9
10    println!(
11        "Tracks {}-{} ({} total), lead-out at LBA {}\n",
12        toc.first_track,
13        toc.last_track,
14        toc.tracks.len(),
15        toc.leadout_lba,
16    );
17
18    for track in &toc.tracks {
19        let kind = if track.is_audio { "audio" } else { "data " };
20        let (m, s, f) = track.start_msf;
21        let sectors = next_track_lba(&toc, track.number) - track.start_lba;
22        let duration_secs = sectors as f64 / 75.0;
23        let mins = (duration_secs / 60.0) as u32;
24        let secs = (duration_secs % 60.0) as u32;
25
26        println!(
27            "  #{:>2}  {}  LBA {:>6}  MSF {:02}:{:02}.{:02}  duration: {:02}:{:02}",
28            track.number, kind, track.start_lba, m, s, f, mins, secs,
29        );
30    }
31
32    Ok(())
33}
34
35/// Returns the start LBA of the next track, or the lead-out LBA for the last track.
36fn next_track_lba(toc: &cd_da_reader::Toc, track_no: u8) -> u32 {
37    let idx = toc
38        .tracks
39        .iter()
40        .position(|t| t.number == track_no)
41        .unwrap();
42    if idx + 1 < toc.tracks.len() {
43        toc.tracks[idx + 1].start_lba
44    } else {
45        toc.leadout_lba
46    }
47}