Python-2.7.3/Modules/ossaudiodev.c

Location Tool Test ID Function Issue
/builddir/build/BUILD/Python-2.7.3/Modules/ossaudiodev.c:566:0 cppcheck syntaxError syntax error
/builddir/build/BUILD/Python-2.7.3/Modules/ossaudiodev.c:566:0 cppcheck syntaxError syntax error
   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 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 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@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@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     PyObject * rv;                    /* return tuple (fmt, channels, rate) */
 494 
 495     if (!PyArg_ParseTuple(args, "iii|i:setparameters",
 496                           &wanted_fmt, &wanted_channels, &wanted_rate,
 497                           &strict))
 498         return NULL;
 499 
 500     fmt = wanted_fmt;
 501     if (ioctl(self->fd, SNDCTL_DSP_SETFMT, &fmt) == -1) {
 502         return PyErr_SetFromErrno(PyExc_IOError);
 503     }
 504     if (strict && fmt != wanted_fmt) {
 505         return PyErr_Format
 506             (OSSAudioError,
 507              "unable to set requested format (wanted %d, got %d)",
 508              wanted_fmt, fmt);
 509     }
 510 
 511     channels = wanted_channels;
 512     if (ioctl(self->fd, SNDCTL_DSP_CHANNELS, &channels) == -1) {
 513         return PyErr_SetFromErrno(PyExc_IOError);
 514     }
 515     if (strict && channels != wanted_channels) {
 516         return PyErr_Format
 517             (OSSAudioError,
 518              "unable to set requested channels (wanted %d, got %d)",
 519              wanted_channels, channels);
 520     }
 521 
 522     rate = wanted_rate;
 523     if (ioctl(self->fd, SNDCTL_DSP_SPEED, &rate) == -1) {
 524         return PyErr_SetFromErrno(PyExc_IOError);
 525     }
 526     if (strict && rate != wanted_rate) {
 527         return PyErr_Format
 528             (OSSAudioError,
 529              "unable to set requested rate (wanted %d, got %d)",
 530              wanted_rate, rate);
 531     }
 532 
 533     /* Construct the return value: a (fmt, channels, rate) tuple that
 534        tells what the audio hardware was actually set to. */
 535     rv = PyTuple_New(3);
 536     if (rv == NULL)
 537         return NULL;
 538     PyTuple_SET_ITEM(rv, 0, PyInt_FromLong(fmt));
 539     PyTuple_SET_ITEM(rv, 1, PyInt_FromLong(channels));
 540     PyTuple_SET_ITEM(rv, 2, PyInt_FromLong(rate));
 541     return rv;
 542 }
 543 
 544 static int
 545 _ssize(oss_audio_t *self, int *nchannels, int *ssize)
 546 {
 547     int fmt;
 548 
 549     fmt = 0;
 550     if (ioctl(self->fd, SNDCTL_DSP_SETFMT, &fmt) < 0)
 551         return -errno;
 552 
 553     switch (fmt) {
 554     case AFMT_MU_LAW:
 555     case AFMT_A_LAW:
 556     case AFMT_U8:
 557     case AFMT_S8:
 558         *ssize = 1;                     /* 8 bit formats: 1 byte */
 559         break;
 560     case AFMT_S16_LE:
 561     case AFMT_S16_BE:
 562     case AFMT_U16_LE:
 563     case AFMT_U16_BE:
 564         *ssize = 2;                     /* 16 bit formats: 2 byte */
 565         break;
 566     case AFMT_MPEG:
syntax error
(emitted by cppcheck)
syntax error
(emitted by cppcheck)
567 case AFMT_IMA_ADPCM: 568 default: 569 return -EOPNOTSUPP; 570 } 571 if (ioctl(self->fd, SNDCTL_DSP_CHANNELS, nchannels) < 0) 572 return -errno; 573 return 0; 574 } 575 576 577 /* bufsize returns the size of the hardware audio buffer in number 578 of samples */ 579 static PyObject * 580 oss_bufsize(oss_audio_t *self, PyObject *unused) 581 { 582 audio_buf_info ai; 583 int nchannels=0, ssize=0; 584 585 if (_ssize(self, &nchannels, &ssize) < 0 || !nchannels || !ssize) { 586 PyErr_SetFromErrno(PyExc_IOError); 587 return NULL; 588 } 589 if (ioctl(self->fd, SNDCTL_DSP_GETOSPACE, &ai) < 0) { 590 PyErr_SetFromErrno(PyExc_IOError); 591 return NULL; 592 } 593 return PyInt_FromLong((ai.fragstotal * ai.fragsize) / (nchannels * ssize)); 594 } 595 596 /* obufcount returns the number of samples that are available in the 597 hardware for playing */ 598 static PyObject * 599 oss_obufcount(oss_audio_t *self, PyObject *unused) 600 { 601 audio_buf_info ai; 602 int nchannels=0, ssize=0; 603 604 if (_ssize(self, &nchannels, &ssize) < 0 || !nchannels || !ssize) { 605 PyErr_SetFromErrno(PyExc_IOError); 606 return NULL; 607 } 608 if (ioctl(self->fd, SNDCTL_DSP_GETOSPACE, &ai) < 0) { 609 PyErr_SetFromErrno(PyExc_IOError); 610 return NULL; 611 } 612 return PyInt_FromLong((ai.fragstotal * ai.fragsize - ai.bytes) / 613 (ssize * nchannels)); 614 } 615 616 /* obufcount returns the number of samples that can be played without 617 blocking */ 618 static PyObject * 619 oss_obuffree(oss_audio_t *self, PyObject *unused) 620 { 621 audio_buf_info ai; 622 int nchannels=0, ssize=0; 623 624 if (_ssize(self, &nchannels, &ssize) < 0 || !nchannels || !ssize) { 625 PyErr_SetFromErrno(PyExc_IOError); 626 return NULL; 627 } 628 if (ioctl(self->fd, SNDCTL_DSP_GETOSPACE, &ai) < 0) { 629 PyErr_SetFromErrno(PyExc_IOError); 630 return NULL; 631 } 632 return PyInt_FromLong(ai.bytes / (ssize * nchannels)); 633 } 634 635 static PyObject * 636 oss_getptr(oss_audio_t *self, PyObject *unused) 637 { 638 count_info info; 639 int req; 640 641 if (self->mode == O_RDONLY) 642 req = SNDCTL_DSP_GETIPTR; 643 else 644 req = SNDCTL_DSP_GETOPTR; 645 if (ioctl(self->fd, req, &info) == -1) { 646 PyErr_SetFromErrno(PyExc_IOError); 647 return NULL; 648 } 649 return Py_BuildValue("iii", info.bytes, info.blocks, info.ptr); 650 } 651 652 653 /* ---------------------------------------------------------------------- 654 * Methods of mixer objects (OSSMixerType) 655 */ 656 657 static PyObject * 658 oss_mixer_close(oss_mixer_t *self, PyObject *unused) 659 { 660 if (self->fd >= 0) { 661 close(self->fd); 662 self->fd = -1; 663 } 664 Py_INCREF(Py_None); 665 return Py_None; 666 } 667 668 static PyObject * 669 oss_mixer_fileno(oss_mixer_t *self, PyObject *unused) 670 { 671 return PyInt_FromLong(self->fd); 672 } 673 674 /* Simple mixer interface methods */ 675 676 static PyObject * 677 oss_mixer_controls(oss_mixer_t *self, PyObject *args) 678 { 679 return _do_ioctl_1_internal(self->fd, args, "controls", 680 SOUND_MIXER_READ_DEVMASK); 681 } 682 683 static PyObject * 684 oss_mixer_stereocontrols(oss_mixer_t *self, PyObject *args) 685 { 686 return _do_ioctl_1_internal(self->fd, args, "stereocontrols", 687 SOUND_MIXER_READ_STEREODEVS); 688 } 689 690 static PyObject * 691 oss_mixer_reccontrols(oss_mixer_t *self, PyObject *args) 692 { 693 return _do_ioctl_1_internal(self->fd, args, "reccontrols", 694 SOUND_MIXER_READ_RECMASK); 695 } 696 697 static PyObject * 698 oss_mixer_get(oss_mixer_t *self, PyObject *args) 699 { 700 int channel, volume; 701 702 /* Can't use _do_ioctl_1 because of encoded arg thingy. */ 703 if (!PyArg_ParseTuple(args, "i:get", &channel)) 704 return NULL; 705 706 if (channel < 0 || channel > SOUND_MIXER_NRDEVICES) { 707 PyErr_SetString(OSSAudioError, "Invalid mixer channel specified."); 708 return NULL; 709 } 710 711 if (ioctl(self->fd, MIXER_READ(channel), &volume) == -1) 712 return PyErr_SetFromErrno(PyExc_IOError); 713 714 return Py_BuildValue("(ii)", volume & 0xff, (volume & 0xff00) >> 8); 715 } 716 717 static PyObject * 718 oss_mixer_set(oss_mixer_t *self, PyObject *args) 719 { 720 int channel, volume, leftVol, rightVol; 721 722 /* Can't use _do_ioctl_1 because of encoded arg thingy. */ 723 if (!PyArg_ParseTuple(args, "i(ii):set", &channel, &leftVol, &rightVol)) 724 return NULL; 725 726 if (channel < 0 || channel > SOUND_MIXER_NRDEVICES) { 727 PyErr_SetString(OSSAudioError, "Invalid mixer channel specified."); 728 return NULL; 729 } 730 731 if (leftVol < 0 || rightVol < 0 || leftVol > 100 || rightVol > 100) { 732 PyErr_SetString(OSSAudioError, "Volumes must be between 0 and 100."); 733 return NULL; 734 } 735 736 volume = (rightVol << 8) | leftVol; 737 738 if (ioctl(self->fd, MIXER_WRITE(channel), &volume) == -1) 739 return PyErr_SetFromErrno(PyExc_IOError); 740 741 return Py_BuildValue("(ii)", volume & 0xff, (volume & 0xff00) >> 8); 742 } 743 744 static PyObject * 745 oss_mixer_get_recsrc(oss_mixer_t *self, PyObject *args) 746 { 747 return _do_ioctl_1_internal(self->fd, args, "get_recsrc", 748 SOUND_MIXER_READ_RECSRC); 749 } 750 751 static PyObject * 752 oss_mixer_set_recsrc(oss_mixer_t *self, PyObject *args) 753 { 754 return _do_ioctl_1(self->fd, args, "set_recsrc", 755 SOUND_MIXER_WRITE_RECSRC); 756 } 757 758 759 /* ---------------------------------------------------------------------- 760 * Method tables and other bureaucracy 761 */ 762 763 static PyMethodDef oss_methods[] = { 764 /* Regular file methods */ 765 { "read", (PyCFunction)oss_read, METH_VARARGS }, 766 { "write", (PyCFunction)oss_write, METH_VARARGS }, 767 { "writeall", (PyCFunction)oss_writeall, METH_VARARGS }, 768 { "close", (PyCFunction)oss_close, METH_NOARGS }, 769 { "fileno", (PyCFunction)oss_fileno, METH_NOARGS }, 770 771 /* Simple ioctl wrappers */ 772 { "nonblock", (PyCFunction)oss_nonblock, METH_NOARGS }, 773 { "setfmt", (PyCFunction)oss_setfmt, METH_VARARGS }, 774 { "getfmts", (PyCFunction)oss_getfmts, METH_NOARGS }, 775 { "channels", (PyCFunction)oss_channels, METH_VARARGS }, 776 { "speed", (PyCFunction)oss_speed, METH_VARARGS }, 777 { "sync", (PyCFunction)oss_sync, METH_VARARGS }, 778 { "reset", (PyCFunction)oss_reset, METH_VARARGS }, 779 { "post", (PyCFunction)oss_post, METH_VARARGS }, 780 781 /* Convenience methods -- wrap a couple of ioctls together */ 782 { "setparameters", (PyCFunction)oss_setparameters, METH_VARARGS }, 783 { "bufsize", (PyCFunction)oss_bufsize, METH_NOARGS }, 784 { "obufcount", (PyCFunction)oss_obufcount, METH_NOARGS }, 785 { "obuffree", (PyCFunction)oss_obuffree, METH_NOARGS }, 786 { "getptr", (PyCFunction)oss_getptr, METH_NOARGS }, 787 788 /* Aliases for backwards compatibility */ 789 { "flush", (PyCFunction)oss_sync, METH_VARARGS }, 790 791 { NULL, NULL} /* sentinel */ 792 }; 793 794 static PyMethodDef oss_mixer_methods[] = { 795 /* Regular file method - OSS mixers are ioctl-only interface */ 796 { "close", (PyCFunction)oss_mixer_close, METH_NOARGS }, 797 { "fileno", (PyCFunction)oss_mixer_fileno, METH_NOARGS }, 798 799 /* Simple ioctl wrappers */ 800 { "controls", (PyCFunction)oss_mixer_controls, METH_VARARGS }, 801 { "stereocontrols", (PyCFunction)oss_mixer_stereocontrols, METH_VARARGS}, 802 { "reccontrols", (PyCFunction)oss_mixer_reccontrols, METH_VARARGS}, 803 { "get", (PyCFunction)oss_mixer_get, METH_VARARGS }, 804 { "set", (PyCFunction)oss_mixer_set, METH_VARARGS }, 805 { "get_recsrc", (PyCFunction)oss_mixer_get_recsrc, METH_VARARGS }, 806 { "set_recsrc", (PyCFunction)oss_mixer_set_recsrc, METH_VARARGS }, 807 808 { NULL, NULL} 809 }; 810 811 static PyObject * 812 oss_getattr(oss_audio_t *self, char *name) 813 { 814 PyObject * rval = NULL; 815 if (strcmp(name, "closed") == 0) { 816 rval = (self->fd == -1) ? Py_True : Py_False; 817 Py_INCREF(rval); 818 } 819 else if (strcmp(name, "name") == 0) { 820 rval = PyString_FromString(self->devicename); 821 } 822 else if (strcmp(name, "mode") == 0) { 823 /* No need for a "default" in this switch: from newossobject(), 824 self->mode can only be one of these three values. */ 825 switch(self->mode) { 826 case O_RDONLY: 827 rval = PyString_FromString("r"); 828 break; 829 case O_RDWR: 830 rval = PyString_FromString("rw"); 831 break; 832 case O_WRONLY: 833 rval = PyString_FromString("w"); 834 break; 835 } 836 } 837 else { 838 rval = Py_FindMethod(oss_methods, (PyObject *)self, name); 839 } 840 return rval; 841 } 842 843 static PyObject * 844 oss_mixer_getattr(oss_mixer_t *self, char *name) 845 { 846 return Py_FindMethod(oss_mixer_methods, (PyObject *)self, name); 847 } 848 849 static PyTypeObject OSSAudioType = { 850 PyVarObject_HEAD_INIT(&PyType_Type, 0) 851 "ossaudiodev.oss_audio_device", /*tp_name*/ 852 sizeof(oss_audio_t), /*tp_size*/ 853 0, /*tp_itemsize*/ 854 /* methods */ 855 (destructor)oss_dealloc, /*tp_dealloc*/ 856 0, /*tp_print*/ 857 (getattrfunc)oss_getattr, /*tp_getattr*/ 858 0, /*tp_setattr*/ 859 0, /*tp_compare*/ 860 0, /*tp_repr*/ 861 }; 862 863 static PyTypeObject OSSMixerType = { 864 PyVarObject_HEAD_INIT(&PyType_Type, 0) 865 "ossaudiodev.oss_mixer_device", /*tp_name*/ 866 sizeof(oss_mixer_t), /*tp_size*/ 867 0, /*tp_itemsize*/ 868 /* methods */ 869 (destructor)oss_mixer_dealloc, /*tp_dealloc*/ 870 0, /*tp_print*/ 871 (getattrfunc)oss_mixer_getattr, /*tp_getattr*/ 872 0, /*tp_setattr*/ 873 0, /*tp_compare*/ 874 0, /*tp_repr*/ 875 }; 876 877 878 static PyObject * 879 ossopen(PyObject *self, PyObject *args) 880 { 881 return (PyObject *)newossobject(args); 882 } 883 884 static PyObject * 885 ossopenmixer(PyObject *self, PyObject *args) 886 { 887 return (PyObject *)newossmixerobject(args); 888 } 889 890 static PyMethodDef ossaudiodev_methods[] = { 891 { "open", ossopen, METH_VARARGS }, 892 { "openmixer", ossopenmixer, METH_VARARGS }, 893 { 0, 0 }, 894 }; 895 896 897 #define _EXPORT_INT(mod, name) \ 898 if (PyModule_AddIntConstant(mod, #name, (long) (name)) == -1) return; 899 900 901 static char *control_labels[] = SOUND_DEVICE_LABELS; 902 static char *control_names[] = SOUND_DEVICE_NAMES; 903 904 905 static int 906 build_namelists (PyObject *module) 907 { 908 PyObject *labels; 909 PyObject *names; 910 PyObject *s; 911 int num_controls; 912 int i; 913 914 num_controls = sizeof(control_labels) / sizeof(control_labels[0]); 915 assert(num_controls == sizeof(control_names) / sizeof(control_names[0])); 916 917 labels = PyList_New(num_controls); 918 names = PyList_New(num_controls); 919 if (labels == NULL || names == NULL) 920 goto error2; 921 for (i = 0; i < num_controls; i++) { 922 s = PyString_FromString(control_labels[i]); 923 if (s == NULL) 924 goto error2; 925 PyList_SET_ITEM(labels, i, s); 926 927 s = PyString_FromString(control_names[i]); 928 if (s == NULL) 929 goto error2; 930 PyList_SET_ITEM(names, i, s); 931 } 932 933 if (PyModule_AddObject(module, "control_labels", labels) == -1) 934 goto error2; 935 if (PyModule_AddObject(module, "control_names", names) == -1) 936 goto error1; 937 938 return 0; 939 940 error2: 941 Py_XDECREF(labels); 942 error1: 943 Py_XDECREF(names); 944 return -1; 945 } 946 947 948 void 949 initossaudiodev(void) 950 { 951 PyObject *m; 952 953 m = Py_InitModule("ossaudiodev", ossaudiodev_methods); 954 if (m == NULL) 955 return; 956 957 OSSAudioError = PyErr_NewException("ossaudiodev.OSSAudioError", 958 NULL, NULL); 959 if (OSSAudioError) { 960 /* Each call to PyModule_AddObject decrefs it; compensate: */ 961 Py_INCREF(OSSAudioError); 962 Py_INCREF(OSSAudioError); 963 PyModule_AddObject(m, "error", OSSAudioError); 964 PyModule_AddObject(m, "OSSAudioError", OSSAudioError); 965 } 966 967 /* Build 'control_labels' and 'control_names' lists and add them 968 to the module. */ 969 if (build_namelists(m) == -1) /* XXX what to do here? */ 970 return; 971 972 /* Expose the audio format numbers -- essential! */ 973 _EXPORT_INT(m, AFMT_QUERY); 974 _EXPORT_INT(m, AFMT_MU_LAW); 975 _EXPORT_INT(m, AFMT_A_LAW); 976 _EXPORT_INT(m, AFMT_IMA_ADPCM); 977 _EXPORT_INT(m, AFMT_U8); 978 _EXPORT_INT(m, AFMT_S16_LE); 979 _EXPORT_INT(m, AFMT_S16_BE); 980 _EXPORT_INT(m, AFMT_S8); 981 _EXPORT_INT(m, AFMT_U16_LE); 982 _EXPORT_INT(m, AFMT_U16_BE); 983 _EXPORT_INT(m, AFMT_MPEG); 984 #ifdef AFMT_AC3 985 _EXPORT_INT(m, AFMT_AC3); 986 #endif 987 #ifdef AFMT_S16_NE 988 _EXPORT_INT(m, AFMT_S16_NE); 989 #endif 990 #ifdef AFMT_U16_NE 991 _EXPORT_INT(m, AFMT_U16_NE); 992 #endif 993 #ifdef AFMT_S32_LE 994 _EXPORT_INT(m, AFMT_S32_LE); 995 #endif 996 #ifdef AFMT_S32_BE 997 _EXPORT_INT(m, AFMT_S32_BE); 998 #endif 999 #ifdef AFMT_MPEG 1000 _EXPORT_INT(m, AFMT_MPEG); 1001 #endif 1002 1003 /* Expose the sound mixer device numbers. */ 1004 _EXPORT_INT(m, SOUND_MIXER_NRDEVICES); 1005 _EXPORT_INT(m, SOUND_MIXER_VOLUME); 1006 _EXPORT_INT(m, SOUND_MIXER_BASS); 1007 _EXPORT_INT(m, SOUND_MIXER_TREBLE); 1008 _EXPORT_INT(m, SOUND_MIXER_SYNTH); 1009 _EXPORT_INT(m, SOUND_MIXER_PCM); 1010 _EXPORT_INT(m, SOUND_MIXER_SPEAKER); 1011 _EXPORT_INT(m, SOUND_MIXER_LINE); 1012 _EXPORT_INT(m, SOUND_MIXER_MIC); 1013 _EXPORT_INT(m, SOUND_MIXER_CD); 1014 _EXPORT_INT(m, SOUND_MIXER_IMIX); 1015 _EXPORT_INT(m, SOUND_MIXER_ALTPCM); 1016 _EXPORT_INT(m, SOUND_MIXER_RECLEV); 1017 _EXPORT_INT(m, SOUND_MIXER_IGAIN); 1018 _EXPORT_INT(m, SOUND_MIXER_OGAIN); 1019 _EXPORT_INT(m, SOUND_MIXER_LINE1); 1020 _EXPORT_INT(m, SOUND_MIXER_LINE2); 1021 _EXPORT_INT(m, SOUND_MIXER_LINE3); 1022 #ifdef SOUND_MIXER_DIGITAL1 1023 _EXPORT_INT(m, SOUND_MIXER_DIGITAL1); 1024 #endif 1025 #ifdef SOUND_MIXER_DIGITAL2 1026 _EXPORT_INT(m, SOUND_MIXER_DIGITAL2); 1027 #endif 1028 #ifdef SOUND_MIXER_DIGITAL3 1029 _EXPORT_INT(m, SOUND_MIXER_DIGITAL3); 1030 #endif 1031 #ifdef SOUND_MIXER_PHONEIN 1032 _EXPORT_INT(m, SOUND_MIXER_PHONEIN); 1033 #endif 1034 #ifdef SOUND_MIXER_PHONEOUT 1035 _EXPORT_INT(m, SOUND_MIXER_PHONEOUT); 1036 #endif 1037 #ifdef SOUND_MIXER_VIDEO 1038 _EXPORT_INT(m, SOUND_MIXER_VIDEO); 1039 #endif 1040 #ifdef SOUND_MIXER_RADIO 1041 _EXPORT_INT(m, SOUND_MIXER_RADIO); 1042 #endif 1043 #ifdef SOUND_MIXER_MONITOR 1044 _EXPORT_INT(m, SOUND_MIXER_MONITOR); 1045 #endif 1046 1047 /* Expose all the ioctl numbers for masochists who like to do this 1048 stuff directly. */ 1049 _EXPORT_INT(m, SNDCTL_COPR_HALT); 1050 _EXPORT_INT(m, SNDCTL_COPR_LOAD); 1051 _EXPORT_INT(m, SNDCTL_COPR_RCODE); 1052 _EXPORT_INT(m, SNDCTL_COPR_RCVMSG); 1053 _EXPORT_INT(m, SNDCTL_COPR_RDATA); 1054 _EXPORT_INT(m, SNDCTL_COPR_RESET); 1055 _EXPORT_INT(m, SNDCTL_COPR_RUN); 1056 _EXPORT_INT(m, SNDCTL_COPR_SENDMSG); 1057 _EXPORT_INT(m, SNDCTL_COPR_WCODE); 1058 _EXPORT_INT(m, SNDCTL_COPR_WDATA); 1059 #ifdef SNDCTL_DSP_BIND_CHANNEL 1060 _EXPORT_INT(m, SNDCTL_DSP_BIND_CHANNEL); 1061 #endif 1062 _EXPORT_INT(m, SNDCTL_DSP_CHANNELS); 1063 _EXPORT_INT(m, SNDCTL_DSP_GETBLKSIZE); 1064 _EXPORT_INT(m, SNDCTL_DSP_GETCAPS); 1065 #ifdef SNDCTL_DSP_GETCHANNELMASK 1066 _EXPORT_INT(m, SNDCTL_DSP_GETCHANNELMASK); 1067 #endif 1068 _EXPORT_INT(m, SNDCTL_DSP_GETFMTS); 1069 _EXPORT_INT(m, SNDCTL_DSP_GETIPTR); 1070 _EXPORT_INT(m, SNDCTL_DSP_GETISPACE); 1071 #ifdef SNDCTL_DSP_GETODELAY 1072 _EXPORT_INT(m, SNDCTL_DSP_GETODELAY); 1073 #endif 1074 _EXPORT_INT(m, SNDCTL_DSP_GETOPTR); 1075 _EXPORT_INT(m, SNDCTL_DSP_GETOSPACE); 1076 #ifdef SNDCTL_DSP_GETSPDIF 1077 _EXPORT_INT(m, SNDCTL_DSP_GETSPDIF); 1078 #endif 1079 _EXPORT_INT(m, SNDCTL_DSP_GETTRIGGER); 1080 _EXPORT_INT(m, SNDCTL_DSP_MAPINBUF); 1081 _EXPORT_INT(m, SNDCTL_DSP_MAPOUTBUF); 1082 _EXPORT_INT(m, SNDCTL_DSP_NONBLOCK); 1083 _EXPORT_INT(m, SNDCTL_DSP_POST); 1084 #ifdef SNDCTL_DSP_PROFILE 1085 _EXPORT_INT(m, SNDCTL_DSP_PROFILE); 1086 #endif 1087 _EXPORT_INT(m, SNDCTL_DSP_RESET); 1088 _EXPORT_INT(m, SNDCTL_DSP_SAMPLESIZE); 1089 _EXPORT_INT(m, SNDCTL_DSP_SETDUPLEX); 1090 _EXPORT_INT(m, SNDCTL_DSP_SETFMT); 1091 _EXPORT_INT(m, SNDCTL_DSP_SETFRAGMENT); 1092 #ifdef SNDCTL_DSP_SETSPDIF 1093 _EXPORT_INT(m, SNDCTL_DSP_SETSPDIF); 1094 #endif 1095 _EXPORT_INT(m, SNDCTL_DSP_SETSYNCRO); 1096 _EXPORT_INT(m, SNDCTL_DSP_SETTRIGGER); 1097 _EXPORT_INT(m, SNDCTL_DSP_SPEED); 1098 _EXPORT_INT(m, SNDCTL_DSP_STEREO); 1099 _EXPORT_INT(m, SNDCTL_DSP_SUBDIVIDE); 1100 _EXPORT_INT(m, SNDCTL_DSP_SYNC); 1101 _EXPORT_INT(m, SNDCTL_FM_4OP_ENABLE); 1102 _EXPORT_INT(m, SNDCTL_FM_LOAD_INSTR); 1103 _EXPORT_INT(m, SNDCTL_MIDI_INFO); 1104 _EXPORT_INT(m, SNDCTL_MIDI_MPUCMD); 1105 _EXPORT_INT(m, SNDCTL_MIDI_MPUMODE); 1106 _EXPORT_INT(m, SNDCTL_MIDI_PRETIME); 1107 _EXPORT_INT(m, SNDCTL_SEQ_CTRLRATE); 1108 _EXPORT_INT(m, SNDCTL_SEQ_GETINCOUNT); 1109 _EXPORT_INT(m, SNDCTL_SEQ_GETOUTCOUNT); 1110 #ifdef SNDCTL_SEQ_GETTIME 1111 _EXPORT_INT(m, SNDCTL_SEQ_GETTIME); 1112 #endif 1113 _EXPORT_INT(m, SNDCTL_SEQ_NRMIDIS); 1114 _EXPORT_INT(m, SNDCTL_SEQ_NRSYNTHS); 1115 _EXPORT_INT(m, SNDCTL_SEQ_OUTOFBAND); 1116 _EXPORT_INT(m, SNDCTL_SEQ_PANIC); 1117 _EXPORT_INT(m, SNDCTL_SEQ_PERCMODE); 1118 _EXPORT_INT(m, SNDCTL_SEQ_RESET); 1119 _EXPORT_INT(m, SNDCTL_SEQ_RESETSAMPLES); 1120 _EXPORT_INT(m, SNDCTL_SEQ_SYNC); 1121 _EXPORT_INT(m, SNDCTL_SEQ_TESTMIDI); 1122 _EXPORT_INT(m, SNDCTL_SEQ_THRESHOLD); 1123 #ifdef SNDCTL_SYNTH_CONTROL 1124 _EXPORT_INT(m, SNDCTL_SYNTH_CONTROL); 1125 #endif 1126 #ifdef SNDCTL_SYNTH_ID 1127 _EXPORT_INT(m, SNDCTL_SYNTH_ID); 1128 #endif 1129 _EXPORT_INT(m, SNDCTL_SYNTH_INFO); 1130 _EXPORT_INT(m, SNDCTL_SYNTH_MEMAVL); 1131 #ifdef SNDCTL_SYNTH_REMOVESAMPLE 1132 _EXPORT_INT(m, SNDCTL_SYNTH_REMOVESAMPLE); 1133 #endif 1134 _EXPORT_INT(m, SNDCTL_TMR_CONTINUE); 1135 _EXPORT_INT(m, SNDCTL_TMR_METRONOME); 1136 _EXPORT_INT(m, SNDCTL_TMR_SELECT); 1137 _EXPORT_INT(m, SNDCTL_TMR_SOURCE); 1138 _EXPORT_INT(m, SNDCTL_TMR_START); 1139 _EXPORT_INT(m, SNDCTL_TMR_STOP); 1140 _EXPORT_INT(m, SNDCTL_TMR_TEMPO); 1141 _EXPORT_INT(m, SNDCTL_TMR_TIMEBASE); 1142 }