Commit d676906a authored by Greg Ward's avatar Greg Ward

Completely change the interface to setparameters():

  * it no longer takes ssize, which served no purpose apart from
    scolding you if you got it wrong
  * changed the order of the three remaining required arguments
    to (format, channels, rate) to match the order in which they
    must be set
  * replaced the optional argument 'emulate' with 'strict': if strict
    true, and the audio device does not accept the requested sampling
    parameters, raise OSSAudioError
  * return a tuple (format, channels, rate) reflecting the sampling
    parameters that were actually set

Change the canonical name of ossaudiodev.error to
ossaudiodev.OSSAudioError (keep an alias for backwards compatibility).

Remove 'audio_types' list and 'n_audio_types' (no longer needed now that
setparameters() no longer has an 'ssize' argument to police).
parent d691c42a
...@@ -58,29 +58,6 @@ typedef struct { ...@@ -58,29 +58,6 @@ typedef struct {
int fd; /* The open mixer device */ int fd; /* The open mixer device */
} oss_mixer_t; } oss_mixer_t;
/* XXX several format defined in soundcard.h are not supported,
including _NE (native endian) options and S32 options
*/
static struct {
int a_bps;
uint32_t a_fmt;
char *a_name;
} audio_types[] = {
{ 8, AFMT_MU_LAW, "logarithmic mu-law 8-bit audio" },
{ 8, AFMT_A_LAW, "logarithmic A-law 8-bit audio" },
{ 8, AFMT_U8, "linear unsigned 8-bit audio" },
{ 8, AFMT_S8, "linear signed 8-bit audio" },
{ 16, AFMT_U16_BE, "linear unsigned 16-bit big-endian audio" },
{ 16, AFMT_U16_LE, "linear unsigned 16-bit little-endian audio" },
{ 16, AFMT_S16_BE, "linear signed 16-bit big-endian audio" },
{ 16, AFMT_S16_LE, "linear signed 16-bit little-endian audio" },
#ifdef AFMT_S16_NE
{ 16, AFMT_S16_NE, "linear signed 16-bit native-endian audio" },
#endif
};
static int n_audio_types = sizeof(audio_types) / sizeof(audio_types[0]);
static PyTypeObject OSSAudioType; static PyTypeObject OSSAudioType;
static PyTypeObject OSSMixerType; static PyTypeObject OSSMixerType;
...@@ -228,6 +205,10 @@ oss_mixer_dealloc(oss_mixer_t *self) ...@@ -228,6 +205,10 @@ oss_mixer_dealloc(oss_mixer_t *self)
*/ */
/* ----------------------------------------------------------------------
* Helper functions
*/
/* _do_ioctl_1() is a private helper function used for the OSS ioctls -- /* _do_ioctl_1() is a private helper function used for the OSS ioctls --
SNDCTL_DSP_{SETFMT,CHANNELS,SPEED} -- that that are called from C SNDCTL_DSP_{SETFMT,CHANNELS,SPEED} -- that that are called from C
like this: like this:
...@@ -254,10 +235,6 @@ _do_ioctl_1(int fd, PyObject *args, char *fname, int cmd) ...@@ -254,10 +235,6 @@ _do_ioctl_1(int fd, PyObject *args, char *fname, int cmd)
} }
/* ----------------------------------------------------------------------
* Helper functions
*/
/* _do_ioctl_1_internal() is a wrapper for ioctls that take no inputs /* _do_ioctl_1_internal() is a wrapper for ioctls that take no inputs
but return an output -- ie. we need to pass a pointer to a local C but return an output -- ie. we need to pass a pointer to a local C
variable so the driver can write its output there, but from Python variable so the driver can write its output there, but from Python
...@@ -266,7 +243,6 @@ _do_ioctl_1(int fd, PyObject *args, char *fname, int cmd) ...@@ -266,7 +243,6 @@ _do_ioctl_1(int fd, PyObject *args, char *fname, int cmd)
devices, but does not use the value of the parameter passed-in in any devices, but does not use the value of the parameter passed-in in any
way. way.
*/ */
static PyObject * static PyObject *
_do_ioctl_1_internal(int fd, PyObject *args, char *fname, int cmd) _do_ioctl_1_internal(int fd, PyObject *args, char *fname, int cmd)
{ {
...@@ -511,66 +487,57 @@ oss_fileno(oss_audio_t *self, PyObject *args) ...@@ -511,66 +487,57 @@ oss_fileno(oss_audio_t *self, PyObject *args)
static PyObject * static PyObject *
oss_setparameters(oss_audio_t *self, PyObject *args) oss_setparameters(oss_audio_t *self, PyObject *args)
{ {
int rate, ssize, nchannels, n, fmt, emulate=0; int wanted_fmt, wanted_channels, wanted_rate, strict=0;
int fmt, channels, rate;
PyObject * rv; /* return tuple (fmt, channels, rate) */
if (!PyArg_ParseTuple(args, "iiii|i:setparameters", if (!PyArg_ParseTuple(args, "iii|i:setparameters",
&rate, &ssize, &nchannels, &fmt, &emulate)) &wanted_fmt, &wanted_channels, &wanted_rate,
return NULL; &strict))
if (rate < 0) {
PyErr_Format(PyExc_ValueError, "expected rate >= 0, not %d",
rate);
return NULL;
}
if (ssize < 0) {
PyErr_Format(PyExc_ValueError, "expected sample size >= 0, not %d",
ssize);
return NULL; return NULL;
fmt = wanted_fmt;
if (ioctl(self->fd, SNDCTL_DSP_SETFMT, &fmt) == -1) {
return PyErr_SetFromErrno(PyExc_IOError);
} }
if (nchannels != 1 && nchannels != 2) { if (strict && fmt != wanted_fmt) {
PyErr_Format(PyExc_ValueError, "nchannels must be 1 or 2, not %d", return PyErr_Format
nchannels); (OSSAudioError,
return NULL; "unable to set requested format (wanted %d, got %d)",
wanted_fmt, fmt);
} }
for (n = 0; n < n_audio_types; n++) channels = wanted_channels;
if (fmt == audio_types[n].a_fmt) if (ioctl(self->fd, SNDCTL_DSP_CHANNELS, &channels) == -1) {
break; return PyErr_SetFromErrno(PyExc_IOError);
if (n == n_audio_types) {
PyErr_Format(PyExc_ValueError, "unknown audio encoding: %d", fmt);
return NULL;
} }
if (audio_types[n].a_bps != ssize) { if (strict && channels != wanted_channels) {
PyErr_Format(PyExc_ValueError, return PyErr_Format
"for %s, expected sample size %d, not %d", (OSSAudioError,
audio_types[n].a_name, audio_types[n].a_bps, ssize); "unable to set requested channels (wanted %d, got %d)",
return NULL; wanted_channels, channels);
} }
if (emulate == 0) { rate = wanted_rate;
if ((self->afmts & audio_types[n].a_fmt) == 0) { if (ioctl(self->fd, SNDCTL_DSP_SPEED, &rate) == -1) {
PyErr_Format(PyExc_ValueError, return PyErr_SetFromErrno(PyExc_IOError);
"%s format not supported by device",
audio_types[n].a_name);
return NULL;
}
}
if (ioctl(self->fd, SNDCTL_DSP_SETFMT,
&audio_types[n].a_fmt) == -1) {
PyErr_SetFromErrno(PyExc_IOError);
return NULL;
} }
if (ioctl(self->fd, SNDCTL_DSP_CHANNELS, &nchannels) == -1) { if (strict && rate != wanted_rate) {
PyErr_SetFromErrno(PyExc_IOError); return PyErr_Format
return NULL; (OSSAudioError,
"unable to set requested rate (wanted %d, got %d)",
wanted_rate, rate);
} }
if (ioctl(self->fd, SNDCTL_DSP_SPEED, &rate) == -1) {
PyErr_SetFromErrno(PyExc_IOError); /* Construct the return value: a (fmt, channels, rate) tuple that
tells what the audio hardware was actually set to. */
rv = PyTuple_New(3);
if (rv == NULL)
return NULL; return NULL;
} PyTuple_SET_ITEM(rv, 0, PyInt_FromLong(fmt));
PyTuple_SET_ITEM(rv, 1, PyInt_FromLong(channels));
Py_INCREF(Py_None); PyTuple_SET_ITEM(rv, 2, PyInt_FromLong(rate));
return Py_None; return rv;
} }
static int static int
...@@ -969,9 +936,11 @@ initossaudiodev(void) ...@@ -969,9 +936,11 @@ initossaudiodev(void)
m = Py_InitModule("ossaudiodev", ossaudiodev_methods); m = Py_InitModule("ossaudiodev", ossaudiodev_methods);
OSSAudioError = PyErr_NewException("ossaudiodev.error", NULL, NULL); OSSAudioError = PyErr_NewException("ossaudiodev.OSSAudioError", NULL, NULL);
if (OSSAudioError) if (OSSAudioError) {
PyModule_AddObject(m, "error", OSSAudioError); PyModule_AddObject(m, "error", OSSAudioError);
PyModule_AddObject(m, "OSSAudioError", OSSAudioError);
}
/* Build 'control_labels' and 'control_names' lists and add them /* Build 'control_labels' and 'control_names' lists and add them
to the module. */ to the module. */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment