17db96d56Sopenharmony_ci/*
27db96d56Sopenharmony_ci * ossaudiodev -- Python interface to the OSS (Open Sound System) API.
37db96d56Sopenharmony_ci *                This is the standard audio API for Linux and some
47db96d56Sopenharmony_ci *                flavours of BSD [XXX which ones?]; it is also available
57db96d56Sopenharmony_ci *                for a wide range of commercial Unices.
67db96d56Sopenharmony_ci *
77db96d56Sopenharmony_ci * Originally written by Peter Bosch, March 2000, as linuxaudiodev.
87db96d56Sopenharmony_ci *
97db96d56Sopenharmony_ci * Renamed to ossaudiodev and rearranged/revised/hacked up
107db96d56Sopenharmony_ci * by Greg Ward <gward@python.net>, November 2002.
117db96d56Sopenharmony_ci * Mixer interface by Nicholas FitzRoy-Dale <wzdd@lardcave.net>, Dec 2002.
127db96d56Sopenharmony_ci *
137db96d56Sopenharmony_ci * (c) 2000 Peter Bosch.  All Rights Reserved.
147db96d56Sopenharmony_ci * (c) 2002 Gregory P. Ward.  All Rights Reserved.
157db96d56Sopenharmony_ci * (c) 2002 Python Software Foundation.  All Rights Reserved.
167db96d56Sopenharmony_ci *
177db96d56Sopenharmony_ci * $Id$
187db96d56Sopenharmony_ci */
197db96d56Sopenharmony_ci
207db96d56Sopenharmony_ci#ifndef Py_BUILD_CORE_BUILTIN
217db96d56Sopenharmony_ci#  define Py_BUILD_CORE_MODULE 1
227db96d56Sopenharmony_ci#endif
237db96d56Sopenharmony_ci#define NEEDS_PY_IDENTIFIER
247db96d56Sopenharmony_ci
257db96d56Sopenharmony_ci#define PY_SSIZE_T_CLEAN
267db96d56Sopenharmony_ci#include "Python.h"
277db96d56Sopenharmony_ci#include "pycore_fileutils.h"     // _Py_write()
287db96d56Sopenharmony_ci#include "structmember.h"         // PyMemberDef
297db96d56Sopenharmony_ci
307db96d56Sopenharmony_ci#include <stdlib.h>               // getenv()
317db96d56Sopenharmony_ci#ifdef HAVE_FCNTL_H
327db96d56Sopenharmony_ci#include <fcntl.h>
337db96d56Sopenharmony_ci#else
347db96d56Sopenharmony_ci#define O_RDONLY 00
357db96d56Sopenharmony_ci#define O_WRONLY 01
367db96d56Sopenharmony_ci#endif
377db96d56Sopenharmony_ci
387db96d56Sopenharmony_ci#include <sys/ioctl.h>
397db96d56Sopenharmony_ci#ifdef __ANDROID__
407db96d56Sopenharmony_ci#include <linux/soundcard.h>
417db96d56Sopenharmony_ci#else
427db96d56Sopenharmony_ci#include <sys/soundcard.h>
437db96d56Sopenharmony_ci#endif
447db96d56Sopenharmony_ci
457db96d56Sopenharmony_ci#ifdef __linux__
467db96d56Sopenharmony_ci
477db96d56Sopenharmony_ci#ifndef HAVE_STDINT_H
487db96d56Sopenharmony_citypedef unsigned long uint32_t;
497db96d56Sopenharmony_ci#endif
507db96d56Sopenharmony_ci
517db96d56Sopenharmony_ci#elif defined(__FreeBSD__)
527db96d56Sopenharmony_ci
537db96d56Sopenharmony_ci# ifndef SNDCTL_DSP_CHANNELS
547db96d56Sopenharmony_ci#  define SNDCTL_DSP_CHANNELS SOUND_PCM_WRITE_CHANNELS
557db96d56Sopenharmony_ci# endif
567db96d56Sopenharmony_ci
577db96d56Sopenharmony_ci#endif
587db96d56Sopenharmony_ci
597db96d56Sopenharmony_citypedef struct {
607db96d56Sopenharmony_ci    PyObject_HEAD
617db96d56Sopenharmony_ci    const char *devicename;           /* name of the device file */
627db96d56Sopenharmony_ci    int      fd;                      /* file descriptor */
637db96d56Sopenharmony_ci    int      mode;                    /* file mode (O_RDONLY, etc.) */
647db96d56Sopenharmony_ci    Py_ssize_t icount;                /* input count */
657db96d56Sopenharmony_ci    Py_ssize_t ocount;                /* output count */
667db96d56Sopenharmony_ci    uint32_t afmts;                   /* audio formats supported by hardware */
677db96d56Sopenharmony_ci} oss_audio_t;
687db96d56Sopenharmony_ci
697db96d56Sopenharmony_citypedef struct {
707db96d56Sopenharmony_ci    PyObject_HEAD
717db96d56Sopenharmony_ci    int      fd;                      /* The open mixer device */
727db96d56Sopenharmony_ci} oss_mixer_t;
737db96d56Sopenharmony_ci
747db96d56Sopenharmony_ci
757db96d56Sopenharmony_cistatic PyTypeObject OSSAudioType;
767db96d56Sopenharmony_cistatic PyTypeObject OSSMixerType;
777db96d56Sopenharmony_ci
787db96d56Sopenharmony_cistatic PyObject *OSSAudioError;
797db96d56Sopenharmony_ci
807db96d56Sopenharmony_ci
817db96d56Sopenharmony_ci/* ----------------------------------------------------------------------
827db96d56Sopenharmony_ci * DSP object initialization/deallocation
837db96d56Sopenharmony_ci */
847db96d56Sopenharmony_ci
857db96d56Sopenharmony_cistatic oss_audio_t *
867db96d56Sopenharmony_cinewossobject(PyObject *arg)
877db96d56Sopenharmony_ci{
887db96d56Sopenharmony_ci    oss_audio_t *self;
897db96d56Sopenharmony_ci    int fd, afmts, imode;
907db96d56Sopenharmony_ci    const char *devicename = NULL;
917db96d56Sopenharmony_ci    const char *mode = NULL;
927db96d56Sopenharmony_ci
937db96d56Sopenharmony_ci    /* Two ways to call open():
947db96d56Sopenharmony_ci         open(device, mode) (for consistency with builtin open())
957db96d56Sopenharmony_ci         open(mode)         (for backwards compatibility)
967db96d56Sopenharmony_ci       because the *first* argument is optional, parsing args is
977db96d56Sopenharmony_ci       a wee bit tricky. */
987db96d56Sopenharmony_ci    if (!PyArg_ParseTuple(arg, "s|s:open", &devicename, &mode))
997db96d56Sopenharmony_ci       return NULL;
1007db96d56Sopenharmony_ci    if (mode == NULL) {                 /* only one arg supplied */
1017db96d56Sopenharmony_ci       mode = devicename;
1027db96d56Sopenharmony_ci       devicename = NULL;
1037db96d56Sopenharmony_ci    }
1047db96d56Sopenharmony_ci
1057db96d56Sopenharmony_ci    if (strcmp(mode, "r") == 0)
1067db96d56Sopenharmony_ci        imode = O_RDONLY;
1077db96d56Sopenharmony_ci    else if (strcmp(mode, "w") == 0)
1087db96d56Sopenharmony_ci        imode = O_WRONLY;
1097db96d56Sopenharmony_ci    else if (strcmp(mode, "rw") == 0)
1107db96d56Sopenharmony_ci        imode = O_RDWR;
1117db96d56Sopenharmony_ci    else {
1127db96d56Sopenharmony_ci        PyErr_SetString(OSSAudioError, "mode must be 'r', 'w', or 'rw'");
1137db96d56Sopenharmony_ci        return NULL;
1147db96d56Sopenharmony_ci    }
1157db96d56Sopenharmony_ci
1167db96d56Sopenharmony_ci    /* Open the correct device: either the 'device' argument,
1177db96d56Sopenharmony_ci       or the AUDIODEV environment variable, or "/dev/dsp". */
1187db96d56Sopenharmony_ci    if (devicename == NULL) {              /* called with one arg */
1197db96d56Sopenharmony_ci       devicename = getenv("AUDIODEV");
1207db96d56Sopenharmony_ci       if (devicename == NULL)             /* $AUDIODEV not set */
1217db96d56Sopenharmony_ci          devicename = "/dev/dsp";
1227db96d56Sopenharmony_ci    }
1237db96d56Sopenharmony_ci
1247db96d56Sopenharmony_ci    /* Open with O_NONBLOCK to avoid hanging on devices that only allow
1257db96d56Sopenharmony_ci       one open at a time.  This does *not* affect later I/O; OSS
1267db96d56Sopenharmony_ci       provides a special ioctl() for non-blocking read/write, which is
1277db96d56Sopenharmony_ci       exposed via oss_nonblock() below. */
1287db96d56Sopenharmony_ci    fd = _Py_open(devicename, imode|O_NONBLOCK);
1297db96d56Sopenharmony_ci    if (fd == -1)
1307db96d56Sopenharmony_ci        return NULL;
1317db96d56Sopenharmony_ci
1327db96d56Sopenharmony_ci    /* And (try to) put it back in blocking mode so we get the
1337db96d56Sopenharmony_ci       expected write() semantics. */
1347db96d56Sopenharmony_ci    if (fcntl(fd, F_SETFL, 0) == -1) {
1357db96d56Sopenharmony_ci        close(fd);
1367db96d56Sopenharmony_ci        PyErr_SetFromErrnoWithFilename(PyExc_OSError, devicename);
1377db96d56Sopenharmony_ci        return NULL;
1387db96d56Sopenharmony_ci    }
1397db96d56Sopenharmony_ci
1407db96d56Sopenharmony_ci    if (ioctl(fd, SNDCTL_DSP_GETFMTS, &afmts) == -1) {
1417db96d56Sopenharmony_ci        close(fd);
1427db96d56Sopenharmony_ci        PyErr_SetFromErrnoWithFilename(PyExc_OSError, devicename);
1437db96d56Sopenharmony_ci        return NULL;
1447db96d56Sopenharmony_ci    }
1457db96d56Sopenharmony_ci    /* Create and initialize the object */
1467db96d56Sopenharmony_ci    if ((self = PyObject_New(oss_audio_t, &OSSAudioType)) == NULL) {
1477db96d56Sopenharmony_ci        close(fd);
1487db96d56Sopenharmony_ci        return NULL;
1497db96d56Sopenharmony_ci    }
1507db96d56Sopenharmony_ci    self->devicename = devicename;
1517db96d56Sopenharmony_ci    self->fd = fd;
1527db96d56Sopenharmony_ci    self->mode = imode;
1537db96d56Sopenharmony_ci    self->icount = self->ocount = 0;
1547db96d56Sopenharmony_ci    self->afmts  = afmts;
1557db96d56Sopenharmony_ci    return self;
1567db96d56Sopenharmony_ci}
1577db96d56Sopenharmony_ci
1587db96d56Sopenharmony_cistatic void
1597db96d56Sopenharmony_cioss_dealloc(oss_audio_t *self)
1607db96d56Sopenharmony_ci{
1617db96d56Sopenharmony_ci    /* if already closed, don't reclose it */
1627db96d56Sopenharmony_ci    if (self->fd != -1)
1637db96d56Sopenharmony_ci        close(self->fd);
1647db96d56Sopenharmony_ci    PyObject_Free(self);
1657db96d56Sopenharmony_ci}
1667db96d56Sopenharmony_ci
1677db96d56Sopenharmony_ci
1687db96d56Sopenharmony_ci/* ----------------------------------------------------------------------
1697db96d56Sopenharmony_ci * Mixer object initialization/deallocation
1707db96d56Sopenharmony_ci */
1717db96d56Sopenharmony_ci
1727db96d56Sopenharmony_cistatic oss_mixer_t *
1737db96d56Sopenharmony_cinewossmixerobject(PyObject *arg)
1747db96d56Sopenharmony_ci{
1757db96d56Sopenharmony_ci    const char *devicename = NULL;
1767db96d56Sopenharmony_ci    int fd;
1777db96d56Sopenharmony_ci    oss_mixer_t *self;
1787db96d56Sopenharmony_ci
1797db96d56Sopenharmony_ci    if (!PyArg_ParseTuple(arg, "|s", &devicename)) {
1807db96d56Sopenharmony_ci        return NULL;
1817db96d56Sopenharmony_ci    }
1827db96d56Sopenharmony_ci
1837db96d56Sopenharmony_ci    if (devicename == NULL) {
1847db96d56Sopenharmony_ci        devicename = getenv("MIXERDEV");
1857db96d56Sopenharmony_ci        if (devicename == NULL)            /* MIXERDEV not set */
1867db96d56Sopenharmony_ci            devicename = "/dev/mixer";
1877db96d56Sopenharmony_ci    }
1887db96d56Sopenharmony_ci
1897db96d56Sopenharmony_ci    fd = _Py_open(devicename, O_RDWR);
1907db96d56Sopenharmony_ci    if (fd == -1)
1917db96d56Sopenharmony_ci        return NULL;
1927db96d56Sopenharmony_ci
1937db96d56Sopenharmony_ci    if ((self = PyObject_New(oss_mixer_t, &OSSMixerType)) == NULL) {
1947db96d56Sopenharmony_ci        close(fd);
1957db96d56Sopenharmony_ci        return NULL;
1967db96d56Sopenharmony_ci    }
1977db96d56Sopenharmony_ci
1987db96d56Sopenharmony_ci    self->fd = fd;
1997db96d56Sopenharmony_ci
2007db96d56Sopenharmony_ci    return self;
2017db96d56Sopenharmony_ci}
2027db96d56Sopenharmony_ci
2037db96d56Sopenharmony_cistatic void
2047db96d56Sopenharmony_cioss_mixer_dealloc(oss_mixer_t *self)
2057db96d56Sopenharmony_ci{
2067db96d56Sopenharmony_ci    /* if already closed, don't reclose it */
2077db96d56Sopenharmony_ci    if (self->fd != -1)
2087db96d56Sopenharmony_ci        close(self->fd);
2097db96d56Sopenharmony_ci    PyObject_Free(self);
2107db96d56Sopenharmony_ci}
2117db96d56Sopenharmony_ci
2127db96d56Sopenharmony_ci
2137db96d56Sopenharmony_ci/* Methods to wrap the OSS ioctls.  The calling convention is pretty
2147db96d56Sopenharmony_ci   simple:
2157db96d56Sopenharmony_ci     nonblock()        -> ioctl(fd, SNDCTL_DSP_NONBLOCK)
2167db96d56Sopenharmony_ci     fmt = setfmt(fmt) -> ioctl(fd, SNDCTL_DSP_SETFMT, &fmt)
2177db96d56Sopenharmony_ci     etc.
2187db96d56Sopenharmony_ci*/
2197db96d56Sopenharmony_ci
2207db96d56Sopenharmony_ci
2217db96d56Sopenharmony_ci/* ----------------------------------------------------------------------
2227db96d56Sopenharmony_ci * Helper functions
2237db96d56Sopenharmony_ci */
2247db96d56Sopenharmony_ci
2257db96d56Sopenharmony_ci/* Check if a given file descriptor is valid (i.e. hasn't been closed).
2267db96d56Sopenharmony_ci * If true, return 1. Otherwise, raise ValueError and return 0.
2277db96d56Sopenharmony_ci */
2287db96d56Sopenharmony_cistatic int _is_fd_valid(int fd)
2297db96d56Sopenharmony_ci{
2307db96d56Sopenharmony_ci    /* the FD is set to -1 in oss_close()/oss_mixer_close() */
2317db96d56Sopenharmony_ci    if (fd >= 0) {
2327db96d56Sopenharmony_ci        return 1;
2337db96d56Sopenharmony_ci    } else {
2347db96d56Sopenharmony_ci        PyErr_SetString(PyExc_ValueError,
2357db96d56Sopenharmony_ci                        "Operation on closed OSS device.");
2367db96d56Sopenharmony_ci        return 0;
2377db96d56Sopenharmony_ci    }
2387db96d56Sopenharmony_ci}
2397db96d56Sopenharmony_ci
2407db96d56Sopenharmony_ci/* _do_ioctl_1() is a private helper function used for the OSS ioctls --
2417db96d56Sopenharmony_ci   SNDCTL_DSP_{SETFMT,CHANNELS,SPEED} -- that are called from C
2427db96d56Sopenharmony_ci   like this:
2437db96d56Sopenharmony_ci     ioctl(fd, SNDCTL_DSP_cmd, &arg)
2447db96d56Sopenharmony_ci
2457db96d56Sopenharmony_ci   where arg is the value to set, and on return the driver sets arg to
2467db96d56Sopenharmony_ci   the value that was actually set.  Mapping this to Python is obvious:
2477db96d56Sopenharmony_ci     arg = dsp.xxx(arg)
2487db96d56Sopenharmony_ci*/
2497db96d56Sopenharmony_cistatic PyObject *
2507db96d56Sopenharmony_ci_do_ioctl_1(int fd, PyObject *args, char *fname, unsigned long cmd)
2517db96d56Sopenharmony_ci{
2527db96d56Sopenharmony_ci    char argfmt[33] = "i:";
2537db96d56Sopenharmony_ci    int arg;
2547db96d56Sopenharmony_ci
2557db96d56Sopenharmony_ci    assert(strlen(fname) <= 30);
2567db96d56Sopenharmony_ci    strncat(argfmt, fname, 30);
2577db96d56Sopenharmony_ci    if (!PyArg_ParseTuple(args, argfmt, &arg))
2587db96d56Sopenharmony_ci        return NULL;
2597db96d56Sopenharmony_ci
2607db96d56Sopenharmony_ci    if (ioctl(fd, cmd, &arg) == -1)
2617db96d56Sopenharmony_ci        return PyErr_SetFromErrno(PyExc_OSError);
2627db96d56Sopenharmony_ci    return PyLong_FromLong(arg);
2637db96d56Sopenharmony_ci}
2647db96d56Sopenharmony_ci
2657db96d56Sopenharmony_ci
2667db96d56Sopenharmony_ci/* _do_ioctl_1_internal() is a wrapper for ioctls that take no inputs
2677db96d56Sopenharmony_ci   but return an output -- ie. we need to pass a pointer to a local C
2687db96d56Sopenharmony_ci   variable so the driver can write its output there, but from Python
2697db96d56Sopenharmony_ci   all we see is the return value.  For example,
2707db96d56Sopenharmony_ci   SOUND_MIXER_READ_DEVMASK returns a bitmask of available mixer
2717db96d56Sopenharmony_ci   devices, but does not use the value of the parameter passed-in in any
2727db96d56Sopenharmony_ci   way.
2737db96d56Sopenharmony_ci*/
2747db96d56Sopenharmony_cistatic PyObject *
2757db96d56Sopenharmony_ci_do_ioctl_1_internal(int fd, PyObject *args, char *fname, unsigned long cmd)
2767db96d56Sopenharmony_ci{
2777db96d56Sopenharmony_ci    char argfmt[32] = ":";
2787db96d56Sopenharmony_ci    int arg = 0;
2797db96d56Sopenharmony_ci
2807db96d56Sopenharmony_ci    assert(strlen(fname) <= 30);
2817db96d56Sopenharmony_ci    strncat(argfmt, fname, 30);
2827db96d56Sopenharmony_ci    if (!PyArg_ParseTuple(args, argfmt, &arg))
2837db96d56Sopenharmony_ci        return NULL;
2847db96d56Sopenharmony_ci
2857db96d56Sopenharmony_ci    if (ioctl(fd, cmd, &arg) == -1)
2867db96d56Sopenharmony_ci        return PyErr_SetFromErrno(PyExc_OSError);
2877db96d56Sopenharmony_ci    return PyLong_FromLong(arg);
2887db96d56Sopenharmony_ci}
2897db96d56Sopenharmony_ci
2907db96d56Sopenharmony_ci
2917db96d56Sopenharmony_ci
2927db96d56Sopenharmony_ci/* _do_ioctl_0() is a private helper for the no-argument ioctls:
2937db96d56Sopenharmony_ci   SNDCTL_DSP_{SYNC,RESET,POST}. */
2947db96d56Sopenharmony_cistatic PyObject *
2957db96d56Sopenharmony_ci_do_ioctl_0(int fd, PyObject *args, char *fname, unsigned long cmd)
2967db96d56Sopenharmony_ci{
2977db96d56Sopenharmony_ci    char argfmt[32] = ":";
2987db96d56Sopenharmony_ci    int rv;
2997db96d56Sopenharmony_ci
3007db96d56Sopenharmony_ci    assert(strlen(fname) <= 30);
3017db96d56Sopenharmony_ci    strncat(argfmt, fname, 30);
3027db96d56Sopenharmony_ci    if (!PyArg_ParseTuple(args, argfmt))
3037db96d56Sopenharmony_ci        return NULL;
3047db96d56Sopenharmony_ci
3057db96d56Sopenharmony_ci    /* According to hannu@opensound.com, all three of the ioctls that
3067db96d56Sopenharmony_ci       use this function can block, so release the GIL.  This is
3077db96d56Sopenharmony_ci       especially important for SYNC, which can block for several
3087db96d56Sopenharmony_ci       seconds. */
3097db96d56Sopenharmony_ci    Py_BEGIN_ALLOW_THREADS
3107db96d56Sopenharmony_ci    rv = ioctl(fd, cmd, 0);
3117db96d56Sopenharmony_ci    Py_END_ALLOW_THREADS
3127db96d56Sopenharmony_ci
3137db96d56Sopenharmony_ci    if (rv == -1)
3147db96d56Sopenharmony_ci        return PyErr_SetFromErrno(PyExc_OSError);
3157db96d56Sopenharmony_ci    Py_RETURN_NONE;
3167db96d56Sopenharmony_ci}
3177db96d56Sopenharmony_ci
3187db96d56Sopenharmony_ci
3197db96d56Sopenharmony_ci/* ----------------------------------------------------------------------
3207db96d56Sopenharmony_ci * Methods of DSP objects (OSSAudioType)
3217db96d56Sopenharmony_ci */
3227db96d56Sopenharmony_ci
3237db96d56Sopenharmony_cistatic PyObject *
3247db96d56Sopenharmony_cioss_nonblock(oss_audio_t *self, PyObject *unused)
3257db96d56Sopenharmony_ci{
3267db96d56Sopenharmony_ci    if (!_is_fd_valid(self->fd))
3277db96d56Sopenharmony_ci        return NULL;
3287db96d56Sopenharmony_ci
3297db96d56Sopenharmony_ci    /* Hmmm: it doesn't appear to be possible to return to blocking
3307db96d56Sopenharmony_ci       mode once we're in non-blocking mode! */
3317db96d56Sopenharmony_ci    if (ioctl(self->fd, SNDCTL_DSP_NONBLOCK, NULL) == -1)
3327db96d56Sopenharmony_ci        return PyErr_SetFromErrno(PyExc_OSError);
3337db96d56Sopenharmony_ci    Py_RETURN_NONE;
3347db96d56Sopenharmony_ci}
3357db96d56Sopenharmony_ci
3367db96d56Sopenharmony_cistatic PyObject *
3377db96d56Sopenharmony_cioss_setfmt(oss_audio_t *self, PyObject *args)
3387db96d56Sopenharmony_ci{
3397db96d56Sopenharmony_ci    if (!_is_fd_valid(self->fd))
3407db96d56Sopenharmony_ci        return NULL;
3417db96d56Sopenharmony_ci
3427db96d56Sopenharmony_ci    return _do_ioctl_1(self->fd, args, "setfmt", SNDCTL_DSP_SETFMT);
3437db96d56Sopenharmony_ci}
3447db96d56Sopenharmony_ci
3457db96d56Sopenharmony_cistatic PyObject *
3467db96d56Sopenharmony_cioss_getfmts(oss_audio_t *self, PyObject *unused)
3477db96d56Sopenharmony_ci{
3487db96d56Sopenharmony_ci    int mask;
3497db96d56Sopenharmony_ci
3507db96d56Sopenharmony_ci    if (!_is_fd_valid(self->fd))
3517db96d56Sopenharmony_ci        return NULL;
3527db96d56Sopenharmony_ci
3537db96d56Sopenharmony_ci    if (ioctl(self->fd, SNDCTL_DSP_GETFMTS, &mask) == -1)
3547db96d56Sopenharmony_ci        return PyErr_SetFromErrno(PyExc_OSError);
3557db96d56Sopenharmony_ci    return PyLong_FromLong(mask);
3567db96d56Sopenharmony_ci}
3577db96d56Sopenharmony_ci
3587db96d56Sopenharmony_cistatic PyObject *
3597db96d56Sopenharmony_cioss_channels(oss_audio_t *self, PyObject *args)
3607db96d56Sopenharmony_ci{
3617db96d56Sopenharmony_ci    if (!_is_fd_valid(self->fd))
3627db96d56Sopenharmony_ci        return NULL;
3637db96d56Sopenharmony_ci
3647db96d56Sopenharmony_ci    return _do_ioctl_1(self->fd, args, "channels", SNDCTL_DSP_CHANNELS);
3657db96d56Sopenharmony_ci}
3667db96d56Sopenharmony_ci
3677db96d56Sopenharmony_cistatic PyObject *
3687db96d56Sopenharmony_cioss_speed(oss_audio_t *self, PyObject *args)
3697db96d56Sopenharmony_ci{
3707db96d56Sopenharmony_ci    if (!_is_fd_valid(self->fd))
3717db96d56Sopenharmony_ci        return NULL;
3727db96d56Sopenharmony_ci
3737db96d56Sopenharmony_ci    return _do_ioctl_1(self->fd, args, "speed", SNDCTL_DSP_SPEED);
3747db96d56Sopenharmony_ci}
3757db96d56Sopenharmony_ci
3767db96d56Sopenharmony_cistatic PyObject *
3777db96d56Sopenharmony_cioss_sync(oss_audio_t *self, PyObject *args)
3787db96d56Sopenharmony_ci{
3797db96d56Sopenharmony_ci    if (!_is_fd_valid(self->fd))
3807db96d56Sopenharmony_ci        return NULL;
3817db96d56Sopenharmony_ci
3827db96d56Sopenharmony_ci    return _do_ioctl_0(self->fd, args, "sync", SNDCTL_DSP_SYNC);
3837db96d56Sopenharmony_ci}
3847db96d56Sopenharmony_ci
3857db96d56Sopenharmony_cistatic PyObject *
3867db96d56Sopenharmony_cioss_reset(oss_audio_t *self, PyObject *args)
3877db96d56Sopenharmony_ci{
3887db96d56Sopenharmony_ci    if (!_is_fd_valid(self->fd))
3897db96d56Sopenharmony_ci        return NULL;
3907db96d56Sopenharmony_ci
3917db96d56Sopenharmony_ci    return _do_ioctl_0(self->fd, args, "reset", SNDCTL_DSP_RESET);
3927db96d56Sopenharmony_ci}
3937db96d56Sopenharmony_ci
3947db96d56Sopenharmony_cistatic PyObject *
3957db96d56Sopenharmony_cioss_post(oss_audio_t *self, PyObject *args)
3967db96d56Sopenharmony_ci{
3977db96d56Sopenharmony_ci    if (!_is_fd_valid(self->fd))
3987db96d56Sopenharmony_ci        return NULL;
3997db96d56Sopenharmony_ci
4007db96d56Sopenharmony_ci    return _do_ioctl_0(self->fd, args, "post", SNDCTL_DSP_POST);
4017db96d56Sopenharmony_ci}
4027db96d56Sopenharmony_ci
4037db96d56Sopenharmony_ci
4047db96d56Sopenharmony_ci/* Regular file methods: read(), write(), close(), etc. as well
4057db96d56Sopenharmony_ci   as one convenience method, writeall(). */
4067db96d56Sopenharmony_ci
4077db96d56Sopenharmony_cistatic PyObject *
4087db96d56Sopenharmony_cioss_read(oss_audio_t *self, PyObject *args)
4097db96d56Sopenharmony_ci{
4107db96d56Sopenharmony_ci    Py_ssize_t size, count;
4117db96d56Sopenharmony_ci    PyObject *rv;
4127db96d56Sopenharmony_ci
4137db96d56Sopenharmony_ci    if (!_is_fd_valid(self->fd))
4147db96d56Sopenharmony_ci        return NULL;
4157db96d56Sopenharmony_ci
4167db96d56Sopenharmony_ci    if (!PyArg_ParseTuple(args, "n:read", &size))
4177db96d56Sopenharmony_ci        return NULL;
4187db96d56Sopenharmony_ci
4197db96d56Sopenharmony_ci    rv = PyBytes_FromStringAndSize(NULL, size);
4207db96d56Sopenharmony_ci    if (rv == NULL)
4217db96d56Sopenharmony_ci        return NULL;
4227db96d56Sopenharmony_ci
4237db96d56Sopenharmony_ci    count = _Py_read(self->fd, PyBytes_AS_STRING(rv), size);
4247db96d56Sopenharmony_ci    if (count == -1) {
4257db96d56Sopenharmony_ci        Py_DECREF(rv);
4267db96d56Sopenharmony_ci        return NULL;
4277db96d56Sopenharmony_ci    }
4287db96d56Sopenharmony_ci
4297db96d56Sopenharmony_ci    self->icount += count;
4307db96d56Sopenharmony_ci    _PyBytes_Resize(&rv, count);
4317db96d56Sopenharmony_ci    return rv;
4327db96d56Sopenharmony_ci}
4337db96d56Sopenharmony_ci
4347db96d56Sopenharmony_cistatic PyObject *
4357db96d56Sopenharmony_cioss_write(oss_audio_t *self, PyObject *args)
4367db96d56Sopenharmony_ci{
4377db96d56Sopenharmony_ci    Py_buffer data;
4387db96d56Sopenharmony_ci    Py_ssize_t rv;
4397db96d56Sopenharmony_ci
4407db96d56Sopenharmony_ci    if (!_is_fd_valid(self->fd))
4417db96d56Sopenharmony_ci        return NULL;
4427db96d56Sopenharmony_ci
4437db96d56Sopenharmony_ci    if (!PyArg_ParseTuple(args, "y*:write", &data)) {
4447db96d56Sopenharmony_ci        return NULL;
4457db96d56Sopenharmony_ci    }
4467db96d56Sopenharmony_ci
4477db96d56Sopenharmony_ci    rv = _Py_write(self->fd, data.buf, data.len);
4487db96d56Sopenharmony_ci    PyBuffer_Release(&data);
4497db96d56Sopenharmony_ci    if (rv == -1)
4507db96d56Sopenharmony_ci        return NULL;
4517db96d56Sopenharmony_ci
4527db96d56Sopenharmony_ci    self->ocount += rv;
4537db96d56Sopenharmony_ci    return PyLong_FromLong(rv);
4547db96d56Sopenharmony_ci}
4557db96d56Sopenharmony_ci
4567db96d56Sopenharmony_cistatic PyObject *
4577db96d56Sopenharmony_cioss_writeall(oss_audio_t *self, PyObject *args)
4587db96d56Sopenharmony_ci{
4597db96d56Sopenharmony_ci    Py_buffer data;
4607db96d56Sopenharmony_ci    const char *cp;
4617db96d56Sopenharmony_ci    Py_ssize_t size;
4627db96d56Sopenharmony_ci    Py_ssize_t rv;
4637db96d56Sopenharmony_ci    fd_set write_set_fds;
4647db96d56Sopenharmony_ci    int select_rv;
4657db96d56Sopenharmony_ci
4667db96d56Sopenharmony_ci    /* NB. writeall() is only useful in non-blocking mode: according to
4677db96d56Sopenharmony_ci       Guenter Geiger <geiger@xdv.org> on the linux-audio-dev list
4687db96d56Sopenharmony_ci       (http://eca.cx/lad/2002/11/0380.html), OSS guarantees that
4697db96d56Sopenharmony_ci       write() in blocking mode consumes the whole buffer.  In blocking
4707db96d56Sopenharmony_ci       mode, the behaviour of write() and writeall() from Python is
4717db96d56Sopenharmony_ci       indistinguishable. */
4727db96d56Sopenharmony_ci
4737db96d56Sopenharmony_ci    if (!_is_fd_valid(self->fd))
4747db96d56Sopenharmony_ci        return NULL;
4757db96d56Sopenharmony_ci
4767db96d56Sopenharmony_ci    if (!PyArg_ParseTuple(args, "y*:writeall", &data))
4777db96d56Sopenharmony_ci        return NULL;
4787db96d56Sopenharmony_ci
4797db96d56Sopenharmony_ci    if (!_PyIsSelectable_fd(self->fd)) {
4807db96d56Sopenharmony_ci        PyErr_SetString(PyExc_ValueError,
4817db96d56Sopenharmony_ci                        "file descriptor out of range for select");
4827db96d56Sopenharmony_ci        PyBuffer_Release(&data);
4837db96d56Sopenharmony_ci        return NULL;
4847db96d56Sopenharmony_ci    }
4857db96d56Sopenharmony_ci    /* use select to wait for audio device to be available */
4867db96d56Sopenharmony_ci    FD_ZERO(&write_set_fds);
4877db96d56Sopenharmony_ci    FD_SET(self->fd, &write_set_fds);
4887db96d56Sopenharmony_ci    cp = (const char *)data.buf;
4897db96d56Sopenharmony_ci    size = data.len;
4907db96d56Sopenharmony_ci
4917db96d56Sopenharmony_ci    while (size > 0) {
4927db96d56Sopenharmony_ci        Py_BEGIN_ALLOW_THREADS
4937db96d56Sopenharmony_ci        select_rv = select(self->fd+1, NULL, &write_set_fds, NULL, NULL);
4947db96d56Sopenharmony_ci        Py_END_ALLOW_THREADS
4957db96d56Sopenharmony_ci
4967db96d56Sopenharmony_ci        assert(select_rv != 0);   /* no timeout, can't expire */
4977db96d56Sopenharmony_ci        if (select_rv == -1) {
4987db96d56Sopenharmony_ci            PyBuffer_Release(&data);
4997db96d56Sopenharmony_ci            return PyErr_SetFromErrno(PyExc_OSError);
5007db96d56Sopenharmony_ci        }
5017db96d56Sopenharmony_ci
5027db96d56Sopenharmony_ci        rv = _Py_write(self->fd, cp, Py_MIN(size, INT_MAX));
5037db96d56Sopenharmony_ci        if (rv == -1) {
5047db96d56Sopenharmony_ci            /* buffer is full, try again */
5057db96d56Sopenharmony_ci            if (errno == EAGAIN) {
5067db96d56Sopenharmony_ci                PyErr_Clear();
5077db96d56Sopenharmony_ci                continue;
5087db96d56Sopenharmony_ci            }
5097db96d56Sopenharmony_ci            /* it's a real error */
5107db96d56Sopenharmony_ci            PyBuffer_Release(&data);
5117db96d56Sopenharmony_ci            return NULL;
5127db96d56Sopenharmony_ci        }
5137db96d56Sopenharmony_ci
5147db96d56Sopenharmony_ci        /* wrote rv bytes */
5157db96d56Sopenharmony_ci        self->ocount += rv;
5167db96d56Sopenharmony_ci        size -= rv;
5177db96d56Sopenharmony_ci        cp += rv;
5187db96d56Sopenharmony_ci    }
5197db96d56Sopenharmony_ci    PyBuffer_Release(&data);
5207db96d56Sopenharmony_ci    Py_RETURN_NONE;
5217db96d56Sopenharmony_ci}
5227db96d56Sopenharmony_ci
5237db96d56Sopenharmony_cistatic PyObject *
5247db96d56Sopenharmony_cioss_close(oss_audio_t *self, PyObject *unused)
5257db96d56Sopenharmony_ci{
5267db96d56Sopenharmony_ci    if (self->fd >= 0) {
5277db96d56Sopenharmony_ci        Py_BEGIN_ALLOW_THREADS
5287db96d56Sopenharmony_ci        close(self->fd);
5297db96d56Sopenharmony_ci        Py_END_ALLOW_THREADS
5307db96d56Sopenharmony_ci        self->fd = -1;
5317db96d56Sopenharmony_ci    }
5327db96d56Sopenharmony_ci    Py_RETURN_NONE;
5337db96d56Sopenharmony_ci}
5347db96d56Sopenharmony_ci
5357db96d56Sopenharmony_cistatic PyObject *
5367db96d56Sopenharmony_cioss_self(PyObject *self, PyObject *unused)
5377db96d56Sopenharmony_ci{
5387db96d56Sopenharmony_ci    Py_INCREF(self);
5397db96d56Sopenharmony_ci    return self;
5407db96d56Sopenharmony_ci}
5417db96d56Sopenharmony_ci
5427db96d56Sopenharmony_cistatic PyObject *
5437db96d56Sopenharmony_cioss_exit(PyObject *self, PyObject *unused)
5447db96d56Sopenharmony_ci{
5457db96d56Sopenharmony_ci    _Py_IDENTIFIER(close);
5467db96d56Sopenharmony_ci
5477db96d56Sopenharmony_ci    PyObject *ret = _PyObject_CallMethodIdNoArgs(self, &PyId_close);
5487db96d56Sopenharmony_ci    if (!ret)
5497db96d56Sopenharmony_ci        return NULL;
5507db96d56Sopenharmony_ci    Py_DECREF(ret);
5517db96d56Sopenharmony_ci    Py_RETURN_NONE;
5527db96d56Sopenharmony_ci}
5537db96d56Sopenharmony_ci
5547db96d56Sopenharmony_cistatic PyObject *
5557db96d56Sopenharmony_cioss_fileno(oss_audio_t *self, PyObject *unused)
5567db96d56Sopenharmony_ci{
5577db96d56Sopenharmony_ci    if (!_is_fd_valid(self->fd))
5587db96d56Sopenharmony_ci        return NULL;
5597db96d56Sopenharmony_ci
5607db96d56Sopenharmony_ci    return PyLong_FromLong(self->fd);
5617db96d56Sopenharmony_ci}
5627db96d56Sopenharmony_ci
5637db96d56Sopenharmony_ci
5647db96d56Sopenharmony_ci/* Convenience methods: these generally wrap a couple of ioctls into one
5657db96d56Sopenharmony_ci   common task. */
5667db96d56Sopenharmony_ci
5677db96d56Sopenharmony_cistatic PyObject *
5687db96d56Sopenharmony_cioss_setparameters(oss_audio_t *self, PyObject *args)
5697db96d56Sopenharmony_ci{
5707db96d56Sopenharmony_ci    int wanted_fmt, wanted_channels, wanted_rate, strict=0;
5717db96d56Sopenharmony_ci    int fmt, channels, rate;
5727db96d56Sopenharmony_ci
5737db96d56Sopenharmony_ci    if (!_is_fd_valid(self->fd))
5747db96d56Sopenharmony_ci        return NULL;
5757db96d56Sopenharmony_ci
5767db96d56Sopenharmony_ci    if (!PyArg_ParseTuple(args, "iii|i:setparameters",
5777db96d56Sopenharmony_ci                          &wanted_fmt, &wanted_channels, &wanted_rate,
5787db96d56Sopenharmony_ci                          &strict))
5797db96d56Sopenharmony_ci        return NULL;
5807db96d56Sopenharmony_ci
5817db96d56Sopenharmony_ci    fmt = wanted_fmt;
5827db96d56Sopenharmony_ci    if (ioctl(self->fd, SNDCTL_DSP_SETFMT, &fmt) == -1) {
5837db96d56Sopenharmony_ci        return PyErr_SetFromErrno(PyExc_OSError);
5847db96d56Sopenharmony_ci    }
5857db96d56Sopenharmony_ci    if (strict && fmt != wanted_fmt) {
5867db96d56Sopenharmony_ci        return PyErr_Format
5877db96d56Sopenharmony_ci            (OSSAudioError,
5887db96d56Sopenharmony_ci             "unable to set requested format (wanted %d, got %d)",
5897db96d56Sopenharmony_ci             wanted_fmt, fmt);
5907db96d56Sopenharmony_ci    }
5917db96d56Sopenharmony_ci
5927db96d56Sopenharmony_ci    channels = wanted_channels;
5937db96d56Sopenharmony_ci    if (ioctl(self->fd, SNDCTL_DSP_CHANNELS, &channels) == -1) {
5947db96d56Sopenharmony_ci        return PyErr_SetFromErrno(PyExc_OSError);
5957db96d56Sopenharmony_ci    }
5967db96d56Sopenharmony_ci    if (strict && channels != wanted_channels) {
5977db96d56Sopenharmony_ci        return PyErr_Format
5987db96d56Sopenharmony_ci            (OSSAudioError,
5997db96d56Sopenharmony_ci             "unable to set requested channels (wanted %d, got %d)",
6007db96d56Sopenharmony_ci             wanted_channels, channels);
6017db96d56Sopenharmony_ci    }
6027db96d56Sopenharmony_ci
6037db96d56Sopenharmony_ci    rate = wanted_rate;
6047db96d56Sopenharmony_ci    if (ioctl(self->fd, SNDCTL_DSP_SPEED, &rate) == -1) {
6057db96d56Sopenharmony_ci        return PyErr_SetFromErrno(PyExc_OSError);
6067db96d56Sopenharmony_ci    }
6077db96d56Sopenharmony_ci    if (strict && rate != wanted_rate) {
6087db96d56Sopenharmony_ci        return PyErr_Format
6097db96d56Sopenharmony_ci            (OSSAudioError,
6107db96d56Sopenharmony_ci             "unable to set requested rate (wanted %d, got %d)",
6117db96d56Sopenharmony_ci             wanted_rate, rate);
6127db96d56Sopenharmony_ci    }
6137db96d56Sopenharmony_ci
6147db96d56Sopenharmony_ci    /* Construct the return value: a (fmt, channels, rate) tuple that
6157db96d56Sopenharmony_ci       tells what the audio hardware was actually set to. */
6167db96d56Sopenharmony_ci    return Py_BuildValue("(iii)", fmt, channels, rate);
6177db96d56Sopenharmony_ci}
6187db96d56Sopenharmony_ci
6197db96d56Sopenharmony_cistatic int
6207db96d56Sopenharmony_ci_ssize(oss_audio_t *self, int *nchannels, int *ssize)
6217db96d56Sopenharmony_ci{
6227db96d56Sopenharmony_ci    int fmt;
6237db96d56Sopenharmony_ci
6247db96d56Sopenharmony_ci    fmt = 0;
6257db96d56Sopenharmony_ci    if (ioctl(self->fd, SNDCTL_DSP_SETFMT, &fmt) < 0)
6267db96d56Sopenharmony_ci        return -errno;
6277db96d56Sopenharmony_ci
6287db96d56Sopenharmony_ci    switch (fmt) {
6297db96d56Sopenharmony_ci    case AFMT_MU_LAW:
6307db96d56Sopenharmony_ci    case AFMT_A_LAW:
6317db96d56Sopenharmony_ci    case AFMT_U8:
6327db96d56Sopenharmony_ci    case AFMT_S8:
6337db96d56Sopenharmony_ci        *ssize = 1;                     /* 8 bit formats: 1 byte */
6347db96d56Sopenharmony_ci        break;
6357db96d56Sopenharmony_ci    case AFMT_S16_LE:
6367db96d56Sopenharmony_ci    case AFMT_S16_BE:
6377db96d56Sopenharmony_ci    case AFMT_U16_LE:
6387db96d56Sopenharmony_ci    case AFMT_U16_BE:
6397db96d56Sopenharmony_ci        *ssize = 2;                     /* 16 bit formats: 2 byte */
6407db96d56Sopenharmony_ci        break;
6417db96d56Sopenharmony_ci    case AFMT_MPEG:
6427db96d56Sopenharmony_ci    case AFMT_IMA_ADPCM:
6437db96d56Sopenharmony_ci    default:
6447db96d56Sopenharmony_ci        return -EOPNOTSUPP;
6457db96d56Sopenharmony_ci    }
6467db96d56Sopenharmony_ci    if (ioctl(self->fd, SNDCTL_DSP_CHANNELS, nchannels) < 0)
6477db96d56Sopenharmony_ci        return -errno;
6487db96d56Sopenharmony_ci    return 0;
6497db96d56Sopenharmony_ci}
6507db96d56Sopenharmony_ci
6517db96d56Sopenharmony_ci
6527db96d56Sopenharmony_ci/* bufsize returns the size of the hardware audio buffer in number
6537db96d56Sopenharmony_ci   of samples */
6547db96d56Sopenharmony_cistatic PyObject *
6557db96d56Sopenharmony_cioss_bufsize(oss_audio_t *self, PyObject *unused)
6567db96d56Sopenharmony_ci{
6577db96d56Sopenharmony_ci    audio_buf_info ai;
6587db96d56Sopenharmony_ci    int nchannels=0, ssize=0;
6597db96d56Sopenharmony_ci
6607db96d56Sopenharmony_ci    if (!_is_fd_valid(self->fd))
6617db96d56Sopenharmony_ci        return NULL;
6627db96d56Sopenharmony_ci
6637db96d56Sopenharmony_ci    if (_ssize(self, &nchannels, &ssize) < 0 || !nchannels || !ssize) {
6647db96d56Sopenharmony_ci        PyErr_SetFromErrno(PyExc_OSError);
6657db96d56Sopenharmony_ci        return NULL;
6667db96d56Sopenharmony_ci    }
6677db96d56Sopenharmony_ci    if (ioctl(self->fd, SNDCTL_DSP_GETOSPACE, &ai) < 0) {
6687db96d56Sopenharmony_ci        PyErr_SetFromErrno(PyExc_OSError);
6697db96d56Sopenharmony_ci        return NULL;
6707db96d56Sopenharmony_ci    }
6717db96d56Sopenharmony_ci    return PyLong_FromLong((ai.fragstotal * ai.fragsize) / (nchannels * ssize));
6727db96d56Sopenharmony_ci}
6737db96d56Sopenharmony_ci
6747db96d56Sopenharmony_ci/* obufcount returns the number of samples that are available in the
6757db96d56Sopenharmony_ci   hardware for playing */
6767db96d56Sopenharmony_cistatic PyObject *
6777db96d56Sopenharmony_cioss_obufcount(oss_audio_t *self, PyObject *unused)
6787db96d56Sopenharmony_ci{
6797db96d56Sopenharmony_ci    audio_buf_info ai;
6807db96d56Sopenharmony_ci    int nchannels=0, ssize=0;
6817db96d56Sopenharmony_ci
6827db96d56Sopenharmony_ci    if (!_is_fd_valid(self->fd))
6837db96d56Sopenharmony_ci        return NULL;
6847db96d56Sopenharmony_ci
6857db96d56Sopenharmony_ci    if (_ssize(self, &nchannels, &ssize) < 0 || !nchannels || !ssize) {
6867db96d56Sopenharmony_ci        PyErr_SetFromErrno(PyExc_OSError);
6877db96d56Sopenharmony_ci        return NULL;
6887db96d56Sopenharmony_ci    }
6897db96d56Sopenharmony_ci    if (ioctl(self->fd, SNDCTL_DSP_GETOSPACE, &ai) < 0) {
6907db96d56Sopenharmony_ci        PyErr_SetFromErrno(PyExc_OSError);
6917db96d56Sopenharmony_ci        return NULL;
6927db96d56Sopenharmony_ci    }
6937db96d56Sopenharmony_ci    return PyLong_FromLong((ai.fragstotal * ai.fragsize - ai.bytes) /
6947db96d56Sopenharmony_ci                          (ssize * nchannels));
6957db96d56Sopenharmony_ci}
6967db96d56Sopenharmony_ci
6977db96d56Sopenharmony_ci/* obufcount returns the number of samples that can be played without
6987db96d56Sopenharmony_ci   blocking */
6997db96d56Sopenharmony_cistatic PyObject *
7007db96d56Sopenharmony_cioss_obuffree(oss_audio_t *self, PyObject *unused)
7017db96d56Sopenharmony_ci{
7027db96d56Sopenharmony_ci    audio_buf_info ai;
7037db96d56Sopenharmony_ci    int nchannels=0, ssize=0;
7047db96d56Sopenharmony_ci
7057db96d56Sopenharmony_ci    if (!_is_fd_valid(self->fd))
7067db96d56Sopenharmony_ci        return NULL;
7077db96d56Sopenharmony_ci
7087db96d56Sopenharmony_ci    if (_ssize(self, &nchannels, &ssize) < 0 || !nchannels || !ssize) {
7097db96d56Sopenharmony_ci        PyErr_SetFromErrno(PyExc_OSError);
7107db96d56Sopenharmony_ci        return NULL;
7117db96d56Sopenharmony_ci    }
7127db96d56Sopenharmony_ci    if (ioctl(self->fd, SNDCTL_DSP_GETOSPACE, &ai) < 0) {
7137db96d56Sopenharmony_ci        PyErr_SetFromErrno(PyExc_OSError);
7147db96d56Sopenharmony_ci        return NULL;
7157db96d56Sopenharmony_ci    }
7167db96d56Sopenharmony_ci    return PyLong_FromLong(ai.bytes / (ssize * nchannels));
7177db96d56Sopenharmony_ci}
7187db96d56Sopenharmony_ci
7197db96d56Sopenharmony_cistatic PyObject *
7207db96d56Sopenharmony_cioss_getptr(oss_audio_t *self, PyObject *unused)
7217db96d56Sopenharmony_ci{
7227db96d56Sopenharmony_ci    count_info info;
7237db96d56Sopenharmony_ci    int req;
7247db96d56Sopenharmony_ci
7257db96d56Sopenharmony_ci    if (!_is_fd_valid(self->fd))
7267db96d56Sopenharmony_ci        return NULL;
7277db96d56Sopenharmony_ci
7287db96d56Sopenharmony_ci    if (self->mode == O_RDONLY)
7297db96d56Sopenharmony_ci        req = SNDCTL_DSP_GETIPTR;
7307db96d56Sopenharmony_ci    else
7317db96d56Sopenharmony_ci        req = SNDCTL_DSP_GETOPTR;
7327db96d56Sopenharmony_ci    if (ioctl(self->fd, req, &info) == -1) {
7337db96d56Sopenharmony_ci        PyErr_SetFromErrno(PyExc_OSError);
7347db96d56Sopenharmony_ci        return NULL;
7357db96d56Sopenharmony_ci    }
7367db96d56Sopenharmony_ci    return Py_BuildValue("iii", info.bytes, info.blocks, info.ptr);
7377db96d56Sopenharmony_ci}
7387db96d56Sopenharmony_ci
7397db96d56Sopenharmony_ci
7407db96d56Sopenharmony_ci/* ----------------------------------------------------------------------
7417db96d56Sopenharmony_ci * Methods of mixer objects (OSSMixerType)
7427db96d56Sopenharmony_ci */
7437db96d56Sopenharmony_ci
7447db96d56Sopenharmony_cistatic PyObject *
7457db96d56Sopenharmony_cioss_mixer_close(oss_mixer_t *self, PyObject *unused)
7467db96d56Sopenharmony_ci{
7477db96d56Sopenharmony_ci    if (self->fd >= 0) {
7487db96d56Sopenharmony_ci        close(self->fd);
7497db96d56Sopenharmony_ci        self->fd = -1;
7507db96d56Sopenharmony_ci    }
7517db96d56Sopenharmony_ci    Py_RETURN_NONE;
7527db96d56Sopenharmony_ci}
7537db96d56Sopenharmony_ci
7547db96d56Sopenharmony_cistatic PyObject *
7557db96d56Sopenharmony_cioss_mixer_fileno(oss_mixer_t *self, PyObject *unused)
7567db96d56Sopenharmony_ci{
7577db96d56Sopenharmony_ci    if (!_is_fd_valid(self->fd))
7587db96d56Sopenharmony_ci        return NULL;
7597db96d56Sopenharmony_ci
7607db96d56Sopenharmony_ci    return PyLong_FromLong(self->fd);
7617db96d56Sopenharmony_ci}
7627db96d56Sopenharmony_ci
7637db96d56Sopenharmony_ci/* Simple mixer interface methods */
7647db96d56Sopenharmony_ci
7657db96d56Sopenharmony_cistatic PyObject *
7667db96d56Sopenharmony_cioss_mixer_controls(oss_mixer_t *self, PyObject *args)
7677db96d56Sopenharmony_ci{
7687db96d56Sopenharmony_ci    if (!_is_fd_valid(self->fd))
7697db96d56Sopenharmony_ci        return NULL;
7707db96d56Sopenharmony_ci
7717db96d56Sopenharmony_ci    return _do_ioctl_1_internal(self->fd, args, "controls",
7727db96d56Sopenharmony_ci        SOUND_MIXER_READ_DEVMASK);
7737db96d56Sopenharmony_ci}
7747db96d56Sopenharmony_ci
7757db96d56Sopenharmony_cistatic PyObject *
7767db96d56Sopenharmony_cioss_mixer_stereocontrols(oss_mixer_t *self, PyObject *args)
7777db96d56Sopenharmony_ci{
7787db96d56Sopenharmony_ci    if (!_is_fd_valid(self->fd))
7797db96d56Sopenharmony_ci        return NULL;
7807db96d56Sopenharmony_ci
7817db96d56Sopenharmony_ci    return _do_ioctl_1_internal(self->fd, args, "stereocontrols",
7827db96d56Sopenharmony_ci        SOUND_MIXER_READ_STEREODEVS);
7837db96d56Sopenharmony_ci}
7847db96d56Sopenharmony_ci
7857db96d56Sopenharmony_cistatic PyObject *
7867db96d56Sopenharmony_cioss_mixer_reccontrols(oss_mixer_t *self, PyObject *args)
7877db96d56Sopenharmony_ci{
7887db96d56Sopenharmony_ci    if (!_is_fd_valid(self->fd))
7897db96d56Sopenharmony_ci        return NULL;
7907db96d56Sopenharmony_ci
7917db96d56Sopenharmony_ci    return _do_ioctl_1_internal(self->fd, args, "reccontrols",
7927db96d56Sopenharmony_ci        SOUND_MIXER_READ_RECMASK);
7937db96d56Sopenharmony_ci}
7947db96d56Sopenharmony_ci
7957db96d56Sopenharmony_cistatic PyObject *
7967db96d56Sopenharmony_cioss_mixer_get(oss_mixer_t *self, PyObject *args)
7977db96d56Sopenharmony_ci{
7987db96d56Sopenharmony_ci    int channel, volume;
7997db96d56Sopenharmony_ci
8007db96d56Sopenharmony_ci    if (!_is_fd_valid(self->fd))
8017db96d56Sopenharmony_ci        return NULL;
8027db96d56Sopenharmony_ci
8037db96d56Sopenharmony_ci    /* Can't use _do_ioctl_1 because of encoded arg thingy. */
8047db96d56Sopenharmony_ci    if (!PyArg_ParseTuple(args, "i:get", &channel))
8057db96d56Sopenharmony_ci        return NULL;
8067db96d56Sopenharmony_ci
8077db96d56Sopenharmony_ci    if (channel < 0 || channel > SOUND_MIXER_NRDEVICES) {
8087db96d56Sopenharmony_ci        PyErr_SetString(OSSAudioError, "Invalid mixer channel specified.");
8097db96d56Sopenharmony_ci        return NULL;
8107db96d56Sopenharmony_ci    }
8117db96d56Sopenharmony_ci
8127db96d56Sopenharmony_ci    if (ioctl(self->fd, MIXER_READ(channel), &volume) == -1)
8137db96d56Sopenharmony_ci        return PyErr_SetFromErrno(PyExc_OSError);
8147db96d56Sopenharmony_ci
8157db96d56Sopenharmony_ci    return Py_BuildValue("(ii)", volume & 0xff, (volume & 0xff00) >> 8);
8167db96d56Sopenharmony_ci}
8177db96d56Sopenharmony_ci
8187db96d56Sopenharmony_cistatic PyObject *
8197db96d56Sopenharmony_cioss_mixer_set(oss_mixer_t *self, PyObject *args)
8207db96d56Sopenharmony_ci{
8217db96d56Sopenharmony_ci    int channel, volume, leftVol, rightVol;
8227db96d56Sopenharmony_ci
8237db96d56Sopenharmony_ci    if (!_is_fd_valid(self->fd))
8247db96d56Sopenharmony_ci        return NULL;
8257db96d56Sopenharmony_ci
8267db96d56Sopenharmony_ci    /* Can't use _do_ioctl_1 because of encoded arg thingy. */
8277db96d56Sopenharmony_ci    if (!PyArg_ParseTuple(args, "i(ii):set", &channel, &leftVol, &rightVol))
8287db96d56Sopenharmony_ci        return NULL;
8297db96d56Sopenharmony_ci
8307db96d56Sopenharmony_ci    if (channel < 0 || channel > SOUND_MIXER_NRDEVICES) {
8317db96d56Sopenharmony_ci        PyErr_SetString(OSSAudioError, "Invalid mixer channel specified.");
8327db96d56Sopenharmony_ci        return NULL;
8337db96d56Sopenharmony_ci    }
8347db96d56Sopenharmony_ci
8357db96d56Sopenharmony_ci    if (leftVol < 0 || rightVol < 0 || leftVol > 100 || rightVol > 100) {
8367db96d56Sopenharmony_ci        PyErr_SetString(OSSAudioError, "Volumes must be between 0 and 100.");
8377db96d56Sopenharmony_ci        return NULL;
8387db96d56Sopenharmony_ci    }
8397db96d56Sopenharmony_ci
8407db96d56Sopenharmony_ci    volume = (rightVol << 8) | leftVol;
8417db96d56Sopenharmony_ci
8427db96d56Sopenharmony_ci    if (ioctl(self->fd, MIXER_WRITE(channel), &volume) == -1)
8437db96d56Sopenharmony_ci        return PyErr_SetFromErrno(PyExc_OSError);
8447db96d56Sopenharmony_ci
8457db96d56Sopenharmony_ci    return Py_BuildValue("(ii)", volume & 0xff, (volume & 0xff00) >> 8);
8467db96d56Sopenharmony_ci}
8477db96d56Sopenharmony_ci
8487db96d56Sopenharmony_cistatic PyObject *
8497db96d56Sopenharmony_cioss_mixer_get_recsrc(oss_mixer_t *self, PyObject *args)
8507db96d56Sopenharmony_ci{
8517db96d56Sopenharmony_ci    if (!_is_fd_valid(self->fd))
8527db96d56Sopenharmony_ci        return NULL;
8537db96d56Sopenharmony_ci
8547db96d56Sopenharmony_ci    return _do_ioctl_1_internal(self->fd, args, "get_recsrc",
8557db96d56Sopenharmony_ci        SOUND_MIXER_READ_RECSRC);
8567db96d56Sopenharmony_ci}
8577db96d56Sopenharmony_ci
8587db96d56Sopenharmony_cistatic PyObject *
8597db96d56Sopenharmony_cioss_mixer_set_recsrc(oss_mixer_t *self, PyObject *args)
8607db96d56Sopenharmony_ci{
8617db96d56Sopenharmony_ci    if (!_is_fd_valid(self->fd))
8627db96d56Sopenharmony_ci        return NULL;
8637db96d56Sopenharmony_ci
8647db96d56Sopenharmony_ci    return _do_ioctl_1(self->fd, args, "set_recsrc",
8657db96d56Sopenharmony_ci        SOUND_MIXER_WRITE_RECSRC);
8667db96d56Sopenharmony_ci}
8677db96d56Sopenharmony_ci
8687db96d56Sopenharmony_ci
8697db96d56Sopenharmony_ci/* ----------------------------------------------------------------------
8707db96d56Sopenharmony_ci * Method tables and other bureaucracy
8717db96d56Sopenharmony_ci */
8727db96d56Sopenharmony_ci
8737db96d56Sopenharmony_cistatic PyMethodDef oss_methods[] = {
8747db96d56Sopenharmony_ci    /* Regular file methods */
8757db96d56Sopenharmony_ci    { "read",           (PyCFunction)oss_read, METH_VARARGS },
8767db96d56Sopenharmony_ci    { "write",          (PyCFunction)oss_write, METH_VARARGS },
8777db96d56Sopenharmony_ci    { "writeall",       (PyCFunction)oss_writeall, METH_VARARGS },
8787db96d56Sopenharmony_ci    { "close",          (PyCFunction)oss_close, METH_NOARGS },
8797db96d56Sopenharmony_ci    { "fileno",         (PyCFunction)oss_fileno, METH_NOARGS },
8807db96d56Sopenharmony_ci
8817db96d56Sopenharmony_ci    /* Simple ioctl wrappers */
8827db96d56Sopenharmony_ci    { "nonblock",       (PyCFunction)oss_nonblock, METH_NOARGS },
8837db96d56Sopenharmony_ci    { "setfmt",         (PyCFunction)oss_setfmt, METH_VARARGS },
8847db96d56Sopenharmony_ci    { "getfmts",        (PyCFunction)oss_getfmts, METH_NOARGS },
8857db96d56Sopenharmony_ci    { "channels",       (PyCFunction)oss_channels, METH_VARARGS },
8867db96d56Sopenharmony_ci    { "speed",          (PyCFunction)oss_speed, METH_VARARGS },
8877db96d56Sopenharmony_ci    { "sync",           (PyCFunction)oss_sync, METH_VARARGS },
8887db96d56Sopenharmony_ci    { "reset",          (PyCFunction)oss_reset, METH_VARARGS },
8897db96d56Sopenharmony_ci    { "post",           (PyCFunction)oss_post, METH_VARARGS },
8907db96d56Sopenharmony_ci
8917db96d56Sopenharmony_ci    /* Convenience methods -- wrap a couple of ioctls together */
8927db96d56Sopenharmony_ci    { "setparameters",  (PyCFunction)oss_setparameters, METH_VARARGS },
8937db96d56Sopenharmony_ci    { "bufsize",        (PyCFunction)oss_bufsize, METH_NOARGS },
8947db96d56Sopenharmony_ci    { "obufcount",      (PyCFunction)oss_obufcount, METH_NOARGS },
8957db96d56Sopenharmony_ci    { "obuffree",       (PyCFunction)oss_obuffree, METH_NOARGS },
8967db96d56Sopenharmony_ci    { "getptr",         (PyCFunction)oss_getptr, METH_NOARGS },
8977db96d56Sopenharmony_ci
8987db96d56Sopenharmony_ci    /* Aliases for backwards compatibility */
8997db96d56Sopenharmony_ci    { "flush",          (PyCFunction)oss_sync, METH_VARARGS },
9007db96d56Sopenharmony_ci
9017db96d56Sopenharmony_ci    /* Support for the context management protocol */
9027db96d56Sopenharmony_ci    { "__enter__",      oss_self, METH_NOARGS },
9037db96d56Sopenharmony_ci    { "__exit__",       oss_exit, METH_VARARGS },
9047db96d56Sopenharmony_ci
9057db96d56Sopenharmony_ci    { NULL,             NULL}           /* sentinel */
9067db96d56Sopenharmony_ci};
9077db96d56Sopenharmony_ci
9087db96d56Sopenharmony_cistatic PyMethodDef oss_mixer_methods[] = {
9097db96d56Sopenharmony_ci    /* Regular file method - OSS mixers are ioctl-only interface */
9107db96d56Sopenharmony_ci    { "close",          (PyCFunction)oss_mixer_close, METH_NOARGS },
9117db96d56Sopenharmony_ci    { "fileno",         (PyCFunction)oss_mixer_fileno, METH_NOARGS },
9127db96d56Sopenharmony_ci
9137db96d56Sopenharmony_ci    /* Support for the context management protocol */
9147db96d56Sopenharmony_ci    { "__enter__",      oss_self, METH_NOARGS },
9157db96d56Sopenharmony_ci    { "__exit__",       oss_exit, METH_VARARGS },
9167db96d56Sopenharmony_ci
9177db96d56Sopenharmony_ci    /* Simple ioctl wrappers */
9187db96d56Sopenharmony_ci    { "controls",       (PyCFunction)oss_mixer_controls, METH_VARARGS },
9197db96d56Sopenharmony_ci    { "stereocontrols", (PyCFunction)oss_mixer_stereocontrols, METH_VARARGS},
9207db96d56Sopenharmony_ci    { "reccontrols",    (PyCFunction)oss_mixer_reccontrols, METH_VARARGS},
9217db96d56Sopenharmony_ci    { "get",            (PyCFunction)oss_mixer_get, METH_VARARGS },
9227db96d56Sopenharmony_ci    { "set",            (PyCFunction)oss_mixer_set, METH_VARARGS },
9237db96d56Sopenharmony_ci    { "get_recsrc",     (PyCFunction)oss_mixer_get_recsrc, METH_VARARGS },
9247db96d56Sopenharmony_ci    { "set_recsrc",     (PyCFunction)oss_mixer_set_recsrc, METH_VARARGS },
9257db96d56Sopenharmony_ci
9267db96d56Sopenharmony_ci    { NULL,             NULL}
9277db96d56Sopenharmony_ci};
9287db96d56Sopenharmony_ci
9297db96d56Sopenharmony_cistatic PyMemberDef oss_members[] = {
9307db96d56Sopenharmony_ci    {"name", T_STRING, offsetof(oss_audio_t, devicename), READONLY, NULL},
9317db96d56Sopenharmony_ci    {NULL}
9327db96d56Sopenharmony_ci};
9337db96d56Sopenharmony_ci
9347db96d56Sopenharmony_cistatic PyObject *
9357db96d56Sopenharmony_cioss_closed_getter(oss_audio_t *self, void *closure)
9367db96d56Sopenharmony_ci{
9377db96d56Sopenharmony_ci    return PyBool_FromLong(self->fd == -1);
9387db96d56Sopenharmony_ci}
9397db96d56Sopenharmony_ci
9407db96d56Sopenharmony_cistatic PyObject *
9417db96d56Sopenharmony_cioss_mode_getter(oss_audio_t *self, void *closure)
9427db96d56Sopenharmony_ci{
9437db96d56Sopenharmony_ci    switch(self->mode) {
9447db96d56Sopenharmony_ci        case O_RDONLY:
9457db96d56Sopenharmony_ci            return PyUnicode_FromString("r");
9467db96d56Sopenharmony_ci            break;
9477db96d56Sopenharmony_ci        case O_RDWR:
9487db96d56Sopenharmony_ci            return PyUnicode_FromString("rw");
9497db96d56Sopenharmony_ci            break;
9507db96d56Sopenharmony_ci        case O_WRONLY:
9517db96d56Sopenharmony_ci            return PyUnicode_FromString("w");
9527db96d56Sopenharmony_ci            break;
9537db96d56Sopenharmony_ci        default:
9547db96d56Sopenharmony_ci            /* From newossobject(), self->mode can only be one
9557db96d56Sopenharmony_ci               of these three values. */
9567db96d56Sopenharmony_ci            Py_UNREACHABLE();
9577db96d56Sopenharmony_ci    }
9587db96d56Sopenharmony_ci}
9597db96d56Sopenharmony_ci
9607db96d56Sopenharmony_cistatic PyGetSetDef oss_getsetlist[] = {
9617db96d56Sopenharmony_ci    {"closed", (getter)oss_closed_getter, (setter)NULL, NULL},
9627db96d56Sopenharmony_ci    {"mode", (getter)oss_mode_getter, (setter)NULL, NULL},
9637db96d56Sopenharmony_ci    {NULL},
9647db96d56Sopenharmony_ci};
9657db96d56Sopenharmony_ci
9667db96d56Sopenharmony_cistatic PyTypeObject OSSAudioType = {
9677db96d56Sopenharmony_ci    PyVarObject_HEAD_INIT(&PyType_Type, 0)
9687db96d56Sopenharmony_ci    "ossaudiodev.oss_audio_device", /*tp_name*/
9697db96d56Sopenharmony_ci    sizeof(oss_audio_t),        /*tp_basicsize*/
9707db96d56Sopenharmony_ci    0,                          /*tp_itemsize*/
9717db96d56Sopenharmony_ci    /* methods */
9727db96d56Sopenharmony_ci    (destructor)oss_dealloc,    /*tp_dealloc*/
9737db96d56Sopenharmony_ci    0,                          /*tp_vectorcall_offset*/
9747db96d56Sopenharmony_ci    0,                          /*tp_getattr*/
9757db96d56Sopenharmony_ci    0,                          /*tp_setattr*/
9767db96d56Sopenharmony_ci    0,                          /*tp_as_async*/
9777db96d56Sopenharmony_ci    0,                          /*tp_repr*/
9787db96d56Sopenharmony_ci    0,                          /*tp_as_number*/
9797db96d56Sopenharmony_ci    0,                          /*tp_as_sequence*/
9807db96d56Sopenharmony_ci    0,                          /*tp_as_mapping*/
9817db96d56Sopenharmony_ci    0,                          /*tp_hash*/
9827db96d56Sopenharmony_ci    0,                          /*tp_call*/
9837db96d56Sopenharmony_ci    0,                          /*tp_str*/
9847db96d56Sopenharmony_ci    0,                          /*tp_getattro*/
9857db96d56Sopenharmony_ci    0,                          /*tp_setattro*/
9867db96d56Sopenharmony_ci    0,                          /*tp_as_buffer*/
9877db96d56Sopenharmony_ci    Py_TPFLAGS_DEFAULT,         /*tp_flags*/
9887db96d56Sopenharmony_ci    0,                          /*tp_doc*/
9897db96d56Sopenharmony_ci    0,                          /*tp_traverse*/
9907db96d56Sopenharmony_ci    0,                          /*tp_clear*/
9917db96d56Sopenharmony_ci    0,                          /*tp_richcompare*/
9927db96d56Sopenharmony_ci    0,                          /*tp_weaklistoffset*/
9937db96d56Sopenharmony_ci    0,                          /*tp_iter*/
9947db96d56Sopenharmony_ci    0,                          /*tp_iternext*/
9957db96d56Sopenharmony_ci    oss_methods,                /*tp_methods*/
9967db96d56Sopenharmony_ci    oss_members,                /*tp_members*/
9977db96d56Sopenharmony_ci    oss_getsetlist,             /*tp_getset*/
9987db96d56Sopenharmony_ci};
9997db96d56Sopenharmony_ci
10007db96d56Sopenharmony_cistatic PyTypeObject OSSMixerType = {
10017db96d56Sopenharmony_ci    PyVarObject_HEAD_INIT(&PyType_Type, 0)
10027db96d56Sopenharmony_ci    "ossaudiodev.oss_mixer_device", /*tp_name*/
10037db96d56Sopenharmony_ci    sizeof(oss_mixer_t),            /*tp_basicsize*/
10047db96d56Sopenharmony_ci    0,                              /*tp_itemsize*/
10057db96d56Sopenharmony_ci    /* methods */
10067db96d56Sopenharmony_ci    (destructor)oss_mixer_dealloc,  /*tp_dealloc*/
10077db96d56Sopenharmony_ci    0,                              /*tp_vectorcall_offset*/
10087db96d56Sopenharmony_ci    0,                              /*tp_getattr*/
10097db96d56Sopenharmony_ci    0,                              /*tp_setattr*/
10107db96d56Sopenharmony_ci    0,                              /*tp_as_async*/
10117db96d56Sopenharmony_ci    0,                              /*tp_repr*/
10127db96d56Sopenharmony_ci    0,                              /*tp_as_number*/
10137db96d56Sopenharmony_ci    0,                              /*tp_as_sequence*/
10147db96d56Sopenharmony_ci    0,                              /*tp_as_mapping*/
10157db96d56Sopenharmony_ci    0,                              /*tp_hash*/
10167db96d56Sopenharmony_ci    0,                              /*tp_call*/
10177db96d56Sopenharmony_ci    0,                              /*tp_str*/
10187db96d56Sopenharmony_ci    0,                              /*tp_getattro*/
10197db96d56Sopenharmony_ci    0,                              /*tp_setattro*/
10207db96d56Sopenharmony_ci    0,                              /*tp_as_buffer*/
10217db96d56Sopenharmony_ci    Py_TPFLAGS_DEFAULT,             /*tp_flags*/
10227db96d56Sopenharmony_ci    0,                              /*tp_doc*/
10237db96d56Sopenharmony_ci    0,                              /*tp_traverse*/
10247db96d56Sopenharmony_ci    0,                              /*tp_clear*/
10257db96d56Sopenharmony_ci    0,                              /*tp_richcompare*/
10267db96d56Sopenharmony_ci    0,                              /*tp_weaklistoffset*/
10277db96d56Sopenharmony_ci    0,                              /*tp_iter*/
10287db96d56Sopenharmony_ci    0,                              /*tp_iternext*/
10297db96d56Sopenharmony_ci    oss_mixer_methods,              /*tp_methods*/
10307db96d56Sopenharmony_ci};
10317db96d56Sopenharmony_ci
10327db96d56Sopenharmony_ci
10337db96d56Sopenharmony_cistatic PyObject *
10347db96d56Sopenharmony_ciossopen(PyObject *self, PyObject *args)
10357db96d56Sopenharmony_ci{
10367db96d56Sopenharmony_ci    return (PyObject *)newossobject(args);
10377db96d56Sopenharmony_ci}
10387db96d56Sopenharmony_ci
10397db96d56Sopenharmony_cistatic PyObject *
10407db96d56Sopenharmony_ciossopenmixer(PyObject *self, PyObject *args)
10417db96d56Sopenharmony_ci{
10427db96d56Sopenharmony_ci    return (PyObject *)newossmixerobject(args);
10437db96d56Sopenharmony_ci}
10447db96d56Sopenharmony_ci
10457db96d56Sopenharmony_cistatic PyMethodDef ossaudiodev_methods[] = {
10467db96d56Sopenharmony_ci    { "open", ossopen, METH_VARARGS },
10477db96d56Sopenharmony_ci    { "openmixer", ossopenmixer, METH_VARARGS },
10487db96d56Sopenharmony_ci    { 0, 0 },
10497db96d56Sopenharmony_ci};
10507db96d56Sopenharmony_ci
10517db96d56Sopenharmony_ci
10527db96d56Sopenharmony_ci#define _EXPORT_INT(mod, name) \
10537db96d56Sopenharmony_ci  if (PyModule_AddIntConstant(mod, #name, (long) (name)) == -1) return NULL;
10547db96d56Sopenharmony_ci
10557db96d56Sopenharmony_ci
10567db96d56Sopenharmony_cistatic char *control_labels[] = SOUND_DEVICE_LABELS;
10577db96d56Sopenharmony_cistatic char *control_names[] = SOUND_DEVICE_NAMES;
10587db96d56Sopenharmony_ci
10597db96d56Sopenharmony_ci
10607db96d56Sopenharmony_cistatic int
10617db96d56Sopenharmony_cibuild_namelists (PyObject *module)
10627db96d56Sopenharmony_ci{
10637db96d56Sopenharmony_ci    PyObject *labels;
10647db96d56Sopenharmony_ci    PyObject *names;
10657db96d56Sopenharmony_ci    PyObject *s;
10667db96d56Sopenharmony_ci    int num_controls;
10677db96d56Sopenharmony_ci    int i;
10687db96d56Sopenharmony_ci
10697db96d56Sopenharmony_ci    num_controls = Py_ARRAY_LENGTH(control_labels);
10707db96d56Sopenharmony_ci    assert(num_controls == Py_ARRAY_LENGTH(control_names));
10717db96d56Sopenharmony_ci
10727db96d56Sopenharmony_ci    labels = PyList_New(num_controls);
10737db96d56Sopenharmony_ci    names = PyList_New(num_controls);
10747db96d56Sopenharmony_ci    if (labels == NULL || names == NULL)
10757db96d56Sopenharmony_ci        goto error2;
10767db96d56Sopenharmony_ci    for (i = 0; i < num_controls; i++) {
10777db96d56Sopenharmony_ci        s = PyUnicode_FromString(control_labels[i]);
10787db96d56Sopenharmony_ci        if (s == NULL)
10797db96d56Sopenharmony_ci            goto error2;
10807db96d56Sopenharmony_ci        PyList_SET_ITEM(labels, i, s);
10817db96d56Sopenharmony_ci
10827db96d56Sopenharmony_ci        s = PyUnicode_FromString(control_names[i]);
10837db96d56Sopenharmony_ci        if (s == NULL)
10847db96d56Sopenharmony_ci            goto error2;
10857db96d56Sopenharmony_ci        PyList_SET_ITEM(names, i, s);
10867db96d56Sopenharmony_ci    }
10877db96d56Sopenharmony_ci
10887db96d56Sopenharmony_ci    if (PyModule_AddObject(module, "control_labels", labels) == -1)
10897db96d56Sopenharmony_ci        goto error2;
10907db96d56Sopenharmony_ci    if (PyModule_AddObject(module, "control_names", names) == -1)
10917db96d56Sopenharmony_ci        goto error1;
10927db96d56Sopenharmony_ci
10937db96d56Sopenharmony_ci    return 0;
10947db96d56Sopenharmony_ci
10957db96d56Sopenharmony_cierror2:
10967db96d56Sopenharmony_ci    Py_XDECREF(labels);
10977db96d56Sopenharmony_cierror1:
10987db96d56Sopenharmony_ci    Py_XDECREF(names);
10997db96d56Sopenharmony_ci    return -1;
11007db96d56Sopenharmony_ci}
11017db96d56Sopenharmony_ci
11027db96d56Sopenharmony_ci
11037db96d56Sopenharmony_cistatic struct PyModuleDef ossaudiodevmodule = {
11047db96d56Sopenharmony_ci        PyModuleDef_HEAD_INIT,
11057db96d56Sopenharmony_ci        "ossaudiodev",
11067db96d56Sopenharmony_ci        NULL,
11077db96d56Sopenharmony_ci        -1,
11087db96d56Sopenharmony_ci        ossaudiodev_methods,
11097db96d56Sopenharmony_ci        NULL,
11107db96d56Sopenharmony_ci        NULL,
11117db96d56Sopenharmony_ci        NULL,
11127db96d56Sopenharmony_ci        NULL
11137db96d56Sopenharmony_ci};
11147db96d56Sopenharmony_ci
11157db96d56Sopenharmony_ciPyMODINIT_FUNC
11167db96d56Sopenharmony_ciPyInit_ossaudiodev(void)
11177db96d56Sopenharmony_ci{
11187db96d56Sopenharmony_ci    PyObject *m;
11197db96d56Sopenharmony_ci
11207db96d56Sopenharmony_ci    if (PyErr_WarnEx(PyExc_DeprecationWarning,
11217db96d56Sopenharmony_ci                     "'ossaudiodev' is deprecated and slated for removal in "
11227db96d56Sopenharmony_ci                     "Python 3.13",
11237db96d56Sopenharmony_ci                     7)) {
11247db96d56Sopenharmony_ci        return NULL;
11257db96d56Sopenharmony_ci    }
11267db96d56Sopenharmony_ci
11277db96d56Sopenharmony_ci    if (PyType_Ready(&OSSAudioType) < 0)
11287db96d56Sopenharmony_ci        return NULL;
11297db96d56Sopenharmony_ci
11307db96d56Sopenharmony_ci    if (PyType_Ready(&OSSMixerType) < 0)
11317db96d56Sopenharmony_ci        return NULL;
11327db96d56Sopenharmony_ci
11337db96d56Sopenharmony_ci    m = PyModule_Create(&ossaudiodevmodule);
11347db96d56Sopenharmony_ci    if (m == NULL)
11357db96d56Sopenharmony_ci        return NULL;
11367db96d56Sopenharmony_ci
11377db96d56Sopenharmony_ci    OSSAudioError = PyErr_NewException("ossaudiodev.OSSAudioError",
11387db96d56Sopenharmony_ci                                       NULL, NULL);
11397db96d56Sopenharmony_ci    if (OSSAudioError) {
11407db96d56Sopenharmony_ci        /* Each call to PyModule_AddObject decrefs it; compensate: */
11417db96d56Sopenharmony_ci        Py_INCREF(OSSAudioError);
11427db96d56Sopenharmony_ci        Py_INCREF(OSSAudioError);
11437db96d56Sopenharmony_ci        PyModule_AddObject(m, "error", OSSAudioError);
11447db96d56Sopenharmony_ci        PyModule_AddObject(m, "OSSAudioError", OSSAudioError);
11457db96d56Sopenharmony_ci    }
11467db96d56Sopenharmony_ci
11477db96d56Sopenharmony_ci    /* Build 'control_labels' and 'control_names' lists and add them
11487db96d56Sopenharmony_ci       to the module. */
11497db96d56Sopenharmony_ci    if (build_namelists(m) == -1)       /* XXX what to do here? */
11507db96d56Sopenharmony_ci        return NULL;
11517db96d56Sopenharmony_ci
11527db96d56Sopenharmony_ci    /* Expose the audio format numbers -- essential! */
11537db96d56Sopenharmony_ci    _EXPORT_INT(m, AFMT_QUERY);
11547db96d56Sopenharmony_ci    _EXPORT_INT(m, AFMT_MU_LAW);
11557db96d56Sopenharmony_ci    _EXPORT_INT(m, AFMT_A_LAW);
11567db96d56Sopenharmony_ci    _EXPORT_INT(m, AFMT_IMA_ADPCM);
11577db96d56Sopenharmony_ci    _EXPORT_INT(m, AFMT_U8);
11587db96d56Sopenharmony_ci    _EXPORT_INT(m, AFMT_S16_LE);
11597db96d56Sopenharmony_ci    _EXPORT_INT(m, AFMT_S16_BE);
11607db96d56Sopenharmony_ci    _EXPORT_INT(m, AFMT_S8);
11617db96d56Sopenharmony_ci    _EXPORT_INT(m, AFMT_U16_LE);
11627db96d56Sopenharmony_ci    _EXPORT_INT(m, AFMT_U16_BE);
11637db96d56Sopenharmony_ci    _EXPORT_INT(m, AFMT_MPEG);
11647db96d56Sopenharmony_ci#ifdef AFMT_AC3
11657db96d56Sopenharmony_ci    _EXPORT_INT(m, AFMT_AC3);
11667db96d56Sopenharmony_ci#endif
11677db96d56Sopenharmony_ci#ifdef AFMT_S16_NE
11687db96d56Sopenharmony_ci    _EXPORT_INT(m, AFMT_S16_NE);
11697db96d56Sopenharmony_ci#endif
11707db96d56Sopenharmony_ci#ifdef AFMT_U16_NE
11717db96d56Sopenharmony_ci    _EXPORT_INT(m, AFMT_U16_NE);
11727db96d56Sopenharmony_ci#endif
11737db96d56Sopenharmony_ci#ifdef AFMT_S32_LE
11747db96d56Sopenharmony_ci    _EXPORT_INT(m, AFMT_S32_LE);
11757db96d56Sopenharmony_ci#endif
11767db96d56Sopenharmony_ci#ifdef AFMT_S32_BE
11777db96d56Sopenharmony_ci    _EXPORT_INT(m, AFMT_S32_BE);
11787db96d56Sopenharmony_ci#endif
11797db96d56Sopenharmony_ci#ifdef AFMT_MPEG
11807db96d56Sopenharmony_ci    _EXPORT_INT(m, AFMT_MPEG);
11817db96d56Sopenharmony_ci#endif
11827db96d56Sopenharmony_ci
11837db96d56Sopenharmony_ci    /* Expose the sound mixer device numbers. */
11847db96d56Sopenharmony_ci    _EXPORT_INT(m, SOUND_MIXER_NRDEVICES);
11857db96d56Sopenharmony_ci    _EXPORT_INT(m, SOUND_MIXER_VOLUME);
11867db96d56Sopenharmony_ci    _EXPORT_INT(m, SOUND_MIXER_BASS);
11877db96d56Sopenharmony_ci    _EXPORT_INT(m, SOUND_MIXER_TREBLE);
11887db96d56Sopenharmony_ci    _EXPORT_INT(m, SOUND_MIXER_SYNTH);
11897db96d56Sopenharmony_ci    _EXPORT_INT(m, SOUND_MIXER_PCM);
11907db96d56Sopenharmony_ci    _EXPORT_INT(m, SOUND_MIXER_SPEAKER);
11917db96d56Sopenharmony_ci    _EXPORT_INT(m, SOUND_MIXER_LINE);
11927db96d56Sopenharmony_ci    _EXPORT_INT(m, SOUND_MIXER_MIC);
11937db96d56Sopenharmony_ci    _EXPORT_INT(m, SOUND_MIXER_CD);
11947db96d56Sopenharmony_ci    _EXPORT_INT(m, SOUND_MIXER_IMIX);
11957db96d56Sopenharmony_ci    _EXPORT_INT(m, SOUND_MIXER_ALTPCM);
11967db96d56Sopenharmony_ci    _EXPORT_INT(m, SOUND_MIXER_RECLEV);
11977db96d56Sopenharmony_ci    _EXPORT_INT(m, SOUND_MIXER_IGAIN);
11987db96d56Sopenharmony_ci    _EXPORT_INT(m, SOUND_MIXER_OGAIN);
11997db96d56Sopenharmony_ci    _EXPORT_INT(m, SOUND_MIXER_LINE1);
12007db96d56Sopenharmony_ci    _EXPORT_INT(m, SOUND_MIXER_LINE2);
12017db96d56Sopenharmony_ci    _EXPORT_INT(m, SOUND_MIXER_LINE3);
12027db96d56Sopenharmony_ci#ifdef SOUND_MIXER_DIGITAL1
12037db96d56Sopenharmony_ci    _EXPORT_INT(m, SOUND_MIXER_DIGITAL1);
12047db96d56Sopenharmony_ci#endif
12057db96d56Sopenharmony_ci#ifdef SOUND_MIXER_DIGITAL2
12067db96d56Sopenharmony_ci    _EXPORT_INT(m, SOUND_MIXER_DIGITAL2);
12077db96d56Sopenharmony_ci#endif
12087db96d56Sopenharmony_ci#ifdef SOUND_MIXER_DIGITAL3
12097db96d56Sopenharmony_ci    _EXPORT_INT(m, SOUND_MIXER_DIGITAL3);
12107db96d56Sopenharmony_ci#endif
12117db96d56Sopenharmony_ci#ifdef SOUND_MIXER_PHONEIN
12127db96d56Sopenharmony_ci    _EXPORT_INT(m, SOUND_MIXER_PHONEIN);
12137db96d56Sopenharmony_ci#endif
12147db96d56Sopenharmony_ci#ifdef SOUND_MIXER_PHONEOUT
12157db96d56Sopenharmony_ci    _EXPORT_INT(m, SOUND_MIXER_PHONEOUT);
12167db96d56Sopenharmony_ci#endif
12177db96d56Sopenharmony_ci#ifdef SOUND_MIXER_VIDEO
12187db96d56Sopenharmony_ci    _EXPORT_INT(m, SOUND_MIXER_VIDEO);
12197db96d56Sopenharmony_ci#endif
12207db96d56Sopenharmony_ci#ifdef SOUND_MIXER_RADIO
12217db96d56Sopenharmony_ci    _EXPORT_INT(m, SOUND_MIXER_RADIO);
12227db96d56Sopenharmony_ci#endif
12237db96d56Sopenharmony_ci#ifdef SOUND_MIXER_MONITOR
12247db96d56Sopenharmony_ci    _EXPORT_INT(m, SOUND_MIXER_MONITOR);
12257db96d56Sopenharmony_ci#endif
12267db96d56Sopenharmony_ci
12277db96d56Sopenharmony_ci    /* Expose all the ioctl numbers for masochists who like to do this
12287db96d56Sopenharmony_ci       stuff directly. */
12297db96d56Sopenharmony_ci#ifdef SNDCTL_COPR_HALT
12307db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_COPR_HALT);
12317db96d56Sopenharmony_ci#endif
12327db96d56Sopenharmony_ci#ifdef SNDCTL_COPR_LOAD
12337db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_COPR_LOAD);
12347db96d56Sopenharmony_ci#endif
12357db96d56Sopenharmony_ci#ifdef SNDCTL_COPR_RCODE
12367db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_COPR_RCODE);
12377db96d56Sopenharmony_ci#endif
12387db96d56Sopenharmony_ci#ifdef SNDCTL_COPR_RCVMSG
12397db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_COPR_RCVMSG);
12407db96d56Sopenharmony_ci#endif
12417db96d56Sopenharmony_ci#ifdef SNDCTL_COPR_RDATA
12427db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_COPR_RDATA);
12437db96d56Sopenharmony_ci#endif
12447db96d56Sopenharmony_ci#ifdef SNDCTL_COPR_RESET
12457db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_COPR_RESET);
12467db96d56Sopenharmony_ci#endif
12477db96d56Sopenharmony_ci#ifdef SNDCTL_COPR_RUN
12487db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_COPR_RUN);
12497db96d56Sopenharmony_ci#endif
12507db96d56Sopenharmony_ci#ifdef SNDCTL_COPR_SENDMSG
12517db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_COPR_SENDMSG);
12527db96d56Sopenharmony_ci#endif
12537db96d56Sopenharmony_ci#ifdef SNDCTL_COPR_WCODE
12547db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_COPR_WCODE);
12557db96d56Sopenharmony_ci#endif
12567db96d56Sopenharmony_ci#ifdef SNDCTL_COPR_WDATA
12577db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_COPR_WDATA);
12587db96d56Sopenharmony_ci#endif
12597db96d56Sopenharmony_ci#ifdef SNDCTL_DSP_BIND_CHANNEL
12607db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_DSP_BIND_CHANNEL);
12617db96d56Sopenharmony_ci#endif
12627db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_DSP_CHANNELS);
12637db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_DSP_GETBLKSIZE);
12647db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_DSP_GETCAPS);
12657db96d56Sopenharmony_ci#ifdef SNDCTL_DSP_GETCHANNELMASK
12667db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_DSP_GETCHANNELMASK);
12677db96d56Sopenharmony_ci#endif
12687db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_DSP_GETFMTS);
12697db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_DSP_GETIPTR);
12707db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_DSP_GETISPACE);
12717db96d56Sopenharmony_ci#ifdef SNDCTL_DSP_GETODELAY
12727db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_DSP_GETODELAY);
12737db96d56Sopenharmony_ci#endif
12747db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_DSP_GETOPTR);
12757db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_DSP_GETOSPACE);
12767db96d56Sopenharmony_ci#ifdef SNDCTL_DSP_GETSPDIF
12777db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_DSP_GETSPDIF);
12787db96d56Sopenharmony_ci#endif
12797db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_DSP_GETTRIGGER);
12807db96d56Sopenharmony_ci#ifdef SNDCTL_DSP_MAPINBUF
12817db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_DSP_MAPINBUF);
12827db96d56Sopenharmony_ci#endif
12837db96d56Sopenharmony_ci#ifdef SNDCTL_DSP_MAPOUTBUF
12847db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_DSP_MAPOUTBUF);
12857db96d56Sopenharmony_ci#endif
12867db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_DSP_NONBLOCK);
12877db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_DSP_POST);
12887db96d56Sopenharmony_ci#ifdef SNDCTL_DSP_PROFILE
12897db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_DSP_PROFILE);
12907db96d56Sopenharmony_ci#endif
12917db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_DSP_RESET);
12927db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_DSP_SAMPLESIZE);
12937db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_DSP_SETDUPLEX);
12947db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_DSP_SETFMT);
12957db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_DSP_SETFRAGMENT);
12967db96d56Sopenharmony_ci#ifdef SNDCTL_DSP_SETSPDIF
12977db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_DSP_SETSPDIF);
12987db96d56Sopenharmony_ci#endif
12997db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_DSP_SETSYNCRO);
13007db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_DSP_SETTRIGGER);
13017db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_DSP_SPEED);
13027db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_DSP_STEREO);
13037db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_DSP_SUBDIVIDE);
13047db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_DSP_SYNC);
13057db96d56Sopenharmony_ci#ifdef SNDCTL_FM_4OP_ENABLE
13067db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_FM_4OP_ENABLE);
13077db96d56Sopenharmony_ci#endif
13087db96d56Sopenharmony_ci#ifdef SNDCTL_FM_LOAD_INSTR
13097db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_FM_LOAD_INSTR);
13107db96d56Sopenharmony_ci#endif
13117db96d56Sopenharmony_ci#ifdef SNDCTL_MIDI_INFO
13127db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_MIDI_INFO);
13137db96d56Sopenharmony_ci#endif
13147db96d56Sopenharmony_ci#ifdef SNDCTL_MIDI_MPUCMD
13157db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_MIDI_MPUCMD);
13167db96d56Sopenharmony_ci#endif
13177db96d56Sopenharmony_ci#ifdef SNDCTL_MIDI_MPUMODE
13187db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_MIDI_MPUMODE);
13197db96d56Sopenharmony_ci#endif
13207db96d56Sopenharmony_ci#ifdef SNDCTL_MIDI_PRETIME
13217db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_MIDI_PRETIME);
13227db96d56Sopenharmony_ci#endif
13237db96d56Sopenharmony_ci#ifdef SNDCTL_SEQ_CTRLRATE
13247db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_SEQ_CTRLRATE);
13257db96d56Sopenharmony_ci#endif
13267db96d56Sopenharmony_ci#ifdef SNDCTL_SEQ_GETINCOUNT
13277db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_SEQ_GETINCOUNT);
13287db96d56Sopenharmony_ci#endif
13297db96d56Sopenharmony_ci#ifdef SNDCTL_SEQ_GETOUTCOUNT
13307db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_SEQ_GETOUTCOUNT);
13317db96d56Sopenharmony_ci#endif
13327db96d56Sopenharmony_ci#ifdef SNDCTL_SEQ_GETTIME
13337db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_SEQ_GETTIME);
13347db96d56Sopenharmony_ci#endif
13357db96d56Sopenharmony_ci#ifdef SNDCTL_SEQ_NRMIDIS
13367db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_SEQ_NRMIDIS);
13377db96d56Sopenharmony_ci#endif
13387db96d56Sopenharmony_ci#ifdef SNDCTL_SEQ_NRSYNTHS
13397db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_SEQ_NRSYNTHS);
13407db96d56Sopenharmony_ci#endif
13417db96d56Sopenharmony_ci#ifdef SNDCTL_SEQ_OUTOFBAND
13427db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_SEQ_OUTOFBAND);
13437db96d56Sopenharmony_ci#endif
13447db96d56Sopenharmony_ci#ifdef SNDCTL_SEQ_PANIC
13457db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_SEQ_PANIC);
13467db96d56Sopenharmony_ci#endif
13477db96d56Sopenharmony_ci#ifdef SNDCTL_SEQ_PERCMODE
13487db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_SEQ_PERCMODE);
13497db96d56Sopenharmony_ci#endif
13507db96d56Sopenharmony_ci#ifdef SNDCTL_SEQ_RESET
13517db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_SEQ_RESET);
13527db96d56Sopenharmony_ci#endif
13537db96d56Sopenharmony_ci#ifdef SNDCTL_SEQ_RESETSAMPLES
13547db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_SEQ_RESETSAMPLES);
13557db96d56Sopenharmony_ci#endif
13567db96d56Sopenharmony_ci#ifdef SNDCTL_SEQ_SYNC
13577db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_SEQ_SYNC);
13587db96d56Sopenharmony_ci#endif
13597db96d56Sopenharmony_ci#ifdef SNDCTL_SEQ_TESTMIDI
13607db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_SEQ_TESTMIDI);
13617db96d56Sopenharmony_ci#endif
13627db96d56Sopenharmony_ci#ifdef SNDCTL_SEQ_THRESHOLD
13637db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_SEQ_THRESHOLD);
13647db96d56Sopenharmony_ci#endif
13657db96d56Sopenharmony_ci#ifdef SNDCTL_SYNTH_CONTROL
13667db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_SYNTH_CONTROL);
13677db96d56Sopenharmony_ci#endif
13687db96d56Sopenharmony_ci#ifdef SNDCTL_SYNTH_ID
13697db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_SYNTH_ID);
13707db96d56Sopenharmony_ci#endif
13717db96d56Sopenharmony_ci#ifdef SNDCTL_SYNTH_INFO
13727db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_SYNTH_INFO);
13737db96d56Sopenharmony_ci#endif
13747db96d56Sopenharmony_ci#ifdef SNDCTL_SYNTH_MEMAVL
13757db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_SYNTH_MEMAVL);
13767db96d56Sopenharmony_ci#endif
13777db96d56Sopenharmony_ci#ifdef SNDCTL_SYNTH_REMOVESAMPLE
13787db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_SYNTH_REMOVESAMPLE);
13797db96d56Sopenharmony_ci#endif
13807db96d56Sopenharmony_ci#ifdef SNDCTL_TMR_CONTINUE
13817db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_TMR_CONTINUE);
13827db96d56Sopenharmony_ci#endif
13837db96d56Sopenharmony_ci#ifdef SNDCTL_TMR_METRONOME
13847db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_TMR_METRONOME);
13857db96d56Sopenharmony_ci#endif
13867db96d56Sopenharmony_ci#ifdef SNDCTL_TMR_SELECT
13877db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_TMR_SELECT);
13887db96d56Sopenharmony_ci#endif
13897db96d56Sopenharmony_ci#ifdef SNDCTL_TMR_SOURCE
13907db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_TMR_SOURCE);
13917db96d56Sopenharmony_ci#endif
13927db96d56Sopenharmony_ci#ifdef SNDCTL_TMR_START
13937db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_TMR_START);
13947db96d56Sopenharmony_ci#endif
13957db96d56Sopenharmony_ci#ifdef SNDCTL_TMR_STOP
13967db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_TMR_STOP);
13977db96d56Sopenharmony_ci#endif
13987db96d56Sopenharmony_ci#ifdef SNDCTL_TMR_TEMPO
13997db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_TMR_TEMPO);
14007db96d56Sopenharmony_ci#endif
14017db96d56Sopenharmony_ci#ifdef SNDCTL_TMR_TIMEBASE
14027db96d56Sopenharmony_ci    _EXPORT_INT(m, SNDCTL_TMR_TIMEBASE);
14037db96d56Sopenharmony_ci#endif
14047db96d56Sopenharmony_ci    return m;
14057db96d56Sopenharmony_ci}
1406