[2] | 1 |
|
---|
| 2 | /* Sad objects */
|
---|
| 3 |
|
---|
| 4 | #include "Python.h"
|
---|
| 5 | #include "structmember.h"
|
---|
| 6 |
|
---|
| 7 | #ifdef HAVE_SYS_AUDIOIO_H
|
---|
| 8 | #define SOLARIS
|
---|
| 9 | #endif
|
---|
| 10 |
|
---|
| 11 | #ifdef HAVE_FCNTL_H
|
---|
| 12 | #include <fcntl.h>
|
---|
| 13 | #endif
|
---|
| 14 |
|
---|
| 15 | #include <stropts.h>
|
---|
| 16 | #include <sys/ioctl.h>
|
---|
| 17 | #ifdef SOLARIS
|
---|
| 18 | #include <sys/audioio.h>
|
---|
| 19 | #else
|
---|
| 20 | #include <sun/audioio.h>
|
---|
| 21 | #endif
|
---|
| 22 |
|
---|
| 23 | /* #define offsetof(str,mem) ((int)(((str *)0)->mem)) */
|
---|
| 24 |
|
---|
| 25 | typedef struct {
|
---|
[391] | 26 | PyObject_HEAD
|
---|
| 27 | int x_fd; /* The open file */
|
---|
| 28 | int x_icount; /* # samples read */
|
---|
| 29 | int x_ocount; /* # samples written */
|
---|
| 30 | int x_isctl; /* True if control device */
|
---|
| 31 |
|
---|
[2] | 32 | } sadobject;
|
---|
| 33 |
|
---|
| 34 | typedef struct {
|
---|
[391] | 35 | PyObject_HEAD
|
---|
| 36 | audio_info_t ai;
|
---|
[2] | 37 | } sadstatusobject;
|
---|
| 38 |
|
---|
| 39 | static PyTypeObject Sadtype;
|
---|
| 40 | static PyTypeObject Sadstatustype;
|
---|
[391] | 41 | static sadstatusobject *sads_alloc(void); /* Forward */
|
---|
[2] | 42 |
|
---|
| 43 | static PyObject *SunAudioError;
|
---|
| 44 |
|
---|
[391] | 45 | #define is_sadobject(v) (Py_TYPE(v) == &Sadtype)
|
---|
| 46 | #define is_sadstatusobject(v) (Py_TYPE(v) == &Sadstatustype)
|
---|
[2] | 47 |
|
---|
| 48 |
|
---|
| 49 | static sadobject *
|
---|
| 50 | newsadobject(PyObject *args)
|
---|
| 51 | {
|
---|
[391] | 52 | sadobject *xp;
|
---|
| 53 | int fd;
|
---|
| 54 | char *mode;
|
---|
| 55 | int imode;
|
---|
| 56 | char* basedev;
|
---|
| 57 | char* ctldev;
|
---|
| 58 | char* opendev;
|
---|
[2] | 59 |
|
---|
[391] | 60 | /* Check arg for r/w/rw */
|
---|
| 61 | if (!PyArg_ParseTuple(args, "s", &mode))
|
---|
| 62 | return NULL;
|
---|
| 63 | if (strcmp(mode, "r") == 0)
|
---|
| 64 | imode = 0;
|
---|
| 65 | else if (strcmp(mode, "w") == 0)
|
---|
| 66 | imode = 1;
|
---|
| 67 | else if (strcmp(mode, "rw") == 0)
|
---|
| 68 | imode = 2;
|
---|
| 69 | else if (strcmp(mode, "control") == 0)
|
---|
| 70 | imode = -1;
|
---|
| 71 | else {
|
---|
| 72 | PyErr_SetString(SunAudioError,
|
---|
| 73 | "Mode should be one of 'r', 'w', 'rw' or 'control'");
|
---|
| 74 | return NULL;
|
---|
| 75 | }
|
---|
[2] | 76 |
|
---|
[391] | 77 | /* Open the correct device. The base device name comes from the
|
---|
| 78 | * AUDIODEV environment variable first, then /dev/audio. The
|
---|
| 79 | * control device tacks "ctl" onto the base device name.
|
---|
| 80 | */
|
---|
| 81 | basedev = getenv("AUDIODEV");
|
---|
| 82 | if (!basedev)
|
---|
| 83 | basedev = "/dev/audio";
|
---|
| 84 | ctldev = PyMem_NEW(char, strlen(basedev) + 4);
|
---|
| 85 | if (!ctldev) {
|
---|
| 86 | PyErr_NoMemory();
|
---|
| 87 | return NULL;
|
---|
| 88 | }
|
---|
| 89 | strcpy(ctldev, basedev);
|
---|
| 90 | strcat(ctldev, "ctl");
|
---|
[2] | 91 |
|
---|
[391] | 92 | if (imode < 0) {
|
---|
| 93 | opendev = ctldev;
|
---|
| 94 | fd = open(ctldev, 2);
|
---|
| 95 | }
|
---|
| 96 | else {
|
---|
| 97 | opendev = basedev;
|
---|
| 98 | fd = open(basedev, imode);
|
---|
| 99 | }
|
---|
| 100 | if (fd < 0) {
|
---|
| 101 | PyErr_SetFromErrnoWithFilename(SunAudioError, opendev);
|
---|
| 102 | PyMem_DEL(ctldev);
|
---|
| 103 | return NULL;
|
---|
| 104 | }
|
---|
| 105 | PyMem_DEL(ctldev);
|
---|
| 106 |
|
---|
| 107 | /* Create and initialize the object */
|
---|
| 108 | xp = PyObject_New(sadobject, &Sadtype);
|
---|
| 109 | if (xp == NULL) {
|
---|
| 110 | close(fd);
|
---|
| 111 | return NULL;
|
---|
| 112 | }
|
---|
| 113 | xp->x_fd = fd;
|
---|
| 114 | xp->x_icount = xp->x_ocount = 0;
|
---|
| 115 | xp->x_isctl = (imode < 0);
|
---|
| 116 |
|
---|
| 117 | return xp;
|
---|
[2] | 118 | }
|
---|
| 119 |
|
---|
| 120 | /* Sad methods */
|
---|
| 121 |
|
---|
| 122 | static void
|
---|
| 123 | sad_dealloc(sadobject *xp)
|
---|
| 124 | {
|
---|
[391] | 125 | close(xp->x_fd);
|
---|
| 126 | PyObject_Del(xp);
|
---|
[2] | 127 | }
|
---|
| 128 |
|
---|
| 129 | static PyObject *
|
---|
| 130 | sad_read(sadobject *self, PyObject *args)
|
---|
| 131 | {
|
---|
[391] | 132 | int size, count;
|
---|
| 133 | char *cp;
|
---|
| 134 | PyObject *rv;
|
---|
[2] | 135 |
|
---|
[391] | 136 | if (!PyArg_ParseTuple(args, "i:read", &size))
|
---|
| 137 | return NULL;
|
---|
| 138 | rv = PyString_FromStringAndSize(NULL, size);
|
---|
| 139 | if (rv == NULL)
|
---|
| 140 | return NULL;
|
---|
[2] | 141 |
|
---|
[391] | 142 | if (!(cp = PyString_AsString(rv)))
|
---|
| 143 | goto finally;
|
---|
| 144 |
|
---|
| 145 | count = read(self->x_fd, cp, size);
|
---|
| 146 | if (count < 0) {
|
---|
| 147 | PyErr_SetFromErrno(SunAudioError);
|
---|
| 148 | goto finally;
|
---|
| 149 | }
|
---|
[2] | 150 | #if 0
|
---|
[391] | 151 | /* TBD: why print this message if you can handle the condition?
|
---|
| 152 | * assume it's debugging info which we can just as well get rid
|
---|
| 153 | * of. in any case this message should *not* be using printf!
|
---|
| 154 | */
|
---|
| 155 | if (count != size)
|
---|
| 156 | printf("sunaudio: funny read rv %d wtd %d\n", count, size);
|
---|
[2] | 157 | #endif
|
---|
[391] | 158 | self->x_icount += count;
|
---|
| 159 | return rv;
|
---|
[2] | 160 |
|
---|
| 161 | finally:
|
---|
[391] | 162 | Py_DECREF(rv);
|
---|
| 163 | return NULL;
|
---|
[2] | 164 | }
|
---|
| 165 |
|
---|
| 166 | static PyObject *
|
---|
| 167 | sad_write(sadobject *self, PyObject *args)
|
---|
| 168 | {
|
---|
[391] | 169 | char *cp;
|
---|
| 170 | int count, size;
|
---|
[2] | 171 |
|
---|
[391] | 172 | if (!PyArg_ParseTuple(args, "s#:write", &cp, &size))
|
---|
| 173 | return NULL;
|
---|
| 174 |
|
---|
| 175 | count = write(self->x_fd, cp, size);
|
---|
| 176 | if (count < 0) {
|
---|
| 177 | PyErr_SetFromErrno(SunAudioError);
|
---|
| 178 | return NULL;
|
---|
| 179 | }
|
---|
[2] | 180 | #if 0
|
---|
[391] | 181 | if (count != size)
|
---|
| 182 | printf("sunaudio: funny write rv %d wanted %d\n", count, size);
|
---|
[2] | 183 | #endif
|
---|
[391] | 184 | self->x_ocount += count;
|
---|
| 185 |
|
---|
| 186 | Py_INCREF(Py_None);
|
---|
| 187 | return Py_None;
|
---|
[2] | 188 | }
|
---|
| 189 |
|
---|
| 190 | static PyObject *
|
---|
| 191 | sad_getinfo(sadobject *self)
|
---|
| 192 | {
|
---|
[391] | 193 | sadstatusobject *rv;
|
---|
[2] | 194 |
|
---|
[391] | 195 | if (!(rv = sads_alloc()))
|
---|
| 196 | return NULL;
|
---|
[2] | 197 |
|
---|
[391] | 198 | if (ioctl(self->x_fd, AUDIO_GETINFO, &rv->ai) < 0) {
|
---|
| 199 | PyErr_SetFromErrno(SunAudioError);
|
---|
| 200 | Py_DECREF(rv);
|
---|
| 201 | return NULL;
|
---|
| 202 | }
|
---|
| 203 | return (PyObject *)rv;
|
---|
[2] | 204 | }
|
---|
| 205 |
|
---|
| 206 | static PyObject *
|
---|
| 207 | sad_setinfo(sadobject *self, sadstatusobject *arg)
|
---|
| 208 | {
|
---|
[391] | 209 | if (!is_sadstatusobject(arg)) {
|
---|
| 210 | PyErr_SetString(PyExc_TypeError,
|
---|
| 211 | "Must be sun audio status object");
|
---|
| 212 | return NULL;
|
---|
| 213 | }
|
---|
| 214 | if (ioctl(self->x_fd, AUDIO_SETINFO, &arg->ai) < 0) {
|
---|
| 215 | PyErr_SetFromErrno(SunAudioError);
|
---|
| 216 | return NULL;
|
---|
| 217 | }
|
---|
| 218 | Py_INCREF(Py_None);
|
---|
| 219 | return Py_None;
|
---|
[2] | 220 | }
|
---|
| 221 |
|
---|
| 222 | static PyObject *
|
---|
| 223 | sad_ibufcount(sadobject *self)
|
---|
| 224 | {
|
---|
[391] | 225 | audio_info_t ai;
|
---|
| 226 |
|
---|
| 227 | if (ioctl(self->x_fd, AUDIO_GETINFO, &ai) < 0) {
|
---|
| 228 | PyErr_SetFromErrno(SunAudioError);
|
---|
| 229 | return NULL;
|
---|
| 230 | }
|
---|
| 231 | return PyInt_FromLong(ai.record.samples - self->x_icount);
|
---|
[2] | 232 | }
|
---|
| 233 |
|
---|
| 234 | static PyObject *
|
---|
| 235 | sad_obufcount(sadobject *self)
|
---|
| 236 | {
|
---|
[391] | 237 | audio_info_t ai;
|
---|
| 238 |
|
---|
| 239 | if (ioctl(self->x_fd, AUDIO_GETINFO, &ai) < 0) {
|
---|
| 240 | PyErr_SetFromErrno(SunAudioError);
|
---|
| 241 | return NULL;
|
---|
| 242 | }
|
---|
| 243 | /* x_ocount is in bytes, whereas play.samples is in frames */
|
---|
| 244 | /* we want frames */
|
---|
| 245 | return PyInt_FromLong(self->x_ocount / (ai.play.channels *
|
---|
| 246 | ai.play.precision / 8) -
|
---|
| 247 | ai.play.samples);
|
---|
[2] | 248 | }
|
---|
| 249 |
|
---|
| 250 | static PyObject *
|
---|
| 251 | sad_drain(sadobject *self)
|
---|
| 252 | {
|
---|
[391] | 253 | if (ioctl(self->x_fd, AUDIO_DRAIN, 0) < 0) {
|
---|
| 254 | PyErr_SetFromErrno(SunAudioError);
|
---|
| 255 | return NULL;
|
---|
| 256 | }
|
---|
| 257 | Py_INCREF(Py_None);
|
---|
| 258 | return Py_None;
|
---|
[2] | 259 | }
|
---|
| 260 |
|
---|
| 261 | #ifdef SOLARIS
|
---|
| 262 | static PyObject *
|
---|
| 263 | sad_getdev(sadobject *self)
|
---|
| 264 | {
|
---|
[391] | 265 | struct audio_device ad;
|
---|
[2] | 266 |
|
---|
[391] | 267 | if (ioctl(self->x_fd, AUDIO_GETDEV, &ad) < 0) {
|
---|
| 268 | PyErr_SetFromErrno(SunAudioError);
|
---|
| 269 | return NULL;
|
---|
| 270 | }
|
---|
| 271 | return Py_BuildValue("(sss)", ad.name, ad.version, ad.config);
|
---|
[2] | 272 | }
|
---|
| 273 | #endif
|
---|
| 274 |
|
---|
| 275 | static PyObject *
|
---|
| 276 | sad_flush(sadobject *self)
|
---|
| 277 | {
|
---|
[391] | 278 | if (ioctl(self->x_fd, I_FLUSH, FLUSHW) < 0) {
|
---|
| 279 | PyErr_SetFromErrno(SunAudioError);
|
---|
| 280 | return NULL;
|
---|
| 281 | }
|
---|
| 282 | Py_INCREF(Py_None);
|
---|
| 283 | return Py_None;
|
---|
[2] | 284 | }
|
---|
| 285 |
|
---|
| 286 | static PyObject *
|
---|
| 287 | sad_close(sadobject *self)
|
---|
| 288 | {
|
---|
[391] | 289 |
|
---|
| 290 | if (self->x_fd >= 0) {
|
---|
| 291 | close(self->x_fd);
|
---|
| 292 | self->x_fd = -1;
|
---|
| 293 | }
|
---|
| 294 | Py_INCREF(Py_None);
|
---|
| 295 | return Py_None;
|
---|
[2] | 296 | }
|
---|
| 297 |
|
---|
| 298 | static PyObject *
|
---|
| 299 | sad_fileno(sadobject *self)
|
---|
| 300 | {
|
---|
[391] | 301 | return PyInt_FromLong(self->x_fd);
|
---|
[2] | 302 | }
|
---|
| 303 |
|
---|
| 304 |
|
---|
| 305 | static PyMethodDef sad_methods[] = {
|
---|
[391] | 306 | { "read", (PyCFunction)sad_read, METH_VARARGS },
|
---|
| 307 | { "write", (PyCFunction)sad_write, METH_VARARGS },
|
---|
| 308 | { "ibufcount", (PyCFunction)sad_ibufcount, METH_NOARGS },
|
---|
| 309 | { "obufcount", (PyCFunction)sad_obufcount, METH_NOARGS },
|
---|
[2] | 310 | #define CTL_METHODS 4
|
---|
[391] | 311 | { "getinfo", (PyCFunction)sad_getinfo, METH_NOARGS },
|
---|
| 312 | { "setinfo", (PyCFunction)sad_setinfo, METH_O},
|
---|
| 313 | { "drain", (PyCFunction)sad_drain, METH_NOARGS },
|
---|
| 314 | { "flush", (PyCFunction)sad_flush, METH_NOARGS },
|
---|
[2] | 315 | #ifdef SOLARIS
|
---|
[391] | 316 | { "getdev", (PyCFunction)sad_getdev, METH_NOARGS },
|
---|
[2] | 317 | #endif
|
---|
[391] | 318 | { "close", (PyCFunction)sad_close, METH_NOARGS },
|
---|
| 319 | { "fileno", (PyCFunction)sad_fileno, METH_NOARGS },
|
---|
| 320 | {NULL, NULL} /* sentinel */
|
---|
[2] | 321 | };
|
---|
| 322 |
|
---|
| 323 | static PyObject *
|
---|
| 324 | sad_getattr(sadobject *xp, char *name)
|
---|
| 325 | {
|
---|
[391] | 326 | if (xp->x_isctl)
|
---|
| 327 | return Py_FindMethod(sad_methods+CTL_METHODS,
|
---|
| 328 | (PyObject *)xp, name);
|
---|
| 329 | else
|
---|
| 330 | return Py_FindMethod(sad_methods, (PyObject *)xp, name);
|
---|
[2] | 331 | }
|
---|
| 332 |
|
---|
| 333 | /* ----------------------------------------------------------------- */
|
---|
| 334 |
|
---|
| 335 | static sadstatusobject *
|
---|
| 336 | sads_alloc(void) {
|
---|
[391] | 337 | return PyObject_New(sadstatusobject, &Sadstatustype);
|
---|
[2] | 338 | }
|
---|
| 339 |
|
---|
| 340 | static void
|
---|
| 341 | sads_dealloc(sadstatusobject *xp)
|
---|
| 342 | {
|
---|
[391] | 343 | PyMem_DEL(xp);
|
---|
[2] | 344 | }
|
---|
| 345 |
|
---|
| 346 | #define OFF(x) offsetof(audio_info_t,x)
|
---|
| 347 | static struct memberlist sads_ml[] = {
|
---|
[391] | 348 | { "i_sample_rate", T_UINT, OFF(record.sample_rate) },
|
---|
| 349 | { "i_channels", T_UINT, OFF(record.channels) },
|
---|
| 350 | { "i_precision", T_UINT, OFF(record.precision) },
|
---|
| 351 | { "i_encoding", T_UINT, OFF(record.encoding) },
|
---|
| 352 | { "i_gain", T_UINT, OFF(record.gain) },
|
---|
| 353 | { "i_port", T_UINT, OFF(record.port) },
|
---|
| 354 | { "i_samples", T_UINT, OFF(record.samples) },
|
---|
| 355 | { "i_eof", T_UINT, OFF(record.eof) },
|
---|
| 356 | { "i_pause", T_UBYTE, OFF(record.pause) },
|
---|
| 357 | { "i_error", T_UBYTE, OFF(record.error) },
|
---|
| 358 | { "i_waiting", T_UBYTE, OFF(record.waiting) },
|
---|
| 359 | { "i_open", T_UBYTE, OFF(record.open) , RO},
|
---|
| 360 | { "i_active", T_UBYTE, OFF(record.active) , RO},
|
---|
[2] | 361 | #ifdef SOLARIS
|
---|
[391] | 362 | { "i_buffer_size", T_UINT, OFF(record.buffer_size) },
|
---|
| 363 | { "i_balance", T_UBYTE, OFF(record.balance) },
|
---|
| 364 | { "i_avail_ports", T_UINT, OFF(record.avail_ports) },
|
---|
[2] | 365 | #endif
|
---|
| 366 |
|
---|
[391] | 367 | { "o_sample_rate", T_UINT, OFF(play.sample_rate) },
|
---|
| 368 | { "o_channels", T_UINT, OFF(play.channels) },
|
---|
| 369 | { "o_precision", T_UINT, OFF(play.precision) },
|
---|
| 370 | { "o_encoding", T_UINT, OFF(play.encoding) },
|
---|
| 371 | { "o_gain", T_UINT, OFF(play.gain) },
|
---|
| 372 | { "o_port", T_UINT, OFF(play.port) },
|
---|
| 373 | { "o_samples", T_UINT, OFF(play.samples) },
|
---|
| 374 | { "o_eof", T_UINT, OFF(play.eof) },
|
---|
| 375 | { "o_pause", T_UBYTE, OFF(play.pause) },
|
---|
| 376 | { "o_error", T_UBYTE, OFF(play.error) },
|
---|
| 377 | { "o_waiting", T_UBYTE, OFF(play.waiting) },
|
---|
| 378 | { "o_open", T_UBYTE, OFF(play.open) , RO},
|
---|
| 379 | { "o_active", T_UBYTE, OFF(play.active) , RO},
|
---|
[2] | 380 | #ifdef SOLARIS
|
---|
[391] | 381 | { "o_buffer_size", T_UINT, OFF(play.buffer_size) },
|
---|
| 382 | { "o_balance", T_UBYTE, OFF(play.balance) },
|
---|
| 383 | { "o_avail_ports", T_UINT, OFF(play.avail_ports) },
|
---|
[2] | 384 | #endif
|
---|
| 385 |
|
---|
[391] | 386 | { "monitor_gain", T_UINT, OFF(monitor_gain) },
|
---|
| 387 | { NULL, 0, 0},
|
---|
[2] | 388 | };
|
---|
| 389 |
|
---|
| 390 | static PyObject *
|
---|
| 391 | sads_getattr(sadstatusobject *xp, char *name)
|
---|
| 392 | {
|
---|
[391] | 393 | return PyMember_Get((char *)&xp->ai, sads_ml, name);
|
---|
[2] | 394 | }
|
---|
| 395 |
|
---|
| 396 | static int
|
---|
| 397 | sads_setattr(sadstatusobject *xp, char *name, PyObject *v)
|
---|
| 398 | {
|
---|
| 399 |
|
---|
[391] | 400 | if (v == NULL) {
|
---|
| 401 | PyErr_SetString(PyExc_TypeError,
|
---|
| 402 | "can't delete sun audio status attributes");
|
---|
| 403 | return -1;
|
---|
| 404 | }
|
---|
| 405 | return PyMember_Set((char *)&xp->ai, sads_ml, name, v);
|
---|
[2] | 406 | }
|
---|
| 407 |
|
---|
| 408 | /* ------------------------------------------------------------------- */
|
---|
| 409 |
|
---|
| 410 |
|
---|
| 411 | static PyTypeObject Sadtype = {
|
---|
[391] | 412 | PyVarObject_HEAD_INIT(&PyType_Type, 0)
|
---|
| 413 | "sunaudiodev.sun_audio_device", /*tp_name*/
|
---|
| 414 | sizeof(sadobject), /*tp_size*/
|
---|
| 415 | 0, /*tp_itemsize*/
|
---|
| 416 | /* methods */
|
---|
| 417 | (destructor)sad_dealloc, /*tp_dealloc*/
|
---|
| 418 | 0, /*tp_print*/
|
---|
| 419 | (getattrfunc)sad_getattr, /*tp_getattr*/
|
---|
| 420 | 0, /*tp_setattr*/
|
---|
| 421 | 0, /*tp_compare*/
|
---|
| 422 | 0, /*tp_repr*/
|
---|
[2] | 423 | };
|
---|
| 424 |
|
---|
| 425 | static PyTypeObject Sadstatustype = {
|
---|
[391] | 426 | PyVarObject_HEAD_INIT(&PyType_Type, 0)
|
---|
| 427 | "sunaudiodev.sun_audio_device_status", /*tp_name*/
|
---|
| 428 | sizeof(sadstatusobject), /*tp_size*/
|
---|
| 429 | 0, /*tp_itemsize*/
|
---|
| 430 | /* methods */
|
---|
| 431 | (destructor)sads_dealloc, /*tp_dealloc*/
|
---|
| 432 | 0, /*tp_print*/
|
---|
| 433 | (getattrfunc)sads_getattr, /*tp_getattr*/
|
---|
| 434 | (setattrfunc)sads_setattr, /*tp_setattr*/
|
---|
| 435 | 0, /*tp_compare*/
|
---|
| 436 | 0, /*tp_repr*/
|
---|
[2] | 437 | };
|
---|
| 438 | /* ------------------------------------------------------------------- */
|
---|
| 439 |
|
---|
| 440 | static PyObject *
|
---|
| 441 | sadopen(PyObject *self, PyObject *args)
|
---|
| 442 | {
|
---|
[391] | 443 | return (PyObject *)newsadobject(args);
|
---|
[2] | 444 | }
|
---|
[391] | 445 |
|
---|
[2] | 446 | static PyMethodDef sunaudiodev_methods[] = {
|
---|
| 447 | { "open", sadopen, METH_VARARGS },
|
---|
| 448 | { 0, 0 },
|
---|
| 449 | };
|
---|
| 450 |
|
---|
| 451 | void
|
---|
| 452 | initsunaudiodev(void)
|
---|
| 453 | {
|
---|
[391] | 454 | PyObject *m, *d;
|
---|
[2] | 455 |
|
---|
[391] | 456 | if (PyErr_WarnPy3k("the sunaudiodev module has been removed in "
|
---|
| 457 | "Python 3.0", 2) < 0)
|
---|
| 458 | return;
|
---|
| 459 |
|
---|
| 460 | m = Py_InitModule("sunaudiodev", sunaudiodev_methods);
|
---|
| 461 | if (m == NULL)
|
---|
| 462 | return;
|
---|
| 463 | d = PyModule_GetDict(m);
|
---|
| 464 | SunAudioError = PyErr_NewException("sunaudiodev.error", NULL, NULL);
|
---|
| 465 | if (SunAudioError)
|
---|
| 466 | PyDict_SetItemString(d, "error", SunAudioError);
|
---|
[2] | 467 | }
|
---|