#!/usr/bin/env python3
"""cd_toc2.py —— 用已验证的 SG_IO 结构直接下发 SCSI READ TOC(0x43) 读 CD 轨道表
复用 /home/zyw/Downloads/vcd-rip/sgio.py 的 sg_io()（结构体/方向常量已核对正确）
用法: sudo python3 cd_toc2.py [/dev/sr0]
"""
import os, struct, sys
sys.path.insert(0, "/home/zyw/Downloads/vcd-rip")
from sgio import sg_io, SG_DXFER_FROM_DEV, SG_DXFER_NONE

DEV = sys.argv[1] if len(sys.argv) > 1 else "/dev/sr0"

def lba2msf(l):
    t = l + 150
    return t // (60 * 75), (t // 75) % 60, t % 75

fd = os.open(DEV, os.O_RDONLY | os.O_NONBLOCK)
try:
    # READ TOC/PMA/ATIP (0x43), format=0000b（标准 TOC）, MSF=1
    cdb = [0x43, 0x00, 0, 0, 0, 0, 0x03, 0x40, 804 >> 8, 804 & 0xFF]
    data, st, host, drv, sb, resid = sg_io(fd, cdb, 804, SG_DXFER_FROM_DEV)
    if st != 0 or not data or len(data) < 4:
        print(f"READ TOC 失败 status={st} host={host} driver={drv} sense={sb.hex()}")
        raise SystemExit(1)
    toc_len = struct.unpack(">H", data[0:2])[0]
    first, last = data[2], data[3]
    print(f"READ TOC 成功: 长度={toc_len} 首轨={first} 末轨={last}")
    print(f"{'轨道':<6}{'类型':<8}{'LBA':>9}  {'MSF':<12}{'时长':>9}   ctrl")
    prev = None
    leadout = None
    tracks = []
    off = 4
    while off + 8 <= min(len(data), toc_len + 2):
        _r, adr_ctrl, tnum, _z, m, s, f = struct.unpack(">BBBBBBB", data[off:off+8])
        ctrl = (adr_ctrl >> 4) & 0xF
        adr = adr_ctrl & 0xF
        kind = "audio" if (ctrl & 0x4) == 0 else "data"
        lba = (m * 60 + s) * 75 + f - 150
        dur = f"{(lba - prev) / 75:.1f}s" if prev is not None else "—"
        label = "LEAD-OUT" if tnum == 0xAA else f"{tnum}"
        print(f"{label:<6}{kind:<8}{lba:>9}  {m:02d}:{s:02d}:{f:02d}   {dur:>9}   adr={adr} ctrl=0x{ctrl:x}")
        if tnum == 0xAA:
            leadout = lba
        else:
            tracks.append((tnum, kind, lba))
            prev = lba
        off += 8

    # 设备容量（READ CAPACITY 0x25）
    data2, st2, *_ = sg_io(fd, [0x25, 0, 0, 0, 0, 0, 0, 0, 0], 8, SG_DXFER_FROM_DEV)
    if st2 == 0 and data2 and len(data2) == 8:
        last_lba, bs = struct.unpack(">II", data2)
        print(f"\n设备容量: 最后 LBA={last_lba}  ({(last_lba+1)*2048/1048576:.1f} MiB @2048B)")
        print(f"          总时长约 {(last_lba+1)/75/60:.1f} 分钟")

    # TOC 是否可信（参照 VCD 那次的教训：TOC 报的 lead-out 可能偏小）
    if tracks:
        last_trk_end = tracks[-1][2]
        print(f"\n末轨起始 LBA={last_trk_end}")
        if leadout and leadout < last_trk_end:
            print(f"⚠️ TOC 的 lead-out({leadout}) < 末轨起始，TOC 不可信")
    # 汇总
    audio_n = sum(1 for t in tracks if t[1] == "audio")
    data_n = sum(1 for t in tracks if t[1] == "data")
    print(f"\n汇总: 共 {len(tracks)} 轨（audio {audio_n} / data {data_n}）")
    if data_n and audio_n:
        print("→ 混合模式盘（mixed-mode）：数据轨 + 音频轨")
    elif audio_n:
        print("→ 纯音频 CD（CD-DA）")
    elif data_n:
        print("→ 纯数据盘（无音频轨）")
finally:
    os.close(fd)
