diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2011-04-28 02:56:28 +0000 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2011-04-28 02:56:28 +0000 |
commit | ac724cca19b8e0564c921db7a2e1a1fc52ccbe18 (patch) | |
tree | 5a65db56eb1c921afd49188d938c7218baf04b08 /apps | |
parent | fa65362a42675d9d84a7ec57fdf5d8e1b575a4cd (diff) | |
download | rockbox-ac724cca19b8e0564c921db7a2e1a1fc52ccbe18.tar.gz rockbox-ac724cca19b8e0564c921db7a2e1a1fc52ccbe18.zip |
Get the NSF internal playlists working again. Fix a few wrongdoings in the metadata parser. Use the larger of track or playlist count to determine 'duration' so that the repeat-one switching to access the raw tracks works.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29793 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps')
-rw-r--r-- | apps/codecs/nsf.c | 29 | ||||
-rw-r--r-- | apps/metadata/nsf.c | 109 |
2 files changed, 85 insertions, 53 deletions
diff --git a/apps/codecs/nsf.c b/apps/codecs/nsf.c index b1bfb82dcd..92d0240200 100644 --- a/apps/codecs/nsf.c +++ b/apps/codecs/nsf.c | |||
@@ -4294,12 +4294,18 @@ jammed: | |||
4294 | 4294 | ||
4295 | /****************** rockbox interface ******************/ | 4295 | /****************** rockbox interface ******************/ |
4296 | 4296 | ||
4297 | /** Operational info **/ | ||
4298 | static int track = 0; | ||
4299 | static char last_path[MAX_PATH]; | ||
4300 | static int dontresettrack = 0; | ||
4301 | static bool repeat_one = false; | ||
4302 | |||
4297 | static void set_codec_track(int t, int d) { | 4303 | static void set_codec_track(int t, int d) { |
4298 | int track,fade,def=0; | 4304 | int track,fade,def=0; |
4299 | SetTrack(t); | 4305 | SetTrack(t); |
4300 | 4306 | ||
4301 | /* for REPEAT_ONE we disable track limits */ | 4307 | /* for REPEAT_ONE we disable track limits */ |
4302 | if (ci->global_settings->repeat_mode!=REPEAT_ONE) { | 4308 | if (!repeat_one) { |
4303 | if (!bIsExtended || nTrackTime[t]==-1) {track=60*2*1000; def=1;} | 4309 | if (!bIsExtended || nTrackTime[t]==-1) {track=60*2*1000; def=1;} |
4304 | else track=nTrackTime[t]; | 4310 | else track=nTrackTime[t]; |
4305 | if (!bIsExtended || nTrackFade[t]==-1) fade=5*1000; | 4311 | if (!bIsExtended || nTrackFade[t]==-1) fade=5*1000; |
@@ -4310,11 +4316,6 @@ static void set_codec_track(int t, int d) { | |||
4310 | ci->set_elapsed(d*1000); /* d is track no to display */ | 4316 | ci->set_elapsed(d*1000); /* d is track no to display */ |
4311 | } | 4317 | } |
4312 | 4318 | ||
4313 | /** Operational info **/ | ||
4314 | static int track = 0; | ||
4315 | static char last_path[MAX_PATH]; | ||
4316 | static int dontresettrack = 0; | ||
4317 | |||
4318 | /* this is the codec entry point */ | 4319 | /* this is the codec entry point */ |
4319 | enum codec_status codec_main(enum codec_entry_call_reason reason) | 4320 | enum codec_status codec_main(enum codec_entry_call_reason reason) |
4320 | { | 4321 | { |
@@ -4356,6 +4357,8 @@ enum codec_status codec_run(void) | |||
4356 | DEBUGF("NSF: file load failed\n"); | 4357 | DEBUGF("NSF: file load failed\n"); |
4357 | return CODEC_ERROR; | 4358 | return CODEC_ERROR; |
4358 | } | 4359 | } |
4360 | |||
4361 | repeat_one = ci->global_settings->repeat_mode == REPEAT_ONE; | ||
4359 | 4362 | ||
4360 | init_nsf: | 4363 | init_nsf: |
4361 | if(!NSFCore_Initialize()) { | 4364 | if(!NSFCore_Initialize()) { |
@@ -4368,21 +4371,11 @@ init_nsf: | |||
4368 | if(!LoadNSF(nDataBufferSize)) { | 4371 | if(!LoadNSF(nDataBufferSize)) { |
4369 | DEBUGF("NSF: LoadNSF failed\n"); return CODEC_ERROR;} | 4372 | DEBUGF("NSF: LoadNSF failed\n"); return CODEC_ERROR;} |
4370 | 4373 | ||
4371 | ci->id3->title=szGameTitle; | ||
4372 | ci->id3->artist=szArtist; | ||
4373 | ci->id3->album=szCopyright; | ||
4374 | if (usingplaylist) { | ||
4375 | ci->id3->length=nPlaylistSize*1000; | ||
4376 | } else { | ||
4377 | ci->id3->length=nTrackCount*1000; | ||
4378 | } | ||
4379 | |||
4380 | if (!dontresettrack||strcmp(ci->id3->path,last_path)) { | 4374 | if (!dontresettrack||strcmp(ci->id3->path,last_path)) { |
4381 | /* if this is the first time we're seeing this file, or if we haven't | 4375 | /* if this is the first time we're seeing this file, or if we haven't |
4382 | been asked to preserve the track number, default to the proper | 4376 | been asked to preserve the track number, default to the proper |
4383 | initial track */ | 4377 | initial track */ |
4384 | if (bIsExtended && | 4378 | if (bIsExtended && !repeat_one && nPlaylistSize>0) { |
4385 | ci->global_settings->repeat_mode!=REPEAT_ONE && nPlaylistSize>0) { | ||
4386 | /* decide to use the playlist */ | 4379 | /* decide to use the playlist */ |
4387 | usingplaylist=1; | 4380 | usingplaylist=1; |
4388 | track=0; | 4381 | track=0; |
@@ -4447,7 +4440,7 @@ init_nsf: | |||
4447 | 4440 | ||
4448 | print_timers(last_path,track); | 4441 | print_timers(last_path,track); |
4449 | 4442 | ||
4450 | if (ci->global_settings->repeat_mode==REPEAT_ONE) { | 4443 | if (repeat_one) { |
4451 | /* in repeat one mode just advance to the next track */ | 4444 | /* in repeat one mode just advance to the next track */ |
4452 | track++; | 4445 | track++; |
4453 | if (track>=nTrackCount) track=0; | 4446 | if (track>=nTrackCount) track=0; |
diff --git a/apps/metadata/nsf.c b/apps/metadata/nsf.c index daffeb27ed..29fd8475bb 100644 --- a/apps/metadata/nsf.c +++ b/apps/metadata/nsf.c | |||
@@ -45,12 +45,21 @@ struct NSFE_INFOCHUNK | |||
45 | 45 | ||
46 | 46 | ||
47 | #define CHAR4_CONST(a, b, c, d) FOURCC(a, b, c, d) | 47 | #define CHAR4_CONST(a, b, c, d) FOURCC(a, b, c, d) |
48 | #define CHUNK_INFO 0x0001 | ||
49 | #define CHUNK_DATA 0x0002 | ||
50 | #define CHUNK_NEND 0x0004 | ||
51 | #define CHUNK_plst 0x0008 | ||
52 | #define CHUNK_time 0x0010 | ||
53 | #define CHUNK_fade 0x0020 | ||
54 | #define CHUNK_tlbl 0x0040 | ||
55 | #define CHUNK_auth 0x0080 | ||
56 | #define CHUNK_BANK 0x0100 | ||
48 | 57 | ||
49 | static bool parse_nsfe(int fd, struct mp3entry *id3) | 58 | static bool parse_nsfe(int fd, struct mp3entry *id3) |
50 | { | 59 | { |
51 | bool info_found = false; | 60 | unsigned int chunks_found = 0; |
52 | bool end_found = false; | 61 | long track_count = 0; |
53 | bool data_found = false; | 62 | long playlist_count = 0; |
54 | 63 | ||
55 | struct NSFE_INFOCHUNK info; | 64 | struct NSFE_INFOCHUNK info; |
56 | memset(&info, 0, sizeof(struct NSFE_INFOCHUNK)); | 65 | memset(&info, 0, sizeof(struct NSFE_INFOCHUNK)); |
@@ -60,9 +69,9 @@ static bool parse_nsfe(int fd, struct mp3entry *id3) | |||
60 | id3->length = 2*1000*60; | 69 | id3->length = 2*1000*60; |
61 | 70 | ||
62 | /* begin reading chunks */ | 71 | /* begin reading chunks */ |
63 | while (!end_found) | 72 | while (!(chunks_found & CHUNK_NEND)) |
64 | { | 73 | { |
65 | int32_t chunk_size, chunk_type; | 74 | uint32_t chunk_size, chunk_type; |
66 | 75 | ||
67 | if (read_uint32le(fd, &chunk_size) != (int)sizeof(uint32_t)) | 76 | if (read_uint32le(fd, &chunk_size) != (int)sizeof(uint32_t)) |
68 | return false; | 77 | return false; |
@@ -72,36 +81,63 @@ static bool parse_nsfe(int fd, struct mp3entry *id3) | |||
72 | 81 | ||
73 | switch (chunk_type) | 82 | switch (chunk_type) |
74 | { | 83 | { |
84 | /* first three types are mandatory (but don't worry about NEND | ||
85 | anyway) */ | ||
75 | case CHAR4_CONST('I', 'N', 'F', 'O'): | 86 | case CHAR4_CONST('I', 'N', 'F', 'O'): |
76 | { | 87 | { |
77 | /* only one info chunk permitted */ | 88 | if (chunks_found & CHUNK_INFO) |
78 | if (info_found) | 89 | return false; /* only one info chunk permitted */ |
79 | return false; | ||
80 | 90 | ||
81 | info_found = true; | 91 | chunks_found |= CHUNK_INFO; |
82 | 92 | ||
83 | /* minimum size */ | 93 | /* minimum size */ |
84 | if (chunk_size < 8) | 94 | if (chunk_size < 8) |
85 | return false; | 95 | return false; |
86 | 96 | ||
87 | ssize_t size = MIN((ssize_t)sizeof(struct NSFE_INFOCHUNK), | 97 | ssize_t size = MIN(sizeof(struct NSFE_INFOCHUNK), chunk_size); |
88 | chunk_size); | ||
89 | 98 | ||
90 | if (read(fd, &info, size) != size) | 99 | if (read(fd, &info, size) != size) |
91 | return false; | 100 | return false; |
92 | 101 | ||
93 | if (size >= 9) | 102 | if (size >= 9) |
94 | id3->length = info.nTrackCount*1000; | 103 | track_count = info.nTrackCount; |
95 | 104 | ||
96 | lseek(fd, chunk_size - size, SEEK_CUR); | 105 | chunk_size -= size; |
97 | break; | 106 | break; |
98 | } | 107 | } |
99 | 108 | ||
100 | case CHAR4_CONST('a', 'u', 't', 'h'): | 109 | case CHAR4_CONST('D', 'A', 'T', 'A'): |
101 | { | 110 | { |
102 | if (!info_found) | 111 | if (!(chunks_found & CHUNK_INFO)) |
112 | return false; | ||
113 | |||
114 | if (chunks_found & CHUNK_DATA) | ||
115 | return false; /* only one may exist */ | ||
116 | |||
117 | if (chunk_size < 1) | ||
103 | return false; | 118 | return false; |
104 | 119 | ||
120 | chunks_found |= CHUNK_DATA; | ||
121 | break; | ||
122 | } | ||
123 | |||
124 | case CHAR4_CONST('N', 'E', 'N', 'D'): | ||
125 | { | ||
126 | /* just end parsing regardless of whether or not this really is the | ||
127 | last chunk/data (but it _should_ be) */ | ||
128 | chunks_found |= CHUNK_NEND; | ||
129 | continue; | ||
130 | } | ||
131 | |||
132 | /* remaining types are optional */ | ||
133 | |||
134 | case CHAR4_CONST('a', 'u', 't', 'h'): | ||
135 | { | ||
136 | if (chunks_found & CHUNK_auth) | ||
137 | return false; /* only one may exist */ | ||
138 | |||
139 | chunks_found |= CHUNK_auth; | ||
140 | |||
105 | /* szGameTitle, szArtist, szCopyright */ | 141 | /* szGameTitle, szArtist, szCopyright */ |
106 | char ** const ar[] = { &id3->title, &id3->artist, &id3->album }; | 142 | char ** const ar[] = { &id3->title, &id3->artist, &id3->album }; |
107 | 143 | ||
@@ -120,39 +156,37 @@ static bool parse_nsfe(int fd, struct mp3entry *id3) | |||
120 | p += len; | 156 | p += len; |
121 | buf_rem -= len; | 157 | buf_rem -= len; |
122 | 158 | ||
123 | if (chunk_size >= len) | 159 | if (chunk_size >= (uint32_t)len) |
124 | chunk_size -= len; | 160 | chunk_size -= len; |
125 | else | 161 | else |
126 | chunk_size = 0; | 162 | chunk_size = 0; |
127 | } | 163 | } |
128 | 164 | ||
129 | lseek(fd, chunk_size, SEEK_CUR); | ||
130 | break; | 165 | break; |
131 | } | 166 | } |
132 | 167 | ||
133 | |||
134 | case CHAR4_CONST('D', 'A', 'T', 'A'): | ||
135 | if (chunk_size < 1) | ||
136 | return false; | ||
137 | |||
138 | data_found = true; | ||
139 | /* fall through */ | ||
140 | case CHAR4_CONST('f', 'a', 'd', 'e'): | ||
141 | case CHAR4_CONST('t', 'i', 'm', 'e'): | ||
142 | case CHAR4_CONST('B', 'A', 'N', 'K'): | ||
143 | case CHAR4_CONST('p', 'l', 's', 't'): | 168 | case CHAR4_CONST('p', 'l', 's', 't'): |
144 | case CHAR4_CONST('t', 'l', 'b', 'l'): /* we unfortunately can't use these anyway */ | ||
145 | { | 169 | { |
146 | if (!info_found) | 170 | if (chunks_found & CHUNK_plst) |
147 | return false; | 171 | return false; /* only one may exist */ |
172 | |||
173 | chunks_found |= CHUNK_plst; | ||
148 | 174 | ||
149 | lseek(fd, chunk_size, SEEK_CUR); | 175 | /* each byte is the index of one track */ |
176 | playlist_count = chunk_size; | ||
150 | break; | 177 | break; |
151 | } | 178 | } |
152 | 179 | ||
153 | case CHAR4_CONST('N', 'E', 'N', 'D'): | 180 | case CHAR4_CONST('t', 'i', 'm', 'e'): |
181 | case CHAR4_CONST('f', 'a', 'd', 'e'): | ||
182 | case CHAR4_CONST('t', 'l', 'b', 'l'): /* we unfortunately can't use these anyway */ | ||
154 | { | 183 | { |
155 | end_found = true; | 184 | /* don't care how many of these there are even though there should |
185 | be only one */ | ||
186 | if (!(chunks_found & CHUNK_INFO)) | ||
187 | return false; | ||
188 | |||
189 | case CHAR4_CONST('B', 'A', 'N', 'K'): | ||
156 | break; | 190 | break; |
157 | } | 191 | } |
158 | 192 | ||
@@ -166,19 +200,24 @@ static bool parse_nsfe(int fd, struct mp3entry *id3) | |||
166 | return false; | 200 | return false; |
167 | 201 | ||
168 | /* otherwise, just skip it */ | 202 | /* otherwise, just skip it */ |
169 | lseek(fd, chunk_size, SEEK_CUR); | ||
170 | break; | 203 | break; |
171 | } | 204 | } |
172 | } /* end switch */ | 205 | } /* end switch */ |
206 | |||
207 | lseek(fd, chunk_size, SEEK_CUR); | ||
173 | } /* end while */ | 208 | } /* end while */ |
174 | 209 | ||
210 | if (track_count | playlist_count) | ||
211 | id3->length = MAX(track_count, playlist_count)*1000; | ||
212 | |||
175 | /* | 213 | /* |
176 | * if we exited the while loop without a 'return', we must have hit an NEND | 214 | * if we exited the while loop without a 'return', we must have hit an NEND |
177 | * chunk if this is the case, the file was layed out as it was expected. | 215 | * chunk if this is the case, the file was layed out as it was expected. |
178 | * now.. make sure we found both an info chunk, AND a data chunk... since | 216 | * now.. make sure we found both an info chunk, AND a data chunk... since |
179 | * these are minimum requirements for a valid NSFE file | 217 | * these are minimum requirements for a valid NSFE file |
180 | */ | 218 | */ |
181 | return info_found && data_found; | 219 | return (chunks_found & (CHUNK_INFO | CHUNK_DATA)) == |
220 | (CHUNK_INFO | CHUNK_DATA); | ||
182 | } | 221 | } |
183 | 222 | ||
184 | static bool parse_nesm(int fd, struct mp3entry *id3) | 223 | static bool parse_nesm(int fd, struct mp3entry *id3) |