video(1) allows users to adjust controls such as brightness, saturation
(etc.) depending on the input device in question. These values persist even
after video(1) has quit, allowing you to e.g. increase the brightness of a
webcam before connecting to a video call. However, the only way to adjust
values is to hold down keys in the GUI, which is slow, error prone, and
can't easily be scripted.
This patch adds a "-c" option to video(1) which either takes the special
value "reset" or a "control=value" pair. For example:
$ video -c reset
resets all the controls to their default values. Assuming the input device
in question supports brightness one can set that as follows:
$ video -c brightness=200
Note that the available controls, and their min/max values, will vary from
device to device.
To keep the patch simple, only one "-c" option can be passed to video(1) at
a time. Note that passing this option causes video(1) to quit before
displaying video (in identical fashion to "-q") which makes it useful for
scripting purposes.
Laurie
Index: video.1
===================================================================
RCS file: /cvs/xenocara/app/video/video.1,v
retrieving revision 1.14
diff -u -r1.14 video.1
--- video.1 25 Feb 2019 12:34:35 -0000 1.14
+++ video.1 13 Jul 2020 18:33:51 -0000
@@ -27,6 +27,7 @@
.Bk -words
.Op Fl \&gqRv
.Op Fl a Ar adaptor
+.Op Fl c Ar reset | control=value
.Op Fl e Ar encoding
.Op Fl f Ar file
.Op Fl i Ar input
@@ -81,6 +82,15 @@
adaptor to use.
The default is 0, the first adaptor reported by
.Xr X 7 .
+.It Fl c Ar reset | control=value
+Set control value (e.g. brightness) and exit. The special name
+.Ql reset
+resets all values to their default. The available controls can be found
+with
+.Fl q
+and the default values with
+.Fl c Ar reset
+.Fl v .
.It Fl e Ar encoding
Lowercase FOURCC name of video encoding to use.
Valid arguments are
Index: video.c
===================================================================
RCS file: /cvs/xenocara/app/video/video.c,v
retrieving revision 1.30
diff -u -r1.30 video.c
--- video.c 1 Jul 2020 06:45:24 -0000 1.30
+++ video.c 13 Jul 2020 18:33:51 -0000
@@ -189,7 +189,10 @@
#define M_IN_FILE 0x4
#define M_OUT_FILE 0x8
#define M_QUERY 0x10
+#define M_RESET 0x20
+#define M_SET_CTRL 0x40
int mode;
+ char *set_ctrl_str;
int verbose;
};
@@ -212,6 +215,7 @@
void dev_set_ctrl(struct video *, int, int);
void dev_reset_ctrls(struct video *);
+int parse_ctrl(struct video *, int *, int *);
int parse_size(struct video *);
int choose_size(struct video *);
int choose_enc(struct video *);
@@ -237,9 +241,9 @@
usage(void)
{
fprintf(stderr, "usage: %s [-gqRv] "
- "[-a adaptor] [-e encoding] [-f file] [-i input] [-O output]\n"
- " %*s [-o output] [-r rate] [-s size]\n", __progname,
- (int)strlen(__progname), "");
+ "[-a adaptor] [-c reset|control=value] [-e encoding] [-f file]\n"
+ " %*s [-i input] [-O output] [-o output] [-r rate] [-s
size]\n",
+ __progname, (int)strlen(__progname), "");
}
int
@@ -1172,6 +1176,38 @@
return 1;
}
+
+int
+parse_ctrl(struct video *vid, int *ctrl_id, int *ctrl_val)
+{
+ char *valp;
+ const char *errstr;
+
+ if (!vid->set_ctrl_str) {
+ return 0;
+ }
+
+ valp = strsep(&vid->set_ctrl_str, "=");
+ if (*valp == '\0' || vid->set_ctrl_str == '\0') {
+ return 0;
+ }
+ for (*ctrl_id = 0; *ctrl_id < CTRL_LAST; (*ctrl_id)++) {
+ if (strcmp(valp, ctrls[*ctrl_id].name) == 0) {
+ break;
+ }
+ }
+ if (*ctrl_id == CTRL_LAST) {
+ warnx("Unknown control '%s'", valp);
+ return 0;
+ }
+ *ctrl_val = strtonum(vid->set_ctrl_str, ctrls[*ctrl_id].min,
ctrls[*ctrl_id].max, &errstr);
+ if (errstr != NULL) {
+ warnx("control value '%s' is %s", valp, errstr);
+ return 0;
+ }
+ return 1;
+}
+
int
parse_size(struct video *vid)
{
@@ -1432,6 +1468,8 @@
int
setup(struct video *vid)
{
+ int ctrl_id, ctrl_val;
+
if (vid->mode & M_IN_FILE) {
if (!strcmp(vid->iofile, "-"))
vid->iofile_fd = STDIN_FILENO;
@@ -1471,6 +1509,19 @@
if (!parse_size(vid) || !choose_size(vid))
return 0;
+ if (vid->mode & M_RESET) {
+ dev_reset_ctrls(vid);
+ return 1;
+ }
+
+ if (vid->mode & M_SET_CTRL) {
+ if (!parse_ctrl(vid, &ctrl_id, &ctrl_val)) {
+ return 0;
+ }
+ dev_set_ctrl(vid, ctrl_id, ctrl_val);
+ return 1;
+ }
+
vid->bpf = vid->width * vid->height * encs[vid->enc].bpp / NBBY;
if (vid->verbose > 0) {
@@ -1900,7 +1951,7 @@
vid.mmap_on = 1; /* mmap method is default */
wout = 1;
- while ((ch = getopt(argc, argv, "gqRva:e:f:i:O:o:r:s:")) != -1) {
+ while ((ch = getopt(argc, argv, "gqRva:c:e:f:i:O:o:r:s:")) != -1) {
switch (ch) {
case 'a':
x->cur_adap = strtonum(optarg, 0, 4, &errstr);
@@ -1909,6 +1960,17 @@
errs++;
}
break;
+ case 'c':
+ if ((vid.mode & M_RESET) || (vid.mode & M_SET_CTRL)) {
+ warnx("Only one '-c' option allowed.");
+ errs++;
+ } else if (strcmp(optarg, "reset") == 0) {
+ vid.mode |= M_RESET;
+ } else {
+ vid.mode |= M_SET_CTRL;
+ vid.set_ctrl_str = strdup(optarg);
+ }
+ break;
case 'e':
vid.enc = find_enc(optarg);
if (vid.enc >= ENC_LAST) {
@@ -2006,6 +2068,10 @@
if (!setup(&vid))
cleanup(&vid, 1);
+
+ if ((vid.mode & M_RESET) || (vid.mode & M_SET_CTRL)) {
+ cleanup(&vid, 0);
+ }
if (vid.mode & M_IN_FILE) {
if (pledge("stdio rpath", NULL) == -1)