1 |
|
|
/* $OpenBSD: radioctl.c,v 1.19 2013/12/21 06:54:53 guenther Exp $ */ |
2 |
|
|
/* $RuOBSD: radioctl.c,v 1.4 2001/10/20 18:09:10 pva Exp $ */ |
3 |
|
|
|
4 |
|
|
/* |
5 |
|
|
* Copyright (c) 2001 Vladimir Popov <jumbo@narod.ru> |
6 |
|
|
* All rights reserved. |
7 |
|
|
* |
8 |
|
|
* Redistribution and use in source and binary forms, with or without |
9 |
|
|
* modification, are permitted provided that the following conditions |
10 |
|
|
* are met: |
11 |
|
|
* 1. Redistributions of source code must retain the above copyright |
12 |
|
|
* notice, this list of conditions and the following disclaimer. |
13 |
|
|
* 2. Redistributions in binary form must reproduce the above copyright |
14 |
|
|
* notice, this list of conditions and the following disclaimer in the |
15 |
|
|
* documentation and/or other materials provided with the distribution. |
16 |
|
|
* |
17 |
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
18 |
|
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
19 |
|
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
20 |
|
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
21 |
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
22 |
|
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; |
23 |
|
|
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
24 |
|
|
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
25 |
|
|
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
26 |
|
|
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 |
|
|
*/ |
28 |
|
|
|
29 |
|
|
#include <sys/ioctl.h> |
30 |
|
|
#include <sys/radioio.h> |
31 |
|
|
|
32 |
|
|
#include <dev/ic/bt8xx.h> |
33 |
|
|
|
34 |
|
|
#include <err.h> |
35 |
|
|
#include <fcntl.h> |
36 |
|
|
#include <stdio.h> |
37 |
|
|
#include <stdlib.h> |
38 |
|
|
#include <string.h> |
39 |
|
|
#include <unistd.h> |
40 |
|
|
#include <ctype.h> |
41 |
|
|
|
42 |
|
|
#define RADIO_ENV "RADIODEVICE" |
43 |
|
|
#define RADIODEVICE "/dev/radio" |
44 |
|
|
|
45 |
|
|
const char *varname[] = { |
46 |
|
|
"search", |
47 |
|
|
#define OPTION_SEARCH 0x00 |
48 |
|
|
"volume", |
49 |
|
|
#define OPTION_VOLUME 0x01 |
50 |
|
|
"frequency", |
51 |
|
|
#define OPTION_FREQUENCY 0x02 |
52 |
|
|
"mute", |
53 |
|
|
#define OPTION_MUTE 0x03 |
54 |
|
|
"reference", |
55 |
|
|
#define OPTION_REFERENCE 0x04 |
56 |
|
|
"mono", |
57 |
|
|
#define OPTION_MONO 0x05 |
58 |
|
|
"stereo", |
59 |
|
|
#define OPTION_STEREO 0x06 |
60 |
|
|
"sensitivity", |
61 |
|
|
#define OPTION_SENSITIVITY 0x07 |
62 |
|
|
"channel", |
63 |
|
|
#define OPTION_CHANNEL 0x08 |
64 |
|
|
"chnlset" |
65 |
|
|
#define OPTION_CHNLSET 0x09 |
66 |
|
|
}; |
67 |
|
|
|
68 |
|
|
#define OPTION_NONE ~0u |
69 |
|
|
#define VALUE_NONE ~0u |
70 |
|
|
|
71 |
|
|
struct opt_t { |
72 |
|
|
char *string; |
73 |
|
|
int option; |
74 |
|
|
int sign; |
75 |
|
|
#define SIGN_NONE 0 |
76 |
|
|
#define SIGN_PLUS 1 |
77 |
|
|
#define SIGN_MINUS -1 |
78 |
|
|
u_int32_t value; |
79 |
|
|
}; |
80 |
|
|
|
81 |
|
|
struct chansets { |
82 |
|
|
int value; |
83 |
|
|
char *name; |
84 |
|
|
} chansets[] = { |
85 |
|
|
{ CHNLSET_NABCST, "nabcst", }, |
86 |
|
|
{ CHNLSET_CABLEIRC, "cableirc", }, |
87 |
|
|
{ CHNLSET_CABLEHRC, "cablehrc", }, |
88 |
|
|
{ CHNLSET_WEUROPE, "weurope", }, |
89 |
|
|
{ CHNLSET_JPNBCST, "jpnbcst", }, |
90 |
|
|
{ CHNLSET_JPNCABLE, "jpncable", }, |
91 |
|
|
{ CHNLSET_XUSSR, "xussr", }, |
92 |
|
|
{ CHNLSET_AUSTRALIA, "australia", }, |
93 |
|
|
{ CHNLSET_FRANCE, "france", }, |
94 |
|
|
{ 0, NULL } |
95 |
|
|
}; |
96 |
|
|
|
97 |
|
|
extern char *__progname; |
98 |
|
|
const char *onchar = "on"; |
99 |
|
|
#define ONCHAR_LEN 2 |
100 |
|
|
const char *offchar = "off"; |
101 |
|
|
#define OFFCHAR_LEN 3 |
102 |
|
|
|
103 |
|
|
struct radio_info ri; |
104 |
|
|
unsigned int i = 0; |
105 |
|
|
|
106 |
|
|
int parse_opt(char *, struct opt_t *); |
107 |
|
|
|
108 |
|
|
void print_vars(int, int); |
109 |
|
|
void do_ioctls(int, struct opt_t *, int); |
110 |
|
|
|
111 |
|
|
void print_value(int, int); |
112 |
|
|
void change_value(const struct opt_t); |
113 |
|
|
void update_value(int, int *, int); |
114 |
|
|
|
115 |
|
|
void warn_unsupported(int); |
116 |
|
|
void usage(void); |
117 |
|
|
|
118 |
|
|
void show_verbose(const char *, int); |
119 |
|
|
void show_int_val(int, const char *, char *, int); |
120 |
|
|
void show_float_val(float, const char *, char *, int); |
121 |
|
|
void show_char_val(const char *, const char *, int); |
122 |
|
|
int str_to_opt(const char *); |
123 |
|
|
u_int str_to_int(char *, int); |
124 |
|
|
|
125 |
|
|
/* |
126 |
|
|
* Control behavior of a FM tuner - set frequency, volume etc |
127 |
|
|
*/ |
128 |
|
|
int |
129 |
|
|
main(int argc, char **argv) |
130 |
|
|
{ |
131 |
|
|
struct opt_t opt; |
132 |
|
|
char **avp; |
133 |
|
|
|
134 |
|
|
char *radiodev = NULL; |
135 |
|
|
int rd = -1; |
136 |
|
|
int optchar; |
137 |
|
|
int show_vars = 0; |
138 |
|
|
int show_choices = 0; |
139 |
|
|
int silent = 0; |
140 |
|
|
int mode = O_RDONLY; |
141 |
|
|
|
142 |
|
|
radiodev = getenv(RADIO_ENV); |
143 |
|
|
if (radiodev == NULL) |
144 |
|
|
radiodev = RADIODEVICE; |
145 |
|
|
|
146 |
|
|
while ((optchar = getopt(argc, argv, "af:nvw")) != -1) { |
147 |
|
|
switch (optchar) { |
148 |
|
|
case 'a': |
149 |
|
|
show_vars = 1; |
150 |
|
|
break; |
151 |
|
|
case 'f': |
152 |
|
|
radiodev = optarg; |
153 |
|
|
break; |
154 |
|
|
case 'n': |
155 |
|
|
silent = 1; |
156 |
|
|
break; |
157 |
|
|
case 'v': |
158 |
|
|
show_choices = 1; |
159 |
|
|
break; |
160 |
|
|
case 'w': |
161 |
|
|
/* backwards compatibility */ |
162 |
|
|
break; |
163 |
|
|
default: |
164 |
|
|
usage(); |
165 |
|
|
/* NOTREACHED */ |
166 |
|
|
} |
167 |
|
|
} |
168 |
|
|
|
169 |
|
|
argc -= optind; |
170 |
|
|
argv += optind; |
171 |
|
|
|
172 |
|
|
if (argc == 0) |
173 |
|
|
show_vars = 1; |
174 |
|
|
|
175 |
|
|
/* |
176 |
|
|
* Scan the options for `name=value` so the |
177 |
|
|
* device can be opened in the proper mode. |
178 |
|
|
*/ |
179 |
|
|
for (avp = argv; *avp != NULL; avp++) |
180 |
|
|
if (strchr(*avp, '=') != NULL) { |
181 |
|
|
mode = O_RDWR; |
182 |
|
|
break; |
183 |
|
|
} |
184 |
|
|
|
185 |
|
|
rd = open(radiodev, mode); |
186 |
|
|
if (rd < 0) |
187 |
|
|
err(1, "%s open error", radiodev); |
188 |
|
|
|
189 |
|
|
if (ioctl(rd, RIOCGINFO, &ri) < 0) |
190 |
|
|
err(1, "RIOCGINFO"); |
191 |
|
|
|
192 |
|
|
if (!argc && show_vars) |
193 |
|
|
print_vars(silent, show_choices); |
194 |
|
|
else if (argc > 0 && !show_vars) { |
195 |
|
|
if (mode == O_RDWR) { |
196 |
|
|
for (; argc--; argv++) |
197 |
|
|
if (parse_opt(*argv, &opt)) |
198 |
|
|
do_ioctls(rd, &opt, silent); |
199 |
|
|
} else { |
200 |
|
|
for (; argc--; argv++) |
201 |
|
|
if (parse_opt(*argv, &opt)) { |
202 |
|
|
show_verbose(varname[opt.option], |
203 |
|
|
silent); |
204 |
|
|
print_value(opt.option, show_choices); |
205 |
|
|
free(opt.string); |
206 |
|
|
putchar('\n'); |
207 |
|
|
} |
208 |
|
|
} |
209 |
|
|
} |
210 |
|
|
|
211 |
|
|
if (close(rd) < 0) |
212 |
|
|
warn("%s close error", radiodev); |
213 |
|
|
|
214 |
|
|
return 0; |
215 |
|
|
} |
216 |
|
|
|
217 |
|
|
void |
218 |
|
|
usage(void) |
219 |
|
|
{ |
220 |
|
|
fprintf(stderr, |
221 |
|
|
"usage: %s [-anv] [-f file]\n" |
222 |
|
|
" %s [-nv] [-f file] name\n" |
223 |
|
|
" %s [-n] [-f file] name=value\n", |
224 |
|
|
__progname, __progname, __progname); |
225 |
|
|
exit(1); |
226 |
|
|
} |
227 |
|
|
|
228 |
|
|
void |
229 |
|
|
show_verbose(const char *nick, int silent) |
230 |
|
|
{ |
231 |
|
|
if (!silent) |
232 |
|
|
printf("%s=", nick); |
233 |
|
|
} |
234 |
|
|
|
235 |
|
|
void |
236 |
|
|
warn_unsupported(int optval) |
237 |
|
|
{ |
238 |
|
|
warnx("driver does not support `%s'", varname[optval]); |
239 |
|
|
} |
240 |
|
|
|
241 |
|
|
void |
242 |
|
|
do_ioctls(int fd, struct opt_t *o, int silent) |
243 |
|
|
{ |
244 |
|
|
int oval; |
245 |
|
|
|
246 |
|
|
if (fd < 0 || o == NULL) |
247 |
|
|
return; |
248 |
|
|
|
249 |
|
|
if (o->option == OPTION_SEARCH && !(ri.caps & RADIO_CAPS_HW_SEARCH)) { |
250 |
|
|
warn_unsupported(o->option); |
251 |
|
|
return; |
252 |
|
|
} |
253 |
|
|
|
254 |
|
|
oval = o->option == OPTION_SEARCH ? OPTION_FREQUENCY : o->option; |
255 |
|
|
if (!silent) |
256 |
|
|
printf("%s: ", varname[oval]); |
257 |
|
|
|
258 |
|
|
print_value(o->option, 0); |
259 |
|
|
printf(" -> "); |
260 |
|
|
|
261 |
|
|
if (o->option == OPTION_SEARCH) { |
262 |
|
|
|
263 |
|
|
if (ioctl(fd, RIOCSSRCH, &o->value) < 0) { |
264 |
|
|
warn("RIOCSSRCH"); |
265 |
|
|
return; |
266 |
|
|
} |
267 |
|
|
|
268 |
|
|
} else { |
269 |
|
|
|
270 |
|
|
change_value(*o); |
271 |
|
|
if (ioctl(fd, RIOCSINFO, &ri) < 0) { |
272 |
|
|
warn("RIOCSINFO"); |
273 |
|
|
return; |
274 |
|
|
} |
275 |
|
|
|
276 |
|
|
} |
277 |
|
|
|
278 |
|
|
if (ioctl(fd, RIOCGINFO, &ri) < 0) { |
279 |
|
|
warn("RIOCGINFO"); |
280 |
|
|
return; |
281 |
|
|
} |
282 |
|
|
|
283 |
|
|
print_value(o->option, 0); |
284 |
|
|
putchar('\n'); |
285 |
|
|
} |
286 |
|
|
|
287 |
|
|
void |
288 |
|
|
change_value(const struct opt_t o) |
289 |
|
|
{ |
290 |
|
|
int unsupported = 0; |
291 |
|
|
|
292 |
|
|
if (o.value == VALUE_NONE) |
293 |
|
|
return; |
294 |
|
|
|
295 |
|
|
switch (o.option) { |
296 |
|
|
case OPTION_VOLUME: |
297 |
|
|
update_value(o.sign, &ri.volume, o.value); |
298 |
|
|
break; |
299 |
|
|
case OPTION_FREQUENCY: |
300 |
|
|
ri.tuner_mode = RADIO_TUNER_MODE_RADIO; |
301 |
|
|
update_value(o.sign, &ri.freq, o.value); |
302 |
|
|
break; |
303 |
|
|
case OPTION_REFERENCE: |
304 |
|
|
if (ri.caps & RADIO_CAPS_REFERENCE_FREQ) |
305 |
|
|
update_value(o.sign, &ri.rfreq, o.value); |
306 |
|
|
else |
307 |
|
|
unsupported++; |
308 |
|
|
break; |
309 |
|
|
case OPTION_MONO: |
310 |
|
|
/* FALLTHROUGH */ |
311 |
|
|
case OPTION_STEREO: |
312 |
|
|
if (ri.caps & RADIO_CAPS_SET_MONO) |
313 |
|
|
ri.stereo = o.option == OPTION_MONO ? !o.value : o.value; |
314 |
|
|
else |
315 |
|
|
unsupported++; |
316 |
|
|
break; |
317 |
|
|
case OPTION_SENSITIVITY: |
318 |
|
|
if (ri.caps & RADIO_CAPS_LOCK_SENSITIVITY) |
319 |
|
|
update_value(o.sign, &ri.lock, o.value); |
320 |
|
|
else |
321 |
|
|
unsupported++; |
322 |
|
|
break; |
323 |
|
|
case OPTION_MUTE: |
324 |
|
|
ri.mute = o.value; |
325 |
|
|
break; |
326 |
|
|
case OPTION_CHANNEL: |
327 |
|
|
ri.tuner_mode = RADIO_TUNER_MODE_TV; |
328 |
|
|
update_value(o.sign, &ri.chan, o.value); |
329 |
|
|
break; |
330 |
|
|
case OPTION_CHNLSET: |
331 |
|
|
ri.chnlset = o.value; |
332 |
|
|
break; |
333 |
|
|
} |
334 |
|
|
|
335 |
|
|
if (unsupported) |
336 |
|
|
warn_unsupported(o.option); |
337 |
|
|
} |
338 |
|
|
|
339 |
|
|
/* |
340 |
|
|
* Convert string to integer representation of a parameter |
341 |
|
|
*/ |
342 |
|
|
int |
343 |
|
|
str_to_opt(const char *topt) |
344 |
|
|
{ |
345 |
|
|
int res, toptlen, varlen, len, varsize; |
346 |
|
|
|
347 |
|
|
if (topt == NULL || *topt == '\0') |
348 |
|
|
return OPTION_NONE; |
349 |
|
|
|
350 |
|
|
varsize = sizeof(varname) / sizeof(varname[0]); |
351 |
|
|
toptlen = strlen(topt); |
352 |
|
|
|
353 |
|
|
for (res = 0; res < varsize; res++) { |
354 |
|
|
varlen = strlen(varname[res]); |
355 |
|
|
len = toptlen > varlen ? toptlen : varlen; |
356 |
|
|
if (strncmp(topt, varname[res], len) == 0) |
357 |
|
|
return res; |
358 |
|
|
} |
359 |
|
|
|
360 |
|
|
warnx("bad name `%s'", topt); |
361 |
|
|
return OPTION_NONE; |
362 |
|
|
} |
363 |
|
|
|
364 |
|
|
void |
365 |
|
|
update_value(int sign, int *value, int update) |
366 |
|
|
{ |
367 |
|
|
switch (sign) { |
368 |
|
|
case SIGN_NONE: |
369 |
|
|
*value = update; |
370 |
|
|
break; |
371 |
|
|
case SIGN_PLUS: |
372 |
|
|
*value += update; |
373 |
|
|
break; |
374 |
|
|
case SIGN_MINUS: |
375 |
|
|
*value -= update; |
376 |
|
|
break; |
377 |
|
|
} |
378 |
|
|
} |
379 |
|
|
|
380 |
|
|
/* |
381 |
|
|
* Convert string to unsigned integer |
382 |
|
|
*/ |
383 |
|
|
u_int |
384 |
|
|
str_to_int(char *str, int optval) |
385 |
|
|
{ |
386 |
|
|
int val; |
387 |
|
|
|
388 |
|
|
if (str == NULL || *str == '\0') |
389 |
|
|
return VALUE_NONE; |
390 |
|
|
|
391 |
|
|
if (optval == OPTION_FREQUENCY) |
392 |
|
|
val = (int)(1000 * atof(str)); |
393 |
|
|
else |
394 |
|
|
val = (int)strtol(str, (char **)NULL, 10); |
395 |
|
|
|
396 |
|
|
return val; |
397 |
|
|
} |
398 |
|
|
|
399 |
|
|
/* |
400 |
|
|
* parse string s into struct opt_t |
401 |
|
|
* return true on success, false on failure |
402 |
|
|
*/ |
403 |
|
|
int |
404 |
|
|
parse_opt(char *s, struct opt_t *o) { |
405 |
|
|
static const char badvalue[] = "bad value `%s'"; |
406 |
|
|
char *topt = NULL; |
407 |
|
|
int slen, optlen; |
408 |
|
|
|
409 |
|
|
if (s == NULL || *s == '\0' || o == NULL) |
410 |
|
|
return 0; |
411 |
|
|
|
412 |
|
|
o->string = NULL; |
413 |
|
|
o->option = OPTION_NONE; |
414 |
|
|
o->value = VALUE_NONE; |
415 |
|
|
o->sign = SIGN_NONE; |
416 |
|
|
|
417 |
|
|
slen = strlen(s); |
418 |
|
|
optlen = strcspn(s, "="); |
419 |
|
|
|
420 |
|
|
/* Set only o->optval, the rest is missing */ |
421 |
|
|
if (slen == optlen) { |
422 |
|
|
o->option = str_to_opt(s); |
423 |
|
|
return o->option == OPTION_NONE ? 0 : 1; |
424 |
|
|
} |
425 |
|
|
|
426 |
|
|
if (optlen > slen - 2) { |
427 |
|
|
warnx(badvalue, s); |
428 |
|
|
return 0; |
429 |
|
|
} |
430 |
|
|
|
431 |
|
|
slen -= ++optlen; |
432 |
|
|
|
433 |
|
|
if ((topt = malloc(optlen)) == NULL) { |
434 |
|
|
warn("memory allocation error"); |
435 |
|
|
return 0; |
436 |
|
|
} |
437 |
|
|
strlcpy(topt, s, optlen); |
438 |
|
|
|
439 |
|
|
if ((o->option = str_to_opt(topt)) == OPTION_NONE) { |
440 |
|
|
free(topt); |
441 |
|
|
return 0; |
442 |
|
|
} |
443 |
|
|
o->string = topt; |
444 |
|
|
|
445 |
|
|
topt = &s[optlen]; |
446 |
|
|
|
447 |
|
|
if (strcmp(o->string, "chnlset") == 0) { |
448 |
|
|
for (i = 0; chansets[i].name; i++) |
449 |
|
|
if (strncmp(chansets[i].name, topt, |
450 |
|
|
strlen(chansets[i].name)) == 0) |
451 |
|
|
break; |
452 |
|
|
if (chansets[i].name != NULL) { |
453 |
|
|
o->value = chansets[i].value; |
454 |
|
|
return 1; |
455 |
|
|
} else { |
456 |
|
|
warnx(badvalue, topt); |
457 |
|
|
return 0; |
458 |
|
|
} |
459 |
|
|
} |
460 |
|
|
|
461 |
|
|
switch (*topt) { |
462 |
|
|
case '+': |
463 |
|
|
case '-': |
464 |
|
|
o->sign = (*topt == '+') ? SIGN_PLUS : SIGN_MINUS; |
465 |
|
|
o->value = str_to_int(&topt[1], o->option); |
466 |
|
|
break; |
467 |
|
|
case 'o': |
468 |
|
|
if (strncmp(topt, offchar, |
469 |
|
|
slen > OFFCHAR_LEN ? slen : OFFCHAR_LEN) == 0) |
470 |
|
|
o->value = 0; |
471 |
|
|
else if (strncmp(topt, onchar, |
472 |
|
|
slen > ONCHAR_LEN ? slen : ONCHAR_LEN) == 0) |
473 |
|
|
o->value = 1; |
474 |
|
|
break; |
475 |
|
|
case 'u': |
476 |
|
|
if (strncmp(topt, "up", slen > 2 ? slen : 2) == 0) |
477 |
|
|
o->value = 1; |
478 |
|
|
break; |
479 |
|
|
case 'd': |
480 |
|
|
if (strncmp(topt, "down", slen > 4 ? slen : 4) == 0) |
481 |
|
|
o->value = 0; |
482 |
|
|
break; |
483 |
|
|
default: |
484 |
|
|
if (isdigit((unsigned char)*topt)) |
485 |
|
|
o->value = str_to_int(topt, o->option); |
486 |
|
|
break; |
487 |
|
|
} |
488 |
|
|
|
489 |
|
|
if (o->value == VALUE_NONE) { |
490 |
|
|
warnx(badvalue, topt); |
491 |
|
|
return 0; |
492 |
|
|
} |
493 |
|
|
|
494 |
|
|
return 1; |
495 |
|
|
} |
496 |
|
|
|
497 |
|
|
/* |
498 |
|
|
* Print current value of the parameter. |
499 |
|
|
*/ |
500 |
|
|
void |
501 |
|
|
print_value(int optval, int show_choices) |
502 |
|
|
{ |
503 |
|
|
if (optval == OPTION_NONE) |
504 |
|
|
return; |
505 |
|
|
|
506 |
|
|
switch (optval) { |
507 |
|
|
case OPTION_SEARCH: |
508 |
|
|
/* FALLTHROUGH */ |
509 |
|
|
case OPTION_FREQUENCY: |
510 |
|
|
printf("%.2fMHz", (float)ri.freq / 1000.); |
511 |
|
|
break; |
512 |
|
|
case OPTION_REFERENCE: |
513 |
|
|
printf("%ukHz", ri.rfreq); |
514 |
|
|
break; |
515 |
|
|
case OPTION_SENSITIVITY: |
516 |
|
|
printf("%umkV", ri.lock); |
517 |
|
|
break; |
518 |
|
|
case OPTION_MUTE: |
519 |
|
|
printf("%s", ri.mute ? onchar : offchar); |
520 |
|
|
break; |
521 |
|
|
case OPTION_MONO: |
522 |
|
|
printf("%s", ri.stereo ? offchar : onchar); |
523 |
|
|
break; |
524 |
|
|
case OPTION_STEREO: |
525 |
|
|
printf("%s", ri.stereo ? onchar : offchar); |
526 |
|
|
break; |
527 |
|
|
case OPTION_CHANNEL: |
528 |
|
|
printf("%u", ri.chan); |
529 |
|
|
break; |
530 |
|
|
case OPTION_CHNLSET: |
531 |
|
|
for (i = 0; chansets[i].name; i++) { |
532 |
|
|
if (chansets[i].value == ri.chnlset) |
533 |
|
|
printf("%s", chansets[i].name); |
534 |
|
|
} |
535 |
|
|
if (show_choices) { |
536 |
|
|
printf("\n\t["); |
537 |
|
|
for (i = 0; chansets[i].name; i++) |
538 |
|
|
printf("%s ", chansets[i].name); |
539 |
|
|
printf("]"); |
540 |
|
|
} |
541 |
|
|
break; |
542 |
|
|
case OPTION_VOLUME: |
543 |
|
|
default: |
544 |
|
|
printf("%u", ri.volume); |
545 |
|
|
break; |
546 |
|
|
} |
547 |
|
|
} |
548 |
|
|
|
549 |
|
|
void |
550 |
|
|
show_int_val(int val, const char *nick, char *append, int silent) |
551 |
|
|
{ |
552 |
|
|
show_verbose(nick, silent); |
553 |
|
|
printf("%u%s\n", val, append); |
554 |
|
|
} |
555 |
|
|
|
556 |
|
|
void |
557 |
|
|
show_float_val(float val, const char *nick, char *append, int silent) |
558 |
|
|
{ |
559 |
|
|
show_verbose(nick, silent); |
560 |
|
|
printf("%.2f%s\n", val, append); |
561 |
|
|
} |
562 |
|
|
|
563 |
|
|
void |
564 |
|
|
show_char_val(const char *val, const char *nick, int silent) |
565 |
|
|
{ |
566 |
|
|
show_verbose(nick, silent); |
567 |
|
|
printf("%s\n", val); |
568 |
|
|
} |
569 |
|
|
|
570 |
|
|
/* |
571 |
|
|
* Print all available parameters |
572 |
|
|
*/ |
573 |
|
|
void |
574 |
|
|
print_vars(int silent, int show_choices) |
575 |
|
|
{ |
576 |
|
|
show_int_val(ri.volume, varname[OPTION_VOLUME], "", silent); |
577 |
|
|
show_int_val(ri.chan, varname[OPTION_CHANNEL], "", silent); |
578 |
|
|
for (i = 0; chansets[i].name; i++) { |
579 |
|
|
if (chansets[i].value == ri.chnlset) |
580 |
|
|
show_char_val(chansets[i].name, varname[OPTION_CHNLSET], silent); |
581 |
|
|
} |
582 |
|
|
if (show_choices) { |
583 |
|
|
printf("\t[ "); |
584 |
|
|
for (i = 0; chansets[i].name; i++) |
585 |
|
|
printf("%s ", chansets[i].name); |
586 |
|
|
printf("]\n"); |
587 |
|
|
} |
588 |
|
|
show_float_val((float)ri.freq / 1000., varname[OPTION_FREQUENCY], |
589 |
|
|
"MHz", silent); |
590 |
|
|
show_char_val(ri.mute ? onchar : offchar, varname[OPTION_MUTE], silent); |
591 |
|
|
|
592 |
|
|
if (ri.caps & RADIO_CAPS_REFERENCE_FREQ) |
593 |
|
|
show_int_val(ri.rfreq, varname[OPTION_REFERENCE], "kHz", silent); |
594 |
|
|
if (ri.caps & RADIO_CAPS_LOCK_SENSITIVITY) |
595 |
|
|
show_int_val(ri.lock, varname[OPTION_SENSITIVITY], "mkV", silent); |
596 |
|
|
|
597 |
|
|
if (ri.caps & RADIO_CAPS_DETECT_SIGNAL) { |
598 |
|
|
show_verbose("signal", silent); |
599 |
|
|
printf("%s\n", ri.info & RADIO_INFO_SIGNAL ? onchar : offchar); |
600 |
|
|
} |
601 |
|
|
if (ri.caps & RADIO_CAPS_DETECT_STEREO) { |
602 |
|
|
show_verbose(varname[OPTION_STEREO], silent); |
603 |
|
|
printf("%s\n", ri.info & RADIO_INFO_STEREO ? onchar : offchar); |
604 |
|
|
} |
605 |
|
|
|
606 |
|
|
if (!silent) { |
607 |
|
|
printf("mode: %s\n", |
608 |
|
|
ri.tuner_mode == RADIO_TUNER_MODE_TV ? "TV" : "radio"); |
609 |
|
|
|
610 |
|
|
puts("card capabilities:"); |
611 |
|
|
} |
612 |
|
|
|
613 |
|
|
if (ri.caps & RADIO_CAPS_SET_MONO) |
614 |
|
|
puts("\tmanageable mono/stereo"); |
615 |
|
|
if (ri.caps & RADIO_CAPS_HW_SEARCH) |
616 |
|
|
puts("\thardware search"); |
617 |
|
|
if (ri.caps & RADIO_CAPS_HW_AFC) |
618 |
|
|
puts("\thardware AFC"); |
619 |
|
|
} |