1# Class interface to the CD module. 2from warnings import warnpy3k 3warnpy3k("the readcd module has been removed in Python 3.0", stacklevel=2) 4del warnpy3k 5 6import cd, CD 7 8class Error(Exception): 9 pass 10class _Stop(Exception): 11 pass 12 13def _doatime(self, cb_type, data): 14 if ((data[0] * 60) + data[1]) * 75 + data[2] > self.end: 15## print 'done with list entry', repr(self.listindex) 16 raise _Stop 17 func, arg = self.callbacks[cb_type] 18 if func: 19 func(arg, cb_type, data) 20 21def _dopnum(self, cb_type, data): 22 if data > self.end: 23## print 'done with list entry', repr(self.listindex) 24 raise _Stop 25 func, arg = self.callbacks[cb_type] 26 if func: 27 func(arg, cb_type, data) 28 29class Readcd: 30 def __init__(self, *arg): 31 if len(arg) == 0: 32 self.player = cd.open() 33 elif len(arg) == 1: 34 self.player = cd.open(arg[0]) 35 elif len(arg) == 2: 36 self.player = cd.open(arg[0], arg[1]) 37 else: 38 raise Error, 'bad __init__ call' 39 self.list = [] 40 self.callbacks = [(None, None)] * 8 41 self.parser = cd.createparser() 42 self.playing = 0 43 self.end = 0 44 self.status = None 45 self.trackinfo = None 46 47 def eject(self): 48 self.player.eject() 49 self.list = [] 50 self.end = 0 51 self.listindex = 0 52 self.status = None 53 self.trackinfo = None 54 if self.playing: 55## print 'stop playing from eject' 56 raise _Stop 57 58 def pmsf2msf(self, track, min, sec, frame): 59 if not self.status: 60 self.cachestatus() 61 if track < self.status[5] or track > self.status[6]: 62 raise Error, 'track number out of range' 63 if not self.trackinfo: 64 self.cacheinfo() 65 start, total = self.trackinfo[track] 66 start = ((start[0] * 60) + start[1]) * 75 + start[2] 67 total = ((total[0] * 60) + total[1]) * 75 + total[2] 68 block = ((min * 60) + sec) * 75 + frame 69 if block > total: 70 raise Error, 'out of range' 71 block = start + block 72 min, block = divmod(block, 75*60) 73 sec, frame = divmod(block, 75) 74 return min, sec, frame 75 76 def reset(self): 77 self.list = [] 78 79 def appendtrack(self, track): 80 self.appendstretch(track, track) 81 82 def appendstretch(self, start, end): 83 if not self.status: 84 self.cachestatus() 85 if not start: 86 start = 1 87 if not end: 88 end = self.status[6] 89 if type(end) == type(0): 90 if end < self.status[5] or end > self.status[6]: 91 raise Error, 'range error' 92 else: 93 l = len(end) 94 if l == 4: 95 prog, min, sec, frame = end 96 if prog < self.status[5] or prog > self.status[6]: 97 raise Error, 'range error' 98 end = self.pmsf2msf(prog, min, sec, frame) 99 elif l != 3: 100 raise Error, 'syntax error' 101 if type(start) == type(0): 102 if start < self.status[5] or start > self.status[6]: 103 raise Error, 'range error' 104 if len(self.list) > 0: 105 s, e = self.list[-1] 106 if type(e) == type(0): 107 if start == e+1: 108 start = s 109 del self.list[-1] 110 else: 111 l = len(start) 112 if l == 4: 113 prog, min, sec, frame = start 114 if prog < self.status[5] or prog > self.status[6]: 115 raise Error, 'range error' 116 start = self.pmsf2msf(prog, min, sec, frame) 117 elif l != 3: 118 raise Error, 'syntax error' 119 self.list.append((start, end)) 120 121 def settracks(self, list): 122 self.list = [] 123 for track in list: 124 self.appendtrack(track) 125 126 def setcallback(self, cb_type, func, arg): 127 if cb_type < 0 or cb_type >= 8: 128 raise Error, 'type out of range' 129 self.callbacks[cb_type] = (func, arg) 130 if self.playing: 131 start, end = self.list[self.listindex] 132 if type(end) == type(0): 133 if cb_type != CD.PNUM: 134 self.parser.setcallback(cb_type, func, arg) 135 else: 136 if cb_type != CD.ATIME: 137 self.parser.setcallback(cb_type, func, arg) 138 139 def removecallback(self, cb_type): 140 if cb_type < 0 or cb_type >= 8: 141 raise Error, 'type out of range' 142 self.callbacks[cb_type] = (None, None) 143 if self.playing: 144 start, end = self.list[self.listindex] 145 if type(end) == type(0): 146 if cb_type != CD.PNUM: 147 self.parser.removecallback(cb_type) 148 else: 149 if cb_type != CD.ATIME: 150 self.parser.removecallback(cb_type) 151 152 def gettrackinfo(self, *arg): 153 if not self.status: 154 self.cachestatus() 155 if not self.trackinfo: 156 self.cacheinfo() 157 if len(arg) == 0: 158 return self.trackinfo[self.status[5]:self.status[6]+1] 159 result = [] 160 for i in arg: 161 if i < self.status[5] or i > self.status[6]: 162 raise Error, 'range error' 163 result.append(self.trackinfo[i]) 164 return result 165 166 def cacheinfo(self): 167 if not self.status: 168 self.cachestatus() 169 self.trackinfo = [] 170 for i in range(self.status[5]): 171 self.trackinfo.append(None) 172 for i in range(self.status[5], self.status[6]+1): 173 self.trackinfo.append(self.player.gettrackinfo(i)) 174 175 def cachestatus(self): 176 self.status = self.player.getstatus() 177 if self.status[0] == CD.NODISC: 178 self.status = None 179 raise Error, 'no disc in player' 180 181 def getstatus(self): 182 return self.player.getstatus() 183 184 def play(self): 185 if not self.status: 186 self.cachestatus() 187 size = self.player.bestreadsize() 188 self.listindex = 0 189 self.playing = 0 190 for i in range(8): 191 func, arg = self.callbacks[i] 192 if func: 193 self.parser.setcallback(i, func, arg) 194 else: 195 self.parser.removecallback(i) 196 if len(self.list) == 0: 197 for i in range(self.status[5], self.status[6]+1): 198 self.appendtrack(i) 199 try: 200 while 1: 201 if not self.playing: 202 if self.listindex >= len(self.list): 203 return 204 start, end = self.list[self.listindex] 205 if type(start) == type(0): 206 dummy = self.player.seektrack( 207 start) 208 else: 209 min, sec, frame = start 210 dummy = self.player.seek( 211 min, sec, frame) 212 if type(end) == type(0): 213 self.parser.setcallback( 214 CD.PNUM, _dopnum, self) 215 self.end = end 216 func, arg = \ 217 self.callbacks[CD.ATIME] 218 if func: 219 self.parser.setcallback(CD.ATIME, func, arg) 220 else: 221 self.parser.removecallback(CD.ATIME) 222 else: 223 min, sec, frame = end 224 self.parser.setcallback( 225 CD.ATIME, _doatime, 226 self) 227 self.end = (min * 60 + sec) * \ 228 75 + frame 229 func, arg = \ 230 self.callbacks[CD.PNUM] 231 if func: 232 self.parser.setcallback(CD.PNUM, func, arg) 233 else: 234 self.parser.removecallback(CD.PNUM) 235 self.playing = 1 236 data = self.player.readda(size) 237 if data == '': 238 self.playing = 0 239 self.listindex = self.listindex + 1 240 continue 241 try: 242 self.parser.parseframe(data) 243 except _Stop: 244 self.playing = 0 245 self.listindex = self.listindex + 1 246 finally: 247 self.playing = 0 248