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