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 35static void tinymix_list_controls(struct mixer *mixer); 36static void tinymix_detail_control(struct mixer *mixer, const char *control, 37 int print_all); 38static void tinymix_set_value(struct mixer *mixer, const char *control, 39 char **values, unsigned int num_values); 40static void tinymix_print_enum(struct mixer_ctl *ctl, int print_all); 41 42int 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 81static 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 104static 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 122static 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 178static 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