fmtools 0.2.5.
[fmtools.git] / fm.c
blob4e4ee38ee6d2207f7562aac9f2edcbf2eeb2f07e
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., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include <math.h>
21 #include <stdio.h>
22 #include <fcntl.h>
23 #include <stdlib.h>
24 #include <unistd.h>
25 #include <getopt.h>
26 #include <string.h>
27 #include <asm/types.h>
28 #include <sys/ioctl.h>
29 #include <linux/videodev.h>
31 void help(char *prog)
33 printf ("usage: %s [-h] [-o] [-q] [-t <tuner>] <freq>|on|off [<volume>]\n", prog);
34 printf ("\n");
35 printf ("-h - display this help\n");
36 printf ("-o - override frequency range limits in card\n");
37 printf ("-q - quiet mode\n");
38 printf ("-t <tuner> - select tuner <tuner>\n");
39 printf ("<tuner> - tuner number - first one is 0, next one 1, etc\n");
40 printf ("<freq> - frequency in MHz (i.e. 94.3)\n");
41 printf ("on - turn radio on\n");
42 printf ("off - turn radio off (mute)\n");
43 printf ("+ - increase volume\n");
44 printf ("- - decrease volume\n");
45 printf ("<volume> - intensity (0-65535)\n");
47 exit (1);
50 void getconfig(int *defaultvol, int *increment)
52 FILE *conf;
53 char buf[256], fn[256];
55 sprintf (fn, "%s/.fmrc", getenv("HOME"));
56 conf = fopen (fn, "r");
58 if (!conf)
59 return;
61 while (fgets(buf, sizeof(buf), conf)) {
62 buf[strlen(buf)-1] = 0;
63 if (strncmp (buf, "VOL", 3) == 0)
64 sscanf (buf, "%*s %i", defaultvol);
65 if (strncmp (buf, "INCR", 3) == 0)
66 sscanf (buf, "%*s %i", increment);
69 fclose (conf);
71 return;
74 int main(int argc, char **argv)
76 int fd, ret, tunevol, quiet=0, i, override = 0;
77 int defaultvol = 8192; /* default volume = 12.5% */
78 int increment = 6554; /* default change = 10% */
79 double fact;
80 unsigned long freq;
81 struct video_audio va;
82 struct video_tuner vt;
83 char *progname;
84 extern char *optarg;
85 extern int optind, opterr, optopt;
86 int tuner = 0;
88 if ((argc < 2) || (argc > 4)) {
89 printf ("usage: %s [-h] [-o] [-q] [-t <tuner>] <freq>|on|off [<volume>]\n", argv[0]);
90 exit (1);
93 progname = argv[0]; /* used after getopt munges argv[] */
95 getconfig(&defaultvol, &increment);
97 while ((i = getopt(argc, argv, "+qhot:")) != EOF) {
98 switch (i) {
99 case 'q':
100 quiet = 1;
101 break;
102 case 'o':
103 override = 1;
104 break;
105 case 't':
106 tuner = atoi(optarg);
107 break;
108 case 'h':
109 default:
110 help(argv[0]);
111 break;
115 argc -= optind;
116 argv += optind;
118 if (argc == 2)
119 tunevol = atoi (argv[1]);
120 else
121 tunevol = defaultvol;
123 if (argc == 0) /* no frequency, on|off, or +|- given */
124 help (progname);
126 /* moved here so -h works without a device */
127 fd = open ("/dev/radio0", O_RDONLY);
128 if (fd == -1) {
129 perror ("Unable to open /dev/radio0");
130 exit (1);
133 if (!strcmp("off", argv[0])) { /* mute the radio */
134 va.audio = 0;
135 va.volume = 0;
136 va.flags = VIDEO_AUDIO_MUTE;
137 ret = ioctl (fd, VIDIOCSAUDIO, &va);
138 if (!quiet)
139 printf ("Radio muted\n");
140 exit (0);
143 if (!strcmp("on", argv[0])) { /* turn radio on */
144 va.audio = 0;
145 va.volume = tunevol;
146 va.flags = 0;
147 ret = ioctl (fd, VIDIOCSAUDIO, &va);
148 if (!quiet)
149 printf ("Radio on at %2.2f%% volume\n",
150 (tunevol / 655.36));
151 exit (0);
154 ret = ioctl (fd, VIDIOCGAUDIO, &va);
156 if (argv[0][0] == '+') { /* volume up */
157 if ((va.volume + increment) > 65535)
158 va.volume = 65535; /* catch overflows in __u16 */
159 else
160 va.volume += increment;
162 if (!quiet)
163 printf ("Setting volume to %2.2f%%\n",
164 (va.volume / 655.35));
165 ret = ioctl (fd, VIDIOCSAUDIO, &va);
166 exit (0);
169 if (argv[0][0] == '-') { /* volume down */
170 if ((va.volume - increment) < 0)
171 va.volume = 0; /* catch negative numbers */
172 else
173 va.volume -= increment;
175 if (!quiet)
176 printf ("Setting volume to %2.2f%%\n",
177 (va.volume / 655.35));
178 ret = ioctl (fd, VIDIOCSAUDIO, &va);
179 exit (0);
182 /* at this point, we are trying to tune to a frequency */
184 vt.tuner = tuner;
185 ret = ioctl(fd, VIDIOCSTUNER, &vt); /* set tuner # */
186 if (ret < 0) {
187 perror ("set tuner");
188 exit (1);
191 ret = ioctl(fd, VIDIOCGTUNER, &vt); /* get frequency range */
193 if (ret == -1 || (vt.flags & VIDEO_TUNER_LOW) == 0)
194 fact = 16.;
195 else
196 fact = 16000.;
197 freq = ceil(atof(argv[0]) * fact); /* rounding up matters */
199 if ((freq < vt.rangelow) || (freq > vt.rangehigh)) {
200 if (override == 0) {
201 printf ("Frequency %2.1f out of range (%2.1f - %2.1f MHz)\n",
202 (freq / fact), (vt.rangelow / fact),
203 (vt.rangehigh / fact));
204 exit (1);
208 /* frequency sanity checked, proceed */
209 ret = ioctl (fd, VIDIOCSFREQ, &freq);
210 if (ret < 0) {
211 perror ("set freq");
212 exit (1);
215 va.audio = 0;
216 va.volume = tunevol;
217 va.flags = 0;
218 va.mode = VIDEO_SOUND_STEREO;
220 ret = ioctl (fd, VIDIOCSAUDIO, &va); /* set the volume */
222 if (!quiet)
223 printf ("Radio tuned to %2.1f MHz at %2.2f%% volume\n",
224 (freq / fact), (tunevol / 655.35));
226 return (0);