Issue #7632: Fix a serious wrong output bug for string -> float conversion.
[python.git] / Mac / Modules / snd / sndsupport.py
blobcf0fa6ca5dedc938e9a8cc9c91632135d28c8673
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 <Carbon/Carbon.h>
21 """
23 initstuff = initstuff + """
24 """
27 # define types used for arguments (in addition to standard and macsupport types)
29 class SndChannelPtrType(OpaqueByValueType):
30 def declare(self, name):
31 # Initializing all SndChannelPtr objects to 0 saves
32 # special-casing NewSndChannel(), where it is formally an
33 # input-output parameter but we treat it as output-only
34 # (since Python users are not supposed to allocate memory)
35 Output("SndChannelPtr %s = 0;", name)
37 SndChannelPtr = SndChannelPtrType('SndChannelPtr', 'SndCh')
39 SndCommand = OpaqueType('SndCommand', 'SndCmd')
40 SndCommand_ptr = OpaqueType('SndCommand', 'SndCmd')
41 SndListHandle = OpaqueByValueType("SndListHandle", "ResObj")
42 SPBPtr = OpaqueByValueType("SPBPtr", "SPBObj")
43 ModalFilterUPP = FakeType("(ModalFilterUPP)0")
46 # NOTE: the following is pretty dangerous. For void pointers we pass buffer addresses
47 # but we have no way to check that the buffer is big enough. This is the same problem
48 # as in C, though (but Pythoneers may not be suspecting this...)
49 void_ptr = Type("void *", "w")
51 class SndCallBackType(InputOnlyType):
52 def __init__(self):
53 Type.__init__(self, 'PyObject*', 'O')
54 def getargsCheck(self, name):
55 Output("if (%s != Py_None && !PyCallable_Check(%s))", name, name)
56 OutLbrace()
57 Output('PyErr_SetString(PyExc_TypeError, "callback must be callable");')
58 Output("goto %s__error__;", name)
59 OutRbrace()
60 def passInput(self, name):
61 return "NewSndCallBackUPP(SndCh_UserRoutine)"
62 def cleanup(self, name):
63 # XXX This knows it is executing inside the SndNewChannel wrapper
64 Output("if (_res != NULL && %s != Py_None)", name)
65 OutLbrace()
66 Output("SndChannelObject *p = (SndChannelObject *)_res;")
67 Output("p->ob_itself->userInfo = (long)p;")
68 Output("Py_INCREF(%s);", name)
69 Output("p->ob_callback = %s;", name)
70 OutRbrace()
71 DedentLevel()
72 Output(" %s__error__: ;", name)
73 IndentLevel()
75 SndCallBackProcPtr = SndCallBackType()
76 SndCallBackUPP = SndCallBackProcPtr
78 SndCompletionProcPtr = FakeType('(SndCompletionProcPtr)0') # XXX
79 SndCompletionUPP = SndCompletionProcPtr
81 ##InOutBuf128 = FixedInputOutputBufferType(128)
82 StateBlock = StructInputOutputBufferType('StateBlock')
84 AudioSelectionPtr = FakeType('0') # XXX
86 ProcPtr = FakeType('0') # XXX
87 FilePlayCompletionUPP = FakeType('0') # XXX
89 SCStatus = StructOutputBufferType('SCStatus')
90 SMStatus = StructOutputBufferType('SMStatus')
91 CompressionInfo = StructOutputBufferType('CompressionInfo')
93 includestuff = includestuff + """
94 /* Convert a SndCommand argument */
95 static int
96 SndCmd_Convert(PyObject *v, SndCommand *pc)
98 int len;
99 pc->param1 = 0;
100 pc->param2 = 0;
101 if (PyTuple_Check(v)) {
102 if (PyArg_ParseTuple(v, "h|hl", &pc->cmd, &pc->param1, &pc->param2))
103 return 1;
104 PyErr_Clear();
105 return PyArg_ParseTuple(v, "Hhs#", &pc->cmd, &pc->param1, &pc->param2, &len);
107 return PyArg_Parse(v, "H", &pc->cmd);
110 static pascal void SndCh_UserRoutine(SndChannelPtr chan, SndCommand *cmd); /* Forward */
111 static pascal void SPB_completion(SPBPtr my_spb); /* Forward */
115 finalstuff = finalstuff + """
116 /* Routine passed to Py_AddPendingCall -- call the Python callback */
117 static int
118 SndCh_CallCallBack(void *arg)
120 SndChannelObject *p = (SndChannelObject *)arg;
121 PyObject *args;
122 PyObject *res;
123 args = Py_BuildValue("(O(hhl))",
124 p, p->ob_cmd.cmd, p->ob_cmd.param1, p->ob_cmd.param2);
125 res = PyEval_CallObject(p->ob_callback, args);
126 Py_DECREF(args);
127 if (res == NULL)
128 return -1;
129 Py_DECREF(res);
130 return 0;
133 /* Routine passed to NewSndChannel -- schedule a call to SndCh_CallCallBack */
134 static pascal void
135 SndCh_UserRoutine(SndChannelPtr chan, SndCommand *cmd)
137 SndChannelObject *p = (SndChannelObject *)(chan->userInfo);
138 if (p->ob_callback != NULL) {
139 long A5 = SetA5(p->ob_A5);
140 p->ob_cmd = *cmd;
141 Py_AddPendingCall(SndCh_CallCallBack, (void *)p);
142 SetA5(A5);
146 /* SPB callbacks - Schedule callbacks to Python */
147 static int
148 SPB_CallCallBack(void *arg)
150 SPBObject *p = (SPBObject *)arg;
151 PyObject *args;
152 PyObject *res;
154 if ( p->ob_thiscallback == 0 ) return 0;
155 args = Py_BuildValue("(O)", p);
156 res = PyEval_CallObject(p->ob_thiscallback, args);
157 p->ob_thiscallback = 0;
158 Py_DECREF(args);
159 if (res == NULL)
160 return -1;
161 Py_DECREF(res);
162 return 0;
165 static pascal void
166 SPB_completion(SPBPtr my_spb)
168 SPBObject *p = (SPBObject *)(my_spb->userLong);
170 if (p && p->ob_completion) {
171 long A5 = SetA5(p->ob_A5);
172 p->ob_thiscallback = p->ob_completion; /* Hope we cannot get two at the same time */
173 Py_AddPendingCall(SPB_CallCallBack, (void *)p);
174 SetA5(A5);
181 # create the module and object definition and link them
183 class SndObjectDefinition(PEP252Mixin, ObjectDefinition):
185 def outputStructMembers(self):
186 ObjectDefinition.outputStructMembers(self)
187 Output("/* Members used to implement callbacks: */")
188 Output("PyObject *ob_callback;")
189 Output("long ob_A5;");
190 Output("SndCommand ob_cmd;")
192 def outputInitStructMembers(self):
193 ObjectDefinition.outputInitStructMembers(self)
194 Output("it->ob_callback = NULL;")
195 Output("it->ob_A5 = SetCurrentA5();");
197 def outputCleanupStructMembers(self):
198 ObjectDefinition.outputCleanupStructMembers(self)
199 Output("Py_XDECREF(self->ob_callback);")
201 def outputFreeIt(self, itselfname):
202 Output("SndDisposeChannel(%s, 1);", itselfname)
204 def outputConvert(self):
205 pass # Not needed
209 class SpbObjectDefinition(PEP252Mixin, ObjectDefinition):
210 getsetlist = [
212 'inRefNum',
213 'return Py_BuildValue("l", self->ob_spb.inRefNum);',
214 'return -1 + PyArg_Parse(v, "l", &self->ob_spb.inRefNum);',
215 None,
216 ), (
217 'count',
218 'return Py_BuildValue("l", self->ob_spb.count);',
219 'return -1 + PyArg_Parse(v, "l", &self->ob_spb.count);',
220 None
221 ), (
222 'milliseconds',
223 'return Py_BuildValue("l", self->ob_spb.milliseconds);',
224 'return -1 + PyArg_Parse(v, "l", &self->ob_spb.milliseconds);',
225 None,
226 ), (
227 'error',
228 'return Py_BuildValue("h", self->ob_spb.error);',
229 None,
230 None
231 ), (
232 'completionRoutine',
233 None,
234 """self->ob_spb.completionRoutine = NewSICompletionUPP(SPB_completion);
235 self->ob_completion = v;
236 Py_INCREF(v);
237 return 0;""",
238 None,
241 def outputStructMembers(self):
242 Output("/* Members used to implement callbacks: */")
243 Output("PyObject *ob_completion;")
244 Output("PyObject *ob_interrupt;")
245 Output("PyObject *ob_thiscallback;");
246 Output("long ob_A5;")
247 Output("SPB ob_spb;")
249 def outputNew(self):
250 Output()
251 Output("%sPyObject *%s_New(void)", self.static, self.prefix)
252 OutLbrace()
253 Output("%s *it;", self.objecttype)
254 self.outputCheckNewArg()
255 Output("it = PyObject_NEW(%s, &%s);", self.objecttype, self.typename)
256 Output("if (it == NULL) return NULL;")
257 self.outputInitStructMembers()
258 Output("return (PyObject *)it;")
259 OutRbrace()
261 def outputInitStructMembers(self):
262 Output("it->ob_completion = NULL;")
263 Output("it->ob_interrupt = NULL;")
264 Output("it->ob_thiscallback = NULL;")
265 Output("it->ob_A5 = SetCurrentA5();")
266 Output("memset((char *)&it->ob_spb, 0, sizeof(it->ob_spb));")
267 Output("it->ob_spb.userLong = (long)it;")
269 def outputCleanupStructMembers(self):
270 ObjectDefinition.outputCleanupStructMembers(self)
271 Output("self->ob_spb.userLong = 0;")
272 Output("self->ob_thiscallback = 0;")
273 Output("Py_XDECREF(self->ob_completion);")
274 Output("Py_XDECREF(self->ob_interrupt);")
276 def outputConvert(self):
277 Output("%sint %s_Convert(PyObject *v, %s *p_itself)", self.static, self.prefix, self.itselftype)
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()
290 sndobject = SndObjectDefinition('SndChannel', 'SndCh', 'SndChannelPtr')
291 spbobject = SpbObjectDefinition('SPB', 'SPBObj', 'SPBPtr')
292 spbgenerator = ManualGenerator("SPB", "_res = SPBObj_New(); return _res;")
293 module = MacModule('_Snd', 'Snd', includestuff, finalstuff, initstuff)
294 module.addobject(sndobject)
295 module.addobject(spbobject)
296 module.add(spbgenerator)
299 # create lists of functions and object methods
301 functions = []
302 sndmethods = []
305 # populate the lists
307 execfile('sndgen.py')
310 # add the functions and methods to the module and object, respectively
312 for f in functions: module.add(f)
313 for f in sndmethods: sndobject.add(f)
316 # generate output
318 SetOutputFileName('_Sndmodule.c')
319 module.generate()