Index: apps/metadata/mp4.c =================================================================== --- apps/metadata/mp4.c (revision 14620) +++ apps/metadata/mp4.c (working copy) @@ -68,6 +68,7 @@ #define MP4_trak MP4_ID('t', 'r', 'a', 'k') #define MP4_trkn MP4_ID('t', 'r', 'k', 'n') #define MP4_udta MP4_ID('u', 'd', 't', 'a') +#define MP4_rate MP4_ID('r', 'a', 't', 'e') #define MP4_extra MP4_ID('-', '-', '-', '-') /* Read the tag data from an MP4 file, storing up to buffer_size bytes in @@ -446,6 +447,12 @@ id3->tracknum = betoh16(n[1]); } break; + + case MP4_rate: + read_mp4_tag_string(fd, size, &buffer, &buffer_left, + &id3->rating_string); + id3->rating=atoi(id3->rating_string)/10; /* rating in MP4 0-100 */ + break; case MP4_extra: { Index: apps/metadata/asf.c =================================================================== --- apps/metadata/asf.c (revision 14620) +++ apps/metadata/asf.c (working copy) @@ -385,8 +385,13 @@ id3->comment = id3buf; asf_utf16LEdecode(fd, strlength[3], &id3buf, &id3buf_remaining); } + + if (strlength[4] > 0) { /* 4 - rating */ + id3->rating_string = id3buf; + asf_utf16LEdecode(fd, strlength[4], &id3buf, &id3buf_remaining); + id3->rating = atoi(id3->rating_string)/10; + } - lseek(fd, strlength[4], SEEK_CUR); /* 4 - rating */ } else if (asf_guid_match(¤t.guid, &asf_guid_extended_content_description)) { uint16_t count; int i; @@ -430,7 +435,26 @@ asf_utf16LEdecode(fd, length, &id3buf, &id3buf_remaining); } else if ((!strcmp("WM/Composer",utf8buf)) && (type == 0)) { id3->composer = id3buf; - asf_utf16LEdecode(fd, length, &id3buf, &id3buf_remaining); + } else if (!strcmp("WM/SharedUserRating",utf8buf)) { + if (type == 0) { + id3->rating_string = id3buf; + asf_utf16LEdecode(fd, length, &id3buf, &id3buf_remaining); + id3->rating = atoi(id3->rating_string)/10; + } else if ((type >=2) && (type <=5)) { + id3->rating = (asf_intdecode(fd, type, length)+1)/10; /*1 to 99*/ + } else { + lseek(fd, length, SEEK_CUR); + } + } else if (!strcmp("SDB/Rating",utf8buf)) { + if (type == 0) { + id3->rating_string = id3buf; + asf_utf16LEdecode(fd, length, &id3buf, &id3buf_remaining); + id3->rating = atoi(id3->rating_string)/10; + } else if ((type >=2) && (type <=5)) { + id3->rating = asf_intdecode(fd, type, length)/10; /*0 to 100*/ + } else { + lseek(fd, length, SEEK_CUR); + } } else if (!strcmp("WM/Year",utf8buf)) { if (type == 0) { id3->year_string = id3buf; Index: apps/metadata/metadata_common.c =================================================================== --- apps/metadata/metadata_common.c (revision 14620) +++ apps/metadata/metadata_common.c (working copy) @@ -292,6 +292,11 @@ { p = &(id3->grouping); } + else if (strcasecmp(name, "rating") == 0) + { + id3->rating=(atoi(value)/10); /* VORBIS and APEv2 rating 0 to 100)*/ + p = &(value); + } else { len = parse_replaygain(name, value, id3, buf, buf_remaining); Index: firmware/export/id3.h =================================================================== --- firmware/export/id3.h (revision 14620) +++ firmware/export/id3.h (working copy) @@ -207,6 +207,7 @@ /* runtime database fields */ long tagcache_idx; short rating; + char* rating_string; short score; long playcount; long lastplayed; Index: firmware/id3.c =================================================================== --- firmware/id3.c (revision 14620) +++ firmware/id3.c (working copy) @@ -351,6 +351,54 @@ return bufferpos; } +/* parse numeric value from rating entry */ +static int parserating( struct mp3entry* entry, char* tag, int bufferpos ) +{ +char* value_str=NULL; +unsigned char value=0; +int desc_len = strlen(tag); + + /* tag is a string with an e-mail address in it, rating is one byte after the (null terminated) e-mail*/ + /* no@email is for mediamonkey ratings*/ + + value_str = tag + desc_len + 1; + value=value_str[0]; + + if (!strcmp(tag, "no@email")) + { + if (value >= 255) + entry->rating=10; + else if (value >= 230) + entry->rating=9; + else if (value >= 204) + entry->rating=8; + else if (value >= 178) + entry->rating=7; + else if (value >= 153) + entry->rating=6; + else if (value >= 128) + entry->rating=5; + else if (value >= 102) + entry->rating=4; + else if (value >= 76) + entry->rating=3; + else if (value >= 51) + entry->rating=2; + else if (value >= 26) + entry->rating=1; + else + entry->rating=0; + + return bufferpos+5; /* POPM length after e-mail should this be +5? ie bytes after e-mail?*/ + } + else + { + entry->rating=((value*11)/256); /* rough calculation for other rating schemes */ + return bufferpos+5; /* POPM length after e-mail should this also be +5?*/ + } + +} + /* parse numeric value from string */ static int parsediscnum( struct mp3entry* entry, char* tag, int bufferpos ) { @@ -496,6 +544,7 @@ { "COMM", 4, offsetof(struct mp3entry, comment), NULL, false }, { "TCON", 4, offsetof(struct mp3entry, genre_string), &parsegenre, false }, { "TCO", 3, offsetof(struct mp3entry, genre_string), &parsegenre, false }, + { "POPM", 4, offsetof(struct mp3entry, rating), &parserating, true }, #if CONFIG_CODEC == SWCODEC { "TXXX", 4, 0, &parseuser, false }, { "RVA2", 4, 0, &parserva2, true },