summaryrefslogtreecommitdiff
path: root/cras/src/alsa_plugin/ctl_cras.c
diff options
context:
space:
mode:
Diffstat (limited to 'cras/src/alsa_plugin/ctl_cras.c')
-rw-r--r--cras/src/alsa_plugin/ctl_cras.c78
1 files changed, 78 insertions, 0 deletions
diff --git a/cras/src/alsa_plugin/ctl_cras.c b/cras/src/alsa_plugin/ctl_cras.c
index 76b0c039..822b63ab 100644
--- a/cras/src/alsa_plugin/ctl_cras.c
+++ b/cras/src/alsa_plugin/ctl_cras.c
@@ -14,6 +14,8 @@ static const size_t MAX_IONODES = 20; /* Max ionodes to print out. */
enum CTL_CRAS_MIXER_CONTROLS {
CTL_CRAS_MIXER_PLAYBACK_SWITCH,
CTL_CRAS_MIXER_PLAYBACK_VOLUME,
+ CTL_CRAS_MIXER_CAPTURE_SWITCH,
+ CTL_CRAS_MIXER_CAPTURE_VOLUME,
NUM_CTL_CRAS_MIXER_ELEMS
};
@@ -31,6 +33,10 @@ static const struct cras_mixer_control cras_elems[NUM_CTL_CRAS_MIXER_ELEMS] = {
SND_CTL_EXT_ACCESS_READWRITE, 1 },
{ "Master Playback Volume", SND_CTL_ELEM_TYPE_INTEGER,
SND_CTL_EXT_ACCESS_READWRITE, 1 },
+ { "Capture Switch", SND_CTL_ELEM_TYPE_BOOLEAN,
+ SND_CTL_EXT_ACCESS_READWRITE, 1 },
+ { "Capture Volume", SND_CTL_ELEM_TYPE_INTEGER,
+ SND_CTL_EXT_ACCESS_READWRITE, 1 },
};
/* Holds the client and ctl plugin pointers. */
@@ -113,6 +119,46 @@ static int ctl_cras_get_integer_info(snd_ctl_ext_t *ext_ctl,
return 0;
}
+static long capture_index_to_gain(struct cras_client *client, long index)
+{
+ long min;
+ long max;
+ long dB_step;
+
+ min = cras_client_get_system_min_capture_gain(client);
+ max = cras_client_get_system_max_capture_gain(client);
+ if (min >= max)
+ return min;
+
+ dB_step = (max - min) / 100;
+
+ if (index <= 0)
+ return min;
+ if (index >= 100)
+ return max;
+ return index * dB_step + min;
+}
+
+static long capture_gain_to_index(struct cras_client *client, long gain)
+{
+ long min;
+ long max;
+ long dB_step;
+
+ min = cras_client_get_system_min_capture_gain(client);
+ max = cras_client_get_system_max_capture_gain(client);
+ if (min >= max)
+ return 0;
+
+ dB_step = (max - min) / 100;
+
+ if (gain <= min)
+ return 0;
+ if (gain >= max)
+ return 100;
+ return (gain - min) / dB_step;
+}
+
static int get_nodes(struct cras_client *client, enum CRAS_STREAM_DIRECTION dir,
struct cras_ionode_info *nodes, size_t num_nodes)
{
@@ -153,6 +199,20 @@ static int ctl_cras_read_integer(snd_ctl_ext_t *ext_ctl, snd_ctl_ext_key_t key,
break;
}
break;
+ case CTL_CRAS_MIXER_CAPTURE_SWITCH:
+ *value = !cras_client_get_system_capture_muted(cras->client);
+ break;
+ case CTL_CRAS_MIXER_CAPTURE_VOLUME:
+ num_nodes = get_nodes(cras->client, CRAS_STREAM_INPUT, nodes,
+ MAX_IONODES);
+ for (i = 0; i < num_nodes; i++) {
+ if (!nodes[i].active)
+ continue;
+ *value = capture_gain_to_index(cras->client,
+ nodes[i].capture_gain);
+ break;
+ }
+ break;
default:
return -EINVAL;
}
@@ -167,6 +227,7 @@ static int ctl_cras_write_integer(snd_ctl_ext_t *ext_ctl, snd_ctl_ext_key_t key,
struct ctl_cras *cras = (struct ctl_cras *)ext_ctl->private_data;
struct cras_ionode_info nodes[MAX_IONODES];
int num_nodes, i;
+ long gain;
switch (key) {
case CTL_CRAS_MIXER_PLAYBACK_SWITCH:
@@ -185,6 +246,23 @@ static int ctl_cras_write_integer(snd_ctl_ext_t *ext_ctl, snd_ctl_ext_key_t key,
*value);
}
break;
+ case CTL_CRAS_MIXER_CAPTURE_SWITCH:
+ cras_client_set_system_capture_mute(cras->client, !(*value));
+ break;
+ case CTL_CRAS_MIXER_CAPTURE_VOLUME:
+ gain = capture_index_to_gain(cras->client, *value);
+ num_nodes = get_nodes(cras->client, CRAS_STREAM_INPUT, nodes,
+ MAX_IONODES);
+ for (i = 0; i < num_nodes; i++) {
+ if (!nodes[i].active)
+ continue;
+ cras_client_set_node_capture_gain(
+ cras->client,
+ cras_make_node_id(nodes[i].iodev_idx,
+ nodes[i].ionode_idx),
+ gain);
+ }
+ break;
default:
return -EINVAL;
}