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 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 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 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 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 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