1 #include <ddk/ntddcdrm.h>
3 typedef struct mp_vcd_priv_st mp_vcd_priv_t
;
6 Unlike Unices, upon reading TOC, Windows will retrieve information for
7 all tracks, so we don't need to call DeviceIoControl() in functions
8 like vcd_seek_to_track() and vcd_get_track_end() for each track. Instead
9 we cache the information in mp_vcd_priv_st.
11 struct mp_vcd_priv_st
{
15 char buf
[VCD_SECTOR_SIZE
];
18 static inline void vcd_set_msf(mp_vcd_priv_t
* vcd
, unsigned sect
)
23 static inline unsigned vcd_get_msf(mp_vcd_priv_t
* vcd
, int track
){
24 int index
= track
- vcd
->toc
.FirstTrack
;
25 /* -150 to compensate the 2-second pregap */
26 return vcd
->toc
.TrackData
[index
].Address
[3] +
27 (vcd
->toc
.TrackData
[index
].Address
[2] +
28 vcd
->toc
.TrackData
[index
].Address
[1] * 60) * 75 - 150;
31 int vcd_seek_to_track(mp_vcd_priv_t
* vcd
, int track
)
34 if (track
< vcd
->toc
.FirstTrack
|| track
> vcd
->toc
.LastTrack
)
36 sect
= vcd_get_msf(vcd
, track
);
37 vcd_set_msf(vcd
, sect
);
38 return VCD_SECTOR_DATA
* (sect
+ 2);
41 int vcd_get_track_end(mp_vcd_priv_t
* vcd
, int track
)
43 if (track
< vcd
->toc
.FirstTrack
|| track
> vcd
->toc
.LastTrack
)
45 return VCD_SECTOR_DATA
* (vcd_get_msf(vcd
, track
+ 1));
48 mp_vcd_priv_t
* vcd_read_toc(int fd
)
50 DWORD dwBytesReturned
;
52 int i
, min
= 0, sec
= 0, frame
= 0;
53 mp_vcd_priv_t
* vcd
= malloc(sizeof(mp_vcd_priv_t
));
57 hd
= (HANDLE
)_get_osfhandle(fd
);
58 if (!DeviceIoControl(hd
, IOCTL_CDROM_READ_TOC
, NULL
, 0, &vcd
->toc
,
59 sizeof(CDROM_TOC
), &dwBytesReturned
, NULL
)) {
60 mp_msg(MSGT_OPEN
, MSGL_ERR
, "read CDROM toc header: %lu\n",
66 mp_msg(MSGT_IDENTIFY
, MSGL_INFO
, "ID_VCD_START_TRACK=%d\n",
68 mp_msg(MSGT_IDENTIFY
, MSGL_INFO
, "ID_VCD_END_TRACK=%d\n",
71 for (i
= vcd
->toc
.FirstTrack
; i
<= vcd
->toc
.LastTrack
+ 1; i
++) {
72 int index
= i
- vcd
->toc
.FirstTrack
;
73 if (i
<= vcd
->toc
.LastTrack
) {
74 mp_msg(MSGT_OPEN
, MSGL_INFO
, "track %02d: adr=%d ctrl=%d"
76 vcd
->toc
.TrackData
[index
].TrackNumber
,
77 vcd
->toc
.TrackData
[index
].Adr
,
78 vcd
->toc
.TrackData
[index
].Control
,
79 vcd
->toc
.TrackData
[index
].Address
[1],
80 vcd
->toc
.TrackData
[index
].Address
[2],
81 vcd
->toc
.TrackData
[index
].Address
[3]);
84 if (mp_msg_test(MSGT_IDENTIFY
, MSGL_INFO
)) {
85 if (i
> vcd
->toc
.FirstTrack
) {
86 min
= vcd
->toc
.TrackData
[index
].Address
[1] - min
;
87 sec
= vcd
->toc
.TrackData
[index
].Address
[2] - sec
;
88 frame
= vcd
->toc
.TrackData
[index
].Address
[3] - frame
;
97 mp_msg(MSGT_IDENTIFY
, MSGL_INFO
, "ID_VCD_TRACK_%d_MSF="
98 "%02d:%02d:%02d\n", i
- 1, min
, sec
, frame
);
99 min
= vcd
->toc
.TrackData
[index
].Address
[1];
100 sec
= vcd
->toc
.TrackData
[index
].Address
[2];
101 frame
= vcd
->toc
.TrackData
[index
].Address
[3];
110 static int vcd_read(mp_vcd_priv_t
* vcd
, char *mem
)
112 DWORD dwBytesReturned
;
113 RAW_READ_INFO cdrom_raw
;
115 /* 2048 isn't a typo: it's the Windows way. */
116 cdrom_raw
.DiskOffset
.QuadPart
= (long long)(2048 * vcd
->sect
);
117 cdrom_raw
.SectorCount
= 1;
118 cdrom_raw
.TrackMode
= XAForm2
;
120 if (!DeviceIoControl(vcd
->hd
, IOCTL_CDROM_RAW_READ
, &cdrom_raw
,
121 sizeof(RAW_READ_INFO
), vcd
->buf
, sizeof(vcd
->buf
),
122 &dwBytesReturned
, NULL
))
126 memcpy(mem
, &vcd
->buf
[VCD_SECTOR_OFFS
], VCD_SECTOR_DATA
);
127 return VCD_SECTOR_DATA
;
131 vim:noet:sw=4:cino=\:0,g0