From f6b99a3ac4dbec210bca7ea92d2ef9084baffc98 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Sat, 9 Jan 2010 13:27:43 -0800 Subject: [PATCH] Better support radios that do not have volume control. Thanks to Paulo Cavalcanti for reminding me that such radios exist. --- fm.c | 34 ++++++++++++++++++++++++---------- fmlib.c | 37 +++++++++++++++++++++++++++---------- fmlib.h | 1 + test-fm.at | 21 +++++++++++++++++++++ 4 files changed, 73 insertions(+), 20 deletions(-) diff --git a/fm.c b/fm.c index be76ce1..1fabbf6 100644 --- a/fm.c +++ b/fm.c @@ -202,7 +202,16 @@ getconfig(const char *fn, } fclose(conf); -} +} + +static void +print_volume(const struct tuner *tuner) +{ + if (tuner_has_volume_control(tuner)) + printf(" at %.2f%% volume\n", tuner_get_volume(tuner)); + else + printf(" (radio does not support volume control)\n"); +} int main(int argc, char **argv) { @@ -274,11 +283,16 @@ int main(int argc, char **argv) printf("Radio muted\n"); } else if (!strcmp(argv[0], "on")) { tuner_set_mute(&tuner, false); - if (!quiet) - printf("Radio on at %.2f%% volume\n", - tuner_get_volume(&tuner)); + if (!quiet) { + printf("Radio on"); + print_volume(&tuner); + } } else if (!strcmp(argv[0], "+") || !strcmp(argv[0], "-")) { - double new_volume = tuner_get_volume(&tuner); + double new_volume; + if (!tuner_has_volume_control(&tuner)) + fatal(0, "Radio does not support volume control"); + + new_volume = tuner_get_volume(&tuner); if (argv[0][0] == '+') new_volume += increment; else @@ -286,8 +300,7 @@ int main(int argc, char **argv) new_volume = clamp(new_volume); if (!quiet) - printf("Setting volume to %.2f%%\n", - new_volume); + printf("Setting volume to %.2f%%\n", new_volume); tuner_set_volume(&tuner, new_volume); } else if (atof(argv[0])) { @@ -295,9 +308,10 @@ int main(int argc, char **argv) double volume = argc > 1 ? clamp(atof(argv[1])) : defaultvol; tuner_set_freq(&tuner, frequency * 16000.0, override); tuner_set_volume(&tuner, volume); - if (!quiet) - printf("Radio tuned to %2.2f MHz at %.2f%% volume\n", - frequency, volume); + if (!quiet) { + printf("Radio tuned to %2.2f MHz", frequency); + print_volume(&tuner); + } } else { fatal(0, "unrecognized command syntax; use --help for help"); } diff --git a/fmlib.c b/fmlib.c index 669cab3..1d0922a 100644 --- a/fmlib.c +++ b/fmlib.c @@ -82,7 +82,7 @@ tuner_open(struct tuner *tuner, const char *device, int index) tuner->test = xmalloc(sizeof *tuner->test); tuner->test->freq = 90 * 16; - tuner->test->volume = volume * 10 + 1000.5; + tuner->test->volume = volume >= 0 ? volume * 10 + 1000.5 : 0; device = "/dev/null"; } @@ -108,21 +108,36 @@ tuner_set_mute(struct tuner *tuner, bool mute) set_control(tuner, V4L2_CID_AUDIO_MUTE, mute); } +bool +tuner_has_volume_control(const struct tuner *tuner) +{ + const struct v4l2_queryctrl *vqc = &tuner->volume_ctrl; + return vqc->maximum > vqc->minimum; +} + double tuner_get_volume(const struct tuner *tuner) { - const struct v4l2_queryctrl *vqc = &tuner->volume_ctrl; - int volume = get_control(tuner, V4L2_CID_AUDIO_VOLUME); - return 100.0 * (volume - vqc->minimum) / (vqc->maximum - vqc->minimum); + if (tuner_has_volume_control(tuner)) { + const struct v4l2_queryctrl *vqc = &tuner->volume_ctrl; + int volume = get_control(tuner, V4L2_CID_AUDIO_VOLUME); + return (100.0 + * (volume - vqc->minimum) + / (vqc->maximum - vqc->minimum)); + } else { + return 100.0; + } } void tuner_set_volume(struct tuner *tuner, double volume) { - struct v4l2_queryctrl *vqc = &tuner->volume_ctrl; - set_control(tuner, V4L2_CID_AUDIO_VOLUME, - (volume / 100.0 * (vqc->maximum - vqc->minimum) - + vqc->minimum)); + if (tuner_has_volume_control(tuner)) { + struct v4l2_queryctrl *vqc = &tuner->volume_ctrl; + set_control(tuner, V4L2_CID_AUDIO_VOLUME, + (volume / 100.0 * (vqc->maximum - vqc->minimum) + + vqc->minimum)); + } } long long int @@ -204,8 +219,10 @@ query_control(const struct tuner *tuner, uint32_t id, qc->id = id; if (tuner->test) { assert(id == V4L2_CID_AUDIO_VOLUME); - qc->minimum = 1000; - qc->maximum = 2000; + if (tuner->test->volume) { + qc->minimum = 1000; + qc->maximum = 2000; + } } else if (ioctl(tuner->fd, VIDIOC_QUERYCTRL, qc) == -1) fatal(errno, "VIDIOC_QUERYCTRL"); } diff --git a/fmlib.h b/fmlib.h index 068feec..9a65474 100644 --- a/fmlib.h +++ b/fmlib.h @@ -41,6 +41,7 @@ void tuner_close(struct tuner *); void tuner_set_mute(struct tuner *, bool mute); +bool tuner_has_volume_control(const struct tuner *); double tuner_get_volume(const struct tuner *); void tuner_set_volume(struct tuner *, double volume); diff --git a/test-fm.at b/test-fm.at index 63312ad..86d000c 100644 --- a/test-fm.at +++ b/test-fm.at @@ -7,6 +7,11 @@ AT_CHECK([RUN_FM on], [0], [Radio on at 50.00% volume ]) AT_CLEANUP +AT_SETUP(["on" command (no volume control)]) +AT_CHECK([RUN_FM([-1]) on], [0], [Radio on (radio does not support volume control) +]) +AT_CLEANUP + AT_SETUP(["on" command (quiet)]) AT_CHECK([RUN_FM -q on]) AT_CLEANUP @@ -20,6 +25,11 @@ AT_SETUP(["off" command (quiet)]) AT_CHECK([RUN_FM -q off]) AT_CLEANUP +AT_SETUP(["+" command, no volume control]) +AT_CHECK([RUN_FM([-1]) +], [1], [], [fm: Radio does not support volume control +]) +AT_CLEANUP + AT_SETUP(["+" command, in-range]) AT_CHECK([RUN_FM +], [0], [Setting volume to 60.00% ]) @@ -41,6 +51,11 @@ AT_CHECK([RUN_FM([99]) +], [0], [Setting volume to 100.00% ]) AT_CLEANUP +AT_SETUP(["-" command, no volume control]) +AT_CHECK([RUN_FM([-1]) -], [1], [], [fm: Radio does not support volume control +]) +AT_CLEANUP + AT_SETUP(["-" command, in-range]) AT_CHECK([RUN_FM -], [0], [Setting volume to 40.00% ]) @@ -67,6 +82,12 @@ AT_CHECK([RUN_FM 90], [0], [Radio tuned to 90.00 MHz at 12.50% volume ]) AT_CLEANUP +AT_SETUP([tune valid freq, no volume control]) +AT_CHECK([RUN_FM([-1]) 90], [0], + [Radio tuned to 90.00 MHz (radio does not support volume control) +]) +AT_CLEANUP + AT_SETUP([tune valid freq, default volume (quiet) ]) AT_CHECK([RUN_FM -q 90]) AT_CLEANUP -- 2.11.4.GIT