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