blob: 21c29178b1cd2181b8ab751c9e5be9e10a3b4b11 [file] [log] [blame]
Greg Ward04613a92002-11-30 22:47:45 +00001/*
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 Ward3d9994d2002-12-11 15:12:01 +000011 * Mixer interface by Nicholas FitzRoy-Dale <wzdd@lardcave.net>, Dec 2002.
Greg Ward04613a92002-11-30 22:47:45 +000012 *
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
32
33#include <sys/ioctl.h>
34#if defined(linux)
35#include <linux/soundcard.h>
36
37typedef unsigned long uint32_t;
38
39#elif defined(__FreeBSD__)
40#include <machine/soundcard.h>
41
42#ifndef SNDCTL_DSP_CHANNELS
43#define SNDCTL_DSP_CHANNELS SOUND_PCM_WRITE_CHANNELS
44#endif
45
46#endif
47
48typedef struct {
49 PyObject_HEAD;
Greg Ward7b43c682002-12-30 02:29:28 +000050 int fd; /* The open file */
51 int mode; /* file mode */
52 int icount; /* Input count */
53 int ocount; /* Output count */
54 uint32_t afmts; /* Audio formats supported by hardware */
Greg Ward8c6b6a92002-12-11 14:43:13 +000055} oss_t;
Greg Ward04613a92002-11-30 22:47:45 +000056
Greg Ward3d9994d2002-12-11 15:12:01 +000057typedef struct {
58 PyObject_HEAD;
Greg Wardad4d9b92002-12-30 03:02:22 +000059 int fd; /* The open mixer device */
Greg Ward3d9994d2002-12-11 15:12:01 +000060} oss_mixer_t;
61
Greg Ward04613a92002-11-30 22:47:45 +000062/* XXX several format defined in soundcard.h are not supported,
63 including _NE (native endian) options and S32 options
64*/
65
66static struct {
Greg Wardad4d9b92002-12-30 03:02:22 +000067 int a_bps;
68 uint32_t a_fmt;
Greg Ward04613a92002-11-30 22:47:45 +000069 char *a_name;
70} audio_types[] = {
Greg Wardad4d9b92002-12-30 03:02:22 +000071 { 8, AFMT_MU_LAW, "logarithmic mu-law 8-bit audio" },
72 { 8, AFMT_A_LAW, "logarithmic A-law 8-bit audio" },
73 { 8, AFMT_U8, "linear unsigned 8-bit audio" },
74 { 8, AFMT_S8, "linear signed 8-bit audio" },
75 { 16, AFMT_U16_BE, "linear unsigned 16-bit big-endian audio" },
76 { 16, AFMT_U16_LE, "linear unsigned 16-bit little-endian audio" },
77 { 16, AFMT_S16_BE, "linear signed 16-bit big-endian audio" },
78 { 16, AFMT_S16_LE, "linear signed 16-bit little-endian audio" },
79 { 16, AFMT_S16_NE, "linear signed 16-bit native-endian audio" },
Greg Ward04613a92002-11-30 22:47:45 +000080};
81
82static int n_audio_types = sizeof(audio_types) / sizeof(audio_types[0]);
83
Greg Ward8c6b6a92002-12-11 14:43:13 +000084static PyTypeObject OSSType;
Greg Ward3d9994d2002-12-11 15:12:01 +000085static PyTypeObject OSSMixerType;
Greg Ward04613a92002-11-30 22:47:45 +000086
Greg Ward97708bc2002-11-30 23:17:10 +000087static PyObject *OSSAudioError;
Greg Ward04613a92002-11-30 22:47:45 +000088
Greg Ward8c6b6a92002-12-11 14:43:13 +000089static oss_t *
90newossobject(PyObject *arg)
Greg Ward04613a92002-11-30 22:47:45 +000091{
Greg Ward8c6b6a92002-12-11 14:43:13 +000092 oss_t *xp;
Greg Ward04613a92002-11-30 22:47:45 +000093 int fd, afmts, imode;
94 char *basedev = NULL;
95 char *mode = NULL;
96
Greg Ward9a568eb2002-11-30 23:20:09 +000097 /* Two ways to call open():
Greg Ward04613a92002-11-30 22:47:45 +000098 open(device, mode) (for consistency with builtin open())
99 open(mode) (for backwards compatibility)
100 because the *first* argument is optional, parsing args is
101 a wee bit tricky. */
102 if (!PyArg_ParseTuple(arg, "s|s:open", &basedev, &mode))
103 return NULL;
104 if (mode == NULL) { /* only one arg supplied */
105 mode = basedev;
106 basedev = NULL;
107 }
108
109 if (strcmp(mode, "r") == 0)
110 imode = O_RDONLY;
111 else if (strcmp(mode, "w") == 0)
112 imode = O_WRONLY;
Greg Ward1e0f57d2002-11-30 23:05:26 +0000113 else if (strcmp(mode, "rw") == 0)
114 imode = O_RDWR;
Greg Ward04613a92002-11-30 22:47:45 +0000115 else {
Greg Ward97708bc2002-11-30 23:17:10 +0000116 PyErr_SetString(OSSAudioError, "mode must be 'r', 'w', or 'rw'");
Greg Ward04613a92002-11-30 22:47:45 +0000117 return NULL;
118 }
119
Greg Ward5c5c5772002-12-30 02:58:04 +0000120 /* Open the correct device: either the 'device' argument,
121 or the AUDIODEV environment variable, or "/dev/dsp". */
Greg Ward04613a92002-11-30 22:47:45 +0000122 if (basedev == NULL) { /* called with one arg */
123 basedev = getenv("AUDIODEV");
124 if (basedev == NULL) /* $AUDIODEV not set */
125 basedev = "/dev/dsp";
126 }
127
128 if ((fd = open(basedev, imode)) == -1) {
Greg Ward97708bc2002-11-30 23:17:10 +0000129 PyErr_SetFromErrnoWithFilename(PyExc_IOError, basedev);
Greg Ward04613a92002-11-30 22:47:45 +0000130 return NULL;
131 }
Greg Ward04613a92002-11-30 22:47:45 +0000132 if (ioctl(fd, SNDCTL_DSP_GETFMTS, &afmts) == -1) {
Greg Ward97708bc2002-11-30 23:17:10 +0000133 PyErr_SetFromErrnoWithFilename(PyExc_IOError, basedev);
Greg Ward04613a92002-11-30 22:47:45 +0000134 return NULL;
135 }
136 /* Create and initialize the object */
Greg Ward8c6b6a92002-12-11 14:43:13 +0000137 if ((xp = PyObject_New(oss_t, &OSSType)) == NULL) {
Greg Ward04613a92002-11-30 22:47:45 +0000138 close(fd);
139 return NULL;
140 }
Greg Ward7b43c682002-12-30 02:29:28 +0000141 xp->fd = fd;
142 xp->mode = imode;
143 xp->icount = xp->ocount = 0;
144 xp->afmts = afmts;
Greg Ward04613a92002-11-30 22:47:45 +0000145 return xp;
146}
147
148static void
Greg Ward8c6b6a92002-12-11 14:43:13 +0000149oss_dealloc(oss_t *xp)
Greg Ward04613a92002-11-30 22:47:45 +0000150{
151 /* if already closed, don't reclose it */
Greg Ward7b43c682002-12-30 02:29:28 +0000152 if (xp->fd != -1)
Greg Wardad4d9b92002-12-30 03:02:22 +0000153 close(xp->fd);
Greg Ward04613a92002-11-30 22:47:45 +0000154 PyObject_Del(xp);
155}
156
Greg Ward3d9994d2002-12-11 15:12:01 +0000157static oss_mixer_t *
158newossmixerobject(PyObject *arg)
159{
160 char *basedev = NULL, *mode = NULL;
161 int fd, imode;
162 oss_mixer_t *xp;
163
Greg Warde7037662002-12-30 03:01:48 +0000164 if (!PyArg_ParseTuple(arg, "|ss", &basedev, &mode)) {
Greg Wardad4d9b92002-12-30 03:02:22 +0000165 return NULL;
Greg Ward3d9994d2002-12-11 15:12:01 +0000166 }
167
168 if (basedev == NULL) {
Greg Wardad4d9b92002-12-30 03:02:22 +0000169 basedev = getenv("MIXERDEV");
170 if (basedev == NULL) /* MIXERDEV not set */
171 basedev = "/dev/mixer";
Greg Ward3d9994d2002-12-11 15:12:01 +0000172 }
173
174 if (mode == NULL || strcmp(mode, "r") == 0)
175 imode = O_RDONLY;
176 else if (strcmp(mode, "w") == 0)
177 imode = O_WRONLY;
178 else if (strcmp(mode, "rw") == 0)
179 imode = O_RDWR;
180 else {
181 PyErr_SetString(OSSAudioError, "mode must be 'r', 'w', or 'rw'");
182 return NULL;
183 }
184
Greg Warde7037662002-12-30 03:01:48 +0000185 if ((fd = open(basedev, imode)) == -1) {
Greg Ward3d9994d2002-12-11 15:12:01 +0000186 PyErr_SetFromErrnoWithFilename(PyExc_IOError, basedev);
187 return NULL;
188 }
189
190 if ((xp = PyObject_New(oss_mixer_t, &OSSMixerType)) == NULL) {
191 close(fd);
192 return NULL;
193 }
194
Greg Ward7b43c682002-12-30 02:29:28 +0000195 xp->fd = fd;
Greg Ward3d9994d2002-12-11 15:12:01 +0000196
197 return xp;
198}
199
200static void
201oss_mixer_dealloc(oss_mixer_t *xp)
202{
203 /* if already closed, don't reclose it */
Greg Ward7b43c682002-12-30 02:29:28 +0000204 if (xp->fd != -1)
Greg Wardad4d9b92002-12-30 03:02:22 +0000205 close(xp->fd);
Greg Ward3d9994d2002-12-11 15:12:01 +0000206 PyObject_Del(xp);
207}
208
Greg Ward131bce02002-11-30 22:56:44 +0000209
210/* Methods to wrap the OSS ioctls. The calling convention is pretty
211 simple:
212 nonblock() -> ioctl(fd, SNDCTL_DSP_NONBLOCK)
213 fmt = setfmt(fmt) -> ioctl(fd, SNDCTL_DSP_SETFMT, &fmt)
214 etc.
215*/
216
217
218/* _do_ioctl_1() is a private helper function used for the OSS ioctls --
219 SNDCTL_DSP_{SETFMT,CHANNELS,SPEED} -- that that are called from C
220 like this:
221 ioctl(fd, SNDCTL_DSP_cmd, &arg)
222
223 where arg is the value to set, and on return the driver sets arg to
224 the value that was actually set. Mapping this to Python is obvious:
225 arg = dsp.xxx(arg)
226*/
227static PyObject *
Greg Wardda9f8532002-12-11 14:49:59 +0000228_do_ioctl_1(int fd, PyObject *args, char *fname, int cmd)
Greg Ward131bce02002-11-30 22:56:44 +0000229{
Greg Wardda9f8532002-12-11 14:49:59 +0000230 char argfmt[33] = "i:";
Greg Ward131bce02002-11-30 22:56:44 +0000231 int arg;
232
Greg Wardda9f8532002-12-11 14:49:59 +0000233 assert(strlen(fname) <= 30);
Greg Ward131bce02002-11-30 22:56:44 +0000234 strcat(argfmt, fname);
235 if (!PyArg_ParseTuple(args, argfmt, &arg))
Greg Wardad4d9b92002-12-30 03:02:22 +0000236 return NULL;
Greg Ward131bce02002-11-30 22:56:44 +0000237
Greg Wardda9f8532002-12-11 14:49:59 +0000238 if (ioctl(fd, cmd, &arg) == -1)
Greg Ward97708bc2002-11-30 23:17:10 +0000239 return PyErr_SetFromErrno(PyExc_IOError);
Greg Ward131bce02002-11-30 22:56:44 +0000240 return PyInt_FromLong(arg);
241}
242
Greg Ward3d9994d2002-12-11 15:12:01 +0000243/* _do_ioctl_1_internal() is a wrapper for ioctls that take no inputs
244 but return an output -- ie. we need to pass a pointer to a local C
245 variable so the driver can write its output there, but from Python
246 all we see is the return value. For example,
247 SOUND_MIXER_READ_DEVMASK returns a bitmask of available mixer
248 devices, but does not use the value of the parameter passed-in in any
249 way.
250*/
251
252static PyObject *
253_do_ioctl_1_internal(int fd, PyObject *args, char *fname, int cmd)
254{
255 char argfmt[32] = ":";
256 int arg = 0;
257
258 assert(strlen(fname) <= 30);
259 strcat(argfmt, fname);
260 if (!PyArg_ParseTuple(args, argfmt, &arg))
Greg Wardad4d9b92002-12-30 03:02:22 +0000261 return NULL;
Greg Ward3d9994d2002-12-11 15:12:01 +0000262
263 if (ioctl(fd, cmd, &arg) == -1)
264 return PyErr_SetFromErrno(PyExc_IOError);
265 return PyInt_FromLong(arg);
266}
267
268
269
Greg Ward131bce02002-11-30 22:56:44 +0000270/* _do_ioctl_0() is a private helper for the no-argument ioctls:
271 SNDCTL_DSP_{SYNC,RESET,POST}. */
272static PyObject *
Greg Wardda9f8532002-12-11 14:49:59 +0000273_do_ioctl_0(int fd, PyObject *args, char *fname, int cmd)
Greg Ward131bce02002-11-30 22:56:44 +0000274{
Greg Wardda9f8532002-12-11 14:49:59 +0000275 char argfmt[32] = ":";
Greg Ward131bce02002-11-30 22:56:44 +0000276
Greg Wardda9f8532002-12-11 14:49:59 +0000277 assert(strlen(fname) <= 30);
Greg Ward131bce02002-11-30 22:56:44 +0000278 strcat(argfmt, fname);
279 if (!PyArg_ParseTuple(args, argfmt))
Greg Wardad4d9b92002-12-30 03:02:22 +0000280 return NULL;
Greg Ward131bce02002-11-30 22:56:44 +0000281
Greg Wardda9f8532002-12-11 14:49:59 +0000282 if (ioctl(fd, cmd, 0) == -1)
Greg Ward97708bc2002-11-30 23:17:10 +0000283 return PyErr_SetFromErrno(PyExc_IOError);
Greg Ward131bce02002-11-30 22:56:44 +0000284 Py_INCREF(Py_None);
285 return Py_None;
286}
287
288
289static PyObject *
Greg Ward8c6b6a92002-12-11 14:43:13 +0000290oss_nonblock(oss_t *self, PyObject *args)
Greg Ward131bce02002-11-30 22:56:44 +0000291{
292 /* Hmmm: it doesn't appear to be possible to return to blocking
293 mode once we're in non-blocking mode! */
294 if (!PyArg_ParseTuple(args, ":nonblock"))
Greg Wardad4d9b92002-12-30 03:02:22 +0000295 return NULL;
Greg Ward7b43c682002-12-30 02:29:28 +0000296 if (ioctl(self->fd, SNDCTL_DSP_NONBLOCK, NULL) == -1)
Greg Ward97708bc2002-11-30 23:17:10 +0000297 return PyErr_SetFromErrno(PyExc_IOError);
Greg Ward131bce02002-11-30 22:56:44 +0000298 Py_INCREF(Py_None);
299 return Py_None;
300}
301
302static PyObject *
Greg Ward8c6b6a92002-12-11 14:43:13 +0000303oss_setfmt(oss_t *self, PyObject *args)
Greg Ward131bce02002-11-30 22:56:44 +0000304{
Greg Ward7b43c682002-12-30 02:29:28 +0000305 return _do_ioctl_1(self->fd, args, "setfmt", SNDCTL_DSP_SETFMT);
Greg Ward131bce02002-11-30 22:56:44 +0000306}
307
308static PyObject *
Greg Ward8c6b6a92002-12-11 14:43:13 +0000309oss_getfmts(oss_t *self, PyObject *args)
Greg Ward131bce02002-11-30 22:56:44 +0000310{
311 int mask;
312 if (!PyArg_ParseTuple(args, ":getfmts"))
Greg Wardad4d9b92002-12-30 03:02:22 +0000313 return NULL;
Greg Ward7b43c682002-12-30 02:29:28 +0000314 if (ioctl(self->fd, SNDCTL_DSP_GETFMTS, &mask) == -1)
Greg Ward97708bc2002-11-30 23:17:10 +0000315 return PyErr_SetFromErrno(PyExc_IOError);
Greg Ward131bce02002-11-30 22:56:44 +0000316 return PyInt_FromLong(mask);
317}
318
319static PyObject *
Greg Ward8c6b6a92002-12-11 14:43:13 +0000320oss_channels(oss_t *self, PyObject *args)
Greg Ward131bce02002-11-30 22:56:44 +0000321{
Greg Ward7b43c682002-12-30 02:29:28 +0000322 return _do_ioctl_1(self->fd, args, "channels", SNDCTL_DSP_CHANNELS);
Greg Ward131bce02002-11-30 22:56:44 +0000323}
324
325static PyObject *
Greg Ward8c6b6a92002-12-11 14:43:13 +0000326oss_speed(oss_t *self, PyObject *args)
Greg Ward131bce02002-11-30 22:56:44 +0000327{
Greg Ward7b43c682002-12-30 02:29:28 +0000328 return _do_ioctl_1(self->fd, args, "speed", SNDCTL_DSP_SPEED);
Greg Ward131bce02002-11-30 22:56:44 +0000329}
330
331static PyObject *
Greg Ward8c6b6a92002-12-11 14:43:13 +0000332oss_sync(oss_t *self, PyObject *args)
Greg Ward131bce02002-11-30 22:56:44 +0000333{
Greg Ward7b43c682002-12-30 02:29:28 +0000334 return _do_ioctl_0(self->fd, args, "sync", SNDCTL_DSP_SYNC);
Greg Ward131bce02002-11-30 22:56:44 +0000335}
336
337static PyObject *
Greg Ward8c6b6a92002-12-11 14:43:13 +0000338oss_reset(oss_t *self, PyObject *args)
Greg Ward131bce02002-11-30 22:56:44 +0000339{
Greg Ward7b43c682002-12-30 02:29:28 +0000340 return _do_ioctl_0(self->fd, args, "reset", SNDCTL_DSP_RESET);
Greg Ward131bce02002-11-30 22:56:44 +0000341}
342
343static PyObject *
Greg Ward8c6b6a92002-12-11 14:43:13 +0000344oss_post(oss_t *self, PyObject *args)
Greg Ward131bce02002-11-30 22:56:44 +0000345{
Greg Ward7b43c682002-12-30 02:29:28 +0000346 return _do_ioctl_0(self->fd, args, "post", SNDCTL_DSP_POST);
Greg Ward131bce02002-11-30 22:56:44 +0000347}
348
349
350/* Regular file methods: read(), write(), close(), etc. as well
351 as one convenience method, writeall(). */
352
Greg Ward04613a92002-11-30 22:47:45 +0000353static PyObject *
Greg Ward8c6b6a92002-12-11 14:43:13 +0000354oss_read(oss_t *self, PyObject *args)
Greg Ward04613a92002-11-30 22:47:45 +0000355{
356 int size, count;
357 char *cp;
358 PyObject *rv;
Greg Wardad4d9b92002-12-30 03:02:22 +0000359
Greg Ward04613a92002-11-30 22:47:45 +0000360 if (!PyArg_ParseTuple(args, "i:read", &size))
361 return NULL;
362 rv = PyString_FromStringAndSize(NULL, size);
363 if (rv == NULL)
364 return NULL;
365 cp = PyString_AS_STRING(rv);
Greg Ward7b43c682002-12-30 02:29:28 +0000366 if ((count = read(self->fd, cp, size)) < 0) {
Greg Ward97708bc2002-11-30 23:17:10 +0000367 PyErr_SetFromErrno(PyExc_IOError);
Greg Ward04613a92002-11-30 22:47:45 +0000368 Py_DECREF(rv);
369 return NULL;
370 }
Greg Ward7b43c682002-12-30 02:29:28 +0000371 self->icount += count;
Greg Ward04613a92002-11-30 22:47:45 +0000372 _PyString_Resize(&rv, count);
373 return rv;
374}
375
376static PyObject *
Greg Ward8c6b6a92002-12-11 14:43:13 +0000377oss_write(oss_t *self, PyObject *args)
Greg Ward04613a92002-11-30 22:47:45 +0000378{
379 char *cp;
380 int rv, size;
Greg Ward131bce02002-11-30 22:56:44 +0000381
382 if (!PyArg_ParseTuple(args, "s#:write", &cp, &size)) {
Greg Wardad4d9b92002-12-30 03:02:22 +0000383 return NULL;
Greg Ward131bce02002-11-30 22:56:44 +0000384 }
Greg Ward7b43c682002-12-30 02:29:28 +0000385 if ((rv = write(self->fd, cp, size)) == -1) {
Greg Ward97708bc2002-11-30 23:17:10 +0000386 return PyErr_SetFromErrno(PyExc_IOError);
Greg Ward131bce02002-11-30 22:56:44 +0000387 } else {
Greg Ward7b43c682002-12-30 02:29:28 +0000388 self->ocount += rv;
Greg Ward131bce02002-11-30 22:56:44 +0000389 }
390 return PyInt_FromLong(rv);
391}
392
393static PyObject *
Greg Ward8c6b6a92002-12-11 14:43:13 +0000394oss_writeall(oss_t *self, PyObject *args)
Greg Ward131bce02002-11-30 22:56:44 +0000395{
396 char *cp;
397 int rv, size;
398 fd_set write_set_fds;
399 int select_rv;
400
401 /* NB. writeall() is only useful in non-blocking mode: according to
402 Guenter Geiger <geiger@xdv.org> on the linux-audio-dev list
403 (http://eca.cx/lad/2002/11/0380.html), OSS guarantees that
404 write() in blocking mode consumes the whole buffer. In blocking
405 mode, the behaviour of write() and writeall() from Python is
406 indistinguishable. */
407
408 if (!PyArg_ParseTuple(args, "s#:write", &cp, &size))
409 return NULL;
Greg Ward04613a92002-11-30 22:47:45 +0000410
411 /* use select to wait for audio device to be available */
412 FD_ZERO(&write_set_fds);
Greg Ward7b43c682002-12-30 02:29:28 +0000413 FD_SET(self->fd, &write_set_fds);
Greg Ward04613a92002-11-30 22:47:45 +0000414
415 while (size > 0) {
Greg Ward7b43c682002-12-30 02:29:28 +0000416 select_rv = select(self->fd+1, NULL, &write_set_fds, NULL, NULL);
Greg Ward131bce02002-11-30 22:56:44 +0000417 assert(select_rv != 0); /* no timeout, can't expire */
418 if (select_rv == -1)
Greg Ward97708bc2002-11-30 23:17:10 +0000419 return PyErr_SetFromErrno(PyExc_IOError);
Greg Ward131bce02002-11-30 22:56:44 +0000420
Greg Ward7b43c682002-12-30 02:29:28 +0000421 rv = write(self->fd, cp, size);
Greg Ward131bce02002-11-30 22:56:44 +0000422 if (rv == -1) {
423 if (errno == EAGAIN) { /* buffer is full, try again */
424 errno = 0;
425 continue;
426 } else /* it's a real error */
Greg Ward97708bc2002-11-30 23:17:10 +0000427 return PyErr_SetFromErrno(PyExc_IOError);
Greg Ward131bce02002-11-30 22:56:44 +0000428 } else { /* wrote rv bytes */
Greg Ward7b43c682002-12-30 02:29:28 +0000429 self->ocount += rv;
Greg Ward131bce02002-11-30 22:56:44 +0000430 size -= rv;
431 cp += rv;
432 }
Greg Ward04613a92002-11-30 22:47:45 +0000433 }
434 Py_INCREF(Py_None);
435 return Py_None;
436}
437
438static PyObject *
Greg Ward8c6b6a92002-12-11 14:43:13 +0000439oss_close(oss_t *self, PyObject *args)
Greg Ward04613a92002-11-30 22:47:45 +0000440{
441 if (!PyArg_ParseTuple(args, ":close"))
Greg Wardad4d9b92002-12-30 03:02:22 +0000442 return NULL;
Greg Ward04613a92002-11-30 22:47:45 +0000443
Greg Ward7b43c682002-12-30 02:29:28 +0000444 if (self->fd >= 0) {
445 close(self->fd);
446 self->fd = -1;
Greg Ward04613a92002-11-30 22:47:45 +0000447 }
448 Py_INCREF(Py_None);
449 return Py_None;
450}
451
452static PyObject *
Greg Ward8c6b6a92002-12-11 14:43:13 +0000453oss_fileno(oss_t *self, PyObject *args)
Greg Ward04613a92002-11-30 22:47:45 +0000454{
455 if (!PyArg_ParseTuple(args, ":fileno"))
Greg Wardad4d9b92002-12-30 03:02:22 +0000456 return NULL;
Greg Ward7b43c682002-12-30 02:29:28 +0000457 return PyInt_FromLong(self->fd);
Greg Ward04613a92002-11-30 22:47:45 +0000458}
459
Greg Ward131bce02002-11-30 22:56:44 +0000460
461/* Convenience methods: these generally wrap a couple of ioctls into one
462 common task. */
463
Greg Ward04613a92002-11-30 22:47:45 +0000464static PyObject *
Greg Ward8c6b6a92002-12-11 14:43:13 +0000465oss_setparameters(oss_t *self, PyObject *args)
Greg Ward04613a92002-11-30 22:47:45 +0000466{
467 int rate, ssize, nchannels, n, fmt, emulate=0;
468
469 if (!PyArg_ParseTuple(args, "iiii|i:setparameters",
470 &rate, &ssize, &nchannels, &fmt, &emulate))
471 return NULL;
472
473 if (rate < 0) {
Greg Wardad4d9b92002-12-30 03:02:22 +0000474 PyErr_Format(PyExc_ValueError, "expected rate >= 0, not %d",
475 rate);
476 return NULL;
Greg Ward04613a92002-11-30 22:47:45 +0000477 }
478 if (ssize < 0) {
Greg Wardad4d9b92002-12-30 03:02:22 +0000479 PyErr_Format(PyExc_ValueError, "expected sample size >= 0, not %d",
480 ssize);
481 return NULL;
Greg Ward04613a92002-11-30 22:47:45 +0000482 }
483 if (nchannels != 1 && nchannels != 2) {
Greg Wardad4d9b92002-12-30 03:02:22 +0000484 PyErr_Format(PyExc_ValueError, "nchannels must be 1 or 2, not %d",
485 nchannels);
486 return NULL;
Greg Ward04613a92002-11-30 22:47:45 +0000487 }
488
489 for (n = 0; n < n_audio_types; n++)
490 if (fmt == audio_types[n].a_fmt)
491 break;
492 if (n == n_audio_types) {
Greg Wardad4d9b92002-12-30 03:02:22 +0000493 PyErr_Format(PyExc_ValueError, "unknown audio encoding: %d", fmt);
494 return NULL;
Greg Ward04613a92002-11-30 22:47:45 +0000495 }
496 if (audio_types[n].a_bps != ssize) {
Greg Wardad4d9b92002-12-30 03:02:22 +0000497 PyErr_Format(PyExc_ValueError,
498 "for %s, expected sample size %d, not %d",
499 audio_types[n].a_name, audio_types[n].a_bps, ssize);
500 return NULL;
Greg Ward04613a92002-11-30 22:47:45 +0000501 }
502
503 if (emulate == 0) {
Greg Wardad4d9b92002-12-30 03:02:22 +0000504 if ((self->afmts & audio_types[n].a_fmt) == 0) {
505 PyErr_Format(PyExc_ValueError,
506 "%s format not supported by device",
507 audio_types[n].a_name);
508 return NULL;
509 }
Greg Ward04613a92002-11-30 22:47:45 +0000510 }
Greg Ward7b43c682002-12-30 02:29:28 +0000511 if (ioctl(self->fd, SNDCTL_DSP_SETFMT,
Greg Wardad4d9b92002-12-30 03:02:22 +0000512 &audio_types[n].a_fmt) == -1) {
Greg Ward97708bc2002-11-30 23:17:10 +0000513 PyErr_SetFromErrno(PyExc_IOError);
Greg Ward04613a92002-11-30 22:47:45 +0000514 return NULL;
515 }
Greg Ward7b43c682002-12-30 02:29:28 +0000516 if (ioctl(self->fd, SNDCTL_DSP_CHANNELS, &nchannels) == -1) {
Greg Ward97708bc2002-11-30 23:17:10 +0000517 PyErr_SetFromErrno(PyExc_IOError);
Greg Ward04613a92002-11-30 22:47:45 +0000518 return NULL;
519 }
Greg Ward7b43c682002-12-30 02:29:28 +0000520 if (ioctl(self->fd, SNDCTL_DSP_SPEED, &rate) == -1) {
Greg Ward97708bc2002-11-30 23:17:10 +0000521 PyErr_SetFromErrno(PyExc_IOError);
Greg Ward04613a92002-11-30 22:47:45 +0000522 return NULL;
523 }
524
525 Py_INCREF(Py_None);
526 return Py_None;
527}
528
529static int
Greg Ward8c6b6a92002-12-11 14:43:13 +0000530_ssize(oss_t *self, int *nchannels, int *ssize)
Greg Ward04613a92002-11-30 22:47:45 +0000531{
532 int fmt;
533
534 fmt = 0;
Greg Ward7b43c682002-12-30 02:29:28 +0000535 if (ioctl(self->fd, SNDCTL_DSP_SETFMT, &fmt) < 0)
Greg Ward04613a92002-11-30 22:47:45 +0000536 return -errno;
537
538 switch (fmt) {
539 case AFMT_MU_LAW:
540 case AFMT_A_LAW:
541 case AFMT_U8:
542 case AFMT_S8:
543 *ssize = sizeof(char);
544 break;
545 case AFMT_S16_LE:
546 case AFMT_S16_BE:
547 case AFMT_U16_LE:
548 case AFMT_U16_BE:
549 *ssize = sizeof(short);
550 break;
551 case AFMT_MPEG:
552 case AFMT_IMA_ADPCM:
553 default:
554 return -EOPNOTSUPP;
555 }
556 *nchannels = 0;
Greg Ward7b43c682002-12-30 02:29:28 +0000557 if (ioctl(self->fd, SNDCTL_DSP_CHANNELS, nchannels) < 0)
Greg Ward04613a92002-11-30 22:47:45 +0000558 return -errno;
559 return 0;
560}
561
562
563/* bufsize returns the size of the hardware audio buffer in number
564 of samples */
565static PyObject *
Greg Ward8c6b6a92002-12-11 14:43:13 +0000566oss_bufsize(oss_t *self, PyObject *args)
Greg Ward04613a92002-11-30 22:47:45 +0000567{
568 audio_buf_info ai;
569 int nchannels, ssize;
570
571 if (!PyArg_ParseTuple(args, ":bufsize")) return NULL;
572
573 if (_ssize(self, &nchannels, &ssize) < 0) {
Greg Ward97708bc2002-11-30 23:17:10 +0000574 PyErr_SetFromErrno(PyExc_IOError);
Greg Ward04613a92002-11-30 22:47:45 +0000575 return NULL;
576 }
Greg Ward7b43c682002-12-30 02:29:28 +0000577 if (ioctl(self->fd, SNDCTL_DSP_GETOSPACE, &ai) < 0) {
Greg Ward97708bc2002-11-30 23:17:10 +0000578 PyErr_SetFromErrno(PyExc_IOError);
Greg Ward04613a92002-11-30 22:47:45 +0000579 return NULL;
580 }
581 return PyInt_FromLong((ai.fragstotal * ai.fragsize) / (nchannels * ssize));
582}
583
584/* obufcount returns the number of samples that are available in the
585 hardware for playing */
586static PyObject *
Greg Ward8c6b6a92002-12-11 14:43:13 +0000587oss_obufcount(oss_t *self, PyObject *args)
Greg Ward04613a92002-11-30 22:47:45 +0000588{
589 audio_buf_info ai;
590 int nchannels, ssize;
591
592 if (!PyArg_ParseTuple(args, ":obufcount"))
593 return NULL;
594
595 if (_ssize(self, &nchannels, &ssize) < 0) {
Greg Ward97708bc2002-11-30 23:17:10 +0000596 PyErr_SetFromErrno(PyExc_IOError);
Greg Ward04613a92002-11-30 22:47:45 +0000597 return NULL;
598 }
Greg Ward7b43c682002-12-30 02:29:28 +0000599 if (ioctl(self->fd, SNDCTL_DSP_GETOSPACE, &ai) < 0) {
Greg Ward97708bc2002-11-30 23:17:10 +0000600 PyErr_SetFromErrno(PyExc_IOError);
Greg Ward04613a92002-11-30 22:47:45 +0000601 return NULL;
602 }
603 return PyInt_FromLong((ai.fragstotal * ai.fragsize - ai.bytes) /
604 (ssize * nchannels));
605}
606
607/* obufcount returns the number of samples that can be played without
608 blocking */
609static PyObject *
Greg Ward8c6b6a92002-12-11 14:43:13 +0000610oss_obuffree(oss_t *self, PyObject *args)
Greg Ward04613a92002-11-30 22:47:45 +0000611{
612 audio_buf_info ai;
613 int nchannels, ssize;
614
615 if (!PyArg_ParseTuple(args, ":obuffree"))
616 return NULL;
617
618 if (_ssize(self, &nchannels, &ssize) < 0) {
Greg Ward97708bc2002-11-30 23:17:10 +0000619 PyErr_SetFromErrno(PyExc_IOError);
Greg Ward04613a92002-11-30 22:47:45 +0000620 return NULL;
621 }
Greg Ward7b43c682002-12-30 02:29:28 +0000622 if (ioctl(self->fd, SNDCTL_DSP_GETOSPACE, &ai) < 0) {
Greg Ward97708bc2002-11-30 23:17:10 +0000623 PyErr_SetFromErrno(PyExc_IOError);
Greg Ward04613a92002-11-30 22:47:45 +0000624 return NULL;
625 }
626 return PyInt_FromLong(ai.bytes / (ssize * nchannels));
627}
628
Greg Ward04613a92002-11-30 22:47:45 +0000629static PyObject *
Greg Ward8c6b6a92002-12-11 14:43:13 +0000630oss_getptr(oss_t *self, PyObject *args)
Greg Ward04613a92002-11-30 22:47:45 +0000631{
632 count_info info;
633 int req;
634
635 if (!PyArg_ParseTuple(args, ":getptr"))
Greg Wardad4d9b92002-12-30 03:02:22 +0000636 return NULL;
Greg Ward04613a92002-11-30 22:47:45 +0000637
Greg Ward7b43c682002-12-30 02:29:28 +0000638 if (self->mode == O_RDONLY)
Greg Wardad4d9b92002-12-30 03:02:22 +0000639 req = SNDCTL_DSP_GETIPTR;
Greg Ward04613a92002-11-30 22:47:45 +0000640 else
Greg Wardad4d9b92002-12-30 03:02:22 +0000641 req = SNDCTL_DSP_GETOPTR;
Greg Ward7b43c682002-12-30 02:29:28 +0000642 if (ioctl(self->fd, req, &info) == -1) {
Greg Ward97708bc2002-11-30 23:17:10 +0000643 PyErr_SetFromErrno(PyExc_IOError);
Greg Ward04613a92002-11-30 22:47:45 +0000644 return NULL;
645 }
646 return Py_BuildValue("iii", info.bytes, info.blocks, info.ptr);
647}
648
Greg Ward3d9994d2002-12-11 15:12:01 +0000649/* Mixer methods */
650static PyObject *
651oss_mixer_close(oss_mixer_t *self, PyObject *args)
652{
653 if (!PyArg_ParseTuple(args, ":close"))
Greg Wardad4d9b92002-12-30 03:02:22 +0000654 return NULL;
Greg Ward3d9994d2002-12-11 15:12:01 +0000655
Greg Ward7b43c682002-12-30 02:29:28 +0000656 if (self->fd >= 0) {
657 close(self->fd);
658 self->fd = -1;
Greg Ward3d9994d2002-12-11 15:12:01 +0000659 }
660 Py_INCREF(Py_None);
661 return Py_None;
662}
663
664static PyObject *
665oss_mixer_fileno(oss_mixer_t *self, PyObject *args)
666{
667 if (!PyArg_ParseTuple(args, ":fileno"))
Greg Wardad4d9b92002-12-30 03:02:22 +0000668 return NULL;
Greg Ward7b43c682002-12-30 02:29:28 +0000669 return PyInt_FromLong(self->fd);
Greg Ward3d9994d2002-12-11 15:12:01 +0000670}
671
672/* Simple mixer interface methods */
673
674static PyObject *
Greg Warde7037662002-12-30 03:01:48 +0000675oss_mixer_devices(oss_mixer_t *self, PyObject *args)
Greg Ward3d9994d2002-12-11 15:12:01 +0000676{
Greg Ward37897c22002-12-30 02:43:36 +0000677 return _do_ioctl_1_internal(self->fd, args, "devices",
Greg Ward3d9994d2002-12-11 15:12:01 +0000678 SOUND_MIXER_READ_DEVMASK);
679}
680
681static PyObject *
Greg Warde7037662002-12-30 03:01:48 +0000682oss_mixer_stereodevices(oss_mixer_t *self, PyObject *args)
Greg Ward3d9994d2002-12-11 15:12:01 +0000683{
Greg Ward37897c22002-12-30 02:43:36 +0000684 return _do_ioctl_1_internal(self->fd, args, "stereodevices",
Greg Ward3d9994d2002-12-11 15:12:01 +0000685 SOUND_MIXER_READ_STEREODEVS);
686}
687
688static PyObject *
Greg Warde7037662002-12-30 03:01:48 +0000689oss_mixer_recdevices(oss_mixer_t *self, PyObject *args)
Greg Ward3d9994d2002-12-11 15:12:01 +0000690{
Greg Ward37897c22002-12-30 02:43:36 +0000691 return _do_ioctl_1_internal(self->fd, args, "recdevices",
Greg Wardb69bb3d2002-12-12 17:35:45 +0000692 SOUND_MIXER_READ_RECMASK);
Greg Ward3d9994d2002-12-11 15:12:01 +0000693}
694
695static PyObject *
Greg Warde7037662002-12-30 03:01:48 +0000696oss_mixer_get(oss_mixer_t *self, PyObject *args)
Greg Ward3d9994d2002-12-11 15:12:01 +0000697{
698 int channel, volume;
699
700 /* Can't use _do_ioctl_1 because of encoded arg thingy. */
Greg Warde7037662002-12-30 03:01:48 +0000701 if (!PyArg_ParseTuple(args, "i:get", &channel))
Greg Wardad4d9b92002-12-30 03:02:22 +0000702 return NULL;
Greg Ward3d9994d2002-12-11 15:12:01 +0000703
704 if (channel < 0 || channel > SOUND_MIXER_NRDEVICES) {
Greg Wardad4d9b92002-12-30 03:02:22 +0000705 PyErr_SetString(OSSAudioError, "Invalid mixer channel specified.");
706 return NULL;
Greg Ward3d9994d2002-12-11 15:12:01 +0000707 }
708
Greg Warde7037662002-12-30 03:01:48 +0000709 if (ioctl(self->fd, MIXER_READ(channel), &volume) == -1)
Greg Wardad4d9b92002-12-30 03:02:22 +0000710 return PyErr_SetFromErrno(PyExc_IOError);
Greg Ward3d9994d2002-12-11 15:12:01 +0000711
Greg Warde7037662002-12-30 03:01:48 +0000712 return Py_BuildValue("(ii)", volume & 0xff, (volume & 0xff00) >> 8);
Greg Ward3d9994d2002-12-11 15:12:01 +0000713}
714
715static PyObject *
Greg Warde7037662002-12-30 03:01:48 +0000716oss_mixer_set(oss_mixer_t *self, PyObject *args)
Greg Ward3d9994d2002-12-11 15:12:01 +0000717{
718 int channel, volume, leftVol, rightVol;
719
720 /* Can't use _do_ioctl_1 because of encoded arg thingy. */
Greg Warde7037662002-12-30 03:01:48 +0000721 if (!PyArg_ParseTuple(args, "i(ii):set", &channel, &leftVol, &rightVol))
Greg Wardad4d9b92002-12-30 03:02:22 +0000722 return NULL;
723
Greg Ward3d9994d2002-12-11 15:12:01 +0000724 if (channel < 0 || channel > SOUND_MIXER_NRDEVICES) {
Greg Wardad4d9b92002-12-30 03:02:22 +0000725 PyErr_SetString(OSSAudioError, "Invalid mixer channel specified.");
726 return NULL;
Greg Ward3d9994d2002-12-11 15:12:01 +0000727 }
728
729 if (leftVol < 0 || rightVol < 0 || leftVol > 100 || rightVol > 100) {
Greg Wardad4d9b92002-12-30 03:02:22 +0000730 PyErr_SetString(OSSAudioError, "Volumes must be between 0 and 100.");
731 return NULL;
Greg Ward3d9994d2002-12-11 15:12:01 +0000732 }
733
734 volume = (rightVol << 8) | leftVol;
735
Greg Warde7037662002-12-30 03:01:48 +0000736 if (ioctl(self->fd, MIXER_WRITE(channel), &volume) == -1)
Greg Wardad4d9b92002-12-30 03:02:22 +0000737 return PyErr_SetFromErrno(PyExc_IOError);
Greg Ward3d9994d2002-12-11 15:12:01 +0000738
Greg Warde7037662002-12-30 03:01:48 +0000739 return Py_BuildValue("(ii)", volume & 0xff, (volume & 0xff00) >> 8);
Greg Ward3d9994d2002-12-11 15:12:01 +0000740}
741
742static PyObject *
Greg Wardf05aa102002-12-30 23:19:32 +0000743oss_mixer_get_recsrc(oss_mixer_t *self, PyObject *args)
Greg Ward3d9994d2002-12-11 15:12:01 +0000744{
Greg Wardf05aa102002-12-30 23:19:32 +0000745 return _do_ioctl_1_internal(self->fd, args, "get_recsrc",
Greg Ward3d9994d2002-12-11 15:12:01 +0000746 SOUND_MIXER_READ_RECSRC);
747}
748
749static PyObject *
Greg Wardf05aa102002-12-30 23:19:32 +0000750oss_mixer_set_recsrc(oss_mixer_t *self, PyObject *args)
Greg Ward3d9994d2002-12-11 15:12:01 +0000751{
Greg Wardf05aa102002-12-30 23:19:32 +0000752 return _do_ioctl_1(self->fd, args, "set_recsrc",
Greg Ward3d9994d2002-12-11 15:12:01 +0000753 SOUND_MIXER_WRITE_RECSRC);
754}
755
756
Greg Ward8c6b6a92002-12-11 14:43:13 +0000757static PyMethodDef oss_methods[] = {
Greg Ward131bce02002-11-30 22:56:44 +0000758 /* Regular file methods */
Greg Wardad4d9b92002-12-30 03:02:22 +0000759 { "read", (PyCFunction)oss_read, METH_VARARGS },
760 { "write", (PyCFunction)oss_write, METH_VARARGS },
761 { "writeall", (PyCFunction)oss_writeall, METH_VARARGS },
762 { "close", (PyCFunction)oss_close, METH_VARARGS },
763 { "fileno", (PyCFunction)oss_fileno, METH_VARARGS },
Greg Ward131bce02002-11-30 22:56:44 +0000764
765 /* Simple ioctl wrappers */
Greg Ward8c6b6a92002-12-11 14:43:13 +0000766 { "nonblock", (PyCFunction)oss_nonblock, METH_VARARGS },
Greg Wardad4d9b92002-12-30 03:02:22 +0000767 { "setfmt", (PyCFunction)oss_setfmt, METH_VARARGS },
Greg Ward8c6b6a92002-12-11 14:43:13 +0000768 { "getfmts", (PyCFunction)oss_getfmts, METH_VARARGS },
769 { "channels", (PyCFunction)oss_channels, METH_VARARGS },
770 { "speed", (PyCFunction)oss_speed, METH_VARARGS },
Greg Wardad4d9b92002-12-30 03:02:22 +0000771 { "sync", (PyCFunction)oss_sync, METH_VARARGS },
772 { "reset", (PyCFunction)oss_reset, METH_VARARGS },
773 { "post", (PyCFunction)oss_post, METH_VARARGS },
Greg Ward131bce02002-11-30 22:56:44 +0000774
775 /* Convenience methods -- wrap a couple of ioctls together */
Greg Wardad4d9b92002-12-30 03:02:22 +0000776 { "setparameters", (PyCFunction)oss_setparameters, METH_VARARGS },
777 { "bufsize", (PyCFunction)oss_bufsize, METH_VARARGS },
778 { "obufcount", (PyCFunction)oss_obufcount, METH_VARARGS },
779 { "obuffree", (PyCFunction)oss_obuffree, METH_VARARGS },
Greg Ward8c6b6a92002-12-11 14:43:13 +0000780 { "getptr", (PyCFunction)oss_getptr, METH_VARARGS },
Greg Ward131bce02002-11-30 22:56:44 +0000781
782 /* Aliases for backwards compatibility */
Greg Wardad4d9b92002-12-30 03:02:22 +0000783 { "flush", (PyCFunction)oss_sync, METH_VARARGS },
Greg Ward131bce02002-11-30 22:56:44 +0000784
Greg Wardad4d9b92002-12-30 03:02:22 +0000785 { NULL, NULL} /* sentinel */
Greg Ward04613a92002-11-30 22:47:45 +0000786};
787
Greg Ward3d9994d2002-12-11 15:12:01 +0000788static PyMethodDef oss_mixer_methods[] = {
789 /* Regular file method - OSS mixers are ioctl-only interface */
Greg Wardad4d9b92002-12-30 03:02:22 +0000790 { "close", (PyCFunction)oss_mixer_close, METH_VARARGS },
791 { "fileno", (PyCFunction)oss_mixer_fileno, METH_VARARGS },
Greg Ward3d9994d2002-12-11 15:12:01 +0000792
793 /* Simple ioctl wrappers */
Greg Wardad4d9b92002-12-30 03:02:22 +0000794 { "devices", (PyCFunction)oss_mixer_devices, METH_VARARGS },
Greg Ward37897c22002-12-30 02:43:36 +0000795 { "stereodevices", (PyCFunction)oss_mixer_stereodevices, METH_VARARGS},
796 { "recdevices", (PyCFunction)oss_mixer_recdevices, METH_VARARGS},
Greg Wardad4d9b92002-12-30 03:02:22 +0000797 { "get", (PyCFunction)oss_mixer_get, METH_VARARGS },
798 { "set", (PyCFunction)oss_mixer_set, METH_VARARGS },
Greg Wardf05aa102002-12-30 23:19:32 +0000799 { "get_recsrc", (PyCFunction)oss_mixer_get_recsrc, METH_VARARGS },
800 { "set_recsrc", (PyCFunction)oss_mixer_set_recsrc, METH_VARARGS },
Greg Ward3d9994d2002-12-11 15:12:01 +0000801
Greg Wardad4d9b92002-12-30 03:02:22 +0000802 { NULL, NULL}
Greg Ward3d9994d2002-12-11 15:12:01 +0000803};
804
Greg Ward04613a92002-11-30 22:47:45 +0000805static PyObject *
Greg Ward8c6b6a92002-12-11 14:43:13 +0000806oss_getattr(oss_t *xp, char *name)
Greg Ward04613a92002-11-30 22:47:45 +0000807{
Greg Ward8c6b6a92002-12-11 14:43:13 +0000808 return Py_FindMethod(oss_methods, (PyObject *)xp, name);
Greg Ward04613a92002-11-30 22:47:45 +0000809}
810
Greg Ward3d9994d2002-12-11 15:12:01 +0000811static PyObject *
812oss_mixer_getattr(oss_mixer_t *xp, char *name)
813{
814 return Py_FindMethod(oss_mixer_methods, (PyObject *)xp, name);
815}
816
Greg Ward8c6b6a92002-12-11 14:43:13 +0000817static PyTypeObject OSSType = {
Greg Ward04613a92002-11-30 22:47:45 +0000818 PyObject_HEAD_INIT(&PyType_Type)
Greg Wardad4d9b92002-12-30 03:02:22 +0000819 0, /*ob_size*/
Greg Ward9a568eb2002-11-30 23:20:09 +0000820 "ossaudiodev.oss_audio_device", /*tp_name*/
Greg Wardad4d9b92002-12-30 03:02:22 +0000821 sizeof(oss_t), /*tp_size*/
822 0, /*tp_itemsize*/
Greg Ward04613a92002-11-30 22:47:45 +0000823 /* methods */
Greg Wardad4d9b92002-12-30 03:02:22 +0000824 (destructor)oss_dealloc, /*tp_dealloc*/
825 0, /*tp_print*/
826 (getattrfunc)oss_getattr, /*tp_getattr*/
827 0, /*tp_setattr*/
828 0, /*tp_compare*/
829 0, /*tp_repr*/
Greg Ward04613a92002-11-30 22:47:45 +0000830};
831
Greg Ward3d9994d2002-12-11 15:12:01 +0000832static PyTypeObject OSSMixerType = {
833 PyObject_HEAD_INIT(&PyType_Type)
Greg Wardad4d9b92002-12-30 03:02:22 +0000834 0, /*ob_size*/
Greg Ward3d9994d2002-12-11 15:12:01 +0000835 "ossaudiodev.oss_mixer_device", /*tp_name*/
Greg Wardad4d9b92002-12-30 03:02:22 +0000836 sizeof(oss_mixer_t), /*tp_size*/
837 0, /*tp_itemsize*/
Greg Ward3d9994d2002-12-11 15:12:01 +0000838 /* methods */
839 (destructor)oss_mixer_dealloc, /*tp_dealloc*/
Greg Wardad4d9b92002-12-30 03:02:22 +0000840 0, /*tp_print*/
Greg Ward3d9994d2002-12-11 15:12:01 +0000841 (getattrfunc)oss_mixer_getattr, /*tp_getattr*/
Greg Wardad4d9b92002-12-30 03:02:22 +0000842 0, /*tp_setattr*/
843 0, /*tp_compare*/
844 0, /*tp_repr*/
Greg Ward3d9994d2002-12-11 15:12:01 +0000845};
846
847
Greg Ward04613a92002-11-30 22:47:45 +0000848static PyObject *
Greg Ward9a568eb2002-11-30 23:20:09 +0000849ossopen(PyObject *self, PyObject *args)
Greg Ward04613a92002-11-30 22:47:45 +0000850{
Greg Ward8c6b6a92002-12-11 14:43:13 +0000851 return (PyObject *)newossobject(args);
Greg Ward04613a92002-11-30 22:47:45 +0000852}
853
Greg Ward3d9994d2002-12-11 15:12:01 +0000854static PyObject *
855ossopenmixer(PyObject *self, PyObject *args)
856{
857 return (PyObject *)newossmixerobject(args);
858}
859
Greg Ward9a568eb2002-11-30 23:20:09 +0000860static PyMethodDef ossaudiodev_methods[] = {
861 { "open", ossopen, METH_VARARGS },
Greg Ward3d9994d2002-12-11 15:12:01 +0000862 { "openmixer", ossopenmixer, METH_VARARGS },
Greg Ward04613a92002-11-30 22:47:45 +0000863 { 0, 0 },
864};
865
Greg Ward1e0f57d2002-11-30 23:05:26 +0000866
867#define _EXPORT_INT(mod, name) \
868 if (PyModule_AddIntConstant(mod, #name, (long) (name)) == -1) return;
869
Greg Ward04613a92002-11-30 22:47:45 +0000870void
Greg Ward9a568eb2002-11-30 23:20:09 +0000871initossaudiodev(void)
Greg Ward04613a92002-11-30 22:47:45 +0000872{
873 PyObject *m;
874
Greg Ward9a568eb2002-11-30 23:20:09 +0000875 m = Py_InitModule("ossaudiodev", ossaudiodev_methods);
Greg Ward04613a92002-11-30 22:47:45 +0000876
Greg Ward97708bc2002-11-30 23:17:10 +0000877 OSSAudioError = PyErr_NewException("ossaudiodev.error", NULL, NULL);
878 if (OSSAudioError)
Greg Wardad4d9b92002-12-30 03:02:22 +0000879 PyModule_AddObject(m, "error", OSSAudioError);
Greg Ward04613a92002-11-30 22:47:45 +0000880
Greg Ward1e0f57d2002-11-30 23:05:26 +0000881 /* Expose the audio format numbers -- essential! */
882 _EXPORT_INT(m, AFMT_QUERY);
883 _EXPORT_INT(m, AFMT_MU_LAW);
884 _EXPORT_INT(m, AFMT_A_LAW);
885 _EXPORT_INT(m, AFMT_IMA_ADPCM);
886 _EXPORT_INT(m, AFMT_U8);
887 _EXPORT_INT(m, AFMT_S16_LE);
888 _EXPORT_INT(m, AFMT_S16_BE);
889 _EXPORT_INT(m, AFMT_S8);
890 _EXPORT_INT(m, AFMT_U16_LE);
891 _EXPORT_INT(m, AFMT_U16_BE);
892 _EXPORT_INT(m, AFMT_MPEG);
893 _EXPORT_INT(m, AFMT_AC3);
894 _EXPORT_INT(m, AFMT_S16_NE);
Greg Wardad4d9b92002-12-30 03:02:22 +0000895
Greg Ward37897c22002-12-30 02:43:36 +0000896 /* Expose the sound mixer device numbers. */
Greg Ward7b43c682002-12-30 02:29:28 +0000897 _EXPORT_INT(m, SOUND_MIXER_NRDEVICES);
Greg Ward3d9994d2002-12-11 15:12:01 +0000898 _EXPORT_INT(m, SOUND_MIXER_VOLUME);
899 _EXPORT_INT(m, SOUND_MIXER_BASS);
900 _EXPORT_INT(m, SOUND_MIXER_TREBLE);
901 _EXPORT_INT(m, SOUND_MIXER_SYNTH);
902 _EXPORT_INT(m, SOUND_MIXER_PCM);
903 _EXPORT_INT(m, SOUND_MIXER_SPEAKER);
904 _EXPORT_INT(m, SOUND_MIXER_LINE);
905 _EXPORT_INT(m, SOUND_MIXER_MIC);
906 _EXPORT_INT(m, SOUND_MIXER_CD);
907 _EXPORT_INT(m, SOUND_MIXER_IMIX);
908 _EXPORT_INT(m, SOUND_MIXER_ALTPCM);
909 _EXPORT_INT(m, SOUND_MIXER_RECLEV);
910 _EXPORT_INT(m, SOUND_MIXER_IGAIN);
911 _EXPORT_INT(m, SOUND_MIXER_OGAIN);
912 _EXPORT_INT(m, SOUND_MIXER_LINE1);
913 _EXPORT_INT(m, SOUND_MIXER_LINE2);
914 _EXPORT_INT(m, SOUND_MIXER_LINE3);
915 _EXPORT_INT(m, SOUND_MIXER_DIGITAL1);
916 _EXPORT_INT(m, SOUND_MIXER_DIGITAL2);
917 _EXPORT_INT(m, SOUND_MIXER_DIGITAL3);
918 _EXPORT_INT(m, SOUND_MIXER_PHONEIN);
919 _EXPORT_INT(m, SOUND_MIXER_PHONEOUT);
920 _EXPORT_INT(m, SOUND_MIXER_VIDEO);
921 _EXPORT_INT(m, SOUND_MIXER_RADIO);
922 _EXPORT_INT(m, SOUND_MIXER_MONITOR);
Greg Ward04613a92002-11-30 22:47:45 +0000923
Greg Ward1e0f57d2002-11-30 23:05:26 +0000924 /* Expose all the ioctl numbers for masochists who like to do this
925 stuff directly. */
926 _EXPORT_INT(m, SNDCTL_COPR_HALT);
927 _EXPORT_INT(m, SNDCTL_COPR_LOAD);
928 _EXPORT_INT(m, SNDCTL_COPR_RCODE);
929 _EXPORT_INT(m, SNDCTL_COPR_RCVMSG);
930 _EXPORT_INT(m, SNDCTL_COPR_RDATA);
931 _EXPORT_INT(m, SNDCTL_COPR_RESET);
932 _EXPORT_INT(m, SNDCTL_COPR_RUN);
933 _EXPORT_INT(m, SNDCTL_COPR_SENDMSG);
934 _EXPORT_INT(m, SNDCTL_COPR_WCODE);
935 _EXPORT_INT(m, SNDCTL_COPR_WDATA);
936 _EXPORT_INT(m, SNDCTL_DSP_BIND_CHANNEL);
937 _EXPORT_INT(m, SNDCTL_DSP_CHANNELS);
938 _EXPORT_INT(m, SNDCTL_DSP_GETBLKSIZE);
939 _EXPORT_INT(m, SNDCTL_DSP_GETCAPS);
940 _EXPORT_INT(m, SNDCTL_DSP_GETCHANNELMASK);
941 _EXPORT_INT(m, SNDCTL_DSP_GETFMTS);
942 _EXPORT_INT(m, SNDCTL_DSP_GETIPTR);
943 _EXPORT_INT(m, SNDCTL_DSP_GETISPACE);
944 _EXPORT_INT(m, SNDCTL_DSP_GETODELAY);
945 _EXPORT_INT(m, SNDCTL_DSP_GETOPTR);
946 _EXPORT_INT(m, SNDCTL_DSP_GETOSPACE);
947 _EXPORT_INT(m, SNDCTL_DSP_GETSPDIF);
948 _EXPORT_INT(m, SNDCTL_DSP_GETTRIGGER);
949 _EXPORT_INT(m, SNDCTL_DSP_MAPINBUF);
950 _EXPORT_INT(m, SNDCTL_DSP_MAPOUTBUF);
951 _EXPORT_INT(m, SNDCTL_DSP_NONBLOCK);
952 _EXPORT_INT(m, SNDCTL_DSP_POST);
953 _EXPORT_INT(m, SNDCTL_DSP_PROFILE);
954 _EXPORT_INT(m, SNDCTL_DSP_RESET);
955 _EXPORT_INT(m, SNDCTL_DSP_SAMPLESIZE);
956 _EXPORT_INT(m, SNDCTL_DSP_SETDUPLEX);
957 _EXPORT_INT(m, SNDCTL_DSP_SETFMT);
958 _EXPORT_INT(m, SNDCTL_DSP_SETFRAGMENT);
959 _EXPORT_INT(m, SNDCTL_DSP_SETSPDIF);
960 _EXPORT_INT(m, SNDCTL_DSP_SETSYNCRO);
961 _EXPORT_INT(m, SNDCTL_DSP_SETTRIGGER);
962 _EXPORT_INT(m, SNDCTL_DSP_SPEED);
963 _EXPORT_INT(m, SNDCTL_DSP_STEREO);
964 _EXPORT_INT(m, SNDCTL_DSP_SUBDIVIDE);
965 _EXPORT_INT(m, SNDCTL_DSP_SYNC);
966 _EXPORT_INT(m, SNDCTL_FM_4OP_ENABLE);
967 _EXPORT_INT(m, SNDCTL_FM_LOAD_INSTR);
968 _EXPORT_INT(m, SNDCTL_MIDI_INFO);
969 _EXPORT_INT(m, SNDCTL_MIDI_MPUCMD);
970 _EXPORT_INT(m, SNDCTL_MIDI_MPUMODE);
971 _EXPORT_INT(m, SNDCTL_MIDI_PRETIME);
972 _EXPORT_INT(m, SNDCTL_SEQ_CTRLRATE);
973 _EXPORT_INT(m, SNDCTL_SEQ_GETINCOUNT);
974 _EXPORT_INT(m, SNDCTL_SEQ_GETOUTCOUNT);
975 _EXPORT_INT(m, SNDCTL_SEQ_GETTIME);
976 _EXPORT_INT(m, SNDCTL_SEQ_NRMIDIS);
977 _EXPORT_INT(m, SNDCTL_SEQ_NRSYNTHS);
978 _EXPORT_INT(m, SNDCTL_SEQ_OUTOFBAND);
979 _EXPORT_INT(m, SNDCTL_SEQ_PANIC);
980 _EXPORT_INT(m, SNDCTL_SEQ_PERCMODE);
981 _EXPORT_INT(m, SNDCTL_SEQ_RESET);
982 _EXPORT_INT(m, SNDCTL_SEQ_RESETSAMPLES);
983 _EXPORT_INT(m, SNDCTL_SEQ_SYNC);
984 _EXPORT_INT(m, SNDCTL_SEQ_TESTMIDI);
985 _EXPORT_INT(m, SNDCTL_SEQ_THRESHOLD);
986 _EXPORT_INT(m, SNDCTL_SYNTH_CONTROL);
987 _EXPORT_INT(m, SNDCTL_SYNTH_ID);
988 _EXPORT_INT(m, SNDCTL_SYNTH_INFO);
989 _EXPORT_INT(m, SNDCTL_SYNTH_MEMAVL);
990 _EXPORT_INT(m, SNDCTL_SYNTH_REMOVESAMPLE);
991 _EXPORT_INT(m, SNDCTL_TMR_CONTINUE);
992 _EXPORT_INT(m, SNDCTL_TMR_METRONOME);
993 _EXPORT_INT(m, SNDCTL_TMR_SELECT);
994 _EXPORT_INT(m, SNDCTL_TMR_SOURCE);
995 _EXPORT_INT(m, SNDCTL_TMR_START);
996 _EXPORT_INT(m, SNDCTL_TMR_STOP);
997 _EXPORT_INT(m, SNDCTL_TMR_TEMPO);
998 _EXPORT_INT(m, SNDCTL_TMR_TIMEBASE);
Greg Ward04613a92002-11-30 22:47:45 +0000999}