From f4a61f0c4a999790f07d061352100ac6310a38f6 Mon Sep 17 00:00:00 2001 From: Dan Everton Date: Fri, 3 Aug 2007 10:00:42 +0000 Subject: [PATCH] Add support for parsing the disc number tag from metadata and use of it in the database. Patch originally from FS#4961 with some minor tweaks by me. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@14154 a1c6a512-1295-4272-9138-f99709370657 --- apps/gui/gwps-common.c | 9 +++++++++ apps/gui/gwps.h | 1 + apps/gui/wps_debug.c | 4 ++++ apps/gui/wps_parser.c | 2 ++ apps/lang/english.lang | 14 ++++++++++++++ apps/metadata/metadata_common.c | 5 +++++ apps/metadata/mp4.c | 10 ++++++++++ apps/screens.c | 34 +++++++++++++++++++++------------ apps/tagcache.c | 8 +++++--- apps/tagcache.h | 6 +++--- apps/tagnavi.config | 1 + apps/tagtree.c | 1 + docs/CREDITS | 1 + firmware/export/id3.h | 2 ++ firmware/id3.c | 13 ++++++++++++- 15 files changed, 92 insertions(+), 19 deletions(-) diff --git a/apps/gui/gwps-common.c b/apps/gui/gwps-common.c index 2c5238b972..9dddff3ea2 100644 --- a/apps/gui/gwps-common.c +++ b/apps/gui/gwps-common.c @@ -876,6 +876,15 @@ static char *get_token_value(struct gui_wps *gwps, case WPS_TOKEN_METADATA_GENRE: return id3->genre_string; + case WPS_TOKEN_METADATA_DISC_NUMBER: + if (id3->disc_string) + return id3->disc_string; + if (id3->discnum) { + snprintf(buf, buf_size, "%d", id3->discnum); + return buf; + } + return NULL; + case WPS_TOKEN_METADATA_TRACK_NUMBER: if (id3->track_string) return id3->track_string; diff --git a/apps/gui/gwps.h b/apps/gui/gwps.h index 371b2b0399..b02b87f2c9 100644 --- a/apps/gui/gwps.h +++ b/apps/gui/gwps.h @@ -193,6 +193,7 @@ enum wps_token_type { WPS_TOKEN_METADATA_ALBUM_ARTIST, WPS_TOKEN_METADATA_ALBUM, WPS_TOKEN_METADATA_GENRE, + WPS_TOKEN_METADATA_DISC_NUMBER, WPS_TOKEN_METADATA_TRACK_NUMBER, WPS_TOKEN_METADATA_TRACK_TITLE, WPS_TOKEN_METADATA_VERSION, diff --git a/apps/gui/wps_debug.c b/apps/gui/wps_debug.c index 0f40a57801..50ffcce119 100644 --- a/apps/gui/wps_debug.c +++ b/apps/gui/wps_debug.c @@ -294,6 +294,10 @@ static void dump_wps_tokens(struct wps_data *data) next_str(next)); break; + case WPS_TOKEN_METADATA_DISC_NUMBER: + snprintf(buf, sizeof(buf), "%strack disc", next_str(next)); + break; + case WPS_TOKEN_METADATA_TRACK_NUMBER: snprintf(buf, sizeof(buf), "%strack number", next_str(next)); diff --git a/apps/gui/wps_parser.c b/apps/gui/wps_parser.c index 86b74129f2..d66e47dfe7 100644 --- a/apps/gui/wps_parser.c +++ b/apps/gui/wps_parser.c @@ -201,6 +201,7 @@ static const struct wps_tag all_tags[] = { { WPS_TOKEN_METADATA_ALBUM, "id", WPS_REFRESH_STATIC, NULL }, { WPS_TOKEN_METADATA_ALBUM_ARTIST, "iA", WPS_REFRESH_STATIC, NULL }, { WPS_TOKEN_METADATA_GENRE, "ig", WPS_REFRESH_STATIC, NULL }, + { WPS_TOKEN_METADATA_DISC_NUMBER, "ik", WPS_REFRESH_STATIC, NULL }, { WPS_TOKEN_METADATA_TRACK_NUMBER, "in", WPS_REFRESH_STATIC, NULL }, { WPS_TOKEN_METADATA_TRACK_TITLE, "it", WPS_REFRESH_STATIC, NULL }, { WPS_TOKEN_METADATA_VERSION, "iv", WPS_REFRESH_STATIC, NULL }, @@ -213,6 +214,7 @@ static const struct wps_tag all_tags[] = { { WPS_TOKEN_METADATA_ALBUM, "Id", WPS_REFRESH_DYNAMIC, NULL }, { WPS_TOKEN_METADATA_ALBUM_ARTIST, "IA", WPS_REFRESH_DYNAMIC, NULL }, { WPS_TOKEN_METADATA_GENRE, "Ig", WPS_REFRESH_DYNAMIC, NULL }, + { WPS_TOKEN_METADATA_DISC_NUMBER, "Ik", WPS_REFRESH_DYNAMIC, NULL }, { WPS_TOKEN_METADATA_TRACK_NUMBER, "In", WPS_REFRESH_DYNAMIC, NULL }, { WPS_TOKEN_METADATA_TRACK_TITLE, "It", WPS_REFRESH_DYNAMIC, NULL }, { WPS_TOKEN_METADATA_VERSION, "Iv", WPS_REFRESH_DYNAMIC, NULL }, diff --git a/apps/lang/english.lang b/apps/lang/english.lang index 2dcb7bc4ef..dcace6db8c 100644 --- a/apps/lang/english.lang +++ b/apps/lang/english.lang @@ -11054,3 +11054,17 @@ *: "Can't write to recording directory" + + id: LANG_ID3_DISCNUM + desc: in tag viewer + user: + + *: "[Discnum]" + + + *: "[Discnum]" + + + *: "" + + \ No newline at end of file diff --git a/apps/metadata/metadata_common.c b/apps/metadata/metadata_common.c index d81d9f71d3..d1a1087188 100644 --- a/apps/metadata/metadata_common.c +++ b/apps/metadata/metadata_common.c @@ -224,6 +224,11 @@ long parse_tag(const char* name, char* value, struct mp3entry* id3, id3->tracknum = atoi(value); p = &(id3->track_string); } + else if (strcasecmp(name, "discnumber") == 0 || strcasecmp(name, "disc") == 0) + { + id3->discnum = atoi(value); + p = &(id3->disc_string); + } else if (((strcasecmp(name, "year") == 0) && (type == TAGTYPE_APE)) || ((strcasecmp(name, "date") == 0) && (type == TAGTYPE_VORBIS))) { diff --git a/apps/metadata/mp4.c b/apps/metadata/mp4.c index 591d020373..3293007870 100644 --- a/apps/metadata/mp4.c +++ b/apps/metadata/mp4.c @@ -43,6 +43,7 @@ #define MP4_cwrt MP4_ID(0xa9, 'w', 'r', 't') #define MP4_ccmt MP4_ID(0xa9, 'c', 'm', 't') #define MP4_cday MP4_ID(0xa9, 'd', 'a', 'y') +#define MP4_disk MP4_ID('d', 'i', 's', 'k') #define MP4_esds MP4_ID('e', 's', 'd', 's') #define MP4_ftyp MP4_ID('f', 't', 'y', 'p') #define MP4_gnre MP4_ID('g', 'n', 'r', 'e') @@ -422,6 +423,15 @@ static bool read_mp4_tags(int fd, struct mp3entry* id3, &id3->genre_string); break; + case MP4_disk: + { + unsigned short n[2]; + + read_mp4_tag(fd, size, (char*) &n, sizeof(n)); + id3->disknum = betoh16(n[1]); + } + break; + case MP4_trkn: { unsigned short n[2]; diff --git a/apps/screens.c b/apps/screens.c index d88eb1167b..b2436f00f1 100644 --- a/apps/screens.c +++ b/apps/screens.c @@ -1151,6 +1151,7 @@ static const int id3_headers[]= LANG_ID3_ARTIST, LANG_ID3_ALBUM, LANG_ID3_ALBUMARTIST, + LANG_ID3_DISCNUM, LANG_ID3_TRACKNUM, LANG_ID3_COMMENT, LANG_ID3_GENRE, @@ -1192,7 +1193,16 @@ static char * id3_get_info(int selected_item, void* data, char *buffer) case 3:/*LANG_ID3_ALBUMARTIST*/ info=id3->albumartist; break; - case 4:/*LANG_ID3_TRACKNUM*/ + case 4:/*LANG_ID3_DISCNUM*/ + if (id3->disc_string) + info = id3->disc_string; + else if (id3->discnum) + { + snprintf(buffer, MAX_PATH, "%d", id3->discnum); + info = buffer; + } + break; + case 5:/*LANG_ID3_TRACKNUM*/ if (id3->track_string) info = id3->track_string; else if (id3->tracknum) @@ -1201,13 +1211,13 @@ static char * id3_get_info(int selected_item, void* data, char *buffer) info = buffer; } break; - case 5:/*LANG_ID3_COMMENT*/ + case 6:/*LANG_ID3_COMMENT*/ info=id3->comment; break; - case 6:/*LANG_ID3_GENRE*/ + case 7:/*LANG_ID3_GENRE*/ info = id3->genre_string; break; - case 7:/*LANG_ID3_YEAR*/ + case 8:/*LANG_ID3_YEAR*/ if (id3->year_string) info = id3->year_string; else if (id3->year) @@ -1216,34 +1226,34 @@ static char * id3_get_info(int selected_item, void* data, char *buffer) info = buffer; } break; - case 8:/*LANG_ID3_LENGTH*/ + case 9:/*LANG_ID3_LENGTH*/ format_time(buffer, MAX_PATH, id3->length); info=buffer; break; - case 9:/*LANG_ID3_PLAYLIST*/ + case 10:/*LANG_ID3_PLAYLIST*/ snprintf(buffer, MAX_PATH, "%d/%d", playlist_get_display_index(), playlist_amount()); info=buffer; break; - case 10:/*LANG_ID3_BITRATE*/ + case 11:/*LANG_ID3_BITRATE*/ snprintf(buffer, MAX_PATH, "%d kbps%s", id3->bitrate, id3->vbr ? str(LANG_ID3_VBR) : (const unsigned char*) ""); info=buffer; break; - case 11:/*LANG_ID3_FREQUENCY*/ + case 12:/*LANG_ID3_FREQUENCY*/ snprintf(buffer, MAX_PATH, "%ld Hz", id3->frequency); info=buffer; break; #if CONFIG_CODEC == SWCODEC - case 12:/*LANG_ID3_TRACK_GAIN*/ + case 13:/*LANG_ID3_TRACK_GAIN*/ info=id3->track_gain_string; break; - case 13:/*LANG_ID3_ALBUM_GAIN*/ + case 14:/*LANG_ID3_ALBUM_GAIN*/ info=id3->album_gain_string; break; - case 14:/*LANG_ID3_PATH*/ + case 15:/*LANG_ID3_PATH*/ #else - case 12:/*LANG_ID3_PATH*/ + case 13:/*LANG_ID3_PATH*/ #endif info=id3->path; break; diff --git a/apps/tagcache.c b/apps/tagcache.c index 6d738bc5fb..da51e0c4e9 100644 --- a/apps/tagcache.c +++ b/apps/tagcache.c @@ -115,7 +115,7 @@ static const int unique_tags[] = { tag_artist, tag_album, tag_genre, 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_discnumber, 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, @@ -123,7 +123,7 @@ static const int numeric_tags[] = { tag_year, tag_tracknumber, tag_length, /* 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", "discnumber", "tracknumber", "bitrate", "length", "playcount", "rating", "playtime", "lastplayed", "commitid" }; /* Status information of the tagcache. */ @@ -188,7 +188,7 @@ struct master_header { /* 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 = "lllllllllllllllllll"; /* (1 + TAG_COUNT) * l */ static const char *tagcache_header_ec = "lll"; static const char *master_header_ec = "llllll"; @@ -1556,6 +1556,7 @@ bool tagcache_fill_tags(struct mp3entry *id3, const char *filename) id3->score = get_tag_numeric(entry, tag_virt_autoscore) / 10; id3->year = get_tag_numeric(entry, tag_year); + id3->discnum = get_tag_numeric(entry, tag_discnumber); id3->tracknum = get_tag_numeric(entry, tag_tracknumber); id3->bitrate = get_tag_numeric(entry, tag_bitrate); if (id3->bitrate == 0) @@ -1699,6 +1700,7 @@ static void add_tagcache(char *path) /* Numeric tags */ entry.tag_offset[tag_year] = track.id3.year; + entry.tag_offset[tag_discnumber] = track.id3.discnum; entry.tag_offset[tag_tracknumber] = track.id3.tracknum; entry.tag_offset[tag_length] = track.id3.length; entry.tag_offset[tag_bitrate] = track.id3.bitrate; diff --git a/apps/tagcache.h b/apps/tagcache.h index 3d80c6975f..ada624783a 100644 --- a/apps/tagcache.h +++ b/apps/tagcache.h @@ -24,14 +24,14 @@ 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_discnumber, 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 18 /* Maximum length of a single tag. */ #define TAG_MAXLEN (MAX_PATH*2) @@ -43,7 +43,7 @@ enum tag_type { tag_artist = 0, tag_album, tag_genre, tag_title, #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 diff --git a/apps/tagnavi.config b/apps/tagnavi.config index 2c5675f5b7..2a98a7f93b 100644 --- a/apps/tagnavi.config +++ b/apps/tagnavi.config @@ -6,6 +6,7 @@ # 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" diff --git a/apps/tagtree.c b/apps/tagtree.c index 271f30ffa8..06150c1f26 100644 --- a/apps/tagtree.c +++ b/apps/tagtree.c @@ -209,6 +209,7 @@ static int get_tag(int *tag) MATCH(tag, buf, "title", tag_title); MATCH(tag, buf, "filename", tag_filename); MATCH(tag, buf, "tracknum", tag_tracknumber); + MATCH(tag, buf, "discnum", tag_discnumber); MATCH(tag, buf, "year", tag_year); MATCH(tag, buf, "playcount", tag_playcount); MATCH(tag, buf, "rating", tag_rating); diff --git a/docs/CREDITS b/docs/CREDITS index ff9658e322..e84521ba8f 100644 --- a/docs/CREDITS +++ b/docs/CREDITS @@ -309,6 +309,7 @@ Johnathon Mihalop Rene Allkivi Tobias Schladt John Zhou +Charles Voelger The libmad team The wavpack team The ffmpeg team diff --git a/firmware/export/id3.h b/firmware/export/id3.h index 3b69d50075..8c91456040 100644 --- a/firmware/export/id3.h +++ b/firmware/export/id3.h @@ -147,11 +147,13 @@ struct mp3entry { char* artist; char* album; char* genre_string; + char* disc_string; char* track_string; char* year_string; char* composer; char* comment; char* albumartist; + int discnum; int tracknum; int version; int layer; diff --git a/firmware/id3.c b/firmware/id3.c index 8e1d96462b..a66318b2fc 100644 --- a/firmware/id3.c +++ b/firmware/id3.c @@ -351,6 +351,13 @@ static int parsetracknum( struct mp3entry* entry, char* tag, int bufferpos ) return bufferpos; } +/* parse numeric value from string */ +static int parsediscnum( struct mp3entry* entry, char* tag, int bufferpos ) +{ + entry->discnum = atoi( tag ); + return bufferpos; +} + /* parse numeric value from string */ static int parseyearnum( struct mp3entry* entry, char* tag, int bufferpos ) { @@ -446,6 +453,7 @@ static const struct tag_resolver taglist[] = { { "TALB", 4, offsetof(struct mp3entry, album), NULL, false }, { "TAL", 3, offsetof(struct mp3entry, album), NULL, false }, { "TRK", 3, offsetof(struct mp3entry, track_string), &parsetracknum, false }, + { "TPOS", 4, offsetof(struct mp3entry, disc_string), &parsediscnum, false }, { "TRCK", 4, offsetof(struct mp3entry, track_string), &parsetracknum, false }, { "TDRC", 4, offsetof(struct mp3entry, year_string), &parseyearnum, false }, { "TYER", 4, offsetof(struct mp3entry, year_string), &parseyearnum, false }, @@ -693,7 +701,7 @@ static void setid3v2title(int fd, struct mp3entry *entry) return; } entry->id3version = version; - entry->tracknum = entry->year = 0; + entry->tracknum = entry->year = entry->discnum = 0; entry->title = entry->artist = entry->album = NULL; /* FIXME incomplete */ global_flags = header[5]; @@ -1112,6 +1120,7 @@ bool get_mp3_metadata(int fd, struct mp3entry *entry, const char *filename, bool entry->filesize = filesize(fd); entry->id3v2len = getid3v2len(fd); entry->tracknum = 0; + entry->discnum = 0; if(v1first) v1found = setid3v1title(fd, entry); @@ -1173,6 +1182,8 @@ void adjust_mp3entry(struct mp3entry *entry, void *dest, void *orig) entry->genre_string += offset; if (entry->track_string) entry->track_string += offset; + if (entry->disc_string) + entry->disc_string += offset; if (entry->year_string) entry->year_string += offset; if (entry->composer)