| 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()
|
|---|