modified version of pyalsaaudio module

This commit is contained in:
Julian Porter
2020-03-06 19:59:04 +00:00
parent be1b3e131d
commit a056a90c61
5 changed files with 245 additions and 5 deletions

View File

@@ -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: Version 0.8.5:
- Return an empty string/bytestring when 'read()' detects an - Return an empty string/bytestring when 'read()' detects an
overrun. Previously the returned data was undefined (contributed by @jcea) overrun. Previously the returned data was undefined (contributed by @jcea)

View File

@@ -29,6 +29,64 @@
#include <alsa/version.h> #include <alsa/version.h>
#include <stdio.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, PyDoc_STRVAR(alsaaudio_module_doc,
"This modules provides support for the ALSA audio API.\n" "This modules provides support for the ALSA audio API.\n"
"\n" "\n"
@@ -572,6 +630,169 @@ alsapcm_dumpinfo(alsapcm_t *self, PyObject *args)
return Py_None; 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(&params);
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(&params);
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(&params);
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(&params);
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 * static PyObject *
alsapcm_pcmtype(alsapcm_t *self, PyObject *args) alsapcm_pcmtype(alsapcm_t *self, PyObject *args)
{ {
@@ -1101,6 +1322,10 @@ static PyMethodDef alsapcm_methods[] = {
{"setperiodsize", (PyCFunction)alsapcm_setperiodsize, METH_VARARGS, {"setperiodsize", (PyCFunction)alsapcm_setperiodsize, METH_VARARGS,
setperiodsize_doc}, setperiodsize_doc},
{"dumpinfo", (PyCFunction)alsapcm_dumpinfo, METH_VARARGS}, {"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}, {"read", (PyCFunction)alsapcm_read, METH_VARARGS, read_doc},
{"write", (PyCFunction)alsapcm_write, METH_VARARGS, write_doc}, {"write", (PyCFunction)alsapcm_write, METH_VARARGS, write_doc},
{"pause", (PyCFunction)alsapcm_pause, METH_VARARGS, pause_doc}, {"pause", (PyCFunction)alsapcm_pause, METH_VARARGS, pause_doc},

View File

@@ -8,7 +8,7 @@ from setuptools import setup
from setuptools.extension import Extension from setuptools.extension import Extension
from sys import version from sys import version
pyalsa_version = '0.8.5' pyalsa_version = '0.8.6'
if __name__ == '__main__': if __name__ == '__main__':
setup( setup(

Binary file not shown.

View File

@@ -59,6 +59,7 @@ static const snd_pcm_format_t formats[] = {
}; };
static const unsigned int rates[] = { static const unsigned int rates[] = {
4000,
5512, 5512,
8000, 8000,
11025, 11025,
@@ -164,7 +165,7 @@ int main(int argc, char *argv[])
printf("Formats:"); printf("Formats:");
for (int i = 0; i < info.nFormats; ++i) { for (int i = 0; i < info.nFormats; ++i) {
printf(" %s", snd_pcm_format_name(formats[i])); printf("%s ", snd_pcm_format_name(info.formats[i]));
} }
putchar('\n'); putchar('\n');
printf("Rates:"); printf("Rates:");
@@ -178,7 +179,7 @@ int main(int argc, char *argv[])
printf(" %u", info.channels[i]); printf(" %u", info.channels[i]);
} }
putchar('\n'); putchar('\n');
/*
err = snd_pcm_open(&pcm, device_name, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK); err = snd_pcm_open(&pcm, device_name, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
if (err < 0) { if (err < 0) {
@@ -205,9 +206,11 @@ int main(int argc, char *argv[])
printf("Formats:"); printf("Formats:");
for (i = 0; i < ARRAY_SIZE(formats); ++i) { for (i = 0; i < ARRAY_SIZE(formats); ++i) {
if (!snd_pcm_hw_params_test_format(pcm, hw_params, formats[i])) if (!snd_pcm_hw_params_test_format(pcm, hw_params, formats[i])) {
printf(" %s", snd_pcm_format_name(formats[i])); printf(" %s", snd_pcm_format_name(formats[i]));
} }
}
putchar('\n'); putchar('\n');
err = snd_pcm_hw_params_get_channels_min(hw_params, &min); err = snd_pcm_hw_params_get_channels_min(hw_params, &min);
@@ -289,7 +292,7 @@ int main(int argc, char *argv[])
snd_pcm_close(pcm); snd_pcm_close(pcm);
*/
return 0; return 0;
} }