Home | History | Annotate | Download | only in tinyalsa
      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 <errno.h>
     31 #include <stdio.h>
     32 #include <stdlib.h>
     33 #include <ctype.h>
     34 #include <string.h>
     35 
     36 static void tinymix_list_controls(struct mixer *mixer);
     37 static void tinymix_detail_control(struct mixer *mixer, const char *control,
     38                                    int print_all);
     39 static void tinymix_set_value(struct mixer *mixer, const char *control,
     40                               char **values, unsigned int num_values);
     41 static void tinymix_print_enum(struct mixer_ctl *ctl, int print_all);
     42 
     43 int main(int argc, char **argv)
     44 {
     45     struct mixer *mixer;
     46     int card = 0;
     47 
     48     if ((argc > 2) && (strcmp(argv[1], "-D") == 0)) {
     49         argv++;
     50         if (argv[1]) {
     51             card = atoi(argv[1]);
     52             argv++;
     53             argc -= 2;
     54         } else {
     55             argc -= 1;
     56         }
     57     }
     58 
     59     mixer = mixer_open(card);
     60     if (!mixer) {
     61         fprintf(stderr, "Failed to open mixer\n");
     62         return EXIT_FAILURE;
     63     }
     64 
     65 
     66     if (argc == 1) {
     67         printf("Mixer name: '%s'\n", mixer_get_name(mixer));
     68         tinymix_list_controls(mixer);
     69     } else if (argc == 2) {
     70         tinymix_detail_control(mixer, argv[1], 1);
     71     } else if (argc >= 3) {
     72         tinymix_set_value(mixer, argv[1], &argv[2], argc - 2);
     73     } else {
     74         printf("Usage: tinymix [-D card] [control id] [value to set]\n");
     75     }
     76 
     77     mixer_close(mixer);
     78 
     79     return 0;
     80 }
     81 
     82 static void tinymix_list_controls(struct mixer *mixer)
     83 {
     84     struct mixer_ctl *ctl;
     85     const char *name, *type;
     86     unsigned int num_ctls, num_values;
     87     unsigned int i;
     88 
     89     num_ctls = mixer_get_num_ctls(mixer);
     90 
     91     printf("Number of controls: %d\n", num_ctls);
     92 
     93     printf("ctl\ttype\tnum\t%-40s value\n", "name");
     94     for (i = 0; i < num_ctls; i++) {
     95         ctl = mixer_get_ctl(mixer, i);
     96 
     97         name = mixer_ctl_get_name(ctl);
     98         type = mixer_ctl_get_type_string(ctl);
     99         num_values = mixer_ctl_get_num_values(ctl);
    100         printf("%d\t%s\t%d\t%-40s", i, type, num_values, name);
    101         tinymix_detail_control(mixer, name, 0);
    102     }
    103 }
    104 
    105 static void tinymix_print_enum(struct mixer_ctl *ctl, int print_all)
    106 {
    107     unsigned int num_enums;
    108     unsigned int i;
    109     const char *string;
    110 
    111     num_enums = mixer_ctl_get_num_enums(ctl);
    112 
    113     for (i = 0; i < num_enums; i++) {
    114         string = mixer_ctl_get_enum_string(ctl, i);
    115         if (print_all)
    116             printf("\t%s%s", mixer_ctl_get_value(ctl, 0) == (int)i ? ">" : "",
    117                    string);
    118         else if (mixer_ctl_get_value(ctl, 0) == (int)i)
    119             printf(" %-s", string);
    120     }
    121 }
    122 
    123 static void tinymix_detail_control(struct mixer *mixer, const char *control,
    124                                    int print_all)
    125 {
    126     struct mixer_ctl *ctl;
    127     enum mixer_ctl_type type;
    128     unsigned int num_values;
    129     unsigned int i;
    130     int min, max;
    131     int ret;
    132     char *buf = NULL;
    133     size_t len;
    134 
    135     if (isdigit(control[0]))
    136         ctl = mixer_get_ctl(mixer, atoi(control));
    137     else
    138         ctl = mixer_get_ctl_by_name(mixer, control);
    139 
    140     if (!ctl) {
    141         fprintf(stderr, "Invalid mixer control\n");
    142         return;
    143     }
    144 
    145     type = mixer_ctl_get_type(ctl);
    146     num_values = mixer_ctl_get_num_values(ctl);
    147 
    148     if (type == MIXER_CTL_TYPE_BYTE) {
    149 
    150         buf = calloc(1, num_values);
    151         if (buf == NULL) {
    152             fprintf(stderr, "Failed to alloc mem for bytes %d\n", num_values);
    153             return;
    154         }
    155 
    156         len = num_values;
    157         ret = mixer_ctl_get_array(ctl, buf, len);
    158         if (ret < 0) {
    159             fprintf(stderr, "Failed to mixer_ctl_get_array\n");
    160             free(buf);
    161             return;
    162         }
    163     }
    164 
    165     if (print_all)
    166         printf("%s:", mixer_ctl_get_name(ctl));
    167 
    168     for (i = 0; i < num_values; i++) {
    169         switch (type)
    170         {
    171         case MIXER_CTL_TYPE_INT:
    172             printf(" %d", mixer_ctl_get_value(ctl, i));
    173             break;
    174         case MIXER_CTL_TYPE_BOOL:
    175             printf(" %s", mixer_ctl_get_value(ctl, i) ? "On" : "Off");
    176             break;
    177         case MIXER_CTL_TYPE_ENUM:
    178             tinymix_print_enum(ctl, print_all);
    179             break;
    180         case MIXER_CTL_TYPE_BYTE:
    181             printf("%02x", buf[i]);
    182             break;
    183         default:
    184             printf(" unknown");
    185             break;
    186         };
    187     }
    188 
    189     if (print_all) {
    190         if (type == MIXER_CTL_TYPE_INT) {
    191             min = mixer_ctl_get_range_min(ctl);
    192             max = mixer_ctl_get_range_max(ctl);
    193             printf(" (range %d->%d)", min, max);
    194         }
    195     }
    196 
    197     free(buf);
    198 
    199     printf("\n");
    200 }
    201 
    202 static void tinymix_set_byte_ctl(struct mixer_ctl *ctl,
    203     char **values, unsigned int num_values)
    204 {
    205     int ret;
    206     char *buf;
    207     char *end;
    208     unsigned int i;
    209     long n;
    210 
    211     buf = calloc(1, num_values);
    212     if (buf == NULL) {
    213         fprintf(stderr, "set_byte_ctl: Failed to alloc mem for bytes %d\n", num_values);
    214         exit(EXIT_FAILURE);
    215     }
    216 
    217     for (i = 0; i < num_values; i++) {
    218         errno = 0;
    219         n = strtol(values[i], &end, 0);
    220         if (*end) {
    221             fprintf(stderr, "%s not an integer\n", values[i]);
    222             goto fail;
    223         }
    224         if (errno) {
    225             fprintf(stderr, "strtol: %s: %s\n", values[i],
    226                 strerror(errno));
    227             goto fail;
    228         }
    229         if (n < 0 || n > 0xff) {
    230             fprintf(stderr, "%s should be between [0, 0xff]\n",
    231                 values[i]);
    232             goto fail;
    233         }
    234         buf[i] = n;
    235     }
    236 
    237     ret = mixer_ctl_set_array(ctl, buf, num_values);
    238     if (ret < 0) {
    239         fprintf(stderr, "Failed to set binary control\n");
    240         goto fail;
    241     }
    242 
    243     free(buf);
    244     return;
    245 
    246 fail:
    247     free(buf);
    248     exit(EXIT_FAILURE);
    249 }
    250 
    251 static void tinymix_set_value(struct mixer *mixer, const char *control,
    252                               char **values, unsigned int num_values)
    253 {
    254     struct mixer_ctl *ctl;
    255     enum mixer_ctl_type type;
    256     unsigned int num_ctl_values;
    257     unsigned int i;
    258 
    259     if (isdigit(control[0]))
    260         ctl = mixer_get_ctl(mixer, atoi(control));
    261     else
    262         ctl = mixer_get_ctl_by_name(mixer, control);
    263 
    264     if (!ctl) {
    265         fprintf(stderr, "Invalid mixer control\n");
    266         return;
    267     }
    268 
    269     type = mixer_ctl_get_type(ctl);
    270     num_ctl_values = mixer_ctl_get_num_values(ctl);
    271 
    272     if (type == MIXER_CTL_TYPE_BYTE) {
    273         tinymix_set_byte_ctl(ctl, values, num_values);
    274         return;
    275     }
    276 
    277     if (isdigit(values[0][0])) {
    278         if (num_values == 1) {
    279             /* Set all values the same */
    280             int value = atoi(values[0]);
    281 
    282             for (i = 0; i < num_ctl_values; i++) {
    283                 if (mixer_ctl_set_value(ctl, i, value)) {
    284                     fprintf(stderr, "Error: invalid value\n");
    285                     return;
    286                 }
    287             }
    288         } else {
    289             /* Set multiple values */
    290             if (num_values > num_ctl_values) {
    291                 fprintf(stderr,
    292                         "Error: %d values given, but control only takes %d\n",
    293                         num_values, num_ctl_values);
    294                 return;
    295             }
    296             for (i = 0; i < num_values; i++) {
    297                 if (mixer_ctl_set_value(ctl, i, atoi(values[i]))) {
    298                     fprintf(stderr, "Error: invalid value for index %d\n", i);
    299                     return;
    300                 }
    301             }
    302         }
    303     } else {
    304         if (type == MIXER_CTL_TYPE_ENUM) {
    305             if (num_values != 1) {
    306                 fprintf(stderr, "Enclose strings in quotes and try again\n");
    307                 return;
    308             }
    309             if (mixer_ctl_set_enum_by_string(ctl, values[0]))
    310                 fprintf(stderr, "Error: invalid enum value\n");
    311         } else {
    312             fprintf(stderr, "Error: only enum types can be set with strings\n");
    313         }
    314     }
    315 }
    316 
    317