Added Freddy Spierenburgs patch for alsamixer_getrange and alsamixer_getenum.

git-svn-id: svn://svn.code.sf.net/p/pyalsaaudio/code/trunk@15 ec2f30ec-7544-0410-870e-f70ca00c83f0
This commit is contained in:
larsimmisch
2008-01-24 13:36:56 +00:00
parent 2cf24ef81b
commit ba03ad3c75
3 changed files with 190 additions and 62 deletions

View File

@@ -1,3 +1,5 @@
/* -*- Mode: C; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/* /*
* alsaaudio -- Python interface to ALSA (Advanced Linux Sound Architecture). * alsaaudio -- Python interface to ALSA (Advanced Linux Sound Architecture).
* The standard audio API for Linux since kernel 2.6 * The standard audio API for Linux since kernel 2.6
@@ -5,7 +7,7 @@
* Contributed by Unispeed A/S (http://www.unispeed.com) * Contributed by Unispeed A/S (http://www.unispeed.com)
* Author: Casper Wilstup (cwi@unispeed.dk) * Author: Casper Wilstup (cwi@unispeed.dk)
* *
* Bug fixes by Lars Immisch <lars@ibp.de> * Bug fixes and maintenance by Lars Immisch <lars@ibp.de>
* *
* License: Python Software Foundation License * License: Python Software Foundation License
* *
@@ -16,14 +18,14 @@
#include <stdio.h> #include <stdio.h>
PyDoc_STRVAR(alsaaudio_module_doc, PyDoc_STRVAR(alsaaudio_module_doc,
"This modules provides support for the ALSA audio API.\n" "This modules provides support for the ALSA audio API.\n"
"\n" "\n"
"To control the PCM device, use the PCM class, Mixers\n" "To control the PCM device, use the PCM class, Mixers\n"
"are controlled using the Mixer class.\n" "are controlled using the Mixer class.\n"
"\n" "\n"
"The following functions are also provided:\n" "The following functions are also provided:\n"
"mixers() -- Return a list of available mixer names\n" "mixers() -- Return a list of available mixer names\n"
); );
typedef struct { typedef struct {
PyObject_HEAD; PyObject_HEAD;
@@ -85,7 +87,8 @@ static int alsapcm_setup(alsapcm_t *self) {
snd_pcm_close(self->handle); snd_pcm_close(self->handle);
self->handle = 0; self->handle = 0;
} }
res = snd_pcm_open(&(self->handle),self->cardname,self->pcmtype,self->pcmmode); res = snd_pcm_open(&(self->handle),self->cardname,self->pcmtype,
self->pcmmode);
if (res < 0) return res; if (res < 0) return res;
/* Allocate a hwparam structure, and fill it in with configuration space */ /* Allocate a hwparam structure, and fill it in with configuration space */
@@ -95,12 +98,14 @@ static int alsapcm_setup(alsapcm_t *self) {
/* Fill it in with default values. */ /* Fill it in with default values. */
snd_pcm_hw_params_any(self->handle, hwparams); snd_pcm_hw_params_any(self->handle, hwparams);
snd_pcm_hw_params_set_access(self->handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED); snd_pcm_hw_params_set_access(self->handle, hwparams,
SND_PCM_ACCESS_RW_INTERLEAVED);
snd_pcm_hw_params_set_format(self->handle, hwparams, self->format); snd_pcm_hw_params_set_format(self->handle, hwparams, self->format);
snd_pcm_hw_params_set_channels(self->handle, hwparams, self->channels); snd_pcm_hw_params_set_channels(self->handle, hwparams, self->channels);
dir = 0; dir = 0;
snd_pcm_hw_params_set_rate(self->handle, hwparams, self->rate, dir); snd_pcm_hw_params_set_rate(self->handle, hwparams, self->rate, dir);
snd_pcm_hw_params_set_period_size(self->handle, hwparams, self->periodsize, dir); snd_pcm_hw_params_set_period_size(self->handle, hwparams, self->periodsize,
dir);
snd_pcm_hw_params_set_periods(self->handle,hwparams,4,0); snd_pcm_hw_params_set_periods(self->handle,hwparams,4,0);
/* Write it to the device */ /* Write it to the device */
@@ -114,7 +119,8 @@ static int alsapcm_setup(alsapcm_t *self) {
snd_pcm_hw_params_get_format(hwparams,&fmt); self->format = fmt; snd_pcm_hw_params_get_format(hwparams,&fmt); self->format = fmt;
snd_pcm_hw_params_get_channels(hwparams,&val); self->channels = val; snd_pcm_hw_params_get_channels(hwparams,&val); self->channels = val;
snd_pcm_hw_params_get_rate(hwparams,&val,&dir); self->rate = val; snd_pcm_hw_params_get_rate(hwparams,&val,&dir); self->rate = val;
snd_pcm_hw_params_get_period_size(hwparams,&frames,&dir); self->periodsize = (int) frames; snd_pcm_hw_params_get_period_size(hwparams,&frames,&dir);
self->periodsize = (int) frames;
self->framesize = self->channels * snd_pcm_hw_params_get_sbits(hwparams)/8; self->framesize = self->channels * snd_pcm_hw_params_get_sbits(hwparams)/8;
return res; return res;
@@ -127,11 +133,15 @@ alsapcm_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
int pcmtype=0; int pcmtype=0;
int pcmmode=0; int pcmmode=0;
char *cardname = "default"; char *cardname = "default";
if (!PyArg_ParseTuple(args,"|iis",&pcmtype,&pcmmode,&cardname)) return NULL; if (!PyArg_ParseTuple(args,"|iis",&pcmtype,&pcmmode,&cardname))
if (!(self = (alsapcm_t *)PyObject_New(alsapcm_t, &ALSAPCMType))) return NULL; return NULL;
if (!(self = (alsapcm_t *)PyObject_New(alsapcm_t, &ALSAPCMType)))
return NULL;
if (pcmtype != SND_PCM_STREAM_PLAYBACK && pcmtype != SND_PCM_STREAM_CAPTURE) { if (pcmtype != SND_PCM_STREAM_PLAYBACK && pcmtype != SND_PCM_STREAM_CAPTURE)
PyErr_SetString(ALSAAudioError, "PCM type must be PCM_PLAYBACK (0) or PCM_CAPTURE (1)"); {
PyErr_SetString(ALSAAudioError, "PCM type must be PCM_PLAYBACK (0) "
"or PCM_CAPTURE (1)");
return NULL; return NULL;
} }
if (pcmmode < 0 || pcmmode > SND_PCM_ASYNC) { if (pcmmode < 0 || pcmmode > SND_PCM_ASYNC) {
@@ -191,13 +201,13 @@ alsapcm_dumpinfo(alsapcm_t *self, PyObject *args) {
snd_pcm_hw_params_get_format(hwparams, &fmt); snd_pcm_hw_params_get_format(hwparams, &fmt);
printf("format = '%s' (%s)\n", printf("format = '%s' (%s)\n",
snd_pcm_format_name(fmt), snd_pcm_format_name(fmt),
snd_pcm_format_description(fmt)); snd_pcm_format_description(fmt));
snd_pcm_hw_params_get_subformat(hwparams, (snd_pcm_subformat_t *)&val); snd_pcm_hw_params_get_subformat(hwparams, (snd_pcm_subformat_t *)&val);
printf("subformat = '%s' (%s)\n", printf("subformat = '%s' (%s)\n",
snd_pcm_subformat_name((snd_pcm_subformat_t)val), snd_pcm_subformat_name((snd_pcm_subformat_t)val),
snd_pcm_subformat_description((snd_pcm_subformat_t)val)); snd_pcm_subformat_description((snd_pcm_subformat_t)val));
snd_pcm_hw_params_get_channels(hwparams, &val); snd_pcm_hw_params_get_channels(hwparams, &val);
printf("channels = %d\n", val); printf("channels = %d\n", val);
@@ -345,7 +355,8 @@ alsapcm_read(alsapcm_t *self, PyObject *args) {
char buffer[8000]; char buffer[8000];
if (self->framesize * self->periodsize > 8000) { if (self->framesize * self->periodsize > 8000) {
PyErr_SetString(ALSAAudioError,"Capture data too large. Try decreasing period size"); PyErr_SetString(ALSAAudioError,"Capture data too large. "
"Try decreasing period size");
return NULL; return NULL;
} }
@@ -366,11 +377,11 @@ alsapcm_read(alsapcm_t *self, PyObject *args) {
if (res != -EPIPE) if (res != -EPIPE)
{ {
if (res == -EAGAIN) { if (res == -EAGAIN) {
res = 0; res = 0;
} }
else if (res < 0) { else if (res < 0) {
PyErr_SetString(ALSAAudioError,snd_strerror(res)); PyErr_SetString(ALSAAudioError,snd_strerror(res));
return NULL; return NULL;
} }
} }
@@ -383,7 +394,8 @@ static PyObject *alsapcm_write(alsapcm_t *self, PyObject *args) {
int res; int res;
if (!PyArg_ParseTuple(args,"s#",&data,&datalen)) return NULL; if (!PyArg_ParseTuple(args,"s#",&data,&datalen)) return NULL;
if (datalen%self->framesize) { if (datalen%self->framesize) {
PyErr_SetString(ALSAAudioError,"Data size must be a multiple of framesize"); PyErr_SetString(ALSAAudioError,
"Data size must be a multiple of framesize");
return NULL; return NULL;
} }
@@ -392,8 +404,8 @@ static PyObject *alsapcm_write(alsapcm_t *self, PyObject *args) {
if (res == -EPIPE) { if (res == -EPIPE) {
/* EPIPE means underrun */ /* EPIPE means underrun */
res = snd_pcm_recover(self->handle, res, 1); res = snd_pcm_recover(self->handle, res, 1);
if (res >= 0) if (res >= 0)
res = snd_pcm_writei(self->handle, data, datalen/self->framesize); res = snd_pcm_writei(self->handle, data, datalen/self->framesize);
} }
Py_END_ALLOW_THREADS Py_END_ALLOW_THREADS
@@ -520,7 +532,7 @@ alsamixer_list(PyObject *self, PyObject *args) {
PyObject *result = PyList_New(0); PyObject *result = PyList_New(0);
if (!PyArg_ParseTuple(args,"|s",&cardname)) return NULL; if (!PyArg_ParseTuple(args,"|s",&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);
if (err < 0) { if (err < 0) {
@@ -528,7 +540,9 @@ alsamixer_list(PyObject *self, PyObject *args) {
snd_mixer_close(handle); snd_mixer_close(handle);
return NULL; return NULL;
} }
for (elem = snd_mixer_first_elem(handle); elem; elem = snd_mixer_elem_next(elem)) { for (elem = snd_mixer_first_elem(handle); elem;
elem = snd_mixer_elem_next(elem))
{
PyObject *mixer; PyObject *mixer;
snd_mixer_selem_get_id(elem, sid); snd_mixer_selem_get_id(elem, sid);
mixer = PyString_FromString(snd_mixer_selem_id_get_name(sid)); mixer = PyString_FromString(snd_mixer_selem_id_get_name(sid));
@@ -560,8 +574,10 @@ alsamixer_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
snd_mixer_elem_t *elem; snd_mixer_elem_t *elem;
int channel; int channel;
if (!PyArg_ParseTuple(args,"|sis",&control,&id,&cardname)) return NULL; if (!PyArg_ParseTuple(args,"|sis",&control,&id,&cardname))
if (!(self = (alsamixer_t *)PyObject_New(alsamixer_t, &ALSAMixerType))) return NULL; return NULL;
if (!(self = (alsamixer_t *)PyObject_New(alsamixer_t, &ALSAMixerType)))
return NULL;
err = alsamixer_gethandle(cardname,&self->handle); err = alsamixer_gethandle(cardname,&self->handle);
if (err<0) { if (err<0) {
@@ -575,7 +591,8 @@ alsamixer_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
elem = alsamixer_find_elem(self->handle,control,id); elem = alsamixer_find_elem(self->handle,control,id);
if (!elem) { if (!elem) {
char errtext[128]; char errtext[128];
sprintf(errtext,"Unable to find mixer control '%s',%i",self->controlname,self->controlid); sprintf(errtext,"Unable to find mixer control '%s',%i",self->controlname,
self->controlid);
snd_mixer_close(self->handle); snd_mixer_close(self->handle);
PyErr_SetString(ALSAAudioError,errtext); PyErr_SetString(ALSAAudioError,errtext);
return NULL; return NULL;
@@ -584,51 +601,60 @@ alsamixer_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
self->volume_cap = self->switch_cap = 0; self->volume_cap = self->switch_cap = 0;
if (snd_mixer_selem_has_common_volume(elem)) { if (snd_mixer_selem_has_common_volume(elem)) {
self->volume_cap |= MIXER_CAP_VOLUME; self->volume_cap |= MIXER_CAP_VOLUME;
if (snd_mixer_selem_has_playback_volume_joined(elem)) self->volume_cap |= MIXER_CAP_VOLUME_JOINED; if (snd_mixer_selem_has_playback_volume_joined(elem))
self->volume_cap |= MIXER_CAP_VOLUME_JOINED;
} }
else { else {
if (snd_mixer_selem_has_playback_volume(elem)) { if (snd_mixer_selem_has_playback_volume(elem)) {
self->volume_cap |= MIXER_CAP_PVOLUME; self->volume_cap |= MIXER_CAP_PVOLUME;
if (snd_mixer_selem_has_playback_volume_joined(elem)) self->volume_cap |= MIXER_CAP_PVOLUME_JOINED; if (snd_mixer_selem_has_playback_volume_joined(elem))
self->volume_cap |= MIXER_CAP_PVOLUME_JOINED;
} }
if (snd_mixer_selem_has_capture_volume(elem)) { if (snd_mixer_selem_has_capture_volume(elem)) {
self->volume_cap |= MIXER_CAP_CVOLUME; self->volume_cap |= MIXER_CAP_CVOLUME;
if (snd_mixer_selem_has_capture_volume_joined(elem)) self->volume_cap |= MIXER_CAP_CVOLUME_JOINED; if (snd_mixer_selem_has_capture_volume_joined(elem))
self->volume_cap |= MIXER_CAP_CVOLUME_JOINED;
} }
} }
if (snd_mixer_selem_has_common_switch(elem)) { if (snd_mixer_selem_has_common_switch(elem)) {
self->switch_cap |= MIXER_CAP_SWITCH; self->switch_cap |= MIXER_CAP_SWITCH;
if (snd_mixer_selem_has_playback_switch_joined(elem)) self->switch_cap |= MIXER_CAP_SWITCH_JOINED; if (snd_mixer_selem_has_playback_switch_joined(elem))
self->switch_cap |= MIXER_CAP_SWITCH_JOINED;
} }
else { else {
if (snd_mixer_selem_has_playback_switch(elem)) { if (snd_mixer_selem_has_playback_switch(elem)) {
self->switch_cap |= MIXER_CAP_PSWITCH; self->switch_cap |= MIXER_CAP_PSWITCH;
if (snd_mixer_selem_has_playback_switch_joined(elem)) self->switch_cap |= MIXER_CAP_PSWITCH_JOINED; if (snd_mixer_selem_has_playback_switch_joined(elem))
self->switch_cap |= MIXER_CAP_PSWITCH_JOINED;
} }
if (snd_mixer_selem_has_capture_switch(elem)) { if (snd_mixer_selem_has_capture_switch(elem)) {
self->switch_cap |= MIXER_CAP_CSWITCH; self->switch_cap |= MIXER_CAP_CSWITCH;
if (snd_mixer_selem_has_capture_switch_joined(elem)) self->switch_cap |= MIXER_CAP_CSWITCH_JOINED; if (snd_mixer_selem_has_capture_switch_joined(elem))
if (snd_mixer_selem_has_capture_switch_exclusive(elem)) self->switch_cap |= MIXER_CAP_CSWITCH_EXCLUSIVE; self->switch_cap |= MIXER_CAP_CSWITCH_JOINED;
if (snd_mixer_selem_has_capture_switch_exclusive(elem))
self->switch_cap |= MIXER_CAP_CSWITCH_EXCLUSIVE;
} }
} }
self->pchannels = 0; self->pchannels = 0;
if (self->volume_cap | MIXER_CAP_PVOLUME || self->switch_cap | MIXER_CAP_PSWITCH) { if (self->volume_cap | MIXER_CAP_PVOLUME ||
self->switch_cap | MIXER_CAP_PSWITCH) {
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)) self->pchannels++;
else break; else break;
} }
} }
} }
self->cchannels = 0; self->cchannels = 0;
if (self->volume_cap | MIXER_CAP_CVOLUME || self->switch_cap | MIXER_CAP_CSWITCH) { if (self->volume_cap | MIXER_CAP_CVOLUME ||
self->switch_cap | MIXER_CAP_CSWITCH) {
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)) self->cchannels++;
else break; else break;
} }
} }
} }
@@ -754,19 +780,91 @@ alsamixer_getvolume(alsamixer_t *self, PyObject *args) {
} }
result = PyList_New(0); result = PyList_New(0);
for (channel = 0; channel <= SND_MIXER_SCHN_LAST; channel++) { for (channel = 0; channel <= SND_MIXER_SCHN_LAST; channel++) {
if (direction == 0 && snd_mixer_selem_has_playback_channel(elem, channel)) { if (direction == 0 && snd_mixer_selem_has_playback_channel(elem, channel))
{
snd_mixer_selem_get_playback_volume(elem, channel, &ival); snd_mixer_selem_get_playback_volume(elem, channel, &ival);
PyList_Append(result,PyInt_FromLong(alsamixer_getpercentage(self->pmin,self->pmax,ival))); PyList_Append(
result, PyInt_FromLong(alsamixer_getpercentage(self->pmin,
self->pmax, ival)));
} }
else if (direction == 1 && snd_mixer_selem_has_capture_channel(elem, channel) else if (direction == 1
&& snd_mixer_selem_has_capture_volume(elem)) { && snd_mixer_selem_has_capture_channel(elem, channel)
&& 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(result,PyInt_FromLong(alsamixer_getpercentage(self->cmin,self->cmax,ival))); PyList_Append(
result,PyInt_FromLong(alsamixer_getpercentage(self->cmin,
self->cmax, ival)));
} }
} }
return result; return result;
} }
static PyObject *
alsamixer_getrange(alsamixer_t *self, PyObject *args) {
snd_mixer_elem_t *elem;
int direction;
char *dirstr = 0;
PyObject *result;
if (!PyArg_ParseTuple(args,"|s",&dirstr)) return NULL;
elem = alsamixer_find_elem(self->handle,self->controlname,self->controlid);
if (!dirstr) {
if (self->pchannels) direction = 0;
else direction = 1;
}
else if (strcasecmp(dirstr,"playback")==0) direction = 0;
else if (strcasecmp(dirstr,"capture")==0) direction = 1;
else {
PyErr_SetString(ALSAAudioError,"Invalid direction argument for direction");
return NULL;
}
result = PyList_New(0);
if (direction == 0 && snd_mixer_selem_has_playback_channel(elem, 0)) {
PyList_Append(result,PyInt_FromLong(self->pmin));
PyList_Append(result,PyInt_FromLong(self->pmax));
}
else if (direction == 1 && snd_mixer_selem_has_capture_channel(elem, 0)
&& snd_mixer_selem_has_capture_volume(elem)) {
PyList_Append(result,PyInt_FromLong(self->cmin));
PyList_Append(result,PyInt_FromLong(self->cmax));
}
return result;
}
static PyObject *
alsamixer_getenum(alsamixer_t *self, PyObject *args) {
snd_mixer_elem_t *elem;
unsigned int index;
char name[32];
int res;
PyObject *result;
if (!PyArg_ParseTuple(args,"")) return NULL;
elem = alsamixer_find_elem(self->handle,self->controlname,self->controlid);
if (!snd_mixer_selem_is_enumerated(elem)) {
PyErr_SetString(ALSAAudioError,"Mixer is no enumerated control");
return NULL;
}
res=snd_mixer_selem_get_enum_item(elem, 0, &index);
if(res) {
PyErr_SetString(ALSAAudioError, snd_strerror(res));
return NULL;
}
res=snd_mixer_selem_get_enum_item_name(elem, index, sizeof(name)-1, name);
if(res) {
PyErr_SetString(ALSAAudioError, snd_strerror(res));
return NULL;
} else {
result = PyList_New(0);
PyList_Append(result,PyString_FromString(name));
}
return result;
}
static PyObject * static PyObject *
alsamixer_getmute(alsamixer_t *self, PyObject *args) { alsamixer_getmute(alsamixer_t *self, PyObject *args) {
snd_mixer_elem_t *elem; snd_mixer_elem_t *elem;
@@ -839,7 +937,8 @@ alsamixer_setvolume(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. Use 'playback' or 'capture'"); PyErr_SetString(ALSAAudioError,"Invalid direction argument. Use "
"'playback' or 'capture'");
return NULL; return NULL;
} }
for (i = 0; i <= SND_MIXER_SCHN_LAST; i++) { for (i = 0; i <= SND_MIXER_SCHN_LAST; i++) {
@@ -849,8 +948,9 @@ alsamixer_setvolume(alsamixer_t *self, PyObject *args) {
snd_mixer_selem_set_playback_volume(elem, i, physvolume); snd_mixer_selem_set_playback_volume(elem, i, physvolume);
done++; done++;
} }
else if (direction == 1 && snd_mixer_selem_has_capture_channel(elem, channel) else if (direction == 1
&& snd_mixer_selem_has_capture_volume(elem)) { && snd_mixer_selem_has_capture_channel(elem, channel)
&& 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++;
@@ -932,6 +1032,8 @@ static PyMethodDef alsamixer_methods[] = {
{"switchcap", (PyCFunction)alsamixer_switchcap, METH_VARARGS}, {"switchcap", (PyCFunction)alsamixer_switchcap, METH_VARARGS},
{"volumecap", (PyCFunction)alsamixer_volumecap, METH_VARARGS}, {"volumecap", (PyCFunction)alsamixer_volumecap, METH_VARARGS},
{"getvolume", (PyCFunction)alsamixer_getvolume, METH_VARARGS}, {"getvolume", (PyCFunction)alsamixer_getvolume, METH_VARARGS},
{"getrange", (PyCFunction)alsamixer_getrange, METH_VARARGS},
{"getenum", (PyCFunction)alsamixer_getenum, METH_VARARGS},
{"getmute", (PyCFunction)alsamixer_getmute, METH_VARARGS}, {"getmute", (PyCFunction)alsamixer_getmute, METH_VARARGS},
{"getrec", (PyCFunction)alsamixer_getrec, METH_VARARGS}, {"getrec", (PyCFunction)alsamixer_getrec, METH_VARARGS},
{"setvolume", (PyCFunction)alsamixer_setvolume, METH_VARARGS}, {"setvolume", (PyCFunction)alsamixer_setvolume, METH_VARARGS},

View File

@@ -176,7 +176,23 @@ 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">getvolume</tt></b>(</nobr></td> <td><nobr><b><tt id='l2h-22' xml:id='l2h-22' 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-23' xml:id='l2h-23' class="method">getvolume</tt></b>(</nobr></td>
<td><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>
Returns a list with the current volume settings for each channel. The list elements Returns a list with the current volume settings for each channel. The list elements
@@ -192,7 +208,7 @@ if the mixer has this capability, otherwise 'capture'
<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-23' xml:id='l2h-23' 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.
@@ -203,7 +219,7 @@ This method will fail if the mixer has no playback switch 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-24' xml:id='l2h-24' class="method">getrec</tt></b>(</nobr></td> <td><nobr><b><tt id='l2h-25' xml:id='l2h-25' 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 channel. 0 means not recording, 1
@@ -215,7 +231,7 @@ This method will fail if the mixer has no capture switch 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-25' xml:id='l2h-25' class="method">setvolume</tt></b>(</nobr></td> <td><nobr><b><tt id='l2h-26' xml:id='l2h-26' 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> <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> <dd>
Change the current volume settings for this mixer. The <var>volume</var> argument controls Change the current volume settings for this mixer. The <var>volume</var> argument controls
@@ -233,7 +249,7 @@ if changed. The default is 'playback' if the mixer has this capability, otherwis
<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">setmute</tt></b>(</nobr></td> <td><nobr><b><tt id='l2h-27' xml:id='l2h-27' 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.
@@ -248,7 +264,7 @@ 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-27' xml:id='l2h-27' class="method">setrec</tt></b>(</nobr></td> <td><nobr><b><tt id='l2h-28' xml:id='l2h-28' 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> argument is either 0 for no capture,

View File

@@ -315,6 +315,16 @@ the list are:
\end{methoddesc} \end{methoddesc}
\begin{methoddesc}[Mixer]{getrange}{\optional{direction}}
Return the volume range of the ALSA mixer controlled by this object.
The optional \var{direction} argument can be either 'playback' or 'capture',
which is relevant if the mixer can control both playback and capture volume.
The default value is 'playback' if the mixer has this capability, otherwise
'capture'
\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. The list elements Returns a list with the current volume settings for each channel. The list elements
are integer percentages. are integer percentages.