summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2011-04-28 02:56:28 +0000
committerMichael Sevakis <jethead71@rockbox.org>2011-04-28 02:56:28 +0000
commitac724cca19b8e0564c921db7a2e1a1fc52ccbe18 (patch)
tree5a65db56eb1c921afd49188d938c7218baf04b08
parentfa65362a42675d9d84a7ec57fdf5d8e1b575a4cd (diff)
downloadrockbox-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
-rw-r--r--apps/codecs/nsf.c29
-rw-r--r--apps/metadata/nsf.c109
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 **/
4298static int track = 0;
4299static char last_path[MAX_PATH];
4300static int dontresettrack = 0;
4301static bool repeat_one = false;
4302
4297static void set_codec_track(int t, int d) { 4303static 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 **/
4314static int track = 0;
4315static char last_path[MAX_PATH];
4316static int dontresettrack = 0;
4317
4318/* this is the codec entry point */ 4319/* this is the codec entry point */
4319enum codec_status codec_main(enum codec_entry_call_reason reason) 4320enum 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
4360init_nsf: 4363init_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
49static bool parse_nsfe(int fd, struct mp3entry *id3) 58static 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
184static bool parse_nesm(int fd, struct mp3entry *id3) 223static bool parse_nesm(int fd, struct mp3entry *id3)