diff options
Diffstat (limited to 'cras/src/alsa_plugin/ctl_cras.c')
-rw-r--r-- | cras/src/alsa_plugin/ctl_cras.c | 78 |
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; } |