diff options
author | Jack Jansen <jack.jansen@cwi.nl> | 1998-02-25 15:47:51 (GMT) |
---|---|---|
committer | Jack Jansen <jack.jansen@cwi.nl> | 1998-02-25 15:47:51 (GMT) |
commit | 52b38b795b0a60d5667a7396322f3d5128340c6d (patch) | |
tree | 3c059cead440796d53f56aa4df2fbf55db2c079f /Mac/Modules/snd | |
parent | e742a82067c29786287ce8c6500b68220e9921de (diff) | |
download | cpython-52b38b795b0a60d5667a7396322f3d5128340c6d.zip cpython-52b38b795b0a60d5667a7396322f3d5128340c6d.tar.gz cpython-52b38b795b0a60d5667a7396322f3d5128340c6d.tar.bz2 |
Support for sound input added. The interface is even worse than the
sound-output interface, so this needs a Python wrapper shortly.
Diffstat (limited to 'Mac/Modules/snd')
-rw-r--r-- | Mac/Modules/snd/Sndmodule.c | 278 | ||||
-rw-r--r-- | Mac/Modules/snd/sndscan.py | 17 | ||||
-rw-r--r-- | Mac/Modules/snd/sndsupport.py | 162 |
3 files changed, 448 insertions, 9 deletions
diff --git a/Mac/Modules/snd/Sndmodule.c b/Mac/Modules/snd/Sndmodule.c index 06031ab..accb563 100644 --- a/Mac/Modules/snd/Sndmodule.c +++ b/Mac/Modules/snd/Sndmodule.c @@ -76,6 +76,8 @@ SndCmd_Convert(PyObject *v, SndCommand *pc) } static pascal void SndCh_UserRoutine(SndChannelPtr chan, SndCommand *cmd); /* Forward */ +static pascal void SPB_completion(SPBPtr my_spb); /* Forward */ +static pascal void SPB_interrupt(SPBPtr my_spb); /* Forward */ static PyObject *Snd_Error; @@ -315,6 +317,133 @@ staticforward PyTypeObject SndChannel_Type = { /* ------------------- End object type SndChannel ------------------- */ +/* ------------------------ Object type SPB ------------------------- */ + +staticforward PyTypeObject SPB_Type; + +#define SPBObj_Check(x) ((x)->ob_type == &SPB_Type) + +typedef struct SPBObject { + PyObject_HEAD + /* Members used to implement callbacks: */ + PyObject *ob_completion; + PyObject *ob_interrupt; + PyObject *ob_thiscallback; + long ob_A5; + SPB ob_spb; +} SPBObject; + +static PyObject *SPBObj_New() +{ + SPBObject *it; + it = PyObject_NEW(SPBObject, &SPB_Type); + if (it == NULL) return NULL; + it->ob_completion = NULL; + it->ob_interrupt = NULL; + it->ob_thiscallback = NULL; + it->ob_A5 = SetCurrentA5(); + memset((char *)&it->ob_spb, 0, sizeof(it->ob_spb)); + it->ob_spb.userLong = (long)it; + return (PyObject *)it; +} +static SPBObj_Convert(v, p_itself) + PyObject *v; + SPBPtr *p_itself; +{ + if (!SPBObj_Check(v)) + { + PyErr_SetString(PyExc_TypeError, "SPB required"); + return 0; + } + *p_itself = &((SPBObject *)v)->ob_spb; + return 1; +} + +static void SPBObj_dealloc(self) + SPBObject *self; +{ + /* Cleanup of self->ob_itself goes here */ + self->ob_spb.userLong = 0; + self->ob_thiscallback = 0; + Py_XDECREF(self->ob_completion); + Py_XDECREF(self->ob_interrupt); + PyMem_DEL(self); +} + +static PyMethodDef SPBObj_methods[] = { + {NULL, NULL, 0} +}; + +static PyMethodChain SPBObj_chain = { SPBObj_methods, NULL }; + +static PyObject *SPBObj_getattr(self, name) + SPBObject *self; + char *name; +{ + + if (strcmp(name, "inRefNum") == 0) + return Py_BuildValue("l", self->ob_spb.inRefNum); + else if (strcmp(name, "count") == 0) + return Py_BuildValue("l", self->ob_spb.count); + else if (strcmp(name, "milliseconds") == 0) + return Py_BuildValue("l", self->ob_spb.milliseconds); + else if (strcmp(name, "error") == 0) + return Py_BuildValue("h", self->ob_spb.error); + return Py_FindMethodInChain(&SPBObj_chain, (PyObject *)self, name); +} + +static int SPBObj_setattr(self, name, value) + SPBObject *self; + char *name; + PyObject *value; +{ + + if (strcmp(name, "inRefNum") == 0) + return PyArg_Parse(value, "l", &self->ob_spb.inRefNum); + else if (strcmp(name, "count") == 0) + return PyArg_Parse(value, "l", &self->ob_spb.count); + else if (strcmp(name, "milliseconds") == 0) + return PyArg_Parse(value, "l", &self->ob_spb.milliseconds); + else if (strcmp(name, "buffer") == 0) + return PyArg_Parse(value, "w#", &self->ob_spb.bufferPtr, &self->ob_spb.bufferLength); + else if (strcmp(name, "completionRoutine") == 0) { + self->ob_spb.completionRoutine = NewSICompletionProc(SPB_completion); + self->ob_completion = value; + Py_INCREF(value); + return 0; + } else if (strcmp(name, "interruptRoutine") == 0) { + self->ob_spb.completionRoutine = NewSIInterruptProc(SPB_interrupt); + self->ob_interrupt = value; + Py_INCREF(value); + return 0; + } + return -1; +} + +staticforward PyTypeObject SPB_Type = { + PyObject_HEAD_INIT(&PyType_Type) + 0, /*ob_size*/ + "SPB", /*tp_name*/ + sizeof(SPBObject), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + /* methods */ + (destructor) SPBObj_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + (getattrfunc) SPBObj_getattr, /*tp_getattr*/ + (setattrfunc) SPBObj_setattr, /*tp_setattr*/ +}; + +/* ---------------------- End object type SPB ----------------------- */ + + +static PyObject *Snd_SPB(_self, _args) + PyObject *_self; + PyObject *_args; +{ + PyObject *_res = NULL; + return SPBObj_New(); +} + static PyObject *Snd_SysBeep(_self, _args) PyObject *_self; PyObject *_args; @@ -839,6 +968,49 @@ static PyObject *Snd_SPBCloseDevice(_self, _args) return _res; } +static PyObject *Snd_SPBRecord(_self, _args) + PyObject *_self; + PyObject *_args; +{ + PyObject *_res = NULL; + OSErr _err; + SPBPtr inParamPtr; + Boolean asynchFlag; + if (!PyArg_ParseTuple(_args, "O&b", + SPBObj_Convert, &inParamPtr, + &asynchFlag)) + return NULL; + _err = SPBRecord(inParamPtr, + asynchFlag); + if (_err != noErr) return PyMac_Error(_err); + Py_INCREF(Py_None); + _res = Py_None; + return _res; +} + +static PyObject *Snd_SPBRecordToFile(_self, _args) + PyObject *_self; + PyObject *_args; +{ + PyObject *_res = NULL; + OSErr _err; + short fRefNum; + SPBPtr inParamPtr; + Boolean asynchFlag; + if (!PyArg_ParseTuple(_args, "hO&b", + &fRefNum, + SPBObj_Convert, &inParamPtr, + &asynchFlag)) + return NULL; + _err = SPBRecordToFile(fRefNum, + inParamPtr, + asynchFlag); + if (_err != noErr) return PyMac_Error(_err); + Py_INCREF(Py_None); + _res = Py_None; + return _res; +} + static PyObject *Snd_SPBPauseRecording(_self, _args) PyObject *_self; PyObject *_args; @@ -924,6 +1096,52 @@ static PyObject *Snd_SPBGetRecordingStatus(_self, _args) return _res; } +static PyObject *Snd_SPBGetDeviceInfo(_self, _args) + PyObject *_self; + PyObject *_args; +{ + PyObject *_res = NULL; + OSErr _err; + long inRefNum; + OSType infoType; + void * infoData; + if (!PyArg_ParseTuple(_args, "lO&w", + &inRefNum, + PyMac_GetOSType, &infoType, + &infoData)) + return NULL; + _err = SPBGetDeviceInfo(inRefNum, + infoType, + infoData); + if (_err != noErr) return PyMac_Error(_err); + Py_INCREF(Py_None); + _res = Py_None; + return _res; +} + +static PyObject *Snd_SPBSetDeviceInfo(_self, _args) + PyObject *_self; + PyObject *_args; +{ + PyObject *_res = NULL; + OSErr _err; + long inRefNum; + OSType infoType; + void * infoData; + if (!PyArg_ParseTuple(_args, "lO&w", + &inRefNum, + PyMac_GetOSType, &infoType, + &infoData)) + return NULL; + _err = SPBSetDeviceInfo(inRefNum, + infoType, + infoData); + if (_err != noErr) return PyMac_Error(_err); + Py_INCREF(Py_None); + _res = Py_None; + return _res; +} + static PyObject *Snd_SPBMillisecondsToBytes(_self, _args) PyObject *_self; PyObject *_args; @@ -963,6 +1181,8 @@ static PyObject *Snd_SPBBytesToMilliseconds(_self, _args) } static PyMethodDef Snd_methods[] = { + {"SPB", (PyCFunction)Snd_SPB, 1, + NULL}, {"SysBeep", (PyCFunction)Snd_SysBeep, 1, "(short duration) -> None"}, {"SndNewChannel", (PyCFunction)Snd_SndNewChannel, 1, @@ -1009,6 +1229,10 @@ static PyMethodDef Snd_methods[] = { "(Str255 deviceName, short permission) -> (long inRefNum)"}, {"SPBCloseDevice", (PyCFunction)Snd_SPBCloseDevice, 1, "(long inRefNum) -> None"}, + {"SPBRecord", (PyCFunction)Snd_SPBRecord, 1, + "(SPBPtr inParamPtr, Boolean asynchFlag) -> None"}, + {"SPBRecordToFile", (PyCFunction)Snd_SPBRecordToFile, 1, + "(short fRefNum, SPBPtr inParamPtr, Boolean asynchFlag) -> None"}, {"SPBPauseRecording", (PyCFunction)Snd_SPBPauseRecording, 1, "(long inRefNum) -> None"}, {"SPBResumeRecording", (PyCFunction)Snd_SPBResumeRecording, 1, @@ -1017,6 +1241,10 @@ static PyMethodDef Snd_methods[] = { "(long inRefNum) -> None"}, {"SPBGetRecordingStatus", (PyCFunction)Snd_SPBGetRecordingStatus, 1, "(long inRefNum) -> (short recordingStatus, short meterLevel, unsigned long totalSamplesToRecord, unsigned long numberOfSamplesRecorded, unsigned long totalMsecsToRecord, unsigned long numberOfMsecsRecorded)"}, + {"SPBGetDeviceInfo", (PyCFunction)Snd_SPBGetDeviceInfo, 1, + "(long inRefNum, OSType infoType, void * infoData) -> None"}, + {"SPBSetDeviceInfo", (PyCFunction)Snd_SPBSetDeviceInfo, 1, + "(long inRefNum, OSType infoType, void * infoData) -> None"}, {"SPBMillisecondsToBytes", (PyCFunction)Snd_SPBMillisecondsToBytes, 1, "(long inRefNum) -> (long milliseconds)"}, {"SPBBytesToMilliseconds", (PyCFunction)Snd_SPBBytesToMilliseconds, 1, @@ -1057,6 +1285,52 @@ SndCh_UserRoutine(SndChannelPtr chan, SndCommand *cmd) } } +/* SPB callbacks - Schedule callbacks to Python */ +static int +SPB_CallCallBack(arg) + void *arg; +{ + SPBObject *p = (SPBObject *)arg; + PyObject *args; + PyObject *res; + + if ( p->ob_thiscallback == 0 ) return 0; + args = Py_BuildValue("(O)", p); + res = PyEval_CallObject(p->ob_thiscallback, args); + p->ob_thiscallback = 0; + Py_DECREF(args); + if (res == NULL) + return -1; + Py_DECREF(res); + return 0; +} + +static pascal void +SPB_completion(SPBPtr my_spb) +{ + SPBObject *p = (SPBObject *)(my_spb->userLong); + + if (p && p->ob_completion) { + long A5 = SetA5(p->ob_A5); + p->ob_thiscallback = p->ob_completion; /* Hope we cannot get two at the same time */ + Py_AddPendingCall(SPB_CallCallBack, (void *)p); + SetA5(A5); + } +} + +static pascal void +SPB_interrupt(SPBPtr my_spb) +{ + SPBObject *p = (SPBObject *)(my_spb->userLong); + + if (p && p->ob_interrupt) { + long A5 = SetA5(p->ob_A5); + p->ob_thiscallback = p->ob_interrupt; /* Hope we cannot get two at the same time */ + Py_AddPendingCall(SPB_CallCallBack, (void *)p); + SetA5(A5); + } +} + void initSnd() { @@ -1077,6 +1351,10 @@ void initSnd() Py_INCREF(&SndChannel_Type); if (PyDict_SetItemString(d, "SndChannelType", (PyObject *)&SndChannel_Type) != 0) Py_FatalError("can't initialize SndChannelType"); + SPB_Type.ob_type = &PyType_Type; + Py_INCREF(&SPB_Type); + if (PyDict_SetItemString(d, "SPBType", (PyObject *)&SPB_Type) != 0) + Py_FatalError("can't initialize SPBType"); } /* ========================= End module Snd ========================= */ diff --git a/Mac/Modules/snd/sndscan.py b/Mac/Modules/snd/sndscan.py index af5ecbb..c7ca36b 100644 --- a/Mac/Modules/snd/sndscan.py +++ b/Mac/Modules/snd/sndscan.py @@ -43,16 +43,13 @@ class SoundScanner(Scanner): 'StartSound', 'StopSound', 'SoundDone', - # These are soundMgr 3.0 routines that I can't seem to find... - 'GetSoundPreference', - 'SetSoundPreference', - 'GetCompressionInfo', - 'GetCompressionName', - # Calls with void_ptr arguments (to be done). + # These do not work for cfm68k: 'SndGetInfo', 'SndSetInfo', - 'SPBGetDeviceInfo', - 'SPBSetDeviceInfo', + 'GetCompressionInfo', + 'GetCompressionName', + 'GetSoundPreference', + 'SetSoundPreference', # And old calls that are no longer supported 'SetSoundVol', 'GetSoundVol', @@ -72,7 +69,6 @@ class SoundScanner(Scanner): "SoundComponentData_ptr", "SoundConverter", "ModalFilterUPP", - "SPBPtr", ] def makerepairinstructions(self): @@ -116,6 +112,9 @@ class SoundScanner(Scanner): ([("StateBlockPtr", "inState", "InMode"), ("StateBlockPtr", "outState", "InMode")], [("StateBlock", "state", "InOutMode")]), + # Catch-all for the last couple of void pointers + ([("void", "*", "OutMode")], + [("void_ptr", "*", "InMode")]), ] if __name__ == "__main__": diff --git a/Mac/Modules/snd/sndsupport.py b/Mac/Modules/snd/sndsupport.py index b3b32f1..cabfa27 100644 --- a/Mac/Modules/snd/sndsupport.py +++ b/Mac/Modules/snd/sndsupport.py @@ -48,6 +48,13 @@ SndChannelPtr = SndChannelPtrType('SndChannelPtr', 'SndCh') SndCommand = OpaqueType('SndCommand', 'SndCmd') SndCommand_ptr = OpaqueType('SndCommand', 'SndCmd') SndListHandle = OpaqueByValueType("SndListHandle", "ResObj") +SPBPtr = OpaqueByValueType("SPBPtr", "SPBObj") + +# +# NOTE: the following is pretty dangerous. For void pointers we pass buffer addresses +# but we have no way to check that the buffer is big enough. This is the same problem +# as in C, though (but Pythoneers may not be suspecting this...) +void_ptr = Type("void *", "w") class SndCallBackType(InputOnlyType): def __init__(self): @@ -118,6 +125,8 @@ SndCmd_Convert(PyObject *v, SndCommand *pc) } static pascal void SndCh_UserRoutine(SndChannelPtr chan, SndCommand *cmd); /* Forward */ +static pascal void SPB_completion(SPBPtr my_spb); /* Forward */ +static pascal void SPB_interrupt(SPBPtr my_spb); /* Forward */ """ @@ -152,6 +161,52 @@ SndCh_UserRoutine(SndChannelPtr chan, SndCommand *cmd) SetA5(A5); } } + +/* SPB callbacks - Schedule callbacks to Python */ +static int +SPB_CallCallBack(arg) + void *arg; +{ + SPBObject *p = (SPBObject *)arg; + PyObject *args; + PyObject *res; + + if ( p->ob_thiscallback == 0 ) return 0; + args = Py_BuildValue("(O)", p); + res = PyEval_CallObject(p->ob_thiscallback, args); + p->ob_thiscallback = 0; + Py_DECREF(args); + if (res == NULL) + return -1; + Py_DECREF(res); + return 0; +} + +static pascal void +SPB_completion(SPBPtr my_spb) +{ + SPBObject *p = (SPBObject *)(my_spb->userLong); + + if (p && p->ob_completion) { + long A5 = SetA5(p->ob_A5); + p->ob_thiscallback = p->ob_completion; /* Hope we cannot get two at the same time */ + Py_AddPendingCall(SPB_CallCallBack, (void *)p); + SetA5(A5); + } +} + +static pascal void +SPB_interrupt(SPBPtr my_spb) +{ + SPBObject *p = (SPBObject *)(my_spb->userLong); + + if (p && p->ob_interrupt) { + long A5 = SetA5(p->ob_A5); + p->ob_thiscallback = p->ob_interrupt; /* Hope we cannot get two at the same time */ + Py_AddPendingCall(SPB_CallCallBack, (void *)p); + SetA5(A5); + } +} """ @@ -177,11 +232,118 @@ class SndObjectDefinition(ObjectDefinition): def outputFreeIt(self, itselfname): Output("SndDisposeChannel(%s, 1);", itselfname) + +# + +class SpbObjectDefinition(ObjectDefinition): + + def outputStructMembers(self): + Output("/* Members used to implement callbacks: */") + Output("PyObject *ob_completion;") + Output("PyObject *ob_interrupt;") + Output("PyObject *ob_thiscallback;"); + Output("long ob_A5;") + Output("SPB ob_spb;") + + def outputNew(self): + Output() + Output("%sPyObject *%s_New()", self.static, self.prefix) + OutLbrace() + Output("%s *it;", self.objecttype) + self.outputCheckNewArg() + Output("it = PyObject_NEW(%s, &%s);", self.objecttype, self.typename) + Output("if (it == NULL) return NULL;") + self.outputInitStructMembers() + Output("return (PyObject *)it;") + OutRbrace() + + def outputInitStructMembers(self): + Output("it->ob_completion = NULL;") + Output("it->ob_interrupt = NULL;") + Output("it->ob_thiscallback = NULL;") + Output("it->ob_A5 = SetCurrentA5();") + Output("memset((char *)&it->ob_spb, 0, sizeof(it->ob_spb));") + Output("it->ob_spb.userLong = (long)it;") + + def outputCleanupStructMembers(self): + ObjectDefinition.outputCleanupStructMembers(self) + Output("self->ob_spb.userLong = 0;") + Output("self->ob_thiscallback = 0;") + Output("Py_XDECREF(self->ob_completion);") + Output("Py_XDECREF(self->ob_interrupt);") + + def outputConvert(self): + Output("%s%s_Convert(v, p_itself)", self.static, self.prefix) + IndentLevel() + Output("PyObject *v;") + Output("%s *p_itself;", self.itselftype) + DedentLevel() + OutLbrace() + self.outputCheckConvertArg() + Output("if (!%s_Check(v))", self.prefix) + OutLbrace() + Output('PyErr_SetString(PyExc_TypeError, "%s required");', self.name) + Output("return 0;") + OutRbrace() + Output("*p_itself = &((%s *)v)->ob_spb;", self.objecttype) + Output("return 1;") + OutRbrace() + + def outputSetattr(self): + Output() + Output("static int %s_setattr(self, name, value)", self.prefix) + IndentLevel() + Output("%s *self;", self.objecttype) + Output("char *name;") + Output("PyObject *value;") + DedentLevel() + OutLbrace() + self.outputSetattrBody() + OutRbrace() + def outputSetattrBody(self): + Output(""" + if (strcmp(name, "inRefNum") == 0) + return PyArg_Parse(value, "l", &self->ob_spb.inRefNum); + else if (strcmp(name, "count") == 0) + return PyArg_Parse(value, "l", &self->ob_spb.count); + else if (strcmp(name, "milliseconds") == 0) + return PyArg_Parse(value, "l", &self->ob_spb.milliseconds); + else if (strcmp(name, "buffer") == 0) + return PyArg_Parse(value, "w#", &self->ob_spb.bufferPtr, &self->ob_spb.bufferLength); + else if (strcmp(name, "completionRoutine") == 0) { + self->ob_spb.completionRoutine = NewSICompletionProc(SPB_completion); + self->ob_completion = value; + Py_INCREF(value); + return 0; + } else if (strcmp(name, "interruptRoutine") == 0) { + self->ob_spb.completionRoutine = NewSIInterruptProc(SPB_interrupt); + self->ob_interrupt = value; + Py_INCREF(value); + return 0; + } + return -1;""") + + def outputGetattrHook(self): + Output(""" + if (strcmp(name, "inRefNum") == 0) + return Py_BuildValue("l", self->ob_spb.inRefNum); + else if (strcmp(name, "count") == 0) + return Py_BuildValue("l", self->ob_spb.count); + else if (strcmp(name, "milliseconds") == 0) + return Py_BuildValue("l", self->ob_spb.milliseconds); + else if (strcmp(name, "error") == 0) + return Py_BuildValue("h", self->ob_spb.error);""") + + sndobject = SndObjectDefinition('SndChannel', 'SndCh', 'SndChannelPtr') +spbobject = SpbObjectDefinition('SPB', 'SPBObj', 'SPBPtr') +spbgenerator = ManualGenerator("SPB", "return SPBObj_New();") module = MacModule('Snd', 'Snd', includestuff, finalstuff, initstuff) module.addobject(sndobject) +module.addobject(spbobject) +module.add(spbgenerator) # create lists of functions and object methods |