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