summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Everton <dan@iocaine.org>2007-08-03 10:00:42 +0000
committerDan Everton <dan@iocaine.org>2007-08-03 10:00:42 +0000
commitf4a61f0c4a999790f07d061352100ac6310a38f6 (patch)
tree0cf03d0a08f5b5de7318ed5db948fd41c5196cca
parent1fbf847eedd90b6f3e40decd64e1094d7a7dc383 (diff)
downloadrockbox-f4a61f0c4a999790f07d061352100ac6310a38f6.tar.gz
rockbox-f4a61f0c4a999790f07d061352100ac6310a38f6.zip
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
-rw-r--r--apps/gui/gwps-common.c9
-rw-r--r--apps/gui/gwps.h1
-rw-r--r--apps/gui/wps_debug.c4
-rw-r--r--apps/gui/wps_parser.c2
-rw-r--r--apps/lang/english.lang14
-rw-r--r--apps/metadata/metadata_common.c5
-rw-r--r--apps/metadata/mp4.c10
-rw-r--r--apps/screens.c34
-rw-r--r--apps/tagcache.c8
-rw-r--r--apps/tagcache.h6
-rw-r--r--apps/tagnavi.config1
-rw-r--r--apps/tagtree.c1
-rw-r--r--docs/CREDITS1
-rw-r--r--firmware/export/id3.h2
-rw-r--r--firmware/id3.c13
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,
876 case WPS_TOKEN_METADATA_GENRE: 876 case WPS_TOKEN_METADATA_GENRE:
877 return id3->genre_string; 877 return id3->genre_string;
878 878
879 case WPS_TOKEN_METADATA_DISC_NUMBER:
880 if (id3->disc_string)
881 return id3->disc_string;
882 if (id3->discnum) {
883 snprintf(buf, buf_size, "%d", id3->discnum);
884 return buf;
885 }
886 return NULL;
887
879 case WPS_TOKEN_METADATA_TRACK_NUMBER: 888 case WPS_TOKEN_METADATA_TRACK_NUMBER:
880 if (id3->track_string) 889 if (id3->track_string)
881 return id3->track_string; 890 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 {
193 WPS_TOKEN_METADATA_ALBUM_ARTIST, 193 WPS_TOKEN_METADATA_ALBUM_ARTIST,
194 WPS_TOKEN_METADATA_ALBUM, 194 WPS_TOKEN_METADATA_ALBUM,
195 WPS_TOKEN_METADATA_GENRE, 195 WPS_TOKEN_METADATA_GENRE,
196 WPS_TOKEN_METADATA_DISC_NUMBER,
196 WPS_TOKEN_METADATA_TRACK_NUMBER, 197 WPS_TOKEN_METADATA_TRACK_NUMBER,
197 WPS_TOKEN_METADATA_TRACK_TITLE, 198 WPS_TOKEN_METADATA_TRACK_TITLE,
198 WPS_TOKEN_METADATA_VERSION, 199 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)
294 next_str(next)); 294 next_str(next));
295 break; 295 break;
296 296
297 case WPS_TOKEN_METADATA_DISC_NUMBER:
298 snprintf(buf, sizeof(buf), "%strack disc", next_str(next));
299 break;
300
297 case WPS_TOKEN_METADATA_TRACK_NUMBER: 301 case WPS_TOKEN_METADATA_TRACK_NUMBER:
298 snprintf(buf, sizeof(buf), "%strack number", 302 snprintf(buf, sizeof(buf), "%strack number",
299 next_str(next)); 303 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[] = {
201 { WPS_TOKEN_METADATA_ALBUM, "id", WPS_REFRESH_STATIC, NULL }, 201 { WPS_TOKEN_METADATA_ALBUM, "id", WPS_REFRESH_STATIC, NULL },
202 { WPS_TOKEN_METADATA_ALBUM_ARTIST, "iA", WPS_REFRESH_STATIC, NULL }, 202 { WPS_TOKEN_METADATA_ALBUM_ARTIST, "iA", WPS_REFRESH_STATIC, NULL },
203 { WPS_TOKEN_METADATA_GENRE, "ig", WPS_REFRESH_STATIC, NULL }, 203 { WPS_TOKEN_METADATA_GENRE, "ig", WPS_REFRESH_STATIC, NULL },
204 { WPS_TOKEN_METADATA_DISC_NUMBER, "ik", WPS_REFRESH_STATIC, NULL },
204 { WPS_TOKEN_METADATA_TRACK_NUMBER, "in", WPS_REFRESH_STATIC, NULL }, 205 { WPS_TOKEN_METADATA_TRACK_NUMBER, "in", WPS_REFRESH_STATIC, NULL },
205 { WPS_TOKEN_METADATA_TRACK_TITLE, "it", WPS_REFRESH_STATIC, NULL }, 206 { WPS_TOKEN_METADATA_TRACK_TITLE, "it", WPS_REFRESH_STATIC, NULL },
206 { WPS_TOKEN_METADATA_VERSION, "iv", WPS_REFRESH_STATIC, NULL }, 207 { WPS_TOKEN_METADATA_VERSION, "iv", WPS_REFRESH_STATIC, NULL },
@@ -213,6 +214,7 @@ static const struct wps_tag all_tags[] = {
213 { WPS_TOKEN_METADATA_ALBUM, "Id", WPS_REFRESH_DYNAMIC, NULL }, 214 { WPS_TOKEN_METADATA_ALBUM, "Id", WPS_REFRESH_DYNAMIC, NULL },
214 { WPS_TOKEN_METADATA_ALBUM_ARTIST, "IA", WPS_REFRESH_DYNAMIC, NULL }, 215 { WPS_TOKEN_METADATA_ALBUM_ARTIST, "IA", WPS_REFRESH_DYNAMIC, NULL },
215 { WPS_TOKEN_METADATA_GENRE, "Ig", WPS_REFRESH_DYNAMIC, NULL }, 216 { WPS_TOKEN_METADATA_GENRE, "Ig", WPS_REFRESH_DYNAMIC, NULL },
217 { WPS_TOKEN_METADATA_DISC_NUMBER, "Ik", WPS_REFRESH_DYNAMIC, NULL },
216 { WPS_TOKEN_METADATA_TRACK_NUMBER, "In", WPS_REFRESH_DYNAMIC, NULL }, 218 { WPS_TOKEN_METADATA_TRACK_NUMBER, "In", WPS_REFRESH_DYNAMIC, NULL },
217 { WPS_TOKEN_METADATA_TRACK_TITLE, "It", WPS_REFRESH_DYNAMIC, NULL }, 219 { WPS_TOKEN_METADATA_TRACK_TITLE, "It", WPS_REFRESH_DYNAMIC, NULL },
218 { WPS_TOKEN_METADATA_VERSION, "Iv", WPS_REFRESH_DYNAMIC, NULL }, 220 { 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 @@
11054 *: "Can't write to recording directory" 11054 *: "Can't write to recording directory"
11055 </voice> 11055 </voice>
11056</phrase> 11056</phrase>
11057<phrase>
11058 id: LANG_ID3_DISCNUM
11059 desc: in tag viewer
11060 user:
11061 <source>
11062 *: "[Discnum]"
11063 </source>
11064 <dest>
11065 *: "[Discnum]"
11066 </dest>
11067 <voice>
11068 *: ""
11069 </voice>
11070</phrase> \ 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,
224 id3->tracknum = atoi(value); 224 id3->tracknum = atoi(value);
225 p = &(id3->track_string); 225 p = &(id3->track_string);
226 } 226 }
227 else if (strcasecmp(name, "discnumber") == 0 || strcasecmp(name, "disc") == 0)
228 {
229 id3->discnum = atoi(value);
230 p = &(id3->disc_string);
231 }
227 else if (((strcasecmp(name, "year") == 0) && (type == TAGTYPE_APE)) 232 else if (((strcasecmp(name, "year") == 0) && (type == TAGTYPE_APE))
228 || ((strcasecmp(name, "date") == 0) && (type == TAGTYPE_VORBIS))) 233 || ((strcasecmp(name, "date") == 0) && (type == TAGTYPE_VORBIS)))
229 { 234 {
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 @@
43#define MP4_cwrt MP4_ID(0xa9, 'w', 'r', 't') 43#define MP4_cwrt MP4_ID(0xa9, 'w', 'r', 't')
44#define MP4_ccmt MP4_ID(0xa9, 'c', 'm', 't') 44#define MP4_ccmt MP4_ID(0xa9, 'c', 'm', 't')
45#define MP4_cday MP4_ID(0xa9, 'd', 'a', 'y') 45#define MP4_cday MP4_ID(0xa9, 'd', 'a', 'y')
46#define MP4_disk MP4_ID('d', 'i', 's', 'k')
46#define MP4_esds MP4_ID('e', 's', 'd', 's') 47#define MP4_esds MP4_ID('e', 's', 'd', 's')
47#define MP4_ftyp MP4_ID('f', 't', 'y', 'p') 48#define MP4_ftyp MP4_ID('f', 't', 'y', 'p')
48#define MP4_gnre MP4_ID('g', 'n', 'r', 'e') 49#define MP4_gnre MP4_ID('g', 'n', 'r', 'e')
@@ -422,6 +423,15 @@ static bool read_mp4_tags(int fd, struct mp3entry* id3,
422 &id3->genre_string); 423 &id3->genre_string);
423 break; 424 break;
424 425
426 case MP4_disk:
427 {
428 unsigned short n[2];
429
430 read_mp4_tag(fd, size, (char*) &n, sizeof(n));
431 id3->disknum = betoh16(n[1]);
432 }
433 break;
434
425 case MP4_trkn: 435 case MP4_trkn:
426 { 436 {
427 unsigned short n[2]; 437 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[]=
1151 LANG_ID3_ARTIST, 1151 LANG_ID3_ARTIST,
1152 LANG_ID3_ALBUM, 1152 LANG_ID3_ALBUM,
1153 LANG_ID3_ALBUMARTIST, 1153 LANG_ID3_ALBUMARTIST,
1154 LANG_ID3_DISCNUM,
1154 LANG_ID3_TRACKNUM, 1155 LANG_ID3_TRACKNUM,
1155 LANG_ID3_COMMENT, 1156 LANG_ID3_COMMENT,
1156 LANG_ID3_GENRE, 1157 LANG_ID3_GENRE,
@@ -1192,7 +1193,16 @@ static char * id3_get_info(int selected_item, void* data, char *buffer)
1192 case 3:/*LANG_ID3_ALBUMARTIST*/ 1193 case 3:/*LANG_ID3_ALBUMARTIST*/
1193 info=id3->albumartist; 1194 info=id3->albumartist;
1194 break; 1195 break;
1195 case 4:/*LANG_ID3_TRACKNUM*/ 1196 case 4:/*LANG_ID3_DISCNUM*/
1197 if (id3->disc_string)
1198 info = id3->disc_string;
1199 else if (id3->discnum)
1200 {
1201 snprintf(buffer, MAX_PATH, "%d", id3->discnum);
1202 info = buffer;
1203 }
1204 break;
1205 case 5:/*LANG_ID3_TRACKNUM*/
1196 if (id3->track_string) 1206 if (id3->track_string)
1197 info = id3->track_string; 1207 info = id3->track_string;
1198 else if (id3->tracknum) 1208 else if (id3->tracknum)
@@ -1201,13 +1211,13 @@ static char * id3_get_info(int selected_item, void* data, char *buffer)
1201 info = buffer; 1211 info = buffer;
1202 } 1212 }
1203 break; 1213 break;
1204 case 5:/*LANG_ID3_COMMENT*/ 1214 case 6:/*LANG_ID3_COMMENT*/
1205 info=id3->comment; 1215 info=id3->comment;
1206 break; 1216 break;
1207 case 6:/*LANG_ID3_GENRE*/ 1217 case 7:/*LANG_ID3_GENRE*/
1208 info = id3->genre_string; 1218 info = id3->genre_string;
1209 break; 1219 break;
1210 case 7:/*LANG_ID3_YEAR*/ 1220 case 8:/*LANG_ID3_YEAR*/
1211 if (id3->year_string) 1221 if (id3->year_string)
1212 info = id3->year_string; 1222 info = id3->year_string;
1213 else if (id3->year) 1223 else if (id3->year)
@@ -1216,34 +1226,34 @@ static char * id3_get_info(int selected_item, void* data, char *buffer)
1216 info = buffer; 1226 info = buffer;
1217 } 1227 }
1218 break; 1228 break;
1219 case 8:/*LANG_ID3_LENGTH*/ 1229 case 9:/*LANG_ID3_LENGTH*/
1220 format_time(buffer, MAX_PATH, id3->length); 1230 format_time(buffer, MAX_PATH, id3->length);
1221 info=buffer; 1231 info=buffer;
1222 break; 1232 break;
1223 case 9:/*LANG_ID3_PLAYLIST*/ 1233 case 10:/*LANG_ID3_PLAYLIST*/
1224 snprintf(buffer, MAX_PATH, "%d/%d", playlist_get_display_index(), 1234 snprintf(buffer, MAX_PATH, "%d/%d", playlist_get_display_index(),
1225 playlist_amount()); 1235 playlist_amount());
1226 info=buffer; 1236 info=buffer;
1227 break; 1237 break;
1228 case 10:/*LANG_ID3_BITRATE*/ 1238 case 11:/*LANG_ID3_BITRATE*/
1229 snprintf(buffer, MAX_PATH, "%d kbps%s", id3->bitrate, 1239 snprintf(buffer, MAX_PATH, "%d kbps%s", id3->bitrate,
1230 id3->vbr ? str(LANG_ID3_VBR) : (const unsigned char*) ""); 1240 id3->vbr ? str(LANG_ID3_VBR) : (const unsigned char*) "");
1231 info=buffer; 1241 info=buffer;
1232 break; 1242 break;
1233 case 11:/*LANG_ID3_FREQUENCY*/ 1243 case 12:/*LANG_ID3_FREQUENCY*/
1234 snprintf(buffer, MAX_PATH, "%ld Hz", id3->frequency); 1244 snprintf(buffer, MAX_PATH, "%ld Hz", id3->frequency);
1235 info=buffer; 1245 info=buffer;
1236 break; 1246 break;
1237#if CONFIG_CODEC == SWCODEC 1247#if CONFIG_CODEC == SWCODEC
1238 case 12:/*LANG_ID3_TRACK_GAIN*/ 1248 case 13:/*LANG_ID3_TRACK_GAIN*/
1239 info=id3->track_gain_string; 1249 info=id3->track_gain_string;
1240 break; 1250 break;
1241 case 13:/*LANG_ID3_ALBUM_GAIN*/ 1251 case 14:/*LANG_ID3_ALBUM_GAIN*/
1242 info=id3->album_gain_string; 1252 info=id3->album_gain_string;
1243 break; 1253 break;
1244 case 14:/*LANG_ID3_PATH*/ 1254 case 15:/*LANG_ID3_PATH*/
1245#else 1255#else
1246 case 12:/*LANG_ID3_PATH*/ 1256 case 13:/*LANG_ID3_PATH*/
1247#endif 1257#endif
1248 info=id3->path; 1258 info=id3->path;
1249 break; 1259 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,
115 tag_composer, tag_comment, tag_albumartist }; 115 tag_composer, tag_comment, tag_albumartist };
116 116
117/* Numeric tags (we can use these tags with conditional clauses). */ 117/* Numeric tags (we can use these tags with conditional clauses). */
118static const int numeric_tags[] = { tag_year, tag_tracknumber, tag_length, 118static const int numeric_tags[] = { tag_year, tag_discnumber, tag_tracknumber, tag_length,
119 tag_bitrate, tag_playcount, tag_rating, tag_playtime, tag_lastplayed, tag_commitid, 119 tag_bitrate, tag_playcount, tag_rating, tag_playtime, tag_lastplayed, tag_commitid,
120 tag_virt_length_min, tag_virt_length_sec, 120 tag_virt_length_min, tag_virt_length_sec,
121 tag_virt_playtime_min, tag_virt_playtime_sec, 121 tag_virt_playtime_min, tag_virt_playtime_sec,
@@ -123,7 +123,7 @@ static const int numeric_tags[] = { tag_year, tag_tracknumber, tag_length,
123 123
124/* String presentation of the tags defined in tagcache.h. Must be in correct order! */ 124/* String presentation of the tags defined in tagcache.h. Must be in correct order! */
125static const char *tags_str[] = { "artist", "album", "genre", "title", 125static const char *tags_str[] = { "artist", "album", "genre", "title",
126 "filename", "composer", "comment", "albumartist", "year", "tracknumber", 126 "filename", "composer", "comment", "albumartist", "year", "discnumber", "tracknumber",
127 "bitrate", "length", "playcount", "rating", "playtime", "lastplayed", "commitid" }; 127 "bitrate", "length", "playcount", "rating", "playtime", "lastplayed", "commitid" };
128 128
129/* Status information of the tagcache. */ 129/* Status information of the tagcache. */
@@ -188,7 +188,7 @@ struct master_header {
188 188
189/* For the endianess correction */ 189/* For the endianess correction */
190static const char *tagfile_entry_ec = "ss"; 190static const char *tagfile_entry_ec = "ss";
191static const char *index_entry_ec = "llllllllllllllllll"; /* (1 + TAG_COUNT) * l */ 191static const char *index_entry_ec = "lllllllllllllllllll"; /* (1 + TAG_COUNT) * l */
192static const char *tagcache_header_ec = "lll"; 192static const char *tagcache_header_ec = "lll";
193static const char *master_header_ec = "llllll"; 193static const char *master_header_ec = "llllll";
194 194
@@ -1556,6 +1556,7 @@ bool tagcache_fill_tags(struct mp3entry *id3, const char *filename)
1556 id3->score = get_tag_numeric(entry, tag_virt_autoscore) / 10; 1556 id3->score = get_tag_numeric(entry, tag_virt_autoscore) / 10;
1557 id3->year = get_tag_numeric(entry, tag_year); 1557 id3->year = get_tag_numeric(entry, tag_year);
1558 1558
1559 id3->discnum = get_tag_numeric(entry, tag_discnumber);
1559 id3->tracknum = get_tag_numeric(entry, tag_tracknumber); 1560 id3->tracknum = get_tag_numeric(entry, tag_tracknumber);
1560 id3->bitrate = get_tag_numeric(entry, tag_bitrate); 1561 id3->bitrate = get_tag_numeric(entry, tag_bitrate);
1561 if (id3->bitrate == 0) 1562 if (id3->bitrate == 0)
@@ -1699,6 +1700,7 @@ static void add_tagcache(char *path)
1699 1700
1700 /* Numeric tags */ 1701 /* Numeric tags */
1701 entry.tag_offset[tag_year] = track.id3.year; 1702 entry.tag_offset[tag_year] = track.id3.year;
1703 entry.tag_offset[tag_discnumber] = track.id3.discnum;
1702 entry.tag_offset[tag_tracknumber] = track.id3.tracknum; 1704 entry.tag_offset[tag_tracknumber] = track.id3.tracknum;
1703 entry.tag_offset[tag_length] = track.id3.length; 1705 entry.tag_offset[tag_length] = track.id3.length;
1704 entry.tag_offset[tag_bitrate] = track.id3.bitrate; 1706 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 @@
24 24
25enum tag_type { tag_artist = 0, tag_album, tag_genre, tag_title, 25enum tag_type { tag_artist = 0, tag_album, tag_genre, tag_title,
26 tag_filename, tag_composer, tag_comment, tag_albumartist, tag_year, 26 tag_filename, tag_composer, tag_comment, tag_albumartist, tag_year,
27 tag_tracknumber, tag_bitrate, tag_length, tag_playcount, tag_rating, 27 tag_discnumber, tag_tracknumber, tag_bitrate, tag_length, tag_playcount, tag_rating,
28 tag_playtime, tag_lastplayed, tag_commitid, 28 tag_playtime, tag_lastplayed, tag_commitid,
29 /* Virtual tags */ 29 /* Virtual tags */
30 tag_virt_length_min, tag_virt_length_sec, 30 tag_virt_length_min, tag_virt_length_sec,
31 tag_virt_playtime_min, tag_virt_playtime_sec, 31 tag_virt_playtime_min, tag_virt_playtime_sec,
32 tag_virt_entryage, tag_virt_autoscore }; 32 tag_virt_entryage, tag_virt_autoscore };
33 33
34#define TAG_COUNT 17 34#define TAG_COUNT 18
35 35
36/* Maximum length of a single tag. */ 36/* Maximum length of a single tag. */
37#define TAG_MAXLEN (MAX_PATH*2) 37#define TAG_MAXLEN (MAX_PATH*2)
@@ -43,7 +43,7 @@ enum tag_type { tag_artist = 0, tag_album, tag_genre, tag_title,
43#define IDX_BUF_DEPTH 64 43#define IDX_BUF_DEPTH 64
44 44
45/* Tag Cache Header version 'TCHxx'. Increment when changing internal structures. */ 45/* Tag Cache Header version 'TCHxx'. Increment when changing internal structures. */
46#define TAGCACHE_MAGIC 0x54434809 46#define TAGCACHE_MAGIC 0x5443480A
47 47
48/* How much to allocate extra space for ramcache. */ 48/* How much to allocate extra space for ramcache. */
49#define TAGCACHE_RESERVE 32768 49#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 @@
6# get overwritten automatically. 6# get overwritten automatically.
7 7
8# Basic format declarations 8# Basic format declarations
9%format "fmt_title" "%d.%02d. %s" discnum tracknum title ? discnum > "0"
9%format "fmt_title" "%02d. %s - %02d:%02d" tracknum title Lm Ls ? tracknum > "0" 10%format "fmt_title" "%02d. %s - %02d:%02d" tracknum title Lm Ls ? tracknum > "0"
10%format "fmt_title" "%s - %02d:%02d" title Lm Ls 11%format "fmt_title" "%s - %02d:%02d" title Lm Ls
11%format "fmt_mostplayed" "%2d|%3d %s (%s)" playcount autoscore title artist %sort = "inverse" %limit = "100" 12%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)
209 MATCH(tag, buf, "title", tag_title); 209 MATCH(tag, buf, "title", tag_title);
210 MATCH(tag, buf, "filename", tag_filename); 210 MATCH(tag, buf, "filename", tag_filename);
211 MATCH(tag, buf, "tracknum", tag_tracknumber); 211 MATCH(tag, buf, "tracknum", tag_tracknumber);
212 MATCH(tag, buf, "discnum", tag_discnumber);
212 MATCH(tag, buf, "year", tag_year); 213 MATCH(tag, buf, "year", tag_year);
213 MATCH(tag, buf, "playcount", tag_playcount); 214 MATCH(tag, buf, "playcount", tag_playcount);
214 MATCH(tag, buf, "rating", tag_rating); 215 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
309Rene Allkivi 309Rene Allkivi
310Tobias Schladt 310Tobias Schladt
311John Zhou 311John Zhou
312Charles Voelger
312The libmad team 313The libmad team
313The wavpack team 314The wavpack team
314The ffmpeg team 315The 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 {
147 char* artist; 147 char* artist;
148 char* album; 148 char* album;
149 char* genre_string; 149 char* genre_string;
150 char* disc_string;
150 char* track_string; 151 char* track_string;
151 char* year_string; 152 char* year_string;
152 char* composer; 153 char* composer;
153 char* comment; 154 char* comment;
154 char* albumartist; 155 char* albumartist;
156 int discnum;
155 int tracknum; 157 int tracknum;
156 int version; 158 int version;
157 int layer; 159 int layer;
diff --git a/firmware/id3.c b/firmware/id3.c
index 8e1d96462b..a66318b2fc 100644
--- a/firmware/id3.c
+++ b/firmware/id3.c
@@ -352,6 +352,13 @@ static int parsetracknum( struct mp3entry* entry, char* tag, int bufferpos )
352} 352}
353 353
354/* parse numeric value from string */ 354/* parse numeric value from string */
355static int parsediscnum( struct mp3entry* entry, char* tag, int bufferpos )
356{
357 entry->discnum = atoi( tag );
358 return bufferpos;
359}
360
361/* parse numeric value from string */
355static int parseyearnum( struct mp3entry* entry, char* tag, int bufferpos ) 362static int parseyearnum( struct mp3entry* entry, char* tag, int bufferpos )
356{ 363{
357 entry->year = atoi( tag ); 364 entry->year = atoi( tag );
@@ -446,6 +453,7 @@ static const struct tag_resolver taglist[] = {
446 { "TALB", 4, offsetof(struct mp3entry, album), NULL, false }, 453 { "TALB", 4, offsetof(struct mp3entry, album), NULL, false },
447 { "TAL", 3, offsetof(struct mp3entry, album), NULL, false }, 454 { "TAL", 3, offsetof(struct mp3entry, album), NULL, false },
448 { "TRK", 3, offsetof(struct mp3entry, track_string), &parsetracknum, false }, 455 { "TRK", 3, offsetof(struct mp3entry, track_string), &parsetracknum, false },
456 { "TPOS", 4, offsetof(struct mp3entry, disc_string), &parsediscnum, false },
449 { "TRCK", 4, offsetof(struct mp3entry, track_string), &parsetracknum, false }, 457 { "TRCK", 4, offsetof(struct mp3entry, track_string), &parsetracknum, false },
450 { "TDRC", 4, offsetof(struct mp3entry, year_string), &parseyearnum, false }, 458 { "TDRC", 4, offsetof(struct mp3entry, year_string), &parseyearnum, false },
451 { "TYER", 4, offsetof(struct mp3entry, year_string), &parseyearnum, false }, 459 { "TYER", 4, offsetof(struct mp3entry, year_string), &parseyearnum, false },
@@ -693,7 +701,7 @@ static void setid3v2title(int fd, struct mp3entry *entry)
693 return; 701 return;
694 } 702 }
695 entry->id3version = version; 703 entry->id3version = version;
696 entry->tracknum = entry->year = 0; 704 entry->tracknum = entry->year = entry->discnum = 0;
697 entry->title = entry->artist = entry->album = NULL; /* FIXME incomplete */ 705 entry->title = entry->artist = entry->album = NULL; /* FIXME incomplete */
698 706
699 global_flags = header[5]; 707 global_flags = header[5];
@@ -1112,6 +1120,7 @@ bool get_mp3_metadata(int fd, struct mp3entry *entry, const char *filename, bool
1112 entry->filesize = filesize(fd); 1120 entry->filesize = filesize(fd);
1113 entry->id3v2len = getid3v2len(fd); 1121 entry->id3v2len = getid3v2len(fd);
1114 entry->tracknum = 0; 1122 entry->tracknum = 0;
1123 entry->discnum = 0;
1115 1124
1116 if(v1first) 1125 if(v1first)
1117 v1found = setid3v1title(fd, entry); 1126 v1found = setid3v1title(fd, entry);
@@ -1173,6 +1182,8 @@ void adjust_mp3entry(struct mp3entry *entry, void *dest, void *orig)
1173 entry->genre_string += offset; 1182 entry->genre_string += offset;
1174 if (entry->track_string) 1183 if (entry->track_string)
1175 entry->track_string += offset; 1184 entry->track_string += offset;
1185 if (entry->disc_string)
1186 entry->disc_string += offset;
1176 if (entry->year_string) 1187 if (entry->year_string)
1177 entry->year_string += offset; 1188 entry->year_string += offset;
1178 if (entry->composer) 1189 if (entry->composer)