• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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