mirror of
https://github.com/larsimmisch/pyalsaaudio.git
synced 2026-05-23 06:52:34 +00:00
modified version of pyalsaaudio module
This commit is contained in:
12
py/CHANGES
12
py/CHANGES
@@ -1,3 +1,15 @@
|
||||
Version 0.8.6:
|
||||
- Added four methods to the 'PCM' class to allow users to get detailed information about the device:
|
||||
|
||||
- 'getformats()' returns a dictionary of name / value pairs, one for each of the card's
|
||||
supported formats - e.g. '{"U8": 1, "S16_LE": 2}',
|
||||
- 'getchannels()' returns a list of the supported channel numbers, e.g. '[1, 2]',
|
||||
- 'getrates()' returns supported sample rates for the device, e.g. '[48000]',
|
||||
- 'getratebounds()' returns the device's official minimum and maximum supported
|
||||
sample rates as a tuple, e.g. '(4000, 48000)'.
|
||||
|
||||
(contributed by @jdstmporter)
|
||||
|
||||
Version 0.8.5:
|
||||
- Return an empty string/bytestring when 'read()' detects an
|
||||
overrun. Previously the returned data was undefined (contributed by @jcea)
|
||||
|
||||
225
py/alsaaudio.c
225
py/alsaaudio.c
@@ -29,6 +29,64 @@
|
||||
#include <alsa/version.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof *(a))
|
||||
static const snd_pcm_format_t ALSAFormats[] = {
|
||||
SND_PCM_FORMAT_S8,
|
||||
SND_PCM_FORMAT_U8,
|
||||
SND_PCM_FORMAT_S16_LE,
|
||||
SND_PCM_FORMAT_S16_BE,
|
||||
SND_PCM_FORMAT_U16_LE,
|
||||
SND_PCM_FORMAT_U16_BE,
|
||||
SND_PCM_FORMAT_S24_LE,
|
||||
SND_PCM_FORMAT_S24_BE,
|
||||
SND_PCM_FORMAT_U24_LE,
|
||||
SND_PCM_FORMAT_U24_BE,
|
||||
SND_PCM_FORMAT_S32_LE,
|
||||
SND_PCM_FORMAT_S32_BE,
|
||||
SND_PCM_FORMAT_U32_LE,
|
||||
SND_PCM_FORMAT_U32_BE,
|
||||
SND_PCM_FORMAT_FLOAT_LE,
|
||||
SND_PCM_FORMAT_FLOAT_BE,
|
||||
SND_PCM_FORMAT_FLOAT64_LE,
|
||||
SND_PCM_FORMAT_FLOAT64_BE,
|
||||
SND_PCM_FORMAT_IEC958_SUBFRAME_LE,
|
||||
SND_PCM_FORMAT_IEC958_SUBFRAME_BE,
|
||||
SND_PCM_FORMAT_MU_LAW,
|
||||
SND_PCM_FORMAT_A_LAW,
|
||||
SND_PCM_FORMAT_IMA_ADPCM,
|
||||
SND_PCM_FORMAT_MPEG,
|
||||
SND_PCM_FORMAT_GSM,
|
||||
SND_PCM_FORMAT_SPECIAL,
|
||||
SND_PCM_FORMAT_S24_3LE,
|
||||
SND_PCM_FORMAT_S24_3BE,
|
||||
SND_PCM_FORMAT_U24_3LE,
|
||||
SND_PCM_FORMAT_U24_3BE,
|
||||
SND_PCM_FORMAT_S20_3LE,
|
||||
SND_PCM_FORMAT_S20_3BE,
|
||||
SND_PCM_FORMAT_U20_3LE,
|
||||
SND_PCM_FORMAT_U20_3BE,
|
||||
SND_PCM_FORMAT_S18_3LE,
|
||||
SND_PCM_FORMAT_S18_3BE,
|
||||
SND_PCM_FORMAT_U18_3LE,
|
||||
SND_PCM_FORMAT_U18_3BE
|
||||
};
|
||||
static const unsigned ALSARates[] = {
|
||||
4000,
|
||||
5512,
|
||||
8000,
|
||||
11025,
|
||||
16000,
|
||||
22050,
|
||||
32000,
|
||||
44100,
|
||||
48000,
|
||||
64000,
|
||||
88200,
|
||||
96000,
|
||||
176400,
|
||||
192000
|
||||
};
|
||||
|
||||
PyDoc_STRVAR(alsaaudio_module_doc,
|
||||
"This modules provides support for the ALSA audio API.\n"
|
||||
"\n"
|
||||
@@ -572,6 +630,169 @@ alsapcm_dumpinfo(alsapcm_t *self, PyObject *args)
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
// auxiliary function
|
||||
|
||||
|
||||
static PyObject *
|
||||
alsapcm_getformats(alsapcm_t *self, PyObject *args) {
|
||||
snd_pcm_t *pcm = self->handle;
|
||||
if (!pcm) {
|
||||
PyErr_SetString(ALSAAudioError, "PCM device is closed");
|
||||
return NULL;
|
||||
}
|
||||
snd_pcm_hw_params_t *params;
|
||||
snd_pcm_hw_params_alloca(¶ms);
|
||||
int err = snd_pcm_hw_params_any(pcm, params);
|
||||
if (err < 0) {
|
||||
PyErr_SetString(ALSAAudioError, "Cannot get hardware parameters");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PyObject *fmts = PyDict_New();
|
||||
for (int i = 0; i < ARRAY_SIZE(ALSAFormats); ++i) {
|
||||
snd_pcm_format_t format = ALSAFormats[i];
|
||||
if (!snd_pcm_hw_params_test_format(pcm, params, format)) {
|
||||
const char *name = snd_pcm_format_name(format);
|
||||
PyObject *pname=PyUnicode_FromString(name);
|
||||
PyObject *value=PyLong_FromLong((long)format);
|
||||
PyDict_SetItem(fmts,pname,value);
|
||||
}
|
||||
}
|
||||
return fmts;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(getformats_doc,
|
||||
"getformats() -> [str:int]\n\
|
||||
\n\
|
||||
Returns dictionary of supported format codes keyed by their standard ALSA names.");
|
||||
|
||||
static PyObject *
|
||||
alsapcm_getratemaxmin(alsapcm_t *self, PyObject *args) {
|
||||
snd_pcm_t *pcm = self->handle;
|
||||
if (!pcm) {
|
||||
PyErr_SetString(ALSAAudioError, "PCM device is closed");
|
||||
return NULL;
|
||||
}
|
||||
snd_pcm_hw_params_t *params;
|
||||
snd_pcm_hw_params_alloca(¶ms);
|
||||
int err = snd_pcm_hw_params_any(pcm, params);
|
||||
if (err < 0) {
|
||||
PyErr_SetString(ALSAAudioError, "Cannot get hardware parameters");
|
||||
return NULL;
|
||||
}
|
||||
unsigned min,max;
|
||||
if(snd_pcm_hw_params_get_rate_min(params, &min,NULL)<0) {
|
||||
PyErr_SetString(ALSAAudioError, "Cannot get minimum supported bitrate");
|
||||
return NULL;
|
||||
}
|
||||
if(snd_pcm_hw_params_get_rate_max(params, &max,NULL)<0) {
|
||||
PyErr_SetString(ALSAAudioError, "Cannot get maximum supported bitrate");
|
||||
return NULL;
|
||||
}
|
||||
PyObject *minp=PyLong_FromLong(min);
|
||||
PyObject *maxp=PyLong_FromLong(max);
|
||||
return PyTuple_Pack(2,minp,maxp);
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(getratebounds_doc,
|
||||
"getratebounds() -> (int,int)\n\
|
||||
\n\
|
||||
Returns the card's minimum and maximum supported sample rates as a tuple.");
|
||||
|
||||
static PyObject *
|
||||
alsapcm_getrates(alsapcm_t *self, PyObject *args) {
|
||||
snd_pcm_t *pcm = self->handle;
|
||||
if (!pcm) {
|
||||
PyErr_SetString(ALSAAudioError, "PCM device is closed");
|
||||
return NULL;
|
||||
}
|
||||
snd_pcm_hw_params_t *params;
|
||||
snd_pcm_hw_params_alloca(¶ms);
|
||||
int err = snd_pcm_hw_params_any(pcm, params);
|
||||
if (err < 0) {
|
||||
PyErr_SetString(ALSAAudioError, "Cannot get hardware parameters");
|
||||
return NULL;
|
||||
}
|
||||
unsigned min,max;
|
||||
if(snd_pcm_hw_params_get_rate_min(params, &min,NULL)<0) {
|
||||
PyErr_SetString(ALSAAudioError, "Cannot get minimum supported bitrate");
|
||||
return NULL;
|
||||
}
|
||||
if(snd_pcm_hw_params_get_rate_max(params, &max,NULL)<0) {
|
||||
PyErr_SetString(ALSAAudioError, "Cannot get maximum supported bitrate");
|
||||
return NULL;
|
||||
}
|
||||
if(min==max) {
|
||||
return PyLong_FromLong(min);
|
||||
}
|
||||
else if(!snd_pcm_hw_params_test_rate(pcm, params, min + 1, 0)) {
|
||||
PyObject *minp=PyLong_FromLong(min);
|
||||
PyObject *maxp=PyLong_FromLong(max);
|
||||
return PyTuple_Pack(2,minp,maxp);
|
||||
}
|
||||
else {
|
||||
PyObject *rates=PyList_New(0);
|
||||
for(int i=0;i<ARRAY_SIZE(ALSARates);i++) {
|
||||
unsigned rate=ALSARates[i];
|
||||
if(!snd_pcm_hw_params_test_rate(pcm, params, rate,0)) {
|
||||
PyObject *prate=PyLong_FromLong(rate);
|
||||
PyList_Append(rates,prate);
|
||||
}
|
||||
}
|
||||
return rates;
|
||||
}
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(getrates_doc,
|
||||
"getrates() -> obj\n\
|
||||
\n\
|
||||
Returns the sample rates supported by the device.\
|
||||
Returned value can be one of three types, depending on the card's properties.\
|
||||
There are three cases:\n\
|
||||
\n\
|
||||
- Card supports only a single rate: returns the rate\n\
|
||||
- Card supports a continuous range of rates: returns a tuple of the range's lower and upper bounds (inclusive)\n\
|
||||
- Card supports a collection of well-known rates: returns a list of the supported rates");
|
||||
|
||||
static PyObject *
|
||||
alsapcm_getchannels(alsapcm_t *self,PyObject *args) {
|
||||
snd_pcm_t *pcm = self->handle;
|
||||
if (!pcm) {
|
||||
PyErr_SetString(ALSAAudioError, "PCM device is closed");
|
||||
return NULL;
|
||||
}
|
||||
snd_pcm_hw_params_t *params;
|
||||
snd_pcm_hw_params_alloca(¶ms);
|
||||
int err = snd_pcm_hw_params_any(pcm, params);
|
||||
if (err < 0) {
|
||||
PyErr_SetString(ALSAAudioError, "Cannot get hardware parameters");
|
||||
return NULL;
|
||||
}
|
||||
unsigned min,max;
|
||||
if(snd_pcm_hw_params_get_channels_min(params, &min)<0) {
|
||||
PyErr_SetString(ALSAAudioError, "Cannot get minimum supported number of channels");
|
||||
return NULL;
|
||||
}
|
||||
if(snd_pcm_hw_params_get_channels_max(params, &max)<0) {
|
||||
PyErr_SetString(ALSAAudioError, "Cannot get maximum supported number of channels");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PyObject *out=PyList_New(0);
|
||||
|
||||
for(unsigned ch=min;ch<=max;++ch) {
|
||||
if (!snd_pcm_hw_params_test_channels(pcm, params, ch)) {
|
||||
PyObject *pch=PyLong_FromLong(ch);
|
||||
PyList_Append(out,pch);
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
PyDoc_STRVAR(getchannels_doc,
|
||||
"getchannels() -> [int]\n\
|
||||
\n\
|
||||
Returns list of supported channel numbers.");
|
||||
|
||||
static PyObject *
|
||||
alsapcm_pcmtype(alsapcm_t *self, PyObject *args)
|
||||
{
|
||||
@@ -1101,6 +1322,10 @@ static PyMethodDef alsapcm_methods[] = {
|
||||
{"setperiodsize", (PyCFunction)alsapcm_setperiodsize, METH_VARARGS,
|
||||
setperiodsize_doc},
|
||||
{"dumpinfo", (PyCFunction)alsapcm_dumpinfo, METH_VARARGS},
|
||||
{"getformats", (PyCFunction)alsapcm_getformats, METH_VARARGS, getformats_doc},
|
||||
{"getratebounds", (PyCFunction)alsapcm_getratemaxmin, METH_VARARGS, getratebounds_doc},
|
||||
{"getrates", (PyCFunction)alsapcm_getrates, METH_VARARGS, getrates_doc},
|
||||
{"getchannels", (PyCFunction)alsapcm_getchannels, METH_VARARGS, getchannels_doc},
|
||||
{"read", (PyCFunction)alsapcm_read, METH_VARARGS, read_doc},
|
||||
{"write", (PyCFunction)alsapcm_write, METH_VARARGS, write_doc},
|
||||
{"pause", (PyCFunction)alsapcm_pause, METH_VARARGS, pause_doc},
|
||||
|
||||
@@ -8,7 +8,7 @@ from setuptools import setup
|
||||
from setuptools.extension import Extension
|
||||
from sys import version
|
||||
|
||||
pyalsa_version = '0.8.5'
|
||||
pyalsa_version = '0.8.6'
|
||||
|
||||
if __name__ == '__main__':
|
||||
setup(
|
||||
|
||||
Reference in New Issue
Block a user