1 /* tinymix.c
2 **
3 ** Copyright 2011, The Android Open Source Project
4 **
5 ** Redistribution and use in source and binary forms, with or without
6 ** modification, are permitted provided that the following conditions are met:
7 ** * Redistributions of source code must retain the above copyright
8 ** notice, this list of conditions and the following disclaimer.
9 ** * Redistributions in binary form must reproduce the above copyright
10 ** notice, this list of conditions and the following disclaimer in the
11 ** documentation and/or other materials provided with the distribution.
12 ** * Neither the name of The Android Open Source Project nor the names of
13 ** its contributors may be used to endorse or promote products derived
14 ** from this software without specific prior written permission.
15 **
16 ** THIS SOFTWARE IS PROVIDED BY The Android Open Source Project ``AS IS'' AND
17 ** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 ** ARE DISCLAIMED. IN NO EVENT SHALL The Android Open Source Project BE LIABLE
20 ** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 ** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 ** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 ** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 ** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
26 ** DAMAGE.
27 */
28
29 #include <tinyalsa/asoundlib.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <ctype.h>
33 #include <string.h>
34
35 static void tinymix_list_controls(struct mixer *mixer);
36 static void tinymix_detail_control(struct mixer *mixer, const char *control,
37 int print_all);
38 static void tinymix_set_value(struct mixer *mixer, const char *control,
39 char **values, unsigned int num_values);
40 static void tinymix_print_enum(struct mixer_ctl *ctl, int print_all);
41
main(int argc,char ** argv)42 int main(int argc, char **argv)
43 {
44 struct mixer *mixer;
45 int card = 0;
46
47 if ((argc > 2) && (strcmp(argv[1], "-D") == 0)) {
48 argv++;
49 if (argv[1]) {
50 card = atoi(argv[1]);
51 argv++;
52 argc -= 2;
53 } else {
54 argc -= 1;
55 }
56 }
57
58 mixer = mixer_open(card);
59 if (!mixer) {
60 fprintf(stderr, "Failed to open mixer\n");
61 return EXIT_FAILURE;
62 }
63
64
65 if (argc == 1) {
66 printf("Mixer name: '%s'\n", mixer_get_name(mixer));
67 tinymix_list_controls(mixer);
68 } else if (argc == 2) {
69 tinymix_detail_control(mixer, argv[1], 1);
70 } else if (argc >= 3) {
71 tinymix_set_value(mixer, argv[1], &argv[2], argc - 2);
72 } else {
73 printf("Usage: tinymix [-D card] [control id] [value to set]\n");
74 }
75
76 mixer_close(mixer);
77
78 return 0;
79 }
80
tinymix_list_controls(struct mixer * mixer)81 static void tinymix_list_controls(struct mixer *mixer)
82 {
83 struct mixer_ctl *ctl;
84 const char *name, *type;
85 unsigned int num_ctls, num_values;
86 unsigned int i;
87
88 num_ctls = mixer_get_num_ctls(mixer);
89
90 printf("Number of controls: %d\n", num_ctls);
91
92 printf("ctl\ttype\tnum\t%-40s value\n", "name");
93 for (i = 0; i < num_ctls; i++) {
94 ctl = mixer_get_ctl(mixer, i);
95
96 name = mixer_ctl_get_name(ctl);
97 type = mixer_ctl_get_type_string(ctl);
98 num_values = mixer_ctl_get_num_values(ctl);
99 printf("%d\t%s\t%d\t%-40s", i, type, num_values, name);
100 tinymix_detail_control(mixer, name, 0);
101 }
102 }
103
tinymix_print_enum(struct mixer_ctl * ctl,int print_all)104 static void tinymix_print_enum(struct mixer_ctl *ctl, int print_all)
105 {
106 unsigned int num_enums;
107 unsigned int i;
108 const char *string;
109
110 num_enums = mixer_ctl_get_num_enums(ctl);
111
112 for (i = 0; i < num_enums; i++) {
113 string = mixer_ctl_get_enum_string(ctl, i);
114 if (print_all)
115 printf("\t%s%s", mixer_ctl_get_value(ctl, 0) == (int)i ? ">" : "",
116 string);
117 else if (mixer_ctl_get_value(ctl, 0) == (int)i)
118 printf(" %-s", string);
119 }
120 }
121
tinymix_detail_control(struct mixer * mixer,const char * control,int print_all)122 static void tinymix_detail_control(struct mixer *mixer, const char *control,
123 int print_all)
124 {
125 struct mixer_ctl *ctl;
126 enum mixer_ctl_type type;
127 unsigned int num_values;
128 unsigned int i;
129 int min, max;
130
131 if (isdigit(control[0]))
132 ctl = mixer_get_ctl(mixer, atoi(control));
133 else
134 ctl = mixer_get_ctl_by_name(mixer, control);
135
136 if (!ctl) {
137 fprintf(stderr, "Invalid mixer control\n");
138 return;
139 }
140
141 type = mixer_ctl_get_type(ctl);
142 num_values = mixer_ctl_get_num_values(ctl);
143
144 if (print_all)
145 printf("%s:", mixer_ctl_get_name(ctl));
146
147 for (i = 0; i < num_values; i++) {
148 switch (type)
149 {
150 case MIXER_CTL_TYPE_INT:
151 printf(" %d", mixer_ctl_get_value(ctl, i));
152 break;
153 case MIXER_CTL_TYPE_BOOL:
154 printf(" %s", mixer_ctl_get_value(ctl, i) ? "On" : "Off");
155 break;
156 case MIXER_CTL_TYPE_ENUM:
157 tinymix_print_enum(ctl, print_all);
158 break;
159 case MIXER_CTL_TYPE_BYTE:
160 printf(" 0x%02x", mixer_ctl_get_value(ctl, i));
161 break;
162 default:
163 printf(" unknown");
164 break;
165 };
166 }
167
168 if (print_all) {
169 if (type == MIXER_CTL_TYPE_INT) {
170 min = mixer_ctl_get_range_min(ctl);
171 max = mixer_ctl_get_range_max(ctl);
172 printf(" (range %d->%d)", min, max);
173 }
174 }
175 printf("\n");
176 }
177
tinymix_set_value(struct mixer * mixer,const char * control,char ** values,unsigned int num_values)178 static void tinymix_set_value(struct mixer *mixer, const char *control,
179 char **values, unsigned int num_values)
180 {
181 struct mixer_ctl *ctl;
182 enum mixer_ctl_type type;
183 unsigned int num_ctl_values;
184 unsigned int i;
185
186 if (isdigit(control[0]))
187 ctl = mixer_get_ctl(mixer, atoi(control));
188 else
189 ctl = mixer_get_ctl_by_name(mixer, control);
190
191 if (!ctl) {
192 fprintf(stderr, "Invalid mixer control\n");
193 return;
194 }
195
196 type = mixer_ctl_get_type(ctl);
197 num_ctl_values = mixer_ctl_get_num_values(ctl);
198
199 if (isdigit(values[0][0])) {
200 if (num_values == 1) {
201 /* Set all values the same */
202 int value = atoi(values[0]);
203
204 for (i = 0; i < num_ctl_values; i++) {
205 if (mixer_ctl_set_value(ctl, i, value)) {
206 fprintf(stderr, "Error: invalid value\n");
207 return;
208 }
209 }
210 } else {
211 /* Set multiple values */
212 if (num_values > num_ctl_values) {
213 fprintf(stderr,
214 "Error: %d values given, but control only takes %d\n",
215 num_values, num_ctl_values);
216 return;
217 }
218 for (i = 0; i < num_values; i++) {
219 if (mixer_ctl_set_value(ctl, i, atoi(values[i]))) {
220 fprintf(stderr, "Error: invalid value for index %d\n", i);
221 return;
222 }
223 }
224 }
225 } else {
226 if (type == MIXER_CTL_TYPE_ENUM) {
227 if (num_values != 1) {
228 fprintf(stderr, "Enclose strings in quotes and try again\n");
229 return;
230 }
231 if (mixer_ctl_set_enum_by_string(ctl, values[0]))
232 fprintf(stderr, "Error: invalid enum value\n");
233 } else {
234 fprintf(stderr, "Error: only enum types can be set with strings\n");
235 }
236 }
237 }
238
239