vBulletin Search Engine Optimization
| |||||||
| Register | FAQ | Members List | Calendar | Search | Today's Posts | Mark Forums Read |
| ||||
| Fine. Though I must admit I often worry about how many programs are in /usr/bin. Do an ls sometime. > robert@ suggested that tunerctl(1), a program for manipulating > /dev/tunerN devices associated with bktr(4), be part of the > base system. mickey@ had also suggested this some time ago, > and now that bktr(4) behaves a little nicer, I think it would > be nice as well. > > below is a patch to add tunerctl and a manpage for it in > src/usr.bin. > > comments/testing would be appreciated, thanks! > > -- > <jakemsr@jakemsr.com> > > Index: usr.bin/Makefile > ================================================== ================= > RCS file: /home/cvs/OpenBSD/src/usr.bin/Makefile,v > retrieving revision 1.93 > diff -u -r1.93 Makefile > --- usr.bin/Makefile 28 May 2005 04:43:18 -0000 1.93 > +++ usr.bin/Makefile 4 Jul 2005 00:15:52 -0000 > @@ -19,8 +19,8 @@ > rup ruptime rusers rwall rwho script sectok sed shar showmount skey \ > skeyaudit skeyinfo skeyinit sort spell split ssh stat su sup systat \ > sudo tail talk tcopy tee telnet tftp tic time tip tn3270 top touch \ > - tput tr true tset tsort tty usbhidaction usbhidctl ul uname unexpand \ > - unifdef uniq units \ > + tput tr true tset tsort tty tunerctl usbhidaction usbhidctl ul uname \ > + unexpand unifdef uniq units \ > unvis users uudecode uuencode vacation vgrind vi vis vmstat w wall wc \ > what whatis which who whois window write x99token xargs xinstall xlint \ > xstr yacc yes > Index: usr.bin/tunerctl/Makefile > ================================================== ================= > RCS file: usr.bin/tunerctl/Makefile > diff -N usr.bin/tunerctl/Makefile > --- /dev/null 1 Jan 1970 00:00:00 -0000 > +++ usr.bin/tunerctl/Makefile 4 Jul 2005 00:17:00 -0000 > @@ -0,0 +1,6 @@ > +# $OpenBSD$ > + > +PROG= tunerctl > +CFLAGS+=-Wall > + > +.include <bsd.prog.mk> > Index: usr.bin/tunerctl/tunerctl.1 > ================================================== ================= > RCS file: usr.bin/tunerctl/tunerctl.1 > diff -N usr.bin/tunerctl/tunerctl.1 > --- /dev/null 1 Jan 1970 00:00:00 -0000 > +++ usr.bin/tunerctl/tunerctl.1 4 Jul 2005 01:13:02 -0000 > @@ -0,0 +1,129 @@ > +.\" > +.\" Copyright (c) 2005 Jacob Meuser <jakemsr@jakemsr.com> > +.\" > +.\" Permission to use, copy, modify, and distribute this software for any > +.\" purpose with or without fee is hereby granted, provided that the above > +.\" copyright notice and this permission notice appear in all copies. > +.\" > +.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES > +.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF > +.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR > +.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES > +.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN > +.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF > +.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. > +.\" > +.\" $OpenBSD$ > +.\" > +.Dd Mar 27, 2005 > +.Dt TUNERCTL 1 > +.Os > +.Sh NAME > +.Nm tunerctl > +.Nd manipulate > +.Xr bktr 4 > +tuner devices. > +.Sh SYNOPSIS > +.Nm > +.Op Fl nv > +.Op Fl f Ar file > +.Fl a > +.Nm > +.Op Fl nv > +.Op Fl f Ar file > +.Ar name > +.Op Ar ... > +.Nm > +.Op Fl q > +.Pf \ \& Op Fl f Ar file > +.Xo > +.Ar name Ns = Ns Ar value > +.Op Ar ... > +.Xc > +.Sh DESCRIPTION > +The > +.Nm > +command displays or sets various variables that affect the behaviour of > +.Xr bktr 4 > +device tuners. > +If a list of variables is present on the command line, > +.Nm > +prints the current value of those variables for the specified device. > +By default, > +.Nm > +operates on the > +.Pa /dev/tuner0 > +device. > +.Pp > +The options are as follows: > +.Bl -tag -width "name=value" > +.It Fl a > +Print all device variables and their current values. > +.It Fl f Ar file > +Specify an alternative tuner device. > +.It Fl n > +Suppress printing of the variable names. > +.It Fl q > +Suppress all printing when setting a variable. > +.It Fl v > +Show the possible values of enumeration and range valued queries. > +Enumeration values are show in > +.Dq [] > +and ranges are show in > +.Dq () . > +.It Ar name Ns = Ns Ar value > +Attempt to set the specified variable > +.Ar name > +to > +.Ar value . > +.El > +.Pp > +Depending on the features of a specific tuner, the setting of some > +variables may not have any effect. > +.Pp > +Variable names explained: > +.Bl -tag -width contrast > +.It Ic chanset > +TV tuner channel set. > +.It Ic channel > +TV tuner channel. > +.It Ic freq > +Frequency in MHz. > +.It Ic afc > +Automatic Frequency Control. > +.It Ic audio > +Audio source. > +.It Ic mute > +Audio mute. > +.It Ic bright > +Video brightness. > +.It Ic contrast > +Video contrast. > +.It Ic hue > +Video hue. > +.It Ic usat > +Video > +.Ql U > +(blue) saturation. > +.It Ic vsat > +Video > +.Ql V > +(red) saturation. > +.El > +.Sh FILES > +.Bl -tag -width /dev/tuner0 > +.It Pa /dev/tuner0 > +default tuner device > +.El > +.Sh EXAMPLES > +The command > +.Pp > +.Dl "$ tunerctl chanset=nabcst channel=13" > +.Pp > +sets the tuner to North American broadcast TV channel 13. > +.Sh SEE ALSO > +.Xr bktr 4 > +.Sh AUTHORS > +.Nm > +and this manual page were written by > +.An Jacob Meuser Aq jakemsr@jakemsr.com . > Index: usr.bin/tunerctl/tunerctl.c > ================================================== ================= > RCS file: usr.bin/tunerctl/tunerctl.c > diff -N usr.bin/tunerctl/tunerctl.c > --- /dev/null 1 Jan 1970 00:00:00 -0000 > +++ usr.bin/tunerctl/tunerctl.c 4 Jul 2005 00:43:12 -0000 > @@ -0,0 +1,469 @@ > +/* > + * Copyright (c) 2005 Jacob Meuser <jakemsr@jakemsr.com> > + * > + * Permission to use, copy, modify, and distribute this software for any > + * purpose with or without fee is hereby granted, provided that the above > + * copyright notice and this permission notice appear in all copies. > + * > + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES > + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF > + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR > + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES > + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN > + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF > + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. > + */ > + > +/* > + * $OpenBSD$ > + */ > + > + > +#include <sys/param.h> > +#include <sys/ioctl.h> > +#include <sys/stat.h> > + > +#include <dev/ic/bt8xx.h> > + > +#include <err.h> > +#include <fcntl.h> > +#include <stdio.h> > +#include <stdlib.h> > +#include <string.h> > +#include <unistd.h> > + > +#define DEFAULT_TUNER_DEVICE "/dev/tuner0" > + > +struct fields { > + char *name; > + int type; > +#define INT 1 > +#define ASRC 2 > +#define CSET 3 > +#define MUTE 4 > +#define OFFON 5 > +#define FREQ 6 > +#define VSAT 7 > +#define USAT 8 > +#define HUE 9 > +#define BRIGHT 10 > +#define CONTR 11 > + int val; > + long io_set; > + long io_get; > + int valmin; > + int valmax; > +} fields[] = { > +{ "chanset", CSET, 0, TVTUNER_SETTYPE, TVTUNER_GETTYPE, 0, 0 }, > +{ "channel", INT, 0, TVTUNER_SETCHNL, TVTUNER_GETCHNL, 0, 150 }, > +{ "freq", FREQ, 0, TVTUNER_SETFREQ, TVTUNER_GETFREQ, 608, 14240 }, > +{ "afc", OFFON, 0, TVTUNER_SETAFC, TVTUNER_GETAFC, 0, 1 }, > +{ "audio", ASRC, 0, BT848_SAUDIO, BT848_GAUDIO, 0, 0 }, > +{ "mute", MUTE, 0, BT848_SAUDIO, BT848_GAUDIO, 0, 1 }, > +{ "bright", BRIGHT, 0, BT848_SBRIG, BT848_GBRIG, > + BT848_BRIGHTMIN, BT848_BRIGHTMAX }, > +{ "contrast", CONTR, 0, BT848_SCONT, BT848_GCONT, > + BT848_CONTRASTMIN, BT848_CONTRASTMAX }, > +{ "hue", HUE, 0, BT848_SHUE, BT848_GHUE, BT848_HUEMIN, > + BT848_HUEMAX }, > +{ "usat", USAT, 0, BT848_SUSAT, BT848_GUSAT, BT848_SATUMIN, > + BT848_SATUMAX }, > +{ "vsat", VSAT, 0, BT848_SVSAT, BT848_GVSAT, BT848_SATVMIN, > + BT848_SATVMAX }, > +{ 0, 0, 0, 0, 0, 0, 0} > +}; > + > +struct chansets { > + int value; > + char *name; > +} chansets[] = { > +{ CHNLSET_NABCST, "nabcst", }, > +{ CHNLSET_CABLEIRC, "cableirc", }, > +{ CHNLSET_CABLEHRC, "cablehrc", }, > +{ CHNLSET_WEUROPE, "weurope", }, > +{ CHNLSET_JPNBCST, "jpnbcst", }, > +{ CHNLSET_JPNCABLE, "jpncable", }, > +{ CHNLSET_XUSSR, "xussr", }, > +{ CHNLSET_AUSTRALIA, "australia", }, > +{ CHNLSET_FRANCE, "france", }, > +{ 0, 0 } > +}; > + > +struct audiosources { > + int value; > + char *name; > +} audiosources[] = { > +{ AUDIO_TUNER, "tuner", }, > +{ AUDIO_EXTERN, "extern", }, > +{ AUDIO_INTERN, "intern", }, > +{ 0, 0 } > +}; > + > +int tuner_fd; > +int print_choices; > +int print_name; > +int print_value; > + > +__dead void usage(void); > +int run(int, char *); > +int findfield(char *); > +int prfield(int); > +int do_ioctls(int, char *); > +#define OFF 0 > +#define ON 1 > +int isoffon(const char *); > + > + > +/* getopt externs */ > +extern char *optarg; > +extern int opterr; > +extern int optind; > +extern int optopt; > +extern int optreset; > + > + > +__dead void > +usage(void) > +{ > + extern char *__progname; > + > + fprintf(stderr, > + "usage: %s [-nv] [-f file] -a\n" > + " %s [-nv] [-f file] name [...]\n" > + " %s [-q] [-f file] name=value [...]\n", > + __progname, __progname, __progname); > + > + exit (1); > +} > + > +int > +isoffon(const char *offon) > +{ > + if (strncmp(offon, "off", 3) == 0) > + return (OFF); > + else if (strncmp(offon, "on", 2) == 0) > + return (ON); > + > + return (-1); > +} > + > +int > +findfield(char *name) > +{ > + int i, found = 0; > + > + for (i = 0; fields[i].name; i++) { > + if (strncmp(fields[i].name, name, strlen(fields[i].name)) ==0) { > + found = 1; > + break; > + } > + } > + if (found == 1) > + return (i); > + else > + return (-1); > +} > + > +int > +prfield(int index) > +{ > + int switchval; > + int i; > + > + if (print_name == 1) > + printf("%s=", fields[index].name); > + > + if (ioctl(tuner_fd, fields[index].io_get, &fields[index].val) < 0) { > + warn("%s", fields[index].name); > + return (1); > + } > + > + switchval = fields[index].type; > + switch (switchval) { > + case ASRC: > + for (i = 0; audiosources[i].name; i++) > + if (audiosources[i].value == > + (fields[index].val & ~AUDIO_MUTE)) > + break; > + printf("%s", audiosources[i].name); > + if (print_choices == 1) { > + printf(" [ "); > + for (i = 0; audiosources[i].name; i++) > + printf("%s ", audiosources[i].name); > + printf("]"); > + } > + break; > + case CSET: > + for (i = 0; chansets[i].name; i++) > + if (chansets[i].value == fields[index].val) > + break; > + printf("%s", chansets[i].name); > + if (print_choices == 1) { > + printf(" [ "); > + for (i = 0; chansets[i].name; i++) > + printf("%s ", chansets[i].name); > + printf("]"); > + } > + break; > + case FREQ: > + printf("%0.2f", (double)fields[index].val / 16); > + if (print_choices == 1) > + printf(" ( %0.2f - %0.2f )", > + (double)fields[index].valmin / 16, > + (double)fields[index].valmax / 16); > + break; > + case INT: > + case BRIGHT: > + case CONTR: > + case HUE: > + case VSAT: > + case USAT: > + i = fields[index].val; > + if (switchval == BRIGHT) { > + i = (i - BT848_BRIGHTREGMIN) * > + BT848_BRIGHTRANGE / BT848_BRIGHTSTEPS + > + BT848_BRIGHTMIN + (i < 0 ? -0.5 : 0.5); > + } else if (switchval == CONTR) { > + i = (i - BT848_CONTRASTREGMIN) * > + BT848_CONTRASTRANGE / BT848_CONTRASTSTEPS + > + BT848_CONTRASTMIN + (i < 0 ? -0.5 : 0.5); > + } else if (switchval == HUE) { > + i = (i - BT848_HUEREGMIN) * > + BT848_HUERANGE / BT848_HUESTEPS + > + BT848_HUEMIN + (i < 0 ? -0.5 : 0.5); > + } else if (switchval == USAT) { > + i = (i - BT848_SATUREGMIN) * > + BT848_SATURANGE / BT848_SATUSTEPS + > + BT848_SATUMIN + (i < 0 ? -0.5 : 0.5); > + } else if (switchval == VSAT) { > + i = (i - BT848_SATVREGMIN) * > + BT848_SATVRANGE / BT848_SATVSTEPS + > + BT848_SATVMIN + (i < 0 ? -0.5 : 0.5); > + } > + printf("%d", i); > + if (print_choices == 1) > + printf(" ( %d - %d )", fields[index].valmin, > + fields[index].valmax); > + break; > + case MUTE: > + case OFFON: > + if (((switchval == MUTE) && (fields[index].val & AUDIO_MUTE)) || > + ((switchval != MUTE) && (fields[index].val == 1))) > + printf("on"); > + else > + printf("off"); > + if (print_choices == 1) > + printf(" [ off on ]"); > + break; > + default: > + warnx("internal error: prfield"); > + break; > + } > + printf("\n"); > + > + return (0); > +} > + > +int > +do_ioctls(int index, char *arg) > +{ > + const char *errstr; > + int i; > + int switchval; > + > + switchval = fields[index].type; > + > + if (arg != NULL) { > + switch(switchval) { > + case ASRC: > + for (i = 0; audiosources[i].name; i++) > + if (strncmp(audiosources[i].name, arg, > + strlen(audiosources[i].name)) == 0) > + break; > + if (audiosources[i].name[0] != '\0') > + fields[index].val = audiosources[i].value; > + else { > + warnx("%s is invalid: %s", fields[index].name, > + arg); > + return (1); > + } > + break; > + case CSET: > + for (i = 0; chansets[i].name; i++) > + if (strncmp(chansets[i].name, arg, > + strlen(chansets[i].name)) == 0) > + break; > + if (chansets[i].name[0] != '\0') > + fields[index].val = chansets[i].value; > + else { > + warnx("%s is invalid: %s", fields[index].name, > + arg); > + return (1); > + } > + break; > + case FREQ: > + fields[index].val = strtod(arg, (char **)NULL) * 16; > + if ((fields[index].val < fields[index].valmin) || > + (fields[index].val > fields[index].valmax)) { > + warnx("%s is invalid: %s", fields[index].name, > + arg); > + return (1); > + } > + break; > + case INT: > + case BRIGHT: > + case CONTR: > + case HUE: > + case USAT: > + case VSAT: > + i = strtonum(arg, fields[index].valmin, > + fields[index].valmax, &errstr); > + if (errstr != NULL) { > + warnx("%s is %s: %s", fields[index].name, > + errstr, arg); > + return (1); > + } > + if (switchval == BRIGHT) { > + i = (i - BT848_BRIGHTMIN) * > + BT848_BRIGHTSTEPS / BT848_BRIGHTRANGE + > + BT848_BRIGHTREGMIN + (i < 0 ? -0.5 : 0.5); > + if (i > BT848_BRIGHTREGMAX) > + i = BT848_BRIGHTREGMAX; > + } else if (switchval == CONTR) { > + i = (i - BT848_CONTRASTMIN) * > + BT848_CONTRASTSTEPS / BT848_CONTRASTRANGE + > + BT848_CONTRASTREGMIN + (i < 0 ? -0.5 : 0.5); > + if (i > BT848_CONTRASTREGMAX) > + i = BT848_CONTRASTREGMAX; > + } else if (switchval == HUE) { > + i = (i - BT848_HUEMIN) * > + BT848_HUESTEPS / BT848_HUERANGE + > + BT848_HUEREGMIN + (i < 0 ? -0.5 : 0.5); > + if (i > BT848_HUEREGMAX) > + i = BT848_HUEREGMAX; > + } else if (switchval == USAT) { > + i = (i - BT848_SATUMIN) * > + BT848_SATUSTEPS / BT848_SATURANGE + > + BT848_SATUREGMIN + (i < 0 ? -0.5 : 0.5); > + if (i > BT848_SATUREGMAX) > + i = BT848_SATUREGMAX; > + } else if (switchval == VSAT) { > + i = (i - BT848_SATVMIN) * > + BT848_SATVSTEPS / BT848_SATVRANGE + > + BT848_SATVREGMIN + (i < 0 ? -0.5 : 0.5); > + if (i > BT848_SATVREGMAX) > + i = BT848_SATVREGMAX; > + } > + fields[index].val = i; > + break; > + case MUTE: > + case OFFON: > + fields[index].val = isoffon(arg); > + if (fields[index].val < 0) { > + warnx("%s is invalid: %s", fields[index].name, > + optarg); > + return (1); > + } > + if (switchval == MUTE) { > + if (fields[index].val == 1) > + fields[index].val = AUDIO_MUTE; > + else > + fields[index].val = AUDIO_UNMUTE; > + } > + break; > + default: > + warnx("internal error: do_ioctls: set"); > + break; > + } > + if (ioctl(tuner_fd, fields[index].io_set,&fields[index].val)<0){ > + warn("%s", fields[index].name); > + return (1); > + } > + } else { > + /* nothing is being set, so the -q option is meaningless */ > + print_value = 1; > + } > + > + if (print_value == 1) > + if (prfield(index) > 0) > + return (1); > + > + return (0); > +} > + > + > +int > +main(int argc, char *argv[]) > +{ > + char *device = DEFAULT_TUNER_DEVICE; > + int aflag = 0; > + int err = 0; > + int ch, i; > + > + print_choices = 0; > + print_name = 1; > + print_value = 1; > + > + while ((ch = getopt(argc, argv, "af:nqv")) != -1) { > + switch (ch) { > + case 'a': > + aflag++; > + break; > + case 'f': > + device = optarg; > + break; > + case 'n': > + print_name = 0; > + break; > + case 'q': > + print_value = 0; > + break; > + case 'v': > + print_choices = 1; > + break; > + default: > + usage(); > + } > + } > + argc -= optind; > + argv += optind; > + > + if ((argc == 0) && (aflag == 0)) > + usage(); > + > + if ((tuner_fd = open(device, O_RDONLY)) < 0) { > + warn("%s", device); > + close(tuner_fd); > + exit (1); > + } > + > + if (aflag > 0) { > + for (i = 0; fields[i].name; i++) { > + if (do_ioctls(i, NULL) > 0) { > + err++; > + break; > + } > + } > + } else { > + for (; argc--; argv++) { > + char *q; > + > + q = strchr(*argv, '='); > + i = findfield(*argv); > + if (i < 0) { > + warnx("field '%s' does not exist", *argv); > + err++; > + break; > + } else { > + if (q != NULL) > + *q++ = 0; > + if (do_ioctls(i, q) > 0) { > + err++; > + break; > + } > + } > + } > + } > + close(tuner_fd); > + exit (err); > +} |