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