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