From df89c125814ff35798c4b2618a26dc6abf8f2c4e Mon Sep 17 00:00:00 2001
From: larsimmisch
Date: Wed, 21 May 2008 14:06:26 +0000
Subject: [PATCH] Decided that getenum should return the selected item and the
available items.
Argument parsing errors are reported with the methodname (minor
improvement).
Smallish documentation improvements.
git-svn-id: svn://svn.code.sf.net/p/pyalsaaudio/code/trunk@23 ec2f30ec-7544-0410-870e-f70ca00c83f0
---
CHANGES | 4 +
README | 4 +-
alsaaudio.c | 250 +++++++++++++++++++++++---------------
doc/about.html | 2 +-
doc/contents.html | 2 +-
doc/front.html | 17 +--
doc/index.html | 3 +-
doc/mixer-objects.html | 221 +++++++++++++++++++++------------
doc/module-alsaaudio.html | 27 ++--
doc/node3.html | 4 +-
doc/node4.html | 30 ++---
doc/node5.html | 19 ++-
doc/node7.html | 80 +++++++-----
doc/pcm-example.html | 7 +-
doc/pcm-objects.html | 201 ++++++++++++++++++------------
doc/pyalsaaudio.html | 3 +-
doc/src/libalsaaudio.tex | 61 +++++++---
doc/src/pyalsaaudio.tex | 2 +-
setup.py | 2 +-
19 files changed, 585 insertions(+), 354 deletions(-)
diff --git a/CHANGES b/CHANGES
index bd3f954..d528334 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,7 @@
+Version 0.4:
+- added mixer.getenum()
+- small documentation improvements
+
Version 0.3:
- wrapped blocking calls with Py_BEGIN_ALLOW_THREADS/Py_END_ALLOW_THREADS
- added pause
diff --git a/README b/README
index 179cb79..cb8dceb 100644
--- a/README
+++ b/README
@@ -1,7 +1,7 @@
PyAlsaAudio
===========
-Author: Casper Wilstrup (cwi@unispeed.dk)
+Author: Casper Wilstrup (cwi@aves.dk)
This package contains wrappers for accessing the ALSA api from Python. It
is currently fairly complete for PCM devices. My next goal is to have
@@ -52,4 +52,4 @@ stdin
'recordtest.py' which captures sound from the microphone at writes
it raw to stdout.
-'mixertest.py' which can be used to manipulate the mixers
+'mixertest.py' which can be used to manipulate the mixers.
diff --git a/alsaaudio.c b/alsaaudio.c
index 0313332..7eddf47 100644
--- a/alsaaudio.c
+++ b/alsaaudio.c
@@ -191,7 +191,7 @@ alsapcm_dumpinfo(alsapcm_t *self, PyObject *args) {
snd_pcm_hw_params_current(self->handle,hwparams);
- if (!PyArg_ParseTuple(args,"")) return NULL;
+ if (!PyArg_ParseTuple(args,":dumpinfo")) return NULL;
printf("PCM handle name = '%s'\n", snd_pcm_name(self->handle));
printf("PCM state = %s\n", snd_pcm_state_name(snd_pcm_state(self->handle)));
@@ -276,7 +276,7 @@ alsapcm_dumpinfo(alsapcm_t *self, PyObject *args) {
static PyObject *
alsapcm_pcmtype(alsapcm_t *self, PyObject *args) {
- if (!PyArg_ParseTuple(args,"")) return NULL;
+ if (!PyArg_ParseTuple(args,":pcmtype")) return NULL;
return PyInt_FromLong(self->pcmtype);
}
@@ -288,7 +288,7 @@ Returns either PCM_CAPTURE or PCM_PLAYBACK.");
static PyObject *
alsapcm_pcmmode(alsapcm_t *self, PyObject *args) {
- if (!PyArg_ParseTuple(args,"")) return NULL;
+ if (!PyArg_ParseTuple(args,"pcmmode")) return NULL;
return PyInt_FromLong(self->pcmmode);
}
@@ -303,7 +303,7 @@ Returns the mode of the PCM object. One of:\n\
static PyObject *
alsapcm_cardname(alsapcm_t *self, PyObject *args) {
- if (!PyArg_ParseTuple(args,"")) return NULL;
+ if (!PyArg_ParseTuple(args,":cardname")) return NULL;
return PyString_FromString(self->cardname);
}
@@ -317,7 +317,7 @@ static PyObject *
alsapcm_setchannels(alsapcm_t *self, PyObject *args) {
int channels;
int res;
- if (!PyArg_ParseTuple(args,"i",&channels)) return NULL;
+ if (!PyArg_ParseTuple(args,"i:setchannels",&channels)) return NULL;
self->channels = channels;
res = alsapcm_setup(self);
if (res < 0) {
@@ -340,7 +340,7 @@ static PyObject *
alsapcm_setrate(alsapcm_t *self, PyObject *args) {
int rate;
int res;
- if (!PyArg_ParseTuple(args,"i",&rate)) return NULL;
+ if (!PyArg_ParseTuple(args,"i:setrate",&rate)) return NULL;
self->rate = rate;
res = alsapcm_setup(self);
if (res < 0) {
@@ -361,7 +361,7 @@ static PyObject *
alsapcm_setformat(alsapcm_t *self, PyObject *args) {
int format;
int res;
- if (!PyArg_ParseTuple(args,"i",&format)) return NULL;
+ if (!PyArg_ParseTuple(args,"i:setformat",&format)) return NULL;
self->format = format;
res = alsapcm_setup(self);
if (res < 0) {
@@ -379,7 +379,7 @@ static PyObject *
alsapcm_setperiodsize(alsapcm_t *self, PyObject *args) {
int periodsize;
int res;
- if (!PyArg_ParseTuple(args,"i",&periodsize)) return NULL;
+ if (!PyArg_ParseTuple(args,"i:setperiodsize",&periodsize)) return NULL;
self->periodsize = periodsize;
res = alsapcm_setup(self);
if (res < 0) {
@@ -408,7 +408,7 @@ alsapcm_read(alsapcm_t *self, PyObject *args) {
return NULL;
}
- if (!PyArg_ParseTuple(args,"")) return NULL;
+ if (!PyArg_ParseTuple(args,":read")) return NULL;
if (self->pcmtype != SND_PCM_STREAM_CAPTURE) {
PyErr_SetString(ALSAAudioError,"Cannot read from playback PCM");
return NULL;
@@ -453,7 +453,7 @@ static PyObject *alsapcm_write(alsapcm_t *self, PyObject *args) {
char *data;
int datalen;
int res;
- if (!PyArg_ParseTuple(args,"s#",&data,&datalen)) return NULL;
+ if (!PyArg_ParseTuple(args,"s#:write",&data,&datalen)) return NULL;
if (datalen%self->framesize) {
PyErr_SetString(ALSAAudioError,
"Data size must be a multiple of framesize");
@@ -500,7 +500,7 @@ written at a later time.");
static PyObject *alsapcm_pause(alsapcm_t *self, PyObject *args) {
int enabled=1, res;
- if (!PyArg_ParseTuple(args,"|i",&enabled)) return NULL;
+ if (!PyArg_ParseTuple(args,"|i:pause",&enabled)) return NULL;
Py_BEGIN_ALLOW_THREADS
res = snd_pcm_pause(self->handle, enabled);
@@ -632,7 +632,7 @@ alsamixer_list(PyObject *self, PyObject *args) {
char *cardname = "default";
PyObject *result = PyList_New(0);
- if (!PyArg_ParseTuple(args,"|s",&cardname)) return NULL;
+ if (!PyArg_ParseTuple(args,"|s:mixers",&cardname)) return NULL;
snd_mixer_selem_id_alloca(&sid);
err = alsamixer_gethandle(cardname,&handle);
@@ -751,8 +751,9 @@ alsamixer_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
if (snd_mixer_selem_is_playback_mono(elem)) self->pchannels = 1;
else {
for (channel=0; channel <= SND_MIXER_SCHN_LAST; channel++) {
- if (snd_mixer_selem_has_playback_channel(elem, channel)) self->pchannels++;
- else break;
+ if (snd_mixer_selem_has_playback_channel(elem, channel))
+ self->pchannels++;
+ else break;
}
}
}
@@ -762,8 +763,9 @@ alsamixer_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
if (snd_mixer_selem_is_capture_mono(elem)) self->cchannels = 1;
else {
for (channel=0; channel <= SND_MIXER_SCHN_LAST; channel++) {
- if (snd_mixer_selem_has_capture_channel(elem, channel)) self->cchannels++;
- else break;
+ if (snd_mixer_selem_has_capture_channel(elem, channel))
+ self->cchannels++;
+ else break;
}
}
}
@@ -784,7 +786,7 @@ static void alsamixer_dealloc(alsamixer_t *self) {
static PyObject *
alsamixer_cardname(alsamixer_t *self, PyObject *args) {
- if (!PyArg_ParseTuple(args,"")) return NULL;
+ if (!PyArg_ParseTuple(args,":cardname")) return NULL;
return PyString_FromString(self->cardname);
}
@@ -796,7 +798,7 @@ Returns the name of the sound card used by this Mixer object.");
static PyObject *
alsamixer_mixer(alsamixer_t *self, PyObject *args) {
- if (!PyArg_ParseTuple(args,"")) return NULL;
+ if (!PyArg_ParseTuple(args,":mixer")) return NULL;
return PyString_FromString(self->controlname);
}
@@ -809,7 +811,7 @@ for example 'Master' or 'PCM'");
static PyObject *
alsamixer_mixerid(alsamixer_t *self, PyObject *args) {
- if (!PyArg_ParseTuple(args,"")) return NULL;
+ if (!PyArg_ParseTuple(args,":mixerid")) return NULL;
return PyInt_FromLong(self->controlid);
}
@@ -822,7 +824,7 @@ Returns the ID of the ALSA mixer controlled by this object.");
static PyObject *
alsamixer_volumecap(alsamixer_t *self, PyObject *args) {
PyObject *result;
- if (!PyArg_ParseTuple(args,"")) return NULL;
+ if (!PyArg_ParseTuple(args,":volumecap")) return NULL;
result = PyList_New(0);
if (self->volume_cap&MIXER_CAP_VOLUME)
PyList_Append(result,PyString_FromString("Volume"));
@@ -856,7 +858,7 @@ Possible values in this list are:\n\
static PyObject *
alsamixer_switchcap(alsamixer_t *self, PyObject *args) {
PyObject *result;
- if (!PyArg_ParseTuple(args,"")) return NULL;
+ if (!PyArg_ParseTuple(args,":switchcap")) return NULL;
result = PyList_New(0);
if (self->volume_cap&MIXER_CAP_SWITCH)
PyList_Append(result,PyString_FromString("Mute"));
@@ -920,7 +922,7 @@ alsamixer_getvolume(alsamixer_t *self, PyObject *args) {
char *dirstr = 0;
PyObject *result;
- if (!PyArg_ParseTuple(args,"|s",&dirstr)) return NULL;
+ if (!PyArg_ParseTuple(args,"|s:getvolume",&dirstr)) return NULL;
elem = alsamixer_find_elem(self->handle,self->controlname,self->controlid);
@@ -948,8 +950,8 @@ alsamixer_getvolume(alsamixer_t *self, PyObject *args) {
&& snd_mixer_selem_has_capture_volume(elem)) {
snd_mixer_selem_get_capture_volume(elem, channel, &ival);
PyList_Append(
- result,PyInt_FromLong(alsamixer_getpercentage(self->cmin,
- self->cmax, ival)));
+ result, PyInt_FromLong(alsamixer_getpercentage(self->cmin,
+ self->cmax, ival)));
}
}
return result;
@@ -972,9 +974,8 @@ alsamixer_getrange(alsamixer_t *self, PyObject *args) {
snd_mixer_elem_t *elem;
int direction;
char *dirstr = 0;
- PyObject *result;
- if (!PyArg_ParseTuple(args,"|s",&dirstr)) return NULL;
+ if (!PyArg_ParseTuple(args,"|s:getrange",&dirstr)) return NULL;
elem = alsamixer_find_elem(self->handle,self->controlname,self->controlid);
@@ -985,20 +986,31 @@ alsamixer_getrange(alsamixer_t *self, PyObject *args) {
else if (strcasecmp(dirstr,"playback")==0) direction = 0;
else if (strcasecmp(dirstr,"capture")==0) direction = 1;
else {
- PyErr_SetString(ALSAAudioError,"Invalid direction argument for direction");
+ PyErr_SetString(ALSAAudioError,"Invalid argument for direction");
return NULL;
}
- result = PyList_New(0);
- if (direction == 0 && snd_mixer_selem_has_playback_channel(elem, 0)) {
- PyList_Append(result,PyInt_FromLong(self->pmin));
- PyList_Append(result,PyInt_FromLong(self->pmax));
+ if (direction == 0) {
+ if (snd_mixer_selem_has_playback_channel(elem, 0)) {
+ return Py_BuildValue("[ii]", self->pmin, self->pmax);
}
- else if (direction == 1 && snd_mixer_selem_has_capture_channel(elem, 0)
- && snd_mixer_selem_has_capture_volume(elem)) {
- PyList_Append(result,PyInt_FromLong(self->cmin));
- PyList_Append(result,PyInt_FromLong(self->cmax));
+
+ PyErr_SetString(ALSAAudioError, "Mixer has no playback channel");
+ return NULL;
+ }
+ else if (direction == 1) {
+ if (snd_mixer_selem_has_capture_channel(elem, 0)
+ && snd_mixer_selem_has_capture_volume(elem)) {
+ return Py_BuildValue("[ii]", self->cmin, self->cmax);
}
- return result;
+
+ PyErr_SetString(ALSAAudioError, "Mixer has no capture channel "
+ "or capture volume");
+ return NULL;
+ }
+
+ // Unreached statement
+ PyErr_SetString(ALSAAudioError,"Huh?");
+ return NULL;
}
PyDoc_STRVAR(getrange_doc,
@@ -1015,40 +1027,73 @@ if the mixer has this capability, otherwise 'capture'");
static PyObject *
alsamixer_getenum(alsamixer_t *self, PyObject *args) {
snd_mixer_elem_t *elem;
+ PyObject *elems;
+ int i, count, rc;
unsigned int index;
char name[32];
- int res;
PyObject *result;
- if (!PyArg_ParseTuple(args,"")) return NULL;
+ if (!PyArg_ParseTuple(args, ":getenum")) return NULL;
elem = alsamixer_find_elem(self->handle,self->controlname,self->controlid);
if (!snd_mixer_selem_is_enumerated(elem)) {
- PyErr_SetString(ALSAAudioError,"Mixer is no enumerated control");
- return NULL;
- }
+ // Not an enumerated control, return an empty tuple
+ return PyTuple_New(0);
+ }
- res=snd_mixer_selem_get_enum_item(elem, 0, &index);
- if(res) {
- PyErr_SetString(ALSAAudioError, snd_strerror(res));
+ count = snd_mixer_selem_get_enum_items(elem);
+ if (count < 0) {
+ PyErr_SetString(ALSAAudioError, snd_strerror(count));
return NULL;
}
- res=snd_mixer_selem_get_enum_item_name(elem, index, sizeof(name)-1, name);
- if(res) {
- PyErr_SetString(ALSAAudioError, snd_strerror(res));
+
+ result = PyTuple_New(2);
+ if (!result)
+ return NULL;
+
+ rc = snd_mixer_selem_get_enum_item(elem, 0, &index);
+ if(rc) {
+ PyErr_SetString(ALSAAudioError, snd_strerror(rc));
return NULL;
- } else {
- result = PyList_New(0);
- PyList_Append(result,PyString_FromString(name));
}
+ rc = snd_mixer_selem_get_enum_item_name(elem, index, sizeof(name)-1, name);
+ if (rc) {
+ Py_DECREF(result);
+ PyErr_SetString(ALSAAudioError, snd_strerror(rc));
+ return NULL;
+ }
+
+ PyTuple_SetItem(result, 0, PyString_FromString(name));
+
+ elems = PyList_New(count);
+ if (!elems)
+ {
+ Py_DECREF(result);
+ return NULL;
+ }
+
+ for (i = 0; i < count; ++i) {
+ rc = snd_mixer_selem_get_enum_item_name(elem, i, sizeof(name)-1, name);
+ if (rc) {
+ Py_DECREF(elems);
+ Py_DECREF(result);
+ PyErr_SetString(ALSAAudioError, snd_strerror(rc));
+ return NULL;
+ }
+
+ PyList_SetItem(elems, i, PyString_FromString(name));
+ }
+
+ PyTuple_SetItem(result, 1, elems);
+
return result;
}
PyDoc_STRVAR(getenum_doc,
-"getenum([direction]) -> List of enumerated controls (string)\n\
+"getenum() -> Tuple of (string, list of strings)\n\
\n\
-Returns a list of strings with the enumerated controls.");
-
+Returns a a tuple. The first element is name of the active enumerated item, \n\
+the second a list available enumerated items.");
static PyObject *
alsamixer_getmute(alsamixer_t *self, PyObject *args) {
@@ -1056,7 +1101,7 @@ alsamixer_getmute(alsamixer_t *self, PyObject *args) {
int i;
int ival;
PyObject *result;
- if (!PyArg_ParseTuple(args,"")) return NULL;
+ if (!PyArg_ParseTuple(args,":getmute")) return NULL;
elem = alsamixer_find_elem(self->handle,self->controlname,self->controlid);
if (!snd_mixer_selem_has_playback_switch(elem)) {
@@ -1088,7 +1133,7 @@ alsamixer_getrec(alsamixer_t *self, PyObject *args) {
int i;
int ival;
PyObject *result;
- if (!PyArg_ParseTuple(args,"")) return NULL;
+ if (!PyArg_ParseTuple(args,":getrec")) return NULL;
elem = alsamixer_find_elem(self->handle,self->controlname,self->controlid);
if (!snd_mixer_selem_has_capture_switch(elem)) {
@@ -1124,7 +1169,9 @@ alsamixer_setvolume(alsamixer_t *self, PyObject *args) {
int channel = MIXER_CHANNEL_ALL;
int done = 0;
- if (!PyArg_ParseTuple(args,"l|is",&volume,&channel,&dirstr)) return NULL;
+ if (!PyArg_ParseTuple(args,"l|is:setvolume",&volume,&channel,&dirstr))
+ return NULL;
+
if (volume < 0 || volume > 100) {
PyErr_SetString(ALSAAudioError,"Volume must be between 0 and 100");
return NULL;
@@ -1146,16 +1193,16 @@ alsamixer_setvolume(alsamixer_t *self, PyObject *args) {
for (i = 0; i <= SND_MIXER_SCHN_LAST; i++) {
if (channel == -1 || channel == i) {
if (direction == 0 && snd_mixer_selem_has_playback_channel(elem, i)) {
- physvolume = alsamixer_getphysvolume(self->pmin,self->pmax,volume);
- snd_mixer_selem_set_playback_volume(elem, i, physvolume);
- done++;
+ physvolume = alsamixer_getphysvolume(self->pmin,self->pmax,volume);
+ snd_mixer_selem_set_playback_volume(elem, i, physvolume);
+ done++;
}
else if (direction == 1
&& snd_mixer_selem_has_capture_channel(elem, channel)
&& snd_mixer_selem_has_capture_volume(elem)) {
- physvolume = alsamixer_getphysvolume(self->cmin,self->cmax,volume);
- snd_mixer_selem_set_capture_volume(elem, i, physvolume);
- done++;
+ physvolume = alsamixer_getphysvolume(self->cmin,self->cmax,volume);
+ snd_mixer_selem_set_capture_volume(elem, i, physvolume);
+ done++;
}
}
}
@@ -1190,7 +1237,7 @@ alsamixer_setmute(alsamixer_t *self, PyObject *args) {
int mute = 0;
int done = 0;
int channel = MIXER_CHANNEL_ALL;
- if (!PyArg_ParseTuple(args,"i|i",&mute,&channel)) return NULL;
+ if (!PyArg_ParseTuple(args,"i|i:setmute",&mute,&channel)) return NULL;
elem = alsamixer_find_elem(self->handle,self->controlname,self->controlid);
if (!snd_mixer_selem_has_playback_switch(elem)) {
@@ -1200,8 +1247,8 @@ alsamixer_setmute(alsamixer_t *self, PyObject *args) {
for (i = 0; i <= SND_MIXER_SCHN_LAST; i++) {
if (channel == MIXER_CHANNEL_ALL || channel == i) {
if (snd_mixer_selem_has_playback_channel(elem, i)) {
- snd_mixer_selem_set_playback_switch(elem, i, !mute);
- done++;
+ snd_mixer_selem_set_playback_switch(elem, i, !mute);
+ done++;
}
}
}
@@ -1231,7 +1278,7 @@ alsamixer_setrec(alsamixer_t *self, PyObject *args) {
int rec = 0;
int done = 0;
int channel = MIXER_CHANNEL_ALL;
- if (!PyArg_ParseTuple(args,"i|i",&rec,&channel)) return NULL;
+ if (!PyArg_ParseTuple(args,"i|i:setrec",&rec,&channel)) return NULL;
elem = alsamixer_find_elem(self->handle,self->controlname,self->controlid);
if (!snd_mixer_selem_has_capture_switch(elem)) {
@@ -1369,39 +1416,52 @@ void initalsaaudio(void) {
}
- _EXPORT_INT(m,"PCM_PLAYBACK",SND_PCM_STREAM_PLAYBACK);
- _EXPORT_INT(m,"PCM_CAPTURE",SND_PCM_STREAM_CAPTURE);
+ _EXPORT_INT(m, "PCM_PLAYBACK",SND_PCM_STREAM_PLAYBACK);
+ _EXPORT_INT(m, "PCM_CAPTURE",SND_PCM_STREAM_CAPTURE);
- _EXPORT_INT(m,"PCM_NORMAL",0);
- _EXPORT_INT(m,"PCM_NONBLOCK",SND_PCM_NONBLOCK);
- _EXPORT_INT(m,"PCM_ASYNC",SND_PCM_ASYNC);
+ _EXPORT_INT(m, "PCM_NORMAL",0);
+ _EXPORT_INT(m, "PCM_NONBLOCK",SND_PCM_NONBLOCK);
+ _EXPORT_INT(m, "PCM_ASYNC",SND_PCM_ASYNC);
/* PCM Formats */
- _EXPORT_INT(m,"PCM_FORMAT_S8",SND_PCM_FORMAT_S8);
- _EXPORT_INT(m,"PCM_FORMAT_U8",SND_PCM_FORMAT_U8);
- _EXPORT_INT(m,"PCM_FORMAT_S16_LE",SND_PCM_FORMAT_S16_LE);
- _EXPORT_INT(m,"PCM_FORMAT_S16_BE",SND_PCM_FORMAT_S16_BE);
- _EXPORT_INT(m,"PCM_FORMAT_U16_LE",SND_PCM_FORMAT_U16_LE);
- _EXPORT_INT(m,"PCM_FORMAT_U16_BE",SND_PCM_FORMAT_U16_BE);
- _EXPORT_INT(m,"PCM_FORMAT_S24_LE",SND_PCM_FORMAT_S24_LE);
- _EXPORT_INT(m,"PCM_FORMAT_S24_BE",SND_PCM_FORMAT_S24_BE);
- _EXPORT_INT(m,"PCM_FORMAT_U24_LE",SND_PCM_FORMAT_U24_LE);
- _EXPORT_INT(m,"PCM_FORMAT_U24_BE",SND_PCM_FORMAT_U24_BE);
- _EXPORT_INT(m,"PCM_FORMAT_S32_LE",SND_PCM_FORMAT_S32_LE);
- _EXPORT_INT(m,"PCM_FORMAT_S32_BE",SND_PCM_FORMAT_S32_BE);
- _EXPORT_INT(m,"PCM_FORMAT_U32_LE",SND_PCM_FORMAT_U32_LE);
- _EXPORT_INT(m,"PCM_FORMAT_U32_BE",SND_PCM_FORMAT_U32_BE);
- _EXPORT_INT(m,"PCM_FORMAT_FLOAT_LE",SND_PCM_FORMAT_FLOAT_LE);
- _EXPORT_INT(m,"PCM_FORMAT_FLOAT_BE",SND_PCM_FORMAT_FLOAT_BE);
- _EXPORT_INT(m,"PCM_FORMAT_FLOAT64_LE",SND_PCM_FORMAT_FLOAT64_LE);
- _EXPORT_INT(m,"PCM_FORMAT_FLOAT64_BE",SND_PCM_FORMAT_FLOAT64_BE);
- _EXPORT_INT(m,"PCM_FORMAT_MU_LAW",SND_PCM_FORMAT_MU_LAW);
- _EXPORT_INT(m,"PCM_FORMAT_A_LAW",SND_PCM_FORMAT_A_LAW);
- _EXPORT_INT(m,"PCM_FORMAT_IMA_ADPCM",SND_PCM_FORMAT_IMA_ADPCM);
- _EXPORT_INT(m,"PCM_FORMAT_MPEG",SND_PCM_FORMAT_MPEG);
- _EXPORT_INT(m,"PCM_FORMAT_GSM",SND_PCM_FORMAT_GSM);
+ _EXPORT_INT(m, "PCM_FORMAT_S8",SND_PCM_FORMAT_S8);
+ _EXPORT_INT(m, "PCM_FORMAT_U8",SND_PCM_FORMAT_U8);
+ _EXPORT_INT(m, "PCM_FORMAT_S16_LE",SND_PCM_FORMAT_S16_LE);
+ _EXPORT_INT(m, "PCM_FORMAT_S16_BE",SND_PCM_FORMAT_S16_BE);
+ _EXPORT_INT(m, "PCM_FORMAT_U16_LE",SND_PCM_FORMAT_U16_LE);
+ _EXPORT_INT(m, "PCM_FORMAT_U16_BE",SND_PCM_FORMAT_U16_BE);
+ _EXPORT_INT(m, "PCM_FORMAT_S24_LE",SND_PCM_FORMAT_S24_LE);
+ _EXPORT_INT(m, "PCM_FORMAT_S24_BE",SND_PCM_FORMAT_S24_BE);
+ _EXPORT_INT(m, "PCM_FORMAT_U24_LE",SND_PCM_FORMAT_U24_LE);
+ _EXPORT_INT(m, "PCM_FORMAT_U24_BE",SND_PCM_FORMAT_U24_BE);
+ _EXPORT_INT(m, "PCM_FORMAT_S32_LE",SND_PCM_FORMAT_S32_LE);
+ _EXPORT_INT(m, "PCM_FORMAT_S32_BE",SND_PCM_FORMAT_S32_BE);
+ _EXPORT_INT(m, "PCM_FORMAT_U32_LE",SND_PCM_FORMAT_U32_LE);
+ _EXPORT_INT(m, "PCM_FORMAT_U32_BE",SND_PCM_FORMAT_U32_BE);
+ _EXPORT_INT(m, "PCM_FORMAT_FLOAT_LE",SND_PCM_FORMAT_FLOAT_LE);
+ _EXPORT_INT(m, "PCM_FORMAT_FLOAT_BE",SND_PCM_FORMAT_FLOAT_BE);
+ _EXPORT_INT(m, "PCM_FORMAT_FLOAT64_LE",SND_PCM_FORMAT_FLOAT64_LE);
+ _EXPORT_INT(m, "PCM_FORMAT_FLOAT64_BE",SND_PCM_FORMAT_FLOAT64_BE);
+ _EXPORT_INT(m, "PCM_FORMAT_MU_LAW",SND_PCM_FORMAT_MU_LAW);
+ _EXPORT_INT(m, "PCM_FORMAT_A_LAW",SND_PCM_FORMAT_A_LAW);
+ _EXPORT_INT(m, "PCM_FORMAT_IMA_ADPCM",SND_PCM_FORMAT_IMA_ADPCM);
+ _EXPORT_INT(m, "PCM_FORMAT_MPEG",SND_PCM_FORMAT_MPEG);
+ _EXPORT_INT(m, "PCM_FORMAT_GSM",SND_PCM_FORMAT_GSM);
/* Mixer stuff */
- _EXPORT_INT(m,"MIXER_CHANNEL_ALL",MIXER_CHANNEL_ALL);
+ _EXPORT_INT(m, "MIXER_CHANNEL_ALL", MIXER_CHANNEL_ALL);
+#if 0 // Omit for now - use case unknown
+ _EXPORT_INT(m, "MIXER_SCHN_UNKNOWN", SND_MIXER_SCHN_UNKNOWN);
+ _EXPORT_INT(m, "MIXER_SCHN_FRONT_LEFT", SND_MIXER_SCHN_FRONT_LEFT);
+ _EXPORT_INT(m, "MIXER_SCHN_FRONT_RIGHT", SND_MIXER_SCHN_FRONT_RIGHT);
+ _EXPORT_INT(m, "MIXER_SCHN_REAR_LEFT", SND_MIXER_SCHN_REAR_LEFT);
+ _EXPORT_INT(m, "MIXER_SCHN_REAR_RIGHT", SND_MIXER_SCHN_REAR_RIGHT);
+ _EXPORT_INT(m, "MIXER_SCHN_FRONT_CENTER", SND_MIXER_SCHN_FRONT_CENTER);
+ _EXPORT_INT(m, "MIXER_SCHN_WOOFER", SND_MIXER_SCHN_WOOFER);
+ _EXPORT_INT(m, "MIXER_SCHN_SIDE_LEFT", SND_MIXER_SCHN_SIDE_LEFT);
+ _EXPORT_INT(m, "MIXER_SCHN_SIDE_RIGHT", SND_MIXER_SCHN_SIDE_RIGHT);
+ _EXPORT_INT(m, "MIXER_SCHN_REAR_CENTER", SND_MIXER_SCHN_REAR_CENTER);
+ _EXPORT_INT(m, "MIXER_SCHN_MONO", SND_MIXER_SCHN_MONO);
+#endif
}
diff --git a/doc/about.html b/doc/about.html
index 494951a..cd7bf76 100644
--- a/doc/about.html
+++ b/doc/about.html
@@ -103,7 +103,7 @@ About this document ...
-Release 0.3.
+Release 0.4.
diff --git a/doc/contents.html b/doc/contents.html
index 389b3c5..5852aa3 100644
--- a/doc/contents.html
+++ b/doc/contents.html
@@ -99,7 +99,7 @@ Contents
-Release 0.3.
+Release 0.4.
diff --git a/doc/front.html b/doc/front.html
index c8e6f47..4941ef5 100644
--- a/doc/front.html
+++ b/doc/front.html
@@ -65,15 +65,16 @@ whatsoever.
Abstract:
-This package contains wrappers for accessing the ALSA API from Python. It
-is currently fairly complete for PCM devices and Mixer access. MIDI sequencer
-support is low on my priority list, but volunteers are welcome.
+This package contains wrappers for accessing the ALSA API from Python.
+It is currently fairly complete for PCM devices and Mixer access. MIDI
+sequencer support is low on my priority list, but volunteers are
+welcome.
-If you find bugs in the wrappers please use the SourceForge bug tracker. Please
-don't send bug reports regarding ALSA specifically. There are several
-bugs in this API, and those should be reported to the ALSA team - not
-me.
+If you find bugs in the wrappers please use the SourceForge bug
+tracker. Please don't send bug reports regarding ALSA specifically.
+There are several bugs in this API, and those should be reported to
+the ALSA team - not me.
@@ -112,7 +113,7 @@ me.
-Release 0.3.
+Release 0.4.
diff --git a/doc/index.html b/doc/index.html
index 947dcb8..7a4dcea 100644
--- a/doc/index.html
+++ b/doc/index.html
@@ -44,6 +44,7 @@
PyAlsaAudio
Casper Wilstrup
+
cwi@aves.dk
@@ -109,7 +110,7 @@
-Release 0.3.
+Release 0.4.
diff --git a/doc/mixer-objects.html b/doc/mixer-objects.html
index 6f3c144..3da7473 100644
--- a/doc/mixer-objects.html
+++ b/doc/mixer-objects.html
@@ -60,19 +60,23 @@ Mixer objects provides access to the ALSA mixer API.
- | class Mixer( |
- [control], [id], [cardname]) |
+ class Mixer( |
+ [control], [id],
+ [cardname]) |
-
-control - specifies which control to manipulate using this mixer object. The list
-of available controls can be found with the alsaaudio.mixers function.
-The default value is 'Master' - other common controls include 'Master Mono', 'PCM', 'Line', etc.
+ control - specifies which control to manipulate using this
+ mixer object. The list of available controls can be found with the
+ alsaaudio.mixers function. The default value is
+ 'Master' - other common controls include 'Master Mono', 'PCM',
+ 'Line', etc.
id - the id of the mixer control. Default is 0
-cardname - specifies which card should be used (this is only relevant
-if you have more than one sound card). Omit to use the default sound card
+cardname - specifies which card should be used (this is only
+ relevant if you have more than one sound card). Omit to use the
+ default sound card
@@ -80,36 +84,36 @@ Mixer objects have the following methods:
- | cardname( |
+ cardname( |
) |
-
-Return the name of the sound card used by this Mixer object
+ Return the name of the sound card used by this Mixer object
-
-Return the name of the specific mixer controlled by this object, For example 'Master'
-or 'PCM'
+ Return the name of the specific mixer controlled by this object, For
+ example 'Master' or 'PCM'
-
-Return the ID of the ALSA mixer controlled by this object.
+ Return the ID of the ALSA mixer controlled by this object.
- | switchcap( |
+ switchcap( |
) |
-
-Returns a list of the switches which are defined by this specific mixer. Possible values in
-this list are:
+ Returns a list of the switches which are defined by this specific
+ mixer. Possible values in this list are:
@@ -137,16 +141,17 @@ this list are:
-To manipulate these swithes use the setrec or setmute methods
+To manipulate these swithes use the setrec or
+setmute methods
- | volumecap( |
+ volumecap( |
) |
-
-Returns a list of the volume control capabilities of this mixer. Possible values in
-the list are:
+ Returns a list of the volume control capabilities of this mixer.
+ Possible values in the list are:
@@ -160,15 +165,18 @@ the list are:
| 'Volume' |
This mixer can control volume |
| 'Joined Volume' |
- This mixer can control volume for all channels at the same time |
+ This mixer can control volume for all channels at
+ the same time |
| 'Playback Volume' |
This mixer can manipulate the playback volume |
| 'Joined Playback Volume' |
- Manipulate playback volumne for all channels at the same time |
+ Manipulate playback volumne for all
+ channels at the same time |
| 'Capture Volume' |
Manipulate sound capture volume |
| 'Joined Capture Volume' |
- Manipulate sound capture volume for all channels at a time |
+ Manipulate sound capture volume for all
+ channels at a time |
@@ -176,34 +184,40 @@ the list are:
- | getrange( |
- [direction]) |
+ getenum( |
+ ) |
-
-Return the volume range of the ALSA mixer controlled by this object.
+ For enumerated controls, return the currently selected item and
+ the list of items available.
-The optional direction argument can be either 'playback' or 'capture',
-which is relevant if the mixer can control both playback and capture volume.
-The default value is 'playback' if the mixer has this capability, otherwise
-'capture'
+Returns a tuple (string, list of strings).
-
+For example, my soundcard has a Mixer called Mono Output Select.
+ Using amixer, I get:
-
- | getvolume( |
- [direction]) |
--
-Returns a list with the current volume settings for each channel. The list elements
-are integer percentages.
+
+$ amixer get "Mono Output Select"
+Simple mixer control 'Mono Output Select',0
+ Capabilities: enum
+ Items: 'Mix' 'Mic'
+ Item0: 'Mix'
+
-The optional direction argument can be either 'playback' or 'capture', which is relevant
-if the mixer can control both playback and capture volume. The default value is 'playback'
-if the mixer has this capability, otherwise 'capture'
+Using alsaaudio, one could do:
+
+>>> import alsaaudio
+>>> m = alsaaudio.Mixer('Mono Output Select')
+>>> m.getenum()
+('Mix', ['Mix', 'Mic'])
+
+This method will return an empty tuple if the mixer is not an
+ enumerated control.
@@ -211,52 +225,95 @@ if the mixer has this capability, otherwise 'capture'
getmute( |
) |
-
-Return a list indicating the current mute setting for each channel. 0 means not muted, 1 means muted.
+ Return a list indicating the current mute setting for each channel.
+ 0 means not muted, 1 means muted.
-This method will fail if the mixer has no playback switch capabilities.
+This method will fail if the mixer has no playback switch
+ capabilities.
- | getrec( |
+ getrange( |
+ [direction]) |
+-
+ Return the volume range of the ALSA mixer controlled by this object.
+
+
+The optional direction argument can be either 'playback' or
+ 'capture', which is relevant if the mixer can control both playback
+ and capture volume. The default value is 'playback' if the mixer
+ has this capability, otherwise 'capture'
+
+
+
+
+
+
-
-Return a list indicating the current record mute setting for each channel. 0 means not recording, 1
-means not recording.
+ Return a list indicating the current record mute setting for each
+ channel. 0 means not recording, 1 means recording.
-This method will fail if the mixer has no capture switch capabilities.
+This method will fail if the mixer has no capture switch
+ capabilities.
- | setvolume( |
- volume,[channel],[direction]) |
+ getvolume( |
+ [direction]) |
-
-Change the current volume settings for this mixer. The volume argument controls
-the new volume setting as an integer percentage.
+ Returns a list with the current volume settings for each channel.
+ The list elements are integer percentages.
-If the optional argument channel is present, the volume is set only for this channel. This
-assumes that the mixer can control the volume for the channels independently.
+The optional direction argument can be either 'playback' or
+ 'capture', which is relevant if the mixer can control both playback
+ and capture volume. The default value is 'playback' if the mixer has
+ this capability, otherwise 'capture'
-The optional direction argument can be either 'playback' or 'capture' is relevant if the mixer
-has independent playback and capture volume capabilities, and controls which of the volumes
-if changed. The default is 'playback' if the mixer has this capability, otherwise 'capture'.
- | setmute( |
+ setvolume( |
+ volume,[channel],
+ [direction]) |
+-
+
+
+Change the current volume settings for this mixer. The volume
+ argument controls the new volume setting as an integer percentage.
+
+
+If the optional argument channel is present, the volume is set
+ only for this channel. This assumes that the mixer can control the
+ volume for the channels independently.
+
+
+The optional direction argument can be either 'playback' or
+ 'capture' is relevant if the mixer has independent playback and
+ capture volume capabilities, and controls which of the volumes if
+ changed. The default is 'playback' if the mixer has this capability,
+ otherwise 'capture'.
+
+
+
+
+ | setmute( |
mute, [channel]) |
-
-Sets the mute flag to a new value. The mute argument is either 0 for not muted, or 1 for muted.
+ Sets the mute flag to a new value. The mute argument is either
+ 0 for not muted, or 1 for muted.
-The optional channel argument controls which channel is muted. The default is to set the mute flag
-for all channels.
+The optional channel argument controls which channel is muted.
+ The default is to set the mute flag for all channels.
This method will fail if the mixer has no playback mute capabilities
@@ -264,42 +321,48 @@ This method will fail if the mixer has no playback mute capabilities
- | setrec( |
+ setrec( |
capture,[channel]) |
-
-Sets the capture mute flag to a new value. The capture argument is either 0 for no capture,
-or 1 for capture.
+ Sets the capture mute flag to a new value. The capture
+ argument is either 0 for no capture, or 1 for capture.
-The optional channel argument controls which channel is changed. The default is to set the capture flag
-for all channels.
+The optional channel argument controls which channel is
+ changed. The default is to set the capture flag for all channels.
-This method will fail if the mixer has no capture switch capabilities
+This method will fail if the mixer has no capture switch
+ capabilities.
A Note on the ALSA Mixer API
-The ALSA mixer API is extremely complicated - and hardly documented at all. alsaaudio implements
-a much simplified way to access this API. In designing the API I've had to make some choices which
-may limit what can and cannot be controlled through the API. However, If I had chosen to implement the
-full API, I would have reexposed the horrible complexity/documentation ratio of the underlying API.
-At least the alsaaudio API is easy to understand and use.
+The ALSA mixer API is extremely complicated - and hardly documented at
+all. alsaaudio implements a much simplified way to access
+this API. In designing the API I've had to make some choices which may
+limit what can and cannot be controlled through the API. However, If I
+had chosen to implement the full API, I would have reexposed the
+horrible complexity/documentation ratio of the underlying API. At
+least the alsaaudio API is easy to understand and use.
-If my design choises prevents you from doing something that the underlying API would have allowed,
-please let me know, so I can incorporate these need into future versions.
+If my design choises prevents you from doing something that the
+underlying API would have allowed, please let me know, so I can
+incorporate these need into future versions.
-If the current state of affairs annoy you, the best you can do is to write a HOWTO on the API and
-make this available on the net. Until somebody does this, the availability of ALSA mixer capable
-devices will stay quite limited.
+If the current state of affairs annoy you, the best you can do is to
+write a HOWTO on the API and make this available on the net. Until
+somebody does this, the availability of ALSA mixer capable devices
+will stay quite limited.
-Unfortunately, I'm not able to create such a HOWTO myself, since I only understand half of the API,
-and that which I do understand has come from a painful trial and error process.
+Unfortunately, I'm not able to create such a HOWTO myself, since I
+only understand half of the API, and that which I do understand has
+come from a painful trial and error process.
@@ -336,7 +399,7 @@ and that which I do understand has come from a painful trial and error process.
-Release 0.3.
+Release 0.4.
diff --git a/doc/module-alsaaudio.html b/doc/module-alsaaudio.html
index 849d2e6..e96d838 100644
--- a/doc/module-alsaaudio.html
+++ b/doc/module-alsaaudio.html
@@ -60,8 +60,7 @@
class="platform">Linux.
-tex2html_comment_mark>15
-
+
@@ -83,12 +82,14 @@ sound card). Omit to use the default sound card.
class PCM( |
[type], [mode], [cardname]) |
-This class is used to represent a PCM device (both playback and capture devices).
-The arguments are:
-
type - can be either PCM_CAPTURE or PCM_PLAYBACK (default).
-
mode - can be either PCM_NONBLOCK, PCM_ASYNC, or PCM_NORMAL (the default).
-
cardname - specifies which card should be used (this is only relevant
-if you have more than one sound card). Omit to use the default sound card
+ This class is used to represent a PCM device (both playback and
+ capture devices).
+ The arguments are:
+
type - can be either PCM_CAPTURE or PCM_PLAYBACK (default).
+
mode - can be either PCM_NONBLOCK, PCM_ASYNC, or PCM_NORMAL (the default).
+
cardname - specifies which card should be used (this is only
+ relevant if you have more than one sound card). Omit to use the
+ default sound card
@@ -99,7 +100,7 @@ if you have more than one sound card). Omit to use the default sound card
This class is used to access a specific ALSA mixer.
The arguments are:
control - Name of the chosen mixed (default is Master).
-
id - id of mixer (default is 0) - More explaniation needed here
+
id - id of mixer (default is 0) - More explanation needed here
cardname specifies which card should be used (this is only relevant
if you have more than one sound card). Omit to use the default sound card
@@ -107,9 +108,9 @@ if you have more than one sound card). Omit to use the default sound card
- exception ALSAAudioError
-
-Exception raised when an operation fails for a ALSA specific reason.
-The exception argument is a string describing the reason of the
-failure.
+ Exception raised when an operation fails for a ALSA specific reason.
+ The exception argument is a string describing the reason of the
+ failure.
@@ -161,7 +162,7 @@ failure.
-Release 0.3.
+Release 0.4.
diff --git a/doc/node3.html b/doc/node3.html
index dbe208d..22c3c01 100644
--- a/doc/node3.html
+++ b/doc/node3.html
@@ -55,7 +55,7 @@
The Advanced Linux Sound Architecture (ALSA) provides audio and MIDI
-functionality to the Linux operating system.
+functionality to the Linux operating system.
Logically ALSA consists of these components:
@@ -113,7 +113,7 @@ More information about ALSA may be found on the project homepage
-Release 0.3.
+Release 0.4.
diff --git a/doc/node4.html b/doc/node4.html
index 05473ca..178e031 100644
--- a/doc/node4.html
+++ b/doc/node4.html
@@ -54,27 +54,29 @@
-The older Linux sound API (OSS) which is now deprecated is well supported
-from the standard Python library, through the ossaudiodev module. No native
-ALSA support exists in the standard library (yet).
+The older Linux sound API (OSS) which is now deprecated is well
+supported from the standard Python library, through the ossaudiodev
+module. No native ALSA support exists in the standard library (yet).
-There are a few other ``ALSA for Python'' projects available, including at
-least two different projects called pyAlsa. Neither of these seem to be under
-active development at the time - and neither are very feature complete.
+There are a few other ``ALSA for Python'' projects available,
+including at least two different projects called pyAlsa. Neither of
+these seem to be under active development at the time - and neither
+are very feature complete.
-I wrote PyAlsaAudio to fill this gap. My long term goal is to have the module
-included in the standard Python library, but that is probably a while of yet.
+I wrote PyAlsaAudio to fill this gap. My long term goal is to have the
+module included in the standard Python library, but that is probably a
+while off yet.
-PyAlsaAudio hass full support for sound capture, playback of sound, as well as
-the ALSA Mixer API.
+PyAlsaAudio hass full support for sound capture, playback of sound, as
+well as the ALSA Mixer API.
-MIDI support is not available, and since I don't own any MIDI hardware, it's
-difficult for me to implement it. Volunteers to work on this would be greatly
-appreciated
+MIDI support is not available, and since I don't own any MIDI
+hardware, it's difficult for me to implement it. Volunteers to work on
+this would be greatly appreciated
@@ -109,7 +111,7 @@ appreciated
-Release 0.3.
+Release 0.4.
diff --git a/doc/node5.html b/doc/node5.html
index 1bd779c..49507bb 100644
--- a/doc/node5.html
+++ b/doc/node5.html
@@ -55,11 +55,18 @@
Note: the wrappers link with the alsasound library (from the alsa-lib
-package). Verify that this is installed by looking for /usr/lib/libasound.so
-before building. Naturally you also need to use a kernel with proper ALSA
-support. This is the default in Linux kernel 2.6 and later. If you are using
-kernel version 2.4 you may need to install the ALSA patches yourself - although
-most distributions ship with ALSA kernels.
+package) and need the ALSA headers for compilation. Verify that you
+have /usr/lib/libasound.so and /usr/include/alsa (or
+similar paths) before building.
+
+
+On Debian (and probably Ubuntu), make sure you have libasound2-dev installed.
+
+
+Naturally you also need to use a kernel with proper ALSA support. This
+is the default in Linux kernel 2.6 and later. If you are using kernel
+version 2.4 you may need to install the ALSA patches yourself -
+although most distributions ship with ALSA kernels.
To install, execute the following:
@@ -108,7 +115,7 @@ And then as root:
-Release 0.3.
+Release 0.4.
diff --git a/doc/node7.html b/doc/node7.html
index 2ce84d6..0dc008a 100644
--- a/doc/node7.html
+++ b/doc/node7.html
@@ -60,72 +60,86 @@ terminology.
- Sample
-- PCM audio, whether it is input or output, consists at the lowest level
-of a number of single samples. A sample represents the sound in a single channel in
-a brief interval. If more than one channel is in use, more than one sample is required
-for each interval to describe the sound. Samples can be of many different sizes, ranging
-from 8 bit to 64 bit presition. The specific format of each sample can also vary - they
-can be big endian byte order, little endian byte order, or even floats.
+
- PCM audio, whether it is input or output, consists at
+ the lowest level of a number of single samples. A sample represents
+ the sound in a single channel in a brief interval. If more than one
+ channel is in use, more than one sample is required for each
+ interval to describe the sound. Samples can be of many different
+ sizes, ranging from 8 bit to 64 bit presition. The specific format
+ of each sample can also vary - they can be big endian byte order,
+ little endian byte order, or even floats.
- Frame
-- A frame consists of exactly one sample per channel. If there is only one
-channel (Mono sound) a frame is simply a single sample. If the sound is stereo, each frame
-consists of two samples, etc.
+
- A frame consists of exactly one sample per channel. If
+ there is only one channel (Mono sound) a frame is simply a single
+ sample. If the sound is stereo, each frame consists of two samples,
+ etc.
- Frame size
-- This is the size in bytes of each frame. This can vary a lot: if each sample is
-8 bits, and we're handling mono sound, the frame size is one byte. Similarly in 6 channel audio with
-64 bit floating point samples, the frame size is 48 bytes
+
- This is the size in bytes of each frame. This can
+ vary a lot: if each sample is 8 bits, and we're handling mono sound,
+ the frame size is one byte. Similarly in 6 channel audio with 64 bit
+ floating point samples, the frame size is 48 bytes
- Rate
-- PCM sound consists of a flow of sound frames. The sound rate controls how often
-the current frame is replaced. For example, a rate of 8000 Hz means that a new frame is played
-or captured 8000 times per second.
+
- PCM sound consists of a flow of sound frames. The sound
+ rate controls how often the current frame is replaced. For example,
+ a rate of 8000 Hz means that a new frame is played or captured 8000
+ times per second.
- Data rate
-- This is the number of bytes, which must be recorded or provided per second
-at a certain frame size and rate.
+
- This is the number of bytes, which must be recorded
+ or provided per second at a certain frame size and rate.
-8000 Hz mono sound with 8 bit (1 byte) samples has a data rate of 8000 * 1 * 1 = 8 kb/s
+8000 Hz mono sound with 8 bit (1 byte) samples has a data rate of
+ 8000 * 1 * 1 = 8 kb/s
-At the other end of the scale, 96000 Hz, 6 channel sound with 64 bit (8 bytes) samples
-has a data rate of 96000 * 6 * 8 = 4608 kb/s (almost 5 Mb sound data per second)
+At the other end of the scale, 96000 Hz, 6 channel sound with 64 bit
+ (8 bytes) samples has a data rate of 96000 * 6 * 8 = 4608 kb/s
+ (almost 5 Mb sound data per second)
- Period
-- When the hardware processes data this is done in chunks of frames. The time interval
-between each processing (A/D or D/A conversion) is known as the period. The size of the period has
-direct implication on the latency of the sound input or output. For low-latency the period size should
-be very small, while low CPU resource usage would usually demand larger period sizes. With ALSA, the
-CPU utilization is not impacted much by the period size, since the kernel layer buffers multiple
-periods internally, so each period generates an interrupt and a memory copy, but userspace can be
-slower and read or write multiple periods at the same time.
+
- When the hardware processes data this is done in chunks
+ of frames. The time interval between each processing (A/D or D/A
+ conversion) is known as the period. The size of the period has
+ direct implication on the latency of the sound input or output. For
+ low-latency the period size should be very small, while low CPU
+ resource usage would usually demand larger period sizes. With ALSA,
+ the CPU utilization is not impacted much by the period size, since
+ the kernel layer buffers multiple periods internally, so each period
+ generates an interrupt and a memory copy, but userspace can be
+ slower and read or write multiple periods at the same time.
- Period size
-- This is the size of each period in Hz. Not bytes, but Hz!. In alsaaudio
-the period size is set directly, and it is therefore important to understand the significance of this
-number. If the period size is configured to for example 32, each write should contain exactly 32 frames
-of sound data, and each read will return either 32 frames of data or nothing at all.
+
- This is the size of each period in Hz. Not
+ bytes, but Hz!. In alsaaudio the period size is set
+ directly, and it is therefore important to understand the
+ significance of this number. If the period size is configured to for
+ example 32, each write should contain exactly 32 frames of sound
+ data, and each read will return either 32 frames of data or nothing
+ at all.
-Once you understand these concepts, you will be ready to actually utilize PCM API. Read on.
+Once you understand these concepts, you will be ready to use the PCM
+API. Read on.
@@ -162,7 +176,7 @@ Once you understand these concepts, you will be ready to actually utilize PCM AP
-Release 0.3.
+Release 0.4.
diff --git a/doc/pcm-example.html b/doc/pcm-example.html
index a16d62e..917f370 100644
--- a/doc/pcm-example.html
+++ b/doc/pcm-example.html
@@ -54,8 +54,9 @@
-For now, the only examples available are the 'playbacktest.py' and the 'recordtest.py' programs included.
-This will change in a future version.
+For now, the only examples available are the 'playbacktest.py' and the
+'recordtest.py' programs included. This will change in a future
+version.
@@ -92,7 +93,7 @@ This will change in a future version.
-Release 0.3.
+Release 0.4.
diff --git a/doc/pcm-objects.html b/doc/pcm-objects.html
index 65737a1..bd53687 100644
--- a/doc/pcm-objects.html
+++ b/doc/pcm-objects.html
@@ -56,13 +56,15 @@
-The acronym PCM is short for Pulse Code Modulation and is the method used in ALSA
-and many other places to handle playback and capture of sampled sound data.
+The acronym PCM is short for Pulse Code Modulation and is the method
+used in ALSA and many other places to handle playback and capture of
+sampled sound data.
-PCM objects in alsaaudio are used to do exactly that, either play sample based
-sound or capture sound from some input source (perhaps a microphone). The PCM object
-constructor takes the following arguments:
+PCM objects in alsaaudio are used to do exactly that, either
+play sample based sound or capture sound from some input source
+(probably a microphone). The PCM object constructor takes the following
+arguments:
@@ -74,18 +76,21 @@ constructor takes the following arguments:
type - can be either PCM_CAPTURE or PCM_PLAYBACK (default).
-mode - can be either PCM_NONBLOCK, PCM_ASYNC, or PCM_NORMAL (the default).
-In PCM_NONBLOCK mode, calls to read will return immediately independent of wether
-there is any actual data to read. Similarly, write calls will return immediately
-without actually writing anything to the playout buffer if the buffer is full.
+mode - can be either PCM_NONBLOCK, PCM_ASYNC, or PCM_NORMAL (the
+default). In PCM_NONBLOCK mode, calls to read will return immediately
+independent of wether there is any actual data to read. Similarly,
+write calls will return immediately without actually writing anything
+to the playout buffer if the buffer is full.
-In the current version of alsaaudio PCM_ASYNC is useless, since it relies
-on a callback procedure, which can't be specified from Python.
+In the current version of alsaaudio PCM_ASYNC is useless,
+since it relies on a callback procedure, which can't be specified through
+this API yet.
-cardname - specifies which card should be used (this is only relevant
-if you have more than one sound card). Omit to use the default sound card
+cardname - specifies which card should be used (this is only
+relevant if you have more than one sound card). Omit to use the
+default sound card
This will construct a PCM object with default settings:
@@ -108,7 +113,7 @@ PCM objects have the following methods:
pcmtype( |
) |
-
-Returns the type of PCM object. Either PCM_CAPTURE or PCM_PLAYBACK.
+ Returns the type of PCM object. Either PCM_CAPTURE or PCM_PLAYBACK.
@@ -116,7 +121,8 @@ Returns the type of PCM object. Either PCM_CAPTURE or PCM_PLAYBACK.
pcmmode( |
) |
-Return the mode of the PCM object. One of PCM_NONBLOCK, PCM_ASYNC, or PCM_NORMAL
+ Return the mode of the PCM object. One of PCM_NONBLOCK, PCM_ASYNC,
+ or PCM_NORMAL
@@ -124,7 +130,7 @@ Return the mode of the PCM object. One of PCM_NONBLOCK, PCM_ASYNC, or PCM_NORMAL
cardname( |
) |
-Return the name of the sound card used by this PCM object.
+ Return the name of the sound card used by this PCM object.
@@ -132,8 +138,9 @@ Return the name of the sound card used by this PCM object.
setchannels( |
nchannels) |
-Used to set the number of capture or playback channels. Common values are: 1 = mono, 2 = stereo,
-and 6 = full 6 channel audio. Few sound cards support more than 2 channels
+ Used to set the number of capture or playback channels. Common
+ values are: 1 = mono, 2 = stereo, and 6 = full 6 channel audio. Few
+ sound cards support more than 2 channels
@@ -141,17 +148,18 @@ and 6 = full 6 channel audio. Few sound cards support more than 2 channels
setrate( |
rate) |
-Set the sample rate in Hz for the device. Typical values are 8000 (poor sound), 16000, 44100 (cd quality),
-and 96000
+ Set the sample rate in Hz for the device. Typical values are 8000
+ (poor sound), 16000, 44100 (cd quality), and 96000
+ | format) |
-
-The sound format of the device. Sound format controls how the PCM device interpret data for playback,
-and how data is encoded in captures.
+ The sound format of the device. Sound format controls how the PCM
+ device interpret data for playback, and how data is encoded in
+ captures.
The following formats are provided by ALSA:
@@ -168,47 +176,66 @@ The following formats are provided by ALSA:
| PCM_FORMAT_U8 |
Signed 8 bit samples for each channel |
| PCM_FORMAT_S16_LE |
- Signed 16 bit samples for each channel (Little Endian byte order) |
+ Signed 16 bit samples for each channel
+ (Little Endian byte order) |
| PCM_FORMAT_S16_BE |
- Signed 16 bit samples for each channel (Big Endian byte order) |
+ Signed 16
+ bit samples for each channel (Big Endian byte order) |
| PCM_FORMAT_U16_LE |
- Unsigned 16 bit samples for each channel (Little Endian byte order) |
+ Unsigned 16 bit samples for each channel
+ (Little Endian byte order) |
| PCM_FORMAT_U16_BE |
- Unsigned 16 bit samples for each channel (Big Endian byte order) |
+ Unsigned 16
+ bit samples for each channel (Big Endian byte order) |
| PCM_FORMAT_S24_LE |
- Signed 24 bit samples for each channel (Little Endian byte order) |
+ Signed 24 bit samples for each channel
+ (Little Endian byte order) |
| PCM_FORMAT_S24_BE |
- Signed 24 bit samples for each channel (Big Endian byte order) |
+ Signed 24
+ bit samples for each channel (Big Endian byte order) |
| PCM_FORMAT_U24_LE |
- Unsigned 24 bit samples for each channel (Little Endian byte order) |
+ Unsigned 24 bit samples for each channel
+ (Little Endian byte order) |
| PCM_FORMAT_U24_BE |
- Unsigned 24 bit samples for each channel (Big Endian byte order) |
+ Unsigned 24
+ bit samples for each channel (Big Endian byte order) |
| PCM_FORMAT_S32_LE |
- Signed 32 bit samples for each channel (Little Endian byte order) |
+ Signed 32 bit samples for each channel
+ (Little Endian byte order) |
| PCM_FORMAT_S32_BE |
- Signed 32 bit samples for each channel (Big Endian byte order) |
+ Signed 32
+ bit samples for each channel (Big Endian byte order) |
| PCM_FORMAT_U32_LE |
- Unsigned 32 bit samples for each channel (Little Endian byte order) |
+ Unsigned 32 bit samples for each channel
+ (Little Endian byte order) |
| PCM_FORMAT_U32_BE |
- Unsigned 32 bit samples for each channel (Big Endian byte order) |
+ Unsigned 32
+ bit samples for each channel (Big Endian byte order) |
| PCM_FORMAT_FLOAT_LE |
- 32 bit samples encoded as float. (Little Endian byte order) |
+ 32 bit samples encoded as float.
+ (Little Endian byte order) |
| PCM_FORMAT_FLOAT_BE |
- 32 bit samples encoded as float (Big Endian byte order) |
+ 32 bit
+ samples encoded as float (Big Endian byte order) |
| PCM_FORMAT_FLOAT64_LE |
- 64 bit samples encoded as float. (Little Endian byte order) |
+ 64 bit samples encoded as float.
+ (Little Endian byte order) |
| PCM_FORMAT_FLOAT64_BE |
- 64 bit samples encoded as float. (Big Endian byte order) |
+ 64 bit
+ samples encoded as float. (Big Endian byte order) |
| PCM_FORMAT_MU_LAW |
- A logarithmic encoding (used by Sun .au files) |
+ A logarithmic encoding (used by Sun .au
+ files) |
| PCM_FORMAT_A_LAW |
Another logarithmic encoding |
| PCM_FORMAT_IMA_ADPCM |
- a 4:1 compressed format defined by the Interactive Multimedia Association |
+ a 4:1 compressed format defined by the
+ Interactive Multimedia Association |
| PCM_FORMAT_MPEG |
- MPEG encoded audio? |
+ MPEG
+ encoded audio? |
| PCM_FORMAT_GSM |
- 9600 constant rate encoding well suitet for speech |
+ 9600 bits/s constant rate encoding for speech |
@@ -219,9 +246,10 @@ The following formats are provided by ALSA:
setperiodsize( |
period) |
-
-Sets the actual period size in frames. Each write should consist of exactly this number of frames, and
-each read will return this number of frames (unless the device is in PCM_NONBLOCK mode, in which case
-it may return nothing at all)
+ Sets the actual period size in frames. Each write should consist of
+ exactly this number of frames, and each read will return this number
+ of frames (unless the device is in PCM_NONBLOCK mode, in which case
+ it may return nothing at all)
@@ -229,14 +257,16 @@ it may return nothing at all)
read( |
) |
-In PCM_NORMAL mode, this function blocks until a full period is available, and then returns a
-tuple (length,data) where length is the size in bytes of the captured data, and data
-is the captured sound frames as a string. The length of the returned data will be periodsize*framesize
-bytes.
+ In PCM_NORMAL mode, this function blocks until a full period is
+ available, and then returns a tuple (length,data) where
+ length is the number of frames of captured data, and
+ data is the captured sound frames as a string. The length of
+ the returned data will be periodsize*framesize bytes.
-In PCM_NONBLOCK mode, the call will not block, but will return (0,'') if no new period
-has become available since the last call to read.
+In PCM_NONBLOCK mode, the call will not block, but will return
+ (0,'') if no new period has become available since the last
+ call to read.
@@ -244,50 +274,67 @@ has become available since the last call to read.
write( |
data) |
-Writes (plays) the sound in data. The length of data must be a multiple of the frame size, and
-should be exactly the size of a period. If less than 'period size' frames are provided, the actual
-playout will not happen until more data is written.
+ Writes (plays) the sound in data. The length of data must be
+ a multiple of the frame size, and should be exactly the size
+ of a period. If less than 'period size' frames are provided, the
+ actual playout will not happen until more data is written.
-If the device is not in PCM_NONBLOCK mode, this call will block if the kernel buffer is full, and
-until enough sound has been played to allow the sound data to be buffered. The call always returns
-the size of the data provided
+If the device is not in PCM_NONBLOCK mode, this call will block if
+ the kernel buffer is full, and until enough sound has been played to
+ allow the sound data to be buffered. The call always returns the
+ size of the data provided
-In PCM_NONBLOCK mode, the call will return immediately, with a return value of zero, if the buffer is
-full. In this case, the data should be written at a later time.
+In PCM_NONBLOCK mode, the call will return immediately, with a
+ return value of zero, if the buffer is full. In this case, the data
+ should be written at a later time.
+
+
+-
+ If enable is 1, playback or capture is paused. If enable is 0,
+ playback/capture is resumed.
A few hints on using PCM devices for playback
-The most common reason for problems with playback of PCM audio, is that the people don't properly understand
-that writes to PCM devices must match exactly the data rate of the device.
+The most common reason for problems with playback of PCM audio, is
+that the people don't properly understand that writes to PCM devices
+must match exactly the data rate of the device.
-If too little data is written to the device, it will underrun, and ugly clicking sounds will occur. Conversely,
-of too much data is written to the device, the write function will either block (PCM_NORMAL mode) or return zero
-(PCM_NONBLOCK mode).
+If too little data is written to the device, it will underrun, and
+ugly clicking sounds will occur. Conversely, of too much data is
+written to the device, the write function will either block
+(PCM_NORMAL mode) or return zero (PCM_NONBLOCK mode).
-If your program does nothing, but play sound, the easiest way is to put the device in PCM_NORMAL mode, and just
-write as much data to the device as possible. This strategy can also be achieved by using a separate thread
-with the sole task of playing out sound.
+If your program does nothing, but play sound, the easiest way is to
+put the device in PCM_NORMAL mode, and just write as much data to the
+device as possible. This strategy can also be achieved by using a
+separate thread with the sole task of playing out sound.
-In GUI programs, however, it may be a better strategy to setup the device, preload the buffer with a few
-periods by calling write a couple of times, and then use some timer method to write one period size of data to
-the device every period. The purpose of the preloading is to avoid underrun clicks if the used timer
-doesn't expire exactly on time.
+In GUI programs, however, it may be a better strategy to setup the
+device, preload the buffer with a few periods by calling write a
+couple of times, and then use some timer method to write one period
+size of data to the device every period. The purpose of the preloading
+is to avoid underrun clicks if the used timer doesn't expire exactly
+on time.
-Also note, that most timer APIs that you can find for Python will cummulate time delays: If you set the timer
-to expire after 1/10'th of a second, the actual timeout will happen slightly later, which will accumulate to
-quite a lot after a few seconds. Hint: use time.time() to check how much time has really passed, and add
-extra writes as nessecary.
+Also note, that most timer APIs that you can find for Python will
+cummulate time delays: If you set the timer to expire after 1/10'th of
+a second, the actual timeout will happen slightly later, which will
+accumulate to quite a lot after a few seconds. Hint: use time.time()
+to check how much time has really passed, and add extra writes as
+nessecary.
@@ -324,7 +371,7 @@ extra writes as nessecary.
-Release 0.3.
+Release 0.4.
diff --git a/doc/pyalsaaudio.html b/doc/pyalsaaudio.html
index d3fb373..bb14cee 100644
--- a/doc/pyalsaaudio.html
+++ b/doc/pyalsaaudio.html
@@ -44,6 +44,7 @@
PyAlsaAudio
Casper Wilstrup
+
cwi@aves.dk
@@ -102,7 +103,7 @@
-Release 0.3.
+Release 0.4.
diff --git a/doc/src/libalsaaudio.tex b/doc/src/libalsaaudio.tex
index 3d35561..784834e 100644
--- a/doc/src/libalsaaudio.tex
+++ b/doc/src/libalsaaudio.tex
@@ -383,6 +383,43 @@ To manipulate these swithes use the \method{setrec} or
\end{methoddesc}
+\begin{methoddesc}[Mixer]{getenum}{}
+ For enumerated controls, return the currently selected item and
+ the list of items available.
+
+ Returns a tuple \textit{(string, list of strings)}.
+
+ For example, my soundcard has a Mixer called \textit{Mono Output Select}.
+ Using \textit{amixer}, I get:
+
+\begin{verbatim}
+$ amixer get "Mono Output Select"
+Simple mixer control 'Mono Output Select',0
+ Capabilities: enum
+ Items: 'Mix' 'Mic'
+ Item0: 'Mix'
+\end{verbatim}
+
+ Using \module{alsaaudio}, one could do:
+\begin{verbatim}
+>>> import alsaaudio
+>>> m = alsaaudio.Mixer('Mono Output Select')
+>>> m.getenum()
+('Mix', ['Mix', 'Mic'])
+\end{verbatim}
+
+ This method will return an empty tuple if the mixer is not an
+ enumerated control.
+\end{methoddesc}
+
+\begin{methoddesc}[Mixer]{getmute}{}
+ Return a list indicating the current mute setting for each channel.
+ 0 means not muted, 1 means muted.
+
+ This method will fail if the mixer has no playback switch
+ capabilities.
+\end{methoddesc}
+
\begin{methoddesc}[Mixer]{getrange}{\optional{direction}}
Return the volume range of the ALSA mixer controlled by this object.
@@ -393,6 +430,14 @@ To manipulate these swithes use the \method{setrec} or
\end{methoddesc}
+\begin{methoddesc}[Mixer]{getrec}{}
+ Return a list indicating the current record mute setting for each
+ channel. 0 means not recording, 1 means recording.
+
+ This method will fail if the mixer has no capture switch
+ capabilities.
+\end{methoddesc}
+
\begin{methoddesc}[Mixer]{getvolume}{\optional{direction}}
Returns a list with the current volume settings for each channel.
The list elements are integer percentages.
@@ -404,22 +449,6 @@ To manipulate these swithes use the \method{setrec} or
\end{methoddesc}
-\begin{methoddesc}[Mixer]{getmute}{}
- Return a list indicating the current mute setting for each channel.
- 0 means not muted, 1 means muted.
-
- This method will fail if the mixer has no playback switch
- capabilities.
-\end{methoddesc}
-
-\begin{methoddesc}[Mixer]{getrec}{}
- Return a list indicating the current record mute setting for each
- channel. 0 means not recording, 1 means recording.
-
- This method will fail if the mixer has no capture switch
- capabilities.
-\end{methoddesc}
-
\begin{methoddesc}[Mixer]{setvolume}{volume,\optional{channel},
\optional{direction}}
diff --git a/doc/src/pyalsaaudio.tex b/doc/src/pyalsaaudio.tex
index 9fc94a2..bfb0a54 100644
--- a/doc/src/pyalsaaudio.tex
+++ b/doc/src/pyalsaaudio.tex
@@ -2,7 +2,7 @@
\title{PyAlsaAudio}
-\release{0.3}
+\release{0.4}
% At minimum, give your name and an email address. You can include a
% snail-mail address if you like.
diff --git a/setup.py b/setup.py
index 9b3b26a..41e34c9 100755
--- a/setup.py
+++ b/setup.py
@@ -18,7 +18,7 @@ if version < '2.2.3':
setup(
name = 'pyalsaaudio',
- version = '0.3',
+ version = '0.4',
description = 'ALSA bindings',
long_description = __doc__,
author = 'Casper Wilstrup',