1 /* Hey Emacs, this is -*-C-*- 2 ****************************************************************************** 3 * linuxaudiodev.c -- Linux audio device for python. 4 * 5 * Author : Peter Bosch 6 * Created On : Thu Mar 2 21:10:33 2000 7 * Status : Unknown, Use with caution! 8 * 9 * Unless other notices are present in any part of this file 10 * explicitly claiming copyrights for other people and/or 11 * organizations, the contents of this file is fully copyright 12 * (C) 2000 Peter Bosch, all rights reserved. 13 ****************************************************************************** 14 */ 15 16 #include "Python.h" 17 #include "structmember.h" 18 19 #ifdef HAVE_FCNTL_H 20 #include <fcntl.h> 21 #else 22 #define O_RDONLY 00 23 #define O_WRONLY 01 24 #endif 25 26 27 #include <sys/ioctl.h> 28 #if defined(linux) 29 #include <linux/soundcard.h> 30 31 #ifndef HAVE_STDINT_H 32 typedef unsigned long uint32_t; 33 #endif 34 35 #elif defined(__FreeBSD__) 36 #include <machine/soundcard.h> 37 38 #ifndef SNDCTL_DSP_CHANNELS 39 #define SNDCTL_DSP_CHANNELS SOUND_PCM_WRITE_CHANNELS 40 #endif 41 42 #endif 43 44 typedef struct { 45 PyObject_HEAD 46 int x_fd; /* The open file */ 47 int x_mode; /* file mode */ 48 int x_icount; /* Input count */ 49 int x_ocount; /* Output count */ 50 uint32_t x_afmts; /* Audio formats supported by hardware*/ 51 } lad_t; 52 53 /* XXX several format defined in soundcard.h are not supported, 54 including _NE (native endian) options and S32 options 55 */ 56 57 static struct { 58 int a_bps; 59 uint32_t a_fmt; 60 char *a_name; 61 } audio_types[] = { 62 { 8, AFMT_MU_LAW, "logarithmic mu-law 8-bit audio" }, 63 { 8, AFMT_A_LAW, "logarithmic A-law 8-bit audio" }, 64 { 8, AFMT_U8, "linear unsigned 8-bit audio" }, 65 { 8, AFMT_S8, "linear signed 8-bit audio" }, 66 { 16, AFMT_U16_BE, "linear unsigned 16-bit big-endian audio" }, 67 { 16, AFMT_U16_LE, "linear unsigned 16-bit little-endian audio" }, 68 { 16, AFMT_S16_BE, "linear signed 16-bit big-endian audio" }, 69 { 16, AFMT_S16_LE, "linear signed 16-bit little-endian audio" }, 70 { 16, AFMT_S16_NE, "linear signed 16-bit native-endian audio" }, 71 }; 72 73 static int n_audio_types = sizeof(audio_types) / sizeof(audio_types[0]); 74 75 static PyTypeObject Ladtype; 76 77 static PyObject *LinuxAudioError; 78 79 static lad_t * 80 newladobject(PyObject *arg) 81 { 82 lad_t *xp; 83 int fd, afmts, imode; 84 char *basedev = NULL; 85 char *mode = NULL; 86 87 /* Two ways to call linuxaudiodev.open(): 88 open(device, mode) (for consistency with builtin open()) 89 open(mode) (for backwards compatibility) 90 because the *first* argument is optional, parsing args is 91 a wee bit tricky. */ 92 if (!PyArg_ParseTuple(arg, "s|s:open", &basedev, &mode)) 93 return NULL; 94 if (mode == NULL) { /* only one arg supplied */ 95 mode = basedev; 96 basedev = NULL; 97 } 98 99 if (strcmp(mode, "r") == 0) 100 imode = O_RDONLY; 101 else if (strcmp(mode, "w") == 0) 102 imode = O_WRONLY; 103 else { 104 PyErr_SetString(LinuxAudioError, "mode should be 'r' or 'w'"); 105 return NULL; 106 } 107 108 /* Open the correct device. The base device name comes from the 109 * AUDIODEV environment variable first, then /dev/dsp. The 110 * control device tacks "ctl" onto the base device name. 111 * 112 * Note that the only difference between /dev/audio and /dev/dsp 113 * is that the former uses logarithmic mu-law encoding and the 114 * latter uses 8-bit unsigned encoding. 115 */ 116 117 if (basedev == NULL) { /* called with one arg */ 118 basedev = getenv("AUDIODEV"); 119 if (basedev == NULL) /* $AUDIODEV not set */ 120 basedev = "/dev/dsp"; 121 } 122 123 if ((fd = open(basedev, imode)) == -1) { 124 PyErr_SetFromErrnoWithFilename(LinuxAudioError, basedev); 125 return NULL; 126 } 127 if (imode == O_WRONLY && ioctl(fd, SNDCTL_DSP_NONBLOCK, NULL) == -1) { 128 PyErr_SetFromErrnoWithFilename(LinuxAudioError, basedev); 129 return NULL; 130 } 131 if (ioctl(fd, SNDCTL_DSP_GETFMTS, &afmts) == -1) { 132 PyErr_SetFromErrnoWithFilename(LinuxAudioError, basedev); 133 return NULL; 134 } 135 /* Create and initialize the object */ 136 if ((xp = PyObject_New(lad_t, &Ladtype)) == NULL) { 137 close(fd); 138 return NULL; 139 } 140 xp->x_fd = fd; 141 xp->x_mode = imode; 142 xp->x_icount = xp->x_ocount = 0; 143 xp->x_afmts = afmts; 144 return xp; 145 } 146 147 static void 148 lad_dealloc(lad_t *xp) 149 { 150 /* if already closed, don't reclose it */ 151 if (xp->x_fd != -1) 152 close(xp->x_fd); 153 PyObject_Del(xp); 154 } 155 156 static PyObject * 157 lad_read(lad_t *self, PyObject *args) 158 { 159 int size, count; 160 char *cp; 161 PyObject *rv; 162 163 if (!PyArg_ParseTuple(args, "i:read", &size)) 164 return NULL; 165 rv = PyString_FromStringAndSize(NULL, size); 166 if (rv == NULL) 167 return NULL; 168 cp = PyString_AS_STRING(rv); 169 if ((count = read(self->x_fd, cp, size)) < 0) { 170 PyErr_SetFromErrno(LinuxAudioError); 171 Py_DECREF(rv); 172 return NULL; 173 } 174 self->x_icount += count; 175 _PyString_Resize(&rv, count); 176 return rv; 177 } 178 179 static PyObject * 180 lad_write(lad_t *self, PyObject *args) 181 { 182 char *cp; 183 int rv, size; 184 fd_set write_set_fds; 185 struct timeval tv; 186 int select_retval; 187 188 if (!PyArg_ParseTuple(args, "s#:write", &cp, &size)) 189 return NULL; 190 191 /* use select to wait for audio device to be available */ 192 FD_ZERO(&write_set_fds); 193 FD_SET(self->x_fd, &write_set_fds); 194 tv.tv_sec = 4; /* timeout values */ 195 tv.tv_usec = 0; 196 197 while (size > 0) { 198 select_retval = select(self->x_fd+1, NULL, &write_set_fds, NULL, &tv); 199 tv.tv_sec = 1; tv.tv_usec = 0; /* willing to wait this long next time*/ 200 if (select_retval) { 201 if ((rv = write(self->x_fd, cp, size)) == -1) { 202 if (errno != EAGAIN) { 203 PyErr_SetFromErrno(LinuxAudioError); 204 return NULL; 205 } else { 206 errno = 0; /* EAGAIN: buffer is full, try again */ 207 } 208 } else { 209 self->x_ocount += rv; 210 size -= rv; 211 cp += rv; 212 } 213 } else { 214 /* printf("Not able to write to linux audio device within %ld seconds\n", tv.tv_sec); */ 215 PyErr_SetFromErrno(LinuxAudioError); 216 return NULL; 217 } 218 } 219 Py_INCREF(Py_None); 220 return Py_None; 221 } 222 223 static PyObject * 224 lad_close(lad_t *self, PyObject *unused) 225 { 226 if (self->x_fd >= 0) { 227 close(self->x_fd); 228 self->x_fd = -1; 229 } 230 Py_RETURN_NONE; 231 } 232 233 static PyObject * 234 lad_fileno(lad_t *self, PyObject *unused) 235 { 236 return PyInt_FromLong(self->x_fd); 237 } 238 239 static PyObject * 240 lad_setparameters(lad_t *self, PyObject *args) 241 { 242 int rate, ssize, nchannels, n, fmt, emulate=0; 243 244 if (!PyArg_ParseTuple(args, "iiii|i:setparameters", 245 &rate, &ssize, &nchannels, &fmt, &emulate)) 246 return NULL; 247 248 if (rate < 0) { 249 PyErr_Format(PyExc_ValueError, "expected rate >= 0, not %d", 250 rate); 251 return NULL; 252 } 253 if (ssize < 0) { 254 PyErr_Format(PyExc_ValueError, "expected sample size >= 0, not %d", 255 ssize); 256 return NULL; 257 } 258 if (nchannels != 1 && nchannels != 2) { 259 PyErr_Format(PyExc_ValueError, "nchannels must be 1 or 2, not %d", 260 nchannels); 261 return NULL; 262 } 263 264 for (n = 0; n < n_audio_types; n++) 265 if (fmt == audio_types[n].a_fmt) 266 break; 267 if (n == n_audio_types) { 268 PyErr_Format(PyExc_ValueError, "unknown audio encoding: %d", fmt); 269 return NULL; 270 } 271 if (audio_types[n].a_bps != ssize) { 272 PyErr_Format(PyExc_ValueError, 273 "for %s, expected sample size %d, not %d", 274 audio_types[n].a_name, audio_types[n].a_bps, ssize); 275 return NULL; 276 } 277 278 if (emulate == 0) { 279 if ((self->x_afmts & audio_types[n].a_fmt) == 0) { 280 PyErr_Format(PyExc_ValueError, 281 "%s format not supported by device", 282 audio_types[n].a_name); 283 return NULL; 284 } 285 } 286 if (ioctl(self->x_fd, SNDCTL_DSP_SETFMT, 287 &audio_types[n].a_fmt) == -1) { 288 PyErr_SetFromErrno(LinuxAudioError); 289 return NULL; 290 } 291 if (ioctl(self->x_fd, SNDCTL_DSP_CHANNELS, &nchannels) == -1) { 292 PyErr_SetFromErrno(LinuxAudioError); 293 return NULL; 294 } 295 if (ioctl(self->x_fd, SNDCTL_DSP_SPEED, &rate) == -1) { 296 PyErr_SetFromErrno(LinuxAudioError); 297 return NULL; 298 } 299 300 Py_INCREF(Py_None); 301 return Py_None; 302 } 303 304 static int 305 _ssize(lad_t *self, int *nchannels, int *ssize) 306 { 307 int fmt; 308 309 fmt = 0; 310 if (ioctl(self->x_fd, SNDCTL_DSP_SETFMT, &fmt) < 0) 311 return -errno; 312 313 switch (fmt) { 314 case AFMT_MU_LAW: 315 case AFMT_A_LAW: 316 case AFMT_U8: 317 case AFMT_S8: 318 *ssize = sizeof(char); 319 break; 320 case AFMT_S16_LE: 321 case AFMT_S16_BE: 322 case AFMT_U16_LE: 323 case AFMT_U16_BE: 324 *ssize = sizeof(short); 325 break; 326 case AFMT_MPEG: 327 case AFMT_IMA_ADPCM: 328 default: 329 return -EOPNOTSUPP; 330 } 331 if (ioctl(self->x_fd, SNDCTL_DSP_CHANNELS, nchannels) < 0) 332 return -errno; 333 return 0; 334 } 335 336 337 /* bufsize returns the size of the hardware audio buffer in number 338 of samples */ 339 static PyObject * 340 lad_bufsize(lad_t *self, PyObject *unused) 341 { 342 audio_buf_info ai; 343 int nchannels=0, ssize=0; 344 345 if (_ssize(self, &nchannels, &ssize) < 0 || !ssize || !nchannels) { 346 PyErr_SetFromErrno(LinuxAudioError); 347 return NULL; 348 } 349 if (ioctl(self->x_fd, SNDCTL_DSP_GETOSPACE, &ai) < 0) { 350 PyErr_SetFromErrno(LinuxAudioError); 351 return NULL; 352 } 353 return PyInt_FromLong((ai.fragstotal * ai.fragsize) / (nchannels * ssize)); 354 } 355 356 /* obufcount returns the number of samples that are available in the 357 hardware for playing */ 358 static PyObject * 359 lad_obufcount(lad_t *self, PyObject *unused) 360 { 361 audio_buf_info ai; 362 int nchannels=0, ssize=0; 363 364 if (_ssize(self, &nchannels, &ssize) < 0 || !ssize || !nchannels) { 365 PyErr_SetFromErrno(LinuxAudioError); 366 return NULL; 367 } 368 if (ioctl(self->x_fd, SNDCTL_DSP_GETOSPACE, &ai) < 0) { 369 PyErr_SetFromErrno(LinuxAudioError); 370 return NULL; 371 } 372 return PyInt_FromLong((ai.fragstotal * ai.fragsize - ai.bytes) / 373 (ssize * nchannels)); 374 } 375 376 /* obufcount returns the number of samples that can be played without 377 blocking */ 378 static PyObject * 379 lad_obuffree(lad_t *self, PyObject *unused) 380 { 381 audio_buf_info ai; 382 int nchannels=0, ssize=0; 383 384 if (_ssize(self, &nchannels, &ssize) < 0 || !ssize || !nchannels) { 385 PyErr_SetFromErrno(LinuxAudioError); 386 return NULL; 387 } 388 if (ioctl(self->x_fd, SNDCTL_DSP_GETOSPACE, &ai) < 0) { 389 PyErr_SetFromErrno(LinuxAudioError); 390 return NULL; 391 } 392 return PyInt_FromLong(ai.bytes / (ssize * nchannels)); 393 } 394 395 /* Flush the device */ 396 static PyObject * 397 lad_flush(lad_t *self, PyObject *unused) 398 { 399 if (ioctl(self->x_fd, SNDCTL_DSP_SYNC, NULL) == -1) { 400 PyErr_SetFromErrno(LinuxAudioError); 401 return NULL; 402 } 403 Py_RETURN_NONE; 404 } 405 406 static PyObject * 407 lad_getptr(lad_t *self, PyObject *unused) 408 { 409 count_info info; 410 int req; 411 412 if (self->x_mode == O_RDONLY) 413 req = SNDCTL_DSP_GETIPTR; 414 else 415 req = SNDCTL_DSP_GETOPTR; 416 if (ioctl(self->x_fd, req, &info) == -1) { 417 PyErr_SetFromErrno(LinuxAudioError); 418 return NULL; 419 } 420 return Py_BuildValue("iii", info.bytes, info.blocks, info.ptr); 421 } 422 423 static PyMethodDef lad_methods[] = { 424 { "read", (PyCFunction)lad_read, METH_VARARGS }, 425 { "write", (PyCFunction)lad_write, METH_VARARGS }, 426 { "setparameters", (PyCFunction)lad_setparameters, METH_VARARGS }, 427 { "bufsize", (PyCFunction)lad_bufsize, METH_VARARGS }, 428 { "obufcount", (PyCFunction)lad_obufcount, METH_NOARGS }, 429 { "obuffree", (PyCFunction)lad_obuffree, METH_NOARGS }, 430 { "flush", (PyCFunction)lad_flush, METH_NOARGS }, 431 { "close", (PyCFunction)lad_close, METH_NOARGS }, 432 { "fileno", (PyCFunction)lad_fileno, METH_NOARGS }, 433 { "getptr", (PyCFunction)lad_getptr, METH_NOARGS }, 434 { NULL, NULL} /* sentinel */ 435 }; 436 437 static PyObject * 438 lad_getattr(lad_t *xp, char *name) 439 { 440 return Py_FindMethod(lad_methods, (PyObject *)xp, name); 441 } 442 443 static PyTypeObject Ladtype = { 444 PyVarObject_HEAD_INIT(&PyType_Type, 0) 445 "linuxaudiodev.linux_audio_device", /*tp_name*/ 446 sizeof(lad_t), /*tp_size*/ 447 0, /*tp_itemsize*/ 448 /* methods */ 449 (destructor)lad_dealloc, /*tp_dealloc*/ 450 0, /*tp_print*/ 451 (getattrfunc)lad_getattr, /*tp_getattr*/ 452 0, /*tp_setattr*/ 453 0, /*tp_compare*/ 454 0, /*tp_repr*/ 455 }; 456 457 static PyObject * 458 ladopen(PyObject *self, PyObject *args) 459 { 460 return (PyObject *)newladobject(args); 461 } 462 463 static PyMethodDef linuxaudiodev_methods[] = { 464 { "open", ladopen, METH_VARARGS }, 465 { 0, 0 }, 466 }; 467 468 void 469 initlinuxaudiodev(void) 470 { 471 PyObject *m; 472 473 if (PyErr_WarnPy3k("the linuxaudiodev module has been removed in " 474 "Python 3.0; use the ossaudiodev module instead", 2) < 0) 475 return; 476 477 m = Py_InitModule("linuxaudiodev", linuxaudiodev_methods); 478 if (m == NULL) 479 return; 480 481 LinuxAudioError = PyErr_NewException("linuxaudiodev.error", NULL, NULL); 482 if (LinuxAudioError) 483 PyModule_AddObject(m, "error", LinuxAudioError); 484 485 if (PyModule_AddIntConstant(m, "AFMT_MU_LAW", (long)AFMT_MU_LAW) == -1) 486 return; 487 if (PyModule_AddIntConstant(m, "AFMT_A_LAW", (long)AFMT_A_LAW) == -1) 488 return; 489 if (PyModule_AddIntConstant(m, "AFMT_U8", (long)AFMT_U8) == -1) 490 return; 491 if (PyModule_AddIntConstant(m, "AFMT_S8", (long)AFMT_S8) == -1) 492 return; 493 if (PyModule_AddIntConstant(m, "AFMT_U16_BE", (long)AFMT_U16_BE) == -1) 494 return; 495 if (PyModule_AddIntConstant(m, "AFMT_U16_LE", (long)AFMT_U16_LE) == -1) 496 return; 497 if (PyModule_AddIntConstant(m, "AFMT_S16_BE", (long)AFMT_S16_BE) == -1) 498 return; 499 if (PyModule_AddIntConstant(m, "AFMT_S16_LE", (long)AFMT_S16_LE) == -1) 500 return; 501 if (PyModule_AddIntConstant(m, "AFMT_S16_NE", (long)AFMT_S16_NE) == -1) 502 return; 503 504 return; 505 } 506