Home | History | Annotate | Download | only in Modules
      1 /*
      2  * ossaudiodev -- Python interface to the OSS (Open Sound System) API.
      3  *                This is the standard audio API for Linux and some
      4  *                flavours of BSD [XXX which ones?]; it is also available
      5  *                for a wide range of commercial Unices.
      6  *
      7  * Originally written by Peter Bosch, March 2000, as linuxaudiodev.
      8  *
      9  * Renamed to ossaudiodev and rearranged/revised/hacked up
     10  * by Greg Ward <gward (at) python.net>, November 2002.
     11  * Mixer interface by Nicholas FitzRoy-Dale <wzdd (at) lardcave.net>, Dec 2002.
     12  *
     13  * (c) 2000 Peter Bosch.  All Rights Reserved.
     14  * (c) 2002 Gregory P. Ward.  All Rights Reserved.
     15  * (c) 2002 Python Software Foundation.  All Rights Reserved.
     16  *
     17  * XXX need a license statement
     18  *
     19  * $Id$
     20  */
     21 
     22 #include "Python.h"
     23 #include "structmember.h"
     24 
     25 #ifdef HAVE_FCNTL_H
     26 #include <fcntl.h>
     27 #else
     28 #define O_RDONLY 00
     29 #define O_WRONLY 01
     30 #endif
     31 
     32 #include <sys/ioctl.h>
     33 #include <sys/soundcard.h>
     34 
     35 #if defined(linux)
     36 
     37 #ifndef HAVE_STDINT_H
     38 typedef unsigned long uint32_t;
     39 #endif
     40 
     41 #elif defined(__FreeBSD__)
     42 
     43 # ifndef SNDCTL_DSP_CHANNELS
     44 #  define SNDCTL_DSP_CHANNELS SOUND_PCM_WRITE_CHANNELS
     45 # endif
     46 
     47 #endif
     48 
     49 typedef struct {
     50     PyObject_HEAD
     51     char    *devicename;              /* name of the device file */
     52     int      fd;                      /* file descriptor */
     53     int      mode;                    /* file mode (O_RDONLY, etc.) */
     54     int      icount;                  /* input count */
     55     int      ocount;                  /* output count */
     56     uint32_t afmts;                   /* audio formats supported by hardware */
     57 } oss_audio_t;
     58 
     59 typedef struct {
     60     PyObject_HEAD
     61     int      fd;                      /* The open mixer device */
     62 } oss_mixer_t;
     63 
     64 
     65 static PyTypeObject OSSAudioType;
     66 static PyTypeObject OSSMixerType;
     67 
     68 static PyObject *OSSAudioError;
     69 
     70 
     71 /* ----------------------------------------------------------------------
     72  * DSP object initialization/deallocation
     73  */
     74 
     75 static oss_audio_t *
     76 newossobject(PyObject *arg)
     77 {
     78     oss_audio_t *self;
     79     int fd, afmts, imode;
     80     char *devicename = NULL;
     81     char *mode = NULL;
     82 
     83     /* Two ways to call open():
     84          open(device, mode) (for consistency with builtin open())
     85          open(mode)         (for backwards compatibility)
     86        because the *first* argument is optional, parsing args is
     87        a wee bit tricky. */
     88     if (!PyArg_ParseTuple(arg, "s|s:open", &devicename, &mode))
     89        return NULL;
     90     if (mode == NULL) {                 /* only one arg supplied */
     91        mode = devicename;
     92        devicename = NULL;
     93     }
     94 
     95     if (strcmp(mode, "r") == 0)
     96         imode = O_RDONLY;
     97     else if (strcmp(mode, "w") == 0)
     98         imode = O_WRONLY;
     99     else if (strcmp(mode, "rw") == 0)
    100         imode = O_RDWR;
    101     else {
    102         PyErr_SetString(OSSAudioError, "mode must be 'r', 'w', or 'rw'");
    103         return NULL;
    104     }
    105 
    106     /* Open the correct device: either the 'device' argument,
    107        or the AUDIODEV environment variable, or "/dev/dsp". */
    108     if (devicename == NULL) {              /* called with one arg */
    109        devicename = getenv("AUDIODEV");
    110        if (devicename == NULL)             /* $AUDIODEV not set */
    111           devicename = "/dev/dsp";
    112     }
    113 
    114     /* Open with O_NONBLOCK to avoid hanging on devices that only allow
    115        one open at a time.  This does *not* affect later I/O; OSS
    116        provides a special ioctl() for non-blocking read/write, which is
    117        exposed via oss_nonblock() below. */
    118     if ((fd = open(devicename, imode|O_NONBLOCK)) == -1) {
    119         PyErr_SetFromErrnoWithFilename(PyExc_IOError, devicename);
    120         return NULL;
    121     }
    122 
    123     /* And (try to) put it back in blocking mode so we get the
    124        expected write() semantics. */
    125     if (fcntl(fd, F_SETFL, 0) == -1) {
    126         close(fd);
    127         PyErr_SetFromErrnoWithFilename(PyExc_IOError, devicename);
    128         return NULL;
    129     }
    130 
    131     if (ioctl(fd, SNDCTL_DSP_GETFMTS, &afmts) == -1) {
    132         close(fd);
    133         PyErr_SetFromErrnoWithFilename(PyExc_IOError, devicename);
    134         return NULL;
    135     }
    136     /* Create and initialize the object */
    137     if ((self = PyObject_New(oss_audio_t, &OSSAudioType)) == NULL) {
    138         close(fd);
    139         return NULL;
    140     }
    141     self->devicename = devicename;
    142     self->fd = fd;
    143     self->mode = imode;
    144     self->icount = self->ocount = 0;
    145     self->afmts  = afmts;
    146     return self;
    147 }
    148 
    149 static void
    150 oss_dealloc(oss_audio_t *self)
    151 {
    152     /* if already closed, don't reclose it */
    153     if (self->fd != -1)
    154         close(self->fd);
    155     PyObject_Del(self);
    156 }
    157 
    158 
    159 /* ----------------------------------------------------------------------
    160  * Mixer object initialization/deallocation
    161  */
    162 
    163 static oss_mixer_t *
    164 newossmixerobject(PyObject *arg)
    165 {
    166     char *devicename = NULL;
    167     int fd;
    168     oss_mixer_t *self;
    169 
    170     if (!PyArg_ParseTuple(arg, "|s", &devicename)) {
    171         return NULL;
    172     }
    173 
    174     if (devicename == NULL) {
    175         devicename = getenv("MIXERDEV");
    176         if (devicename == NULL)            /* MIXERDEV not set */
    177             devicename = "/dev/mixer";
    178     }
    179 
    180     if ((fd = open(devicename, O_RDWR)) == -1) {
    181         PyErr_SetFromErrnoWithFilename(PyExc_IOError, devicename);
    182         return NULL;
    183     }
    184 
    185     if ((self = PyObject_New(oss_mixer_t, &OSSMixerType)) == NULL) {
    186         close(fd);
    187         return NULL;
    188     }
    189 
    190     self->fd = fd;
    191 
    192     return self;
    193 }
    194 
    195 static void
    196 oss_mixer_dealloc(oss_mixer_t *self)
    197 {
    198     /* if already closed, don't reclose it */
    199     if (self->fd != -1)
    200         close(self->fd);
    201     PyObject_Del(self);
    202 }
    203 
    204 
    205 /* Methods to wrap the OSS ioctls.  The calling convention is pretty
    206    simple:
    207      nonblock()        -> ioctl(fd, SNDCTL_DSP_NONBLOCK)
    208      fmt = setfmt(fmt) -> ioctl(fd, SNDCTL_DSP_SETFMT, &fmt)
    209      etc.
    210 */
    211 
    212 
    213 /* ----------------------------------------------------------------------
    214  * Helper functions
    215  */
    216 
    217 /* _do_ioctl_1() is a private helper function used for the OSS ioctls --
    218    SNDCTL_DSP_{SETFMT,CHANNELS,SPEED} -- that are called from C
    219    like this:
    220      ioctl(fd, SNDCTL_DSP_cmd, &arg)
    221 
    222    where arg is the value to set, and on return the driver sets arg to
    223    the value that was actually set.  Mapping this to Python is obvious:
    224      arg = dsp.xxx(arg)
    225 */
    226 static PyObject *
    227 _do_ioctl_1(int fd, PyObject *args, char *fname, int cmd)
    228 {
    229     char argfmt[33] = "i:";
    230     int arg;
    231 
    232     assert(strlen(fname) <= 30);
    233     strcat(argfmt, fname);
    234     if (!PyArg_ParseTuple(args, argfmt, &arg))
    235         return NULL;
    236 
    237     if (ioctl(fd, cmd, &arg) == -1)
    238         return PyErr_SetFromErrno(PyExc_IOError);
    239     return PyInt_FromLong(arg);
    240 }
    241 
    242 
    243 /* _do_ioctl_1_internal() is a wrapper for ioctls that take no inputs
    244    but return an output -- ie. we need to pass a pointer to a local C
    245    variable so the driver can write its output there, but from Python
    246    all we see is the return value.  For example,
    247    SOUND_MIXER_READ_DEVMASK returns a bitmask of available mixer
    248    devices, but does not use the value of the parameter passed-in in any
    249    way.
    250 */
    251 static PyObject *
    252 _do_ioctl_1_internal(int fd, PyObject *args, char *fname, int cmd)
    253 {
    254     char argfmt[32] = ":";
    255     int arg = 0;
    256 
    257     assert(strlen(fname) <= 30);
    258     strcat(argfmt, fname);
    259     if (!PyArg_ParseTuple(args, argfmt, &arg))
    260         return NULL;
    261 
    262     if (ioctl(fd, cmd, &arg) == -1)
    263         return PyErr_SetFromErrno(PyExc_IOError);
    264     return PyInt_FromLong(arg);
    265 }
    266 
    267 
    268 
    269 /* _do_ioctl_0() is a private helper for the no-argument ioctls:
    270    SNDCTL_DSP_{SYNC,RESET,POST}. */
    271 static PyObject *
    272 _do_ioctl_0(int fd, PyObject *args, char *fname, int cmd)
    273 {
    274     char argfmt[32] = ":";
    275     int rv;
    276 
    277     assert(strlen(fname) <= 30);
    278     strcat(argfmt, fname);
    279     if (!PyArg_ParseTuple(args, argfmt))
    280         return NULL;
    281 
    282     /* According to hannu (at) opensound.com, all three of the ioctls that
    283        use this function can block, so release the GIL.  This is
    284        especially important for SYNC, which can block for several
    285        seconds. */
    286     Py_BEGIN_ALLOW_THREADS
    287     rv = ioctl(fd, cmd, 0);
    288     Py_END_ALLOW_THREADS
    289 
    290     if (rv == -1)
    291         return PyErr_SetFromErrno(PyExc_IOError);
    292     Py_INCREF(Py_None);
    293     return Py_None;
    294 }
    295 
    296 
    297 /* ----------------------------------------------------------------------
    298  * Methods of DSP objects (OSSAudioType)
    299  */
    300 
    301 static PyObject *
    302 oss_nonblock(oss_audio_t *self, PyObject *unused)
    303 {
    304     /* Hmmm: it doesn't appear to be possible to return to blocking
    305        mode once we're in non-blocking mode! */
    306     if (ioctl(self->fd, SNDCTL_DSP_NONBLOCK, NULL) == -1)
    307         return PyErr_SetFromErrno(PyExc_IOError);
    308     Py_INCREF(Py_None);
    309     return Py_None;
    310 }
    311 
    312 static PyObject *
    313 oss_setfmt(oss_audio_t *self, PyObject *args)
    314 {
    315     return _do_ioctl_1(self->fd, args, "setfmt", SNDCTL_DSP_SETFMT);
    316 }
    317 
    318 static PyObject *
    319 oss_getfmts(oss_audio_t *self, PyObject *unused)
    320 {
    321     int mask;
    322     if (ioctl(self->fd, SNDCTL_DSP_GETFMTS, &mask) == -1)
    323         return PyErr_SetFromErrno(PyExc_IOError);
    324     return PyInt_FromLong(mask);
    325 }
    326 
    327 static PyObject *
    328 oss_channels(oss_audio_t *self, PyObject *args)
    329 {
    330     return _do_ioctl_1(self->fd, args, "channels", SNDCTL_DSP_CHANNELS);
    331 }
    332 
    333 static PyObject *
    334 oss_speed(oss_audio_t *self, PyObject *args)
    335 {
    336     return _do_ioctl_1(self->fd, args, "speed", SNDCTL_DSP_SPEED);
    337 }
    338 
    339 static PyObject *
    340 oss_sync(oss_audio_t *self, PyObject *args)
    341 {
    342     return _do_ioctl_0(self->fd, args, "sync", SNDCTL_DSP_SYNC);
    343 }
    344 
    345 static PyObject *
    346 oss_reset(oss_audio_t *self, PyObject *args)
    347 {
    348     return _do_ioctl_0(self->fd, args, "reset", SNDCTL_DSP_RESET);
    349 }
    350 
    351 static PyObject *
    352 oss_post(oss_audio_t *self, PyObject *args)
    353 {
    354     return _do_ioctl_0(self->fd, args, "post", SNDCTL_DSP_POST);
    355 }
    356 
    357 
    358 /* Regular file methods: read(), write(), close(), etc. as well
    359    as one convenience method, writeall(). */
    360 
    361 static PyObject *
    362 oss_read(oss_audio_t *self, PyObject *args)
    363 {
    364     int size, count;
    365     char *cp;
    366     PyObject *rv;
    367 
    368     if (!PyArg_ParseTuple(args, "i:read", &size))
    369         return NULL;
    370     rv = PyString_FromStringAndSize(NULL, size);
    371     if (rv == NULL)
    372         return NULL;
    373     cp = PyString_AS_STRING(rv);
    374 
    375     Py_BEGIN_ALLOW_THREADS
    376     count = read(self->fd, cp, size);
    377     Py_END_ALLOW_THREADS
    378 
    379     if (count < 0) {
    380         PyErr_SetFromErrno(PyExc_IOError);
    381         Py_DECREF(rv);
    382         return NULL;
    383     }
    384     self->icount += count;
    385     _PyString_Resize(&rv, count);
    386     return rv;
    387 }
    388 
    389 static PyObject *
    390 oss_write(oss_audio_t *self, PyObject *args)
    391 {
    392     char *cp;
    393     int rv, size;
    394 
    395     if (!PyArg_ParseTuple(args, "s#:write", &cp, &size)) {
    396         return NULL;
    397     }
    398 
    399     Py_BEGIN_ALLOW_THREADS
    400     rv = write(self->fd, cp, size);
    401     Py_END_ALLOW_THREADS
    402 
    403     if (rv == -1) {
    404         return PyErr_SetFromErrno(PyExc_IOError);
    405     } else {
    406         self->ocount += rv;
    407     }
    408     return PyInt_FromLong(rv);
    409 }
    410 
    411 static PyObject *
    412 oss_writeall(oss_audio_t *self, PyObject *args)
    413 {
    414     char *cp;
    415     int rv, size;
    416     fd_set write_set_fds;
    417     int select_rv;
    418 
    419     /* NB. writeall() is only useful in non-blocking mode: according to
    420        Guenter Geiger <geiger (at) xdv.org> on the linux-audio-dev list
    421        (http://eca.cx/lad/2002/11/0380.html), OSS guarantees that
    422        write() in blocking mode consumes the whole buffer.  In blocking
    423        mode, the behaviour of write() and writeall() from Python is
    424        indistinguishable. */
    425 
    426     if (!PyArg_ParseTuple(args, "s#:write", &cp, &size))
    427         return NULL;
    428 
    429     if (!_PyIsSelectable_fd(self->fd)) {
    430         PyErr_SetString(PyExc_ValueError,
    431                         "file descriptor out of range for select");
    432         return NULL;
    433     }
    434     /* use select to wait for audio device to be available */
    435     FD_ZERO(&write_set_fds);
    436     FD_SET(self->fd, &write_set_fds);
    437 
    438     while (size > 0) {
    439         Py_BEGIN_ALLOW_THREADS
    440         select_rv = select(self->fd+1, NULL, &write_set_fds, NULL, NULL);
    441         Py_END_ALLOW_THREADS
    442         assert(select_rv != 0);         /* no timeout, can't expire */
    443         if (select_rv == -1)
    444             return PyErr_SetFromErrno(PyExc_IOError);
    445 
    446         Py_BEGIN_ALLOW_THREADS
    447         rv = write(self->fd, cp, size);
    448         Py_END_ALLOW_THREADS
    449         if (rv == -1) {
    450             if (errno == EAGAIN) {      /* buffer is full, try again */
    451                 errno = 0;
    452                 continue;
    453             } else                      /* it's a real error */
    454                 return PyErr_SetFromErrno(PyExc_IOError);
    455         } else {                        /* wrote rv bytes */
    456             self->ocount += rv;
    457             size -= rv;
    458             cp += rv;
    459         }
    460     }
    461     Py_INCREF(Py_None);
    462     return Py_None;
    463 }
    464 
    465 static PyObject *
    466 oss_close(oss_audio_t *self, PyObject *unused)
    467 {
    468     if (self->fd >= 0) {
    469         Py_BEGIN_ALLOW_THREADS
    470         close(self->fd);
    471         Py_END_ALLOW_THREADS
    472         self->fd = -1;
    473     }
    474     Py_INCREF(Py_None);
    475     return Py_None;
    476 }
    477 
    478 static PyObject *
    479 oss_fileno(oss_audio_t *self, PyObject *unused)
    480 {
    481     return PyInt_FromLong(self->fd);
    482 }
    483 
    484 
    485 /* Convenience methods: these generally wrap a couple of ioctls into one
    486    common task. */
    487 
    488 static PyObject *
    489 oss_setparameters(oss_audio_t *self, PyObject *args)
    490 {
    491     int wanted_fmt, wanted_channels, wanted_rate, strict=0;
    492     int fmt, channels, rate;
    493 
    494     if (!PyArg_ParseTuple(args, "iii|i:setparameters",
    495                           &wanted_fmt, &wanted_channels, &wanted_rate,
    496                           &strict))
    497         return NULL;
    498 
    499     fmt = wanted_fmt;
    500     if (ioctl(self->fd, SNDCTL_DSP_SETFMT, &fmt) == -1) {
    501         return PyErr_SetFromErrno(PyExc_IOError);
    502     }
    503     if (strict && fmt != wanted_fmt) {
    504         return PyErr_Format
    505             (OSSAudioError,
    506              "unable to set requested format (wanted %d, got %d)",
    507              wanted_fmt, fmt);
    508     }
    509 
    510     channels = wanted_channels;
    511     if (ioctl(self->fd, SNDCTL_DSP_CHANNELS, &channels) == -1) {
    512         return PyErr_SetFromErrno(PyExc_IOError);
    513     }
    514     if (strict && channels != wanted_channels) {
    515         return PyErr_Format
    516             (OSSAudioError,
    517              "unable to set requested channels (wanted %d, got %d)",
    518              wanted_channels, channels);
    519     }
    520 
    521     rate = wanted_rate;
    522     if (ioctl(self->fd, SNDCTL_DSP_SPEED, &rate) == -1) {
    523         return PyErr_SetFromErrno(PyExc_IOError);
    524     }
    525     if (strict && rate != wanted_rate) {
    526         return PyErr_Format
    527             (OSSAudioError,
    528              "unable to set requested rate (wanted %d, got %d)",
    529              wanted_rate, rate);
    530     }
    531 
    532     /* Construct the return value: a (fmt, channels, rate) tuple that
    533        tells what the audio hardware was actually set to. */
    534     return Py_BuildValue("(iii)", fmt, channels, rate);
    535 }
    536 
    537 static int
    538 _ssize(oss_audio_t *self, int *nchannels, int *ssize)
    539 {
    540     int fmt;
    541 
    542     fmt = 0;
    543     if (ioctl(self->fd, SNDCTL_DSP_SETFMT, &fmt) < 0)
    544         return -errno;
    545 
    546     switch (fmt) {
    547     case AFMT_MU_LAW:
    548     case AFMT_A_LAW:
    549     case AFMT_U8:
    550     case AFMT_S8:
    551         *ssize = 1;                     /* 8 bit formats: 1 byte */
    552         break;
    553     case AFMT_S16_LE:
    554     case AFMT_S16_BE:
    555     case AFMT_U16_LE:
    556     case AFMT_U16_BE:
    557         *ssize = 2;                     /* 16 bit formats: 2 byte */
    558         break;
    559     case AFMT_MPEG:
    560     case AFMT_IMA_ADPCM:
    561     default:
    562         return -EOPNOTSUPP;
    563     }
    564     if (ioctl(self->fd, SNDCTL_DSP_CHANNELS, nchannels) < 0)
    565         return -errno;
    566     return 0;
    567 }
    568 
    569 
    570 /* bufsize returns the size of the hardware audio buffer in number
    571    of samples */
    572 static PyObject *
    573 oss_bufsize(oss_audio_t *self, PyObject *unused)
    574 {
    575     audio_buf_info ai;
    576     int nchannels=0, ssize=0;
    577 
    578     if (_ssize(self, &nchannels, &ssize) < 0 || !nchannels || !ssize) {
    579         PyErr_SetFromErrno(PyExc_IOError);
    580         return NULL;
    581     }
    582     if (ioctl(self->fd, SNDCTL_DSP_GETOSPACE, &ai) < 0) {
    583         PyErr_SetFromErrno(PyExc_IOError);
    584         return NULL;
    585     }
    586     return PyInt_FromLong((ai.fragstotal * ai.fragsize) / (nchannels * ssize));
    587 }
    588 
    589 /* obufcount returns the number of samples that are available in the
    590    hardware for playing */
    591 static PyObject *
    592 oss_obufcount(oss_audio_t *self, PyObject *unused)
    593 {
    594     audio_buf_info ai;
    595     int nchannels=0, ssize=0;
    596 
    597     if (_ssize(self, &nchannels, &ssize) < 0 || !nchannels || !ssize) {
    598         PyErr_SetFromErrno(PyExc_IOError);
    599         return NULL;
    600     }
    601     if (ioctl(self->fd, SNDCTL_DSP_GETOSPACE, &ai) < 0) {
    602         PyErr_SetFromErrno(PyExc_IOError);
    603         return NULL;
    604     }
    605     return PyInt_FromLong((ai.fragstotal * ai.fragsize - ai.bytes) /
    606                           (ssize * nchannels));
    607 }
    608 
    609 /* obufcount returns the number of samples that can be played without
    610    blocking */
    611 static PyObject *
    612 oss_obuffree(oss_audio_t *self, PyObject *unused)
    613 {
    614     audio_buf_info ai;
    615     int nchannels=0, ssize=0;
    616 
    617     if (_ssize(self, &nchannels, &ssize) < 0 || !nchannels || !ssize) {
    618         PyErr_SetFromErrno(PyExc_IOError);
    619         return NULL;
    620     }
    621     if (ioctl(self->fd, SNDCTL_DSP_GETOSPACE, &ai) < 0) {
    622         PyErr_SetFromErrno(PyExc_IOError);
    623         return NULL;
    624     }
    625     return PyInt_FromLong(ai.bytes / (ssize * nchannels));
    626 }
    627 
    628 static PyObject *
    629 oss_getptr(oss_audio_t *self, PyObject *unused)
    630 {
    631     count_info info;
    632     int req;
    633 
    634     if (self->mode == O_RDONLY)
    635         req = SNDCTL_DSP_GETIPTR;
    636     else
    637         req = SNDCTL_DSP_GETOPTR;
    638     if (ioctl(self->fd, req, &info) == -1) {
    639         PyErr_SetFromErrno(PyExc_IOError);
    640         return NULL;
    641     }
    642     return Py_BuildValue("iii", info.bytes, info.blocks, info.ptr);
    643 }
    644 
    645 
    646 /* ----------------------------------------------------------------------
    647  * Methods of mixer objects (OSSMixerType)
    648  */
    649 
    650 static PyObject *
    651 oss_mixer_close(oss_mixer_t *self, PyObject *unused)
    652 {
    653     if (self->fd >= 0) {
    654         close(self->fd);
    655         self->fd = -1;
    656     }
    657     Py_INCREF(Py_None);
    658     return Py_None;
    659 }
    660 
    661 static PyObject *
    662 oss_mixer_fileno(oss_mixer_t *self, PyObject *unused)
    663 {
    664     return PyInt_FromLong(self->fd);
    665 }
    666 
    667 /* Simple mixer interface methods */
    668 
    669 static PyObject *
    670 oss_mixer_controls(oss_mixer_t *self, PyObject *args)
    671 {
    672     return _do_ioctl_1_internal(self->fd, args, "controls",
    673         SOUND_MIXER_READ_DEVMASK);
    674 }
    675 
    676 static PyObject *
    677 oss_mixer_stereocontrols(oss_mixer_t *self, PyObject *args)
    678 {
    679     return _do_ioctl_1_internal(self->fd, args, "stereocontrols",
    680         SOUND_MIXER_READ_STEREODEVS);
    681 }
    682 
    683 static PyObject *
    684 oss_mixer_reccontrols(oss_mixer_t *self, PyObject *args)
    685 {
    686     return _do_ioctl_1_internal(self->fd, args, "reccontrols",
    687         SOUND_MIXER_READ_RECMASK);
    688 }
    689 
    690 static PyObject *
    691 oss_mixer_get(oss_mixer_t *self, PyObject *args)
    692 {
    693     int channel, volume;
    694 
    695     /* Can't use _do_ioctl_1 because of encoded arg thingy. */
    696     if (!PyArg_ParseTuple(args, "i:get", &channel))
    697         return NULL;
    698 
    699     if (channel < 0 || channel > SOUND_MIXER_NRDEVICES) {
    700         PyErr_SetString(OSSAudioError, "Invalid mixer channel specified.");
    701         return NULL;
    702     }
    703 
    704     if (ioctl(self->fd, MIXER_READ(channel), &volume) == -1)
    705         return PyErr_SetFromErrno(PyExc_IOError);
    706 
    707     return Py_BuildValue("(ii)", volume & 0xff, (volume & 0xff00) >> 8);
    708 }
    709 
    710 static PyObject *
    711 oss_mixer_set(oss_mixer_t *self, PyObject *args)
    712 {
    713     int channel, volume, leftVol, rightVol;
    714 
    715     /* Can't use _do_ioctl_1 because of encoded arg thingy. */
    716     if (!PyArg_ParseTuple(args, "i(ii):set", &channel, &leftVol, &rightVol))
    717         return NULL;
    718 
    719     if (channel < 0 || channel > SOUND_MIXER_NRDEVICES) {
    720         PyErr_SetString(OSSAudioError, "Invalid mixer channel specified.");
    721         return NULL;
    722     }
    723 
    724     if (leftVol < 0 || rightVol < 0 || leftVol > 100 || rightVol > 100) {
    725         PyErr_SetString(OSSAudioError, "Volumes must be between 0 and 100.");
    726         return NULL;
    727     }
    728 
    729     volume = (rightVol << 8) | leftVol;
    730 
    731     if (ioctl(self->fd, MIXER_WRITE(channel), &volume) == -1)
    732         return PyErr_SetFromErrno(PyExc_IOError);
    733 
    734     return Py_BuildValue("(ii)", volume & 0xff, (volume & 0xff00) >> 8);
    735 }
    736 
    737 static PyObject *
    738 oss_mixer_get_recsrc(oss_mixer_t *self, PyObject *args)
    739 {
    740     return _do_ioctl_1_internal(self->fd, args, "get_recsrc",
    741         SOUND_MIXER_READ_RECSRC);
    742 }
    743 
    744 static PyObject *
    745 oss_mixer_set_recsrc(oss_mixer_t *self, PyObject *args)
    746 {
    747     return _do_ioctl_1(self->fd, args, "set_recsrc",
    748         SOUND_MIXER_WRITE_RECSRC);
    749 }
    750 
    751 
    752 /* ----------------------------------------------------------------------
    753  * Method tables and other bureaucracy
    754  */
    755 
    756 static PyMethodDef oss_methods[] = {
    757     /* Regular file methods */
    758     { "read",           (PyCFunction)oss_read, METH_VARARGS },
    759     { "write",          (PyCFunction)oss_write, METH_VARARGS },
    760     { "writeall",       (PyCFunction)oss_writeall, METH_VARARGS },
    761     { "close",          (PyCFunction)oss_close, METH_NOARGS },
    762     { "fileno",         (PyCFunction)oss_fileno, METH_NOARGS },
    763 
    764     /* Simple ioctl wrappers */
    765     { "nonblock",       (PyCFunction)oss_nonblock, METH_NOARGS },
    766     { "setfmt",         (PyCFunction)oss_setfmt, METH_VARARGS },
    767     { "getfmts",        (PyCFunction)oss_getfmts, METH_NOARGS },
    768     { "channels",       (PyCFunction)oss_channels, METH_VARARGS },
    769     { "speed",          (PyCFunction)oss_speed, METH_VARARGS },
    770     { "sync",           (PyCFunction)oss_sync, METH_VARARGS },
    771     { "reset",          (PyCFunction)oss_reset, METH_VARARGS },
    772     { "post",           (PyCFunction)oss_post, METH_VARARGS },
    773 
    774     /* Convenience methods -- wrap a couple of ioctls together */
    775     { "setparameters",  (PyCFunction)oss_setparameters, METH_VARARGS },
    776     { "bufsize",        (PyCFunction)oss_bufsize, METH_NOARGS },
    777     { "obufcount",      (PyCFunction)oss_obufcount, METH_NOARGS },
    778     { "obuffree",       (PyCFunction)oss_obuffree, METH_NOARGS },
    779     { "getptr",         (PyCFunction)oss_getptr, METH_NOARGS },
    780 
    781     /* Aliases for backwards compatibility */
    782     { "flush",          (PyCFunction)oss_sync, METH_VARARGS },
    783 
    784     { NULL,             NULL}           /* sentinel */
    785 };
    786 
    787 static PyMethodDef oss_mixer_methods[] = {
    788     /* Regular file method - OSS mixers are ioctl-only interface */
    789     { "close",          (PyCFunction)oss_mixer_close, METH_NOARGS },
    790     { "fileno",         (PyCFunction)oss_mixer_fileno, METH_NOARGS },
    791 
    792     /* Simple ioctl wrappers */
    793     { "controls",       (PyCFunction)oss_mixer_controls, METH_VARARGS },
    794     { "stereocontrols", (PyCFunction)oss_mixer_stereocontrols, METH_VARARGS},
    795     { "reccontrols",    (PyCFunction)oss_mixer_reccontrols, METH_VARARGS},
    796     { "get",            (PyCFunction)oss_mixer_get, METH_VARARGS },
    797     { "set",            (PyCFunction)oss_mixer_set, METH_VARARGS },
    798     { "get_recsrc",     (PyCFunction)oss_mixer_get_recsrc, METH_VARARGS },
    799     { "set_recsrc",     (PyCFunction)oss_mixer_set_recsrc, METH_VARARGS },
    800 
    801     { NULL,             NULL}
    802 };
    803 
    804 static PyObject *
    805 oss_getattr(oss_audio_t *self, char *name)
    806 {
    807     PyObject * rval = NULL;
    808     if (strcmp(name, "closed") == 0) {
    809         rval = (self->fd == -1) ? Py_True : Py_False;
    810         Py_INCREF(rval);
    811     }
    812     else if (strcmp(name, "name") == 0) {
    813         rval = PyString_FromString(self->devicename);
    814     }
    815     else if (strcmp(name, "mode") == 0) {
    816         /* No need for a "default" in this switch: from newossobject(),
    817            self->mode can only be one of these three values. */
    818         switch(self->mode) {
    819             case O_RDONLY:
    820                 rval = PyString_FromString("r");
    821                 break;
    822             case O_RDWR:
    823                 rval = PyString_FromString("rw");
    824                 break;
    825             case O_WRONLY:
    826                 rval = PyString_FromString("w");
    827                 break;
    828         }
    829     }
    830     else {
    831         rval = Py_FindMethod(oss_methods, (PyObject *)self, name);
    832     }
    833     return rval;
    834 }
    835 
    836 static PyObject *
    837 oss_mixer_getattr(oss_mixer_t *self, char *name)
    838 {
    839     return Py_FindMethod(oss_mixer_methods, (PyObject *)self, name);
    840 }
    841 
    842 static PyTypeObject OSSAudioType = {
    843     PyVarObject_HEAD_INIT(&PyType_Type, 0)
    844     "ossaudiodev.oss_audio_device", /*tp_name*/
    845     sizeof(oss_audio_t),        /*tp_size*/
    846     0,                          /*tp_itemsize*/
    847     /* methods */
    848     (destructor)oss_dealloc,    /*tp_dealloc*/
    849     0,                          /*tp_print*/
    850     (getattrfunc)oss_getattr,   /*tp_getattr*/
    851     0,                          /*tp_setattr*/
    852     0,                          /*tp_compare*/
    853     0,                          /*tp_repr*/
    854 };
    855 
    856 static PyTypeObject OSSMixerType = {
    857     PyVarObject_HEAD_INIT(&PyType_Type, 0)
    858     "ossaudiodev.oss_mixer_device", /*tp_name*/
    859     sizeof(oss_mixer_t),            /*tp_size*/
    860     0,                              /*tp_itemsize*/
    861     /* methods */
    862     (destructor)oss_mixer_dealloc,  /*tp_dealloc*/
    863     0,                              /*tp_print*/
    864     (getattrfunc)oss_mixer_getattr, /*tp_getattr*/
    865     0,                              /*tp_setattr*/
    866     0,                              /*tp_compare*/
    867     0,                              /*tp_repr*/
    868 };
    869 
    870 
    871 static PyObject *
    872 ossopen(PyObject *self, PyObject *args)
    873 {
    874     return (PyObject *)newossobject(args);
    875 }
    876 
    877 static PyObject *
    878 ossopenmixer(PyObject *self, PyObject *args)
    879 {
    880     return (PyObject *)newossmixerobject(args);
    881 }
    882 
    883 static PyMethodDef ossaudiodev_methods[] = {
    884     { "open", ossopen, METH_VARARGS },
    885     { "openmixer", ossopenmixer, METH_VARARGS },
    886     { 0, 0 },
    887 };
    888 
    889 
    890 #define _EXPORT_INT(mod, name) \
    891   if (PyModule_AddIntConstant(mod, #name, (long) (name)) == -1) return;
    892 
    893 
    894 static char *control_labels[] = SOUND_DEVICE_LABELS;
    895 static char *control_names[] = SOUND_DEVICE_NAMES;
    896 
    897 
    898 static int
    899 build_namelists (PyObject *module)
    900 {
    901     PyObject *labels;
    902     PyObject *names;
    903     PyObject *s;
    904     int num_controls;
    905     int i;
    906 
    907     num_controls = sizeof(control_labels) / sizeof(control_labels[0]);
    908     assert(num_controls == sizeof(control_names) / sizeof(control_names[0]));
    909 
    910     labels = PyList_New(num_controls);
    911     names = PyList_New(num_controls);
    912     if (labels == NULL || names == NULL)
    913         goto error2;
    914     for (i = 0; i < num_controls; i++) {
    915         s = PyString_FromString(control_labels[i]);
    916         if (s == NULL)
    917             goto error2;
    918         PyList_SET_ITEM(labels, i, s);
    919 
    920         s = PyString_FromString(control_names[i]);
    921         if (s == NULL)
    922             goto error2;
    923         PyList_SET_ITEM(names, i, s);
    924     }
    925 
    926     if (PyModule_AddObject(module, "control_labels", labels) == -1)
    927         goto error2;
    928     if (PyModule_AddObject(module, "control_names", names) == -1)
    929         goto error1;
    930 
    931     return 0;
    932 
    933 error2:
    934     Py_XDECREF(labels);
    935 error1:
    936     Py_XDECREF(names);
    937     return -1;
    938 }
    939 
    940 
    941 void
    942 initossaudiodev(void)
    943 {
    944     PyObject *m;
    945 
    946     m = Py_InitModule("ossaudiodev", ossaudiodev_methods);
    947     if (m == NULL)
    948 	return;
    949 
    950     OSSAudioError = PyErr_NewException("ossaudiodev.OSSAudioError",
    951 				       NULL, NULL);
    952     if (OSSAudioError) {
    953         /* Each call to PyModule_AddObject decrefs it; compensate: */
    954         Py_INCREF(OSSAudioError);
    955         Py_INCREF(OSSAudioError);
    956         PyModule_AddObject(m, "error", OSSAudioError);
    957         PyModule_AddObject(m, "OSSAudioError", OSSAudioError);
    958     }
    959 
    960     /* Build 'control_labels' and 'control_names' lists and add them
    961        to the module. */
    962     if (build_namelists(m) == -1)       /* XXX what to do here? */
    963         return;
    964 
    965     /* Expose the audio format numbers -- essential! */
    966     _EXPORT_INT(m, AFMT_QUERY);
    967     _EXPORT_INT(m, AFMT_MU_LAW);
    968     _EXPORT_INT(m, AFMT_A_LAW);
    969     _EXPORT_INT(m, AFMT_IMA_ADPCM);
    970     _EXPORT_INT(m, AFMT_U8);
    971     _EXPORT_INT(m, AFMT_S16_LE);
    972     _EXPORT_INT(m, AFMT_S16_BE);
    973     _EXPORT_INT(m, AFMT_S8);
    974     _EXPORT_INT(m, AFMT_U16_LE);
    975     _EXPORT_INT(m, AFMT_U16_BE);
    976     _EXPORT_INT(m, AFMT_MPEG);
    977 #ifdef AFMT_AC3
    978     _EXPORT_INT(m, AFMT_AC3);
    979 #endif
    980 #ifdef AFMT_S16_NE
    981     _EXPORT_INT(m, AFMT_S16_NE);
    982 #endif
    983 #ifdef AFMT_U16_NE
    984     _EXPORT_INT(m, AFMT_U16_NE);
    985 #endif
    986 #ifdef AFMT_S32_LE
    987     _EXPORT_INT(m, AFMT_S32_LE);
    988 #endif
    989 #ifdef AFMT_S32_BE
    990     _EXPORT_INT(m, AFMT_S32_BE);
    991 #endif
    992 #ifdef AFMT_MPEG
    993     _EXPORT_INT(m, AFMT_MPEG);
    994 #endif
    995 
    996     /* Expose the sound mixer device numbers. */
    997     _EXPORT_INT(m, SOUND_MIXER_NRDEVICES);
    998     _EXPORT_INT(m, SOUND_MIXER_VOLUME);
    999     _EXPORT_INT(m, SOUND_MIXER_BASS);
   1000     _EXPORT_INT(m, SOUND_MIXER_TREBLE);
   1001     _EXPORT_INT(m, SOUND_MIXER_SYNTH);
   1002     _EXPORT_INT(m, SOUND_MIXER_PCM);
   1003     _EXPORT_INT(m, SOUND_MIXER_SPEAKER);
   1004     _EXPORT_INT(m, SOUND_MIXER_LINE);
   1005     _EXPORT_INT(m, SOUND_MIXER_MIC);
   1006     _EXPORT_INT(m, SOUND_MIXER_CD);
   1007     _EXPORT_INT(m, SOUND_MIXER_IMIX);
   1008     _EXPORT_INT(m, SOUND_MIXER_ALTPCM);
   1009     _EXPORT_INT(m, SOUND_MIXER_RECLEV);
   1010     _EXPORT_INT(m, SOUND_MIXER_IGAIN);
   1011     _EXPORT_INT(m, SOUND_MIXER_OGAIN);
   1012     _EXPORT_INT(m, SOUND_MIXER_LINE1);
   1013     _EXPORT_INT(m, SOUND_MIXER_LINE2);
   1014     _EXPORT_INT(m, SOUND_MIXER_LINE3);
   1015 #ifdef SOUND_MIXER_DIGITAL1
   1016     _EXPORT_INT(m, SOUND_MIXER_DIGITAL1);
   1017 #endif
   1018 #ifdef SOUND_MIXER_DIGITAL2
   1019     _EXPORT_INT(m, SOUND_MIXER_DIGITAL2);
   1020 #endif
   1021 #ifdef SOUND_MIXER_DIGITAL3
   1022     _EXPORT_INT(m, SOUND_MIXER_DIGITAL3);
   1023 #endif
   1024 #ifdef SOUND_MIXER_PHONEIN
   1025     _EXPORT_INT(m, SOUND_MIXER_PHONEIN);
   1026 #endif
   1027 #ifdef SOUND_MIXER_PHONEOUT
   1028     _EXPORT_INT(m, SOUND_MIXER_PHONEOUT);
   1029 #endif
   1030 #ifdef SOUND_MIXER_VIDEO
   1031     _EXPORT_INT(m, SOUND_MIXER_VIDEO);
   1032 #endif
   1033 #ifdef SOUND_MIXER_RADIO
   1034     _EXPORT_INT(m, SOUND_MIXER_RADIO);
   1035 #endif
   1036 #ifdef SOUND_MIXER_MONITOR
   1037     _EXPORT_INT(m, SOUND_MIXER_MONITOR);
   1038 #endif
   1039 
   1040     /* Expose all the ioctl numbers for masochists who like to do this
   1041        stuff directly. */
   1042     _EXPORT_INT(m, SNDCTL_COPR_HALT);
   1043     _EXPORT_INT(m, SNDCTL_COPR_LOAD);
   1044     _EXPORT_INT(m, SNDCTL_COPR_RCODE);
   1045     _EXPORT_INT(m, SNDCTL_COPR_RCVMSG);
   1046     _EXPORT_INT(m, SNDCTL_COPR_RDATA);
   1047     _EXPORT_INT(m, SNDCTL_COPR_RESET);
   1048     _EXPORT_INT(m, SNDCTL_COPR_RUN);
   1049     _EXPORT_INT(m, SNDCTL_COPR_SENDMSG);
   1050     _EXPORT_INT(m, SNDCTL_COPR_WCODE);
   1051     _EXPORT_INT(m, SNDCTL_COPR_WDATA);
   1052 #ifdef SNDCTL_DSP_BIND_CHANNEL
   1053     _EXPORT_INT(m, SNDCTL_DSP_BIND_CHANNEL);
   1054 #endif
   1055     _EXPORT_INT(m, SNDCTL_DSP_CHANNELS);
   1056     _EXPORT_INT(m, SNDCTL_DSP_GETBLKSIZE);
   1057     _EXPORT_INT(m, SNDCTL_DSP_GETCAPS);
   1058 #ifdef SNDCTL_DSP_GETCHANNELMASK
   1059     _EXPORT_INT(m, SNDCTL_DSP_GETCHANNELMASK);
   1060 #endif
   1061     _EXPORT_INT(m, SNDCTL_DSP_GETFMTS);
   1062     _EXPORT_INT(m, SNDCTL_DSP_GETIPTR);
   1063     _EXPORT_INT(m, SNDCTL_DSP_GETISPACE);
   1064 #ifdef SNDCTL_DSP_GETODELAY
   1065     _EXPORT_INT(m, SNDCTL_DSP_GETODELAY);
   1066 #endif
   1067     _EXPORT_INT(m, SNDCTL_DSP_GETOPTR);
   1068     _EXPORT_INT(m, SNDCTL_DSP_GETOSPACE);
   1069 #ifdef SNDCTL_DSP_GETSPDIF
   1070     _EXPORT_INT(m, SNDCTL_DSP_GETSPDIF);
   1071 #endif
   1072     _EXPORT_INT(m, SNDCTL_DSP_GETTRIGGER);
   1073     _EXPORT_INT(m, SNDCTL_DSP_MAPINBUF);
   1074     _EXPORT_INT(m, SNDCTL_DSP_MAPOUTBUF);
   1075     _EXPORT_INT(m, SNDCTL_DSP_NONBLOCK);
   1076     _EXPORT_INT(m, SNDCTL_DSP_POST);
   1077 #ifdef SNDCTL_DSP_PROFILE
   1078     _EXPORT_INT(m, SNDCTL_DSP_PROFILE);
   1079 #endif
   1080     _EXPORT_INT(m, SNDCTL_DSP_RESET);
   1081     _EXPORT_INT(m, SNDCTL_DSP_SAMPLESIZE);
   1082     _EXPORT_INT(m, SNDCTL_DSP_SETDUPLEX);
   1083     _EXPORT_INT(m, SNDCTL_DSP_SETFMT);
   1084     _EXPORT_INT(m, SNDCTL_DSP_SETFRAGMENT);
   1085 #ifdef SNDCTL_DSP_SETSPDIF
   1086     _EXPORT_INT(m, SNDCTL_DSP_SETSPDIF);
   1087 #endif
   1088     _EXPORT_INT(m, SNDCTL_DSP_SETSYNCRO);
   1089     _EXPORT_INT(m, SNDCTL_DSP_SETTRIGGER);
   1090     _EXPORT_INT(m, SNDCTL_DSP_SPEED);
   1091     _EXPORT_INT(m, SNDCTL_DSP_STEREO);
   1092     _EXPORT_INT(m, SNDCTL_DSP_SUBDIVIDE);
   1093     _EXPORT_INT(m, SNDCTL_DSP_SYNC);
   1094     _EXPORT_INT(m, SNDCTL_FM_4OP_ENABLE);
   1095     _EXPORT_INT(m, SNDCTL_FM_LOAD_INSTR);
   1096     _EXPORT_INT(m, SNDCTL_MIDI_INFO);
   1097     _EXPORT_INT(m, SNDCTL_MIDI_MPUCMD);
   1098     _EXPORT_INT(m, SNDCTL_MIDI_MPUMODE);
   1099     _EXPORT_INT(m, SNDCTL_MIDI_PRETIME);
   1100     _EXPORT_INT(m, SNDCTL_SEQ_CTRLRATE);
   1101     _EXPORT_INT(m, SNDCTL_SEQ_GETINCOUNT);
   1102     _EXPORT_INT(m, SNDCTL_SEQ_GETOUTCOUNT);
   1103 #ifdef SNDCTL_SEQ_GETTIME
   1104     _EXPORT_INT(m, SNDCTL_SEQ_GETTIME);
   1105 #endif
   1106     _EXPORT_INT(m, SNDCTL_SEQ_NRMIDIS);
   1107     _EXPORT_INT(m, SNDCTL_SEQ_NRSYNTHS);
   1108     _EXPORT_INT(m, SNDCTL_SEQ_OUTOFBAND);
   1109     _EXPORT_INT(m, SNDCTL_SEQ_PANIC);
   1110     _EXPORT_INT(m, SNDCTL_SEQ_PERCMODE);
   1111     _EXPORT_INT(m, SNDCTL_SEQ_RESET);
   1112     _EXPORT_INT(m, SNDCTL_SEQ_RESETSAMPLES);
   1113     _EXPORT_INT(m, SNDCTL_SEQ_SYNC);
   1114     _EXPORT_INT(m, SNDCTL_SEQ_TESTMIDI);
   1115     _EXPORT_INT(m, SNDCTL_SEQ_THRESHOLD);
   1116 #ifdef SNDCTL_SYNTH_CONTROL
   1117     _EXPORT_INT(m, SNDCTL_SYNTH_CONTROL);
   1118 #endif
   1119 #ifdef SNDCTL_SYNTH_ID
   1120     _EXPORT_INT(m, SNDCTL_SYNTH_ID);
   1121 #endif
   1122     _EXPORT_INT(m, SNDCTL_SYNTH_INFO);
   1123     _EXPORT_INT(m, SNDCTL_SYNTH_MEMAVL);
   1124 #ifdef SNDCTL_SYNTH_REMOVESAMPLE
   1125     _EXPORT_INT(m, SNDCTL_SYNTH_REMOVESAMPLE);
   1126 #endif
   1127     _EXPORT_INT(m, SNDCTL_TMR_CONTINUE);
   1128     _EXPORT_INT(m, SNDCTL_TMR_METRONOME);
   1129     _EXPORT_INT(m, SNDCTL_TMR_SELECT);
   1130     _EXPORT_INT(m, SNDCTL_TMR_SOURCE);
   1131     _EXPORT_INT(m, SNDCTL_TMR_START);
   1132     _EXPORT_INT(m, SNDCTL_TMR_STOP);
   1133     _EXPORT_INT(m, SNDCTL_TMR_TEMPO);
   1134     _EXPORT_INT(m, SNDCTL_TMR_TIMEBASE);
   1135 }
   1136