summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJaroslav Kysela <perex@perex.cz>2008-04-21 11:44:20 +0200
committerJaroslav Kysela <perex@perex.cz>2008-04-21 11:44:20 +0200
commit058dde8b7da6f7b725e4ef8b9b237f2a5c6ff01e (patch)
treed448c9cd2544c67cce3bafe99ad92469ca1dae09
parent82af1df465181da783d85256afdda26942eaecbf (diff)
downloadalsa-lib-058dde8b7da6f7b725e4ef8b9b237f2a5c6ff01e.tar.gz
implemented integer volume <-> dB volume conversion functions for simple mixer
-rw-r--r--include/mixer.h4
-rw-r--r--include/mixer_abst.h2
-rw-r--r--modules/mixer/simple/python.c48
-rw-r--r--src/mixer/simple.c58
-rw-r--r--src/mixer/simple_none.c29
5 files changed, 139 insertions, 2 deletions
diff --git a/include/mixer.h b/include/mixer.h
index ac46b121..59deb9f2 100644
--- a/include/mixer.h
+++ b/include/mixer.h
@@ -250,6 +250,10 @@ int snd_mixer_selem_has_capture_switch(snd_mixer_elem_t *elem);
int snd_mixer_selem_has_capture_switch_joined(snd_mixer_elem_t *elem);
int snd_mixer_selem_has_capture_switch_exclusive(snd_mixer_elem_t *elem);
+int snd_mixer_selem_ask_playback_vol_dB(snd_mixer_elem_t *elem, long value, long *dBvalue);
+int snd_mixer_selem_ask_capture_vol_dB(snd_mixer_elem_t *elem, long value, long *dBvalue);
+int snd_mixer_selem_ask_playback_dB_vol(snd_mixer_elem_t *elem, long dBvalue, int dir, long *value);
+int snd_mixer_selem_ask_capture_dB_vol(snd_mixer_elem_t *elem, long dBvalue, int dir, long *value);
int snd_mixer_selem_get_playback_volume(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long *value);
int snd_mixer_selem_get_capture_volume(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long *value);
int snd_mixer_selem_get_playback_dB(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long *value);
diff --git a/include/mixer_abst.h b/include/mixer_abst.h
index d39d8358..7844b191 100644
--- a/include/mixer_abst.h
+++ b/include/mixer_abst.h
@@ -82,6 +82,8 @@ struct sm_elem_ops {
int (*get_range)(snd_mixer_elem_t *elem, int dir, long *min, long *max);
int (*set_range)(snd_mixer_elem_t *elem, int dir, long min, long max);
int (*get_dB_range)(snd_mixer_elem_t *elem, int dir, long *min, long *max);
+ int (*ask_vol_dB)(snd_mixer_elem_t *elem, int dir, long value, long *dbValue);
+ int (*ask_dB_vol)(snd_mixer_elem_t *elem, int dir, long dbValue, long *value, int xdir);
int (*get_volume)(snd_mixer_elem_t *elem, int dir, snd_mixer_selem_channel_id_t channel, long *value);
int (*get_dB)(snd_mixer_elem_t *elem, int dir, snd_mixer_selem_channel_id_t channel, long *value);
int (*set_volume)(snd_mixer_elem_t *elem, int dir, snd_mixer_selem_channel_id_t channel, long value);
diff --git a/modules/mixer/simple/python.c b/modules/mixer/simple/python.c
index 6d9b9fd2..c822c52a 100644
--- a/modules/mixer/simple/python.c
+++ b/modules/mixer/simple/python.c
@@ -204,7 +204,7 @@ static int set_range_ops(snd_mixer_elem_t *elem, int dir,
}
static int get_x_ops(snd_mixer_elem_t *elem, int dir,
- snd_mixer_selem_channel_id_t channel, long *value,
+ long channel, long *value,
const char *attr)
{
PyObject *obj1, *res;
@@ -251,6 +251,49 @@ static int get_switch_ops(snd_mixer_elem_t *elem, int dir,
return res;
}
+static int ask_vol_dB_ops(snd_mixer_elem_t *elem,
+ int dir,
+ long value,
+ long *dbValue)
+{
+ return get_x_ops(elem, dir, value, dbValue, "opsGetVolDB");
+}
+
+static int ask_dB_vol_ops(snd_mixer_elem_t *elem,
+ int dir,
+ long value,
+ long *dbValue,
+ int xdir)
+{
+ PyObject *obj1, *res;
+ struct pymelem *pymelem = melem_to_pymelem(elem);
+ int err;
+
+ obj1 = PyTuple_New(3);
+ PyTuple_SET_ITEM(obj1, 0, PyInt_FromLong(dir));
+ PyTuple_SET_ITEM(obj1, 1, PyInt_FromLong(value));
+ PyTuple_SET_ITEM(obj1, 2, PyInt_FromLong(xdir));
+ err = pcall(pymelem, "opsGetDBVol", obj1, &res);
+ if (err >= 0) {
+ err = !PyInt_Check(PyTuple_GetItem(res, 1));
+ if (err) {
+ err = !PyLong_Check(PyTuple_GetItem(res, 1));
+ if (err) {
+ PyErr_Format(PyExc_TypeError, "wrong result (invalid tuple)");
+ PyErr_Print();
+ PyErr_Clear();
+ err = -EIO;
+ } else {
+ *dbValue = PyLong_AsLong(PyTuple_GetItem(res, 1));
+ }
+ } else {
+ *dbValue = PyInt_AsLong(PyTuple_GetItem(res, 1));
+ }
+ }
+ Py_XDECREF(res);
+ return err;
+}
+
static int get_dB_ops(snd_mixer_elem_t *elem,
int dir,
snd_mixer_selem_channel_id_t channel,
@@ -278,7 +321,6 @@ static int set_volume_ops(snd_mixer_elem_t *elem, int dir,
return pcall(pymelem, "opsSetVolume", obj1, NULL);
}
-
static int set_switch_ops(snd_mixer_elem_t *elem, int dir,
snd_mixer_selem_channel_id_t channel, int value)
{
@@ -384,6 +426,8 @@ static struct sm_elem_ops simple_python_ops = {
.get_range = get_range_ops,
.get_dB_range = get_dB_range_ops,
.set_range = set_range_ops,
+ .ask_vol_dB = ask_vol_dB_ops,
+ .ask_dB_vol = ask_dB_vol_ops,
.get_volume = get_volume_ops,
.get_dB = get_dB_ops,
.set_volume = set_volume_ops,
diff --git a/src/mixer/simple.c b/src/mixer/simple.c
index ae948ace..c44f8b42 100644
--- a/src/mixer/simple.c
+++ b/src/mixer/simple.c
@@ -358,6 +358,35 @@ int snd_mixer_selem_has_playback_switch_joined(snd_mixer_elem_t *elem)
}
/**
+ * \brief Return corresponding dB value to an integer playback volume for a mixer simple element
+ * \param elem Mixer simple element handle
+ * \param value value to be converted to dB range
+ * \param dBvalue pointer to returned dB value
+ * \return 0 on success otherwise a negative error code
+ */
+int snd_mixer_selem_ask_playback_vol_dB(snd_mixer_elem_t *elem, long value, long *dBvalue)
+{
+ CHECK_BASIC(elem);
+ CHECK_DIR(elem, SM_CAP_PVOLUME);
+ return sm_selem_ops(elem)->ask_vol_dB(elem, SM_PLAY, value, dBvalue);
+}
+
+/**
+ * \brief Return corresponding integer playback volume for given dB value for a mixer simple element
+ * \param elem Mixer simple element handle
+ * \param value value to be converted to dB range
+ * \param dir select direction (-1 = accurate or first bellow, 0 = accurate, 1 = accurate or first above)
+ * \param dBvalue pointer to returned dB value
+ * \return 0 on success otherwise a negative error code
+ */
+int snd_mixer_selem_ask_playback_dB_vol(snd_mixer_elem_t *elem, long dBvalue, int dir, long *value)
+{
+ CHECK_BASIC(elem);
+ CHECK_DIR(elem, SM_CAP_PVOLUME);
+ return sm_selem_ops(elem)->ask_dB_vol(elem, SM_PLAY, dBvalue, value, dir);
+}
+
+/**
* \brief Return value of playback volume control of a mixer simple element
* \param elem Mixer simple element handle
* \param channel mixer simple element channel identifier
@@ -658,6 +687,35 @@ int snd_mixer_selem_get_capture_group(snd_mixer_elem_t *elem)
}
/**
+ * \brief Return corresponding dB value to an integer capture volume for a mixer simple element
+ * \param elem Mixer simple element handle
+ * \param value value to be converted to dB range
+ * \param dBvalue pointer to returned dB value
+ * \return 0 on success otherwise a negative error code
+ */
+int snd_mixer_selem_ask_capture_vol_dB(snd_mixer_elem_t *elem, long value, long *dBvalue)
+{
+ CHECK_BASIC(elem);
+ CHECK_DIR(elem, SM_CAP_CVOLUME);
+ return sm_selem_ops(elem)->ask_vol_dB(elem, SM_CAPT, value, dBvalue);
+}
+
+/**
+ * \brief Return corresponding integer capture volume for given dB value for a mixer simple element
+ * \param elem Mixer simple element handle
+ * \param dBvalue dB value to be converted to integer range
+ * \param value pointer to returned integer value
+ * \param dir select direction (-1 = accurate or first bellow, 0 = accurate, 1 = accurate or first above)
+ * \return 0 on success otherwise a negative error code
+ */
+int snd_mixer_selem_ask_capture_dB_vol(snd_mixer_elem_t *elem, long dBvalue, int dir, long *value)
+{
+ CHECK_BASIC(elem);
+ CHECK_DIR(elem, SM_CAP_CVOLUME);
+ return sm_selem_ops(elem)->ask_dB_vol(elem, SM_CAPT, dBvalue, value, dir);
+}
+
+/**
* \brief Return value of capture volume control of a mixer simple element
* \param elem Mixer simple element handle
* \param channel mixer simple element channel identifier
diff --git a/src/mixer/simple_none.c b/src/mixer/simple_none.c
index b490e1c1..ef277de2 100644
--- a/src/mixer/simple_none.c
+++ b/src/mixer/simple_none.c
@@ -1174,6 +1174,21 @@ static int convert_from_dB(snd_hctl_elem_t *ctl, struct selem_str *rec,
db_gain, value, xdir);
}
+static int ask_vol_dB_ops(snd_mixer_elem_t *elem,
+ int dir,
+ long value,
+ long *dBvalue)
+{
+ selem_none_t *s = snd_mixer_elem_get_private(elem);
+ selem_ctl_t *c;
+
+ c = get_selem_ctl(s, dir);
+ if (! c)
+ return -EINVAL;
+ int res = convert_to_dB(c->elem, &s->str[dir], value, dBvalue);
+ return res;
+}
+
static int get_dB_ops(snd_mixer_elem_t *elem,
int dir,
snd_mixer_selem_channel_id_t channel,
@@ -1219,6 +1234,18 @@ static int set_volume_ops(snd_mixer_elem_t *elem, int dir,
return 0;
}
+static int ask_dB_vol_ops(snd_mixer_elem_t *elem, int dir,
+ long dbValue, long *value, int xdir)
+{
+ selem_none_t *s = snd_mixer_elem_get_private(elem);
+ selem_ctl_t *c;
+
+ c = get_selem_ctl(s, dir);
+ if (! c)
+ return -EINVAL;
+ return convert_from_dB(c->elem, &s->str[dir], dbValue, value, xdir);
+}
+
static int set_dB_ops(snd_mixer_elem_t *elem, int dir,
snd_mixer_selem_channel_id_t channel,
long db_gain, int xdir)
@@ -1350,6 +1377,8 @@ static struct sm_elem_ops simple_none_ops = {
.get_range = get_range_ops,
.get_dB_range = get_dB_range_ops,
.set_range = set_range_ops,
+ .ask_vol_dB = ask_vol_dB_ops,
+ .ask_dB_vol = ask_dB_vol_ops,
.get_volume = get_volume_ops,
.get_dB = get_dB_ops,
.set_volume = set_volume_ops,