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