aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Wilson <ksattic@gmail.com>2011-06-05 21:18:52 -0700
committerSimon Wilson <ksattic@gmail.com>2011-06-05 21:18:52 -0700
commitf0a20ee4ccbba5504bd87397fcf9d9a89467208d (patch)
tree0db49de15456ae4f240b5560f7c12ab14437fa1d
parent066c9f6753dff5e2b8556eeaec986651bf835e08 (diff)
Implement mixer setting in tinymix
- re-add function to set enum type by string - implement setting of mixer values in tinymix - fix bug: read current mixer values before writing
-rw-r--r--include/tinyalsa/asoundlib.h1
-rw-r--r--mixer.c28
-rw-r--r--tinymix.c37
3 files changed, 65 insertions, 1 deletions
diff --git a/include/tinyalsa/asoundlib.h b/include/tinyalsa/asoundlib.h
index 2965c17..4ee04a3 100644
--- a/include/tinyalsa/asoundlib.h
+++ b/include/tinyalsa/asoundlib.h
@@ -129,5 +129,6 @@ int mixer_ctl_set_percent(struct mixer_ctl *ctl, unsigned int id, int percent);
int mixer_ctl_get_value(struct mixer_ctl *ctl, unsigned int id);
int mixer_ctl_set_value(struct mixer_ctl *ctl, unsigned int id, int value);
+int mixer_ctl_set_enum_by_string(struct mixer_ctl *ctl, const char *string);
#endif
diff --git a/mixer.c b/mixer.c
index 65be1f3..eedcbb7 100644
--- a/mixer.c
+++ b/mixer.c
@@ -348,6 +348,8 @@ int mixer_ctl_set_value(struct mixer_ctl *ctl, unsigned int id, int value)
memset(&ev, 0, sizeof(ev));
ev.id.numid = ctl->info->id.numid;
+ if (ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_READ, &ev))
+ return -1;
switch (ctl->info->type) {
case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
@@ -400,3 +402,29 @@ int mixer_ctl_get_enum_string(struct mixer_ctl *ctl, unsigned int enum_id,
return 0;
}
+int mixer_ctl_set_enum_by_string(struct mixer_ctl *ctl, const char *string)
+{
+ unsigned int i, num_enums;
+ struct snd_ctl_elem_value ev;
+
+ if (!ctl || (ctl->info->type != SNDRV_CTL_ELEM_TYPE_ENUMERATED)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ num_enums = ctl->info->value.enumerated.items;
+ for (i = 0; i < num_enums; i++) {
+ if (!strcmp(string, ctl->ename[i])) {
+ memset(&ev, 0, sizeof(ev));
+ ev.value.enumerated.item[0] = i;
+ ev.id.numid = ctl->info->id.numid;
+ if (ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_WRITE, &ev) < 0)
+ return -1;
+ return 0;
+ }
+ }
+
+ errno = EINVAL;
+ return -1;
+}
+
diff --git a/tinymix.c b/tinymix.c
index 68c23d1..bf24a7c 100644
--- a/tinymix.c
+++ b/tinymix.c
@@ -32,6 +32,8 @@
static void tinymix_list_controls(struct mixer *mixer);
static void tinymix_detail_control(struct mixer *mixer, unsigned int id);
+static void tinymix_set_value(struct mixer *mixer, unsigned int id,
+ char *value);
int main(int argc, char **argv)
{
@@ -43,8 +45,10 @@ int main(int argc, char **argv)
tinymix_list_controls(mixer);
else if (argc == 2)
tinymix_detail_control(mixer, atoi(argv[1]));
+ else if (argc == 3)
+ tinymix_set_value(mixer, atoi(argv[1]), argv[2]);
else
- printf("Usage: tinymix [control id]\n");
+ printf("Usage: tinymix [control id] [value to set]\n");
mixer_close(mixer);
@@ -129,3 +133,34 @@ static void tinymix_detail_control(struct mixer *mixer, unsigned int id)
printf("\n");
}
+static void tinymix_set_value(struct mixer *mixer, unsigned int id,
+ char *string)
+{
+ struct mixer_ctl *ctl;
+ enum mixer_ctl_type type;
+ unsigned int num_values;
+ unsigned int i;
+
+ ctl = mixer_get_ctl(mixer, id);
+ type = mixer_ctl_get_type(ctl);
+ num_values = mixer_ctl_get_num_values(ctl);
+
+ if (isdigit(string[0])) {
+ int value = atoi(string);
+
+ for (i = 0; i < num_values; i++) {
+ if (mixer_ctl_set_value(ctl, i, value)) {
+ fprintf(stderr, "Error: invalid value\n");
+ return;
+ }
+ }
+ } else {
+ if (type == MIXER_CTL_TYPE_ENUM) {
+ if (mixer_ctl_set_enum_by_string(ctl, string))
+ fprintf(stderr, "Error: invalid enum value\n");
+ } else {
+ fprintf(stderr, "Error: only enum types can be set with strings\n");
+ }
+ }
+}
+