1 #ifndef MPLAYER_VCD_READ_WIN32_H
2 #define MPLAYER_VCD_READ_WIN32_H
4 #include <ddk/ntddcdrm.h>
7 typedef struct mp_vcd_priv_st mp_vcd_priv_t
;
10 Unlike Unices, upon reading TOC, Windows will retrieve information for
11 all tracks, so we don't need to call DeviceIoControl() in functions
12 like vcd_seek_to_track() and vcd_get_track_end() for each track. Instead
13 we cache the information in mp_vcd_priv_st.
15 struct mp_vcd_priv_st
{
19 char buf
[VCD_SECTOR_SIZE
];
22 static inline void vcd_set_msf(mp_vcd_priv_t
* vcd
, unsigned sect
)
27 static inline unsigned vcd_get_msf(mp_vcd_priv_t
* vcd
, int track
){
28 int index
= track
- vcd
->toc
.FirstTrack
;
29 /* -150 to compensate the 2-second pregap */
30 return vcd
->toc
.TrackData
[index
].Address
[3] +
31 (vcd
->toc
.TrackData
[index
].Address
[2] +
32 vcd
->toc
.TrackData
[index
].Address
[1] * 60) * 75 - 150;
35 int vcd_seek_to_track(mp_vcd_priv_t
* vcd
, int track
)
38 if (track
< vcd
->toc
.FirstTrack
|| track
> vcd
->toc
.LastTrack
)
40 sect
= vcd_get_msf(vcd
, track
);
41 vcd_set_msf(vcd
, sect
);
42 return VCD_SECTOR_DATA
* (sect
+ 2);
45 int vcd_get_track_end(mp_vcd_priv_t
* vcd
, int track
)
47 if (track
< vcd
->toc
.FirstTrack
|| track
> vcd
->toc
.LastTrack
)
49 return VCD_SECTOR_DATA
* (vcd_get_msf(vcd
, track
+ 1));
52 mp_vcd_priv_t
* vcd_read_toc(int fd
)
54 DWORD dwBytesReturned
;
56 int i
, min
= 0, sec
= 0, frame
= 0;
57 mp_vcd_priv_t
* vcd
= malloc(sizeof(mp_vcd_priv_t
));
61 hd
= (HANDLE
)_get_osfhandle(fd
);
62 if (!DeviceIoControl(hd
, IOCTL_CDROM_READ_TOC
, NULL
, 0, &vcd
->toc
,
63 sizeof(CDROM_TOC
), &dwBytesReturned
, NULL
)) {
64 mp_msg(MSGT_OPEN
, MSGL_ERR
, "read CDROM toc header: %lu\n",
70 mp_msg(MSGT_IDENTIFY
, MSGL_INFO
, "ID_VCD_START_TRACK=%d\n",
72 mp_msg(MSGT_IDENTIFY
, MSGL_INFO
, "ID_VCD_END_TRACK=%d\n",
75 for (i
= vcd
->toc
.FirstTrack
; i
<= vcd
->toc
.LastTrack
+ 1; i
++) {
76 int index
= i
- vcd
->toc
.FirstTrack
;
77 if (i
<= vcd
->toc
.LastTrack
) {
78 mp_msg(MSGT_OPEN
, MSGL_INFO
, "track %02d: adr=%d ctrl=%d"
80 vcd
->toc
.TrackData
[index
].TrackNumber
,
81 vcd
->toc
.TrackData
[index
].Adr
,
82 vcd
->toc
.TrackData
[index
].Control
,
83 vcd
->toc
.TrackData
[index
].Address
[1],
84 vcd
->toc
.TrackData
[index
].Address
[2],
85 vcd
->toc
.TrackData
[index
].Address
[3]);
88 if (mp_msg_test(MSGT_IDENTIFY
, MSGL_INFO
)) {
89 if (i
> vcd
->toc
.FirstTrack
) {
90 min
= vcd
->toc
.TrackData
[index
].Address
[1] - min
;
91 sec
= vcd
->toc
.TrackData
[index
].Address
[2] - sec
;
92 frame
= vcd
->toc
.TrackData
[index
].Address
[3] - frame
;
101 mp_msg(MSGT_IDENTIFY
, MSGL_INFO
, "ID_VCD_TRACK_%d_MSF="
102 "%02d:%02d:%02d\n", i
- 1, min
, sec
, frame
);
103 min
= vcd
->toc
.TrackData
[index
].Address
[1];
104 sec
= vcd
->toc
.TrackData
[index
].Address
[2];
105 frame
= vcd
->toc
.TrackData
[index
].Address
[3];
114 static int vcd_read(mp_vcd_priv_t
* vcd
, char *mem
)
116 DWORD dwBytesReturned
;
117 RAW_READ_INFO cdrom_raw
;
119 /* 2048 isn't a typo: it's the Windows way. */
120 cdrom_raw
.DiskOffset
.QuadPart
= (long long)(2048 * vcd
->sect
);
121 cdrom_raw
.SectorCount
= 1;
122 cdrom_raw
.TrackMode
= XAForm2
;
124 if (!DeviceIoControl(vcd
->hd
, IOCTL_CDROM_RAW_READ
, &cdrom_raw
,
125 sizeof(RAW_READ_INFO
), vcd
->buf
, sizeof(vcd
->buf
),
126 &dwBytesReturned
, NULL
))
130 memcpy(mem
, &vcd
->buf
[VCD_SECTOR_OFFS
], VCD_SECTOR_DATA
);
131 return VCD_SECTOR_DATA
;
134 #endif /* MPLAYER_VCD_READ_WIN32_H */
137 vim:noet:sw=4:cino=\:0,g0