Index: apps/gui/gwps-common.c
===================================================================
--- apps/gui/gwps-common.c	(revision 12921)
+++ apps/gui/gwps-common.c	(working copy)
@@ -540,6 +540,16 @@
             *flags |= WPS_REFRESH_STATIC;
             switch(tag[1])
             {
+                case 'a':  
+                    *flags |= WPS_REFRESH_DYNAMIC;
+                    *intval = id3->albumart;
+                    return aa_strings[(*intval)++];
+
+                case 'l':
+                    *flags |= WPS_REFRESH_DYNAMIC;
+                    *intval = id3->lyrics;
+                    return lyr_strings[(*intval)++];
+
                 case 'v':  /* VBR file? */
                     return id3->vbr ? "(avg)" : NULL;
 
Index: apps/metadata.c
===================================================================
--- apps/metadata.c	(revision 12921)
+++ apps/metadata.c	(working copy)
@@ -22,6 +22,7 @@
 #include <ctype.h>
 #include <inttypes.h>
 
+#include "dircache.h"
 #include "errno.h"
 #include "metadata.h"
 #include "mp3_playback.h"
@@ -52,6 +53,12 @@
 
 #define MP4_ID(a, b, c, d)  (((a) << 24) | ((b) << 16) | ((c) << 8) | (d))
 
+#if LCD_DEPTH > 2
+#define AA_EXT ".bmp"
+#else
+#define AA_EXT ".jpg"
+#endif
+
 #define MP4_3gp6 MP4_ID('3', 'g', 'p', '6')
 #define MP4_alac MP4_ID('a', 'l', 'a', 'c')
 #define MP4_calb MP4_ID(0xa9, 'a', 'l', 'b')
@@ -124,6 +131,97 @@
     32000, 44100, 48000, 64000, 88200, 96000, 192000 
 };
 
+/* checks for existence of file if possible using dircache */
+bool exists(const char* pathname) {
+
+  bool found = false;
+  int fd;
+
+/* debugf("EXISTS %s?\n", pathname);*/
+
+#ifdef HAVE_DIRCACHE
+  if(dircache_is_enabled()) 
+    found = (NULL != dircache_get_entry_ptr(pathname));
+  else 
+#endif
+
+  { 
+    fd=open(pathname, O_RDONLY);
+    if(fd>-1) {     
+       close(fd);   	
+       found = true;
+    }   
+  }  
+  return found;
+ 
+}
+
+unsigned char aa_strings[4][6] = {"NONE", "FILE", "ALBUM", "DIR"};
+
+
+void has_albumart(struct mp3entry* id3) {
+
+  int found = 0;
+  unsigned char *path, *dot, *slash;
+  int length, alength; 
+  
+  /* is valid id3 ? */
+  if(!(id3 && (path=id3->path) && (dot=strrchr(path,'.')))) 
+    return;
+
+  length=dot-path; 
+  
+  /* try <filename>.jpg */
+  memcpy(path+length,AA_EXT,5);
+  if(exists(path)) found = 1;
+  
+  slash=strrchr(path,'/');
+  length = slash ? slash-path+1 : 0; 
+
+  /* try <album>.jpg */
+  if((!found) && (id3->album != NULL)){
+
+    alength = strlen(id3->album);
+    memcpy(path+length,id3->album,alength);
+  
+    memcpy(path+length+alength,AA_EXT,5);
+    if(exists(path)) found = 2;
+  }
+  
+  /* try folder.jpg  */
+  if(!found){
+    memcpy(path+length,"folder" AA_EXT,11);
+    if(exists(path)) found = 3;
+  }
+  
+  id3->albumart = found;
+  
+}
+
+unsigned char lyr_strings[5][5] = {"NONE", "LRC8", "LRC", "SNC", "TXT"};
+
+void has_lyrics(struct mp3entry* id3) {
+
+
+  int found = 0;   
+  unsigned char *path, *dot;
+  int length, i; 
+  
+  /* is valid id3 ? */
+  if(!(id3 && (path=id3->path) && (dot=strrchr(path,'.')))) 
+    return;
+
+  length=dot-path+1; 
+
+  for(i=1; (i<5) && (found==0); i++) {
+    memcpy(path+length,lyr_strings[i],strlen(lyr_strings[i])+1);
+    if(exists(path)) found = i;
+  }    
+
+  id3->lyrics = found;
+
+}
+
 /* Read a string from the file. Read up to size bytes, or, if eos != -1, 
  * until the eos character is found (eos is not stored in buf, unless it is
  * nil). Writes up to buf_size chars to buf, always terminating with a nil.
@@ -2327,6 +2425,14 @@
     
     lseek(fd, 0, SEEK_SET);
     strncpy(track->id3.path, trackname, sizeof(track->id3.path));
+ 
+    has_lyrics(&track->id3);    
+/*  only changes extensions - no need to restore path */
+/*  strncpy(track->id3.path, trackname, sizeof(track->id3.path)); */
+ 
+    has_albumart(&track->id3);
+    strncpy(track->id3.path, trackname, sizeof(track->id3.path));
+      
     track->taginfo_ready = true;
 
     return true;
Index: apps/tagcache.c
===================================================================
--- apps/tagcache.c	(revision 12922)
+++ apps/tagcache.c	(working copy)
@@ -114,13 +114,13 @@
     tag_composer, tag_comment, tag_albumartist };
 
 /* Numeric tags (we can use these tags with conditional clauses). */
-static const int numeric_tags[] = { tag_year, tag_tracknumber, tag_length, 
+static const int numeric_tags[] = { tag_year, tag_lyrics, tag_albumart, tag_tracknumber, tag_length, 
     tag_bitrate, tag_playcount, tag_rating, tag_playtime, tag_lastplayed, tag_commitid,
-    tag_virt_entryage, tag_virt_autoscore };
+    tag_virt_entryage, tag_virt_autoscore, tag_virt_relplay };
 
 /* String presentation of the tags defined in tagcache.h. Must be in correct order! */
 static const char *tags_str[] = { "artist", "album", "genre", "title", 
-    "filename", "composer", "comment", "albumartist", "year", "tracknumber", 
+    "filename", "composer", "comment", "albumartist", "year", "lyrics", "albumart", "tracknumber", 
     "bitrate", "length", "playcount", "rating", "playtime", "lastplayed", "commitid" };
 
 /* Status information of the tagcache. */
@@ -167,7 +167,7 @@
 
 /* For the endianess correction */
 static const char *tagfile_entry_ec   = "ss";
-static const char *index_entry_ec     = "llllllllllllllllll"; /* (1 + TAG_COUNT) * l */
+static const char *index_entry_ec     = "llllllllllllllllllll"; /* (1 + TAG_COUNT) * l */
 static const char *tagcache_header_ec = "lll";
 static const char *master_header_ec   = "llllll";
 
@@ -659,6 +659,7 @@
     
     switch (tag) 
     {
+        case tag_virt_relplay:
         case tag_virt_autoscore:
             if (idx->tag_seek[tag_length] == 0 
                 || idx->tag_seek[tag_playcount] == 0)
@@ -668,8 +669,10 @@
             else
             {
                 data = 100 * idx->tag_seek[tag_playtime]
-                    / idx->tag_seek[tag_length]
-                    / idx->tag_seek[tag_playcount];
+                    / idx->tag_seek[tag_length];
+
+                if(tag == tag_virt_autoscore) 
+                    data /= idx->tag_seek[tag_playcount];
             }
             break;
         
@@ -1500,6 +1503,8 @@
 
     id3->playcount  = get_tag_numeric(entry, tag_playcount);
     id3->rating     = get_tag_numeric(entry, tag_rating);
+    id3->lyrics     = get_tag_numeric(entry, tag_lyrics);
+    id3->albumart   = get_tag_numeric(entry, tag_albumart);
     id3->lastplayed = get_tag_numeric(entry, tag_lastplayed);
     id3->score      = get_tag_numeric(entry, tag_virt_autoscore) / 10;
     id3->year       = get_tag_numeric(entry, tag_year);
@@ -1646,6 +1651,8 @@
     
     /* Numeric tags */
     entry.tag_offset[tag_year] = track.id3.year;
+    entry.tag_offset[tag_lyrics] = track.id3.lyrics;
+    entry.tag_offset[tag_albumart] = track.id3.albumart;
     entry.tag_offset[tag_tracknumber] = track.id3.tracknum;
     entry.tag_offset[tag_length] = track.id3.length;
     entry.tag_offset[tag_bitrate] = track.id3.bitrate;
Index: apps/tagcache.h
===================================================================
--- apps/tagcache.h	(revision 12922)
+++ apps/tagcache.h	(working copy)
@@ -24,12 +24,13 @@
 
 enum tag_type { tag_artist = 0, tag_album, tag_genre, tag_title,
     tag_filename, tag_composer, tag_comment, tag_albumartist, tag_year, 
+    tag_lyrics, tag_albumart, 
     tag_tracknumber, tag_bitrate, tag_length, tag_playcount, tag_rating, 
     tag_playtime, tag_lastplayed, tag_commitid,
     /* Virtual tags */
-    tag_virt_entryage, tag_virt_autoscore };
+    tag_virt_entryage, tag_virt_autoscore, tag_virt_relplay };
 
-#define TAG_COUNT 17
+#define TAG_COUNT 19
 
 /* Maximum length of a single tag. */
 #define TAG_MAXLEN (MAX_PATH*2)
@@ -41,7 +42,7 @@
 #define IDX_BUF_DEPTH 64
 
 /* Tag Cache Header version 'TCHxx'. Increment when changing internal structures. */
-#define TAGCACHE_MAGIC  0x54434809
+#define TAGCACHE_MAGIC  0x54434880
 
 /* How much to allocate extra space for ramcache. */
 #define TAGCACHE_RESERVE 32768
Index: apps/tagnavi.config
===================================================================
--- apps/tagnavi.config	(revision 12922)
+++ apps/tagnavi.config	(working copy)
@@ -10,10 +10,9 @@
 %format "fmt_title"       "%s" title
 %format "fmt_mostplayed"  "(%3d) %s - %s" playcount artist title %sort = "inverse" %limit = "100"
 %format "fmt_lastplayed"  "%06d%s - %s" lastplayed artist title %sort = "inverse" %limit = "99" %strip = "6"
-%format "fmt_best_tracks" "%02d. %s (%2d)" tracknum title rating %sort = "inverse"
+%format "fmt_best_tracks" "%02d. %s (%3d)" tracknum title autoscore
 %format "fmt_played"      "(%3d/%d) %s" autoscore playcount title
 %format "fmt_score"       "(%3d) %s" autoscore title
-%format "fmt_rating"      "(%2d) %s" rating title %sort = "inverse"
 
 # Include our custom menu
 %include "/.rockbox/tagnavi_custom.config"
@@ -29,7 +28,6 @@
 "Title" -> title ? title ~ ""
 "Filename" -> filename ? filename ~ ""
 "Score" -> title = "fmt_score" ? autoscore > ""
-"Rating" -> title = "fmt_rating" ? rating > ""
 
 # ^ An empy line ends the menu
 
@@ -44,13 +42,12 @@
 "Genre"    -> genre    -> artist -> album -> title = "fmt_title"
 "Composer" -> composer -> album -> title = "fmt_title"
 "Track"    -> title
-"Rating"    -> rating -> title = "fmt_rating"
 "Year"     -> year ? year > "1000" & year < "2008" -> artist -> album -> title = "fmt_title"
 "Search..." ==> "search"
 "Most played tracks" -> title = "fmt_mostplayed" ? playcount > "0"
 "Last played tracks" -> title = "fmt_lastplayed" ? playcount > "0"
 "Never played tracks" -> artist ? playcount == "0" -> album -> title = "fmt_title"
-"Best tracks" -> artist ? playcount > "1" & rating > "8" -> album -> title = "fmt_best_tracks"
+"Best tracks" -> artist ? playcount > "1" & autoscore > "85" -> album -> title = "fmt_best_tracks"
 "List played tracks" -> title = "fmt_played" ? playcount > "0"
 "Last added tracks" -> artist ? entryage == "0" -> album -> title = "fmt_title"
 "Custom view..."  ==> "custom"
Index: apps/tagtree.c
===================================================================
--- apps/tagtree.c	(revision 12922)
+++ apps/tagtree.c	(working copy)
@@ -204,12 +204,15 @@
     MATCH(tag, buf, "filename", tag_filename);
     MATCH(tag, buf, "tracknum", tag_tracknumber);
     MATCH(tag, buf, "year", tag_year);
+    MATCH(tag, buf, "lyrics", tag_lyrics);
+    MATCH(tag, buf, "albumart", tag_albumart);
     MATCH(tag, buf, "playcount", tag_playcount);
     MATCH(tag, buf, "rating", tag_rating);
     MATCH(tag, buf, "lastplayed", tag_lastplayed);
     MATCH(tag, buf, "commitid", tag_commitid);
     MATCH(tag, buf, "entryage", tag_virt_entryage);
     MATCH(tag, buf, "autoscore", tag_virt_autoscore);
+    MATCH(tag, buf, "relplay", tag_virt_relplay);
     MATCH(tag, buf, "%sort", var_sorttype);
     MATCH(tag, buf, "%limit", var_limit);
     MATCH(tag, buf, "%strip", var_strip);
@@ -615,6 +618,8 @@
 {
     (void)last_track;
     long playcount;
+    long lyrics;
+    long albumart;
     long rating;
     long playtime;
     long lastplayed;
@@ -645,6 +650,8 @@
     
     playcount++;
     
+    lyrics   = (long) id3->lyrics;
+    albumart = (long) id3->albumart;
     rating   = (long) id3->rating;
     
     lastplayed = tagcache_increase_serial();
@@ -659,12 +666,14 @@
     playtime += MIN(id3->length, id3->elapsed + 15 * 1000);
     
     logf("ube:%s", id3->path);
-    logf("-> %d/%ld/%ld/%ld", last_track, playcount, rating, playtime);
+    logf("-> %d/%ld/%ld/%ld/%ld/%ld", last_track, playcount, lyrics, albumart, rating, playtime);
     logf("-> %ld/%ld/%ld", id3->elapsed, id3->length, MIN(id3->length, id3->elapsed + 15 * 1000));
     
     /* lastplayed not yet supported. */
     
     if (!tagcache_modify_numeric_entry(&tcs, tag_playcount, playcount)
+        || !tagcache_modify_numeric_entry(&tcs, tag_lyrics, lyrics)
+        || !tagcache_modify_numeric_entry(&tcs, tag_albumart, albumart)
         || !tagcache_modify_numeric_entry(&tcs, tag_rating, rating)
         || !tagcache_modify_numeric_entry(&tcs, tag_playtime, playtime)
         || !tagcache_modify_numeric_entry(&tcs, tag_lastplayed, lastplayed))
@@ -1159,6 +1168,11 @@
         }
         else
             dptr->name = tcs->result;
+            
+        if(tcs->type == tag_lyrics)    
+            dptr->name = lyr_strings[atoi(tcs->result)];    
+        else if(tcs->type == tag_albumart)    
+            dptr->name = aa_strings[atoi(tcs->result)];    
         
         dptr++;
         current_entry_count++;
Index: firmware/export/id3.h
===================================================================
--- firmware/export/id3.h	(revision 12922)
+++ firmware/export/id3.h	(working copy)
@@ -23,6 +23,9 @@
 #include "config.h"
 #include "file.h"
 
+extern unsigned char aa_strings[4][6];
+extern unsigned char lyr_strings[5][5];
+
 /* Audio file types. */
 /* NOTE: The values of the AFMT_* items are used for the %fc tag in the WPS
          - so new entries MUST be added to the end to maintain compatibility.
@@ -197,6 +200,10 @@
     long songentryoffset;
     long rundbentryoffset;
 
+    /* associated file indicators */
+    short lyrics;
+    short albumart;
+
     /* runtime database fields */
     short rating;
     short score;
Index: firmware/include/file.h
===================================================================
--- firmware/include/file.h	(revision 12921)
+++ firmware/include/file.h	(working copy)
@@ -25,7 +25,7 @@
 #undef MAX_PATH /* this avoids problems when building simulator */
 #define MAX_PATH 260
 
-#define MAX_OPEN_FILES 11
+#define MAX_OPEN_FILES 14
 
 #ifndef SEEK_SET
 #define SEEK_SET 0
