LCOV - code coverage report
Current view: top level - Modules - ossaudiodev.c (source / functions) Hit Total Coverage
Test: CPython lcov report Lines: 143 528 27.1 %
Date: 2022-07-07 18:19:46 Functions: 2 44 4.5 %

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

Generated by: LCOV version 1.14