SF #1499797, Fix for memory leak in WindowsError_str
[python.git] / Lib / plat-mac / Audio_mac.py
blobfd96095ad67adf3d8602f7937ef27c970850d699
1 QSIZE = 100000
2 error='Audio_mac.error'
4 class Play_Audio_mac:
6 def __init__(self, qsize=QSIZE):
7 self._chan = None
8 self._qsize = qsize
9 self._outrate = 22254
10 self._sampwidth = 1
11 self._nchannels = 1
12 self._gc = []
13 self._usercallback = None
15 def __del__(self):
16 self.stop()
17 self._usercallback = None
19 def wait(self):
20 import time
21 while self.getfilled():
22 time.sleep(0.1)
23 self._chan = None
24 self._gc = []
26 def stop(self, quietNow = 1):
27 ##chan = self._chan
28 self._chan = None
29 ##chan.SndDisposeChannel(1)
30 self._gc = []
32 def setoutrate(self, outrate):
33 self._outrate = outrate
35 def setsampwidth(self, sampwidth):
36 self._sampwidth = sampwidth
38 def setnchannels(self, nchannels):
39 self._nchannels = nchannels
41 def writeframes(self, data):
42 import time
43 from Carbon.Sound import bufferCmd, callBackCmd, extSH
44 import struct
45 import MacOS
46 if not self._chan:
47 from Carbon import Snd
48 self._chan = Snd.SndNewChannel(5, 0, self._callback)
49 nframes = len(data) / self._nchannels / self._sampwidth
50 if len(data) != nframes * self._nchannels * self._sampwidth:
51 raise error, 'data is not a whole number of frames'
52 while self._gc and \
53 self.getfilled() + nframes > \
54 self._qsize / self._nchannels / self._sampwidth:
55 time.sleep(0.1)
56 if self._sampwidth == 1:
57 import audioop
58 data = audioop.add(data, '\x80'*len(data), 1)
59 h1 = struct.pack('llHhllbbl',
60 id(data)+MacOS.string_id_to_buffer,
61 self._nchannels,
62 self._outrate, 0,
65 extSH,
66 60,
67 nframes)
68 h2 = 22*'\0'
69 h3 = struct.pack('hhlll',
70 self._sampwidth*8,
75 header = h1+h2+h3
76 self._gc.append((header, data))
77 self._chan.SndDoCommand((bufferCmd, 0, header), 0)
78 self._chan.SndDoCommand((callBackCmd, 0, 0), 0)
80 def _callback(self, *args):
81 del self._gc[0]
82 if self._usercallback:
83 self._usercallback()
85 def setcallback(self, callback):
86 self._usercallback = callback
88 def getfilled(self):
89 filled = 0
90 for header, data in self._gc:
91 filled = filled + len(data)
92 return filled / self._nchannels / self._sampwidth
94 def getfillable(self):
95 return (self._qsize / self._nchannels / self._sampwidth) - self.getfilled()
97 def ulaw2lin(self, data):
98 import audioop
99 return audioop.ulaw2lin(data, 2)
101 def test():
102 import aifc
103 import EasyDialogs
104 fn = EasyDialogs.AskFileForOpen(message="Select an AIFF soundfile", typeList=("AIFF",))
105 if not fn: return
106 af = aifc.open(fn, 'r')
107 print af.getparams()
108 p = Play_Audio_mac()
109 p.setoutrate(af.getframerate())
110 p.setsampwidth(af.getsampwidth())
111 p.setnchannels(af.getnchannels())
112 BUFSIZ = 10000
113 while 1:
114 data = af.readframes(BUFSIZ)
115 if not data: break
116 p.writeframes(data)
117 print 'wrote', len(data), 'space', p.getfillable()
118 p.wait()
120 if __name__ == '__main__':
121 test()