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 34static void tinymix_list_controls(struct mixer *mixer); 35static void tinymix_detail_control(struct mixer *mixer, unsigned int id, 36 int print_all); 37static void tinymix_set_value(struct mixer *mixer, unsigned int id, 38 char *value); 39static void tinymix_print_enum(struct mixer_ctl *ctl, int print_all); 40 41int main(int argc, char **argv) 42{ 43 struct mixer *mixer; 44 int card = 0; 45 46 if ((argc > 2) && (strcmp(argv[1], "-D") == 0)) { 47 argv++; 48 if (argv[1]) { 49 card = atoi(argv[1]); 50 argv++; 51 argc -= 2; 52 } else { 53 argc -= 1; 54 } 55 } 56 57 mixer = mixer_open(card); 58 if (!mixer) { 59 fprintf(stderr, "Failed to open mixer\n"); 60 return EXIT_FAILURE; 61 } 62 63 if (argc == 1) 64 tinymix_list_controls(mixer); 65 else if (argc == 2) 66 tinymix_detail_control(mixer, atoi(argv[1]), 1); 67 else if (argc == 3) 68 tinymix_set_value(mixer, atoi(argv[1]), argv[2]); 69 else 70 printf("Usage: tinymix [-D card] [control id] [value to set]\n"); 71 72 mixer_close(mixer); 73 74 return 0; 75} 76 77static void tinymix_list_controls(struct mixer *mixer) 78{ 79 struct mixer_ctl *ctl; 80 const char *name, *type; 81 unsigned int num_ctls, num_values; 82 unsigned int i; 83 84 num_ctls = mixer_get_num_ctls(mixer); 85 86 printf("Number of controls: %d\n", num_ctls); 87 88 printf("ctl\ttype\tnum\t%-40s value\n", "name"); 89 for (i = 0; i < num_ctls; i++) { 90 ctl = mixer_get_ctl(mixer, i); 91 92 name = mixer_ctl_get_name(ctl); 93 type = mixer_ctl_get_type_string(ctl); 94 num_values = mixer_ctl_get_num_values(ctl); 95 printf("%d\t%s\t%d\t%-40s", i, type, num_values, name); 96 tinymix_detail_control(mixer, i, 0); 97 } 98} 99 100static void tinymix_print_enum(struct mixer_ctl *ctl, int print_all) 101{ 102 unsigned int num_enums; 103 unsigned int i; 104 const char *string; 105 106 num_enums = mixer_ctl_get_num_enums(ctl); 107 108 for (i = 0; i < num_enums; i++) { 109 string = mixer_ctl_get_enum_string(ctl, i); 110 if (print_all) 111 printf("\t%s%s", mixer_ctl_get_value(ctl, 0) == (int)i ? ">" : "", 112 string); 113 else if (mixer_ctl_get_value(ctl, 0) == (int)i) 114 printf(" %-s", string); 115 } 116} 117 118static void tinymix_detail_control(struct mixer *mixer, unsigned int id, 119 int print_all) 120{ 121 struct mixer_ctl *ctl; 122 enum mixer_ctl_type type; 123 unsigned int num_values; 124 unsigned int i; 125 int min, max; 126 127 if (id >= mixer_get_num_ctls(mixer)) { 128 fprintf(stderr, "Invalid mixer control\n"); 129 return; 130 } 131 132 ctl = mixer_get_ctl(mixer, id); 133 134 type = mixer_ctl_get_type(ctl); 135 num_values = mixer_ctl_get_num_values(ctl); 136 137 if (print_all) 138 printf("%s:", mixer_ctl_get_name(ctl)); 139 140 for (i = 0; i < num_values; i++) { 141 switch (type) 142 { 143 case MIXER_CTL_TYPE_INT: 144 printf(" %d", mixer_ctl_get_value(ctl, i)); 145 break; 146 case MIXER_CTL_TYPE_BOOL: 147 printf(" %s", mixer_ctl_get_value(ctl, i) ? "On" : "Off"); 148 break; 149 case MIXER_CTL_TYPE_ENUM: 150 tinymix_print_enum(ctl, print_all); 151 break; 152 case MIXER_CTL_TYPE_BYTE: 153 printf(" 0x%02x", mixer_ctl_get_value(ctl, i)); 154 break; 155 default: 156 printf(" unknown"); 157 break; 158 }; 159 } 160 161 if (print_all) { 162 if (type == MIXER_CTL_TYPE_INT) { 163 min = mixer_ctl_get_range_min(ctl); 164 max = mixer_ctl_get_range_max(ctl); 165 printf(" (range %d->%d)", min, max); 166 } 167 } 168 printf("\n"); 169} 170 171static void tinymix_set_value(struct mixer *mixer, unsigned int id, 172 char *string) 173{ 174 struct mixer_ctl *ctl; 175 enum mixer_ctl_type type; 176 unsigned int num_values; 177 unsigned int i; 178 179 ctl = mixer_get_ctl(mixer, id); 180 type = mixer_ctl_get_type(ctl); 181 num_values = mixer_ctl_get_num_values(ctl); 182 183 if (isdigit(string[0])) { 184 int value = atoi(string); 185 186 for (i = 0; i < num_values; i++) { 187 if (mixer_ctl_set_value(ctl, i, value)) { 188 fprintf(stderr, "Error: invalid value\n"); 189 return; 190 } 191 } 192 } else { 193 if (type == MIXER_CTL_TYPE_ENUM) { 194 if (mixer_ctl_set_enum_by_string(ctl, string)) 195 fprintf(stderr, "Error: invalid enum value\n"); 196 } else { 197 fprintf(stderr, "Error: only enum types can be set with strings\n"); 198 } 199 } 200} 201 202