# This script generates the Sound interface for Python. # It uses the "bgen" package to generate C code. # It execs the file sndgen.py which contain the function definitions # (sndgen.py was generated by sndscan.py, scanning the header file). from macsupport import * # define our own function and module generators class SndMixIn: pass class SndFunction(SndMixIn, OSErrFunctionGenerator): pass class SndMethod(SndMixIn, OSErrMethodGenerator): pass # includestuff etc. are imported from macsupport includestuff = includestuff + """ #include #ifndef HAVE_UNIVERSAL_HEADERS #define SndCallBackUPP ProcPtr #define NewSndCallBackProc(x) ((SndCallBackProcPtr)(x)) #define SndListHandle Handle #endif """ initstuff = initstuff + """ """ # define types used for arguments (in addition to standard and macsupport types) class SndChannelPtrType(OpaqueByValueType): def declare(self, name): # Initializing all SndChannelPtr objects to 0 saves # special-casing NewSndChannel(), where it is formally an # input-output parameter but we treat it as output-only # (since Python users are not supposed to allocate memory) Output("SndChannelPtr %s = 0;", name) SndChannelPtr = SndChannelPtrType('SndChannelPtr', 'SndCh') SndCommand = OpaqueType('SndCommand', 'SndCmd') SndCommand_ptr = OpaqueType('SndCommand', 'SndCmd') SndListHandle = OpaqueByValueType("SndListHandle", "ResObj") class SndCallBackType(InputOnlyType): def __init__(self): Type.__init__(self, 'PyObject*', 'O') def getargsCheck(self, name): Output("if (%s != Py_None && !PyCallable_Check(%s))", name, name) OutLbrace() Output('PyErr_SetString(PyExc_TypeError, "callback must be callable");') Output("goto %s__error__;", name) OutRbrace() def passInput(self, name): return "NewSndCallBackProc(SndCh_UserRoutine)" def cleanup(self, name): # XXX This knows it is executing inside the SndNewChannel wrapper Output("if (_res != NULL && %s != Py_None)", name) OutLbrace() Output("SndChannelObject *p = (SndChannelObject *)_res;") Output("p->ob_itself->userInfo = (long)p;") Output("Py_INCREF(%s);", name) Output("p->ob_callback = %s;", name) OutRbrace() DedentLevel() Output(" %s__error__: ;", name) IndentLevel() SndCallBackProcPtr = SndCallBackType() SndCompletionProcPtr = FakeType('(SndCompletionProcPtr)0') # XXX NumVersion = OpaqueByValueType('NumVersion', 'NumVer') InOutBuf128 = FixedInputOutputBufferType(128) AudioSelectionPtr = FakeType('0') # XXX ProcPtr = FakeType('0') # XXX SCStatus = StructOutputBufferType('SCStatus') SMStatus = StructOutputBufferType('SMStatus') includestuff = includestuff + """ #include /* for Set(Current)A5 */ /* Create a SndCommand object (an (int, int, int) tuple) */ static PyObject * SndCmd_New(SndCommand *pc) { return Py_BuildValue("hhl", pc->cmd, pc->param1, pc->param2); } /* Convert a SndCommand argument */ static int SndCmd_Convert(PyObject *v, SndCommand *pc) { int len; pc->param1 = 0; pc->param2 = 0; if (PyTuple_Check(v)) { if (PyArg_ParseTuple(v, "h|hl", &pc->cmd, &pc->param1, &pc->param2)) return 1; PyErr_Clear(); return PyArg_ParseTuple(v, "hhs#", &pc->cmd, &pc->param1, &pc->param2, &len); } return PyArg_Parse(v, "h", &pc->cmd); } /* Create a NumVersion object (a quintuple of integers) */ static PyObject * NumVer_New(NumVersion nv) { return Py_BuildValue("iiiii", nv.majorRev, #ifdef THINK_C nv.minorRev, nv.bugFixRev, #else (nv.minorAndBugRev>>4) & 0xf, nv.minorAndBugRev & 0xf, #endif nv.stage, nv.nonRelRev); } static pascal void SndCh_UserRoutine(SndChannelPtr chan, SndCommand *cmd); /* Forward */ """ finalstuff = finalstuff + """ /* Routine passed to Py_AddPendingCall -- call the Python callback */ static int SndCh_CallCallBack(arg) void *arg; { SndChannelObject *p = (SndChannelObject *)arg; PyObject *args; PyObject *res; args = Py_BuildValue("(O(hhl))", p, p->ob_cmd.cmd, p->ob_cmd.param1, p->ob_cmd.param2); res = PyEval_CallObject(p->ob_callback, args); Py_DECREF(args); if (res == NULL) return -1; Py_DECREF(res); return 0; } /* Routine passed to NewSndChannel -- schedule a call to SndCh_CallCallBack */ static pascal void SndCh_UserRoutine(SndChannelPtr chan, SndCommand *cmd) { SndChannelObject *p = (SndChannelObject *)(chan->userInfo); if (p->ob_callback != NULL) { long A5 = SetA5(p->ob_A5); p->ob_cmd = *cmd; Py_AddPendingCall(SndCh_CallCallBack, (void *)p); SetA5(A5); } } """ # create the module and object definition and link them class SndObjectDefinition(ObjectDefinition): def outputStructMembers(self): ObjectDefinition.outputStructMembers(self) Output("/* Members used to implement callbacks: */") Output("PyObject *ob_callback;") Output("long ob_A5;"); Output("SndCommand ob_cmd;") def outputInitStructMembers(self): ObjectDefinition.outputInitStructMembers(self) Output("it->ob_callback = NULL;") Output("it->ob_A5 = SetCurrentA5();"); def outputCleanupStructMembers(self): ObjectDefinition.outputCleanupStructMembers(self) Output("Py_XDECREF(self->ob_callback);") def outputFreeIt(self, itselfname): Output("SndDisposeChannel(%s, 1);", itselfname) sndobject = SndObjectDefinition('SndChannel', 'SndCh', 'SndChannelPtr') module = MacModule('Snd', 'Snd', includestuff, finalstuff, initstuff) module.addobject(sndobject) # create lists of functions and object methods functions = [] sndmethods = [] # populate the lists execfile('sndgen.py') # add the functions and methods to the module and object, respectively for f in functions: module.add(f) for f in sndmethods: sndobject.add(f) # generate output SetOutputFileName('Sndmodule.c') module.generate()