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).
|
---|
5 |
|
---|
6 | from macsupport import *
|
---|
7 |
|
---|
8 |
|
---|
9 | # define our own function and module generators
|
---|
10 |
|
---|
11 | class SndMixIn: pass
|
---|
12 |
|
---|
13 | class SndFunction(SndMixIn, OSErrFunctionGenerator): pass
|
---|
14 | class SndMethod(SndMixIn, OSErrMethodGenerator): pass
|
---|
15 |
|
---|
16 |
|
---|
17 | # includestuff etc. are imported from macsupport
|
---|
18 |
|
---|
19 | includestuff = includestuff + """
|
---|
20 | #include <Carbon/Carbon.h>
|
---|
21 | """
|
---|
22 |
|
---|
23 | initstuff = initstuff + """
|
---|
24 | """
|
---|
25 |
|
---|
26 |
|
---|
27 | # define types used for arguments (in addition to standard and macsupport types)
|
---|
28 |
|
---|
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)
|
---|
36 |
|
---|
37 | SndChannelPtr = SndChannelPtrType('SndChannelPtr', 'SndCh')
|
---|
38 |
|
---|
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")
|
---|
44 |
|
---|
45 | #
|
---|
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")
|
---|
50 |
|
---|
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()
|
---|
74 |
|
---|
75 | SndCallBackProcPtr = SndCallBackType()
|
---|
76 | SndCallBackUPP = SndCallBackProcPtr
|
---|
77 |
|
---|
78 | SndCompletionProcPtr = FakeType('(SndCompletionProcPtr)0') # XXX
|
---|
79 | SndCompletionUPP = SndCompletionProcPtr
|
---|
80 |
|
---|
81 | ##InOutBuf128 = FixedInputOutputBufferType(128)
|
---|
82 | StateBlock = StructInputOutputBufferType('StateBlock')
|
---|
83 |
|
---|
84 | AudioSelectionPtr = FakeType('0') # XXX
|
---|
85 |
|
---|
86 | ProcPtr = FakeType('0') # XXX
|
---|
87 | FilePlayCompletionUPP = FakeType('0') # XXX
|
---|
88 |
|
---|
89 | SCStatus = StructOutputBufferType('SCStatus')
|
---|
90 | SMStatus = StructOutputBufferType('SMStatus')
|
---|
91 | CompressionInfo = StructOutputBufferType('CompressionInfo')
|
---|
92 |
|
---|
93 | includestuff = includestuff + """
|
---|
94 | /* Convert a SndCommand argument */
|
---|
95 | static int
|
---|
96 | SndCmd_Convert(PyObject *v, SndCommand *pc)
|
---|
97 | {
|
---|
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);
|
---|
106 | }
|
---|
107 | return PyArg_Parse(v, "H", &pc->cmd);
|
---|
108 | }
|
---|
109 |
|
---|
110 | static pascal void SndCh_UserRoutine(SndChannelPtr chan, SndCommand *cmd); /* Forward */
|
---|
111 | static pascal void SPB_completion(SPBPtr my_spb); /* Forward */
|
---|
112 | """
|
---|
113 |
|
---|
114 |
|
---|
115 | finalstuff = finalstuff + """
|
---|
116 | /* Routine passed to Py_AddPendingCall -- call the Python callback */
|
---|
117 | static int
|
---|
118 | SndCh_CallCallBack(void *arg)
|
---|
119 | {
|
---|
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;
|
---|
131 | }
|
---|
132 |
|
---|
133 | /* Routine passed to NewSndChannel -- schedule a call to SndCh_CallCallBack */
|
---|
134 | static pascal void
|
---|
135 | SndCh_UserRoutine(SndChannelPtr chan, SndCommand *cmd)
|
---|
136 | {
|
---|
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);
|
---|
143 | }
|
---|
144 | }
|
---|
145 |
|
---|
146 | /* SPB callbacks - Schedule callbacks to Python */
|
---|
147 | static int
|
---|
148 | SPB_CallCallBack(void *arg)
|
---|
149 | {
|
---|
150 | SPBObject *p = (SPBObject *)arg;
|
---|
151 | PyObject *args;
|
---|
152 | PyObject *res;
|
---|
153 |
|
---|
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;
|
---|
163 | }
|
---|
164 |
|
---|
165 | static pascal void
|
---|
166 | SPB_completion(SPBPtr my_spb)
|
---|
167 | {
|
---|
168 | SPBObject *p = (SPBObject *)(my_spb->userLong);
|
---|
169 |
|
---|
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);
|
---|
175 | }
|
---|
176 | }
|
---|
177 |
|
---|
178 | """
|
---|
179 |
|
---|
180 |
|
---|
181 | # create the module and object definition and link them
|
---|
182 |
|
---|
183 | class SndObjectDefinition(PEP252Mixin, ObjectDefinition):
|
---|
184 |
|
---|
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;")
|
---|
191 |
|
---|
192 | def outputInitStructMembers(self):
|
---|
193 | ObjectDefinition.outputInitStructMembers(self)
|
---|
194 | Output("it->ob_callback = NULL;")
|
---|
195 | Output("it->ob_A5 = SetCurrentA5();");
|
---|
196 |
|
---|
197 | def outputCleanupStructMembers(self):
|
---|
198 | ObjectDefinition.outputCleanupStructMembers(self)
|
---|
199 | Output("Py_XDECREF(self->ob_callback);")
|
---|
200 |
|
---|
201 | def outputFreeIt(self, itselfname):
|
---|
202 | Output("SndDisposeChannel(%s, 1);", itselfname)
|
---|
203 |
|
---|
204 | def outputConvert(self):
|
---|
205 | pass # Not needed
|
---|
206 |
|
---|
207 | #
|
---|
208 |
|
---|
209 | class SpbObjectDefinition(PEP252Mixin, ObjectDefinition):
|
---|
210 | getsetlist = [
|
---|
211 | (
|
---|
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,
|
---|
239 | )]
|
---|
240 |
|
---|
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;")
|
---|
248 |
|
---|
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()
|
---|
260 |
|
---|
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;")
|
---|
268 |
|
---|
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);")
|
---|
275 |
|
---|
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()
|
---|
288 |
|
---|
289 |
|
---|
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)
|
---|
297 |
|
---|
298 |
|
---|
299 | # create lists of functions and object methods
|
---|
300 |
|
---|
301 | functions = []
|
---|
302 | sndmethods = []
|
---|
303 |
|
---|
304 |
|
---|
305 | # populate the lists
|
---|
306 |
|
---|
307 | execfile('sndgen.py')
|
---|
308 |
|
---|
309 |
|
---|
310 | # add the functions and methods to the module and object, respectively
|
---|
311 |
|
---|
312 | for f in functions: module.add(f)
|
---|
313 | for f in sndmethods: sndobject.add(f)
|
---|
314 |
|
---|
315 |
|
---|
316 | # generate output
|
---|
317 |
|
---|
318 | SetOutputFileName('_Sndmodule.c')
|
---|
319 | module.generate()
|
---|