Bump version number to 2.4.2 to pick up the latest minor bug fixes.
[python/dscho.git] / Mac / Modules / snd / sndsupport.py
blob47c17cebe081c0f3a95818f575187dadcf2ebf1d
1 # 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).
6 from macsupport import *
9 # define our own function and module generators
11 class SndMixIn: pass
13 class SndFunction(SndMixIn, OSErrFunctionGenerator): pass
14 class SndMethod(SndMixIn, OSErrMethodGenerator): pass
17 # includestuff etc. are imported from macsupport
19 includestuff = includestuff + """
20 #ifdef WITHOUT_FRAMEWORKS
21 #include <Sound.h>
22 #include <OSUtils.h> /* for Set(Current)A5 */
23 #else
24 #include <Carbon/Carbon.h>
25 #endif
26 """
28 initstuff = initstuff + """
29 """
32 # define types used for arguments (in addition to standard and macsupport types)
34 class 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)
42 SndChannelPtr = SndChannelPtrType('SndChannelPtr', 'SndCh')
44 SndCommand = OpaqueType('SndCommand', 'SndCmd')
45 SndCommand_ptr = OpaqueType('SndCommand', 'SndCmd')
46 SndListHandle = OpaqueByValueType("SndListHandle", "ResObj")
47 SPBPtr = OpaqueByValueType("SPBPtr", "SPBObj")
48 ModalFilterUPP = FakeType("(ModalFilterUPP)0")
51 # NOTE: the following is pretty dangerous. For void pointers we pass buffer addresses
52 # but we have no way to check that the buffer is big enough. This is the same problem
53 # as in C, though (but Pythoneers may not be suspecting this...)
54 void_ptr = Type("void *", "w")
56 class SndCallBackType(InputOnlyType):
57 def __init__(self):
58 Type.__init__(self, 'PyObject*', 'O')
59 def getargsCheck(self, name):
60 Output("if (%s != Py_None && !PyCallable_Check(%s))", name, name)
61 OutLbrace()
62 Output('PyErr_SetString(PyExc_TypeError, "callback must be callable");')
63 Output("goto %s__error__;", name)
64 OutRbrace()
65 def passInput(self, name):
66 return "NewSndCallBackUPP(SndCh_UserRoutine)"
67 def cleanup(self, name):
68 # XXX This knows it is executing inside the SndNewChannel wrapper
69 Output("if (_res != NULL && %s != Py_None)", name)
70 OutLbrace()
71 Output("SndChannelObject *p = (SndChannelObject *)_res;")
72 Output("p->ob_itself->userInfo = (long)p;")
73 Output("Py_INCREF(%s);", name)
74 Output("p->ob_callback = %s;", name)
75 OutRbrace()
76 DedentLevel()
77 Output(" %s__error__: ;", name)
78 IndentLevel()
80 SndCallBackProcPtr = SndCallBackType()
81 SndCallBackUPP = SndCallBackProcPtr
83 SndCompletionProcPtr = FakeType('(SndCompletionProcPtr)0') # XXX
84 SndCompletionUPP = SndCompletionProcPtr
86 ##InOutBuf128 = FixedInputOutputBufferType(128)
87 StateBlock = StructInputOutputBufferType('StateBlock')
89 AudioSelectionPtr = FakeType('0') # XXX
91 ProcPtr = FakeType('0') # XXX
92 FilePlayCompletionUPP = FakeType('0') # XXX
94 SCStatus = StructOutputBufferType('SCStatus')
95 SMStatus = StructOutputBufferType('SMStatus')
96 CompressionInfo = StructOutputBufferType('CompressionInfo')
98 includestuff = includestuff + """
99 #if !TARGET_API_MAC_CARBON
100 /* Create a SndCommand object (an (int, int, int) tuple) */
101 static PyObject *
102 SndCmd_New(SndCommand *pc)
104 return Py_BuildValue("hhl", pc->cmd, pc->param1, pc->param2);
106 #endif
108 /* Convert a SndCommand argument */
109 static int
110 SndCmd_Convert(PyObject *v, SndCommand *pc)
112 int len;
113 pc->param1 = 0;
114 pc->param2 = 0;
115 if (PyTuple_Check(v)) {
116 if (PyArg_ParseTuple(v, "h|hl", &pc->cmd, &pc->param1, &pc->param2))
117 return 1;
118 PyErr_Clear();
119 return PyArg_ParseTuple(v, "Hhs#", &pc->cmd, &pc->param1, &pc->param2, &len);
121 return PyArg_Parse(v, "H", &pc->cmd);
124 static pascal void SndCh_UserRoutine(SndChannelPtr chan, SndCommand *cmd); /* Forward */
125 static pascal void SPB_completion(SPBPtr my_spb); /* Forward */
126 #if !TARGET_API_MAC_CARBON
127 static pascal void SPB_interrupt(SPBPtr my_spb); /* Forward */
128 #endif
132 finalstuff = finalstuff + """
133 /* Routine passed to Py_AddPendingCall -- call the Python callback */
134 static int
135 SndCh_CallCallBack(void *arg)
137 SndChannelObject *p = (SndChannelObject *)arg;
138 PyObject *args;
139 PyObject *res;
140 args = Py_BuildValue("(O(hhl))",
141 p, p->ob_cmd.cmd, p->ob_cmd.param1, p->ob_cmd.param2);
142 res = PyEval_CallObject(p->ob_callback, args);
143 Py_DECREF(args);
144 if (res == NULL)
145 return -1;
146 Py_DECREF(res);
147 return 0;
150 /* Routine passed to NewSndChannel -- schedule a call to SndCh_CallCallBack */
151 static pascal void
152 SndCh_UserRoutine(SndChannelPtr chan, SndCommand *cmd)
154 SndChannelObject *p = (SndChannelObject *)(chan->userInfo);
155 if (p->ob_callback != NULL) {
156 long A5 = SetA5(p->ob_A5);
157 p->ob_cmd = *cmd;
158 Py_AddPendingCall(SndCh_CallCallBack, (void *)p);
159 SetA5(A5);
163 /* SPB callbacks - Schedule callbacks to Python */
164 static int
165 SPB_CallCallBack(void *arg)
167 SPBObject *p = (SPBObject *)arg;
168 PyObject *args;
169 PyObject *res;
171 if ( p->ob_thiscallback == 0 ) return 0;
172 args = Py_BuildValue("(O)", p);
173 res = PyEval_CallObject(p->ob_thiscallback, args);
174 p->ob_thiscallback = 0;
175 Py_DECREF(args);
176 if (res == NULL)
177 return -1;
178 Py_DECREF(res);
179 return 0;
182 static pascal void
183 SPB_completion(SPBPtr my_spb)
185 SPBObject *p = (SPBObject *)(my_spb->userLong);
187 if (p && p->ob_completion) {
188 long A5 = SetA5(p->ob_A5);
189 p->ob_thiscallback = p->ob_completion; /* Hope we cannot get two at the same time */
190 Py_AddPendingCall(SPB_CallCallBack, (void *)p);
191 SetA5(A5);
195 #if !TARGET_API_MAC_CARBON
196 static pascal void
197 SPB_interrupt(SPBPtr my_spb)
199 SPBObject *p = (SPBObject *)(my_spb->userLong);
201 if (p && p->ob_interrupt) {
202 long A5 = SetA5(p->ob_A5);
203 p->ob_thiscallback = p->ob_interrupt; /* Hope we cannot get two at the same time */
204 Py_AddPendingCall(SPB_CallCallBack, (void *)p);
205 SetA5(A5);
208 #endif
212 # create the module and object definition and link them
214 class SndObjectDefinition(ObjectDefinition):
216 def outputStructMembers(self):
217 ObjectDefinition.outputStructMembers(self)
218 Output("/* Members used to implement callbacks: */")
219 Output("PyObject *ob_callback;")
220 Output("long ob_A5;");
221 Output("SndCommand ob_cmd;")
223 def outputInitStructMembers(self):
224 ObjectDefinition.outputInitStructMembers(self)
225 Output("it->ob_callback = NULL;")
226 Output("it->ob_A5 = SetCurrentA5();");
228 def outputCleanupStructMembers(self):
229 ObjectDefinition.outputCleanupStructMembers(self)
230 Output("Py_XDECREF(self->ob_callback);")
232 def outputFreeIt(self, itselfname):
233 Output("SndDisposeChannel(%s, 1);", itselfname)
235 def outputConvert(self):
236 pass # Not needed
240 class SpbObjectDefinition(ObjectDefinition):
242 def outputStructMembers(self):
243 Output("/* Members used to implement callbacks: */")
244 Output("PyObject *ob_completion;")
245 Output("PyObject *ob_interrupt;")
246 Output("PyObject *ob_thiscallback;");
247 Output("long ob_A5;")
248 Output("SPB ob_spb;")
250 def outputNew(self):
251 Output()
252 Output("%sPyObject *%s_New(void)", self.static, self.prefix)
253 OutLbrace()
254 Output("%s *it;", self.objecttype)
255 self.outputCheckNewArg()
256 Output("it = PyObject_NEW(%s, &%s);", self.objecttype, self.typename)
257 Output("if (it == NULL) return NULL;")
258 self.outputInitStructMembers()
259 Output("return (PyObject *)it;")
260 OutRbrace()
262 def outputInitStructMembers(self):
263 Output("it->ob_completion = NULL;")
264 Output("it->ob_interrupt = NULL;")
265 Output("it->ob_thiscallback = NULL;")
266 Output("it->ob_A5 = SetCurrentA5();")
267 Output("memset((char *)&it->ob_spb, 0, sizeof(it->ob_spb));")
268 Output("it->ob_spb.userLong = (long)it;")
270 def outputCleanupStructMembers(self):
271 ObjectDefinition.outputCleanupStructMembers(self)
272 Output("self->ob_spb.userLong = 0;")
273 Output("self->ob_thiscallback = 0;")
274 Output("Py_XDECREF(self->ob_completion);")
275 Output("Py_XDECREF(self->ob_interrupt);")
277 def outputConvert(self):
278 Output("%sint %s_Convert(PyObject *v, %s *p_itself)", self.static, self.prefix, self.itselftype)
279 OutLbrace()
280 self.outputCheckConvertArg()
281 Output("if (!%s_Check(v))", self.prefix)
282 OutLbrace()
283 Output('PyErr_SetString(PyExc_TypeError, "%s required");', self.name)
284 Output("return 0;")
285 OutRbrace()
286 Output("*p_itself = &((%s *)v)->ob_spb;", self.objecttype)
287 Output("return 1;")
288 OutRbrace()
290 def outputSetattr(self):
291 Output()
292 Output("static int %s_setattr(%s *self, char *name, PyObject *value)",
293 self.prefix, self.objecttype)
294 OutLbrace()
295 self.outputSetattrBody()
296 OutRbrace()
298 def outputSetattrBody(self):
299 Output("""
300 int rv = 0;
302 if (strcmp(name, "inRefNum") == 0)
303 rv = PyArg_Parse(value, "l", &self->ob_spb.inRefNum);
304 else if (strcmp(name, "count") == 0)
305 rv = PyArg_Parse(value, "l", &self->ob_spb.count);
306 else if (strcmp(name, "milliseconds") == 0)
307 rv = PyArg_Parse(value, "l", &self->ob_spb.milliseconds);
308 else if (strcmp(name, "buffer") == 0)
309 rv = PyArg_Parse(value, "w#", &self->ob_spb.bufferPtr, &self->ob_spb.bufferLength);
310 else if (strcmp(name, "completionRoutine") == 0) {
311 self->ob_spb.completionRoutine = NewSICompletionUPP(SPB_completion);
312 self->ob_completion = value;
313 Py_INCREF(value);
314 rv = 1;
315 #if !TARGET_API_MAC_CARBON
316 } else if (strcmp(name, "interruptRoutine") == 0) {
317 self->ob_spb.completionRoutine = NewSIInterruptUPP(SPB_interrupt);
318 self->ob_interrupt = value;
319 Py_INCREF(value);
320 rv = 1;
321 #endif
323 if ( rv ) return 0;
324 else return -1;""")
326 def outputGetattrHook(self):
327 Output("""
328 if (strcmp(name, "inRefNum") == 0)
329 return Py_BuildValue("l", self->ob_spb.inRefNum);
330 else if (strcmp(name, "count") == 0)
331 return Py_BuildValue("l", self->ob_spb.count);
332 else if (strcmp(name, "milliseconds") == 0)
333 return Py_BuildValue("l", self->ob_spb.milliseconds);
334 else if (strcmp(name, "error") == 0)
335 return Py_BuildValue("h", self->ob_spb.error);""")
339 sndobject = SndObjectDefinition('SndChannel', 'SndCh', 'SndChannelPtr')
340 spbobject = SpbObjectDefinition('SPB', 'SPBObj', 'SPBPtr')
341 spbgenerator = ManualGenerator("SPB", "_res = SPBObj_New(); return _res;")
342 module = MacModule('_Snd', 'Snd', includestuff, finalstuff, initstuff)
343 module.addobject(sndobject)
344 module.addobject(spbobject)
345 module.add(spbgenerator)
348 # create lists of functions and object methods
350 functions = []
351 sndmethods = []
354 # populate the lists
356 execfile('sndgen.py')
359 # add the functions and methods to the module and object, respectively
361 for f in functions: module.add(f)
362 for f in sndmethods: sndobject.add(f)
365 # generate output
367 SetOutputFileName('_Sndmodule.c')
368 module.generate()