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