implemented integer volume <-> dB volume conversion functions for simple mixer
authorJaroslav Kysela <perex@perex.cz>
Mon, 21 Apr 2008 09:44:20 +0000 (11:44 +0200)
committerJaroslav Kysela <perex@perex.cz>
Mon, 21 Apr 2008 09:44:20 +0000 (11:44 +0200)
include/mixer.h
include/mixer_abst.h
modules/mixer/simple/python.c
src/mixer/simple.c
src/mixer/simple_none.c

index ac46b12..59deb9f 100644 (file)
@@ -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);
index d39d835..7844b19 100644 (file)
@@ -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);
index 6d9b9fd..c822c52 100644 (file)
@@ -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,
index ae948ac..c44f8b4 100644 (file)
@@ -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
index b490e1c..ef277de 100644 (file)
@@ -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,