Work with tuners that do not support V4L2_CID_AUDIO_VOLUME.
authorBen Pfaff <blp@cs.stanford.edu>
Sat, 1 Sep 2012 23:31:15 +0000 (1 16:31 -0700)
committerBen Pfaff <blp@cs.stanford.edu>
Sat, 1 Sep 2012 23:31:15 +0000 (1 16:31 -0700)
Rajil Saraswat <rajil.s@gmail.com> reported that D-link/Gemtek tuners using
the dsbr100 driver do not support V4L2_CID_AUDIO_VOLUME and therefore fm
failed as follows:

    #fm -d /dev/radio0  -T forever on 106.20
    ioctl VIDIOCGAUDIO: Inappropriate ioctl for device

This commit should fix the problem.

Signed-off-by: Ben Pfaff <blp@cs.stanford.edu>
fm.c
fmlib.c

diff --git a/fm.c b/fm.c
index 61aaaec..c1c725f 100644 (file)
--- a/fm.c
+++ b/fm.c
@@ -1,6 +1,6 @@
 /* fm.c - simple V4L2 compatible tuner for radio cards
 
-   Copyright (C) 2004, 2006, 2009 Ben Pfaff <blp@cs.stanford.edu>
+   Copyright (C) 2004, 2006, 2009, 2012 Ben Pfaff <blp@cs.stanford.edu>
    Copyright (C) 1998 Russell Kroll <rkroll@exploits.org>
 
    This program is free software; you can redistribute it and/or modify it
@@ -318,7 +318,8 @@ int main(int argc, char **argv)
                 double frequency = atof(argv[0]);
                 double volume = argc > 1 ? clamp(atof(argv[1])) : defaultvol;
                 tuner_set_freq(&tuner, frequency * 16000.0, override);
-                tuner_set_volume(&tuner, volume);
+                if (tuner_has_volume_control(&tuner))
+                        tuner_set_volume(&tuner, volume);
                 if (!quiet) {
                         printf("Radio tuned to %2.2f MHz", frequency);
                         print_volume(&tuner);
diff --git a/fmlib.c b/fmlib.c
index 60bb9d1..ba185a3 100644 (file)
--- a/fmlib.c
+++ b/fmlib.c
@@ -1,6 +1,6 @@
 /* fmlib.c - simple V4L2 compatible tuner for radio cards
 
-   Copyright (C) 2009 Ben Pfaff <blp@cs.stanford.edu>
+   Copyright (C) 2009, 2012 Ben Pfaff <blp@cs.stanford.edu>
 
    This program is free software; you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by the Free
@@ -224,6 +224,9 @@ tuner_sleep(const struct tuner *tuner, int secs)
                 sleep(secs);
 }
 \f
+/* Queries 'tuner' for a property with the given 'id' and fills in 'qc' with
+ * the result.  If 'tuner' doesn't have such a property, clears 'qc' to
+ * all-zeros. */
 static void
 query_control(const struct tuner *tuner, uint32_t id,
               struct v4l2_queryctrl *qc)
@@ -236,8 +239,14 @@ query_control(const struct tuner *tuner, uint32_t id,
                         qc->minimum = 1000;
                         qc->maximum = 2000;
                 }
-        } else if (ioctl(tuner->fd, VIDIOC_QUERYCTRL, qc) == -1)
+        } else if (ioctl(tuner->fd, VIDIOC_QUERYCTRL, qc) != -1) {
+                /* Success. */
+        } else if (errno == ENOTTY) {
+                /* This tuner doesn't support 'id'. */
+                memset(qc, 0, sizeof *qc);
+        } else {
                 fatal(errno, "VIDIOC_QUERYCTRL");
+        }
 }
 
 static int32_t