]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/mothra/getpix.c
cwfs: fix listen filedescriptor leaks
[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 [ICO]   "ico -c",
23 };
24
25 void getimage(Rtext *t, Www *w){
26         Action *ap;
27         Url *url;
28         Image *b;
29         int fd, typ;
30         char err[512], buf[80], *s;
31         Pix *p;
32
33         ap=t->user;
34         url=emalloc(sizeof(Url));
35         seturl(url, ap->image, w->url->fullname);
36         for(p=w->pix;p!=nil; p=p->next)
37                 if(strcmp(ap->image, p->name)==0 && ap->width==p->width && ap->height==p->height){
38                         t->b = p->b;
39                         w->changed=1;
40                         return;
41                 }
42         fd=urlget(url, -1);
43         if(fd==-1){
44         Err:
45                 snprint(err, sizeof(err), "[img: %s: %r]", urlstr(url));
46                 free(t->text);
47                 t->text=strdup(err);
48                 w->changed=1;
49                 close(fd);
50                 goto Out;
51         }
52         typ = snooptype(fd);
53         if(typ < 0 || typ >= nelem(pixcmd) || pixcmd[typ] == nil){
54                 werrstr("unknown image type");
55                 goto Err;
56         }
57         if((fd = pipeline(fd, "exec %s", pixcmd[typ])) < 0)
58                 goto Err;
59         if(ap->width>0 || ap->height>0){
60                 s = buf;
61                 s += sprint(s, "exec resize");
62                 if(ap->width>0)
63                         s += sprint(s, " -x %d", ap->width);
64                 if(ap->height>0)
65                         s += sprint(s, " -y %d", ap->height);
66                 USED(s);
67                 if((fd = pipeline(fd, buf)) < 0)
68                         goto Err;
69         }
70         b=readimage(display, fd, 1);
71         if(b==0){
72                 werrstr("can't read image");
73                 goto Err;
74         }
75         close(fd);
76         p=emalloc(sizeof(Pix));
77         nstrcpy(p->name, ap->image, sizeof(p->name));
78         p->b=b;
79         p->width=ap->width;
80         p->height=ap->height;
81         p->next=w->pix;
82         w->pix=p;
83         t->b=b;
84         w->changed=1;
85 Out:
86         freeurl(url);
87 }
88
89 void getpix(Rtext *t, Www *w){
90         int i, pid, nworker, worker[NXPROC];
91         Action *ap;
92
93         nworker = 0;
94         for(i=0; i<nelem(worker); i++)
95                 worker[i] = -1;
96
97         for(;t!=0;t=t->next){
98                 ap=t->user;
99                 if(ap && ap->image){
100                         pid = rfork(RFFDG|RFPROC|RFMEM);
101                         switch(pid){
102                         case -1:
103                                 fprint(2, "fork: %r\n");
104                                 break;
105                         case 0:
106                                 getimage(t, w);
107                                 exits(0);
108                         default:
109                                 for(i=0; i<nelem(worker); i++)
110                                         if(worker[i] == -1){
111                                                 worker[i] = pid;
112                                                 nworker++;
113                                                 break;
114                                         }
115
116                                 while(nworker == nelem(worker)){
117                                         if((pid = waitpid()) < 0)
118                                                 break;
119                                         for(i=0; i<nelem(worker); i++)
120                                                 if(worker[i] == pid){
121                                                         worker[i] = -1;
122                                                         nworker--;
123                                                         break;
124                                                 }
125                                 }
126                         }
127                         
128                 }
129         }
130         while(nworker > 0){
131                 if((pid = waitpid()) < 0)
132                         break;
133                 for(i=0; i<nelem(worker); i++)
134                         if(worker[i] == pid){
135                                 worker[i] = -1;
136                                 nworker--;
137                                 break;
138                         }
139         }
140 }
141
142 ulong countpix(void *p){
143         ulong n=0;
144         Pix *x;
145         for(x = p; x; x = x->next)
146                 n += Dy(x->b->r)*bytesperline(x->b->r, x->b->depth);
147         return n;
148 }
149
150 void freepix(void *p){
151         Pix *x, *xx;
152         xx = p;
153         while(x = xx){
154                 xx = x->next;
155                 freeimage(x->b);
156                 free(x);
157         }
158 }