libresman

view examples/imgthumbs/src/thumbs.c @ 16:0a789208498d

fixed resman.def added debug mode in thumbs.c
author John Tsiombikas <nuclear@member.fsf.org>
date Tue, 11 Feb 2014 18:47:33 +0200
parents a42888d26839
children 43a9fe4a80ee
line source
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <errno.h>
5 #include <assert.h>
6 #include <dirent.h>
7 #include <imago2.h>
8 #include "opengl.h"
9 #include "thumbs.h"
10 #include "resman.h"
12 #define DBG_SYNC
14 #ifndef GL_COMPRESSED_RGB
15 #define GL_COMPRESSED_RGB 0x84ed
16 #endif
18 struct resman *texman;
20 static int load_res_texture(const char *fname, int id, void *cls);
21 static int done_res_texture(int id, void *cls);
22 static void free_res_texture(int id, void *cls);
25 struct thumbnail *create_thumbs(const char *dirpath)
26 {
27 DIR *dir;
28 struct dirent *dent;
29 /* allocate dummy head node */
30 struct thumbnail *list = calloc(1, sizeof *list);
32 if(!texman) {
33 texman = resman_create();
34 resman_set_load_func(texman, load_res_texture, 0);
35 resman_set_done_func(texman, done_res_texture, 0);
36 resman_set_destroy_func(texman, free_res_texture, 0);
37 }
39 if(!(dir = opendir(dirpath))) {
40 fprintf(stderr, "failed to open directory: %s: %s\n", dirpath, strerror(errno));
41 return 0;
42 }
44 while((dent = readdir(dir))) {
45 #ifdef DBG_SYNC
46 int xsz, ysz;
47 unsigned char *pixels;
48 #endif
49 struct thumbnail *node;
51 if(!(node = malloc(sizeof *node))) {
52 perror("failed to allocate thumbnail list node");
53 continue;
54 }
55 memset(node, 0, sizeof *node);
57 if(!(node->fname = malloc(strlen(dirpath) + strlen(dent->d_name) + 2))) {
58 free(node);
59 continue;
60 }
61 strcpy(node->fname, dirpath);
62 if(dirpath[strlen(dirpath) - 1] != '/') {
63 strcat(node->fname, "/");
64 }
65 strcat(node->fname, dent->d_name);
67 node->aspect = 1.0;
69 #ifndef DBG_SYNC
70 resman_lookup(texman, node->fname, node);
71 #else
72 if(!(pixels = img_load_pixels(node->fname, &xsz, &ysz, IMG_FMT_RGBA32))) {
73 free(node->fname);
74 free(node);
75 continue;
76 }
78 printf("loaded image: %s\n", node->fname);
80 glGenTextures(1, &node->tex);
81 glBindTexture(GL_TEXTURE_2D, node->tex);
82 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
83 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
84 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, xsz, ysz, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
85 img_free_pixels(pixels);
87 node->aspect = (float)xsz / (float)ysz;
88 #endif
90 node->next = list->next;
91 node->prev = list;
92 }
93 closedir(dir);
95 return list;
96 }
98 void free_thumbs(struct thumbnail *thumbs)
99 {
100 if(!thumbs) return;
102 while(thumbs) {
103 struct thumbnail *tmp = thumbs;
104 thumbs = thumbs->next;
106 free(tmp->fname);
107 free(tmp);
108 }
109 }
112 void update_thumbs(void)
113 {
114 resman_poll(texman);
115 }
117 void draw_thumbs(struct thumbnail *thumbs, float thumb_sz, float start_y)
118 {
119 int vp[4];
120 float gap = thumb_sz / 4.0;
121 float x = gap;
122 float y = gap + start_y;
123 float view_aspect;
125 glGetIntegerv(GL_VIEWPORT, vp);
126 view_aspect = (float)(vp[2] - vp[0]) / (vp[3] - vp[1]);
128 glMatrixMode(GL_PROJECTION);
129 glPushMatrix();
130 glLoadIdentity();
131 glOrtho(0, 1, 1.0 / view_aspect, 0, -1, 1);
133 glMatrixMode(GL_MODELVIEW);
135 thumbs = thumbs->next; /* skip dummy node */
136 while(thumbs) {
137 glPushMatrix();
138 glTranslatef(x, y, 0);
140 glScalef(thumb_sz, thumb_sz, 1);
142 glBegin(GL_QUADS);
143 glColor3f(0.25, 0.25, 0.25);
144 glTexCoord2f(0, 0); glVertex2f(0, 0);
145 glTexCoord2f(1, 0); glVertex2f(1, 0);
146 glTexCoord2f(1, 1); glVertex2f(1, 1);
147 glTexCoord2f(0, 1); glVertex2f(0, 1);
148 glEnd();
150 if(thumbs->tex) {
151 if(thumbs->aspect >= 1.0) {
152 glTranslatef(0, 0.5 - 0.5 / thumbs->aspect, 0);
153 glScalef(1, 1.0 / thumbs->aspect, 1);
154 } else {
155 glTranslatef(0.5 - thumbs->aspect / 2.0, 0, 0);
156 glScalef(thumbs->aspect, 1, 1);
157 }
159 if(glIsTexture(thumbs->tex)) {
160 glEnable(GL_TEXTURE_2D);
161 glBindTexture(GL_TEXTURE_2D, thumbs->tex);
163 glBegin(GL_QUADS);
164 glColor3f(1, 1, 1);
165 glTexCoord2f(0, 0); glVertex2f(0, 0);
166 glTexCoord2f(1, 0); glVertex2f(1, 0);
167 glTexCoord2f(1, 1); glVertex2f(1, 1);
168 glTexCoord2f(0, 1); glVertex2f(0, 1);
169 glEnd();
170 } else {
171 fprintf(stderr, "invalid texture: %u\n", thumbs->tex);
172 }
174 glPopMatrix();
175 glDisable(GL_TEXTURE_2D);
176 }
178 thumbs->layout_pos[0] = x;
179 thumbs->layout_pos[1] = y;
180 thumbs->layout_size[0] = thumb_sz;
181 thumbs->layout_size[1] = thumb_sz;
183 x += thumb_sz + gap;
184 if(x >= 1.0 - thumb_sz) {
185 x = gap;
186 y += thumb_sz + gap;
187 }
189 thumbs = thumbs->next;
190 }
192 glMatrixMode(GL_PROJECTION);
193 glPopMatrix();
194 glMatrixMode(GL_MODELVIEW);
195 }
197 static int load_res_texture(const char *fname, int id, void *cls)
198 {
199 struct thumbnail *rdata = resman_get_res_data(texman, id);
201 assert(rdata);
202 if(!rdata->img) {
203 if(!(rdata->img = img_create())) {
204 return -1;
205 }
206 }
208 if(img_load(rdata->img, fname) == -1) {
209 img_free(rdata->img);
210 rdata->img = 0;
211 return -1;
212 }
213 rdata->aspect = (float)rdata->img->width / (float)rdata->img->height;
215 /* set the resource's data to the loaded image, so that we can use
216 * it in the done callback */
217 resman_set_res_data(texman, id, rdata);
218 return 0;
219 }
221 static int done_res_texture(int id, void *cls)
222 {
223 struct thumbnail *rdata = resman_get_res_data(texman, id);
224 int load_result = resman_get_res_result(texman, id);
226 if(load_result == -1) {
227 /* returning -1 will remove this resource, the free_res_texture
228 * destroy handler will be called, which will remove the node
229 * from the list
230 */
231 return -1;
232 }
234 if(resman_get_res_result(texman, id) != 0 || !rdata) {
235 fprintf(stderr, "failed to load resource %d (%s)\n", id, resman_get_res_name(texman, id));
236 } else {
237 printf("done loading resource %d (%s)\n", id, resman_get_res_name(texman, id));
238 }
240 if(!rdata->tex) {
241 glGenTextures(1, &rdata->tex);
242 }
243 glBindTexture(GL_TEXTURE_2D, rdata->tex);
244 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
245 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
246 glTexImage2D(GL_TEXTURE_2D, 0, img_glintfmt(rdata->img),
247 rdata->img->width, rdata->img->height, 0, img_glfmt(rdata->img),
248 img_gltype(rdata->img), rdata->img->pixels);
249 return 0;
250 }
252 static void free_res_texture(int id, void *cls)
253 {
254 struct thumbnail *thumb = resman_get_res_data(texman, id);
256 if(thumb) {
257 if(thumb->tex) {
258 glDeleteTextures(1, &thumb->tex);
259 }
260 if(thumb->img) {
261 img_free(thumb->img);
262 }
263 }
265 /* remove from the list */
266 if(thumb->prev) {
267 thumb->prev->next = thumb->next;
268 }
269 if(thumb->next) {
270 thumb->next->prev = thumb->prev;
271 }
272 free(thumb);
273 }