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
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
22 #include <OSUtils.h> /* for Set(Current)A5 */
24 #include <Carbon/Carbon.h>
28 initstuff
= initstuff
+ """
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
):
58 Type
.__init
__(self
, 'PyObject*', 'O')
59 def getargsCheck(self
, name
):
60 Output("if (%s != Py_None && !PyCallable_Check(%s))", name
, name
)
62 Output('PyErr_SetString(PyExc_TypeError, "callback must be callable");')
63 Output("goto %s__error__;", name
)
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
)
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
)
77 Output(" %s__error__: ;", name
)
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 /* Convert a SndCommand argument */
101 SndCmd_Convert(PyObject *v, SndCommand *pc)
106 if (PyTuple_Check(v)) {
107 if (PyArg_ParseTuple(v, "h|hl", &pc->cmd, &pc->param1, &pc->param2))
110 return PyArg_ParseTuple(v, "Hhs#", &pc->cmd, &pc->param1, &pc->param2, &len);
112 return PyArg_Parse(v, "H", &pc->cmd);
115 static pascal void SndCh_UserRoutine(SndChannelPtr chan, SndCommand *cmd); /* Forward */
116 static pascal void SPB_completion(SPBPtr my_spb); /* Forward */
120 finalstuff
= finalstuff
+ """
121 /* Routine passed to Py_AddPendingCall -- call the Python callback */
123 SndCh_CallCallBack(void *arg)
125 SndChannelObject *p = (SndChannelObject *)arg;
128 args = Py_BuildValue("(O(hhl))",
129 p, p->ob_cmd.cmd, p->ob_cmd.param1, p->ob_cmd.param2);
130 res = PyEval_CallObject(p->ob_callback, args);
138 /* Routine passed to NewSndChannel -- schedule a call to SndCh_CallCallBack */
140 SndCh_UserRoutine(SndChannelPtr chan, SndCommand *cmd)
142 SndChannelObject *p = (SndChannelObject *)(chan->userInfo);
143 if (p->ob_callback != NULL) {
144 long A5 = SetA5(p->ob_A5);
146 Py_AddPendingCall(SndCh_CallCallBack, (void *)p);
151 /* SPB callbacks - Schedule callbacks to Python */
153 SPB_CallCallBack(void *arg)
155 SPBObject *p = (SPBObject *)arg;
159 if ( p->ob_thiscallback == 0 ) return 0;
160 args = Py_BuildValue("(O)", p);
161 res = PyEval_CallObject(p->ob_thiscallback, args);
162 p->ob_thiscallback = 0;
171 SPB_completion(SPBPtr my_spb)
173 SPBObject *p = (SPBObject *)(my_spb->userLong);
175 if (p && p->ob_completion) {
176 long A5 = SetA5(p->ob_A5);
177 p->ob_thiscallback = p->ob_completion; /* Hope we cannot get two at the same time */
178 Py_AddPendingCall(SPB_CallCallBack, (void *)p);
186 # create the module and object definition and link them
188 class SndObjectDefinition(PEP252Mixin
, ObjectDefinition
):
190 def outputStructMembers(self
):
191 ObjectDefinition
.outputStructMembers(self
)
192 Output("/* Members used to implement callbacks: */")
193 Output("PyObject *ob_callback;")
194 Output("long ob_A5;");
195 Output("SndCommand ob_cmd;")
197 def outputInitStructMembers(self
):
198 ObjectDefinition
.outputInitStructMembers(self
)
199 Output("it->ob_callback = NULL;")
200 Output("it->ob_A5 = SetCurrentA5();");
202 def outputCleanupStructMembers(self
):
203 ObjectDefinition
.outputCleanupStructMembers(self
)
204 Output("Py_XDECREF(self->ob_callback);")
206 def outputFreeIt(self
, itselfname
):
207 Output("SndDisposeChannel(%s, 1);", itselfname
)
209 def outputConvert(self
):
214 class SpbObjectDefinition(PEP252Mixin
, ObjectDefinition
):
218 'return Py_BuildValue("l", self->ob_spb.inRefNum);',
219 'return -1 + PyArg_Parse(v, "l", &self->ob_spb.inRefNum);',
223 'return Py_BuildValue("l", self->ob_spb.count);',
224 'return -1 + PyArg_Parse(v, "l", &self->ob_spb.count);',
228 'return Py_BuildValue("l", self->ob_spb.milliseconds);',
229 'return -1 + PyArg_Parse(v, "l", &self->ob_spb.milliseconds);',
233 'return Py_BuildValue("h", self->ob_spb.error);',
239 """self->ob_spb.completionRoutine = NewSICompletionUPP(SPB_completion);
240 self->ob_completion = v;
246 def outputStructMembers(self
):
247 Output("/* Members used to implement callbacks: */")
248 Output("PyObject *ob_completion;")
249 Output("PyObject *ob_interrupt;")
250 Output("PyObject *ob_thiscallback;");
251 Output("long ob_A5;")
252 Output("SPB ob_spb;")
256 Output("%sPyObject *%s_New(void)", self
.static
, self
.prefix
)
258 Output("%s *it;", self
.objecttype
)
259 self
.outputCheckNewArg()
260 Output("it = PyObject_NEW(%s, &%s);", self
.objecttype
, self
.typename
)
261 Output("if (it == NULL) return NULL;")
262 self
.outputInitStructMembers()
263 Output("return (PyObject *)it;")
266 def outputInitStructMembers(self
):
267 Output("it->ob_completion = NULL;")
268 Output("it->ob_interrupt = NULL;")
269 Output("it->ob_thiscallback = NULL;")
270 Output("it->ob_A5 = SetCurrentA5();")
271 Output("memset((char *)&it->ob_spb, 0, sizeof(it->ob_spb));")
272 Output("it->ob_spb.userLong = (long)it;")
274 def outputCleanupStructMembers(self
):
275 ObjectDefinition
.outputCleanupStructMembers(self
)
276 Output("self->ob_spb.userLong = 0;")
277 Output("self->ob_thiscallback = 0;")
278 Output("Py_XDECREF(self->ob_completion);")
279 Output("Py_XDECREF(self->ob_interrupt);")
281 def outputConvert(self
):
282 Output("%sint %s_Convert(PyObject *v, %s *p_itself)", self
.static
, self
.prefix
, self
.itselftype
)
284 self
.outputCheckConvertArg()
285 Output("if (!%s_Check(v))", self
.prefix
)
287 Output('PyErr_SetString(PyExc_TypeError, "%s required");', self
.name
)
290 Output("*p_itself = &((%s *)v)->ob_spb;", self
.objecttype
)
295 sndobject
= SndObjectDefinition('SndChannel', 'SndCh', 'SndChannelPtr')
296 spbobject
= SpbObjectDefinition('SPB', 'SPBObj', 'SPBPtr')
297 spbgenerator
= ManualGenerator("SPB", "_res = SPBObj_New(); return _res;")
298 module
= MacModule('_Snd', 'Snd', includestuff
, finalstuff
, initstuff
)
299 module
.addobject(sndobject
)
300 module
.addobject(spbobject
)
301 module
.add(spbgenerator
)
304 # create lists of functions and object methods
312 execfile('sndgen.py')
315 # add the functions and methods to the module and object, respectively
317 for f
in functions
: module
.add(f
)
318 for f
in sndmethods
: sndobject
.add(f
)
323 SetOutputFileName('_Sndmodule.c')