Merge branch 'master' of ssh://skeezixgit@git.openpandora.org/srv/git/pandora-libraries
[pandora-libraries.git] / minimenu / mmcache.c
1
2 #include <limits.h>
3
4 #include "SDL.h"
5 #include "SDL_image.h"
6 #include "SDL_rotozoom.h"
7
8 #include "pnd_pxml.h"
9 #include "pnd_utility.h"
10 #include "pnd_conf.h"
11 #include "pnd_container.h"
12 #include "pnd_discovery.h"
13 #include "pnd_logger.h"
14 #include "pnd_desktop.h"
15 #include "pnd_pndfiles.h"
16 #include "pnd_apps.h"
17
18 #include "mmenu.h"
19 #include "mmapps.h"
20 #include "mmcache.h"
21
22 extern pnd_conf_handle g_conf;
23
24 mm_cache_t *g_icon_cache = NULL;
25 mm_cache_t *g_preview_cache = NULL;
26
27 unsigned char cache_preview ( pnd_disco_t *app, unsigned int maxwidth, unsigned int maxheight ) {
28   SDL_Surface *s;
29   mm_cache_t *c;
30
31   // does this sucker even have a preview?
32   if ( ! app -> preview_pic1 ) {
33     return ( 1 ); // nothing here, so thats fine
34   }
35
36   // check if already cached
37   if ( ( c = cache_query_preview ( app -> unique_id ) ) ) {
38     return ( 1 ); // already got it
39   }
40
41   // not cached, load it up
42   //
43
44   // see if we can mount the pnd/dir
45   // does preview file exist?
46   //   if so, load it up, size it, cache it
47   //   if not, warning and bail
48   // unmount it
49
50   // can we mount?
51   char fullpath [ PATH_MAX ];
52   char filepath [ PATH_MAX ];
53
54   sprintf ( fullpath, "%s/%s", app -> object_path, app -> object_filename );
55
56   if ( ! pnd_pnd_mount ( pnd_run_script, fullpath, app -> unique_id ) ) {
57     pnd_log ( pndn_debug, "Couldn't mount '%s' for preview\n", fullpath );
58     return ( 0 ); // couldn't mount?!
59   }
60
61   sprintf ( filepath, "%s/%s/%s", PND_MOUNT_PATH, app -> unique_id, app -> preview_pic1 );
62   s = IMG_Load ( filepath );
63
64   pnd_pnd_unmount ( pnd_run_script, fullpath, app -> unique_id );
65
66   if ( ! s ) {
67     pnd_log ( pndn_debug, "Couldn't open image '%s' for preview\n", filepath );
68     return ( 0 );
69   }
70
71   //pnd_log ( pndn_debug, "Image size is %u x %u (max %u x %u)\n", s -> w, s -> h, maxwidth, maxheight );
72
73   // scale
74   if ( s -> w < maxwidth ) {
75     // scale up?
76     if ( pnd_conf_get_as_int_d ( g_conf, "previewpic.scale_up_bool", 1 ) ) {
77       SDL_Surface *scaled;
78       double scale = (double)maxwidth / (double)s -> w;
79       //pnd_log ( pndn_debug, "  Upscaling; scale factor %f\n", scale );
80       scaled = rotozoomSurface ( s, 0 /* angle*/, scale /* scale */, 1 /* smooth==1*/ );
81       SDL_FreeSurface ( s );
82       s = scaled;
83     }
84   } else if ( s -> w > maxwidth ) {
85     SDL_Surface *scaled;
86     double scale = (double)maxwidth / (double)s -> w;
87     //pnd_log ( pndn_debug, "  Downscaling; scale factor %f\n", scale );
88     scaled = rotozoomSurface ( s, 0 /* angle*/, scale /* scale */, 1 /* smooth==1*/ );
89     SDL_FreeSurface ( s );
90     s = scaled;
91   }
92
93   // add to cache
94   c = (mm_cache_t*) malloc ( sizeof(mm_cache_t) );
95   bzero ( c, sizeof(mm_cache_t) );
96
97   if ( ! g_preview_cache ) {
98     g_preview_cache = c;
99   } else {
100     c -> next = g_preview_cache;
101     g_preview_cache = c;
102   }
103
104   strncpy ( c -> uniqueid, app -> unique_id, 1000 );
105   c -> i = s;
106
107   return ( 1 );
108 }
109
110 unsigned char cache_icon ( pnd_disco_t *app, unsigned char maxwidth, unsigned char maxheight ) {
111   SDL_Surface *s;
112   mm_cache_t *c;
113
114   // check if already cached
115   if ( ( c = cache_query_icon ( app -> unique_id ) ) ) {
116     return ( 1 ); // already got it
117   }
118
119   // not cached, load it up
120   //
121
122   // pull icon into buffer
123   unsigned int buflen = 0;
124   unsigned char *iconbuf;
125   iconbuf = pnd_emit_icon_to_buffer ( app, &buflen );
126
127   if ( ! iconbuf ) {
128     return ( 0 );
129   }
130
131   // ready up a RWbuffer for SDL
132   SDL_RWops *rwops = SDL_RWFromMem ( iconbuf, buflen );
133
134   s = IMG_Load_RW ( rwops, 1 /* free the rwops */ );
135
136   if ( ! s ) {
137     return ( 0 );
138   }
139
140   free ( iconbuf ); // ditch the icon from ram
141
142   //pnd_log ( pndn_debug, "Image size is %u x %u (max %u x %u)\n", s -> w, s -> h, maxwidth, maxheight );
143
144   // scale the icon?
145   if ( s -> w < maxwidth ) {
146     // scale up?
147     if ( pnd_conf_get_as_int_d ( g_conf, "grid.scale_up_bool", 1 ) ) {
148       SDL_Surface *scaled;
149       double scale = (double)maxwidth / (double)s -> w;
150       //pnd_log ( pndn_debug, "  Upscaling; scale factor %f\n", scale );
151       scaled = rotozoomSurface ( s, 0 /* angle*/, scale /* scale */, 1 /* smooth==1*/ );
152       SDL_FreeSurface ( s );
153       s = scaled;
154     }
155   } else if ( s -> w > maxwidth ) {
156     SDL_Surface *scaled;
157     double scale = (double)maxwidth / (double)s -> w;
158     //pnd_log ( pndn_debug, "  Downscaling; scale factor %f\n", scale );
159     scaled = rotozoomSurface ( s, 0 /* angle*/, scale /* scale */, 1 /* smooth==1*/ );
160     SDL_FreeSurface ( s );
161     s = scaled;
162   }
163
164   // add to cache
165   c = (mm_cache_t*) malloc ( sizeof(mm_cache_t) );
166   bzero ( c, sizeof(mm_cache_t) );
167
168   if ( ! g_icon_cache ) {
169     g_icon_cache = c;
170   } else {
171     c -> next = g_icon_cache;
172     g_icon_cache = c;
173   }
174
175   strncpy ( c -> uniqueid, app -> unique_id, 1000 );
176   c -> i = s;
177
178   return ( 1 );
179 }
180
181 mm_cache_t *cache_query ( char *id, mm_cache_t *head ) {
182   mm_cache_t *iter = head;
183
184   if ( ! id ) {
185     return ( NULL );
186   }
187
188   while ( iter ) {
189     if ( iter -> uniqueid &&
190          strcasecmp ( iter -> uniqueid, id ) == 0 )
191     {
192       return ( iter );
193     }
194     iter = iter -> next;
195   } // while
196
197   return ( NULL );
198 }
199
200 mm_cache_t *cache_query_icon ( char *id ) {
201   return ( cache_query ( id, g_icon_cache ) );
202 }
203
204 mm_cache_t *cache_query_preview ( char *id ) {
205   return ( cache_query ( id, g_preview_cache ) );
206 }