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