1 /*
2 * This file is part of MPlayer.
3 *
4 * MPlayer is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * MPlayer is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18
19 #ifndef MPLAYER_VCD_READ_DARWIN_H
20 #define MPLAYER_VCD_READ_DARWIN_H
21
22 #define _XOPEN_SOURCE 500
23
24 #include <stdlib.h>
25 #include <string.h>
26 #include <errno.h>
27 #include <sys/types.h>
28 #include <sys/uio.h>
29 #include <unistd.h>
30 #include <CoreFoundation/CFBase.h>
31 #include <IOKit/IOKitLib.h>
32 #include <IOKit/storage/IOCDTypes.h>
33 #include <IOKit/storage/IOCDMedia.h>
34 #include <IOKit/storage/IOCDMediaBSDClient.h>
35 #include "mpbswap.h"
36 #include "mp_msg.h"
37 #include "stream.h"
38
39 //=================== VideoCD ==========================
40 #define CDROM_LEADOUT 0xAA
41
42 typedef struct
43 {
44 uint8_t sync [12];
45 uint8_t header [4];
46 uint8_t subheader [8];
47 uint8_t data [2324];
48 uint8_t spare [4];
49 } cdsector_t;
50
51 typedef struct mp_vcd_priv_st
52 {
53 int fd;
54 cdsector_t buf;
55 dk_cd_read_track_info_t entry;
56 struct CDDiscInfo hdr;
57 CDMSF msf;
58 unsigned int track;
59 } mp_vcd_priv_t;
60
vcd_set_msf(mp_vcd_priv_t * vcd,unsigned int sect)61 static inline void vcd_set_msf(mp_vcd_priv_t* vcd, unsigned int sect)
62 {
63 vcd->msf = CDConvertLBAToMSF(sect);
64 }
65
vcd_get_msf(mp_vcd_priv_t * vcd)66 static inline unsigned int vcd_get_msf(mp_vcd_priv_t* vcd)
67 {
68 return CDConvertMSFToLBA(vcd->msf);
69 }
70
vcd_seek_to_track(mp_vcd_priv_t * vcd,int track)71 static int vcd_seek_to_track(mp_vcd_priv_t* vcd, int track)
72 {
73 struct CDTrackInfo entry;
74
75 memset( &vcd->entry, 0, sizeof(vcd->entry));
76 vcd->entry.addressType = kCDTrackInfoAddressTypeTrackNumber;
77 vcd->entry.address = track;
78 vcd->entry.bufferLength = sizeof(entry);
79 vcd->entry.buffer = &entry;
80
81 if (ioctl(vcd->fd, DKIOCCDREADTRACKINFO, &vcd->entry))
82 {
83 mp_msg(MSGT_STREAM,MSGL_ERR,"ioctl dif1: %s\n",strerror(errno));
84 return -1;
85 }
86 vcd->msf = CDConvertLBAToMSF(be2me_32(entry.trackStartAddress));
87 return VCD_SECTOR_DATA*vcd_get_msf(vcd);
88 }
89
vcd_get_track_end(mp_vcd_priv_t * vcd,int track)90 static int vcd_get_track_end(mp_vcd_priv_t* vcd, int track)
91 {
92 struct CDTrackInfo entry;
93
94 if (track > vcd->hdr.lastTrackNumberInLastSessionLSB) {
95 mp_msg(MSGT_OPEN, MSGL_ERR,
96 "track number %d greater than last track number %d\n",
97 track, vcd->hdr.lastTrackNumberInLastSessionLSB);
98 return -1;
99 }
100
101 //read track info
102 memset( &vcd->entry, 0, sizeof(vcd->entry));
103 vcd->entry.addressType = kCDTrackInfoAddressTypeTrackNumber;
104 vcd->entry.address = track<vcd->hdr.lastTrackNumberInLastSessionLSB?track+1:vcd->hdr.lastTrackNumberInLastSessionLSB;
105 vcd->entry.bufferLength = sizeof(entry);
106 vcd->entry.buffer = &entry;
107
108 if (ioctl(vcd->fd, DKIOCCDREADTRACKINFO, &vcd->entry))
109 {
110 mp_msg(MSGT_STREAM,MSGL_ERR,"ioctl dif2: %s\n",strerror(errno));
111 return -1;
112 }
113 if (track == vcd->hdr.lastTrackNumberInLastSessionLSB)
114 vcd->msf = CDConvertLBAToMSF(be2me_32(entry.trackStartAddress) +
115 be2me_32(entry.trackSize));
116 else
117 vcd->msf = CDConvertLBAToMSF(be2me_32(entry.trackStartAddress));
118 return VCD_SECTOR_DATA*vcd_get_msf(vcd);
119 }
120
vcd_read_toc(int fd)121 static mp_vcd_priv_t* vcd_read_toc(int fd)
122 {
123 dk_cd_read_disc_info_t tochdr;
124 struct CDDiscInfo hdr;
125
126 dk_cd_read_track_info_t tocentry;
127 struct CDTrackInfo entry;
128 CDMSF trackMSF;
129
130 mp_vcd_priv_t* vcd;
131 int i, min = 0, sec = 0, frame = 0;
132
133 //read toc header
134 memset(&tochdr, 0, sizeof(tochdr));
135 tochdr.buffer = &hdr;
136 tochdr.bufferLength = sizeof(hdr);
137
138 if (ioctl(fd, DKIOCCDREADDISCINFO, &tochdr) < 0)
139 {
140 mp_msg(MSGT_OPEN,MSGL_ERR,"read CDROM toc header: %s\n",strerror(errno));
141 return NULL;
142 }
143
144 //print all track info
145 mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VCD_START_TRACK=%d\n", hdr.firstTrackNumberInLastSessionLSB);
146 mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VCD_END_TRACK=%d\n", hdr.lastTrackNumberInLastSessionLSB);
147 for (i=hdr.firstTrackNumberInLastSessionLSB ; i<=hdr.lastTrackNumberInLastSessionLSB + 1; i++)
148 {
149 if (i <= hdr.lastTrackNumberInLastSessionLSB) {
150 memset( &tocentry, 0, sizeof(tocentry));
151 tocentry.addressType = kCDTrackInfoAddressTypeTrackNumber;
152 tocentry.address = i;
153 tocentry.bufferLength = sizeof(entry);
154 tocentry.buffer = &entry;
155
156 if (ioctl(fd,DKIOCCDREADTRACKINFO,&tocentry)==-1)
157 {
158 mp_msg(MSGT_OPEN,MSGL_ERR,"read CDROM toc entry: %s\n",strerror(errno));
159 return NULL;
160 }
161
162 trackMSF = CDConvertLBAToMSF(be2me_32(entry.trackStartAddress));
163 }
164 else
165 trackMSF = CDConvertLBAToMSF(be2me_32(entry.trackStartAddress)
166 + be2me_32(entry.trackSize));
167
168 //mp_msg(MSGT_OPEN,MSGL_INFO,"track %02d: adr=%d ctrl=%d format=%d %02d:%02d:%02d\n",
169 if (i<=hdr.lastTrackNumberInLastSessionLSB)
170 mp_msg(MSGT_OPEN,MSGL_INFO,"track %02d: format=%d %02d:%02d:%02d\n",
171 (int)tocentry.address,
172 //(int)tocentry.entry.addr_type,
173 //(int)tocentry.entry.control,
174 (int)tocentry.addressType,
175 (int)trackMSF.minute,
176 (int)trackMSF.second,
177 (int)trackMSF.frame
178 );
179
180 if (mp_msg_test(MSGT_IDENTIFY, MSGL_INFO))
181 {
182 if (i > hdr.firstTrackNumberInLastSessionLSB)
183 {
184 min = trackMSF.minute - min;
185 sec = trackMSF.second - sec;
186 frame = trackMSF.frame - frame;
187 if ( frame < 0 )
188 {
189 frame += 75;
190 sec --;
191 }
192 if ( sec < 0 )
193 {
194 sec += 60;
195 min --;
196 }
197 mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VCD_TRACK_%d_MSF=%02d:%02d:%02d\n", i - 1, min, sec, frame);
198 }
199 min = trackMSF.minute;
200 sec = trackMSF.second;
201 frame = trackMSF.frame;
202 }
203 }
204
205 vcd = malloc(sizeof(mp_vcd_priv_t));
206 vcd->fd = fd;
207 vcd->hdr = hdr;
208 vcd->msf = trackMSF;
209 return vcd;
210 }
211
vcd_end_track(mp_vcd_priv_t * vcd)212 static int vcd_end_track(mp_vcd_priv_t* vcd)
213 {
214 return vcd->hdr.lastTrackNumberInLastSessionLSB;
215 }
216
vcd_read(mp_vcd_priv_t * vcd,char * mem)217 static int vcd_read(mp_vcd_priv_t* vcd,char *mem)
218 {
219 if (pread(vcd->fd,&vcd->buf,VCD_SECTOR_SIZE,vcd_get_msf(vcd)*VCD_SECTOR_SIZE) != VCD_SECTOR_SIZE)
220 return 0; // EOF?
221
222 vcd->msf.frame++;
223 if (vcd->msf.frame==75)
224 {
225 vcd->msf.frame=0;
226 vcd->msf.second++;
227
228 if (vcd->msf.second==60)
229 {
230 vcd->msf.second=0;
231 vcd->msf.minute++;
232 }
233 }
234
235 memcpy(mem,vcd->buf.data,VCD_SECTOR_DATA);
236 return VCD_SECTOR_DATA;
237 }
238
239 #endif /* MPLAYER_VCD_READ_DARWIN_H */
240