diff -r cc39c2785e33 Modules/ossaudiodev.c --- a/Modules/ossaudiodev.c Mon Aug 20 11:47:34 2012 +0200 +++ b/Modules/ossaudiodev.c Mon Aug 20 11:49:05 2012 +0200 @@ -61,11 +61,44 @@ int fd; /* The open mixer device */ } oss_mixer_t; +typedef struct { + PyObject *OSSAudioError; + PyObject *OSSAudioType; + PyObject *OSSMixerType; +} ossaudiodevstate; -static PyTypeObject OSSAudioType; -static PyTypeObject OSSMixerType; +#define ossaudiodev_state(o) ((ossaudiodevstate *)PyModule_GetState(o)) -static PyObject *OSSAudioError; +static int +ossaudiodev_clear(PyObject *m) +{ + ossaudiodevstate *state = ossaudiodev_state(m); + Py_CLEAR(state->OSSAudioError); + Py_CLEAR(state->OSSAudioType); + Py_CLEAR(state->OSSMixerType); + return 0; +} + +static int +ossaudiodev_traverse(PyObject *m, visitproc visit, void *arg) +{ + ossaudiodevstate *state = ossaudiodev_state(m); + Py_VISIT(state->OSSAudioError); + Py_VISIT(state->OSSAudioType); + Py_VISIT(state->OSSMixerType); + return 0; +} + +static void +ossaudiodev_free(void *m) +{ + ossaudiodev_clear((PyObject *)m); +} + +static PyModuleDef ossaudiodevmodule; + +#define ossaudiodevstate_global ((ossaudiodevstate *)PyModule_GetState(PyState_FindModule(&ossaudiodevmodule))) + /* ---------------------------------------------------------------------- @@ -99,7 +132,7 @@ else if (strcmp(mode, "rw") == 0) imode = O_RDWR; else { - PyErr_SetString(OSSAudioError, "mode must be 'r', 'w', or 'rw'"); + PyErr_SetString(ossaudiodevstate_global->OSSAudioError, "mode must be 'r', 'w', or 'rw'"); return NULL; } @@ -134,10 +167,11 @@ return NULL; } /* Create and initialize the object */ - if ((self = PyObject_New(oss_audio_t, &OSSAudioType)) == NULL) { + if ((self = PyObject_New(oss_audio_t, ossaudiodevstate_global->OSSAudioType)) == NULL) { close(fd); return NULL; } + Py_INCREF(ossaudiodevstate_global->OSSAudioType); self->devicename = devicename; self->fd = fd; self->mode = imode; @@ -149,9 +183,13 @@ static void oss_dealloc(oss_audio_t *self) { + PyTypeObject *type = Py_TYPE(self); /* if already closed, don't reclose it */ if (self->fd != -1) close(self->fd); + if((void *)type->tp_dealloc == (void *)oss_dealloc) { + Py_DECREF(type); + } PyObject_Del(self); } @@ -182,11 +220,12 @@ return NULL; } - if ((self = PyObject_New(oss_mixer_t, &OSSMixerType)) == NULL) { + if ((self = PyObject_New(oss_mixer_t, ossaudiodevstate_global->OSSMixerType)) == NULL) { close(fd); return NULL; } + Py_INCREF(ossaudiodevstate_global->OSSMixerType); self->fd = fd; return self; @@ -195,9 +234,13 @@ static void oss_mixer_dealloc(oss_mixer_t *self) { + PyTypeObject *type = Py_TYPE(self); /* if already closed, don't reclose it */ if (self->fd != -1) close(self->fd); + if((void *)type->tp_dealloc == (void *)oss_mixer_dealloc) { + Py_DECREF(type); + } PyObject_Del(self); } @@ -577,7 +620,7 @@ } if (strict && fmt != wanted_fmt) { return PyErr_Format - (OSSAudioError, + (ossaudiodevstate_global->OSSAudioError, "unable to set requested format (wanted %d, got %d)", wanted_fmt, fmt); } @@ -588,7 +631,7 @@ } if (strict && channels != wanted_channels) { return PyErr_Format - (OSSAudioError, + (ossaudiodevstate_global->OSSAudioError, "unable to set requested channels (wanted %d, got %d)", wanted_channels, channels); } @@ -599,7 +642,7 @@ } if (strict && rate != wanted_rate) { return PyErr_Format - (OSSAudioError, + (ossaudiodevstate_global->OSSAudioError, "unable to set requested rate (wanted %d, got %d)", wanted_rate, rate); } @@ -805,7 +848,7 @@ return NULL; if (channel < 0 || channel > SOUND_MIXER_NRDEVICES) { - PyErr_SetString(OSSAudioError, "Invalid mixer channel specified."); + PyErr_SetString(ossaudiodevstate_global->OSSAudioError, "Invalid mixer channel specified."); return NULL; } @@ -828,12 +871,12 @@ return NULL; if (channel < 0 || channel > SOUND_MIXER_NRDEVICES) { - PyErr_SetString(OSSAudioError, "Invalid mixer channel specified."); + PyErr_SetString(ossaudiodevstate_global->OSSAudioError, "Invalid mixer channel specified."); return NULL; } if (leftVol < 0 || rightVol < 0 || leftVol > 100 || rightVol > 100) { - PyErr_SetString(OSSAudioError, "Volumes must be between 0 and 100."); + PyErr_SetString(ossaudiodevstate_global->OSSAudioError, "Volumes must be between 0 and 100."); return NULL; } @@ -963,70 +1006,38 @@ return rval; } -static PyTypeObject OSSAudioType = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) - "ossaudiodev.oss_audio_device", /*tp_name*/ - sizeof(oss_audio_t), /*tp_size*/ - 0, /*tp_itemsize*/ - /* methods */ - (destructor)oss_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_reserved*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0, /*tp_call*/ - 0, /*tp_str*/ - (getattrofunc)oss_getattro, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT, /*tp_flags*/ - 0, /*tp_doc*/ - 0, /*tp_traverse*/ - 0, /*tp_clear*/ - 0, /*tp_richcompare*/ - 0, /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - oss_methods, /*tp_methods*/ +static PyType_Slot OSSAudioType_slots[] = { + {Py_tp_dealloc, (destructor)oss_dealloc}, + {Py_tp_getattro, (getattrofunc)oss_getattro}, + {Py_tp_methods, oss_methods}, + {Py_tp_members, }, + {0, 0} }; -static PyTypeObject OSSMixerType = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) - "ossaudiodev.oss_mixer_device", /*tp_name*/ - sizeof(oss_mixer_t), /*tp_size*/ - 0, /*tp_itemsize*/ - /* methods */ - (destructor)oss_mixer_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_reserved*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT, /*tp_flags*/ - 0, /*tp_doc*/ - 0, /*tp_traverse*/ - 0, /*tp_clear*/ - 0, /*tp_richcompare*/ - 0, /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - oss_mixer_methods, /*tp_methods*/ +static PyType_Spec OSSAudioType_spec = { + "ossaudiodev.oss_audio_device", + sizeof(oss_audio_t), + 0, + Py_TPFLAGS_DEFAULT, + OSSAudioType_slots, }; +static PyType_Slot OSSMixerType_slots[] = { + {Py_tp_dealloc, (destructor)oss_mixer_dealloc}, + {Py_tp_methods, oss_mixer_methods}, + {Py_tp_members, }, + {0, 0} +}; + +static PyType_Spec OSSMixerType_spec = { + "ossaudiodev.oss_mixer_device", + sizeof(oss_mixer_t), + 0, + Py_TPFLAGS_DEFAULT, + OSSMixerType_slots, +}; + + static PyObject * ossopen(PyObject *self, PyObject *args) @@ -1102,37 +1113,44 @@ PyModuleDef_HEAD_INIT, "ossaudiodev", NULL, - -1, + sizeof(ossaudiodevstate), ossaudiodev_methods, NULL, - NULL, - NULL, - NULL + ossaudiodev_traverse, + ossaudiodev_clear, + ossaudiodev_free, }; PyMODINIT_FUNC PyInit_ossaudiodev(void) { PyObject *m; - - if (PyType_Ready(&OSSAudioType) < 0) - return NULL; - - if (PyType_Ready(&OSSMixerType) < 0) - return NULL; + ossaudiodevstate *state; m = PyModule_Create(&ossaudiodevmodule); if (m == NULL) return NULL; - OSSAudioError = PyErr_NewException("ossaudiodev.OSSAudioError", - NULL, NULL); - if (OSSAudioError) { + state = ossaudiodev_state(m); + + state->OSSAudioType = PyType_FromSpec(&OSSAudioType_spec); + if (state->OSSAudioType == NULL) + return NULL; + + state->OSSMixerType = PyType_FromSpec(&OSSMixerType_spec); + if (state->OSSMixerType == NULL) + return NULL; + + state->OSSAudioError = PyErr_NewException( + "ossaudiodev.OSSAudioError", + NULL, + NULL); + if (state->OSSAudioError) { /* Each call to PyModule_AddObject decrefs it; compensate: */ - Py_INCREF(OSSAudioError); - Py_INCREF(OSSAudioError); - PyModule_AddObject(m, "error", OSSAudioError); - PyModule_AddObject(m, "OSSAudioError", OSSAudioError); + Py_INCREF(state->OSSAudioError); + Py_INCREF(state->OSSAudioError); + PyModule_AddObject(m, "error", state->OSSAudioError); + PyModule_AddObject(m, "OSSAudioError", state->OSSAudioError); } /* Build 'control_labels' and 'control_names' lists and add them