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