]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/camv.c
f3977fe7c4be99cf0c378c1fe6bf4a691517976f
[plan9front.git] / sys / src / cmd / camv.c
1 #include <u.h>
2 #include <libc.h>
3 #include <thread.h>
4 #include <draw.h>
5 #include <bio.h>
6 #include <mouse.h>
7 #include <keyboard.h>
8
9 Screen *scr;
10 Image *disp;
11 Mousectl *mc;
12 Keyboardctl *kc;
13 int ctlfd;
14 char *videoname;
15
16 typedef struct Control Control;
17 struct Control {
18         char *unit, *ctrl;
19         char *value;
20         char *info;
21         Control *next;
22 };
23 Control *ctls;
24
25 Image *bg;
26
27 void *
28 emalloc(ulong n)
29 {
30         void *v;
31         
32         v = malloc(n);
33         if(v == nil) sysfatal("malloc: %r");
34         memset(v, 0, n);
35         setmalloctag(v, getcallerpc(&n));
36         return v;
37 }
38
39 void
40 screeninit(void)
41 {
42         bg = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0xCCCCCCFF);
43         scr = allocscreen(screen, bg, 0);
44         disp = allocwindow(scr, screen->r, 0, 0xCCCCCCFF);
45         draw(screen, screen->r, bg, nil, ZP);
46         flushimage(display, 1);
47 }
48
49 void
50 usage(void)
51 {
52         fprint(2, "usage: %s cam-device\n", argv0);
53         threadexitsall("usage");
54 }
55
56 void
57 readctls(void)
58 {
59         char *s;
60         char *f[5];
61         int nf;
62         static Biobuf *bp;
63         Control *c, **cp;
64         
65         if(bp == nil)
66                 bp = Bfdopen(ctlfd, OREAD);
67         Bflush(bp);
68         Bseek(bp, 0, 0);
69         assert(bp != nil);
70         cp = &ctls;
71         for(; s = Brdstr(bp, '\n', 1), s != nil; free(s)){
72                 nf = tokenize(s, f, nelem(f));
73                 if(nf < 3){
74                         fprint(2, "don't know how to interpret ctl line: %s\n", s);
75                         continue;
76                 }
77                 c = emalloc(sizeof(Control));
78                 c->unit = strdup(f[0]);
79                 c->ctrl = strdup(f[1]);
80                 c->value = strdup(f[2]);
81                 if(nf >= 4) c->info = strdup(f[3]);
82                 *cp = c;
83                 cp = &c->next;
84         }
85 }
86
87 void
88 freectls(void)
89 {
90         Control *c, *d;
91         
92         for(c = ctls; c != nil; c = d){
93                 d = c->next;
94                 free(c->unit);
95                 free(c->ctrl);
96                 free(c->value);
97                 free(c->info);
98                 free(c);
99         }
100         ctls = nil;
101 }
102
103 void
104 opencamera(char *dir)
105 {
106         char *s;
107         
108         s = smprint("%s/ctl", dir);
109         ctlfd = open(s, ORDWR);
110         if(ctlfd < 0) sysfatal("open: %r");
111         free(s);
112         readctls();
113         videoname = smprint("%s/video", dir);
114 }
115
116 void
117 resizethread(void *)
118 {
119         ulong dummy;
120
121         while(recv(mc->resizec, &dummy) > 0){
122                 lockdisplay(display);
123                 if(getwindow(display, Refnone) < 0)
124                         sysfatal("resize failed: %r");
125                 screeninit();
126                 unlockdisplay(display);
127         }
128 }
129
130 void
131 rmb(void)
132 {
133         enum {
134                 QUIT,
135         };
136         static char *items[] = {
137                 [QUIT] "quit",
138                 nil,
139         };
140         static Menu menu = { .item = items };
141         switch(menuhit(3, mc, &menu, scr)){
142         case QUIT:
143                 threadexitsall(nil);
144         }
145 }
146
147 char *
148 ctlgen(int n)
149 {
150         Control *c;
151         static char buf[512];
152         
153         for(c = ctls; n-- > 0 && c != nil; c = c->next)
154                 ;
155         if(c == nil)
156                 return nil;
157         snprint(buf, sizeof(buf), "%s(%s) = %s", c->ctrl, c->unit, c->value);
158         return buf;
159         
160 }
161
162 void
163 mmb(void)
164 {
165         static char buf[512];
166         static char nval[512];
167         int n;
168         Control *c;
169         Menu menu = { .gen = ctlgen };
170         
171         n = menuhit(2, mc, &menu, scr);
172         if(n < 0) return;
173         for(c = ctls; n-- > 0 && c != nil; c = c->next)
174                 ;
175         assert(c != nil);
176         snprint(buf, sizeof(buf), "%s(%s) = %s%c(%s)", c->ctrl, c->unit, c->value, c->info != nil ? ' ' : 0, c->info);
177         nval[0] = 0;
178         if(enter(buf, nval, sizeof(nval), mc, kc, scr) <= 0) return;
179         if(fprint(ctlfd, "%q %q %q", c->unit, c->ctrl, nval) < 0){
180                 fprint(2, "fprint: %r\n");
181                 return;
182         }
183         freectls();
184         readctls();
185 }
186
187 void
188 videoproc(void *)
189 {
190         int fd;
191         Image *i;
192         Point p, q;
193         Rectangle r;
194
195 restart:        
196         fd = open(videoname, OREAD);
197         if(fd < 0) sysfatal("open: %r");
198         for(;;){
199                 i = readimage(display, fd, 1);
200                 if(i == nil) break;
201                 p = divpt(addpt(screen->r.min, screen->r.max), 2);
202                 q = divpt(subpt(i->r.max, i->r.min), 2);
203                 r = (Rectangle){subpt(p, q), addpt(p, q)};
204                 lockdisplay(display);
205                 draw(disp, r, i, nil, i->r.min);
206                 freeimage(i);
207                 flushimage(display, 1);
208                 unlockdisplay(display);
209         }
210         fprint(2, "readimage: %r\n");
211         close(fd);
212         goto restart;
213 }
214
215 void
216 threadmain(int argc, char **argv)
217 {
218         ARGBEGIN {
219         default: usage();
220         } ARGEND;
221         
222         quotefmtinstall();
223         if(argc != 1) usage();
224         opencamera(argv[0]);
225         
226         if(initdraw(nil, nil, "camv") < 0)
227                 sysfatal("initdraw: %r");
228         screeninit();
229         kc = initkeyboard(nil);
230         if(kc == nil) sysfatal("initkeyboard: %r");
231         mc = initmouse(nil, screen);
232         if(mc == nil) sysfatal("initmouse: %r");
233         threadcreate(resizethread, nil, mainstacksize);
234         proccreate(videoproc, nil, mainstacksize);
235         display->locking = 1;
236         flushimage(display, 1);
237         unlockdisplay(display);
238         while(recv(mc->c, &mc->Mouse) >= 0){
239                 if(mc->buttons == 0)
240                         continue;
241                 lockdisplay(display);
242                 if((mc->buttons & 4) != 0)
243                         rmb();
244                 else if((mc->buttons & 2) != 0)
245                         mmb();
246                 flushimage(display, 1);
247                 unlockdisplay(display);
248         }
249 }