libresman

changeset 1:469ce01809bc

rudimentary imgthumbs "example program". doesn't use libresman yet
author John Tsiombikas <nuclear@member.fsf.org>
date Fri, 31 Jan 2014 03:17:24 +0200
parents 61d7ff6da54b
children 026cdd1737ff
files .hgignore examples/imgthumbs/Makefile examples/imgthumbs/src/main.c examples/imgthumbs/src/opengl.h examples/imgthumbs/src/thumbs.c examples/imgthumbs/src/thumbs.h src/resman.h
diffstat 7 files changed, 464 insertions(+), 35 deletions(-) [+]
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/.hgignore	Fri Jan 31 03:17:24 2014 +0200
     1.3 @@ -0,0 +1,17 @@
     1.4 +\.o$
     1.5 +\.swp$
     1.6 +\.d$
     1.7 +^libresman.so
     1.8 +^libresman.a
     1.9 +\.jpg$
    1.10 +\.png$
    1.11 +\.gif$
    1.12 +\.tga$
    1.13 +\.jpeg$
    1.14 +\.targa$
    1.15 +\.tif$
    1.16 +\.bmp$
    1.17 +\.ppm$
    1.18 +\.pnm$
    1.19 +\.xpm$
    1.20 +\.rgba$
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/examples/imgthumbs/Makefile	Fri Jan 31 03:17:24 2014 +0200
     2.3 @@ -0,0 +1,19 @@
     2.4 +src = $(wildcard src/*.c)
     2.5 +obj = $(src:.c=.o)
     2.6 +bin = imgthumbs
     2.7 +
     2.8 +CFLAGS = -pedantic -Wall -g -I../../src
     2.9 +LDFLAGS = $(libgl) -limago
    2.10 +
    2.11 +ifeq ($(shell uname -s), Darwin)
    2.12 +	libgl = -framework OpenGL -framework GLUT
    2.13 +else
    2.14 +	libgl = -lGL -lGLU -lglut
    2.15 +endif
    2.16 +
    2.17 +$(bin): $(obj)
    2.18 +	$(CC) -o $@ $(obj) $(LDFLAGS)
    2.19 +
    2.20 +.PHONY: clean
    2.21 +clean:
    2.22 +	rm -f $(obj) $(bin)
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/examples/imgthumbs/src/main.c	Fri Jan 31 03:17:24 2014 +0200
     3.3 @@ -0,0 +1,232 @@
     3.4 +#include <stdio.h>
     3.5 +#include <stdlib.h>
     3.6 +#include <assert.h>
     3.7 +#include "opengl.h"
     3.8 +#include "resman.h"
     3.9 +#include "thumbs.h"
    3.10 +
    3.11 +static int init(void);
    3.12 +static void cleanup(void);
    3.13 +static void display(void);
    3.14 +/*static void idle(void);*/
    3.15 +static void reshape(int x, int y);
    3.16 +static void keyb(unsigned char key, int x, int y);
    3.17 +static void mouse(int bn, int st, int x, int y);
    3.18 +static void motion(int x, int y);
    3.19 +static struct thumbnail *find_thumb(int x, int y);
    3.20 +
    3.21 +const char *path = ".";
    3.22 +struct resman *texman;
    3.23 +int win_width, win_height;
    3.24 +float win_aspect;
    3.25 +float pan_x, pan_y;
    3.26 +float show_pan_x, show_pan_y;
    3.27 +float show_zoom = 1.0;
    3.28 +float thumbs_size = 0.25;
    3.29 +
    3.30 +struct thumbnail *thumbs, *show_thumb;
    3.31 +
    3.32 +int main(int argc, char **argv)
    3.33 +{
    3.34 +	glutInit(&argc, argv);
    3.35 +
    3.36 +	if(argv[1]) {
    3.37 +		path = argv[1];
    3.38 +	}
    3.39 +
    3.40 +	glutInitWindowSize(800, 600);
    3.41 +	glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
    3.42 +	glutCreateWindow("imgthumbs");
    3.43 +
    3.44 +	glutDisplayFunc(display);
    3.45 +	glutReshapeFunc(reshape);
    3.46 +	glutKeyboardFunc(keyb);
    3.47 +	glutMouseFunc(mouse);
    3.48 +	glutMotionFunc(motion);
    3.49 +
    3.50 +	if(init() == -1) {
    3.51 +		return 1;
    3.52 +	}
    3.53 +	atexit(cleanup);
    3.54 +
    3.55 +	glutMainLoop();
    3.56 +	return 0;
    3.57 +}
    3.58 +
    3.59 +static int init(void)
    3.60 +{
    3.61 +	thumbs = create_thumbs(path);
    3.62 +	return 0;
    3.63 +}
    3.64 +
    3.65 +static void cleanup(void)
    3.66 +{
    3.67 +	free_thumbs(thumbs);
    3.68 +}
    3.69 +
    3.70 +static void display(void)
    3.71 +{
    3.72 +	glClear(GL_COLOR_BUFFER_BIT);
    3.73 +
    3.74 +	glMatrixMode(GL_MODELVIEW);
    3.75 +	glLoadIdentity();
    3.76 +
    3.77 +	if(show_thumb) {
    3.78 +		glEnable(GL_TEXTURE_2D);
    3.79 +		glBindTexture(GL_TEXTURE_2D, show_thumb->tex);
    3.80 +
    3.81 +		glScalef(show_zoom, show_zoom, 1);
    3.82 +		glTranslatef(2.0 * show_pan_x, 2.0 * show_pan_y, 0);
    3.83 +		if(show_thumb->aspect >= 1.0) {
    3.84 +			glScalef(1, 1.0 / show_thumb->aspect, 1);
    3.85 +		} else {
    3.86 +			glScalef(show_thumb->aspect, 1, 1);
    3.87 +		}
    3.88 +
    3.89 +		glBegin(GL_QUADS);
    3.90 +		glColor3f(1, 1, 1);
    3.91 +		glTexCoord2f(0, 0); glVertex2f(-1, -1);
    3.92 +		glTexCoord2f(1, 0); glVertex2f(1, -1);
    3.93 +		glTexCoord2f(1, 1); glVertex2f(1, 1);
    3.94 +		glTexCoord2f(0, 1); glVertex2f(-1, 1);
    3.95 +		glEnd();
    3.96 +
    3.97 +		glDisable(GL_TEXTURE_2D);
    3.98 +	} else {
    3.99 +		draw_thumbs(thumbs, thumbs_size, pan_y);
   3.100 +	}
   3.101 +
   3.102 +	glutSwapBuffers();
   3.103 +	assert(glGetError() == GL_NO_ERROR);
   3.104 +}
   3.105 +
   3.106 +/*
   3.107 +static void idle(void)
   3.108 +{
   3.109 +	glutPostRedisplay();
   3.110 +}
   3.111 +*/
   3.112 +
   3.113 +static void reshape(int x, int y)
   3.114 +{
   3.115 +	win_aspect = (float)x / (float)y;
   3.116 +
   3.117 +	glViewport(0, 0, x, y);
   3.118 +
   3.119 +	glMatrixMode(GL_PROJECTION);
   3.120 +	glLoadIdentity();
   3.121 +	glOrtho(-1, 1, 1.0 / win_aspect, -1.0 / win_aspect, -1, 1);
   3.122 +
   3.123 +	win_width = x;
   3.124 +	win_height = y;
   3.125 +}
   3.126 +
   3.127 +static void keyb(unsigned char key, int x, int y)
   3.128 +{
   3.129 +	switch(key) {
   3.130 +	case 27:
   3.131 +		exit(0);
   3.132 +
   3.133 +	case ' ':
   3.134 +		show_zoom = 1.0;
   3.135 +		thumbs_size = 0.25;
   3.136 +		pan_x = pan_y = show_pan_x = show_pan_y = 0;
   3.137 +		glutPostRedisplay();
   3.138 +		break;
   3.139 +	}
   3.140 +}
   3.141 +
   3.142 +static int bnstate[32];
   3.143 +static int prev_x, prev_y;
   3.144 +static int click_x[32], click_y[32];
   3.145 +
   3.146 +static void mouse(int bn, int st, int x, int y)
   3.147 +{
   3.148 +	int bidx = bn - GLUT_LEFT_BUTTON;
   3.149 +	int state = st == GLUT_DOWN ? 1 : 0;
   3.150 +
   3.151 +	bnstate[bidx] = state;
   3.152 +
   3.153 +	prev_x = x;
   3.154 +	prev_y = y;
   3.155 +
   3.156 +	if(state) {
   3.157 +		click_x[bidx] = x;
   3.158 +		click_y[bidx] = y;
   3.159 +	} else {
   3.160 +		int is_drag = abs(x - click_x[bidx]) > 3 || abs(y - click_y[bidx]) > 3;
   3.161 +
   3.162 +		if(bidx == 0) {
   3.163 +			if(!show_thumb) {
   3.164 +				if(!is_drag) {
   3.165 +					struct thumbnail *sel = find_thumb(x, y);
   3.166 +					if(sel) {
   3.167 +						show_thumb = sel;
   3.168 +						show_pan_x = show_pan_y = 0;
   3.169 +						glutPostRedisplay();
   3.170 +					}
   3.171 +				}
   3.172 +			}
   3.173 +		} else {
   3.174 +			if(!is_drag) {
   3.175 +				show_thumb = 0;
   3.176 +				glutPostRedisplay();
   3.177 +			}
   3.178 +		}
   3.179 +	}
   3.180 +}
   3.181 +
   3.182 +static void motion(int x, int y)
   3.183 +{
   3.184 +	int dx = x - prev_x;
   3.185 +	int dy = y - prev_y;
   3.186 +	prev_x = x;
   3.187 +	prev_y = y;
   3.188 +
   3.189 +	if(!dx && !dy) return;
   3.190 +
   3.191 +	if(bnstate[0]) {
   3.192 +		float fdx = dx / (float)win_width;
   3.193 +		float fdy = dy / (float)win_height / win_aspect;
   3.194 +
   3.195 +		if(show_thumb) {
   3.196 +			show_pan_x += fdx / show_zoom;
   3.197 +			show_pan_y += fdy / show_zoom;
   3.198 +		} else {
   3.199 +			pan_x += fdx;
   3.200 +			pan_y += fdy;
   3.201 +		}
   3.202 +		glutPostRedisplay();
   3.203 +	}
   3.204 +
   3.205 +	if(bnstate[2]) {
   3.206 +		if(show_thumb) {
   3.207 +			show_zoom -= dy * 0.0075;
   3.208 +			if(show_zoom <= 0) show_zoom = 0;
   3.209 +		} else {
   3.210 +			thumbs_size -= dy * 0.005;
   3.211 +			if(thumbs_size <= 0.01) thumbs_size = 0.01;
   3.212 +		}
   3.213 +		glutPostRedisplay();
   3.214 +	}
   3.215 +}
   3.216 +
   3.217 +static struct thumbnail *find_thumb(int x, int y)
   3.218 +{
   3.219 +	float fx = (float)x / (float)win_width;
   3.220 +	float fy = (float)y / (float)win_height / win_aspect;
   3.221 +	struct thumbnail *node;
   3.222 +
   3.223 +	node = thumbs;
   3.224 +	while(node) {
   3.225 +		float nx = node->layout_pos[0];
   3.226 +		float ny = node->layout_pos[1];
   3.227 +
   3.228 +		if(fx >= nx && fx < nx + node->layout_size[0] &&
   3.229 +				fy >= ny && fy < ny + node->layout_size[1]) {
   3.230 +			return node;
   3.231 +		}
   3.232 +		node = node->next;
   3.233 +	}
   3.234 +	return 0;
   3.235 +}
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/examples/imgthumbs/src/opengl.h	Fri Jan 31 03:17:24 2014 +0200
     4.3 @@ -0,0 +1,10 @@
     4.4 +#ifndef OPENGL_H_
     4.5 +#define OPENGL_H_
     4.6 +
     4.7 +#ifdef __APPLE__
     4.8 +#include <GLUT/glut.h>
     4.9 +#else
    4.10 +#include <GL/glut.h>
    4.11 +#endif
    4.12 +
    4.13 +#endif	/* OPENGL_H_ */
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/examples/imgthumbs/src/thumbs.c	Fri Jan 31 03:17:24 2014 +0200
     5.3 @@ -0,0 +1,152 @@
     5.4 +#include <stdio.h>
     5.5 +#include <stdlib.h>
     5.6 +#include <string.h>
     5.7 +#include <errno.h>
     5.8 +#include <dirent.h>
     5.9 +#include <imago2.h>
    5.10 +#include "opengl.h"
    5.11 +#include "thumbs.h"
    5.12 +
    5.13 +struct thumbnail *create_thumbs(const char *dirpath)
    5.14 +{
    5.15 +	DIR *dir;
    5.16 +	struct dirent *dent;
    5.17 +	struct thumbnail *list = 0;
    5.18 +
    5.19 +	if(!(dir = opendir(dirpath))) {
    5.20 +		fprintf(stderr, "failed to open directory: %s: %s\n", dirpath, strerror(errno));
    5.21 +		return 0;
    5.22 +	}
    5.23 +
    5.24 +	while((dent = readdir(dir))) {
    5.25 +		int xsz, ysz;
    5.26 +		unsigned char *pixels;
    5.27 +		struct thumbnail *node;
    5.28 +
    5.29 +		if(!(node = malloc(sizeof *node))) {
    5.30 +			perror("failed to allocate thumbnail list node");
    5.31 +			continue;
    5.32 +		}
    5.33 +
    5.34 +		if(!(node->fname = malloc(strlen(dirpath) + strlen(dent->d_name) + 2))) {
    5.35 +			free(node);
    5.36 +			continue;
    5.37 +		}
    5.38 +		strcpy(node->fname, dirpath);
    5.39 +		if(dirpath[strlen(dirpath) - 1] != '/') {
    5.40 +			strcat(node->fname, "/");
    5.41 +		}
    5.42 +		strcat(node->fname, dent->d_name);
    5.43 +
    5.44 +		if(!(pixels = img_load_pixels(node->fname, &xsz, &ysz, IMG_FMT_RGBA32))) {
    5.45 +			free(node->fname);
    5.46 +			free(node);
    5.47 +			continue;
    5.48 +		}
    5.49 +
    5.50 +		printf("loaded image: %s\n", node->fname);
    5.51 +
    5.52 +		glGenTextures(1, &node->tex);
    5.53 +		glBindTexture(GL_TEXTURE_2D, node->tex);
    5.54 +		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    5.55 +		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    5.56 +		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, xsz, ysz, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
    5.57 +		img_free_pixels(pixels);
    5.58 +
    5.59 +		node->aspect = (float)xsz / (float)ysz;
    5.60 +
    5.61 +		node->next = list;
    5.62 +		list = node;
    5.63 +	}
    5.64 +	closedir(dir);
    5.65 +
    5.66 +	return list;
    5.67 +}
    5.68 +
    5.69 +void free_thumbs(struct thumbnail *thumbs)
    5.70 +{
    5.71 +	if(!thumbs) return;
    5.72 +
    5.73 +	while(thumbs) {
    5.74 +		struct thumbnail *tmp = thumbs;
    5.75 +		thumbs = thumbs->next;
    5.76 +
    5.77 +		free(tmp->fname);
    5.78 +		free(tmp);
    5.79 +	}
    5.80 +}
    5.81 +
    5.82 +
    5.83 +void draw_thumbs(struct thumbnail *thumbs, float thumb_sz, float start_y)
    5.84 +{
    5.85 +	int vp[4];
    5.86 +	float gap = thumb_sz / 4.0;
    5.87 +	float x = gap;
    5.88 +	float y = gap + start_y;
    5.89 +	float view_aspect;
    5.90 +
    5.91 +	glGetIntegerv(GL_VIEWPORT, vp);
    5.92 +	view_aspect = (float)(vp[2] - vp[0]) / (vp[3] - vp[1]);
    5.93 +
    5.94 +	glMatrixMode(GL_PROJECTION);
    5.95 +	glPushMatrix();
    5.96 +	glLoadIdentity();
    5.97 +	glOrtho(0, 1, 1.0 / view_aspect, 0, -1, 1);
    5.98 +
    5.99 +	glMatrixMode(GL_MODELVIEW);
   5.100 +
   5.101 +	while(thumbs) {
   5.102 +
   5.103 +		glPushMatrix();
   5.104 +		glTranslatef(x, y, 0);
   5.105 +
   5.106 +		glScalef(thumb_sz, thumb_sz, 1);
   5.107 +
   5.108 +		glBegin(GL_QUADS);
   5.109 +		glColor3f(0.25, 0.25, 0.25);
   5.110 +		glTexCoord2f(0, 0); glVertex2f(0, 0);
   5.111 +		glTexCoord2f(1, 0); glVertex2f(1, 0);
   5.112 +		glTexCoord2f(1, 1); glVertex2f(1, 1);
   5.113 +		glTexCoord2f(0, 1); glVertex2f(0, 1);
   5.114 +		glEnd();
   5.115 +
   5.116 +		if(thumbs->aspect >= 1.0) {
   5.117 +			glTranslatef(0, 0.5 - 0.5 / thumbs->aspect, 0);
   5.118 +			glScalef(1, 1.0 / thumbs->aspect, 1);
   5.119 +		} else {
   5.120 +			glTranslatef(0.5 - thumbs->aspect / 2.0, 0, 0);
   5.121 +			glScalef(thumbs->aspect, 1, 1);
   5.122 +		}
   5.123 +
   5.124 +		glEnable(GL_TEXTURE_2D);
   5.125 +		glBindTexture(GL_TEXTURE_2D, thumbs->tex);
   5.126 +
   5.127 +		glBegin(GL_QUADS);
   5.128 +		glColor3f(1, 1, 1);
   5.129 +		glTexCoord2f(0, 0); glVertex2f(0, 0);
   5.130 +		glTexCoord2f(1, 0); glVertex2f(1, 0);
   5.131 +		glTexCoord2f(1, 1); glVertex2f(1, 1);
   5.132 +		glTexCoord2f(0, 1); glVertex2f(0, 1);
   5.133 +		glEnd();
   5.134 +
   5.135 +		glPopMatrix();
   5.136 +		glDisable(GL_TEXTURE_2D);
   5.137 +
   5.138 +		thumbs->layout_pos[0] = x;
   5.139 +		thumbs->layout_pos[1] = y;
   5.140 +		thumbs->layout_size[0] = thumb_sz;
   5.141 +		thumbs->layout_size[1] = thumb_sz;
   5.142 +
   5.143 +		x += thumb_sz + gap;
   5.144 +		if(x >= 1.0 - thumb_sz) {
   5.145 +			x = gap;
   5.146 +			y += thumb_sz + gap;
   5.147 +		}
   5.148 +
   5.149 +		thumbs = thumbs->next;
   5.150 +	}
   5.151 +
   5.152 +	glMatrixMode(GL_PROJECTION);
   5.153 +	glPopMatrix();
   5.154 +	glMatrixMode(GL_MODELVIEW);
   5.155 +}
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/examples/imgthumbs/src/thumbs.h	Fri Jan 31 03:17:24 2014 +0200
     6.3 @@ -0,0 +1,21 @@
     6.4 +#ifndef THUMBS_H_
     6.5 +#define THUMBS_H_
     6.6 +
     6.7 +
     6.8 +struct thumbnail {
     6.9 +	char *fname;
    6.10 +	unsigned int tex;
    6.11 +	float aspect;
    6.12 +
    6.13 +	float layout_pos[2];
    6.14 +	float layout_size[2];
    6.15 +
    6.16 +	struct thumbnail *next;
    6.17 +};
    6.18 +
    6.19 +struct thumbnail *create_thumbs(const char *dirpath);
    6.20 +void free_thumbs(struct thumbnail *thumbs);
    6.21 +
    6.22 +void draw_thumbs(struct thumbnail *thumbs, float thumb_sz, float start_y);
    6.23 +
    6.24 +#endif	/* THUMBS_H_ */
     7.1 --- a/src/resman.h	Wed Jan 29 08:17:31 2014 +0200
     7.2 +++ b/src/resman.h	Fri Jan 31 03:17:24 2014 +0200
     7.3 @@ -1,53 +1,31 @@
     7.4  #ifndef RESOURCE_MANAGER_H_
     7.5  #define RESOURCE_MANAGER_H_
     7.6  
     7.7 -/* TODO API */
     7.8 -
     7.9 -/* usage example:
    7.10 -int texload(const char *fname, void *cls)
    7.11 -{
    7.12 -	// open image, parse data ...
    7.13 -}
    7.14 -
    7.15 -struct resman rman;
    7.16 -
    7.17 -resman_init(&rman);
    7.18 -resman_set_load_func(&rman, texload, 0);
    7.19 -resman_set_done_func(&rman, texload_done, 0);
    7.20 -...
    7.21 -
    7.22 -struct texture *tex;
    7.23 -struct resman_job *rjob;
    7.24 -
    7.25 -rjob = resman_get(&rman, "tex.png", 0);
    7.26 -...
    7.27 -resman_wait_job(&rman, rjob);
    7.28 -tex = resman_get_job_data(rjob);
    7.29 -resman_free_job(&rman, rjob);
    7.30 -
    7.31 -...
    7.32 -resman_destroy(&rman);
    7.33 -*/
    7.34 -
    7.35  struct resman;
    7.36  
    7.37 -typedef int (*resman_load_func_t)(const char *fname, void *cls);
    7.38 -typedef void (*resman_done_func_t)(int status, void *cls);
    7.39 -
    7.40 -
    7.41  int resman_init(struct resman *rman);
    7.42  void resman_destroy(struct resman *rman);
    7.43  
    7.44  /* The load callback will be called to load a data file. It may be called in the
    7.45   * context of a different loading thread.
    7.46   */
    7.47 -void resman_set_load_func(struct resman *rman, resman_load_func_t func, void *cls);
    7.48 +/*void resman_set_load_func(struct resman *rman, resman_load_func_t func, void *cls);*/
    7.49  
    7.50  /* The "done" callback will be called in the context of the main thread, whenever a
    7.51   * file was sucessfully loaded, or an error occured.
    7.52   * It's first argument (status) is set to whatever the load function returned, and its
    7.53 - * closure pointer is the closure 
    7.54 + * closure pointer is the closure  ...
    7.55   */
    7.56 -void resman_set_done_func(struct resman *rman, resman_done_func_t func);
    7.57 +/*void resman_set_done_func(struct resman *rman, resman_done_func_t func);*/
    7.58 +
    7.59 +
    7.60 +int resman_lookup(struct resman *rman, const char *fname, void *cls);
    7.61 +void resman_wait(struct resman *rman, int id);
    7.62 +
    7.63 +int resman_poll(struct resman *rman);
    7.64 +
    7.65 +void resman_set_res_data(struct resman *rman, int res_id, void *data);
    7.66 +void *resman_get_res_data(struct resman *rman, int res_id);
    7.67 +
    7.68  
    7.69  #endif	/* RESOURCE_MANAGER_H_ */