Improve Automake packaging.
[fmtools.git] / fm.c
blob61aaaec8e9f9e2b231fa0988847614243798245f
1 /* fm.c - simple V4L2 compatible tuner for radio cards
3 Copyright (C) 2004, 2006, 2009 Ben Pfaff <blp@cs.stanford.edu>
4 Copyright (C) 1998 Russell Kroll <rkroll@exploits.org>
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 2 of the License, or (at your option)
9 any later version.
11 This program is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 more details.
16 You should have received a copy of the GNU General Public License along with
17 this program. If not, see <http://www.gnu.org/licenses/>.
20 #include <math.h>
21 #include <errno.h>
22 #include <stdio.h>
23 #include <fcntl.h>
24 #include <stdbool.h>
25 #include <stdint.h>
26 #include <stdlib.h>
27 #include <unistd.h>
28 #include <getopt.h>
29 #include <string.h>
30 #include <limits.h>
32 #include "fmlib.h"
34 #define DEFAULT_DEVICE "/dev/radio0"
36 static double
37 clamp(double percent)
39 return percent < 0.0 ? 0.0 : percent > 100.0 ? 100.0 : percent;
42 static int
43 convert_time (const char *string)
45 if (strcmp(string, "forever") == 0 ||
46 strcmp(string, "-") == 0 ||
47 atoi(string) < 0)
48 return 0;
49 else if (strcmp(string, "none") == 0 ||
50 strcmp(string, "0") == 0)
51 return -1;
52 else
54 char worktime[80+1];
55 int inttime;
56 const char *suffix;
58 suffix = string + strspn(string, "0123456789");
60 strncpy(worktime, string, suffix - string);
61 worktime[suffix - string] = '\0';
62 inttime = atoi(worktime);
64 switch (*suffix)
66 case 's':
67 case '\0':
68 break;
69 case 'm':
70 inttime *= 60;
71 break;
72 case 'h':
73 inttime *= 60 * 60;
74 break;
75 case 'd':
76 inttime *= 24 * 60 * 60;
77 break;
78 default:
79 break;
82 return inttime;
88 static char *
89 format_time (char *buffer, const char *string)
91 if (strcmp(string, "forever") == 0 ||
92 strcmp(string, "-") == 0 ||
93 atoi(string) < 0)
94 strcpy(buffer, "forever");
95 else if (strcmp(string, "none") == 0 ||
96 strcmp(string, "0") == 0)
97 strcpy(buffer, "none");
98 else
100 char worktime[80+1];
101 const char *suffix;
102 char *format;
103 int int_time;
105 suffix = string + strspn(string, "0123456789");
106 strncpy(worktime, string, suffix - string);
107 worktime[suffix - string] = '\0';
108 int_time = atoi(worktime);
110 switch (*suffix)
112 case 'm':
113 format = "%d minute(s)";
114 break;
115 case 'h':
116 format = "%d hour(s)";
117 break;
118 case 'd':
119 format = "%d day(s)";
120 break;
121 case 's':
122 case '\0':
123 default:
124 format = "%d second(s)";
125 break;
128 sprintf(buffer, format, int_time);
131 return buffer;
134 static void
135 maybe_sleep(const struct tuner *tuner, const char *wait_time)
137 char message[80+1];
138 int int_wait_time;
140 int_wait_time = convert_time(wait_time);
142 if (int_wait_time > 0)
144 printf("Sleeping for %s\n", format_time(message, wait_time));
145 tuner_sleep(tuner, int_wait_time);
146 } else if (int_wait_time == 0)
148 printf("Sleeping forever...CTRL-C exits\n");
149 for (;;)
150 pause();
154 static void
155 usage(void)
157 printf("fmtools fm version %s\n\n", VERSION);
158 printf("usage: %s [-h] [-o] [-q] [-d <dev>] [-t <tuner>] "
159 "[-T none|forever|time] <freq>|on|off [<volume>]\n\n",
160 program_name);
161 printf("A small controller for Video for Linux radio devices.\n\n");
162 printf(" -h display this help\n");
163 printf(" -o override frequency range limits of card\n");
164 printf(" -q quiet mode\n");
165 printf(" -d <dev> select device (default: /dev/radio0)\n");
166 printf(" -t <tuner> select tuner (default: 0)\n");
167 printf(" -T <time> after setting frequency, sleep for some time\n"\
168 " (default: none; -=forever)\n");
169 printf(" <freq> frequency in MHz (i.e. 94.3)\n");
170 printf(" on turn radio on\n");
171 printf(" off turn radio off (mute)\n");
172 printf(" + increase volume\n");
173 printf(" - decrease volume\n");
174 printf(" <volume> percentage (0-100)\n");
175 exit(EXIT_SUCCESS);
178 static void
179 getconfig(const char *fn,
180 double *defaultvol, double *increment, char *wait_time)
182 FILE *conf;
183 char buf[256];
185 if (!fn) {
186 snprintf(buf, sizeof buf, "%s/.fmrc", getenv("HOME"));
187 fn = buf;
189 conf = fopen(fn, "r");
191 if (!conf)
192 return;
194 while(fgets(buf, sizeof(buf), conf)) {
195 buf[strlen(buf)-1] = 0;
196 if (!strncmp(buf, "VOL", 3))
197 sscanf(buf, "%*s %lf", defaultvol);
198 if (!strncmp(buf, "INCR", 3))
199 sscanf(buf, "%*s %lf", increment);
200 if (!strncmp(buf, "TIME", 4))
201 sscanf(buf, "%*s %s", wait_time);
204 fclose(conf);
207 static void
208 print_volume(const struct tuner *tuner)
210 if (tuner_has_volume_control(tuner))
211 printf(" at %.2f%% volume", tuner_get_volume(tuner));
212 else
213 printf(" (radio does not support volume control)");
216 static void
217 print_mute(const struct tuner *tuner)
219 if (tuner_is_muted(tuner))
220 printf(" (radio is muted, use \"fm on\" to unmute)");
223 int main(int argc, char **argv)
225 struct tuner tuner;
226 const char *device = NULL;
227 int index = 0;
228 bool quiet = false;
229 bool override = false;
230 const char *config_file = NULL;
231 double defaultvol = 12.5;
232 double increment = 10;
233 char wait_time_buf[256+1] = "";
234 const char *wait_time = NULL;
236 program_name = argv[0];
238 /* need at least a frequency */
239 if (argc < 2)
240 fatal(0, "usage: %s [-h] [-o] [-q] [-d <dev>] [-t <tuner>] "
241 "[-T time|forever|none] "
242 "<freq>|on|off [<volume>]\n", program_name);
244 for (;;) {
245 int option = getopt(argc, argv, "+qhot:T:c:d:");
246 if (option == -1)
247 break;
249 switch (option) {
250 case 'q':
251 quiet = 1;
252 break;
253 case 'o':
254 override = 1;
255 break;
256 case 't':
257 index = atoi(optarg);
258 break;
259 case 'T':
260 wait_time = optarg;
261 break;
262 case 'd':
263 device = optarg;
264 break;
265 case 'c':
266 config_file = optarg;
267 break;
268 case 'h':
269 default:
270 usage();
271 break;
275 getconfig(config_file, &defaultvol, &increment, wait_time_buf);
276 if (!wait_time)
277 wait_time = *wait_time_buf ? wait_time_buf : "none";
279 argc -= optind;
280 argv += optind;
282 if (argc == 0) /* no frequency, on|off, or +|- given */
283 usage();
285 tuner_open(&tuner, device, index);
287 if (!strcmp(argv[0], "off")) {
288 tuner_set_mute(&tuner, true);
289 if (!quiet)
290 printf("Radio muted\n");
291 } else if (!strcmp(argv[0], "on")) {
292 tuner_set_mute(&tuner, false);
293 if (!quiet) {
294 printf("Radio on");
295 print_volume(&tuner);
296 putchar('\n');
298 } else if (!strcmp(argv[0], "+") || !strcmp(argv[0], "-")) {
299 double new_volume;
300 if (!tuner_has_volume_control(&tuner))
301 fatal(0, "Radio does not support volume control");
303 new_volume = tuner_get_volume(&tuner);
304 if (argv[0][0] == '+')
305 new_volume += increment;
306 else
307 new_volume -= increment;
308 new_volume = clamp(new_volume);
310 tuner_set_volume(&tuner, new_volume);
312 if (!quiet) {
313 printf("Setting volume to %.2f%%", new_volume);
314 print_mute(&tuner);
315 putchar('\n');
317 } else if (atof(argv[0])) {
318 double frequency = atof(argv[0]);
319 double volume = argc > 1 ? clamp(atof(argv[1])) : defaultvol;
320 tuner_set_freq(&tuner, frequency * 16000.0, override);
321 tuner_set_volume(&tuner, volume);
322 if (!quiet) {
323 printf("Radio tuned to %2.2f MHz", frequency);
324 print_volume(&tuner);
325 print_mute(&tuner);
326 putchar('\n');
328 } else {
329 fatal(0, "unrecognized command syntax; use --help for help");
331 maybe_sleep(&tuner, wait_time);
332 tuner_close(&tuner);
333 return 0;