Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 52b38b7

Browse files
committed
Support for sound input added. The interface is even worse than the
sound-output interface, so this needs a Python wrapper shortly.
1 parent e742a82 commit 52b38b7

3 files changed

Lines changed: 448 additions & 9 deletions

File tree

Mac/Modules/snd/Sndmodule.c

Lines changed: 278 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ SndCmd_Convert(PyObject *v, SndCommand *pc)
7676
}
7777

7878
static pascal void SndCh_UserRoutine(SndChannelPtr chan, SndCommand *cmd); /* Forward */
79+
static pascal void SPB_completion(SPBPtr my_spb); /* Forward */
80+
static pascal void SPB_interrupt(SPBPtr my_spb); /* Forward */
7981

8082
static PyObject *Snd_Error;
8183

@@ -315,6 +317,133 @@ staticforward PyTypeObject SndChannel_Type = {
315317
/* ------------------- End object type SndChannel ------------------- */
316318

317319

320+
/* ------------------------ Object type SPB ------------------------- */
321+
322+
staticforward PyTypeObject SPB_Type;
323+
324+
#define SPBObj_Check(x) ((x)->ob_type == &SPB_Type)
325+
326+
typedef struct SPBObject {
327+
PyObject_HEAD
328+
/* Members used to implement callbacks: */
329+
PyObject *ob_completion;
330+
PyObject *ob_interrupt;
331+
PyObject *ob_thiscallback;
332+
long ob_A5;
333+
SPB ob_spb;
334+
} SPBObject;
335+
336+
static PyObject *SPBObj_New()
337+
{
338+
SPBObject *it;
339+
it = PyObject_NEW(SPBObject, &SPB_Type);
340+
if (it == NULL) return NULL;
341+
it->ob_completion = NULL;
342+
it->ob_interrupt = NULL;
343+
it->ob_thiscallback = NULL;
344+
it->ob_A5 = SetCurrentA5();
345+
memset((char *)&it->ob_spb, 0, sizeof(it->ob_spb));
346+
it->ob_spb.userLong = (long)it;
347+
return (PyObject *)it;
348+
}
349+
static SPBObj_Convert(v, p_itself)
350+
PyObject *v;
351+
SPBPtr *p_itself;
352+
{
353+
if (!SPBObj_Check(v))
354+
{
355+
PyErr_SetString(PyExc_TypeError, "SPB required");
356+
return 0;
357+
}
358+
*p_itself = &((SPBObject *)v)->ob_spb;
359+
return 1;
360+
}
361+
362+
static void SPBObj_dealloc(self)
363+
SPBObject *self;
364+
{
365+
/* Cleanup of self->ob_itself goes here */
366+
self->ob_spb.userLong = 0;
367+
self->ob_thiscallback = 0;
368+
Py_XDECREF(self->ob_completion);
369+
Py_XDECREF(self->ob_interrupt);
370+
PyMem_DEL(self);
371+
}
372+
373+
static PyMethodDef SPBObj_methods[] = {
374+
{NULL, NULL, 0}
375+
};
376+
377+
static PyMethodChain SPBObj_chain = { SPBObj_methods, NULL };
378+
379+
static PyObject *SPBObj_getattr(self, name)
380+
SPBObject *self;
381+
char *name;
382+
{
383+
384+
if (strcmp(name, "inRefNum") == 0)
385+
return Py_BuildValue("l", self->ob_spb.inRefNum);
386+
else if (strcmp(name, "count") == 0)
387+
return Py_BuildValue("l", self->ob_spb.count);
388+
else if (strcmp(name, "milliseconds") == 0)
389+
return Py_BuildValue("l", self->ob_spb.milliseconds);
390+
else if (strcmp(name, "error") == 0)
391+
return Py_BuildValue("h", self->ob_spb.error);
392+
return Py_FindMethodInChain(&SPBObj_chain, (PyObject *)self, name);
393+
}
394+
395+
static int SPBObj_setattr(self, name, value)
396+
SPBObject *self;
397+
char *name;
398+
PyObject *value;
399+
{
400+
401+
if (strcmp(name, "inRefNum") == 0)
402+
return PyArg_Parse(value, "l", &self->ob_spb.inRefNum);
403+
else if (strcmp(name, "count") == 0)
404+
return PyArg_Parse(value, "l", &self->ob_spb.count);
405+
else if (strcmp(name, "milliseconds") == 0)
406+
return PyArg_Parse(value, "l", &self->ob_spb.milliseconds);
407+
else if (strcmp(name, "buffer") == 0)
408+
return PyArg_Parse(value, "w#", &self->ob_spb.bufferPtr, &self->ob_spb.bufferLength);
409+
else if (strcmp(name, "completionRoutine") == 0) {
410+
self->ob_spb.completionRoutine = NewSICompletionProc(SPB_completion);
411+
self->ob_completion = value;
412+
Py_INCREF(value);
413+
return 0;
414+
} else if (strcmp(name, "interruptRoutine") == 0) {
415+
self->ob_spb.completionRoutine = NewSIInterruptProc(SPB_interrupt);
416+
self->ob_interrupt = value;
417+
Py_INCREF(value);
418+
return 0;
419+
}
420+
return -1;
421+
}
422+
423+
staticforward PyTypeObject SPB_Type = {
424+
PyObject_HEAD_INIT(&PyType_Type)
425+
0, /*ob_size*/
426+
"SPB", /*tp_name*/
427+
sizeof(SPBObject), /*tp_basicsize*/
428+
0, /*tp_itemsize*/
429+
/* methods */
430+
(destructor) SPBObj_dealloc, /*tp_dealloc*/
431+
0, /*tp_print*/
432+
(getattrfunc) SPBObj_getattr, /*tp_getattr*/
433+
(setattrfunc) SPBObj_setattr, /*tp_setattr*/
434+
};
435+
436+
/* ---------------------- End object type SPB ----------------------- */
437+
438+
439+
static PyObject *Snd_SPB(_self, _args)
440+
PyObject *_self;
441+
PyObject *_args;
442+
{
443+
PyObject *_res = NULL;
444+
return SPBObj_New();
445+
}
446+
318447
static PyObject *Snd_SysBeep(_self, _args)
319448
PyObject *_self;
320449
PyObject *_args;
@@ -839,6 +968,49 @@ static PyObject *Snd_SPBCloseDevice(_self, _args)
839968
return _res;
840969
}
841970

971+
static PyObject *Snd_SPBRecord(_self, _args)
972+
PyObject *_self;
973+
PyObject *_args;
974+
{
975+
PyObject *_res = NULL;
976+
OSErr _err;
977+
SPBPtr inParamPtr;
978+
Boolean asynchFlag;
979+
if (!PyArg_ParseTuple(_args, "O&b",
980+
SPBObj_Convert, &inParamPtr,
981+
&asynchFlag))
982+
return NULL;
983+
_err = SPBRecord(inParamPtr,
984+
asynchFlag);
985+
if (_err != noErr) return PyMac_Error(_err);
986+
Py_INCREF(Py_None);
987+
_res = Py_None;
988+
return _res;
989+
}
990+
991+
static PyObject *Snd_SPBRecordToFile(_self, _args)
992+
PyObject *_self;
993+
PyObject *_args;
994+
{
995+
PyObject *_res = NULL;
996+
OSErr _err;
997+
short fRefNum;
998+
SPBPtr inParamPtr;
999+
Boolean asynchFlag;
1000+
if (!PyArg_ParseTuple(_args, "hO&b",
1001+
&fRefNum,
1002+
SPBObj_Convert, &inParamPtr,
1003+
&asynchFlag))
1004+
return NULL;
1005+
_err = SPBRecordToFile(fRefNum,
1006+
inParamPtr,
1007+
asynchFlag);
1008+
if (_err != noErr) return PyMac_Error(_err);
1009+
Py_INCREF(Py_None);
1010+
_res = Py_None;
1011+
return _res;
1012+
}
1013+
8421014
static PyObject *Snd_SPBPauseRecording(_self, _args)
8431015
PyObject *_self;
8441016
PyObject *_args;
@@ -924,6 +1096,52 @@ static PyObject *Snd_SPBGetRecordingStatus(_self, _args)
9241096
return _res;
9251097
}
9261098

1099+
static PyObject *Snd_SPBGetDeviceInfo(_self, _args)
1100+
PyObject *_self;
1101+
PyObject *_args;
1102+
{
1103+
PyObject *_res = NULL;
1104+
OSErr _err;
1105+
long inRefNum;
1106+
OSType infoType;
1107+
void * infoData;
1108+
if (!PyArg_ParseTuple(_args, "lO&w",
1109+
&inRefNum,
1110+
PyMac_GetOSType, &infoType,
1111+
&infoData))
1112+
return NULL;
1113+
_err = SPBGetDeviceInfo(inRefNum,
1114+
infoType,
1115+
infoData);
1116+
if (_err != noErr) return PyMac_Error(_err);
1117+
Py_INCREF(Py_None);
1118+
_res = Py_None;
1119+
return _res;
1120+
}
1121+
1122+
static PyObject *Snd_SPBSetDeviceInfo(_self, _args)
1123+
PyObject *_self;
1124+
PyObject *_args;
1125+
{
1126+
PyObject *_res = NULL;
1127+
OSErr _err;
1128+
long inRefNum;
1129+
OSType infoType;
1130+
void * infoData;
1131+
if (!PyArg_ParseTuple(_args, "lO&w",
1132+
&inRefNum,
1133+
PyMac_GetOSType, &infoType,
1134+
&infoData))
1135+
return NULL;
1136+
_err = SPBSetDeviceInfo(inRefNum,
1137+
infoType,
1138+
infoData);
1139+
if (_err != noErr) return PyMac_Error(_err);
1140+
Py_INCREF(Py_None);
1141+
_res = Py_None;
1142+
return _res;
1143+
}
1144+
9271145
static PyObject *Snd_SPBMillisecondsToBytes(_self, _args)
9281146
PyObject *_self;
9291147
PyObject *_args;
@@ -963,6 +1181,8 @@ static PyObject *Snd_SPBBytesToMilliseconds(_self, _args)
9631181
}
9641182

9651183
static PyMethodDef Snd_methods[] = {
1184+
{"SPB", (PyCFunction)Snd_SPB, 1,
1185+
NULL},
9661186
{"SysBeep", (PyCFunction)Snd_SysBeep, 1,
9671187
"(short duration) -> None"},
9681188
{"SndNewChannel", (PyCFunction)Snd_SndNewChannel, 1,
@@ -1009,6 +1229,10 @@ static PyMethodDef Snd_methods[] = {
10091229
"(Str255 deviceName, short permission) -> (long inRefNum)"},
10101230
{"SPBCloseDevice", (PyCFunction)Snd_SPBCloseDevice, 1,
10111231
"(long inRefNum) -> None"},
1232+
{"SPBRecord", (PyCFunction)Snd_SPBRecord, 1,
1233+
"(SPBPtr inParamPtr, Boolean asynchFlag) -> None"},
1234+
{"SPBRecordToFile", (PyCFunction)Snd_SPBRecordToFile, 1,
1235+
"(short fRefNum, SPBPtr inParamPtr, Boolean asynchFlag) -> None"},
10121236
{"SPBPauseRecording", (PyCFunction)Snd_SPBPauseRecording, 1,
10131237
"(long inRefNum) -> None"},
10141238
{"SPBResumeRecording", (PyCFunction)Snd_SPBResumeRecording, 1,
@@ -1017,6 +1241,10 @@ static PyMethodDef Snd_methods[] = {
10171241
"(long inRefNum) -> None"},
10181242
{"SPBGetRecordingStatus", (PyCFunction)Snd_SPBGetRecordingStatus, 1,
10191243
"(long inRefNum) -> (short recordingStatus, short meterLevel, unsigned long totalSamplesToRecord, unsigned long numberOfSamplesRecorded, unsigned long totalMsecsToRecord, unsigned long numberOfMsecsRecorded)"},
1244+
{"SPBGetDeviceInfo", (PyCFunction)Snd_SPBGetDeviceInfo, 1,
1245+
"(long inRefNum, OSType infoType, void * infoData) -> None"},
1246+
{"SPBSetDeviceInfo", (PyCFunction)Snd_SPBSetDeviceInfo, 1,
1247+
"(long inRefNum, OSType infoType, void * infoData) -> None"},
10201248
{"SPBMillisecondsToBytes", (PyCFunction)Snd_SPBMillisecondsToBytes, 1,
10211249
"(long inRefNum) -> (long milliseconds)"},
10221250
{"SPBBytesToMilliseconds", (PyCFunction)Snd_SPBBytesToMilliseconds, 1,
@@ -1057,6 +1285,52 @@ SndCh_UserRoutine(SndChannelPtr chan, SndCommand *cmd)
10571285
}
10581286
}
10591287

1288+
/* SPB callbacks - Schedule callbacks to Python */
1289+
static int
1290+
SPB_CallCallBack(arg)
1291+
void *arg;
1292+
{
1293+
SPBObject *p = (SPBObject *)arg;
1294+
PyObject *args;
1295+
PyObject *res;
1296+
1297+
if ( p->ob_thiscallback == 0 ) return 0;
1298+
args = Py_BuildValue("(O)", p);
1299+
res = PyEval_CallObject(p->ob_thiscallback, args);
1300+
p->ob_thiscallback = 0;
1301+
Py_DECREF(args);
1302+
if (res == NULL)
1303+
return -1;
1304+
Py_DECREF(res);
1305+
return 0;
1306+
}
1307+
1308+
static pascal void
1309+
SPB_completion(SPBPtr my_spb)
1310+
{
1311+
SPBObject *p = (SPBObject *)(my_spb->userLong);
1312+
1313+
if (p && p->ob_completion) {
1314+
long A5 = SetA5(p->ob_A5);
1315+
p->ob_thiscallback = p->ob_completion; /* Hope we cannot get two at the same time */
1316+
Py_AddPendingCall(SPB_CallCallBack, (void *)p);
1317+
SetA5(A5);
1318+
}
1319+
}
1320+
1321+
static pascal void
1322+
SPB_interrupt(SPBPtr my_spb)
1323+
{
1324+
SPBObject *p = (SPBObject *)(my_spb->userLong);
1325+
1326+
if (p && p->ob_interrupt) {
1327+
long A5 = SetA5(p->ob_A5);
1328+
p->ob_thiscallback = p->ob_interrupt; /* Hope we cannot get two at the same time */
1329+
Py_AddPendingCall(SPB_CallCallBack, (void *)p);
1330+
SetA5(A5);
1331+
}
1332+
}
1333+
10601334

10611335
void initSnd()
10621336
{
@@ -1077,6 +1351,10 @@ void initSnd()
10771351
Py_INCREF(&SndChannel_Type);
10781352
if (PyDict_SetItemString(d, "SndChannelType", (PyObject *)&SndChannel_Type) != 0)
10791353
Py_FatalError("can't initialize SndChannelType");
1354+
SPB_Type.ob_type = &PyType_Type;
1355+
Py_INCREF(&SPB_Type);
1356+
if (PyDict_SetItemString(d, "SPBType", (PyObject *)&SPB_Type) != 0)
1357+
Py_FatalError("can't initialize SPBType");
10801358
}
10811359

10821360
/* ========================= End module Snd ========================= */

Mac/Modules/snd/sndscan.py

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,16 +43,13 @@ def makeblacklistnames(self):
4343
'StartSound',
4444
'StopSound',
4545
'SoundDone',
46-
# These are soundMgr 3.0 routines that I can't seem to find...
47-
'GetSoundPreference',
48-
'SetSoundPreference',
49-
'GetCompressionInfo',
50-
'GetCompressionName',
51-
# Calls with void_ptr arguments (to be done).
46+
# These do not work for cfm68k:
5247
'SndGetInfo',
5348
'SndSetInfo',
54-
'SPBGetDeviceInfo',
55-
'SPBSetDeviceInfo',
49+
'GetCompressionInfo',
50+
'GetCompressionName',
51+
'GetSoundPreference',
52+
'SetSoundPreference',
5653
# And old calls that are no longer supported
5754
'SetSoundVol',
5855
'GetSoundVol',
@@ -72,7 +69,6 @@ def makeblacklisttypes(self):
7269
"SoundComponentData_ptr",
7370
"SoundConverter",
7471
"ModalFilterUPP",
75-
"SPBPtr",
7672
]
7773

7874
def makerepairinstructions(self):
@@ -116,6 +112,9 @@ def makerepairinstructions(self):
116112
([("StateBlockPtr", "inState", "InMode"), ("StateBlockPtr", "outState", "InMode")],
117113
[("StateBlock", "state", "InOutMode")]),
118114

115+
# Catch-all for the last couple of void pointers
116+
([("void", "*", "OutMode")],
117+
[("void_ptr", "*", "InMode")]),
119118
]
120119

121120
if __name__ == "__main__":

0 commit comments

Comments
 (0)