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	25 Feb 2006 14:57:07 -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,126 @@
     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)
+        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)
+        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 = &track->id3.albumart_data[0]; */
+    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 +1655,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	25 Feb 2006 14:57:13 -0000
@@ -189,7 +189,77 @@
 
         break;
 #endif
-
+        
+        case 'C':
+            /* Album cover */
+        {
+            data->wps_has_albumart = true;
+            
+            char *ptr = buf+2;
+            char *pos = NULL;
+            
+            /* format: %C|x|y|[maxwidth|maxheight|] */
+            
+            /* get x-position */
+            pos = strchr(ptr, '|');
+            if (pos)
+            {
+                data->albumart_x = atoi(ptr);
+            }
+            else
+            {
+                buf++;
+                return false;
+            }
+            
+            /* get y-position */
+            ptr = pos+1;
+            pos = strchr(ptr, '|');
+            if (pos)
+            {
+                data->albumart_y = atoi(ptr);
+            }
+            else
+            {
+                buf++;
+                return false;
+            }
+            
+            /* get max width */
+            ptr = pos+1;
+            pos = strchr(ptr, '|');
+            if (pos)
+            {
+                data->albumart_max_width = atoi(ptr);
+                if (data->albumart_max_width == 0) data->albumart_max_width = LCD_WIDTH;
+            }
+            else
+            {
+                buf++;
+                /* no max width and max height specified, default to LCD size */
+                data->albumart_max_width = LCD_WIDTH;
+                data->albumart_max_height = LCD_HEIGHT;
+                return true;
+            }
+            
+            /* get max height */
+            ptr = pos+1;
+            pos = strchr(ptr, '|');
+            if (pos)
+            {
+                data->albumart_max_height = atoi(ptr);
+                if (data->albumart_max_height == 0) data->albumart_max_height = LCD_HEIGHT;
+            }
+            else
+            {
+                buf++;
+                return false;
+            }
+            
+            return true;
+        }
+        break;
+        
         case 'P':
             /* progress bar image */
         {
@@ -1415,6 +1485,35 @@
                 wps_draw_image(gwps, n);
         }
     }
+    
+    /* display album art only if the wps has a tag for it */
+    if (data->wps_has_albumart
+        && gwps->state->id3->albumart_found
+        && gwps->state->id3->albumart_width <= data->albumart_max_width
+        && gwps->state->id3->albumart_height <= data->albumart_max_height)
+    {
+        int x;  /* coordinates where the cover will be drawn */
+        int 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 < LCD_WIDTH && data->albumart_max_height < LCD_HEIGHT)
+        {
+            x = data->albumart_x + (data->albumart_max_width - gwps->state->id3->albumart_width)/2;
+            y = data->albumart_y + (data->albumart_max_height - gwps->state->id3->albumart_height)/2;
+        }
+        else
+        {
+            x = data->albumart_x;
+            y = data->albumart_y;
+        }
+        
+        /* 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	25 Feb 2006 14:57:13 -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.23
diff -u -r1.23 gwps.h
--- apps/gui/gwps.h	24 Feb 2006 15:42:50 -0000	1.23
+++ apps/gui/gwps.h	25 Feb 2006 14:57:14 -0000
@@ -327,6 +327,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	25 Feb 2006 14:57:17 -0000
@@ -22,6 +22,7 @@
 #include <stdbool.h>
 #include "config.h"
 #include "file.h"
+#include "lcd.h"
 
 /* Audio file types. */
 /* NOTE: When adding new audio types, also add to codec_labels[] in id3.c */
@@ -124,6 +125,15 @@
     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[15625]; /* buffer where album art is stored */
+                        /* I don't know what size to give it... 15625 allows bitmaps up to 125x125 */
+    int albumart_width;
+    int albumart_height;
+    bool albumart_found; /* true if cover.bmp was found in the same dir as the track */
+#endif
 };
 
 enum {
