1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2010 Yoshihisa Uchida
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
24 #include "string-extra.h"
27 #include "metadata_common.h"
28 #include "metadata_parsers.h"
29 #include "rbunicode.h"
32 static const int basebits
[4] = { 4, 8, 12, 16 };
34 static const int frequency
[5] = { 4000, 8000, 11025, 22050, 44100 };
36 static const int support_codepages
[5] = {
37 #ifdef HAVE_LCD_BITMAP
38 SJIS
, ISO_8859_1
, -1, GB_2312
, BIG_5
,
40 -1, ISO_8859_1
, -1, -1, -1,
45 #define UCS2 (NUM_CODEPAGES + 1)
48 #define TAG_TITLE (('S'<<8)|'T')
49 #define TAG_ARTIST (('A'<<8)|'N')
50 #define TAG_COMPOSER (('S'<<8)|'W')
52 /* convert functions */
53 #define CONVERT_SMAF_CHANNELS(c) (((c) >> 7) + 1)
56 static inline int convert_smaf_audio_basebit(unsigned int basebit
)
60 return basebits
[basebit
];
63 static inline int convert_smaf_audio_frequency(unsigned int freq
)
67 return frequency
[freq
];
70 static int convert_smaf_codetype(unsigned int codetype
)
73 return support_codepages
[codetype
];
74 else if (codetype
== 0x20 || codetype
== 0x24) /* In Rockbox, UCS2 and UTF-16 are same. */
76 else if (codetype
== 0x23)
78 else if (codetype
== 0xff)
83 static void set_length(struct mp3entry
*id3
, unsigned int ch
, unsigned int basebit
,
84 unsigned int numbytes
)
86 int bitspersample
= convert_smaf_audio_basebit(basebit
);
88 if (bitspersample
!= 0 && id3
->frequency
!= 0)
90 /* Calculate track length [ms] and bitrate [kbit/s] */
91 id3
->length
= (uint64_t)numbytes
* 8000LL
92 / (bitspersample
* CONVERT_SMAF_CHANNELS(ch
) * id3
->frequency
);
93 id3
->bitrate
= bitspersample
* id3
->frequency
/ 1000;
96 /* output contents/wave data/id3 info (for debug) */
97 DEBUGF("contents info ----\n");
98 DEBUGF(" TITLE: %s\n", (id3
->title
)? id3
->title
: "(NULL)");
99 DEBUGF(" ARTIST: %s\n", (id3
->artist
)? id3
->artist
: "(NULL)");
100 DEBUGF(" COMPOSER: %s\n", (id3
->composer
)? id3
->composer
: "(NULL)");
101 DEBUGF("wave data info ----\n");
102 DEBUGF(" channels: %u\n", CONVERT_SMAF_CHANNELS(ch
));
103 DEBUGF(" bitspersample: %d\n", bitspersample
);
104 DEBUGF(" numbytes; %u\n", numbytes
);
105 DEBUGF("id3 info ----\n");
106 DEBUGF(" frquency: %u\n", (unsigned int)id3
->frequency
);
107 DEBUGF(" bitrate: %d\n", id3
->bitrate
);
108 DEBUGF(" length: %u\n", (unsigned int)id3
->length
);
111 /* contents parse functions */
114 * 1) When the codepage is UTF-8 or UCS2, contents data do not start BOM.
115 * 2) The byte order of contents data is big endian.
118 static void decode2utf8(const unsigned char *src
, unsigned char **dst
,
119 int srcsize
, int *dstsize
, int codepage
)
121 unsigned char tmpbuf
[srcsize
* 3 + 1];
125 if (codepage
< NUM_CODEPAGES
)
126 p
= iso_decode(src
, tmpbuf
, codepage
, srcsize
);
127 else /* codepage == UCS2 */
128 p
= utf16BEdecode(src
, tmpbuf
, srcsize
);
132 strlcpy(*dst
, tmpbuf
, *dstsize
);
133 utf8size
= (p
- tmpbuf
) + 1;
134 if (utf8size
> *dstsize
)
136 DEBUGF("metadata warning: data length: %d > contents store buffer size: %d\n",
141 *dstsize
-= utf8size
;
144 static int read_audio_track_contets(int fd
, int codepage
, unsigned char **dst
,
147 /* value length <= 256 bytes */
148 unsigned char buf
[256];
149 unsigned char *p
= buf
;
150 unsigned char *q
= buf
;
155 while (p
- buf
< 256 && *p
!= ',')
158 if (codepage
!= UCS2
)
163 else if (*p
== '\0' && *(p
+1) == '\\')
168 if (codepage
== UTF_8
)
170 while ((*p
& MASK
) != COMP
)
173 #ifdef HAVE_LCD_BITMAP
174 else if (codepage
== SJIS
)
176 if (*p
<= 0xa0 || *p
>= 0xe0)
183 if (codepage
== UCS2
)
186 datasize
= p
- buf
+ 1;
187 lseek(fd
, datasize
- 256, SEEK_CUR
);
190 decode2utf8(buf
, dst
, q
- buf
, dstsize
, codepage
);
195 static void read_score_track_contets(int fd
, int codepage
, int datasize
,
196 unsigned char **dst
, int *dstsize
)
198 unsigned char buf
[datasize
];
200 read(fd
, buf
, datasize
);
201 decode2utf8(buf
, dst
, datasize
, dstsize
, codepage
);
204 /* traverse chunk functions */
206 static unsigned int search_chunk(int fd
, const unsigned char *name
, int nlen
)
208 unsigned char buf
[8];
209 unsigned int chunksize
;
211 while (read(fd
, buf
, 8) > 0)
213 chunksize
= get_long_be(buf
+ 4);
214 if (memcmp(buf
, name
, nlen
) == 0)
217 lseek(fd
, chunksize
, SEEK_CUR
);
219 DEBUGF("metadata error: missing '%s' chunk\n", name
);
223 static bool parse_smaf_audio_track(int fd
, struct mp3entry
*id3
, unsigned int datasize
)
225 /* temporary buffer */
226 unsigned char *tmp
= (unsigned char*)id3
->path
;
227 /* contents stored buffer */
228 unsigned char *buf
= id3
->id3v2buf
;
229 int bufsize
= sizeof(id3
->id3v2buf
);
231 unsigned int chunksize
= datasize
;
236 /* parse contents info */
238 codepage
= convert_smaf_codetype(tmp
[2]);
241 DEBUGF("metadata error: smaf unsupport codetype: %d\n", tmp
[2]);
246 while ((id3
->title
== NULL
|| id3
->artist
== NULL
|| id3
->composer
== NULL
)
247 && (datasize
> 0 && bufsize
> 0))
249 if (read(fd
, tmp
, 3) <= 0)
254 DEBUGF("metadata error: illegal tag: %c%c%c\n", tmp
[0], tmp
[1], tmp
[2]);
257 switch ((tmp
[0]<<8)|tmp
[1])
261 valsize
= read_audio_track_contets(fd
, codepage
, &buf
, &bufsize
);
265 valsize
= read_audio_track_contets(fd
, codepage
, &buf
, &bufsize
);
269 valsize
= read_audio_track_contets(fd
, codepage
, &buf
, &bufsize
);
272 valsize
= read_audio_track_contets(fd
, codepage
, NULL
, &bufsize
);
275 datasize
-= (valsize
+ 3);
278 /* search PCM Audio Track Chunk */
279 lseek(fd
, 16 + chunksize
, SEEK_SET
);
281 chunksize
= search_chunk(fd
, "ATR", 3);
284 DEBUGF("metadata error: missing PCM Audio Track Chunk\n");
293 * +2: bit 7 0:mono/1:stereo, bit 4-6 format, bit 0-3: frequency
294 * +3: bit 4-7: base bit
298 * Note: If PCM Audio Track does not include Sequence Data Chunk,
299 * tmp+6 is the start position of Wave Data Chunk.
303 /* search Wave Data Chunk */
304 chunksize
= search_chunk(fd
, "Awa", 3);
307 DEBUGF("metadata error: missing Wave Data Chunk\n");
311 /* set track length and bitrate */
312 id3
->frequency
= convert_smaf_audio_frequency(tmp
[2] & 0x0f);
313 set_length(id3
, tmp
[2], tmp
[3] >> 4, chunksize
);
317 static bool parse_smaf_score_track(int fd
, struct mp3entry
*id3
)
319 /* temporary buffer */
320 unsigned char *tmp
= (unsigned char*)id3
->path
;
321 unsigned char *p
= tmp
;
322 /* contents stored buffer */
323 unsigned char *buf
= id3
->id3v2buf
;
324 int bufsize
= sizeof(id3
->id3v2buf
);
326 unsigned int chunksize
;
327 unsigned int datasize
;
332 /* parse Optional Data Chunk */
334 if (memcmp(tmp
+ 5, "OPDA", 4) != 0)
336 DEBUGF("metadata error: missing Optional Data Chunk\n");
340 /* Optional Data Chunk size */
341 chunksize
= get_long_be(tmp
+ 9);
343 /* parse Data Chunk */
344 if (memcmp(tmp
+ 13, "Dch", 3) != 0)
346 DEBUGF("metadata error: missing Data Chunk\n");
350 codepage
= convert_smaf_codetype(tmp
[16]);
353 DEBUGF("metadata error: smaf unsupport codetype: %d\n", tmp
[16]);
357 /* Data Chunk size */
358 datasize
= get_long_be(tmp
+ 17);
359 while ((id3
->title
== NULL
|| id3
->artist
== NULL
|| id3
->composer
== NULL
)
360 && (datasize
> 0 && bufsize
> 0))
362 if (read(fd
, tmp
, 4) <= 0)
365 valsize
= (tmp
[2] << 8) | tmp
[3];
366 datasize
-= (valsize
+ 4);
367 switch ((tmp
[0]<<8)|tmp
[1])
371 read_score_track_contets(fd
, codepage
, valsize
, &buf
, &bufsize
);
375 read_score_track_contets(fd
, codepage
, valsize
, &buf
, &bufsize
);
379 read_score_track_contets(fd
, codepage
, valsize
, &buf
, &bufsize
);
382 lseek(fd
, valsize
, SEEK_CUR
);
387 /* search Score Track Chunk */
388 lseek(fd
, 29 + chunksize
, SEEK_SET
);
390 if (search_chunk(fd
, "MTR", 3) == 0)
392 DEBUGF("metadata error: missing Score Track Chunk\n");
398 * usually, next chunk ('M***') found within 40 bytes.
401 read(fd
, tmp
, chunksize
);
403 tmp
[chunksize
] = 'M'; /* stopper */
407 chunksize
-= (p
- tmp
);
410 DEBUGF("metadata error: missing Score Track Stream PCM Data Chunk");
414 /* search Score Track Stream PCM Data Chunk */
415 lseek(fd
, -chunksize
, SEEK_CUR
);
416 if (search_chunk(fd
, "Mtsp", 4) == 0)
418 DEBUGF("metadata error: missing Score Track Stream PCM Data Chunk\n");
423 * parse Score Track Stream Wave Data Chunk
425 * +4-7: chunk size (WaveType(3bytes) + wave data count)
426 * +8: bit 7 0:mono/1:stereo, bit 4-6 format, bit 0-3: base bit
427 * +9: frequency (MSB)
428 * +10: frequency (LSB)
431 if (memcmp(tmp
, "Mwa", 3) != 0)
433 DEBUGF("metadata error: missing Score Track Stream Wave Data Chunk\n");
437 /* set track length and bitrate */
438 id3
->frequency
= (tmp
[9] << 8) | tmp
[10];
439 set_length(id3
, tmp
[8], tmp
[8] & 0x0f, get_long_be(tmp
+ 4) - 3);
443 bool get_smaf_metadata(int fd
, struct mp3entry
* id3
)
445 /* temporary buffer */
446 unsigned char *tmp
= (unsigned char *)id3
->path
;
447 unsigned int chunksize
;
451 id3
->composer
= NULL
;
453 id3
->vbr
= false; /* All SMAF files are CBR */
454 id3
->filesize
= filesize(fd
);
456 /* check File Chunk and Contents Info Chunk */
457 lseek(fd
, 0, SEEK_SET
);
459 if ((memcmp(tmp
, "MMMD", 4) != 0) || (memcmp(tmp
+ 8, "CNTI", 4) != 0))
461 DEBUGF("metadata error: does not smaf format\n");
465 chunksize
= get_long_be(tmp
+ 12);
467 return parse_smaf_audio_track(fd
, id3
, chunksize
);
469 return parse_smaf_score_track(fd
, id3
);