]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/mothra/getpix.c
mothra: allow plmouse() to update mouse state, use a pipe to signal screen update
[plan9front.git] / sys / src / cmd / mothra / getpix.c
1 #include <u.h>
2 #include <libc.h>
3 #include <draw.h>
4 #include <event.h>
5 #include <panel.h>
6 #include "mothra.h"
7
8 typedef struct Pix Pix;
9 struct Pix{
10         Pix *next;
11         Image *b;
12         int width;
13         int height;
14         char name[NNAME];
15 };
16
17 char *pixcmd[]={
18 [GIF]   "gif -9t",
19 [JPEG]  "jpg -9t",
20 [PNG]   "png -9t",
21 [BMP]   "bmp -9t",
22 };
23
24 void getimage(Rtext *t, Www *w){
25         int pfd[2];
26         Action *ap;
27         Url url;
28         Image *b;
29         int fd, typ;
30         char err[512];
31         Pix *p;
32
33         ap=t->user;
34         seturl(&url, ap->image, w->url->fullname);
35         for(p=w->pix;p!=nil; p=p->next)
36                 if(strcmp(ap->image, p->name)==0 && ap->width==p->width && ap->height==p->height){
37                         t->b = p->b;
38                         update(w);
39                         return;
40                 }
41         fd=urlopen(&url, GET, 0);
42         if(fd==-1){
43         Err:
44                 snprint(err, sizeof(err), "[%s: %r]", url.fullname);
45                 free(t->text);
46                 t->text=strdup(err);
47                 update(w);
48                 close(fd);
49                 return;
50         }
51         typ = snooptype(fd);
52         if(typ < 0 || typ >= nelem(pixcmd) || pixcmd[typ] == nil){
53                 werrstr("unknown image type");
54                 goto Err;
55         }
56         if((fd = pipeline(pixcmd[typ], fd)) < 0)
57                 goto Err;
58         if(ap->width>0 || ap->height>0){
59                 char buf[80];
60                 char *p;
61
62                 p = buf;
63                 p += sprint(p, "resize");
64                 if(ap->width>0)
65                         p += sprint(p, " -x %d", ap->width);
66                 if(ap->height>0)
67                         p += sprint(p, " -y %d", ap->height);
68                 if((fd = pipeline(buf, fd)) < 0)
69                         goto Err;
70         }
71         b=readimage(display, fd, 1);
72         if(b==0){
73                 werrstr("can't read image");
74                 goto Err;
75         }
76         close(fd);
77         p = emallocz(sizeof(Pix), 1);
78         strncpy(p->name, ap->image, sizeof(p->name));
79         p->b=b;
80         p->width=ap->width;
81         p->height=ap->height;
82         p->next=w->pix;
83         w->pix=p;
84         t->b=b;
85         update(w);
86 }
87
88 void getpix(Rtext *t, Www *w){
89         int i, pid, nworker, worker[NXPROC];
90         Action *ap;
91
92         nworker = 0;
93         for(i=0; i<nelem(worker); i++)
94                 worker[i] = -1;
95
96         for(;t!=0;t=t->next){
97                 ap=t->user;
98                 if(ap && ap->image){
99                         pid = rfork(RFFDG|RFPROC|RFMEM);
100                         switch(pid){
101                         case -1:
102                                 fprint(2, "fork: %r\n");
103                                 break;
104                         case 0:
105                                 getimage(t, w);
106                                 exits(0);
107                         default:
108                                 for(i=0; i<nelem(worker); i++)
109                                         if(worker[i] == -1){
110                                                 worker[i] = pid;
111                                                 nworker++;
112                                                 break;
113                                         }
114
115                                 while(nworker == nelem(worker)){
116                                         if((pid = waitpid()) < 0)
117                                                 break;
118                                         for(i=0; i<nelem(worker); i++)
119                                                 if(worker[i] == pid){
120                                                         worker[i] = -1;
121                                                         nworker--;
122                                                         break;
123                                                 }
124                                 }
125                         }
126                         
127                 }
128         }
129         while(nworker > 0){
130                 if((pid = waitpid()) < 0)
131                         break;
132                 for(i=0; i<nelem(worker); i++)
133                         if(worker[i] == pid){
134                                 worker[i] = -1;
135                                 nworker--;
136                                 break;
137                         }
138         }
139 }
140
141 ulong countpix(void *p){
142         ulong n=0;
143         Pix *x;
144         for(x = p; x; x = x->next)
145                 n += Dy(x->b->r)*bytesperline(x->b->r, x->b->depth);
146         return n;
147 }
148
149 void freepix(void *p){
150         Pix *x, *xx;
151         xx = p;
152         while(x = xx){
153                 xx = x->next;
154                 freeimage(x->b);
155                 free(x);
156         }
157 }