fmtools 0.99.0.
[fmtools.git] / fm.c
blob287b544aad1b15a95a4d368bf7d86d09d025eaa3
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 <errno.h>
22 #include <stdio.h>
23 #include <fcntl.h>
24 #include <stdlib.h>
25 #include <unistd.h>
26 #include <getopt.h>
27 #include <string.h>
28 #include <asm/types.h>
29 #include <sys/ioctl.h>
30 #include <linux/videodev.h>
32 void help(char *prog)
34 printf("usage: %s [-h] [-o] [-q] [-d <dev>] [-t <tuner>] <freq>|on|off [<volume>]\n", prog);
35 printf("\n");
36 printf(" -h display this help\n");
37 printf(" -o override frequency range limits of card\n");
38 printf(" -q quiet mode\n");
39 printf(" -d <dev> select device (default: /dev/radio0)\n");
40 printf(" -t <tuner> select tuner (default: 0)\n");
41 printf(" <freq> frequency in MHz (i.e. 94.3)\n");
42 printf(" on turn radio on\n");
43 printf(" off turn radio off (mute)\n");
44 printf(" + increase volume\n");
45 printf(" - decrease volume\n");
46 printf(" <volume> intensity (0-65535)\n");
47 exit(0);
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))
64 sscanf(buf, "%*s %i", defaultvol);
65 if (!strncmp(buf, "INCR", 3))
66 sscanf(buf, "%*s %i", increment);
69 fclose(conf);
72 int main(int argc, char **argv)
74 int fd, ret, tunevol, quiet=0, i, override = 0;
75 int defaultvol = 8192; /* default volume = 12.5% */
76 int increment = 6554; /* default change = 10% */
77 double fact;
78 unsigned long freq;
79 struct video_audio va;
80 struct video_tuner vt;
81 char *progname;
82 int tuner = 0;
83 char *dev = NULL;
85 /* need at least a frequency */
86 if (argc < 2) {
87 printf ("usage: %s [-h] [-o] [-q] [-d <dev>] [-t <tuner>] <freq>|on|off [<volume>]\n", argv[0]);
88 exit (1);
91 progname = argv[0]; /* used after getopt munges argv[] */
93 getconfig(&defaultvol, &increment);
95 while ((i = getopt(argc, argv, "+qhot:d:")) != EOF) {
96 switch (i) {
97 case 'q':
98 quiet = 1;
99 break;
100 case 'o':
101 override = 1;
102 break;
103 case 't':
104 tuner = atoi(optarg);
105 break;
106 case 'd':
107 dev = strdup(optarg);
108 break;
109 case 'h':
110 default:
111 help(argv[0]);
112 break;
116 argc -= optind;
117 argv += optind;
119 if (argc == 0) /* no frequency, on|off, or +|- given */
120 help(progname);
122 if (argc == 2)
123 tunevol = atoi(argv[1]);
124 else
125 tunevol = defaultvol;
127 if (!dev)
128 dev = strdup("/dev/radio0"); /* use default */
130 fd = open(dev, O_RDONLY);
131 if (fd < 0) {
132 fprintf(stderr, "Unable to open %s: %s\n", dev, strerror(errno));
133 exit(1);
136 if (!strcmp("off", argv[0])) { /* mute the radio */
137 va.audio = 0;
138 va.volume = 0;
139 va.flags = VIDEO_AUDIO_MUTE;
140 ret = ioctl(fd, VIDIOCSAUDIO, &va);
141 if (ret < 0) {
142 perror("ioctl VIDIOCSAUDIO");
143 exit(1);
146 if (!quiet)
147 printf ("Radio muted\n");
148 exit(0);
151 if (!strcmp("on", argv[0])) { /* turn radio on */
152 va.audio = 0;
153 va.volume = tunevol;
154 va.flags = 0;
155 ret = ioctl(fd, VIDIOCSAUDIO, &va);
156 if (ret < 0) {
157 perror("ioctl VIDIOCSAUDIO");
158 exit(1);
161 if (!quiet)
162 printf("Radio on at %2.2f%% volume\n",
163 (tunevol / 655.36));
164 exit(0);
167 ret = ioctl(fd, VIDIOCGAUDIO, &va);
168 if (ret < 0) {
169 perror("ioctl VIDIOCGAUDIO");
170 exit(1);
173 if (argv[0][0] == '+') { /* volume up */
174 if ((va.volume + increment) > 65535)
175 va.volume = 65535; /* catch overflows in __u16 */
176 else
177 va.volume += increment;
179 if (!quiet)
180 printf("Setting volume to %2.2f%%\n",
181 (va.volume / 655.35));
183 ret = ioctl (fd, VIDIOCSAUDIO, &va);
184 if (ret < 0) {
185 perror("ioctl VIDIOCSAUDIO");
186 exit(1);
189 exit (0);
192 if (argv[0][0] == '-') { /* volume down */
193 if ((va.volume - increment) < 0)
194 va.volume = 0; /* catch negative numbers */
195 else
196 va.volume -= increment;
198 if (!quiet)
199 printf("Setting volume to %2.2f%%\n",
200 (va.volume / 655.35));
202 ret = ioctl (fd, VIDIOCSAUDIO, &va);
203 if (ret < 0) {
204 perror("ioctl VIDIOCSAUDIO");
205 exit(1);
208 exit (0);
211 /* at this point, we are trying to tune to a frequency */
213 vt.tuner = tuner;
214 ret = ioctl(fd, VIDIOCSTUNER, &vt); /* set tuner # */
215 if (ret < 0) {
216 perror("ioctl VIDIOCSTUNER");
217 exit(1);
220 ret = ioctl(fd, VIDIOCGTUNER, &vt); /* get frequency range */
221 if (ret < 0) {
222 perror("ioctl VIDIOCGTUNER");
223 exit(1);
226 if ((ret == -1) || ((vt.flags & VIDEO_TUNER_LOW) == 0))
227 fact = 16.;
228 else
229 fact = 16000.;
231 freq = ceil(atof(argv[0]) * fact); /* rounding up matters */
233 if ((freq < vt.rangelow) || (freq > vt.rangehigh)) {
234 if (override == 0) {
235 printf("Frequency %2.1f out of range (%2.1f - %2.1f MHz)\n",
236 (freq / fact), (vt.rangelow / fact),
237 (vt.rangehigh / fact));
238 exit(1);
242 /* frequency sanity checked, proceed */
243 ret = ioctl(fd, VIDIOCSFREQ, &freq);
244 if (ret < 0) {
245 perror("ioctl VIDIOCSFREQ");
246 exit (1);
249 va.audio = 0;
250 va.volume = tunevol;
251 va.flags = 0;
252 va.mode = VIDEO_SOUND_STEREO;
254 ret = ioctl(fd, VIDIOCSAUDIO, &va); /* set the volume */
255 if (ret < 0) {
256 perror("ioctl VIDIOCSAUDIO");
257 exit(1);
260 if (!quiet)
261 printf ("Radio tuned to %2.1f MHz at %2.2f%% volume\n",
262 (freq / fact), (tunevol / 655.35));
264 return 0;