1
0
Fork 0
forked from len0rd/rockbox

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
This commit is contained in:
Michael Sevakis 2011-04-28 02:56:28 +00:00
parent fa65362a42
commit ac724cca19
2 changed files with 87 additions and 55 deletions

View file

@ -4294,12 +4294,18 @@ jammed:
/****************** rockbox interface ******************/ /****************** rockbox interface ******************/
/** Operational info **/
static int track = 0;
static char last_path[MAX_PATH];
static int dontresettrack = 0;
static bool repeat_one = false;
static void set_codec_track(int t, int d) { static void set_codec_track(int t, int d) {
int track,fade,def=0; int track,fade,def=0;
SetTrack(t); SetTrack(t);
/* for REPEAT_ONE we disable track limits */ /* for REPEAT_ONE we disable track limits */
if (ci->global_settings->repeat_mode!=REPEAT_ONE) { if (!repeat_one) {
if (!bIsExtended || nTrackTime[t]==-1) {track=60*2*1000; def=1;} if (!bIsExtended || nTrackTime[t]==-1) {track=60*2*1000; def=1;}
else track=nTrackTime[t]; else track=nTrackTime[t];
if (!bIsExtended || nTrackFade[t]==-1) fade=5*1000; if (!bIsExtended || nTrackFade[t]==-1) fade=5*1000;
@ -4310,11 +4316,6 @@ static void set_codec_track(int t, int d) {
ci->set_elapsed(d*1000); /* d is track no to display */ ci->set_elapsed(d*1000); /* d is track no to display */
} }
/** Operational info **/
static int track = 0;
static char last_path[MAX_PATH];
static int dontresettrack = 0;
/* this is the codec entry point */ /* this is the codec entry point */
enum codec_status codec_main(enum codec_entry_call_reason reason) enum codec_status codec_main(enum codec_entry_call_reason reason)
{ {
@ -4357,6 +4358,8 @@ enum codec_status codec_run(void)
return CODEC_ERROR; return CODEC_ERROR;
} }
repeat_one = ci->global_settings->repeat_mode == REPEAT_ONE;
init_nsf: init_nsf:
if(!NSFCore_Initialize()) { if(!NSFCore_Initialize()) {
DEBUGF("NSF: NSFCore_Initialize failed\n"); return CODEC_ERROR;} DEBUGF("NSF: NSFCore_Initialize failed\n"); return CODEC_ERROR;}
@ -4368,21 +4371,11 @@ init_nsf:
if(!LoadNSF(nDataBufferSize)) { if(!LoadNSF(nDataBufferSize)) {
DEBUGF("NSF: LoadNSF failed\n"); return CODEC_ERROR;} DEBUGF("NSF: LoadNSF failed\n"); return CODEC_ERROR;}
ci->id3->title=szGameTitle;
ci->id3->artist=szArtist;
ci->id3->album=szCopyright;
if (usingplaylist) {
ci->id3->length=nPlaylistSize*1000;
} else {
ci->id3->length=nTrackCount*1000;
}
if (!dontresettrack||strcmp(ci->id3->path,last_path)) { if (!dontresettrack||strcmp(ci->id3->path,last_path)) {
/* if this is the first time we're seeing this file, or if we haven't /* if this is the first time we're seeing this file, or if we haven't
been asked to preserve the track number, default to the proper been asked to preserve the track number, default to the proper
initial track */ initial track */
if (bIsExtended && if (bIsExtended && !repeat_one && nPlaylistSize>0) {
ci->global_settings->repeat_mode!=REPEAT_ONE && nPlaylistSize>0) {
/* decide to use the playlist */ /* decide to use the playlist */
usingplaylist=1; usingplaylist=1;
track=0; track=0;
@ -4447,7 +4440,7 @@ init_nsf:
print_timers(last_path,track); print_timers(last_path,track);
if (ci->global_settings->repeat_mode==REPEAT_ONE) { if (repeat_one) {
/* in repeat one mode just advance to the next track */ /* in repeat one mode just advance to the next track */
track++; track++;
if (track>=nTrackCount) track=0; if (track>=nTrackCount) track=0;

View file

@ -45,12 +45,21 @@ struct NSFE_INFOCHUNK
#define CHAR4_CONST(a, b, c, d) FOURCC(a, b, c, d) #define CHAR4_CONST(a, b, c, d) FOURCC(a, b, c, d)
#define CHUNK_INFO 0x0001
#define CHUNK_DATA 0x0002
#define CHUNK_NEND 0x0004
#define CHUNK_plst 0x0008
#define CHUNK_time 0x0010
#define CHUNK_fade 0x0020
#define CHUNK_tlbl 0x0040
#define CHUNK_auth 0x0080
#define CHUNK_BANK 0x0100
static bool parse_nsfe(int fd, struct mp3entry *id3) static bool parse_nsfe(int fd, struct mp3entry *id3)
{ {
bool info_found = false; unsigned int chunks_found = 0;
bool end_found = false; long track_count = 0;
bool data_found = false; long playlist_count = 0;
struct NSFE_INFOCHUNK info; struct NSFE_INFOCHUNK info;
memset(&info, 0, sizeof(struct NSFE_INFOCHUNK)); memset(&info, 0, sizeof(struct NSFE_INFOCHUNK));
@ -60,9 +69,9 @@ static bool parse_nsfe(int fd, struct mp3entry *id3)
id3->length = 2*1000*60; id3->length = 2*1000*60;
/* begin reading chunks */ /* begin reading chunks */
while (!end_found) while (!(chunks_found & CHUNK_NEND))
{ {
int32_t chunk_size, chunk_type; uint32_t chunk_size, chunk_type;
if (read_uint32le(fd, &chunk_size) != (int)sizeof(uint32_t)) if (read_uint32le(fd, &chunk_size) != (int)sizeof(uint32_t))
return false; return false;
@ -72,35 +81,62 @@ static bool parse_nsfe(int fd, struct mp3entry *id3)
switch (chunk_type) switch (chunk_type)
{ {
/* first three types are mandatory (but don't worry about NEND
anyway) */
case CHAR4_CONST('I', 'N', 'F', 'O'): case CHAR4_CONST('I', 'N', 'F', 'O'):
{ {
/* only one info chunk permitted */ if (chunks_found & CHUNK_INFO)
if (info_found) return false; /* only one info chunk permitted */
return false;
info_found = true; chunks_found |= CHUNK_INFO;
/* minimum size */ /* minimum size */
if (chunk_size < 8) if (chunk_size < 8)
return false; return false;
ssize_t size = MIN((ssize_t)sizeof(struct NSFE_INFOCHUNK), ssize_t size = MIN(sizeof(struct NSFE_INFOCHUNK), chunk_size);
chunk_size);
if (read(fd, &info, size) != size) if (read(fd, &info, size) != size)
return false; return false;
if (size >= 9) if (size >= 9)
id3->length = info.nTrackCount*1000; track_count = info.nTrackCount;
lseek(fd, chunk_size - size, SEEK_CUR); chunk_size -= size;
break; break;
} }
case CHAR4_CONST('D', 'A', 'T', 'A'):
{
if (!(chunks_found & CHUNK_INFO))
return false;
if (chunks_found & CHUNK_DATA)
return false; /* only one may exist */
if (chunk_size < 1)
return false;
chunks_found |= CHUNK_DATA;
break;
}
case CHAR4_CONST('N', 'E', 'N', 'D'):
{
/* just end parsing regardless of whether or not this really is the
last chunk/data (but it _should_ be) */
chunks_found |= CHUNK_NEND;
continue;
}
/* remaining types are optional */
case CHAR4_CONST('a', 'u', 't', 'h'): case CHAR4_CONST('a', 'u', 't', 'h'):
{ {
if (!info_found) if (chunks_found & CHUNK_auth)
return false; return false; /* only one may exist */
chunks_found |= CHUNK_auth;
/* szGameTitle, szArtist, szCopyright */ /* szGameTitle, szArtist, szCopyright */
char ** const ar[] = { &id3->title, &id3->artist, &id3->album }; char ** const ar[] = { &id3->title, &id3->artist, &id3->album };
@ -120,39 +156,37 @@ static bool parse_nsfe(int fd, struct mp3entry *id3)
p += len; p += len;
buf_rem -= len; buf_rem -= len;
if (chunk_size >= len) if (chunk_size >= (uint32_t)len)
chunk_size -= len; chunk_size -= len;
else else
chunk_size = 0; chunk_size = 0;
} }
lseek(fd, chunk_size, SEEK_CUR);
break; break;
} }
case CHAR4_CONST('D', 'A', 'T', 'A'):
if (chunk_size < 1)
return false;
data_found = true;
/* fall through */
case CHAR4_CONST('f', 'a', 'd', 'e'):
case CHAR4_CONST('t', 'i', 'm', 'e'):
case CHAR4_CONST('B', 'A', 'N', 'K'):
case CHAR4_CONST('p', 'l', 's', 't'): case CHAR4_CONST('p', 'l', 's', 't'):
{
if (chunks_found & CHUNK_plst)
return false; /* only one may exist */
chunks_found |= CHUNK_plst;
/* each byte is the index of one track */
playlist_count = chunk_size;
break;
}
case CHAR4_CONST('t', 'i', 'm', 'e'):
case CHAR4_CONST('f', 'a', 'd', 'e'):
case CHAR4_CONST('t', 'l', 'b', 'l'): /* we unfortunately can't use these anyway */ case CHAR4_CONST('t', 'l', 'b', 'l'): /* we unfortunately can't use these anyway */
{ {
if (!info_found) /* don't care how many of these there are even though there should
be only one */
if (!(chunks_found & CHUNK_INFO))
return false; return false;
lseek(fd, chunk_size, SEEK_CUR); case CHAR4_CONST('B', 'A', 'N', 'K'):
break;
}
case CHAR4_CONST('N', 'E', 'N', 'D'):
{
end_found = true;
break; break;
} }
@ -166,19 +200,24 @@ static bool parse_nsfe(int fd, struct mp3entry *id3)
return false; return false;
/* otherwise, just skip it */ /* otherwise, just skip it */
lseek(fd, chunk_size, SEEK_CUR);
break; break;
} }
} /* end switch */ } /* end switch */
lseek(fd, chunk_size, SEEK_CUR);
} /* end while */ } /* end while */
if (track_count | playlist_count)
id3->length = MAX(track_count, playlist_count)*1000;
/* /*
* if we exited the while loop without a 'return', we must have hit an NEND * if we exited the while loop without a 'return', we must have hit an NEND
* chunk if this is the case, the file was layed out as it was expected. * chunk if this is the case, the file was layed out as it was expected.
* now.. make sure we found both an info chunk, AND a data chunk... since * now.. make sure we found both an info chunk, AND a data chunk... since
* these are minimum requirements for a valid NSFE file * these are minimum requirements for a valid NSFE file
*/ */
return info_found && data_found; return (chunks_found & (CHUNK_INFO | CHUNK_DATA)) ==
(CHUNK_INFO | CHUNK_DATA);
} }
static bool parse_nesm(int fd, struct mp3entry *id3) static bool parse_nesm(int fd, struct mp3entry *id3)