Index: apps/metadata.c =================================================================== --- apps/metadata.c (revision 13624) +++ apps/metadata.c (working copy) @@ -74,6 +74,9 @@ #define MP4_mp4a MP4_ID('m', 'p', '4', 'a') #define MP4_mp42 MP4_ID('m', 'p', '4', '2') #define MP4_qt MP4_ID('q', 't', ' ', ' ') +#define MP4_soal MP4_ID('s', 'o', 'a', 'l') +#define MP4_soar MP4_ID('s', 'o', 'a', 'r') +#define MP4_sonm MP4_ID('s', 'o', 'n', 'm') #define MP4_soun MP4_ID('s', 'o', 'u', 'n') #define MP4_stbl MP4_ID('s', 't', 'b', 'l') #define MP4_stsd MP4_ID('s', 't', 's', 'd') @@ -274,6 +277,20 @@ { p = &(id3->albumartist); } +#ifdef HAVE_TAGCACHE + else if (strcasecmp(name, "artistsort") == 0) + { + p = &(id3->sort_artist); + } + else if (strcasecmp(name, "albumsort") == 0) + { + p = &(id3->sort_album); + } + else if (strcasecmp(name, "titlesort") == 0) + { + p = &(id3->sort_title); + } +#endif else { len = parse_replaygain(name, value, id3, buf, buf_remaining); @@ -1479,7 +1496,22 @@ id3->genre_string = id3_get_num_genre(betoh16(genre) - 1); } break; +#ifdef HAVE_TAGCACHE + case MP4_soal: + read_mp4_tag_string(fd, size, &buffer, &buffer_left, + &id3->sort_album); + break; + case MP4_soar: + read_mp4_tag_string(fd, size, &buffer, &buffer_left, + &id3->sort_artist); + break; + + case MP4_sonm: + read_mp4_tag_string(fd, size, &buffer, &buffer_left, + &id3->sort_title); + break; +#endif case MP4_trkn: { unsigned short n[2]; Index: apps/tagcache.c =================================================================== --- apps/tagcache.c (revision 13624) +++ apps/tagcache.c (working copy) @@ -108,11 +108,13 @@ /* Tags we want to get sorted (loaded to the tempbuf). */ static const int sorted_tags[] = { tag_artist, tag_album, tag_genre, - tag_composer, tag_comment, tag_albumartist, tag_title }; + tag_composer, tag_comment, tag_albumartist, tag_title, tag_sortartist, + tag_sortalbum, tag_sorttitle }; /* 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, tag_comment, tag_albumartist }; + tag_composer, tag_comment, tag_albumartist, tag_sortartist, tag_sortalbum, + tag_sorttitle }; /* Numeric tags (we can use these tags with conditional clauses). */ static const int numeric_tags[] = { tag_year, tag_tracknumber, tag_length, @@ -123,8 +125,9 @@ /* 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", - "bitrate", "length", "playcount", "rating", "playtime", "lastplayed", "commitid" }; + "filename", "composer", "comment", "albumartist", "sortartist", "sortalbum", + "sorttitle", "year", "tracknumber", "bitrate", "length", "playcount", "rating", + "playtime", "lastplayed", "commitid" }; /* Status information of the tagcache. */ static struct tagcache_stat tc_stat; @@ -170,7 +173,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 = "lllllllllllllllllllll"; /* (1 + TAG_COUNT) * l */ static const char *tagcache_header_ec = "lll"; static const char *master_header_ec = "llllll"; @@ -1531,6 +1534,9 @@ id3->composer = get_tag_string(entry, tag_composer); id3->comment = get_tag_string(entry, tag_comment); id3->albumartist = get_tag_string(entry, tag_albumartist); + id3->sort_title = get_tag_string(entry, tag_sorttitle); + id3->sort_artist = get_tag_string(entry, tag_sortartist); + id3->sort_album = get_tag_string(entry, tag_sortalbum); id3->playcount = get_tag_numeric(entry, tag_playcount); id3->rating = get_tag_numeric(entry, tag_rating); @@ -1693,6 +1699,9 @@ ADD_TAG(entry, tag_composer, &track.id3.composer); ADD_TAG(entry, tag_comment, &track.id3.comment); ADD_TAG(entry, tag_albumartist, &track.id3.albumartist); + ADD_TAG(entry, tag_sorttitle, &track.id3.sort_title); + ADD_TAG(entry, tag_sortalbum, &track.id3.sort_album); + ADD_TAG(entry, tag_sortartist, &track.id3.sort_artist); entry.data_length = offset; /* Write the header */ @@ -1707,6 +1716,9 @@ write_item(track.id3.composer); write_item(track.id3.comment); write_item(track.id3.albumartist); + write_item(track.id3.sort_title); + write_item(track.id3.sort_album); + write_item(track.id3.sort_artist); total_entry_count++; } Index: apps/tagcache.h =================================================================== --- apps/tagcache.h (revision 13624) +++ apps/tagcache.h (working copy) @@ -23,15 +23,16 @@ #include "id3.h" enum tag_type { tag_artist = 0, tag_album, tag_genre, tag_title, - tag_filename, tag_composer, tag_comment, tag_albumartist, tag_year, - tag_tracknumber, tag_bitrate, tag_length, tag_playcount, tag_rating, - tag_playtime, tag_lastplayed, tag_commitid, + tag_filename, tag_composer, tag_comment, tag_albumartist, tag_sortartist, + tag_sortalbum, tag_sorttitle, tag_year, 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 }; -#define TAG_COUNT 17 +#define TAG_COUNT 20 /* 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 0x5443480A /* How much to allocate extra space for ramcache. */ #define TAGCACHE_RESERVE 32768 Index: apps/tagtree.c =================================================================== --- apps/tagtree.c (revision 13624) +++ apps/tagtree.c (working copy) @@ -201,6 +201,9 @@ MATCH(tag, buf, "albumartist", tag_albumartist); MATCH(tag, buf, "ensemble", tag_albumartist); MATCH(tag, buf, "genre", tag_genre); + MATCH(tag, buf, "sortartist", tag_sortartist); + MATCH(tag, buf, "sortalbum", tag_sortalbum); + MATCH(tag, buf, "sorttitle", tag_sorttitle); MATCH(tag, buf, "length", tag_length); MATCH(tag, buf, "Lm", tag_virt_length_min); MATCH(tag, buf, "Ls", tag_virt_length_sec); Index: firmware/export/id3.h =================================================================== --- firmware/export/id3.h (revision 13624) +++ firmware/export/id3.h (working copy) @@ -149,6 +149,11 @@ char* composer; char* comment; char* albumartist; +#ifdef HAVE_TAGCACHE + char* sort_title; + char* sort_album; + char* sort_artist; +#endif int tracknum; int version; int layer; Index: firmware/id3.c =================================================================== --- firmware/id3.c (revision 13624) +++ firmware/id3.c (working copy) @@ -213,7 +213,7 @@ display it, at a runtime cost.) 2. If any special processing beyond copying the tag value from the Id3 - block to the struct mp3entry is rrequired (such as converting to an + block to the struct mp3entry is required (such as converting to an int), write a function to perform this special processing. This function's prototype must match that of @@ -449,10 +449,20 @@ { "TYE", 3, offsetof(struct mp3entry, year_string), &parseyearnum, false }, { "TCOM", 4, offsetof(struct mp3entry, composer), NULL, false }, { "TPE2", 4, offsetof(struct mp3entry, albumartist), NULL, false }, - { "TP2", 3, offsetof(struct mp3entry, albumartist), NULL, false }, + { "TP2", 3, offsetof(struct mp3entry, albumartist), NULL, false }, { "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 }, +#ifdef HAVE_TAGCACHE + /* id3v2.4 versions */ + { "TSOA", 4, offsetof(struct mp3entry, sort_album), NULL, false }, + { "TSOP", 4, offsetof(struct mp3entry, sort_artist), NULL, false }, + { "TSOT", 4, offsetof(struct mp3entry, sort_title), NULL, false }, + /* id3v2.3 versions */ + { "XSOA", 4, offsetof(struct mp3entry, sort_album), NULL, false }, + { "XSOP", 4, offsetof(struct mp3entry, sort_artist), NULL, false }, + { "XSOT", 4, offsetof(struct mp3entry, sort_title), NULL, false }, +#endif #if CONFIG_CODEC == SWCODEC { "TXXX", 4, 0, &parseuser, false }, { "RVA2", 4, 0, &parserva2, true }, @@ -625,7 +635,6 @@ return true; } - /* * Sets the title of an MP3 entry based on its ID3v2 tag. * @@ -1178,6 +1187,14 @@ entry->comment += offset; if (entry->albumartist) entry->albumartist += offset; +#ifdef HAVE_TAGCACHE + if (entry->sort_artist) + entry->sort_artist += offset; + if (entry->sort_album) + entry->sort_album += offset; + if (entry->sort_title) + entry->sort_title += offset; +#endif #if CONFIG_CODEC == SWCODEC if (entry->track_gain_string) entry->track_gain_string += offset;