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