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