Index: apps/gui/gwps-common.c =================================================================== --- apps/gui/gwps-common.c (revision 13649) +++ apps/gui/gwps-common.c (working copy) @@ -941,6 +941,14 @@ (id3->frequency % 1000) / 100); return buf; + case WPS_TOKEN_FILE_AART: + *intval = id3->albumart; + return aa_strings[(*intval)++]; + + case WPS_TOKEN_FILE_LYRICS: + *intval = id3->lyrics; + return lyr_strings[(*intval)++]; + case WPS_TOKEN_FILE_NAME: if (get_dir(buf, buf_size, id3->path, 0)) { /* Remove extension */ Index: apps/gui/gwps.h =================================================================== --- apps/gui/gwps.h (revision 13649) +++ apps/gui/gwps.h (working copy) @@ -171,6 +171,8 @@ WPS_TOKEN_FILE_CODEC, WPS_TOKEN_FILE_FREQUENCY, WPS_TOKEN_FILE_FREQUENCY_KHZ, + WPS_TOKEN_FILE_AART, + WPS_TOKEN_FILE_LYRICS, WPS_TOKEN_FILE_NAME, WPS_TOKEN_FILE_NAME_WITH_EXTENSION, WPS_TOKEN_FILE_PATH, Index: apps/gui/wps_parser.c =================================================================== --- apps/gui/wps_parser.c (revision 13649) +++ apps/gui/wps_parser.c (working copy) @@ -173,6 +173,8 @@ { WPS_TOKEN_FILE_BITRATE, "fb", WPS_REFRESH_STATIC, NULL }, { WPS_TOKEN_FILE_CODEC, "fc", WPS_REFRESH_STATIC, NULL }, { WPS_TOKEN_FILE_FREQUENCY, "ff", WPS_REFRESH_STATIC, NULL }, + { WPS_TOKEN_FILE_AART, "fa", WPS_REFRESH_STATIC, NULL }, + { WPS_TOKEN_FILE_LYRICS, "fl", WPS_REFRESH_STATIC, NULL }, { WPS_TOKEN_FILE_FREQUENCY_KHZ, "fk", WPS_REFRESH_STATIC, NULL }, { WPS_TOKEN_FILE_NAME_WITH_EXTENSION, "fm", WPS_REFRESH_STATIC, NULL }, { WPS_TOKEN_FILE_NAME, "fn", WPS_REFRESH_STATIC, NULL }, @@ -186,6 +188,8 @@ { WPS_TOKEN_FILE_BITRATE, "Fb", WPS_REFRESH_DYNAMIC, NULL }, { WPS_TOKEN_FILE_CODEC, "Fc", WPS_REFRESH_DYNAMIC, NULL }, { WPS_TOKEN_FILE_FREQUENCY, "Ff", WPS_REFRESH_DYNAMIC, NULL }, + { WPS_TOKEN_FILE_AART, "Fa", WPS_REFRESH_DYNAMIC, NULL }, + { WPS_TOKEN_FILE_LYRICS, "Fl", WPS_REFRESH_DYNAMIC, NULL }, { WPS_TOKEN_FILE_FREQUENCY_KHZ, "Fk", WPS_REFRESH_DYNAMIC, NULL }, { WPS_TOKEN_FILE_NAME_WITH_EXTENSION, "Fm", WPS_REFRESH_DYNAMIC, NULL }, { WPS_TOKEN_FILE_NAME, "Fn", WPS_REFRESH_DYNAMIC, NULL }, Index: apps/metadata.c =================================================================== --- apps/metadata.c (revision 13649) +++ apps/metadata.c (working copy) @@ -23,6 +23,7 @@ #include #include "system.h" +#include "dircache.h" #include "playback.h" #include "debug.h" #include "logf.h" @@ -60,6 +61,102 @@ #endif /* CONFIG_CODEC == SWCODEC */ +#if LCD_DEPTH > 2 +#define AA_EXT ".bmp" +#else +#define AA_EXT ".jpg" +#endif + +unsigned char aa_strings[4][6] = {"NONE", "FILE", "ALBUM", "DIR"}; + +/* 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) { + + 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 .jpg */ + memcpy(path+length,AA_EXT,5); + if(exists(path)) found = 1; + + slash=strrchr(path,'/'); + length = slash ? slash-path+1 : 0; + + /* try .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; + +} + /* Simple file type probing by looking at the filename extension. */ unsigned int probe_file_format(const char *filename) { @@ -368,6 +465,13 @@ strncpy(track->id3.path, trackname, sizeof(track->id3.path)); track->taginfo_ready = true; + 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)); + return true; } Index: apps/tagcache.c =================================================================== --- apps/tagcache.c (revision 13649) +++ apps/tagcache.c (working copy) @@ -115,15 +115,15 @@ 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_length_min, tag_virt_length_sec, tag_virt_playtime_min, tag_virt_playtime_sec, - 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. */ @@ -170,7 +170,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"; @@ -693,6 +693,7 @@ data = (idx->tag_seek[tag_playtime]/1000) / 60; break; + case tag_virt_relplay: case tag_virt_autoscore: if (idx->tag_seek[tag_length] == 0 || idx->tag_seek[tag_playcount] == 0) @@ -702,8 +703,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; @@ -1534,6 +1537,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); @@ -1680,6 +1685,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 13649) +++ apps/tagcache.h (working copy) @@ -24,14 +24,15 @@ 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_length_min, tag_virt_length_sec, tag_virt_playtime_min, tag_virt_playtime_sec, - 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) @@ -43,7 +44,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/tagtree.c =================================================================== --- apps/tagtree.c (revision 13649) +++ apps/tagtree.c (working copy) @@ -210,12 +210,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); @@ -671,6 +674,10 @@ /* lastplayed not yet supported. */ if (!tagcache_modify_numeric_entry(&tcs, tag_playcount, playcount) + || !tagcache_modify_numeric_entry(&tcs, tag_year, id3->year) + || !tagcache_modify_numeric_entry(&tcs, tag_tracknumber, id3->tracknum) + || !tagcache_modify_numeric_entry(&tcs, tag_lyrics, id3->lyrics) + || !tagcache_modify_numeric_entry(&tcs, tag_albumart, id3->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)) @@ -1170,6 +1177,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 13649) +++ 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. @@ -198,6 +201,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 13649) +++ 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