fmtools version 1.0.
[fmtools.git] / fm.c
blob51dfb42efeff9fb7dfb31706af33bb4cf3034c5c
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
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 <sys/ioctl.h>
29 #include "videodev.h"
31 #include "version.h"
33 #define DEFAULT_DEVICE "/dev/radio0"
35 void help(char *prog)
37 printf("fmtools fm version %s\n\n", FMT_VERSION);
38 printf("usage: %s [-h] [-o] [-q] [-d <dev>] [-t <tuner>] <freq>|on|off [<volume>]\n\n", prog);
39 printf("A small controller for Video for Linux radio devices.\n\n");
40 printf(" -h display this help\n");
41 printf(" -o override frequency range limits of card\n");
42 printf(" -q quiet mode\n");
43 printf(" -d <dev> select device (default: /dev/radio0)\n");
44 printf(" -t <tuner> select tuner (default: 0)\n");
45 printf(" <freq> frequency in MHz (i.e. 94.3)\n");
46 printf(" on turn radio on\n");
47 printf(" off turn radio off (mute)\n");
48 printf(" + increase volume\n");
49 printf(" - decrease volume\n");
50 printf(" <volume> intensity (0-65535)\n");
51 exit(0);
54 void getconfig(int *defaultvol, int *increment)
56 FILE *conf;
57 char buf[256], fn[256];
59 sprintf(fn, "%s/.fmrc", getenv("HOME"));
60 conf = fopen(fn, "r");
62 if (!conf)
63 return;
65 while(fgets(buf, sizeof(buf), conf)) {
66 buf[strlen(buf)-1] = 0;
67 if (!strncmp(buf, "VOL", 3))
68 sscanf(buf, "%*s %i", defaultvol);
69 if (!strncmp(buf, "INCR", 3))
70 sscanf(buf, "%*s %i", increment);
73 fclose(conf);
76 int main(int argc, char **argv)
78 int fd, ret, tunevol, quiet=0, i, override = 0;
79 int defaultvol = 8192; /* default volume = 12.5% */
80 int increment = 6554; /* default change = 10% */
81 double fact;
82 unsigned long freq;
83 struct video_audio va;
84 struct video_tuner vt;
85 char *progname;
86 int tuner = 0;
87 char *dev = NULL;
89 /* need at least a frequency */
90 if (argc < 2) {
91 printf("usage: %s [-h] [-o] [-q] [-d <dev>] [-t <tuner>] "
92 "<freq>|on|off [<volume>]\n", argv[0]);
93 exit(1);
96 progname = argv[0]; /* used after getopt munges argv[] */
98 getconfig(&defaultvol, &increment);
100 while ((i = getopt(argc, argv, "+qhot:d:")) != EOF) {
101 switch (i) {
102 case 'q':
103 quiet = 1;
104 break;
105 case 'o':
106 override = 1;
107 break;
108 case 't':
109 tuner = atoi(optarg);
110 break;
111 case 'd':
112 dev = strdup(optarg);
113 break;
114 case 'h':
115 default:
116 help(argv[0]);
117 break;
121 argc -= optind;
122 argv += optind;
124 if (argc == 0) /* no frequency, on|off, or +|- given */
125 help(progname);
127 if (argc == 2)
128 tunevol = atoi(argv[1]);
129 else
130 tunevol = defaultvol;
132 if (!dev)
133 dev = DEFAULT_DEVICE;
135 fd = open(dev, O_RDONLY);
136 if (fd < 0) {
137 fprintf(stderr, "Unable to open %s: %s\n",
138 dev, strerror(errno));
139 exit(1);
142 ret = ioctl(fd, VIDIOCGAUDIO, &va);
143 if (ret < 0) {
144 perror("ioctl VIDIOCGAUDIO");
145 exit(1);
148 /* initialize this so it doesn't pick up random junk data */
149 va.balance = 32768;
151 if (!strcmp("off", argv[0])) { /* mute the radio */
152 va.audio = 0;
153 va.volume = 0;
154 va.flags = VIDEO_AUDIO_MUTE;
155 ret = ioctl(fd, VIDIOCSAUDIO, &va);
156 if (ret < 0) {
157 perror("ioctl VIDIOCSAUDIO");
158 exit(1);
161 if (!quiet)
162 printf("Radio muted\n");
163 exit(0);
166 if (!strcmp("on", argv[0])) { /* turn radio on */
167 va.audio = 0;
168 va.volume = tunevol;
169 va.flags = 0;
170 ret = ioctl(fd, VIDIOCSAUDIO, &va);
171 if (ret < 0) {
172 perror("ioctl VIDIOCSAUDIO");
173 exit(1);
176 if (!quiet)
177 printf("Radio on at %2.2f%% volume\n",
178 (tunevol / 655.36));
179 exit(0);
182 if (argv[0][0] == '+') { /* volume up */
183 if ((va.volume + increment) > 65535)
184 va.volume = 65535; /* catch overflows in __u16 */
185 else
186 va.volume += increment;
188 if (!quiet)
189 printf("Setting volume to %2.2f%%\n",
190 (va.volume / 655.35));
192 ret = ioctl(fd, VIDIOCSAUDIO, &va);
193 if (ret < 0) {
194 perror("ioctl VIDIOCSAUDIO");
195 exit(1);
198 exit(0);
201 if (argv[0][0] == '-') { /* volume down */
202 if ((va.volume - increment) < 0)
203 va.volume = 0; /* catch negative numbers */
204 else
205 va.volume -= increment;
207 if (!quiet)
208 printf("Setting volume to %2.2f%%\n",
209 (va.volume / 655.35));
211 ret = ioctl(fd, VIDIOCSAUDIO, &va);
212 if (ret < 0) {
213 perror("ioctl VIDIOCSAUDIO");
214 exit(1);
217 exit(0);
220 /* at this point, we are trying to tune to a frequency */
222 vt.tuner = tuner;
223 ret = ioctl(fd, VIDIOCSTUNER, &vt); /* set tuner # */
224 if (ret < 0) {
225 perror("ioctl VIDIOCSTUNER");
226 exit(1);
229 ret = ioctl(fd, VIDIOCGTUNER, &vt); /* get frequency range */
230 if (ret < 0) {
231 perror("ioctl VIDIOCGTUNER");
232 exit(1);
235 if ((ret == -1) || ((vt.flags & VIDEO_TUNER_LOW) == 0))
236 fact = 16.;
237 else
238 fact = 16000.;
240 freq = rint(atof(argv[0]) * fact); /* rounding to nearest int */
242 if ((freq < vt.rangelow) || (freq > vt.rangehigh)) {
243 if (override == 0) {
244 printf("Frequency %2.1f out of range (%2.1f - %2.1f MHz)\n",
245 (freq / fact), (vt.rangelow / fact),
246 (vt.rangehigh / fact));
247 exit(1);
251 /* frequency sanity checked, proceed */
252 ret = ioctl(fd, VIDIOCSFREQ, &freq);
253 if (ret < 0) {
254 perror("ioctl VIDIOCSFREQ");
255 exit(1);
258 va.audio = 0;
259 va.volume = tunevol;
260 va.flags = 0;
261 va.mode = VIDEO_SOUND_STEREO;
263 ret = ioctl(fd, VIDIOCSAUDIO, &va); /* set the volume */
264 if (ret < 0) {
265 perror("ioctl VIDIOCSAUDIO");
266 exit(1);
269 if (!quiet)
270 printf("Radio tuned to %2.2f MHz at %2.2f%% volume\n",
271 (freq / fact), (tunevol / 655.35));
273 return 0;