1 /* fm.c - simple v4l compatible tuner for radio cards
3 Copyright (C) 1998 Russell Kroll <rkroll@exploits.org>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #include <sys/ioctl.h>
34 #define DEFAULT_DEVICE "/dev/radio0"
38 static int convert_time (const char *string
)
40 if (strcmp (string
, "forever") == 0 ||
41 strcmp (string
, "-") == 0 ||
44 else if (strcmp (string
, "none") == 0 ||
45 strcmp (string
, "0") == 0)
53 suffix
= string
+ strspn (string
, "0123456789");
55 strncpy (worktime
, string
, suffix
- string
);
56 worktime
[suffix
- string
] = '\0';
57 inttime
= atoi (worktime
);
71 inttime
*= 24 * 60 * 60;
83 static char *format_time (char *buffer
,
86 if (strcmp (string
, "forever") == 0 ||
87 strcmp (string
, "-") == 0 ||
89 strcpy (buffer
, "forever");
90 else if (strcmp (string
, "none") == 0 ||
91 strcmp (string
, "0") == 0)
92 strcpy (buffer
, "none");
100 suffix
= string
+ strspn (string
, "0123456789");
101 strncpy (worktime
, string
, suffix
- string
);
102 worktime
[suffix
- string
] = '\0';
103 int_time
= atoi (worktime
);
108 format
= "%d minute(s)";
111 format
= "%d hour(s)";
114 format
= "%d day(s)";
119 format
= "%d second(s)";
123 sprintf (buffer
, format
, int_time
);
131 static void maybe_sleep (const char *wait_time
)
136 int_wait_time
= convert_time (wait_time
);
138 if (int_wait_time
> 0)
140 printf ("Sleeping for %s\n", format_time (message
, wait_time
));
141 sleep (int_wait_time
);
143 else if (int_wait_time
== 0)
145 printf ("Sleeping forever...CTRL-C exits\n");
154 void help(char *prog
)
156 printf("fmtools fm version %s\n\n", FMT_VERSION
);
157 printf("usage: %s [-h] [-o] [-q] [-d <dev>] [-t <tuner>] "
158 "[-T none|forever|time] <freq>|on|off [<volume>]\n\n",
160 printf("A small controller for Video for Linux radio devices.\n\n");
161 printf(" -h display this help\n");
162 printf(" -o override frequency range limits of card\n");
163 printf(" -q quiet mode\n");
164 printf(" -d <dev> select device (default: /dev/radio0)\n");
165 printf(" -t <tuner> select tuner (default: 0)\n");
166 printf(" -T <time> after setting frequency, sleep for some time\n"\
167 " (default: none; -=forever)\n");
168 printf(" <freq> frequency in MHz (i.e. 94.3)\n");
169 printf(" on turn radio on\n");
170 printf(" off turn radio off (mute)\n");
171 printf(" + increase volume\n");
172 printf(" - decrease volume\n");
173 printf(" <volume> intensity (0-65535)\n");
177 void getconfig(int *defaultvol
, int *increment
, char *wait_time
)
180 char buf
[256], fn
[256];
182 sprintf(fn
, "%s/.fmrc", getenv("HOME"));
183 conf
= fopen(fn
, "r");
188 while(fgets(buf
, sizeof(buf
), conf
)) {
189 buf
[strlen(buf
)-1] = 0;
190 if (!strncmp(buf
, "VOL", 3))
191 sscanf(buf
, "%*s %i", defaultvol
);
192 if (!strncmp(buf
, "INCR", 3))
193 sscanf(buf
, "%*s %i", increment
);
194 if (!strncmp(buf
, "TIME", 4))
195 sscanf(buf
, "%*s %s", wait_time
);
201 int main(int argc
, char **argv
)
203 int fd
, ret
, tunevol
, quiet
=0, i
, override
= 0;
204 int defaultvol
= 8192; /* default volume = 12.5% */
205 int increment
= 6554; /* default change = 10% */
208 struct video_audio va
;
209 struct video_tuner vt
;
212 char wait_time_buf
[256+1] = "";
213 char *wait_time
= "none";
216 /* need at least a frequency */
218 printf("usage: %s [-h] [-o] [-q] [-d <dev>] [-t <tuner>] "
219 "[-T time|forever|none] "
220 "<freq>|on|off [<volume>]\n", argv
[0]);
224 progname
= argv
[0]; /* used after getopt munges argv[] */
226 getconfig(&defaultvol
, &increment
, wait_time_buf
);
228 wait_time
= wait_time_buf
;
230 while ((i
= getopt(argc
, argv
, "+qhot:T:d:")) != EOF
) {
239 tuner
= atoi(optarg
);
245 dev
= strdup(optarg
);
257 if (argc
== 0) /* no frequency, on|off, or +|- given */
261 tunevol
= atoi(argv
[1]);
263 tunevol
= defaultvol
;
266 dev
= DEFAULT_DEVICE
;
268 fd
= open(dev
, O_RDONLY
);
270 fprintf(stderr
, "Unable to open %s: %s\n",
271 dev
, strerror(errno
));
275 ret
= ioctl(fd
, VIDIOCGAUDIO
, &va
);
277 perror("ioctl VIDIOCGAUDIO");
281 /* initialize this so it doesn't pick up random junk data */
284 if (!strcmp("off", argv
[0])) { /* mute the radio */
287 va
.flags
= VIDEO_AUDIO_MUTE
;
288 ret
= ioctl(fd
, VIDIOCSAUDIO
, &va
);
290 perror("ioctl VIDIOCSAUDIO");
295 printf("Radio muted\n");
299 if (!strcmp("on", argv
[0])) { /* turn radio on */
303 ret
= ioctl(fd
, VIDIOCSAUDIO
, &va
);
305 perror("ioctl VIDIOCSAUDIO");
310 printf("Radio on at %2.2f%% volume\n",
312 maybe_sleep (wait_time
);
316 if (argv
[0][0] == '+') { /* volume up */
317 if ((va
.volume
+ increment
) > 65535)
318 va
.volume
= 65535; /* catch overflows in __u16 */
320 va
.volume
+= increment
;
323 printf("Setting volume to %2.2f%%\n",
324 (va
.volume
/ 655.35));
326 ret
= ioctl(fd
, VIDIOCSAUDIO
, &va
);
328 perror("ioctl VIDIOCSAUDIO");
332 maybe_sleep (wait_time
);
336 if (argv
[0][0] == '-') { /* volume down */
337 if ((va
.volume
- increment
) < 0)
338 va
.volume
= 0; /* catch negative numbers */
340 va
.volume
-= increment
;
343 printf("Setting volume to %2.2f%%\n",
344 (va
.volume
/ 655.35));
346 ret
= ioctl(fd
, VIDIOCSAUDIO
, &va
);
348 perror("ioctl VIDIOCSAUDIO");
352 maybe_sleep (wait_time
);
356 /* at this point, we are trying to tune to a frequency */
359 ret
= ioctl(fd
, VIDIOCSTUNER
, &vt
); /* set tuner # */
361 perror("ioctl VIDIOCSTUNER");
365 ret
= ioctl(fd
, VIDIOCGTUNER
, &vt
); /* get frequency range */
367 perror("ioctl VIDIOCGTUNER");
371 if ((ret
== -1) || ((vt
.flags
& VIDEO_TUNER_LOW
) == 0))
376 freq
= rint(atof(argv
[0]) * fact
); /* rounding to nearest int */
378 if ((freq
< vt
.rangelow
) || (freq
> vt
.rangehigh
)) {
380 printf("Frequency %2.1f out of range (%2.1f - %2.1f MHz)\n",
381 (freq
/ fact
), (vt
.rangelow
/ fact
),
382 (vt
.rangehigh
/ fact
));
387 /* frequency sanity checked, proceed */
388 ret
= ioctl(fd
, VIDIOCSFREQ
, &freq
);
390 perror("ioctl VIDIOCSFREQ");
397 va
.mode
= VIDEO_SOUND_STEREO
;
399 ret
= ioctl(fd
, VIDIOCSAUDIO
, &va
); /* set the volume */
401 perror("ioctl VIDIOCSAUDIO");
406 printf("Radio tuned to %2.2f MHz at %2.2f%% volume\n",
407 (freq
/ fact
), (tunevol
/ 655.35));
409 maybe_sleep (wait_time
);