forked from len0rd/rockbox
ID3v2.3 treats the global unsynch flag in a silly way, so we have to unsynch the whole tag before we can parse the individual frames.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@4188 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
32c66315c8
commit
219d52a86f
1 changed files with 79 additions and 26 deletions
103
firmware/id3.c
103
firmware/id3.c
|
|
@ -40,6 +40,7 @@
|
||||||
|
|
||||||
#include "id3.h"
|
#include "id3.h"
|
||||||
#include "mp3data.h"
|
#include "mp3data.h"
|
||||||
|
#include "system.h"
|
||||||
|
|
||||||
#define UNSYNC(b0,b1,b2,b3) (((b0 & 0x7F) << (3*7)) | \
|
#define UNSYNC(b0,b1,b2,b3) (((b0 & 0x7F) << (3*7)) | \
|
||||||
((b1 & 0x7F) << (2*7)) | \
|
((b1 & 0x7F) << (2*7)) | \
|
||||||
|
|
@ -108,12 +109,13 @@ struct tag_resolver {
|
||||||
int (*ppFunc)(struct mp3entry*, char* tag, int bufferpos);
|
int (*ppFunc)(struct mp3entry*, char* tag, int bufferpos);
|
||||||
};
|
};
|
||||||
|
|
||||||
static int unsynchronize(char* tag, int len)
|
static bool global_ff_found = false;
|
||||||
|
|
||||||
|
static int unsynchronize(char* tag, int len, bool *ff_found)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
unsigned char c;
|
unsigned char c;
|
||||||
unsigned char *rp, *wp;
|
unsigned char *rp, *wp;
|
||||||
bool ff_found = false;
|
|
||||||
|
|
||||||
wp = rp = tag;
|
wp = rp = tag;
|
||||||
|
|
||||||
|
|
@ -123,20 +125,76 @@ static int unsynchronize(char* tag, int len)
|
||||||
write pointer */
|
write pointer */
|
||||||
c = *rp++;
|
c = *rp++;
|
||||||
*wp = c;
|
*wp = c;
|
||||||
if(ff_found) {
|
if(*ff_found) {
|
||||||
/* Increment the write pointer if it isn't an unsynch pattern */
|
/* Increment the write pointer if it isn't an unsynch pattern */
|
||||||
if(c != 0)
|
if(c != 0)
|
||||||
wp++;
|
wp++;
|
||||||
ff_found = false;
|
*ff_found = false;
|
||||||
} else {
|
} else {
|
||||||
if(c == 0xff)
|
if(c == 0xff)
|
||||||
ff_found = true;
|
*ff_found = true;
|
||||||
wp++;
|
wp++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (int)wp - (int)tag;
|
return (int)wp - (int)tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int unsynchronize_frame(char* tag, int len)
|
||||||
|
{
|
||||||
|
bool ff_found = false;
|
||||||
|
|
||||||
|
return unsynchronize(tag, len, &ff_found);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int read_unsynched(int fd, void *buf, int len, bool reset)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int rc;
|
||||||
|
int remaining = len;
|
||||||
|
char *wp;
|
||||||
|
char *rp;
|
||||||
|
|
||||||
|
if(reset)
|
||||||
|
global_ff_found = false;
|
||||||
|
|
||||||
|
wp = buf;
|
||||||
|
|
||||||
|
while(remaining) {
|
||||||
|
rp = wp;
|
||||||
|
rc = read(fd, rp, remaining);
|
||||||
|
if(rc < 0)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
i = unsynchronize(wp, remaining, &global_ff_found);
|
||||||
|
remaining -= i;
|
||||||
|
wp += i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return len;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int skip_unsynched(int fd, int len, bool reset)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
int remaining = len;
|
||||||
|
int rlen;
|
||||||
|
char buf[32];
|
||||||
|
|
||||||
|
if(reset)
|
||||||
|
global_ff_found = false;
|
||||||
|
|
||||||
|
while(remaining) {
|
||||||
|
rlen = MIN(sizeof(buf), (unsigned int)remaining);
|
||||||
|
rc = read(fd, buf, rlen);
|
||||||
|
if(rc < 0)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
remaining -= unsynchronize(buf, rlen, &global_ff_found);
|
||||||
|
}
|
||||||
|
|
||||||
|
return len;
|
||||||
|
};
|
||||||
|
|
||||||
/* parse numeric value from string */
|
/* parse numeric value from string */
|
||||||
static int parsetracknum( struct mp3entry* entry, char* tag, int bufferpos )
|
static int parsetracknum( struct mp3entry* entry, char* tag, int bufferpos )
|
||||||
{
|
{
|
||||||
|
|
@ -365,6 +423,7 @@ static void setid3v2title(int fd, struct mp3entry *entry)
|
||||||
bool unsynch = false;
|
bool unsynch = false;
|
||||||
int data_length_ind;
|
int data_length_ind;
|
||||||
int i;
|
int i;
|
||||||
|
int rc;
|
||||||
|
|
||||||
/* Bail out if the tag is shorter than 10 bytes */
|
/* Bail out if the tag is shorter than 10 bytes */
|
||||||
if(entry->id3v2len < 10)
|
if(entry->id3v2len < 10)
|
||||||
|
|
@ -433,7 +492,11 @@ static void setid3v2title(int fd, struct mp3entry *entry)
|
||||||
|
|
||||||
/* Read frame header and check length */
|
/* Read frame header and check length */
|
||||||
if(version >= ID3_VER_2_3) {
|
if(version >= ID3_VER_2_3) {
|
||||||
if(10 != read(fd, header, 10))
|
if(global_unsynch && version <= ID3_VER_2_3)
|
||||||
|
rc = read_unsynched(fd, header, 10, false);
|
||||||
|
else
|
||||||
|
rc = read(fd, header, 10);
|
||||||
|
if(rc != 10)
|
||||||
return;
|
return;
|
||||||
/* Adjust for the 10 bytes we read */
|
/* Adjust for the 10 bytes we read */
|
||||||
size -= 10;
|
size -= 10;
|
||||||
|
|
@ -531,15 +594,20 @@ static void setid3v2title(int fd, struct mp3entry *entry)
|
||||||
if( !*ptag && !memcmp( header, tr->tag, tr->tag_length ) ) {
|
if( !*ptag && !memcmp( header, tr->tag, tr->tag_length ) ) {
|
||||||
|
|
||||||
/* found a tag matching one in tagList, and not yet filled */
|
/* found a tag matching one in tagList, and not yet filled */
|
||||||
|
if(global_unsynch && version <= ID3_VER_2_3)
|
||||||
|
bytesread = read_unsynched(fd, buffer + bufferpos,
|
||||||
|
framelen, false);
|
||||||
|
else
|
||||||
bytesread = read(fd, buffer + bufferpos, framelen);
|
bytesread = read(fd, buffer + bufferpos, framelen);
|
||||||
|
|
||||||
if( bytesread != framelen )
|
if( bytesread != framelen )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
size -= bytesread;
|
size -= bytesread;
|
||||||
*ptag = buffer + bufferpos;
|
*ptag = buffer + bufferpos;
|
||||||
|
|
||||||
if(global_unsynch || unsynch)
|
if(unsynch || (global_unsynch && version >= ID3_VER_2_4))
|
||||||
bytesread = unsynchronize(*ptag, bytesread);
|
bytesread = unsynchronize_frame(*ptag, bytesread);
|
||||||
|
|
||||||
unicode_munge( ptag, &bytesread );
|
unicode_munge( ptag, &bytesread );
|
||||||
tag = *ptag;
|
tag = *ptag;
|
||||||
|
|
@ -555,23 +623,8 @@ static void setid3v2title(int fd, struct mp3entry *entry)
|
||||||
/* no tag in tagList was found, or it was a repeat.
|
/* no tag in tagList was found, or it was a repeat.
|
||||||
skip it using the total size */
|
skip it using the total size */
|
||||||
|
|
||||||
/* We may need to compensate for the unsynchronization scheme */
|
if(global_unsynch && version <= ID3_VER_2_3) {
|
||||||
if(global_unsynch && !data_length_ind) {
|
skip_unsynched(fd, totframelen, false);
|
||||||
bool ff_found = false;
|
|
||||||
|
|
||||||
for(i = 0;i < totframelen;i++) {
|
|
||||||
unsigned char c;
|
|
||||||
bytesread = read(fd, &c, 1);
|
|
||||||
if(ff_found) {
|
|
||||||
if(c == 0)
|
|
||||||
/* Found an unsynch pattern, counting it */
|
|
||||||
totframelen++;
|
|
||||||
ff_found = false;
|
|
||||||
} else {
|
|
||||||
if(c == 0xff)
|
|
||||||
ff_found = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if(data_length_ind)
|
if(data_length_ind)
|
||||||
totframelen = data_length_ind;
|
totframelen = data_length_ind;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue