Index: apps/metadata.c
===================================================================
RCS file: /cvsroot/rockbox/apps/metadata.c,v
retrieving revision 1.55
diff -u -r1.55 metadata.c
--- apps/metadata.c	29 Oct 2006 22:18:30 -0000	1.55
+++ apps/metadata.c	3 Nov 2006 14:16:11 -0000
@@ -30,6 +30,7 @@
 #include "replaygain.h"
 #include "debug.h"
 #include "system.h"
+#include "dircache.h"
 
 enum tagtype { TAGTYPE_APE = 1, TAGTYPE_VORBIS };
 
@@ -143,6 +144,96 @@
     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;
+ 
+}
+
+void has_albumart(struct mp3entry* id3) {
+
+  static unsigned char aa[4][6] = {"", "FILE", "ALBUM", "DIR"};
+
+  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,".jpg",5);
+  if(exists(path)) found = 1;
+  
+  /* try <album>.jpg */
+  if((!found) && (id3->album != NULL)){
+    slash=strrchr(path,'/');
+    length = slash ? slash-path+1 : 0; 
+
+    alength = strlen(id3->album);
+    memcpy(path+length,id3->album,alength);
+  
+    memcpy(path+length+alength,".jpg",5);
+    if(exists(path)) found = 2;
+  }
+  
+  /* try folder.jpg  */
+  if(!found){
+    memcpy(path+length,"folder.jpg",11);
+    if(exists(path)) found = 3;
+  }
+  
+  id3->albumarti = found;
+  id3->albumart = aa[found];
+  
+}
+
+void has_lyrics(struct mp3entry* id3) {
+
+  static unsigned char lyr[5][5] = {"", "LRC8", "LRC", "SNC", "TXT"};
+
+  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[i],strlen(lyr[i])+1);
+    if(exists(path)) found = i;
+  }    
+
+  id3->lyricsi = found;
+  id3->lyrics = lyr[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.
@@ -336,6 +427,10 @@
     {
         p = &(id3->composer);
     }
+    else if (strcasecmp(name, "comment") == 0)
+    {
+        p = &(id3->comment);
+    }
     else
     {
         len = parse_replaygain(name, value, id3, buf, buf_remaining);
@@ -1929,9 +2024,16 @@
     }
 
     /* We have successfully read the metadata from the file */
-
     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
===================================================================
RCS file: /cvsroot/rockbox/apps/tagcache.c,v
retrieving revision 1.75
diff -u -r1.75 tagcache.c
--- apps/tagcache.c	24 Oct 2006 17:39:06 -0000	1.75
+++ apps/tagcache.c	3 Nov 2006 15:19:51 -0000
@@ -91,18 +91,18 @@
 static long tempbuf_pos;
 
 /* Tags we want to get sorted (loaded to the tempbuf). */
-static const int sorted_tags[] = { tag_artist, tag_album, tag_genre, tag_composer, tag_title };
+static const int sorted_tags[] = { tag_artist, tag_album, tag_genre, tag_composer, tag_comment, tag_lyrics, tag_albumart, tag_title };
 
 /* Uniqued tags (we can use these tags with filters and conditional clauses). */
-static const int unique_tags[] = { tag_artist, tag_album, tag_genre, tag_composer };
+static const int unique_tags[] = { tag_artist, tag_album, tag_genre, tag_composer, tag_comment, tag_lyrics, tag_albumart };
 
 /* Numeric tags (we can use these tags with conditional clauses). */
 static const int numeric_tags[] = { tag_year, tag_tracknumber, tag_length, tag_bitrate,
-    tag_playcount, tag_playtime, tag_lastplayed, tag_virt_autoscore };
+    tag_playcount, tag_rating, tag_playtime, tag_lastplayed, tag_virt_autoscore, tag_virt_relplay };
 
 static const char *tags_str[] = { "artist", "album", "genre", "title", 
-    "filename", "composer", "year", "tracknumber", "bitrate", "length",
-    "playcount", "playtime", "lastplayed" };
+    "filename", "composer", "comment", "lyrics", "albumart", "year", "tracknumber", "bitrate", "length",
+    "playcount", "rating", "playtime", "lastplayed" };
 
 /* Status information of the tagcache. */
 static struct tagcache_stat stat;
@@ -635,6 +635,7 @@
     
     switch (tag) 
     {
+        case tag_virt_relplay:
         case tag_virt_autoscore:
             if (idx->tag_seek[tag_length] == 0 
                 || idx->tag_seek[tag_playcount] == 0)
@@ -644,8 +645,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;
         
@@ -1366,6 +1369,7 @@
 {
     struct index_entry *entry;
     int idx_id;
+    char * tmp;
     
     if (!stat.ready)
         return false;
@@ -1377,11 +1381,12 @@
     
     entry = &hdr->indices[idx_id];
     
-    id3->title = get_tag(entry, tag_title)->tag_data;
-    id3->artist = get_tag(entry, tag_artist)->tag_data;
-    id3->album = get_tag(entry, tag_album)->tag_data;
-    id3->genre_string = get_tag(entry, tag_genre)->tag_data;
-    id3->composer = get_tag(entry, tag_composer)->tag_data;
+    tmp = get_tag(entry, tag_title)->tag_data;    id3->title        = (tmp[0]=='<') ? NULL : tmp;
+    tmp = get_tag(entry, tag_artist)->tag_data;   id3->artist       = (tmp[0]=='<') ? NULL : tmp;
+    tmp = get_tag(entry, tag_album)->tag_data;    id3->album        = (tmp[0]=='<') ? NULL : tmp;
+    tmp = get_tag(entry, tag_genre)->tag_data;    id3->genre_string = (tmp[0]=='<') ? NULL : tmp;
+    tmp = get_tag(entry, tag_composer)->tag_data; id3->composer     = (tmp[0]=='<') ? NULL : tmp;
+    tmp = get_tag(entry, tag_comment)->tag_data;  id3->comment      = (tmp[0]=='<') ? NULL : tmp;
     id3->year = get_tag_numeric(entry, tag_year);
     id3->tracknum = get_tag_numeric(entry, tag_tracknumber);
     id3->bitrate = get_tag_numeric(entry, tag_bitrate);
@@ -1530,6 +1536,9 @@
     ADD_TAG(entry, tag_album, &track.id3.album);
     ADD_TAG(entry, tag_genre, &genrestr);
     ADD_TAG(entry, tag_composer, &track.id3.composer);
+    ADD_TAG(entry, tag_comment, &track.id3.comment);
+    ADD_TAG(entry, tag_lyrics, &track.id3.lyrics);
+    ADD_TAG(entry, tag_albumart, &track.id3.albumart);
     entry.data_length = offset;
     
     /* Write the header */
@@ -1542,6 +1551,9 @@
     write_item(track.id3.album);
     write_item(genrestr);
     write_item(track.id3.composer);
+    write_item(track.id3.comment);
+    write_item(track.id3.lyrics);
+    write_item(track.id3.albumart);
     total_entry_count++;    
 }
 
@@ -2694,7 +2706,7 @@
     char tag_data[MAX_PATH];
     int idx_id;
     long masterfd = (long)parameters;
-    const int import_tags[] = { tag_playcount, tag_playtime, tag_lastplayed };
+    const int import_tags[] = { tag_playcount, tag_rating, tag_playtime, tag_lastplayed };
     int i;
     (void)line_n;
     
Index: apps/tagcache.h
===================================================================
RCS file: /cvsroot/rockbox/apps/tagcache.h,v
retrieving revision 1.29
diff -u -r1.29 tagcache.h
--- apps/tagcache.h	25 Oct 2006 15:14:15 -0000	1.29
+++ apps/tagcache.h	3 Nov 2006 15:19:53 -0000
@@ -23,12 +23,12 @@
 #include "id3.h"
 
 enum tag_type { tag_artist = 0, tag_album, tag_genre, tag_title,
-    tag_filename, tag_composer, tag_year, tag_tracknumber,
-    tag_bitrate, tag_length, tag_playcount, tag_playtime, tag_lastplayed,
+    tag_filename, tag_composer, tag_comment, tag_lyrics, tag_albumart, tag_year, tag_tracknumber,
+    tag_bitrate, tag_length, tag_playcount, tag_rating, tag_playtime, tag_lastplayed,
     /* Virtual tags */
-    tag_virt_autoscore };
+    tag_virt_autoscore, tag_virt_relplay };
 
-#define TAG_COUNT 13
+#define TAG_COUNT 17
 
 /* Allow a little drift to the filename ordering (should not be too high/low). */
 #define POS_HISTORY_COUNT 4
@@ -37,7 +37,7 @@
 #define IDX_BUF_DEPTH 64
 
 /* Tag Cache Header version 'TCHxx'. Increment when changing internal structures. */
-#define TAGCACHE_MAGIC  0x54434806
+#define TAGCACHE_MAGIC  0x54434809
 
 /* How much to allocate extra space for ramcache. */
 #define TAGCACHE_RESERVE 32768
Index: apps/tagtree.c
===================================================================
RCS file: /cvsroot/rockbox/apps/tagtree.c,v
retrieving revision 1.55
diff -u -r1.55 tagtree.c
--- apps/tagtree.c	25 Oct 2006 15:14:15 -0000	1.55
+++ apps/tagtree.c	3 Nov 2006 17:08:18 -0000
@@ -194,6 +194,9 @@
     MATCH(tag, buf, "artist", tag_artist);
     MATCH(tag, buf, "bitrate", tag_bitrate);
     MATCH(tag, buf, "composer", tag_composer);
+    MATCH(tag, buf, "comment", tag_comment);
+    MATCH(tag, buf, "lyrics", tag_lyrics);
+    MATCH(tag, buf, "albumart", tag_albumart);
     MATCH(tag, buf, "genre", tag_genre);
     MATCH(tag, buf, "length", tag_length);
     MATCH(tag, buf, "title", tag_title);
@@ -201,8 +204,10 @@
     MATCH(tag, buf, "tracknum", tag_tracknumber);
     MATCH(tag, buf, "year", tag_year);
     MATCH(tag, buf, "playcount", tag_playcount);
+    MATCH(tag, buf, "rating", tag_rating);
     MATCH(tag, buf, "lastplayed", tag_lastplayed);
     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);
@@ -595,9 +600,10 @@
     }
     
     id3->playcount  = tagcache_get_numeric(&tcs, tag_playcount);
+    if(!id3->rating) id3->rating = tagcache_get_numeric(&tcs, tag_rating);
     id3->lastplayed = tagcache_get_numeric(&tcs, tag_lastplayed);
-    id3->rating     = tagcache_get_numeric(&tcs, tag_virt_autoscore) / 10;
-    
+    id3->score      = tagcache_get_numeric(&tcs, tag_virt_autoscore) / 10;
+
     tagcache_search_finish(&tcs);
 }
 
@@ -605,6 +611,7 @@
 {
     (void)last_track;
     long playcount;
+    long rating;
     long playtime;
     long lastplayed;
     
@@ -634,6 +641,8 @@
     
     playcount++;
     
+    rating = (long) id3->rating;
+    
     lastplayed = tagcache_increase_serial();
     if (lastplayed < 0)
     {
@@ -646,12 +655,13 @@
     playtime += MIN(id3->length, id3->elapsed + 15 * 1000);
     
     logf("ube:%s", id3->path);
-    logf("-> %d/%d/%d", last_track, playcount, playtime);
+    logf("-> %d/%d/%d/%d", last_track, playcount, rating, playtime);
     logf("-> %d/%d/%d", 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_rating, rating)
         || !tagcache_modify_numeric_entry(&tcs, tag_playtime, playtime)
         || !tagcache_modify_numeric_entry(&tcs, tag_lastplayed, lastplayed))
     {
Index: apps/gui/gwps-common.c
===================================================================
RCS file: /cvsroot/rockbox/apps/gui/gwps-common.c,v
retrieving revision 1.64
diff -u -r1.64 gwps-common.c
--- apps/gui/gwps-common.c	30 Oct 2006 00:23:30 -0000	1.64
+++ apps/gui/gwps-common.c	3 Nov 2006 14:16:11 -0000
@@ -504,6 +504,9 @@
                 case 'c':  /* ID3 Composer */
                     return id3->composer;
 
+                case 'C':  /* ID3 Comment */
+                    return id3->comment;
+
                 case 'y':  /* year */
                     if( id3->year_string )
                         return id3->year_string;
@@ -551,6 +554,16 @@
             *flags |= WPS_REFRESH_STATIC;
             switch(tag[1])
             {
+                case 'a':  
+                    *flags |= WPS_REFRESH_DYNAMIC;
+                    *intval = id3->albumarti;
+                    return id3->albumart;
+
+                case 'l':
+                    *flags |= WPS_REFRESH_DYNAMIC;
+                    *intval = id3->lyricsi;
+                    return id3->lyrics;
+
                 case 'v':  /* VBR file? */
                     return id3->vbr ? "(avg)" : NULL;
 
@@ -927,6 +940,7 @@
             {
                 case 'p':  /* Playcount */
                     *flags |= WPS_REFRESH_STATIC;
+                    *intval = cid3->playcount+1;
                     snprintf(buf, buf_size, "%ld", cid3->playcount);
                     return buf;
                 case 'r':  /* Rating */
Index: firmware/id3.c
===================================================================
RCS file: /cvsroot/rockbox/firmware/id3.c,v
retrieving revision 1.135
diff -u -r1.135 id3.c
--- firmware/id3.c	25 Oct 2006 16:57:53 -0000	1.135
+++ firmware/id3.c	3 Nov 2006 14:16:11 -0000
@@ -316,6 +316,14 @@
     return bufferpos;
 }
 
+/* parse comment */
+static int parsecomment( struct mp3entry* entry, char* tag, int bufferpos )
+{
+    
+    entry->comment = tag + 4;       // simplistic
+    return bufferpos;
+}
+
 /* parse numeric genre from string, version 2.2 and 2.3 */
 static int parsegenre( struct mp3entry* entry, char* tag, int bufferpos )
 {
@@ -413,6 +421,7 @@
     { "TYER", 4, offsetof(struct mp3entry, year_string), &parseyearnum, false },
     { "TYE",  3, offsetof(struct mp3entry, year_string), &parseyearnum, false },
     { "TCOM", 4, offsetof(struct mp3entry, composer), NULL, false },
+    { "COMM", 4, offsetof(struct mp3entry, comment), &parsecomment, false },
     { "TCON", 4, offsetof(struct mp3entry, genre_string), &parsegenre, false },
     { "TCO",  3, offsetof(struct mp3entry, genre_string), &parsegenre, false },
 #if CONFIG_CODEC == SWCODEC
@@ -1116,6 +1125,8 @@
         entry->year_string += offset;
     if (entry->composer)
         entry->composer += offset;
+    if (entry->comment)
+        entry->comment += offset;
 #if CONFIG_CODEC == SWCODEC
     if (entry->track_gain_string)
         entry->track_gain_string += offset;
Index: firmware/export/id3.h
===================================================================
RCS file: /cvsroot/rockbox/firmware/export/id3.h,v
retrieving revision 1.32
diff -u -r1.32 id3.h
--- firmware/export/id3.h	25 Oct 2006 16:57:53 -0000	1.32
+++ firmware/export/id3.h	3 Nov 2006 14:28:01 -0000
@@ -97,6 +97,7 @@
     char* track_string;
     char* year_string;
     char* composer;
+    char* comment;
     int tracknum;
     int version;
     int layer;
@@ -147,8 +148,15 @@
     long songentryoffset;
     long rundbentryoffset;
 
+    /* associated file indicators */
+    char* lyrics;
+    int lyricsi;
+    char* albumart;
+    int albumarti;
+
     /* runtime database fields */
     short rating;
+    short score;
     long playcount;
     long lastplayed;
     
