1 #ifndef MPLAYER_VCD_READ_WIN32_H
2 #define MPLAYER_VCD_READ_WIN32_H
7 #include <ddk/ntddcdrm.h>
10 typedef struct mp_vcd_priv_st mp_vcd_priv_t
;
13 Unlike Unices, upon reading TOC, Windows will retrieve information for
14 all tracks, so we don't need to call DeviceIoControl() in functions
15 like vcd_seek_to_track() and vcd_get_track_end() for each track. Instead
16 we cache the information in mp_vcd_priv_st.
18 struct mp_vcd_priv_st
{
22 char buf
[VCD_SECTOR_SIZE
];
25 static inline void vcd_set_msf(mp_vcd_priv_t
* vcd
, unsigned sect
)
30 static inline unsigned vcd_get_msf(mp_vcd_priv_t
* vcd
, int track
){
31 int index
= track
- vcd
->toc
.FirstTrack
;
32 /* -150 to compensate the 2-second pregap */
33 return vcd
->toc
.TrackData
[index
].Address
[3] +
34 (vcd
->toc
.TrackData
[index
].Address
[2] +
35 vcd
->toc
.TrackData
[index
].Address
[1] * 60) * 75 - 150;
38 int vcd_seek_to_track(mp_vcd_priv_t
* vcd
, int track
)
41 if (track
< vcd
->toc
.FirstTrack
|| track
> vcd
->toc
.LastTrack
)
43 sect
= vcd_get_msf(vcd
, track
);
44 vcd_set_msf(vcd
, sect
);
45 return VCD_SECTOR_DATA
* (sect
+ 2);
48 int vcd_get_track_end(mp_vcd_priv_t
* vcd
, int track
)
50 if (track
< vcd
->toc
.FirstTrack
|| track
> vcd
->toc
.LastTrack
)
52 return VCD_SECTOR_DATA
* (vcd_get_msf(vcd
, track
+ 1));
55 mp_vcd_priv_t
* vcd_read_toc(int fd
)
57 DWORD dwBytesReturned
;
59 int i
, min
= 0, sec
= 0, frame
= 0;
60 mp_vcd_priv_t
* vcd
= malloc(sizeof(mp_vcd_priv_t
));
64 hd
= (HANDLE
)_get_osfhandle(fd
);
65 if (!DeviceIoControl(hd
, IOCTL_CDROM_READ_TOC
, NULL
, 0, &vcd
->toc
,
66 sizeof(CDROM_TOC
), &dwBytesReturned
, NULL
)) {
67 mp_msg(MSGT_OPEN
, MSGL_ERR
, "read CDROM toc header: %lu\n",
73 mp_msg(MSGT_IDENTIFY
, MSGL_INFO
, "ID_VCD_START_TRACK=%d\n",
75 mp_msg(MSGT_IDENTIFY
, MSGL_INFO
, "ID_VCD_END_TRACK=%d\n",
78 for (i
= vcd
->toc
.FirstTrack
; i
<= vcd
->toc
.LastTrack
+ 1; i
++) {
79 int index
= i
- vcd
->toc
.FirstTrack
;
80 if (i
<= vcd
->toc
.LastTrack
) {
81 mp_msg(MSGT_OPEN
, MSGL_INFO
, "track %02d: adr=%d ctrl=%d"
83 vcd
->toc
.TrackData
[index
].TrackNumber
,
84 vcd
->toc
.TrackData
[index
].Adr
,
85 vcd
->toc
.TrackData
[index
].Control
,
86 vcd
->toc
.TrackData
[index
].Address
[1],
87 vcd
->toc
.TrackData
[index
].Address
[2],
88 vcd
->toc
.TrackData
[index
].Address
[3]);
91 if (mp_msg_test(MSGT_IDENTIFY
, MSGL_INFO
)) {
92 if (i
> vcd
->toc
.FirstTrack
) {
93 min
= vcd
->toc
.TrackData
[index
].Address
[1] - min
;
94 sec
= vcd
->toc
.TrackData
[index
].Address
[2] - sec
;
95 frame
= vcd
->toc
.TrackData
[index
].Address
[3] - frame
;
104 mp_msg(MSGT_IDENTIFY
, MSGL_INFO
, "ID_VCD_TRACK_%d_MSF="
105 "%02d:%02d:%02d\n", i
- 1, min
, sec
, frame
);
106 min
= vcd
->toc
.TrackData
[index
].Address
[1];
107 sec
= vcd
->toc
.TrackData
[index
].Address
[2];
108 frame
= vcd
->toc
.TrackData
[index
].Address
[3];
117 static int vcd_read(mp_vcd_priv_t
* vcd
, char *mem
)
119 DWORD dwBytesReturned
;
120 RAW_READ_INFO cdrom_raw
;
122 /* 2048 isn't a typo: it's the Windows way. */
123 cdrom_raw
.DiskOffset
.QuadPart
= (long long)(2048 * vcd
->sect
);
124 cdrom_raw
.SectorCount
= 1;
125 cdrom_raw
.TrackMode
= XAForm2
;
127 if (!DeviceIoControl(vcd
->hd
, IOCTL_CDROM_RAW_READ
, &cdrom_raw
,
128 sizeof(RAW_READ_INFO
), vcd
->buf
, sizeof(vcd
->buf
),
129 &dwBytesReturned
, NULL
))
133 memcpy(mem
, &vcd
->buf
[VCD_SECTOR_OFFS
], VCD_SECTOR_DATA
);
134 return VCD_SECTOR_DATA
;
137 #endif /* MPLAYER_VCD_READ_WIN32_H */
140 vim:noet:sw=4:cino=\:0,g0