Index: apps/metadata.c
===================================================================
RCS file: /cvsroot/rockbox/apps/metadata.c,v
retrieving revision 1.39
diff -u -r1.39 metadata.c
--- apps/metadata.c	1 Feb 2006 16:42:01 -0000	1.39
+++ apps/metadata.c	27 Feb 2006 19:33:37 -0000
@@ -29,6 +29,7 @@
 #include "replaygain.h"
 #include "debug.h"
 #include "system.h"
+#include "bmp.h"
 
 enum tagtype { TAGTYPE_APE = 1, TAGTYPE_VORBIS };
 
@@ -1342,6 +1343,125 @@
     return AFMT_UNKNOWN;
 }
 
+
+#ifdef HAVE_LCD_BITMAP
+
+/* Strip filename from a full path
+ *
+ * buf      - buffer to extract directory to.
+ * buf_size - size of buffer.
+ * fullpath  - fullpath to extract from.
+ *
+ * Returns the full path to the file, minus the file name (including the last slash).
+ */
+static char* strip_filename(char* buf, int buf_size, const char* fullpath)
+{
+    char* sep;
+    int len;
+    
+    if (!buf || buf_size <= 0 || !fullpath)
+        return NULL;
+
+    buf[0] = 0;
+
+    /* if 'fullpath' is not a full path, but only a filename, return immediatly */
+    sep = strrchr(fullpath,'/');
+    if (sep == NULL)
+        return NULL;
+
+    len = MIN(sep - fullpath + 1, buf_size - 1);
+    strncpy(buf, fullpath, len);
+    buf[len] = 0;
+    return buf;
+}
+
+static char* strip_extension(char* buf, int buf_size, const char* file)
+{
+    char* sep;
+    int len;
+ 
+    if (!buf || buf_size <= 0 || !file)
+        return NULL;
+
+    buf[0] = 0;
+
+    sep = strrchr(file,'.');
+    if (sep == NULL)
+        return NULL;
+    
+    len = MIN(sep - file, buf_size - 1);
+    strncpy(buf, file, len);
+    buf[len] = 0;
+    return buf;
+}
+
+static bool file_exists(char *file)
+{
+    int fd;
+
+    if (!file || strlen(file) <= 0)
+        return false;
+
+    fd = open(file, O_RDONLY);
+    if (fd<0)
+        return false;
+    close(fd);
+    return true;
+}
+
+/* Look for album art in the same dir as the track and load it
+ * Returns true if an album art was found and loaded, and false otherwise */
+static bool get_album_art(struct track_info* track, const char* trackname)
+{
+    int ret = 0;
+    char path[MAX_PATH+1];
+
+    if (!track || !trackname)
+        return false;
+    
+    strip_extension(path, sizeof(path) - 4, trackname);
+    strcat(path, ".bmp");           /* the first file we look for is one specific to the track playing */
+    if (!file_exists(path))         /* if it doesn't exist, we look for a file specific to the track's album name */
+    {
+        char dir[MAX_PATH+1];
+        strip_filename(dir, sizeof(dir), trackname);
+        if (track->id3.album && strlen(track->id3.album) > 0)
+        {
+            snprintf(path, sizeof(path)-1,
+                     "%s%s.bmp",
+                     (strlen(dir) >= 1) ? dir : "",
+                     track->id3.album);
+            path[sizeof(path)-1] = 0;
+        }
+
+        if (!file_exists(path))         /* if it still doesn't exist, we look for a generic file */
+        {
+            snprintf(path, sizeof(path)-1,
+                     "%scover.bmp",
+                     (strlen(dir) >= 1) ? dir : "");
+            path[sizeof(path)-1] = 0;
+            if (!file_exists(path))
+                return false;
+        }
+    }
+
+    /* load the cover art bitmap we found */
+    struct bitmap temp_bm;
+    temp_bm.data = (unsigned char *)(track->id3.albumart_data);
+    ret = read_bmp_file(path, &temp_bm,
+                        sizeof(track->id3.albumart_data),
+                        FORMAT_ANY|FORMAT_TRANSPARENT);
+    if (ret > 0)
+    {
+        track->id3.albumart_width = temp_bm.width;
+        track->id3.albumart_height = temp_bm.height;
+        return true;
+    }
+    else return false;
+}
+#endif
+
+
 /* Get metadata for track - return false if parsing showed problems with the
  * file that would prevent playback.
  */
@@ -1534,6 +1654,10 @@
         break;
     }
 
+#ifdef HAVE_LCD_BITMAP
+    track->id3.albumart_found = get_album_art(track, trackname);
+#endif
+
     /* We have successfully read the metadata from the file */
 
     lseek(fd, 0, SEEK_SET);
Index: apps/gui/gwps-common.c
===================================================================
RCS file: /cvsroot/rockbox/apps/gui/gwps-common.c,v
retrieving revision 1.41
diff -u -r1.41 gwps-common.c
--- apps/gui/gwps-common.c	12 Feb 2006 15:37:15 -0000	1.41
+++ apps/gui/gwps-common.c	27 Feb 2006 19:33:39 -0000
@@ -100,6 +100,7 @@
  * %xl   -   preload image
  * %we   -   enable statusbar on wps regardless of the global setting
  * %wd   -   disable statusbar on wps regardless of the global setting
+ * %C    -   display a cover bitmap at given position
  * and also for:
  * #     -   a comment line
  *
@@ -190,6 +191,58 @@
         break;
 #endif
 
+        case 'C':
+            /* Album cover */
+            /* format: %C|x|y|[maxwidth|maxheight|] */
+        {
+            char *pos = buf;
+
+            /* get x-position */
+            pos = strchr(pos, '|');
+            if (!pos)
+                return false;
+            data->albumart_x = atoi(++pos);
+
+            /* get y-position */
+            pos = strchr(pos, '|');
+            if (!pos)
+                return false;
+            data->albumart_y = atoi(++pos);
+
+            /* default max width and height are set to -1 (don't use it) */
+            data->albumart_max_width = -1;
+            data->albumart_max_height = -1;
+
+            /* the next fields are optional... */
+            /* get max width */
+            pos = strchr(pos, '|');
+            if (pos)
+            {
+                data->albumart_max_width = atoi(++pos);
+                if (data->albumart_max_width > LCD_WIDTH)
+                    data->albumart_max_width = LCD_WIDTH;
+                else
+                if (data->albumart_max_width <= 0)
+                    data->albumart_max_width = -1;
+
+                pos = strchr(pos, '|');
+                if (pos)
+                {
+                    data->albumart_max_height = atoi(++pos);
+                    if (data->albumart_max_height > LCD_HEIGHT)
+                        data->albumart_max_height = LCD_HEIGHT;
+                    else
+                    if (data->albumart_max_height <= 0)
+                        data->albumart_max_height = -1;
+                }
+            }
+
+            data->wps_has_albumart = true;
+            return true;
+        }
+
+        break;
+        
         case 'P':
             /* progress bar image */
         {
@@ -1415,6 +1468,37 @@
                 wps_draw_image(gwps, n);
         }
     }
+
+    /* display album art only if the wps has a tag for it, */
+    /* AND if it's smaller than the max size given in the WPS tags (if given). */
+    /* There is no need to check the bitmap is smaller than the screen, */
+    /* because if it's bigger, it won't have been loaded */
+    if (data->wps_has_albumart
+        && gwps->state->id3->albumart_found
+        && (data->albumart_max_width < 0
+            || gwps->state->id3->albumart_width <= data->albumart_max_width)
+        && (data->albumart_max_height < 0 
+            || gwps->state->id3->albumart_height <= data->albumart_max_height))
+    {
+        /* coordinates where the cover will be drawn */
+        int x = data->albumart_x;
+        int y = data->albumart_y;
+
+        /* if a bounding box was defined, center the cover art in it, */
+        /* otherwise, just draw at the normal coordinates */
+        if (data->albumart_max_width > 0)
+            x += (data->albumart_max_width - gwps->state->id3->albumart_width)/2;
+        if (data->albumart_max_height > 0)
+            y += (data->albumart_max_height - gwps->state->id3->albumart_height)/2;
+
+        /* display cover */
+        gwps->display->set_drawmode(DRMODE_FG);
+        gwps->display->transparent_bitmap(
+                                (fb_data *)gwps->state->id3->albumart_data,
+                                x, y, gwps->state->id3->albumart_width,
+                                      gwps->state->id3->albumart_height);
+    }
+
     display->set_drawmode(DRMODE_SOLID);
 }
 #endif
Index: apps/gui/gwps.c
===================================================================
RCS file: /cvsroot/rockbox/apps/gui/gwps.c,v
retrieving revision 1.26
diff -u -r1.26 gwps.c
--- apps/gui/gwps.c	10 Feb 2006 14:07:53 -0000	1.26
+++ apps/gui/gwps.c	27 Feb 2006 19:33:39 -0000
@@ -836,6 +836,7 @@
     data->wps_sb_tag = false;
     data->show_sb_on_wps = false;
     data->progressbar.have_bitmap_pb=false;
+    data->wps_has_albumart = false;
 }
 #else
 #define wps_clear(a)
Index: apps/gui/gwps.h
===================================================================
RCS file: /cvsroot/rockbox/apps/gui/gwps.h,v
retrieving revision 1.24
diff -u -r1.24 gwps.h
--- apps/gui/gwps.h	26 Feb 2006 18:17:47 -0000	1.24
+++ apps/gui/gwps.h	27 Feb 2006 19:33:39 -0000
@@ -328,6 +328,13 @@
     int img_buf_free;
     bool wps_sb_tag;
     bool show_sb_on_wps;
+
+    /* album art support */
+    bool wps_has_albumart;
+    int albumart_x;
+    int albumart_y;
+    int albumart_max_width;
+    int albumart_max_height;
 #endif
 #ifdef HAVE_LCD_CHARCELLS
     unsigned char wps_progress_pat[8];
Index: firmware/export/id3.h
===================================================================
RCS file: /cvsroot/rockbox/firmware/export/id3.h,v
retrieving revision 1.26
diff -u -r1.26 id3.h
--- firmware/export/id3.h	1 Feb 2006 16:42:02 -0000	1.26
+++ firmware/export/id3.h	27 Feb 2006 19:33:40 -0000
@@ -22,6 +22,8 @@
 #include <stdbool.h>
 #include "config.h"
 #include "file.h"
+#include "lcd.h"
+#include "system.h"
 
 /* Audio file types. */
 /* NOTE: When adding new audio types, also add to codec_labels[] in id3.c */
@@ -124,6 +126,17 @@
     long track_peak;    /* 7.24 signed fixed point. 0 for no peak. */
     long album_peak;
 #endif
+
+#ifdef HAVE_LCD_BITMAP
+    /* album art support */
+    fb_data albumart_data[MIN(LCD_WIDTH, 125) * MIN(LCD_HEIGHT, 125)];
+                        /* buffer where album art is stored */
+                        /* I don't know what size to give it... */
+                        /* currently bitmaps up to 125x125 are allowed */
+    int albumart_width;
+    int albumart_height;
+    bool albumart_found; /* true if cover.bmp was found in the same dir as the track */
+#endif
 };
 
 enum {
