diff --git a/apps/codecs/smaf.c b/apps/codecs/smaf.c index cd1155b..7ac2ec5 100644 --- a/apps/codecs/smaf.c +++ b/apps/codecs/smaf.c @@ -99,13 +99,24 @@ static int convert_smaf_audio_basebit(unsigned int basebit) return basebits[basebit]; } -static bool parse_audio_track(struct pcm_format *fmt, - unsigned char **stbuf, unsigned char *endbuf) +static bool parse_audio_track(struct pcm_format *fmt, off_t *pos) { - unsigned char *buf = *stbuf; - int chunksize; + unsigned char *buf; + size_t chunksize; + size_t readsize; + + /* size of the next chunk. */ + chunksize = 6; + + buf = ci->request_buffer(&readsize, chunksize); + if (readsize < chunksize) + { + DEBUGF("CODEC_ERROR: audio track chunk is too small\n"); + return false; + } + ci->advance_buffer(chunksize); + *pos += chunksize; - buf += 8; fmt->channels = ((buf[2] & 0x80) >> 7) + 1; fmt->formattag = convert_smaf_audio_format(SMAF_TRACK_CHUNK_AUDIO, (buf[2] >> 4) & 0x07); @@ -120,50 +131,85 @@ static bool parse_audio_track(struct pcm_format *fmt, DEBUGF("CODEC_ERROR: unsupport pcm data basebit : %d\n", buf[3] >> 4); return false; } - buf += 6; - while (buf < endbuf) + + while (*pos < (off_t)ci->id3->filesize) { - chunksize = get_be32(buf + 4) + 8; + /* get chunk name and chunksize */ + buf = ci->request_buffer(&readsize, 8); + if (readsize < 8) + { + DEBUGF("CODEC_ERROR: audio track chunk is too small\n"); + return false; + } + ci->advance_buffer(8); + *pos += 8; + + chunksize = get_be32(buf + 4); if (memcmp(buf, "Awa", 3) == 0) { - fmt->numbytes = get_be32(buf + 4); - buf += 8; + fmt->numbytes = chunksize; return true; } - buf += chunksize; + else + { + ci->advance_buffer(chunksize); + *pos += chunksize; + } } DEBUGF("CODEC_ERROR: smaf does not include stream pcm data\n"); return false; } -static bool parse_score_track(struct pcm_format *fmt, - unsigned char **stbuf, unsigned char *endbuf) +static bool parse_score_track(struct pcm_format *fmt, int smaftype, off_t *pos) { - unsigned char *buf = *stbuf; - int chunksize; + unsigned char *buf; + size_t chunksize; + size_t readsize; + + /* + * size of the next chunk. + * MA-2/MA-3/MA-5: 20 bytes + * MA-7: 36 bytes + */ + chunksize = (smaftype < 7)? 20 : 36; - if (buf[9] != 0x00) + buf = ci->request_buffer(&readsize, chunksize); + if (readsize < chunksize) { - DEBUGF("CODEC_ERROR: score track chunk unsupport sequence type %d\n", buf[9]); + DEBUGF("CODEC_ERROR: score track chunk is too small\n"); return false; } + ci->advance_buffer(chunksize); + *pos += chunksize; - /* - * skip to the next chunk. - * MA-2/MA-3/MA-5: padding 16 bytes - * MA-7: padding 32 bytes - */ - if (buf[3] < 7) - buf += 28; - else - buf += 44; - - while (buf < endbuf) + if (buf[1] != 0x00) + { + DEBUGF("CODEC_ERROR: score track chunk unsupport sequence type %d\n", buf[1]); + return false; + } + + while (*pos < (off_t)ci->id3->filesize) { - chunksize = get_be32(buf + 4) + 8; + /* get chunk name and chunksize */ + buf = ci->request_buffer(&readsize, 8); + if (readsize < 8) + { + DEBUGF("CODEC_ERROR: score track chunk is too small\n"); + return false; + } + ci->advance_buffer(8); + *pos += 8; + if (memcmp(buf, "Mtsp", 4) == 0) { - buf += 8; + buf = ci->request_buffer(&readsize, 11); + if (readsize < 11) + { + DEBUGF("CODEC_ERROR: score track chunk is too small\n"); + return false; + } + *pos += 11; + if (memcmp(buf, "Mwa", 3) != 0) { DEBUGF("CODEC_ERROR: smaf does not include stream pcm data\n"); @@ -186,58 +232,79 @@ static bool parse_score_track(struct pcm_format *fmt, buf[8] & 0x0f); return false; } - buf += 11; return true; } - buf += chunksize; + else + { + chunksize = get_be32(buf + 4); + ci->advance_buffer(chunksize); + *pos += chunksize; + } } DEBUGF("CODEC_ERROR: smaf does not include stream pcm data\n"); return false; } -static bool parse_header(struct pcm_format *fmt, size_t *pos) +static bool parse_header(struct pcm_format *fmt, off_t *pos) { - unsigned char *buf, *stbuf, *endbuf; + unsigned char *buf; size_t chunksize; + size_t readsize; + *pos = 0; ci->memset(fmt, 0, sizeof(struct pcm_format)); - /* assume the SMAF pcm data position is less than 1024 bytes */ - stbuf = ci->request_buffer(&chunksize, 1024); - if (chunksize < 1024) + /* get chunk name and chunksize */ + buf = ci->request_buffer(&readsize, 8); + if (readsize < 8) + { + DEBUGF("CODEC_ERROR: smaf file is too small\n"); return false; + } + ci->advance_buffer(8); + *pos += 8; - buf = stbuf; - endbuf = stbuf + chunksize; - if (memcmp(buf, "MMMD", 4) != 0) { DEBUGF("CODEC_ERROR: does not smaf format %c%c%c%c\n", buf[0], buf[1], buf[2], buf[3]); return false; } - buf += 8; - while (buf < endbuf) + while (*pos < (off_t)ci->id3->filesize) { - chunksize = get_be32(buf + 4) + 8; + /* get chunk name and chunksize */ + buf = ci->request_buffer(&readsize, 8); + if (readsize < 8) + { + DEBUGF("CODEC_ERROR: smaf file is too small\n"); + return false; + } + ci->advance_buffer(8); + *pos += 8; + if (memcmp(buf, "ATR", 3) == 0) { - if (!parse_audio_track(fmt, &buf, endbuf)) + if (!parse_audio_track(fmt, pos)) return false; break; } - if (memcmp(buf, "MTR", 3) == 0) + else if (memcmp(buf, "MTR", 3) == 0) { - if (!parse_score_track(fmt, &buf, endbuf)) + if (!parse_score_track(fmt, buf[3], pos)) return false; break; } - buf += chunksize; + else + { + chunksize = get_be32(buf + 4); + ci->advance_buffer(chunksize); + *pos += chunksize; + } } - if (buf >= endbuf) + if (*pos >= (off_t)ci->id3->filesize) { DEBUGF("CODEC_ERROR: unsupported smaf format\n"); return false; @@ -251,11 +318,9 @@ static bool parse_header(struct pcm_format *fmt, size_t *pos) /* data signess (default signed) */ fmt->is_signed = (fmt->formattag != SMAF_FORMAT_UNSIGNED_PCM); + /* data is always big endian */ fmt->is_little_endian = false; - /* sets pcm data position */ - *pos = buf - stbuf; - return true; } @@ -305,7 +370,7 @@ next_track: decodedsamples = 0; codec = 0; - if (!parse_header(&format, &n)) + if (!parse_header(&format, &firstblockposn)) { i = CODEC_ERROR; goto done; @@ -371,8 +436,8 @@ next_track: goto done; } - firstblockposn = 1024 - n; - ci->advance_buffer(firstblockposn); + ci->seek_buffer(firstblockposn); + ci->seek_complete(); /* The main decoder loop */ bytesdone = 0; diff --git a/apps/metadata/smaf.c b/apps/metadata/smaf.c old mode 100644 new mode 100755 index 586802b..1aa2526 --- a/apps/metadata/smaf.c +++ b/apps/metadata/smaf.c @@ -31,11 +31,11 @@ #include "rbunicode.h" #include "logf.h" -static int basebits[4] = { 4, 8, 12, 16 }; +static const char basebits[4] = { 4, 8, 12, 16 }; -static int frequency[5] = { 4000, 8000, 11025, 22050, 44100 }; +static const int frequency[5] = { 4000, 8000, 11025, 22050, 44100 }; -static int support_codepages[7] = { +static const char support_codepages[7] = { SJIS, ISO_8859_1, -1, GB_2312, BIG_5, -1, -1, }; @@ -48,79 +48,24 @@ static int support_codepages[7] = { #define TAG_ARTIST (('A'<<8)|'N') #define TAG_COMPOSER (('S'<<8)|'W') -static bool read_datachunk(unsigned char *src, int size, unsigned short tag, - int codepage, unsigned char *dst) -{ - int datasize = 0; - unsigned char *utf8; - - while(size > datasize + 4) - { - datasize = (src[2] << 8) | src[3]; - if (tag == ((src[0] << 8) | src[1])) - { - src += 4; - if (codepage < NUM_CODEPAGES) - utf8 = iso_decode(src, dst, codepage, datasize); - else /* codepage == UTF_16, UCS_2 */ - utf8 = utf16BEdecode(src, dst, datasize); - *utf8 = '\0'; - - return true; - } - src += (datasize + 4); - } - return false; -} - -static bool read_option(unsigned char *src, int size, unsigned short tag, - int codepage, unsigned char *dst) -{ - int datasize = 0; - unsigned char *endsrc = src + size; - unsigned char *utf8; - - while(src < endsrc) - { - utf8 = src; - src += 3; - datasize = 0; - while (*src != ',' || *(src-1) == '\\') - { - datasize++; - src++; - } - if (tag == ((utf8[0] << 8) | utf8[1]) && utf8[2] == ':') - { - utf8 += 3; - if (codepage < NUM_CODEPAGES) - utf8 = iso_decode(utf8, dst, codepage, datasize); - else /* codepage == UTF_16, UCS_2 */ - utf8 = utf16BEdecode(utf8, dst, datasize); - *utf8 = '\0'; - - return true; - } - src++; - } - return false; -} +#define CONTENTS_TAG(b) ((b[0]<<8)|b[1]) +#define CONTENTS_SIZE(b) ((b[2]<<8)|b[3]) -static int convert_smaf_audio_frequency(unsigned int freq) +static inline int convert_smaf_audio_frequency(unsigned int freq) { if (freq > 4) return 0; return frequency[freq]; } -static int convert_smaf_audio_basebit(unsigned int basebit) +static inline unsigned char convert_smaf_audio_basebit(unsigned int basebit) { if (basebit > 4) return 0; return basebits[basebit]; } -static int convert_smaf_codetype(unsigned int codetype) +static char convert_smaf_codetype(unsigned int codetype) { if (codetype < 7) return support_codepages[codetype]; @@ -137,233 +82,418 @@ static int convert_smaf_codetype(unsigned int codetype) return -1; } -static bool get_smaf_metadata_audio_track(struct mp3entry *id3, - unsigned char* buf, unsigned char *endbuf) +static int decode2utf8(const unsigned char *src, unsigned char *dst, + int srcsize, int dstsize, char codepage) { - int bitspersample; - int channels; - int chunksize; - long numbytes; - unsigned long totalsamples; - - channels = ((buf[10] & 0x80) >> 7) + 1; - bitspersample = convert_smaf_audio_basebit(buf[11] >> 4); - if (bitspersample == 0) + unsigned char tmpbuf[srcsize * 3]; + unsigned char *p; + int utf8size; + + if (codepage < NUM_CODEPAGES) + p = iso_decode(src, tmpbuf, codepage, srcsize); + else /* codepage == UTF_16, UCS_2 */ + p = utf16BEdecode(src, tmpbuf, srcsize); + + *p = '\0'; + + strlcpy(dst, tmpbuf, dstsize); + utf8size = (p - tmpbuf) + 1; + if (utf8size > dstsize) + { + DEBUGF("metadata warning: data length: %d > contents store buffer size: %d\n", + utf8size, dstsize); + utf8size = dstsize; + } + return utf8size; +} + +static bool read_option(int fd, char codepage, unsigned char *dst, int dstsize, + int *datasize, int *realsize) +{ + /* value length <= 256 bytes */ + unsigned char buf[256]; + unsigned char *p = buf; + int count = 0; + + *datasize = (int)read(fd, buf, 256); + if (*datasize < 1) { - DEBUGF("metada error: smaf unsupport basebit %d\n", buf[11] >> 4); + DEBUGF("metadata error: smaf read error\n"); return false; } - id3->frequency = convert_smaf_audio_frequency(buf[10] & 0x0f); - buf += 14; - while (buf < endbuf) + while (p - buf < *datasize) { - chunksize = get_long_be(buf + 4) + 8; - if (memcmp(buf, "Awa", 3) == 0) + if (*p == ',') + break; + + if (*p == '\\' && *(p+1) == ',') + p++; + + count++; + p++; + } + if (p - buf < *datasize) + { + lseek(fd, (p - buf) - (*datasize) + 1, SEEK_CUR); + *datasize = (p - buf) + 1; + } + + if (dst != NULL) + *realsize = decode2utf8(buf, dst, count, dstsize, codepage); + + return true; +} + +static bool read_data(int fd, char codepage, int datasize, + unsigned char *dst, int dstsize, int *realsize) +{ + unsigned char buf[datasize]; + + if (read(fd, buf, datasize) < datasize) + { + DEBUGF("metadata error: smaf contents field is too small\n"); + return false; + } + + *realsize = decode2utf8(buf, dst, datasize, dstsize, codepage); + return true; +} + +static bool parse_smaf_audio_track_contents(int fd, struct mp3entry *id3, int size) +{ + /* temporary buffer */ + unsigned char *buf = (unsigned char*)id3->path; + /* contents stored buffer */ + unsigned char *cbuf = id3->id3v2buf; + char codepage; + int csize = sizeof(id3->id3v2buf); + int dsize; + int rsize; + + if (read(fd, buf, 5) < 5) + { + DEBUGF("metadata error: smaf contents field is too small\n"); + return false; + } + codepage = convert_smaf_codetype(buf[2]); + if (codepage < 0) + { + DEBUGF("metadata error: smaf unsupport codetype: %d\n", buf[2]); + return false; + } + + size -= 5; + while ((id3->title == NULL || id3->artist == NULL || id3->composer == NULL) + && (size > 0 && csize > 0)) + { + if (read(fd, buf, 3) < 3) { - numbytes = get_long_be(buf + 4) - 3; - totalsamples = (numbytes << 3) / (bitspersample * channels); + DEBUGF("metadata error: smaf contents field is too small\n"); + return false; + } + if (buf[2] != ':') + { + DEBUGF("metadata error: smaf illegal tag format %c%c%c\n", + buf[0], buf[1], buf[2]); + return false; + } + switch (CONTENTS_TAG(buf)) + { + case TAG_TITLE: + if (!read_option(fd, codepage, cbuf, csize, &dsize, &rsize)) + return false; + + id3->title = cbuf; + break; + case TAG_ARTIST: + if (!read_option(fd, codepage, cbuf, csize, &dsize, &rsize)) + return false; + + id3->artist = cbuf; + break; + case TAG_COMPOSER: + if (!read_option(fd, codepage, cbuf, csize, &dsize, &rsize)) + return false; + + id3->composer = cbuf; + break; + default: + if (!read_option(fd, codepage, NULL, csize, &dsize, &rsize)) + return false; + rsize = 0; + break; + } + cbuf += rsize; + csize -= rsize; + size -= (dsize + 3); + } + return true; +} - /* Calculate track length (in ms) and estimate the bitrate (in kbit/s) */ - id3->length = ((int64_t)totalsamples * 1000LL) / id3->frequency; +static bool parse_smaf_score_track_contents(int fd, struct mp3entry *id3) +{ + /* temporary buffer */ + unsigned char *buf = (unsigned char *)id3->path; + /* contents stored buffer */ + unsigned char *cbuf = id3->id3v2buf; + char codepage; + int csize = sizeof(id3->id3v2buf); + int dsize; + int rsize; + int size; + + if (read(fd, buf, 8) < 8) + { + DEBUGF("metadata error: smaf contents field is too small\n"); + return false; + } + if (memcmp(buf, "Dch", 3) != 0) + { + DEBUGF("metadata error: smaf does not include Dch chunk\n"); + return false; + } + codepage = convert_smaf_codetype(buf[3]); + if (codepage < 0) + { + DEBUGF("metadata error: smaf unsupport codetype: %d\n", buf[3]); + return false; + } - return true; + size = get_long_be(buf + 4); + while ((id3->title == NULL || id3->artist == NULL || id3->composer == NULL) + && (size > 0 && csize > 0)) + { + if (read(fd, buf, 4) < 4) + { + DEBUGF("metadata error: smaf contents field is too small\n"); + return false; + } + + dsize = CONTENTS_SIZE(buf); + + switch (CONTENTS_TAG(buf)) + { + case TAG_TITLE: + if (!read_data(fd, codepage, dsize, cbuf, csize, &rsize)) + return false; + + id3->title = cbuf; + break; + case TAG_ARTIST: + if (!read_data(fd, codepage, dsize, cbuf, csize, &rsize)) + return false; + + id3->artist = cbuf; + break; + case TAG_COMPOSER: + if (!read_data(fd, codepage, dsize, cbuf, csize, &rsize)) + return false; + + id3->composer = cbuf; + break; + default: + lseek(fd, dsize, SEEK_CUR); + rsize = 0; + break; } - buf += chunksize; + cbuf += rsize; + csize -= rsize; + size -= (dsize + 4); + } + + return true; +} + +static bool set_length(struct mp3entry *id3, unsigned char ch, unsigned char basebit, + long numbytes) +{ + unsigned char channels = (ch >> 7) + 1; + unsigned char bitspersample = convert_smaf_audio_basebit(basebit); + + if (bitspersample == 0) + { + DEBUGF("metadata error: smaf unsupport basebit %d\n", basebit); + return false; + } + if (id3->frequency == 0) + { + DEBUGF("metadata error: smaf frequency is zero\n"); + return false; + } + + /* Calculate track length [ms] */ + id3->length = ((uint64_t)numbytes * 8000LL) + / (bitspersample * channels * id3->frequency); + + return true; +} + +static bool get_smaf_metadata_audio_track(int fd, struct mp3entry *id3, + unsigned long pos) +{ + /* temporary buffer */ + unsigned char *buf = (unsigned char *)id3->path; + unsigned char basebit; + unsigned char channels; + unsigned long chunksize; + + if (read(fd, buf, 6) < 6) + { + DEBUGF("metadata error: smaf contents field is too small\n"); + return false; + } + pos += 6; + + channels = buf[2]; + basebit = buf[3] >> 4; + id3->frequency = convert_smaf_audio_frequency(buf[2] & 0x0f); + + while (pos < id3->filesize) + { + if (read(fd, buf, 8) < 8) + { + DEBUGF("metadata error: smaf contents field is too small\n"); + return false; + } + chunksize = get_long_be(buf + 4); + if (memcmp(buf, "Awa", 3) == 0) + return set_length(id3, channels, basebit, chunksize); + + lseek(fd, chunksize, SEEK_CUR); + pos += (chunksize + 8); } - DEBUGF("metada error: smaf does not include pcm audio data\n"); + DEBUGF("metadata error: smaf does not include pcm audio data\n"); return false; } -static bool get_smaf_metadata_score_track(struct mp3entry *id3, - unsigned char* buf, unsigned char *endbuf) +static bool get_smaf_metadata_score_track(int fd, struct mp3entry *id3, + int smaftype, unsigned long pos) { - int bitspersample; - int channels; - int chunksize; - long numbytes; - unsigned long totalsamples; + /* temporary buffer */ + unsigned char *buf = (unsigned char *)id3->path; + unsigned long chunksize; /* - * skip to the next chunk. - * MA-2/MA-3/MA-5: padding 16 bytes - * MA-7: padding 32 bytes + * chunksize + * MA-2/MA-3/MA-5: 20 bytes + * MA-7: 36 bytes */ - if (buf[3] < 7) - buf += 28; - else - buf += 44; + chunksize = (smaftype < 7)? 20 : 36; + lseek(fd, chunksize, SEEK_CUR); + pos += chunksize; - while (buf + 10 < endbuf) + while (pos < id3->filesize) { - chunksize = get_long_be(buf + 4) + 8; - if (memcmp(buf, "Mtsp", 4) == 0) + if (read(fd, buf, 8) < 8) { - buf += 8; - if (memcmp(buf, "Mwa", 3) != 0) + DEBUGF("metadata error: smaf contents field is too small\n"); + return false; + } + pos += 8; + if (memcmp(buf, "Mtsp", 4) != 0) + { + chunksize = get_long_be(buf + 4); + lseek(fd, chunksize, SEEK_CUR); + pos += chunksize; + } + else + { + if (read(fd, buf, 11) < 11) { - DEBUGF("metada error: smaf unsupport format: %c%c%c%c\n", - buf[0], buf[1], buf[2], buf[3]); + DEBUGF("metadata error: smaf contents field is too small\n"); return false; } - - channels = ((buf[8] & 0x80) >> 7) + 1; - bitspersample = convert_smaf_audio_basebit(buf[8] & 0x0f); - if (bitspersample == 0) + if (memcmp(buf, "Mwa", 3) != 0) { - DEBUGF("metada error: smaf unsupport basebit %d\n", buf[8] & 0x0f); + DEBUGF("metadata error: smaf unsupport format: %c%c%c%c\n", + buf[0], buf[1], buf[2], buf[3]); return false; } - numbytes = get_long_be(buf + 4) - 3; - totalsamples = numbytes * 8 / (bitspersample * channels); - id3->frequency = (buf[9] << 8) | buf[10]; - - /* Calculate track length (in ms) and estimate the bitrate (in kbit/s) */ - id3->length = ((int64_t) totalsamples * 1000) / id3->frequency; - - return true; + return set_length(id3, buf[8], buf[8] & 0x0f, get_long_be(buf + 4) - 3); } - buf += chunksize; } - DEBUGF("metada error: smaf does not include pcm audio data\n"); + DEBUGF("metadata error: smaf does not include pcm audio data\n"); return false; } bool get_smaf_metadata(int fd, struct mp3entry* id3) { - unsigned char smafbuf[1024]; + /* temporary buffer */ + unsigned char *buf = (unsigned char *)id3->path; + unsigned long csize; + unsigned long pos; - /* Use the trackname part of the id3 structure as a temporary buffer */ - unsigned char* buf = (unsigned char *)id3->path; - unsigned char *endbuf = smafbuf + sizeof(smafbuf); - int i; - int contents_size; - int codepage = ISO_8859_1; - - id3->title = NULL; - id3->artist = NULL; + id3->title = NULL; + id3->artist = NULL; id3->composer = NULL; - id3->vbr = false; /* All SMAF files are CBR */ + id3->vbr = false; /* All SMAF files are CBR */ id3->filesize = filesize(fd); - /* get RIFF chunk header */ - if ((lseek(fd, 0, SEEK_SET) < 0) || (read(fd, buf, 21) < 21)) + /* get SMAF magic and CNTI chunk */ + if ((lseek(fd, 0, SEEK_SET) < 0) || (read(fd, buf, 16) < 16)) { return false; } - if ((memcmp(buf, "MMMD", 4) != 0) || (memcmp(&buf[8], "CNTI", 4) != 0)) + if ((memcmp(buf, "MMMD", 4) != 0) || (memcmp(buf + 8, "CNTI", 4) != 0)) { - DEBUGF("metada error: does not smaf format\n"); + DEBUGF("metadata error: does not smaf format\n"); return false; } - contents_size = get_long_be(buf + 12); - if (contents_size < 5) + csize = get_long_be(buf + 12); + if (csize < 5) { - DEBUGF("metada error: CNTI chunk size is small %d\n", contents_size); + DEBUGF("metadata error: CNTI chunk size is small %ld\n", csize); return false; } - contents_size -= 5; - i = contents_size; - if (i == 0) + if (csize == 5) { - read(fd, buf, 16); - if (memcmp(buf, "OPDA", 4) != 0) + if (read(fd, buf, 13) < 13) { - DEBUGF("metada error: smaf does not include OPDA chunk\n"); + DEBUGF("metadata error: smaf contents field is too small\n"); return false; } - contents_size = get_long_be(buf + 4) - 8; - - if (memcmp(buf + 8, "Dch", 3) != 0) + if (memcmp(buf + 5, "OPDA", 4) != 0) { - DEBUGF("metada error: smaf does not include Dch chunk\n"); - return false; - } - codepage = convert_smaf_codetype(buf[11]); - if (codepage < 0) - { - DEBUGF("metada error: smaf unsupport codetype: %d\n", buf[11]); + DEBUGF("metadata error: smaf does not include OPDA chunk\n"); return false; } - i = get_long_be(buf + 12); + csize = get_long_be(buf + 9) + 13; - if (i > MAX_PATH) - { - DEBUGF("metada warning: smaf contents size is big %d\n", i); - i = MAX_PATH; - } - if (read(fd, buf, i) < i) + if (!parse_smaf_score_track_contents(fd, id3)) return false; + } + else if (!parse_smaf_audio_track_contents(fd, id3, csize)) + return false; - /* title */ - if (read_datachunk(buf, i, TAG_TITLE, codepage, id3->id3v1buf[0])) - id3->title = id3->id3v1buf[0]; - - /* artist */ - if (read_datachunk(buf, i, TAG_ARTIST, codepage, id3->id3v1buf[1])) - id3->artist = id3->id3v1buf[1]; + pos = 16 + csize; + lseek(fd, pos, SEEK_SET); - /* composer */ - if (read_datachunk(buf, i, TAG_COMPOSER, codepage, id3->id3v1buf[2])) - id3->composer = id3->id3v1buf[2]; - } - else + while (pos < id3->filesize) { - codepage = convert_smaf_codetype(buf[14]); - if (codepage < 0) + if (read(fd, buf, 8) < 8) { - DEBUGF("metada error: smaf unsupport codetype: %d\n", buf[11]); + DEBUGF("metadata error: smaf contents field is too small\n"); return false; } - if (i > MAX_PATH) - { - DEBUGF("metada warning: smaf contents size is big %d\n", i); - i = MAX_PATH; - } - if (read(fd, buf, i) < i) - return false; - - /* title */ - if (read_option(buf, i, TAG_TITLE, codepage, id3->id3v1buf[0])) - id3->title = id3->id3v1buf[0]; - - /* artist */ - if (read_option(buf, i, TAG_ARTIST, codepage, id3->id3v1buf[1])) - id3->artist = id3->id3v1buf[1]; - - /* composer */ - if (read_option(buf, i, TAG_COMPOSER, codepage, id3->id3v1buf[2])) - id3->composer = id3->id3v1buf[2]; - } - - if (contents_size > i) - lseek(fd, contents_size - i, SEEK_CUR); - - /* assume the SMAF pcm data position is near the start */ - if (read(fd, smafbuf, sizeof(smafbuf)) < (ssize_t)sizeof(smafbuf)) - return false; - - buf = smafbuf; - while (buf + 8 < endbuf) - { - i = get_long_be(buf + 4) + 8; - if (memcmp(buf, "ATR", 3) == 0) - return get_smaf_metadata_audio_track(id3, buf, endbuf); + return get_smaf_metadata_audio_track(fd, id3, pos); else if (memcmp(buf, "MTR", 3) == 0) - return get_smaf_metadata_score_track(id3, buf, endbuf); + return get_smaf_metadata_score_track(fd, id3, buf[3], pos); - buf += i; + csize = get_long_be(buf + 4); + pos += (csize + 8); + lseek(fd, csize, SEEK_CUR); } - DEBUGF("metada error: smaf does not include track chunk\n"); + DEBUGF("metadata error: smaf does not include track chunk\n"); return false; }