First checkin of Minimenu
[pandora-libraries.git] / minimenu / mmcache.c
diff --git a/minimenu/mmcache.c b/minimenu/mmcache.c
new file mode 100644 (file)
index 0000000..cd7c8b2
--- /dev/null
@@ -0,0 +1,200 @@
+
+#include <limits.h>
+
+#include "SDL.h"
+#include "SDL_image.h"
+#include "SDL_rotozoom.h"
+
+#include "pnd_pxml.h"
+#include "pnd_utility.h"
+#include "pnd_conf.h"
+#include "pnd_container.h"
+#include "pnd_discovery.h"
+#include "pnd_logger.h"
+#include "pnd_desktop.h"
+#include "pnd_pndfiles.h"
+#include "pnd_apps.h"
+
+#include "mmenu.h"
+#include "mmapps.h"
+#include "mmcache.h"
+
+extern pnd_conf_handle g_conf;
+
+mm_cache_t *g_icon_cache = NULL;
+mm_cache_t *g_preview_cache = NULL;
+
+unsigned char cache_preview ( pnd_disco_t *app, unsigned char maxwidth, unsigned char maxheight ) {
+  SDL_Surface *s;
+  mm_cache_t *c;
+
+  // does this sucker even have a preview?
+  if ( ! app -> preview_pic1 ) {
+    return ( 1 ); // nothing here, so thats fine
+  }
+
+  // check if already cached
+  if ( ( c = cache_query_preview ( app -> unique_id ) ) ) {
+    return ( 1 ); // already got it
+  }
+
+  // not cached, load it up
+  //
+
+  // see if we can mount the pnd/dir
+  // does preview file exist?
+  //   if so, load it up, size it, cache it
+  //   if not, warning and bail
+  // unmount it
+
+  // can we mount?
+  char fullpath [ PATH_MAX ];
+  char filepath [ PATH_MAX ];
+
+  sprintf ( fullpath, "%s/%s", app -> object_path, app -> object_filename );
+
+  if ( ! pnd_pnd_mount ( pnd_run_script, fullpath, app -> unique_id ) ) {
+    pnd_log ( pndn_debug, "Couldn't mount '%s' for preview\n", fullpath );
+    return ( 0 ); // couldn't mount?!
+  }
+
+  sprintf ( filepath, "%s/%s/%s", PND_MOUNT_PATH, app -> unique_id, app -> preview_pic1 );
+  s = IMG_Load ( filepath );
+
+  pnd_pnd_unmount ( pnd_run_script, fullpath, app -> unique_id );
+
+  if ( ! s ) {
+    pnd_log ( pndn_debug, "Couldn't open image '%s' for preview\n", filepath );
+    return ( 0 );
+  }
+
+  pnd_log ( pndn_debug, "Image size is %u x %u (max %u x %u)\n", s -> w, s -> h, maxwidth, maxheight );
+
+  // scale
+  if ( s -> w < maxwidth ) {
+    SDL_Surface *scaled;
+    double scale = (double)maxwidth / (double)s -> w;
+    pnd_log ( pndn_debug, "  Upscaling; scale factor %f\n", scale );
+    scaled = rotozoomSurface ( s, 0 /* angle*/, scale /* scale */, 1 /* smooth==1*/ );
+    SDL_FreeSurface ( s );
+    s = scaled;
+  } else if ( s -> w > maxwidth ) {
+    SDL_Surface *scaled;
+    double scale = (double)maxwidth / (double)s -> w;
+    pnd_log ( pndn_debug, "  Downscaling; scale factor %f\n", scale );
+    scaled = rotozoomSurface ( s, 0 /* angle*/, scale /* scale */, 1 /* smooth==1*/ );
+    SDL_FreeSurface ( s );
+    s = scaled;
+  }
+
+  // add to cache
+  c = (mm_cache_t*) malloc ( sizeof(mm_cache_t) );
+  bzero ( c, sizeof(mm_cache_t) );
+
+  if ( ! g_preview_cache ) {
+    g_preview_cache = c;
+  } else {
+    c -> next = g_preview_cache;
+    g_preview_cache = c;
+  }
+
+  strncpy ( c -> uniqueid, app -> unique_id, 1000 );
+  c -> i = s;
+
+  return ( 1 );
+}
+
+unsigned char cache_icon ( pnd_disco_t *app, unsigned char maxwidth, unsigned char maxheight ) {
+  SDL_Surface *s;
+  mm_cache_t *c;
+
+  // check if already cached
+  if ( ( c = cache_query_icon ( app -> unique_id ) ) ) {
+    return ( 1 ); // already got it
+  }
+
+  // not cached, load it up
+  //
+
+  // pull icon into buffer
+  unsigned int buflen = 0;
+  unsigned char *iconbuf;
+  iconbuf = pnd_emit_icon_to_buffer ( app, &buflen );
+
+  if ( ! iconbuf ) {
+    return ( 0 );
+  }
+
+  // ready up a RWbuffer for SDL
+  SDL_RWops *rwops = SDL_RWFromMem ( iconbuf, buflen );
+
+  s = IMG_Load_RW ( rwops, 1 /* free the rwops */ );
+
+  if ( ! s ) {
+    return ( 0 );
+  }
+
+  free ( iconbuf ); // ditch the icon from ram
+
+  pnd_log ( pndn_debug, "Image size is %u x %u (max %u x %u)\n", s -> w, s -> h, maxwidth, maxheight );
+
+  // scale the icon?
+  if ( s -> w < maxwidth ) {
+    SDL_Surface *scaled;
+    double scale = (double)maxwidth / (double)s -> w;
+    pnd_log ( pndn_debug, "  Upscaling; scale factor %f\n", scale );
+    scaled = rotozoomSurface ( s, 0 /* angle*/, scale /* scale */, 1 /* smooth==1*/ );
+    SDL_FreeSurface ( s );
+    s = scaled;
+  } else if ( s -> w > maxwidth ) {
+    SDL_Surface *scaled;
+    double scale = (double)maxwidth / (double)s -> w;
+    pnd_log ( pndn_debug, "  Downscaling; scale factor %f\n", scale );
+    scaled = rotozoomSurface ( s, 0 /* angle*/, scale /* scale */, 1 /* smooth==1*/ );
+    SDL_FreeSurface ( s );
+    s = scaled;
+  }
+
+  // add to cache
+  c = (mm_cache_t*) malloc ( sizeof(mm_cache_t) );
+  bzero ( c, sizeof(mm_cache_t) );
+
+  if ( ! g_icon_cache ) {
+    g_icon_cache = c;
+  } else {
+    c -> next = g_icon_cache;
+    g_icon_cache = c;
+  }
+
+  strncpy ( c -> uniqueid, app -> unique_id, 1000 );
+  c -> i = s;
+
+  return ( 1 );
+}
+
+mm_cache_t *cache_query ( char *id, mm_cache_t *head ) {
+  mm_cache_t *iter = head;
+
+  if ( ! id ) {
+    return ( NULL );
+  }
+
+  while ( iter ) {
+    if ( iter -> uniqueid &&
+        strcasecmp ( iter -> uniqueid, id ) == 0 )
+    {
+      return ( iter );
+    }
+    iter = iter -> next;
+  } // while
+
+  return ( NULL );
+}
+
+mm_cache_t *cache_query_icon ( char *id ) {
+  return ( cache_query ( id, g_icon_cache ) );
+}
+
+mm_cache_t *cache_query_preview ( char *id ) {
+  return ( cache_query ( id, g_preview_cache ) );
+}