cd7c8b269cdb33406acf94d288d1eb6c0c6df49d
[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 char maxwidth, unsigned char 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     SDL_Surface *scaled;
76     double scale = (double)maxwidth / (double)s -> w;
77     pnd_log ( pndn_debug, "  Upscaling; scale factor %f\n", scale );
78     scaled = rotozoomSurface ( s, 0 /* angle*/, scale /* scale */, 1 /* smooth==1*/ );
79     SDL_FreeSurface ( s );
80     s = scaled;
81   } else if ( s -> w > maxwidth ) {
82     SDL_Surface *scaled;
83     double scale = (double)maxwidth / (double)s -> w;
84     pnd_log ( pndn_debug, "  Downscaling; scale factor %f\n", scale );
85     scaled = rotozoomSurface ( s, 0 /* angle*/, scale /* scale */, 1 /* smooth==1*/ );
86     SDL_FreeSurface ( s );
87     s = scaled;
88   }
89
90   // add to cache
91   c = (mm_cache_t*) malloc ( sizeof(mm_cache_t) );
92   bzero ( c, sizeof(mm_cache_t) );
93
94   if ( ! g_preview_cache ) {
95     g_preview_cache = c;
96   } else {
97     c -> next = g_preview_cache;
98     g_preview_cache = c;
99   }
100
101   strncpy ( c -> uniqueid, app -> unique_id, 1000 );
102   c -> i = s;
103
104   return ( 1 );
105 }
106
107 unsigned char cache_icon ( pnd_disco_t *app, unsigned char maxwidth, unsigned char maxheight ) {
108   SDL_Surface *s;
109   mm_cache_t *c;
110
111   // check if already cached
112   if ( ( c = cache_query_icon ( app -> unique_id ) ) ) {
113     return ( 1 ); // already got it
114   }
115
116   // not cached, load it up
117   //
118
119   // pull icon into buffer
120   unsigned int buflen = 0;
121   unsigned char *iconbuf;
122   iconbuf = pnd_emit_icon_to_buffer ( app, &buflen );
123
124   if ( ! iconbuf ) {
125     return ( 0 );
126   }
127
128   // ready up a RWbuffer for SDL
129   SDL_RWops *rwops = SDL_RWFromMem ( iconbuf, buflen );
130
131   s = IMG_Load_RW ( rwops, 1 /* free the rwops */ );
132
133   if ( ! s ) {
134     return ( 0 );
135   }
136
137   free ( iconbuf ); // ditch the icon from ram
138
139   pnd_log ( pndn_debug, "Image size is %u x %u (max %u x %u)\n", s -> w, s -> h, maxwidth, maxheight );
140
141   // scale the icon?
142   if ( s -> w < maxwidth ) {
143     SDL_Surface *scaled;
144     double scale = (double)maxwidth / (double)s -> w;
145     pnd_log ( pndn_debug, "  Upscaling; scale factor %f\n", scale );
146     scaled = rotozoomSurface ( s, 0 /* angle*/, scale /* scale */, 1 /* smooth==1*/ );
147     SDL_FreeSurface ( s );
148     s = scaled;
149   } else if ( s -> w > maxwidth ) {
150     SDL_Surface *scaled;
151     double scale = (double)maxwidth / (double)s -> w;
152     pnd_log ( pndn_debug, "  Downscaling; scale factor %f\n", scale );
153     scaled = rotozoomSurface ( s, 0 /* angle*/, scale /* scale */, 1 /* smooth==1*/ );
154     SDL_FreeSurface ( s );
155     s = scaled;
156   }
157
158   // add to cache
159   c = (mm_cache_t*) malloc ( sizeof(mm_cache_t) );
160   bzero ( c, sizeof(mm_cache_t) );
161
162   if ( ! g_icon_cache ) {
163     g_icon_cache = c;
164   } else {
165     c -> next = g_icon_cache;
166     g_icon_cache = c;
167   }
168
169   strncpy ( c -> uniqueid, app -> unique_id, 1000 );
170   c -> i = s;
171
172   return ( 1 );
173 }
174
175 mm_cache_t *cache_query ( char *id, mm_cache_t *head ) {
176   mm_cache_t *iter = head;
177
178   if ( ! id ) {
179     return ( NULL );
180   }
181
182   while ( iter ) {
183     if ( iter -> uniqueid &&
184          strcasecmp ( iter -> uniqueid, id ) == 0 )
185     {
186       return ( iter );
187     }
188     iter = iter -> next;
189   } // while
190
191   return ( NULL );
192 }
193
194 mm_cache_t *cache_query_icon ( char *id ) {
195   return ( cache_query ( id, g_icon_cache ) );
196 }
197
198 mm_cache_t *cache_query_preview ( char *id ) {
199   return ( cache_query ( id, g_preview_cache ) );
200 }