Index: apps/metadata/mp4.c =================================================================== --- apps/metadata/mp4.c (Revision 18437) +++ apps/metadata/mp4.c (Arbeitskopie) @@ -63,6 +63,10 @@ #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_soaa MP4_ID('s', 'o', 'a', 'a') +#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') @@ -453,6 +457,26 @@ } break; + case MP4_soaa: + read_mp4_tag_string(fd, size, &buffer, &buffer_left, + &id3->albumartistsort); + break; + + case MP4_soal: + read_mp4_tag_string(fd, size, &buffer, &buffer_left, + &id3->albumsort); + break; + + case MP4_soar: + read_mp4_tag_string(fd, size, &buffer, &buffer_left, + &id3->artistsort); + break; + + case MP4_sonm: + read_mp4_tag_string(fd, size, &buffer, &buffer_left, + &id3->titlesort); + break; + case MP4_extra: { char tag_name[TAG_NAME_LENGTH]; Index: apps/metadata/metadata_common.c =================================================================== --- apps/metadata/metadata_common.c (Revision 18437) +++ apps/metadata/metadata_common.c (Arbeitskopie) @@ -293,6 +293,22 @@ { p = &(id3->grouping); } + else if (strcasecmp(name, "artistsort") == 0) + { + p = &(id3->artistsort); + } + else if (strcasecmp(name, "albumartistsort") == 0) + { + p = &(id3->albumartistsort); + } + else if (strcasecmp(name, "albumsort") == 0) + { + p = &(id3->albumsort); + } + else if (strcasecmp(name, "titlesort") == 0) + { + p = &(id3->titlesort); + } else { len = parse_replaygain(name, value, id3, buf, buf_remaining); Index: apps/tagcache.c =================================================================== --- apps/tagcache.c (Revision 18437) +++ apps/tagcache.c (Arbeitskopie) @@ -91,6 +91,21 @@ #define do_timed_yield() do { } while(0) #endif +/* + * Adding tags: + * - add the tags to the tag_type enum in tagcache.h + * - add the tags to: - sorted_tags[] + * - unique_tags[] + * - numeric_tags[] + * where appropriate (see comments) + * - add the representing string to *tags_str[] + * - add an "l" for each in *index_entry_ec (line 208) + * - do the obvious other stuff, e.g. updating the + * metadata information for the various formats and get + * through the add_tag stuff starting at line ~1750 + */ + + #ifndef __PCTOOL__ /* Tag Cache thread. */ static struct event_queue tagcache_queue; @@ -112,11 +127,15 @@ /* 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_grouping, tag_title }; + tag_composer, tag_comment, tag_albumartist, tag_grouping, tag_title, + tag_titlesort, tag_albumsort, tag_artistsort, tag_albumartistsort +}; /* 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_grouping }; + tag_composer, tag_comment, tag_albumartist, tag_grouping, + tag_albumsort, tag_artistsort, tag_albumartistsort +}; /* Numeric tags (we can use these tags with conditional clauses). */ static const int numeric_tags[] = { tag_year, tag_discnumber, @@ -128,9 +147,11 @@ /* 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", "grouping", "year", - "discnumber", "tracknumber", "bitrate", "length", "playcount", "rating", - "playtime", "lastplayed", "commitid", "mtime" }; + "filename", "composer", "comment", "albumartist", "grouping", + "titlesortorder", "albumsortorder", "performersortorder", + "albumartistsortorder", "year", "discnumber", "tracknumber", + "bitrate", "length", "playcount", "rating", "playtime", + "lastplayed", "commitid", "mtime" }; /* Status information of the tagcache. */ static struct tagcache_stat tc_stat; @@ -194,7 +215,7 @@ /** Note: This should be (1 + TAG_COUNT) amount of l's. */ -static const char *index_entry_ec = "lllllllllllllllllllll"; +static const char *index_entry_ec = "lllllllllllllllllllllllll"; static const char *tagcache_header_ec = "lll"; static const char *master_header_ec = "llllll"; @@ -1596,6 +1617,11 @@ id3->albumartist = get_tag_string(entry, tag_albumartist); id3->grouping = get_tag_string(entry, tag_grouping); + id3->titlesort = get_tag_string(entry, tag_titlesort); + id3->albumsort = get_tag_string(entry, tag_albumsort); + id3->artistsort = get_tag_string(entry, tag_artistsort); + id3->albumartistsort = get_tag_string(entry, tag_albumartistsort); + id3->playcount = get_tag_numeric(entry, tag_playcount); id3->rating = get_tag_numeric(entry, tag_rating); id3->lastplayed = get_tag_numeric(entry, tag_lastplayed); @@ -1641,12 +1667,14 @@ return length + 1; } -#define ADD_TAG(entry,tag,data) \ - /* Adding tag */ \ - entry.tag_offset[tag] = offset; \ - entry.tag_length[tag] = check_if_empty(data); \ - offset += entry.tag_length[tag] - +static int add_tag(int offset, struct temp_file_entry *entry, int tag, + char **data) +{ + entry->tag_offset[tag] = offset; + entry->tag_length[tag] = check_if_empty(data); + return entry->tag_length[tag]; +} + static void add_tagcache(char *path, unsigned long mtime #if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE) ,const struct dirent *dc @@ -1663,7 +1691,8 @@ int path_length = strlen(path); bool has_albumartist; bool has_grouping; - + bool have_titlesort, have_albumsort, have_artistsort, + have_albumartistsort; if (cachefd < 0) return ; @@ -1782,34 +1811,64 @@ entry.tag_offset[tag_mtime] = mtime; /* String tags. */ - has_albumartist = id3.albumartist != NULL - && strlen(id3.albumartist) > 0; - has_grouping = id3.grouping != NULL - && strlen(id3.grouping) > 0; + has_albumartist = id3.albumartist != NULL && + strlen(id3.albumartist) > 0; + has_grouping = id3.grouping != NULL && + strlen(id3.grouping) > 0; + have_titlesort = id3.titlesort != NULL && + strlen(id3.titlesort) > 0; + have_albumsort = id3.albumsort != NULL && + strlen(id3.albumsort) > 0; + have_artistsort = id3.artistsort != NULL && + strlen(id3.artistsort) > 0; + have_albumartistsort = id3.albumartistsort != NULL && + strlen(id3.albumartistsort) > 0; - ADD_TAG(entry, tag_filename, &path); - ADD_TAG(entry, tag_title, &id3.title); - ADD_TAG(entry, tag_artist, &id3.artist); - ADD_TAG(entry, tag_album, &id3.album); - ADD_TAG(entry, tag_genre, &id3.genre_string); - ADD_TAG(entry, tag_composer, &id3.composer); - ADD_TAG(entry, tag_comment, &id3.comment); + offset += add_tag(offset, &entry, tag_filename, &path); + offset += add_tag(offset, &entry, tag_title, &id3.title); + offset += add_tag(offset, &entry, tag_artist, &id3.artist); + offset += add_tag(offset, &entry, tag_album, &id3.album); + offset += add_tag(offset, &entry, tag_genre, &id3.genre_string); + offset += add_tag(offset, &entry, tag_composer, &id3.composer); + offset += add_tag(offset, &entry, tag_comment, &id3.comment); if (has_albumartist) { - ADD_TAG(entry, tag_albumartist, &id3.albumartist); + offset += add_tag(offset, &entry, tag_albumartist, &id3.albumartist); } else { - ADD_TAG(entry, tag_albumartist, &id3.artist); + offset += add_tag(offset, &entry, tag_albumartist, &id3.artist); } if (has_grouping) { - ADD_TAG(entry, tag_grouping, &id3.grouping); + offset += add_tag(offset, &entry, tag_grouping, &id3.grouping); } else { - ADD_TAG(entry, tag_grouping, &id3.title); + offset += add_tag(offset, &entry, tag_grouping, &id3.title); } + if (have_titlesort) + offset += add_tag(offset, &entry, tag_titlesort, &id3.titlesort); + else + offset += add_tag(offset, &entry, tag_titlesort, &id3.title); + + if (have_albumsort) + offset += add_tag(offset, &entry, tag_albumsort, &id3.albumsort); + else + offset += add_tag(offset, &entry, tag_albumsort, &id3.album); + + if (have_artistsort) + offset += add_tag(offset, &entry, tag_artistsort, &id3.artistsort); + else + offset += add_tag(offset, &entry, tag_artistsort, &id3.artist); + + if (have_albumartistsort) + offset += add_tag(offset, &entry, tag_albumartistsort, + &id3.albumartistsort); + else + offset += add_tag(offset, &entry, tag_albumartistsort, + &id3.albumartist); + entry.data_length = offset; /* Write the header */ @@ -1823,22 +1882,36 @@ write_item(id3.genre_string); write_item(id3.composer); write_item(id3.comment); + if (has_albumartist) - { write_item(id3.albumartist); - } else - { write_item(id3.artist); - } + if (has_grouping) - { write_item(id3.grouping); - } else - { write_item(id3.title); - } + + if (have_titlesort) + write_item(id3.titlesort); + else + write_item(id3.title); + + if (have_albumsort) + write_item(id3.albumsort); + else + write_item(id3.album); + if (have_artistsort) + write_item(id3.artistsort); + else + write_item(id3.artist); + + if (have_albumartistsort) + write_item(id3.albumartistsort); + else + write_item(id3.albumartist); + total_entry_count++; } @@ -2406,8 +2479,8 @@ close(fd); return -2; } - - if (entry.tag_length >= (int)sizeof(buf)) + + if (entry.tag_length >= (int)sizeof(buf)) { logf("too long tag #3"); close(fd); Index: apps/tagcache.h =================================================================== --- apps/tagcache.h (Revision 18437) +++ apps/tagcache.h (Arbeitskopie) @@ -29,9 +29,11 @@ tagcache.c and bump up the header version too. */ enum tag_type { tag_artist = 0, tag_album, tag_genre, tag_title, - tag_filename, tag_composer, tag_comment, tag_albumartist, tag_grouping, tag_year, - tag_discnumber, tag_tracknumber, tag_bitrate, tag_length, tag_playcount, tag_rating, - tag_playtime, tag_lastplayed, tag_commitid, tag_mtime, + tag_filename, tag_composer, tag_comment, tag_albumartist, tag_grouping, + tag_titlesort, tag_albumsort, tag_artistsort, tag_albumartistsort, + tag_year, tag_discnumber, tag_tracknumber, tag_bitrate, tag_length, + tag_playcount, tag_rating, tag_playtime, tag_lastplayed, tag_commitid, + tag_mtime, /* Real tags end here, count them. */ TAG_COUNT, /* Virtual tags */ @@ -49,7 +51,7 @@ #define IDX_BUF_DEPTH 64 /* Tag Cache Header version 'TCHxx'. Increment when changing internal structures. */ -#define TAGCACHE_MAGIC 0x5443480c +#define TAGCACHE_MAGIC 0x5443480d /* How much to allocate extra space for ramcache. */ #define TAGCACHE_RESERVE 32768 Index: apps/tagnavi.config =================================================================== --- apps/tagnavi.config (Revision 18437) +++ apps/tagnavi.config (Arbeitskopie) @@ -6,15 +6,15 @@ # get overwritten automatically. # Basic format declarations -%format "fmt_title" "%d.%02d. %s" discnum tracknum title ? discnum > "0" -%format "fmt_title" "%02d. %s - %02d:%02d" tracknum title Lm Ls ? tracknum > "0" -%format "fmt_title" "%s - %02d:%02d" title Lm Ls -%format "fmt_mostplayed" "%2d|%3d %s (%s)" playcount autoscore title artist %sort = "inverse" %limit = "100" -%format "fmt_lastplayed" "%06d%s - %s" lastplayed artist title %sort = "inverse" %limit = "99" %strip = "6" -%format "fmt_forgotten" "%06d%s - %s" lastplayed artist title %limit = "99" %strip = "6" -%format "fmt_best_tracks" "%02d. %s (%3d)" tracknum title autoscore -%format "fmt_score" "(%3d) %s-%s" autoscore title artist -%format "fmt_rating" "(%2d) %s-%s" rating title artist %sort = "inverse" +%format "fmt_title" "%d.%02d. %s" discnum tracknum titlesort ? discnum > "0" +%format "fmt_title" "%02d. %s - %02d:%02d" tracknum titlesort Lm Ls ? tracknum > "0" +%format "fmt_title" "%s - %02d:%02d" titlesort Lm Ls +%format "fmt_mostplayed" "%2d|%3d %s (%s)" playcount autoscore titlesort artistsort %sort = "inverse" %limit = "100" +%format "fmt_lastplayed" "%06d%s - %s" lastplayed artistsort titlesort %sort = "inverse" %limit = "99" %strip = "6" +%format "fmt_forgotten" "%06d%s - %s" lastplayed artistsort titlesort %limit = "99" %strip = "6" +%format "fmt_best_tracks" "%02d. %s (%3d)" tracknum titlesort autoscore +%format "fmt_score" "(%3d) %s-%s" autoscore titlesort artist +%format "fmt_rating" "(%2d) %s-%s" rating titlesort artistsort %sort = "inverse" # Include our custom menu %include "/.rockbox/tagnavi_custom.config" @@ -25,65 +25,65 @@ # Define the A to Z Artist sub menu %menu_start "custom_artist" "Artist A to Z" -"Numeric" -> artist ? artist < "A" -> album -> title = "fmt_title" -"A" -> artist ? artist ^ "A" -> album -> title = "fmt_title" -"B" -> artist ? artist ^ "B" -> album -> title = "fmt_title" -"C" -> artist ? artist ^ "C" -> album -> title = "fmt_title" -"D" -> artist ? artist ^ "D" -> album -> title = "fmt_title" -"E" -> artist ? artist ^ "E" -> album -> title = "fmt_title" -"F" -> artist ? artist ^ "F" -> album -> title = "fmt_title" -"G" -> artist ? artist ^ "G" -> album -> title = "fmt_title" -"H" -> artist ? artist ^ "H" -> album -> title = "fmt_title" -"I" -> artist ? artist ^ "I" -> album -> title = "fmt_title" -"J" -> artist ? artist ^ "J" -> album -> title = "fmt_title" -"K" -> artist ? artist ^ "K" -> album -> title = "fmt_title" -"L" -> artist ? artist ^ "L" -> album -> title = "fmt_title" -"M" -> artist ? artist ^ "M" -> album -> title = "fmt_title" -"N" -> artist ? artist ^ "N" -> album -> title = "fmt_title" -"O" -> artist ? artist ^ "O" -> album -> title = "fmt_title" -"P" -> artist ? artist ^ "P" -> album -> title = "fmt_title" -"Q" -> artist ? artist ^ "Q" -> album -> title = "fmt_title" -"R" -> artist ? artist ^ "R" -> album -> title = "fmt_title" -"S" -> artist ? artist ^ "S" -> album -> title = "fmt_title" -"T" -> artist ? artist ^ "T" -> album -> title = "fmt_title" -"U" -> artist ? artist ^ "U" -> album -> title = "fmt_title" -"V" -> artist ? artist ^ "V" -> album -> title = "fmt_title" -"W" -> artist ? artist ^ "W" -> album -> title = "fmt_title" -"X" -> artist ? artist ^ "X" -> album -> title = "fmt_title" -"Y" -> artist ? artist ^ "Y" -> album -> title = "fmt_title" -"Z" -> artist ? artist ^ "Z" -> album -> title = "fmt_title" +"Numeric" -> artistsort ? artistsort < "A" -> albumsort -> title = "fmt_title" +"A" -> artistsort ? artistsort ^ "A" -> albumsort -> title = "fmt_title" +"B" -> artistsort ? artistsort ^ "B" -> albumsort -> title = "fmt_title" +"C" -> artistsort ? artistsort ^ "C" -> albumsort -> title = "fmt_title" +"D" -> artistsort ? artistsort ^ "D" -> albumsort -> title = "fmt_title" +"E" -> artistsort ? artistsort ^ "E" -> albumsort -> title = "fmt_title" +"F" -> artistsort ? artistsort ^ "F" -> albumsort -> title = "fmt_title" +"G" -> artistsort ? artistsort ^ "G" -> albumsort -> title = "fmt_title" +"H" -> artistsort ? artistsort ^ "H" -> albumsort -> title = "fmt_title" +"I" -> artistsort ? artistsort ^ "I" -> albumsort -> title = "fmt_title" +"J" -> artistsort ? artistsort ^ "J" -> albumsort -> title = "fmt_title" +"K" -> artistsort ? artistsort ^ "K" -> albumsort -> title = "fmt_title" +"L" -> artistsort ? artistsort ^ "L" -> albumsort -> title = "fmt_title" +"M" -> artistsort ? artistsort ^ "M" -> albumsort -> title = "fmt_title" +"N" -> artistsort ? artistsort ^ "N" -> albumsort -> title = "fmt_title" +"O" -> artistsort ? artistsort ^ "O" -> albumsort -> title = "fmt_title" +"P" -> artistsort ? artistsort ^ "P" -> albumsort -> title = "fmt_title" +"Q" -> artistsort ? artistsort ^ "Q" -> albumsort -> title = "fmt_title" +"R" -> artistsort ? artistsort ^ "R" -> albumsort -> title = "fmt_title" +"S" -> artistsort ? artistsort ^ "S" -> albumsort -> title = "fmt_title" +"T" -> artistsort ? artistsort ^ "T" -> albumsort -> title = "fmt_title" +"U" -> artistsort ? artistsort ^ "U" -> albumsort -> title = "fmt_title" +"V" -> artistsort ? artistsort ^ "V" -> albumsort -> title = "fmt_title" +"W" -> artistsort ? artistsort ^ "W" -> albumsort -> title = "fmt_title" +"X" -> artistsort ? artistsort ^ "X" -> albumsort -> title = "fmt_title" +"Y" -> artistsort ? artistsort ^ "Y" -> albumsort -> title = "fmt_title" +"Z" -> artistsort ? artistsort ^ "Z" -> albumsort -> title = "fmt_title" # ^ An empy line ends the menu # Define the A to Z album sub menu %menu_start "custom_album" "Album A to Z" -"Numeric" -> album ? album < "A" -> title = "fmt_title" -"A" -> album ? album ^ "A" -> title = "fmt_title" -"B" -> album ? album ^ "B" -> title = "fmt_title" -"C" -> album ? album ^ "C" -> title = "fmt_title" -"D" -> album ? album ^ "D" -> title = "fmt_title" -"E" -> album ? album ^ "E" -> title = "fmt_title" -"F" -> album ? album ^ "F" -> title = "fmt_title" -"G" -> album ? album ^ "G" -> title = "fmt_title" -"H" -> album ? album ^ "H" -> title = "fmt_title" -"I" -> album ? album ^ "I" -> title = "fmt_title" -"J" -> album ? album ^ "J" -> title = "fmt_title" -"K" -> album ? album ^ "K" -> title = "fmt_title" -"L" -> album ? album ^ "L" -> title = "fmt_title" -"M" -> album ? album ^ "M" -> title = "fmt_title" -"N" -> album ? album ^ "N" -> title = "fmt_title" -"O" -> album ? album ^ "O" -> title = "fmt_title" -"P" -> album ? album ^ "P" -> title = "fmt_title" -"Q" -> album ? album ^ "Q" -> title = "fmt_title" -"R" -> album ? album ^ "R" -> title = "fmt_title" -"S" -> album ? album ^ "S" -> title = "fmt_title" -"T" -> album ? album ^ "T" -> title = "fmt_title" -"U" -> album ? album ^ "U" -> title = "fmt_title" -"V" -> album ? album ^ "V" -> title = "fmt_title" -"W" -> album ? album ^ "W" -> title = "fmt_title" -"X" -> album ? album ^ "X" -> title = "fmt_title" -"Y" -> album ? album ^ "Y" -> title = "fmt_title" -"Z" -> album ? album ^ "Z" -> title = "fmt_title" +"Numeric" -> albumsort ? albumsort < "A" -> title = "fmt_title" +"A" -> albumsort ? albumsort ^ "A" -> title = "fmt_title" +"B" -> albumsort ? albumsort ^ "B" -> title = "fmt_title" +"C" -> albumsort ? albumsort ^ "C" -> title = "fmt_title" +"D" -> albumsort ? albumsort ^ "D" -> title = "fmt_title" +"E" -> albumsort ? albumsort ^ "E" -> title = "fmt_title" +"F" -> albumsort ? albumsort ^ "F" -> title = "fmt_title" +"G" -> albumsort ? albumsort ^ "G" -> title = "fmt_title" +"H" -> albumsort ? albumsort ^ "H" -> title = "fmt_title" +"I" -> albumsort ? albumsort ^ "I" -> title = "fmt_title" +"J" -> albumsort ? albumsort ^ "J" -> title = "fmt_title" +"K" -> albumsort ? albumsort ^ "K" -> title = "fmt_title" +"L" -> albumsort ? albumsort ^ "L" -> title = "fmt_title" +"M" -> albumsort ? albumsort ^ "M" -> title = "fmt_title" +"N" -> albumsort ? albumsort ^ "N" -> title = "fmt_title" +"O" -> albumsort ? albumsort ^ "O" -> title = "fmt_title" +"P" -> albumsort ? albumsort ^ "P" -> title = "fmt_title" +"Q" -> albumsort ? albumsort ^ "Q" -> title = "fmt_title" +"R" -> albumsort ? albumsort ^ "R" -> title = "fmt_title" +"S" -> albumsort ? albumsort ^ "S" -> title = "fmt_title" +"T" -> albumsort ? albumsort ^ "T" -> title = "fmt_title" +"U" -> albumsort ? albumsort ^ "U" -> title = "fmt_title" +"V" -> albumsort ? albumsort ^ "V" -> title = "fmt_title" +"W" -> albumsort ? albumsort ^ "W" -> title = "fmt_title" +"X" -> albumsort ? albumsort ^ "X" -> title = "fmt_title" +"Y" -> albumsort ? albumsort ^ "Y" -> title = "fmt_title" +"Z" -> albumsort ? albumsort ^ "Z" -> title = "fmt_title" # Define the A to Z track sub menu %menu_start "custom_track" "Track A to Z" @@ -142,20 +142,21 @@ # Define the "same as current" sub menu %menu_start "same" "Same as current" "Directory" -> title ? filename ^ "#directory#" -"Title" -> title = "fmt_title" ? title = "#title#" -"Artist" -> album ? artist = "#artist#" -> title = "fmt_title" -"Album" -> title = "fmt_title" ? album = "#album#" +"Title" -> title = "fmt_title" ? titlesort = "#title#" +"Artist" -> albumsort ? artistsort = "#artist#" -> title = "fmt_title" +"Artist Artist" -> albumsort ? albumartistsort = "#albumartist#" -> title = "fmt_title" +"Album" -> title = "fmt_title" ? albumsort = "#album#" "Composer" -> title = "fmt_title" ? composer = "#composer#" # Define the runtime sub menu %menu_start "runtime" "Play history" "Most played (Plays|Score)" -> title = "fmt_mostplayed" ? playcount > "0" "Recently played tracks" -> title = "fmt_lastplayed" ? playcount > "0" -"Never played tracks" -> artist ? playcount == "0" -> album -> title = "fmt_title" -"Favourite artists" -> artist ? playcount > "3" & autoscore > "85" -> album -> title = "fmt_best_tracks" -"Favourite albums" -> album ? playcount > "3" & autoscore > "85" -> title = "fmt_best_tracks" +"Never played tracks" -> artistsort ? playcount == "0" -> albumsort -> title = "fmt_title" +"Favourite artists" -> artistsort ? playcount > "3" & autoscore > "85" -> albumsort -> title = "fmt_best_tracks" +"Favourite albums" -> albumsort ? playcount > "3" & autoscore > "85" -> title = "fmt_best_tracks" "Recent favourites" -> title = "fmt_lastplayed" ? playcount > "3" & autoscore > "85" -"New favourites" -> artist ? playcount <= "3" & autoscore > "85" -> album -> title = "fmt_best_tracks" +"New favourites" -> artistsort ? playcount <= "3" & autoscore > "85" -> albumsort -> title = "fmt_best_tracks" "Forgotten favourites" -> title = "fmt_forgotten" ? playcount > "3" & autoscore > "85" # @@ -164,15 +165,15 @@ # Define the title of the main menu %menu_start "main" "Database" -"Artist" -> artist -> album -> title = "fmt_title" -"Album Artist" -> albumartist -> album -> title = "fmt_title" -"Album" -> album -> title = "fmt_title" -"Genre" -> genre -> artist -> album -> title = "fmt_title" -"Composer" -> composer -> album -> title = "fmt_title" +"Artist" -> artistsort -> albumsort -> title = "fmt_title" +"Album Artist" -> albumartistsort -> albumsort -> title = "fmt_title" +"Album" -> albumsort -> title = "fmt_title" +"Genre" -> genre -> artistsort -> albumsort -> title = "fmt_title" +"Composer" -> composer -> albumsort -> title = "fmt_title" "Track" -> title -"Year" -> year ? year > "0" -> artist -> album -> title = "fmt_title" +"Year" -> year ? year > "0" -> artistsort -> albumsort -> title = "fmt_title" "User Rating" -> rating -> title = "fmt_title" -"Recently Added" -> album ? entryage < "4" & commitid > "0" -> title = "fmt_title" +"Recently Added" -> albumsort ? entryage < "4" & commitid > "0" -> title = "fmt_title" "A to Z..." ==> "a2z" "History..." ==> "runtime" "Same as current..." ==> "same" Index: apps/tagtree.c =================================================================== --- apps/tagtree.c (Revision 18437) +++ apps/tagtree.c (Arbeitskopie) @@ -216,6 +216,10 @@ MATCH(tag, buf, "albumartist", tag_albumartist); MATCH(tag, buf, "ensemble", tag_albumartist); MATCH(tag, buf, "grouping", tag_grouping); + MATCH(tag, buf, "titlesort", tag_titlesort); + MATCH(tag, buf, "albumsort", tag_albumsort); + MATCH(tag, buf, "artistsort", tag_artistsort); + MATCH(tag, buf, "albumartistsort", tag_albumartistsort); MATCH(tag, buf, "genre", tag_genre); MATCH(tag, buf, "length", tag_length); MATCH(tag, buf, "Lm", tag_virt_length_min); Index: firmware/export/id3.h =================================================================== --- firmware/export/id3.h (Revision 18437) +++ firmware/export/id3.h (Arbeitskopie) @@ -158,6 +158,10 @@ char* comment; char* albumartist; char* grouping; + char* titlesort; + char* albumsort; + char* artistsort; + char* albumartistsort; int discnum; int tracknum; int version; Index: firmware/id3.c =================================================================== --- firmware/id3.c (Revision 18437) +++ firmware/id3.c (Arbeitskopie) @@ -221,7 +221,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 @@ -398,7 +398,7 @@ } #if CONFIG_CODEC == SWCODEC -/* parse user defined text, looking for replaygain information. */ +/* Parse the TXXX frame of ID3v2 for various different bits of data */ static int parseuser( struct mp3entry* entry, char* tag, int bufferpos ) { char* value = NULL; @@ -410,8 +410,15 @@ * parse it */ value = tag + desc_len + 1; - value_len = parse_replaygain(tag, value, entry, tag, - bufferpos - (tag - entry->id3v2buf)); + + if (strncmp("replaygain", tag, 10) == 0) { + /* Note: for ID3v2.4, parse_replaygain will not overwrite replaygain + values already parsed from RVA2 tags */ + value_len = parse_replaygain(tag, value, entry, tag, + bufferpos - (tag - entry->id3v2buf)); + } else if (strncmp("ALBUMARTISTSORT", tag, 15) == 0) { + entry->albumartistsort = value; + } } return tag - entry->id3v2buf + value_len; @@ -507,6 +514,14 @@ { "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 }, + /* id3v2.4 versions */ + { "TSOA", 4, offsetof(struct mp3entry, albumsort), NULL, false }, + { "TSOP", 4, offsetof(struct mp3entry, artistsort), NULL, false }, + { "TSOT", 4, offsetof(struct mp3entry, titlesort), NULL, false }, + /* these may also appear */ + { "XSOA", 4, offsetof(struct mp3entry, albumsort), NULL, false }, + { "XSOP", 4, offsetof(struct mp3entry, artistsort), NULL, false }, + { "XSOT", 4, offsetof(struct mp3entry, titlesort), NULL, false }, #if CONFIG_CODEC == SWCODEC { "TXXX", 4, 0, &parseuser, false }, { "RVA2", 4, 0, &parserva2, true }, @@ -767,7 +782,9 @@ } entry->id3version = version; entry->tracknum = entry->year = entry->discnum = 0; - entry->title = entry->artist = entry->album = NULL; /* FIXME incomplete */ + entry->title = entry->artist = entry->album = + entry->titlesort = entry->artistsort = + entry->albumsort = entry->albumartistsort = NULL; /* FIXME incomplete */ global_flags = header[5]; @@ -1255,6 +1272,14 @@ entry->albumartist += offset; if (entry->grouping) entry->grouping += offset; + if (entry->artistsort) + entry->artistsort += offset; + if (entry->albumsort) + entry->albumsort += offset; + if (entry->titlesort) + entry->titlesort += offset; + if (entry->albumartistsort) + entry->albumartistsort += offset; #if CONFIG_CODEC == SWCODEC if (entry->track_gain_string) entry->track_gain_string += offset;