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