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