blob: 9c100acfd3569b8253cac01150722bdb4dbd4028 [file] [log] [blame]
Guido van Rossum17448e21995-01-30 11:53:55 +00001# This script generates the Sound interface for Python.
2# It uses the "bgen" package to generate C code.
3# It execs the file sndgen.py which contain the function definitions
4# (sndgen.py was generated by sndscan.py, scanning the <Sound.h> header file).
5
6from macsupport import *
7
8
9# define our own function and module generators
10
11class SndMixIn: pass
12
13class SndFunction(SndMixIn, OSErrFunctionGenerator): pass
14class SndMethod(SndMixIn, OSErrMethodGenerator): pass
15
16
17# includestuff etc. are imported from macsupport
18
19includestuff = includestuff + """
Jack Jansenfa77e1a2001-05-22 21:56:42 +000020#ifdef WITHOUT_FRAMEWORKS
Guido van Rossum17448e21995-01-30 11:53:55 +000021#include <Sound.h>
Jack Jansenfa77e1a2001-05-22 21:56:42 +000022#include <OSUtils.h> /* for Set(Current)A5 */
23#else
24#include <Carbon/Carbon.h>
25#endif
Guido van Rossum17448e21995-01-30 11:53:55 +000026"""
27
28initstuff = initstuff + """
29"""
30
31
32# define types used for arguments (in addition to standard and macsupport types)
33
34class SndChannelPtrType(OpaqueByValueType):
35 def declare(self, name):
36 # Initializing all SndChannelPtr objects to 0 saves
37 # special-casing NewSndChannel(), where it is formally an
38 # input-output parameter but we treat it as output-only
39 # (since Python users are not supposed to allocate memory)
40 Output("SndChannelPtr %s = 0;", name)
41
42SndChannelPtr = SndChannelPtrType('SndChannelPtr', 'SndCh')
43
44SndCommand = OpaqueType('SndCommand', 'SndCmd')
45SndCommand_ptr = OpaqueType('SndCommand', 'SndCmd')
46SndListHandle = OpaqueByValueType("SndListHandle", "ResObj")
Jack Jansen52b38b71998-02-25 15:47:51 +000047SPBPtr = OpaqueByValueType("SPBPtr", "SPBObj")
48
49#
50# NOTE: the following is pretty dangerous. For void pointers we pass buffer addresses
51# but we have no way to check that the buffer is big enough. This is the same problem
52# as in C, though (but Pythoneers may not be suspecting this...)
53void_ptr = Type("void *", "w")
Guido van Rossum17448e21995-01-30 11:53:55 +000054
55class SndCallBackType(InputOnlyType):
56 def __init__(self):
57 Type.__init__(self, 'PyObject*', 'O')
58 def getargsCheck(self, name):
Guido van Rossum97842951995-02-19 15:59:49 +000059 Output("if (%s != Py_None && !PyCallable_Check(%s))", name, name)
Guido van Rossum17448e21995-01-30 11:53:55 +000060 OutLbrace()
61 Output('PyErr_SetString(PyExc_TypeError, "callback must be callable");')
62 Output("goto %s__error__;", name)
63 OutRbrace()
64 def passInput(self, name):
Jack Jansenfa77e1a2001-05-22 21:56:42 +000065 return "NewSndCallBackUPP(SndCh_UserRoutine)"
Guido van Rossum17448e21995-01-30 11:53:55 +000066 def cleanup(self, name):
67 # XXX This knows it is executing inside the SndNewChannel wrapper
68 Output("if (_res != NULL && %s != Py_None)", name)
69 OutLbrace()
70 Output("SndChannelObject *p = (SndChannelObject *)_res;")
71 Output("p->ob_itself->userInfo = (long)p;")
72 Output("Py_INCREF(%s);", name)
73 Output("p->ob_callback = %s;", name)
74 OutRbrace()
75 DedentLevel()
76 Output(" %s__error__: ;", name)
77 IndentLevel()
78
79SndCallBackProcPtr = SndCallBackType()
Jack Jansenb81cf9d1995-06-06 13:08:40 +000080SndCallBackUPP = SndCallBackProcPtr
Guido van Rossum17448e21995-01-30 11:53:55 +000081
82SndCompletionProcPtr = FakeType('(SndCompletionProcPtr)0') # XXX
Jack Jansenb81cf9d1995-06-06 13:08:40 +000083SndCompletionUPP = SndCompletionProcPtr
Guido van Rossum17448e21995-01-30 11:53:55 +000084
Jack Jansen7d0bc831995-06-09 20:56:31 +000085##InOutBuf128 = FixedInputOutputBufferType(128)
86StateBlock = StructInputOutputBufferType('StateBlock')
Guido van Rossum17448e21995-01-30 11:53:55 +000087
88AudioSelectionPtr = FakeType('0') # XXX
89
90ProcPtr = FakeType('0') # XXX
Jack Jansenb81cf9d1995-06-06 13:08:40 +000091FilePlayCompletionUPP = FakeType('0') # XXX
Guido van Rossum17448e21995-01-30 11:53:55 +000092
93SCStatus = StructOutputBufferType('SCStatus')
94SMStatus = StructOutputBufferType('SMStatus')
Jack Jansenb81cf9d1995-06-06 13:08:40 +000095CompressionInfo = StructOutputBufferType('CompressionInfo')
Guido van Rossum17448e21995-01-30 11:53:55 +000096
97includestuff = includestuff + """
Guido van Rossum17448e21995-01-30 11:53:55 +000098
99/* Create a SndCommand object (an (int, int, int) tuple) */
100static PyObject *
101SndCmd_New(SndCommand *pc)
102{
103 return Py_BuildValue("hhl", pc->cmd, pc->param1, pc->param2);
104}
105
106/* Convert a SndCommand argument */
107static int
108SndCmd_Convert(PyObject *v, SndCommand *pc)
109{
110 int len;
111 pc->param1 = 0;
112 pc->param2 = 0;
113 if (PyTuple_Check(v)) {
114 if (PyArg_ParseTuple(v, "h|hl", &pc->cmd, &pc->param1, &pc->param2))
115 return 1;
116 PyErr_Clear();
Jack Jansen0b13e7c2000-07-07 13:09:35 +0000117 return PyArg_ParseTuple(v, "Hhs#", &pc->cmd, &pc->param1, &pc->param2, &len);
Guido van Rossum17448e21995-01-30 11:53:55 +0000118 }
Jack Jansen0b13e7c2000-07-07 13:09:35 +0000119 return PyArg_Parse(v, "H", &pc->cmd);
Guido van Rossum17448e21995-01-30 11:53:55 +0000120}
121
Guido van Rossum17448e21995-01-30 11:53:55 +0000122static pascal void SndCh_UserRoutine(SndChannelPtr chan, SndCommand *cmd); /* Forward */
Jack Jansen52b38b71998-02-25 15:47:51 +0000123static pascal void SPB_completion(SPBPtr my_spb); /* Forward */
Jack Jansen319c67b2001-01-12 23:39:59 +0000124#if !TARGET_API_MAC_CARBON
Jack Jansen52b38b71998-02-25 15:47:51 +0000125static pascal void SPB_interrupt(SPBPtr my_spb); /* Forward */
Jack Jansen319c67b2001-01-12 23:39:59 +0000126#endif
Guido van Rossum17448e21995-01-30 11:53:55 +0000127"""
128
129
130finalstuff = finalstuff + """
131/* Routine passed to Py_AddPendingCall -- call the Python callback */
132static int
Jack Jansenfa77e1a2001-05-22 21:56:42 +0000133SndCh_CallCallBack(void *arg)
Guido van Rossum17448e21995-01-30 11:53:55 +0000134{
135 SndChannelObject *p = (SndChannelObject *)arg;
136 PyObject *args;
137 PyObject *res;
138 args = Py_BuildValue("(O(hhl))",
139 p, p->ob_cmd.cmd, p->ob_cmd.param1, p->ob_cmd.param2);
140 res = PyEval_CallObject(p->ob_callback, args);
141 Py_DECREF(args);
142 if (res == NULL)
143 return -1;
144 Py_DECREF(res);
145 return 0;
146}
147
148/* Routine passed to NewSndChannel -- schedule a call to SndCh_CallCallBack */
149static pascal void
150SndCh_UserRoutine(SndChannelPtr chan, SndCommand *cmd)
151{
152 SndChannelObject *p = (SndChannelObject *)(chan->userInfo);
153 if (p->ob_callback != NULL) {
154 long A5 = SetA5(p->ob_A5);
155 p->ob_cmd = *cmd;
156 Py_AddPendingCall(SndCh_CallCallBack, (void *)p);
157 SetA5(A5);
158 }
159}
Jack Jansen52b38b71998-02-25 15:47:51 +0000160
161/* SPB callbacks - Schedule callbacks to Python */
162static int
Jack Jansenfa77e1a2001-05-22 21:56:42 +0000163SPB_CallCallBack(void *arg)
Jack Jansen52b38b71998-02-25 15:47:51 +0000164{
165 SPBObject *p = (SPBObject *)arg;
166 PyObject *args;
167 PyObject *res;
168
169 if ( p->ob_thiscallback == 0 ) return 0;
170 args = Py_BuildValue("(O)", p);
171 res = PyEval_CallObject(p->ob_thiscallback, args);
172 p->ob_thiscallback = 0;
173 Py_DECREF(args);
174 if (res == NULL)
175 return -1;
176 Py_DECREF(res);
177 return 0;
178}
179
180static pascal void
181SPB_completion(SPBPtr my_spb)
182{
183 SPBObject *p = (SPBObject *)(my_spb->userLong);
184
185 if (p && p->ob_completion) {
186 long A5 = SetA5(p->ob_A5);
187 p->ob_thiscallback = p->ob_completion; /* Hope we cannot get two at the same time */
188 Py_AddPendingCall(SPB_CallCallBack, (void *)p);
189 SetA5(A5);
190 }
191}
192
Jack Jansen319c67b2001-01-12 23:39:59 +0000193#if !TARGET_API_MAC_CARBON
Jack Jansen52b38b71998-02-25 15:47:51 +0000194static pascal void
195SPB_interrupt(SPBPtr my_spb)
196{
197 SPBObject *p = (SPBObject *)(my_spb->userLong);
198
199 if (p && p->ob_interrupt) {
200 long A5 = SetA5(p->ob_A5);
201 p->ob_thiscallback = p->ob_interrupt; /* Hope we cannot get two at the same time */
202 Py_AddPendingCall(SPB_CallCallBack, (void *)p);
203 SetA5(A5);
204 }
205}
Jack Jansen319c67b2001-01-12 23:39:59 +0000206#endif
Guido van Rossum17448e21995-01-30 11:53:55 +0000207"""
208
209
210# create the module and object definition and link them
211
212class SndObjectDefinition(ObjectDefinition):
213
214 def outputStructMembers(self):
215 ObjectDefinition.outputStructMembers(self)
216 Output("/* Members used to implement callbacks: */")
217 Output("PyObject *ob_callback;")
218 Output("long ob_A5;");
219 Output("SndCommand ob_cmd;")
220
221 def outputInitStructMembers(self):
222 ObjectDefinition.outputInitStructMembers(self)
223 Output("it->ob_callback = NULL;")
224 Output("it->ob_A5 = SetCurrentA5();");
225
226 def outputCleanupStructMembers(self):
227 ObjectDefinition.outputCleanupStructMembers(self)
228 Output("Py_XDECREF(self->ob_callback);")
229
230 def outputFreeIt(self, itselfname):
231 Output("SndDisposeChannel(%s, 1);", itselfname)
Jack Jansen52b38b71998-02-25 15:47:51 +0000232
233#
Guido van Rossum17448e21995-01-30 11:53:55 +0000234
Jack Jansen52b38b71998-02-25 15:47:51 +0000235class SpbObjectDefinition(ObjectDefinition):
236
237 def outputStructMembers(self):
238 Output("/* Members used to implement callbacks: */")
239 Output("PyObject *ob_completion;")
240 Output("PyObject *ob_interrupt;")
241 Output("PyObject *ob_thiscallback;");
242 Output("long ob_A5;")
243 Output("SPB ob_spb;")
244
245 def outputNew(self):
246 Output()
Jack Jansen3685a432001-06-20 21:22:23 +0000247 Output("%sPyObject *%s_New(void)", self.static, self.prefix)
Jack Jansen52b38b71998-02-25 15:47:51 +0000248 OutLbrace()
249 Output("%s *it;", self.objecttype)
250 self.outputCheckNewArg()
251 Output("it = PyObject_NEW(%s, &%s);", self.objecttype, self.typename)
252 Output("if (it == NULL) return NULL;")
253 self.outputInitStructMembers()
254 Output("return (PyObject *)it;")
255 OutRbrace()
256
257 def outputInitStructMembers(self):
258 Output("it->ob_completion = NULL;")
259 Output("it->ob_interrupt = NULL;")
260 Output("it->ob_thiscallback = NULL;")
261 Output("it->ob_A5 = SetCurrentA5();")
262 Output("memset((char *)&it->ob_spb, 0, sizeof(it->ob_spb));")
263 Output("it->ob_spb.userLong = (long)it;")
264
265 def outputCleanupStructMembers(self):
266 ObjectDefinition.outputCleanupStructMembers(self)
267 Output("self->ob_spb.userLong = 0;")
268 Output("self->ob_thiscallback = 0;")
269 Output("Py_XDECREF(self->ob_completion);")
270 Output("Py_XDECREF(self->ob_interrupt);")
271
272 def outputConvert(self):
Jack Jansenfa77e1a2001-05-22 21:56:42 +0000273 Output("%s%s_Convert(PyObject *v, %s *p_itself)", self.static, self.prefix, self.itselftype)
Jack Jansen52b38b71998-02-25 15:47:51 +0000274 OutLbrace()
275 self.outputCheckConvertArg()
276 Output("if (!%s_Check(v))", self.prefix)
277 OutLbrace()
278 Output('PyErr_SetString(PyExc_TypeError, "%s required");', self.name)
279 Output("return 0;")
280 OutRbrace()
281 Output("*p_itself = &((%s *)v)->ob_spb;", self.objecttype)
282 Output("return 1;")
283 OutRbrace()
284
285 def outputSetattr(self):
286 Output()
Jack Jansenfa77e1a2001-05-22 21:56:42 +0000287 Output("static int %s_setattr(%s *self, char *name, PyObject *value)",
288 self.prefix, self.objecttype)
Jack Jansen52b38b71998-02-25 15:47:51 +0000289 OutLbrace()
290 self.outputSetattrBody()
291 OutRbrace()
292
293 def outputSetattrBody(self):
294 Output("""
Jack Jansena239a921998-04-15 14:08:28 +0000295 int rv = 0;
296
297 if (strcmp(name, "inRefNum") == 0)
298 rv = PyArg_Parse(value, "l", &self->ob_spb.inRefNum);
299 else if (strcmp(name, "count") == 0)
300 rv = PyArg_Parse(value, "l", &self->ob_spb.count);
301 else if (strcmp(name, "milliseconds") == 0)
302 rv = PyArg_Parse(value, "l", &self->ob_spb.milliseconds);
303 else if (strcmp(name, "buffer") == 0)
304 rv = PyArg_Parse(value, "w#", &self->ob_spb.bufferPtr, &self->ob_spb.bufferLength);
305 else if (strcmp(name, "completionRoutine") == 0) {
Jack Jansenfa77e1a2001-05-22 21:56:42 +0000306 self->ob_spb.completionRoutine = NewSICompletionUPP(SPB_completion);
Jack Jansena239a921998-04-15 14:08:28 +0000307 self->ob_completion = value;
308 Py_INCREF(value);
309 rv = 1;
Jack Jansen319c67b2001-01-12 23:39:59 +0000310#if !TARGET_API_MAC_CARBON
Jack Jansena239a921998-04-15 14:08:28 +0000311 } else if (strcmp(name, "interruptRoutine") == 0) {
Jack Jansenfa77e1a2001-05-22 21:56:42 +0000312 self->ob_spb.completionRoutine = NewSIInterruptUPP(SPB_interrupt);
Jack Jansena239a921998-04-15 14:08:28 +0000313 self->ob_interrupt = value;
314 Py_INCREF(value);
315 rv = 1;
Jack Jansen8d929ae2000-06-21 22:07:06 +0000316#endif
Jack Jansena239a921998-04-15 14:08:28 +0000317 }
318 if ( rv ) return 0;
319 else return -1;""")
Jack Jansen52b38b71998-02-25 15:47:51 +0000320
321 def outputGetattrHook(self):
322 Output("""
323 if (strcmp(name, "inRefNum") == 0)
324 return Py_BuildValue("l", self->ob_spb.inRefNum);
325 else if (strcmp(name, "count") == 0)
326 return Py_BuildValue("l", self->ob_spb.count);
327 else if (strcmp(name, "milliseconds") == 0)
328 return Py_BuildValue("l", self->ob_spb.milliseconds);
329 else if (strcmp(name, "error") == 0)
330 return Py_BuildValue("h", self->ob_spb.error);""")
331
332
Guido van Rossum17448e21995-01-30 11:53:55 +0000333
334sndobject = SndObjectDefinition('SndChannel', 'SndCh', 'SndChannelPtr')
Jack Jansen52b38b71998-02-25 15:47:51 +0000335spbobject = SpbObjectDefinition('SPB', 'SPBObj', 'SPBPtr')
336spbgenerator = ManualGenerator("SPB", "return SPBObj_New();")
Jack Jansen77105a92001-08-23 13:51:46 +0000337module = MacModule('_Snd', 'Snd', includestuff, finalstuff, initstuff)
Guido van Rossum17448e21995-01-30 11:53:55 +0000338module.addobject(sndobject)
Jack Jansen52b38b71998-02-25 15:47:51 +0000339module.addobject(spbobject)
340module.add(spbgenerator)
Guido van Rossum17448e21995-01-30 11:53:55 +0000341
342
343# create lists of functions and object methods
344
345functions = []
346sndmethods = []
347
348
349# populate the lists
350
351execfile('sndgen.py')
352
353
354# add the functions and methods to the module and object, respectively
355
356for f in functions: module.add(f)
357for f in sndmethods: sndobject.add(f)
358
359
360# generate output
361
Jack Jansen77105a92001-08-23 13:51:46 +0000362SetOutputFileName('_Sndmodule.c')
Guido van Rossum17448e21995-01-30 11:53:55 +0000363module.generate()