Better support radios that do not have volume control.
authorBen Pfaff <blp@cs.stanford.edu>
Sat, 9 Jan 2010 21:27:43 +0000 (9 13:27 -0800)
committerBen Pfaff <blp@cs.stanford.edu>
Sat, 9 Jan 2010 21:27:43 +0000 (9 13:27 -0800)
Thanks to Paulo Cavalcanti <promac@gmail.com> for reminding me that such
radios exist.

fm.c
fmlib.c
fmlib.h
test-fm.at

diff --git a/fm.c b/fm.c
index be76ce1..1fabbf6 100644 (file)
--- 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 (file)
--- 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 (file)
--- 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);
 
index 63312ad..86d000c 100644 (file)
@@ -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