Home | History | Annotate | Download | only in Modules
      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