Rename GP_Context -> GP_Pixmap
[gfxprim.git] / demos / spiv / image_loader.c
blob8f86f92fc259a2516361f5cbbe0855328db1f285
1 /*****************************************************************************
2 * This file is part of gfxprim library. *
3 * *
4 * Gfxprim is free software; you can redistribute it and/or *
5 * modify it under the terms of the GNU Lesser General Public *
6 * License as published by the Free Software Foundation; either *
7 * version 2.1 of the License, or (at your option) any later version. *
8 * *
9 * Gfxprim is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
12 * Lesser General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU Lesser General Public *
15 * License along with gfxprim; if not, write to the Free Software *
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, *
17 * Boston, MA 02110-1301 USA *
18 * *
19 * Copyright (C) 2009-2013 Cyril Hrubis <metan@ucw.cz> *
20 * *
21 *****************************************************************************/
23 #include <errno.h>
25 #include <core/GP_Pixmap.h>
26 #include <core/GP_Debug.h>
28 #include <loaders/GP_Loaders.h>
30 #include "cpu_timer.h"
31 #include "image_cache.h"
32 #include "image_list.h"
33 #include "image_loader.h"
35 static struct image_cache *img_cache;
36 static struct image_list *img_list;
37 static GP_Pixmap *cur_img;
38 static GP_DataStorage *cur_meta_data;
39 static GP_Container *cur_cont;
41 int image_loader_init(const char *args[], unsigned int cache_max_bytes)
43 img_cache = image_cache_create(cache_max_bytes);
45 if (!img_cache) {
46 GP_WARN("Failed to initialize image cache (size=%u)",
47 cache_max_bytes);
50 img_list = image_list_create(args);
52 if (!img_list) {
53 GP_FATAL("Failed to initialize image list");
54 return 1;
57 return 0;
60 GP_Pixmap *image_loader_get_image(GP_ProgressCallback *callback, int elevate)
62 struct cpu_timer timer;
63 const char *path;
64 GP_Pixmap *img;
65 int err, ret;
67 if (cur_img)
68 return cur_img;
70 if (cur_cont) {
71 cpu_timer_start(&timer, "Loading");
72 cur_meta_data = GP_DataStorageCreate();
73 GP_ContainerLoadEx(cur_cont, &cur_img, cur_meta_data, callback);
74 cpu_timer_stop(&timer);
75 return cur_img;
78 path = image_list_img_path(img_list);
80 if (!image_cache_get(img_cache, &cur_img, &cur_meta_data, elevate, path))
81 return cur_img;
83 cpu_timer_start(&timer, "Loading");
85 cur_meta_data = GP_DataStorageCreate();
87 ret = GP_LoadImageEx(path, &img, cur_meta_data, callback);
89 if (ret) {
90 err = errno;
93 * Try containers, ZIP for now, more to come
95 * TODO: How to cache container content?
97 cur_cont = GP_OpenZip(path);
99 if (cur_cont) {
100 GP_ContainerLoadEx(cur_cont, &img, cur_meta_data, callback);
102 if (img) {
103 cur_img = img;
104 cpu_timer_stop(&timer);
105 return img;
108 GP_ContainerClose(cur_cont);
109 cur_cont = NULL;
112 errno = err;
113 return NULL;
116 image_cache_put(img_cache, img, cur_meta_data, path);
118 cpu_timer_stop(&timer);
120 return img;
123 GP_DataStorage *image_loader_get_meta_data(void)
125 return cur_meta_data;
128 const char *image_loader_img_path(void)
130 //TODO: Make this more elegant
131 static char path[512];
133 if (cur_cont) {
134 snprintf(path, sizeof(path), "%s:%u",
135 image_list_img_path(img_list), cur_cont->cur_img);
136 return path;
139 return image_list_img_path(img_list);
142 const char *image_loader_img_name(void)
144 return image_list_img_path(img_list);
147 static void drop_cur_img(void)
149 const char *path;
151 path = image_list_img_path(img_list);
154 * Currently loaded image is too big to be cached -> free it.
156 if (image_cache_get(img_cache, NULL, NULL, 0, path)) {
157 GP_PixmapFree(cur_img);
158 GP_DataStorageDestroy(cur_meta_data);
161 cur_img = NULL;
162 cur_meta_data = NULL;
165 void image_loader_seek(enum img_seek_offset offset, int whence)
167 drop_cur_img();
169 if (cur_cont) {
170 switch (offset) {
171 case IMG_FIRST:
172 case IMG_LAST:
173 //TODO do something better for IMG_DIR
174 case IMG_DIR:
175 GP_ContainerClose(cur_cont);
176 cur_cont = NULL;
177 goto list_seek;
178 case IMG_CUR:
179 break;
182 * TODO: We should be able to count how much
183 * we get out of the container and seek
184 * N images in the list
186 * What about wrapping around?
188 if (GP_ContainerSeek(cur_cont, whence, GP_CONT_CUR)) {
189 GP_ContainerClose(cur_cont);
190 cur_cont = NULL;
191 goto list_seek;
194 return;
197 list_seek:
199 switch (offset) {
200 case IMG_FIRST:
201 image_list_first(img_list);
202 break;
203 case IMG_LAST:
204 image_list_last(img_list);
205 break;
206 case IMG_CUR:
207 break;
208 case IMG_DIR:
209 image_list_dir_move(img_list, whence);
210 return;
213 if (!whence)
214 return;
216 image_list_move(img_list, whence);
219 unsigned int image_loader_count(void)
221 return image_list_count(img_list);
224 unsigned int image_loader_pos(void)
226 return image_list_pos(img_list);
229 int image_loader_is_in_dir(void)
231 return image_list_dir_count(img_list) != 0;
234 unsigned int image_loader_dir_count(void)
236 return image_list_dir_count(img_list);
239 unsigned int image_loader_dir_pos(void)
241 return image_list_dir_pos(img_list);
244 void image_loader_drop_cache(void)
246 drop_cur_img();
247 image_cache_drop(img_cache);
250 void image_loader_destroy(void)
252 GP_DEBUG(1, "Destroying loader");
253 drop_cur_img();
254 GP_DEBUG(1, "Destroying cache");
255 image_cache_destroy(img_cache);
256 GP_DEBUG(1, "Destroying image list");
257 image_list_destroy(img_list);