The 0.5 release happened on 2/15, not on 2/14. :-)
[python/dscho.git] / Mac / Modules / snd / sndsupport.py
blob9856e79a1e85b6eefa0e78fa7fc3fa6317a3635d
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 #include <Sound.h>
22 #ifndef HAVE_UNIVERSAL_HEADERS
23 #define SndCallBackUPP ProcPtr
24 #define NewSndCallBackProc(x) ((SndCallBackProcPtr)(x))
25 #define SndListHandle Handle
26 #endif
27 """
29 initstuff = initstuff + """
30 """
33 # define types used for arguments (in addition to standard and macsupport types)
35 class SndChannelPtrType(OpaqueByValueType):
36 def declare(self, name):
37 # Initializing all SndChannelPtr objects to 0 saves
38 # special-casing NewSndChannel(), where it is formally an
39 # input-output parameter but we treat it as output-only
40 # (since Python users are not supposed to allocate memory)
41 Output("SndChannelPtr %s = 0;", name)
43 SndChannelPtr = SndChannelPtrType('SndChannelPtr', 'SndCh')
45 SndCommand = OpaqueType('SndCommand', 'SndCmd')
46 SndCommand_ptr = OpaqueType('SndCommand', 'SndCmd')
47 SndListHandle = OpaqueByValueType("SndListHandle", "ResObj")
48 SPBPtr = OpaqueByValueType("SPBPtr", "SPBObj")
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 "NewSndCallBackProc(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 #include <OSUtils.h> /* for Set(Current)A5 */
101 /* Create a SndCommand object (an (int, int, int) tuple) */
102 static PyObject *
103 SndCmd_New(SndCommand *pc)
105 return Py_BuildValue("hhl", pc->cmd, pc->param1, pc->param2);
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 static pascal void SPB_interrupt(SPBPtr my_spb); /* Forward */
130 finalstuff = finalstuff + """
131 /* Routine passed to Py_AddPendingCall -- call the Python callback */
132 static int
133 SndCh_CallCallBack(arg)
134 void *arg;
136 SndChannelObject *p = (SndChannelObject *)arg;
137 PyObject *args;
138 PyObject *res;
139 args = Py_BuildValue("(O(hhl))",
140 p, p->ob_cmd.cmd, p->ob_cmd.param1, p->ob_cmd.param2);
141 res = PyEval_CallObject(p->ob_callback, args);
142 Py_DECREF(args);
143 if (res == NULL)
144 return -1;
145 Py_DECREF(res);
146 return 0;
149 /* Routine passed to NewSndChannel -- schedule a call to SndCh_CallCallBack */
150 static pascal void
151 SndCh_UserRoutine(SndChannelPtr chan, SndCommand *cmd)
153 SndChannelObject *p = (SndChannelObject *)(chan->userInfo);
154 if (p->ob_callback != NULL) {
155 long A5 = SetA5(p->ob_A5);
156 p->ob_cmd = *cmd;
157 Py_AddPendingCall(SndCh_CallCallBack, (void *)p);
158 SetA5(A5);
162 /* SPB callbacks - Schedule callbacks to Python */
163 static int
164 SPB_CallCallBack(arg)
165 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 static pascal void
196 SPB_interrupt(SPBPtr my_spb)
198 SPBObject *p = (SPBObject *)(my_spb->userLong);
200 if (p && p->ob_interrupt) {
201 long A5 = SetA5(p->ob_A5);
202 p->ob_thiscallback = p->ob_interrupt; /* Hope we cannot get two at the same time */
203 Py_AddPendingCall(SPB_CallCallBack, (void *)p);
204 SetA5(A5);
210 # create the module and object definition and link them
212 class SndObjectDefinition(ObjectDefinition):
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;")
221 def outputInitStructMembers(self):
222 ObjectDefinition.outputInitStructMembers(self)
223 Output("it->ob_callback = NULL;")
224 Output("it->ob_A5 = SetCurrentA5();");
226 def outputCleanupStructMembers(self):
227 ObjectDefinition.outputCleanupStructMembers(self)
228 Output("Py_XDECREF(self->ob_callback);")
230 def outputFreeIt(self, itselfname):
231 Output("SndDisposeChannel(%s, 1);", itselfname)
235 class SpbObjectDefinition(ObjectDefinition):
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;")
245 def outputNew(self):
246 Output()
247 Output("%sPyObject *%s_New()", self.static, self.prefix)
248 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()
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;")
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);")
272 def outputConvert(self):
273 Output("%s%s_Convert(v, p_itself)", self.static, self.prefix)
274 IndentLevel()
275 Output("PyObject *v;")
276 Output("%s *p_itself;", self.itselftype)
277 DedentLevel()
278 OutLbrace()
279 self.outputCheckConvertArg()
280 Output("if (!%s_Check(v))", self.prefix)
281 OutLbrace()
282 Output('PyErr_SetString(PyExc_TypeError, "%s required");', self.name)
283 Output("return 0;")
284 OutRbrace()
285 Output("*p_itself = &((%s *)v)->ob_spb;", self.objecttype)
286 Output("return 1;")
287 OutRbrace()
289 def outputSetattr(self):
290 Output()
291 Output("static int %s_setattr(self, name, value)", self.prefix)
292 IndentLevel()
293 Output("%s *self;", self.objecttype)
294 Output("char *name;")
295 Output("PyObject *value;")
296 DedentLevel()
297 OutLbrace()
298 self.outputSetattrBody()
299 OutRbrace()
301 def outputSetattrBody(self):
302 Output("""
303 int rv = 0;
305 if (strcmp(name, "inRefNum") == 0)
306 rv = PyArg_Parse(value, "l", &self->ob_spb.inRefNum);
307 else if (strcmp(name, "count") == 0)
308 rv = PyArg_Parse(value, "l", &self->ob_spb.count);
309 else if (strcmp(name, "milliseconds") == 0)
310 rv = PyArg_Parse(value, "l", &self->ob_spb.milliseconds);
311 else if (strcmp(name, "buffer") == 0)
312 rv = PyArg_Parse(value, "w#", &self->ob_spb.bufferPtr, &self->ob_spb.bufferLength);
313 else if (strcmp(name, "completionRoutine") == 0) {
314 self->ob_spb.completionRoutine = NewSICompletionProc(SPB_completion);
315 self->ob_completion = value;
316 Py_INCREF(value);
317 rv = 1;
318 } else if (strcmp(name, "interruptRoutine") == 0) {
319 self->ob_spb.completionRoutine = NewSIInterruptProc(SPB_interrupt);
320 self->ob_interrupt = value;
321 Py_INCREF(value);
322 rv = 1;
324 if ( rv ) return 0;
325 else return -1;""")
327 def outputGetattrHook(self):
328 Output("""
329 if (strcmp(name, "inRefNum") == 0)
330 return Py_BuildValue("l", self->ob_spb.inRefNum);
331 else if (strcmp(name, "count") == 0)
332 return Py_BuildValue("l", self->ob_spb.count);
333 else if (strcmp(name, "milliseconds") == 0)
334 return Py_BuildValue("l", self->ob_spb.milliseconds);
335 else if (strcmp(name, "error") == 0)
336 return Py_BuildValue("h", self->ob_spb.error);""")
340 sndobject = SndObjectDefinition('SndChannel', 'SndCh', 'SndChannelPtr')
341 spbobject = SpbObjectDefinition('SPB', 'SPBObj', 'SPBPtr')
342 spbgenerator = ManualGenerator("SPB", "return SPBObj_New();")
343 module = MacModule('Snd', 'Snd', includestuff, finalstuff, initstuff)
344 module.addobject(sndobject)
345 module.addobject(spbobject)
346 module.add(spbgenerator)
349 # create lists of functions and object methods
351 functions = []
352 sndmethods = []
355 # populate the lists
357 execfile('sndgen.py')
360 # add the functions and methods to the module and object, respectively
362 for f in functions: module.add(f)
363 for f in sndmethods: sndobject.add(f)
366 # generate output
368 SetOutputFileName('Sndmodule.c')
369 module.generate()