shithub: riscv

Download patch

ref: bf555abcc3056ec74b785b6ff3f8e4b398ef09de
parent: 657f0ed99a23c2ee6872d890c8ca8ef97fed9ac9
author: aiju <devnull@localhost>
date: Wed Mar 7 15:45:19 EST 2018

add camv

--- /dev/null
+++ b/sys/src/cmd/camv.c
@@ -1,0 +1,243 @@
+#include <u.h>
+#include <libc.h>
+#include <thread.h>
+#include <draw.h>
+#include <bio.h>
+#include <mouse.h>
+#include <keyboard.h>
+
+Screen *scr;
+Image *disp;
+Mousectl *mc;
+Keyboardctl *kc;
+int ctlfd;
+char *videoname;
+
+typedef struct Control Control;
+struct Control {
+	char *unit, *ctrl;
+	char *value;
+	char *info;
+	Control *next;
+};
+Control *ctls;
+
+Image *bg;
+
+void *
+emalloc(ulong n)
+{
+	void *v;
+	
+	v = malloc(n);
+	if(v == nil) sysfatal("malloc: %r");
+	memset(v, 0, n);
+	setmalloctag(v, getcallerpc(&n));
+	return v;
+}
+
+void
+screeninit(void)
+{
+	bg = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0xCCCCCCFF);
+	scr = allocscreen(screen, bg, 0);
+	disp = allocwindow(scr, screen->r, 0, 0xCCCCCCFF);
+	draw(screen, screen->r, bg, nil, ZP);
+	flushimage(display, 1);
+}
+
+void
+usage(void)
+{
+	fprint(2, "usage: %s cam-device\n", argv0);
+	threadexitsall("usage");
+}
+
+void
+readctls(void)
+{
+	char *s;
+	char *f[5];
+	int nf;
+	static Biobuf *bp;
+	Control *c, **cp;
+	
+	if(bp == nil)
+		bp = Bfdopen(ctlfd, OREAD);
+	Bflush(bp);
+	Bseek(bp, 0, 0);
+	assert(bp != nil);
+	cp = &ctls;
+	for(; s = Brdstr(bp, '\n', 1), s != nil; free(s)){
+		nf = tokenize(s, f, nelem(f));
+		if(nf < 3){
+			fprint(2, "don't know how to interpret ctl line: %s\n", s);
+			continue;
+		}
+		c = emalloc(sizeof(Control));
+		c->unit = strdup(f[0]);
+		c->ctrl = strdup(f[1]);
+		c->value = strdup(f[2]);
+		if(nf >= 4) c->info = strdup(f[3]);
+		*cp = c;
+		cp = &c->next;
+	}
+}
+
+void
+freectls(void)
+{
+	Control *c, *d;
+	
+	for(c = ctls; c != nil; c = d){
+		d = c->next;
+		free(c->unit);
+		free(c->ctrl);
+		free(c->value);
+		free(c->info);
+		free(c);
+	}
+	ctls = nil;
+}
+
+void
+opencamera(char *dir)
+{
+	char *s;
+	
+	s = smprint("%s/ctl", dir);
+	ctlfd = open(s, ORDWR);
+	if(ctlfd < 0) sysfatal("open: %r");
+	free(s);
+	readctls();
+	videoname = smprint("%s/video", dir);
+}
+
+void
+resizethread(void *)
+{
+	ulong dummy;
+
+	while(recv(mc->resizec, &dummy) > 0){
+		lockdisplay(display);
+		if(getwindow(display, Refnone) < 0)
+			sysfatal("resize failed: %r");
+		screeninit();
+		unlockdisplay(display);
+	}
+}
+
+void
+rmb(void)
+{
+	enum {
+		QUIT,
+	};
+	static char *items[] = {
+		[QUIT] "quit",
+		nil,
+	};
+	static Menu menu = { .item = items };
+	switch(menuhit(3, mc, &menu, scr)){
+	case QUIT:
+		threadexitsall(nil);
+	}
+}
+
+char *
+ctlgen(int n)
+{
+	Control *c;
+	static char buf[512];
+	
+	for(c = ctls; n-- > 0 && c != nil; c = c->next)
+		;
+	if(c == nil)
+		return nil;
+	snprint(buf, sizeof(buf), "%s(%s) = %s", c->ctrl, c->unit, c->value);
+	return buf;
+	
+}
+
+void
+mmb(void)
+{
+	static char buf[512];
+	static char nval[512];
+	int n;
+	Control *c;
+	Menu menu = { .gen = ctlgen };
+	
+	n = menuhit(2, mc, &menu, scr);
+	if(n < 0) return;
+	for(c = ctls; n-- > 0 && c != nil; c = c->next)
+		;
+	assert(c != nil);
+	snprint(buf, sizeof(buf), "%s(%s) = %s%c(%s)", c->ctrl, c->unit, c->value, c->info != nil ? ' ' : 0, c->info);
+	nval[0] = 0;
+	if(enter(buf, nval, sizeof(nval), mc, kc, scr) <= 0) return;
+	if(fprint(ctlfd, "%q %q %q", c->unit, c->ctrl, nval) < 0){
+		fprint(2, "fprint: %r\n");
+		return;
+	}
+	freectls();
+	readctls();
+}
+
+void
+videoproc(void *)
+{
+	int fd;
+	Image *i;
+	Point p, q;
+	Rectangle r;
+
+restart:	
+	fd = open(videoname, OREAD);
+	if(fd < 0) sysfatal("open: %r");
+	for(;;){
+		i = readimage(display, fd, 1);
+		if(i == nil) break;
+		p = divpt(addpt(screen->r.min, screen->r.max), 2);
+		q = divpt(subpt(i->r.max, i->r.min), 2);
+		r = (Rectangle){subpt(p, q), addpt(p, q)};
+		lockdisplay(display);
+		draw(disp, r, i, nil, i->r.min);
+		flushimage(display, 1);
+		freeimage(i);
+		unlockdisplay(display);
+	}
+	fprint(2, "readimage: %r\n");
+	close(fd);
+	goto restart;
+}
+
+void
+threadmain(int argc, char **argv)
+{
+	ARGBEGIN {
+	default: usage();
+	} ARGEND;
+	
+	quotefmtinstall();
+	if(argc != 1) usage();
+	opencamera(argv[0]);
+	
+	if(initdraw(nil, nil, "camv") < 0)
+		sysfatal("initdraw: %r");
+	screeninit();
+	kc = initkeyboard(nil);
+	if(kc == nil) sysfatal("initkeyboard: %r");
+	mc = initmouse(nil, screen);
+	if(mc == nil) sysfatal("initmouse: %r");
+	threadcreate(resizethread, nil, mainstacksize);
+	proccreate(videoproc, nil, mainstacksize);
+	display->locking = 1;
+	unlockdisplay(display);
+	while(readmouse(mc) >= 0){
+		if((mc->buttons & 4) != 0)
+			rmb();
+		else if((mc->buttons & 2) != 0)
+			mmb();
+	}
+}