]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Support for sound input added. The interface is even worse than the
authorJack Jansen <jack.jansen@cwi.nl>
Wed, 25 Feb 1998 15:47:51 +0000 (15:47 +0000)
committerJack Jansen <jack.jansen@cwi.nl>
Wed, 25 Feb 1998 15:47:51 +0000 (15:47 +0000)
sound-output interface, so this needs a Python wrapper shortly.

Mac/Modules/snd/Sndmodule.c
Mac/Modules/snd/sndscan.py
Mac/Modules/snd/sndsupport.py

index 06031ab77c1836319b2f7b20106321308e6fff0c..accb563b36242922ef51089c1d3f0a423ce593ef 100644 (file)
@@ -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 ========================= */
index af5ecbb765790fd7c285eb1f3639c00d3ee6d3c2..c7ca36bcc3d18cc51d506578d0205999a5eb6bb5 100644 (file)
@@ -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__":
index b3b32f1999b1a5f6b0e77acfafa9bd3bdef105a6..cabfa2720ea2070e64d03d4984abf725ab85e3f1 100644 (file)
@@ -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