CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
orangepi-xunlong

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.

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