summaryrefslogtreecommitdiff
path: root/firmware/id3.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/id3.c')
-rw-r--r--firmware/id3.c166
1 files changed, 109 insertions, 57 deletions
diff --git a/firmware/id3.c b/firmware/id3.c
index 7344bf53c7..d783053426 100644
--- a/firmware/id3.c
+++ b/firmware/id3.c
@@ -41,6 +41,7 @@
41#include "id3.h" 41#include "id3.h"
42#include "mp3data.h" 42#include "mp3data.h"
43#include "system.h" 43#include "system.h"
44#include "replaygain.h"
44 45
45#define UNSYNC(b0,b1,b2,b3) (((long)(b0 & 0x7F) << (3*7)) | \ 46#define UNSYNC(b0,b1,b2,b3) (((long)(b0 & 0x7F) << (3*7)) | \
46 ((long)(b1 & 0x7F) << (2*7)) | \ 47 ((long)(b1 & 0x7F) << (2*7)) | \
@@ -163,6 +164,10 @@ char* id3_get_codec(const struct mp3entry* id3)
163 Many ID3 symbolic names come in more than one form. You can add both 164 Many ID3 symbolic names come in more than one form. You can add both
164 forms, each referencing the same variable in struct mp3entry. 165 forms, each referencing the same variable in struct mp3entry.
165 If both forms are present, the last found will be used. 166 If both forms are present, the last found will be used.
167 Note that the offset can be zero, in which case no entry will be set
168 in the mp3entry struct; the frame is still read into the buffer and
169 the special processing function is called (several times, if there
170 are several frames with the same name).
166 171
167 4. Alternately, use the TAG_LIST_ENTRY macro with 172 4. Alternately, use the TAG_LIST_ENTRY macro with
168 ID3 tag symbolic name, 173 ID3 tag symbolic name,
@@ -305,6 +310,34 @@ static int parsegenre( struct mp3entry* entry, char* tag, int bufferpos )
305 } 310 }
306} 311}
307 312
313#if CONFIG_HWCODEC == MASNONE
314/* parse user defined text, looking for replaygain information. */
315static int parseuser( struct mp3entry* entry, char* tag, int bufferpos )
316{
317 char* value = NULL;
318 int desc_len = strlen(tag);
319 int value_len = 0;
320
321 if ((tag - entry->id3v2buf + desc_len + 2) < bufferpos) {
322 /* At least part of the value was read, so we can safely try to
323 * parse it
324 */
325
326 value = tag + desc_len + 1;
327 value_len = parse_replaygain(tag, value, entry, tag,
328 bufferpos - (tag - entry->id3v2buf));
329 }
330
331 if (value_len) {
332 bufferpos = tag - entry->id3v2buf + value_len;
333 } else {
334 bufferpos = tag - entry->id3v2buf;
335 }
336
337 return bufferpos;
338}
339#endif
340
308static const struct tag_resolver taglist[] = { 341static const struct tag_resolver taglist[] = {
309 { "TPE1", 4, offsetof(struct mp3entry, artist), NULL }, 342 { "TPE1", 4, offsetof(struct mp3entry, artist), NULL },
310 { "TP1", 3, offsetof(struct mp3entry, artist), NULL }, 343 { "TP1", 3, offsetof(struct mp3entry, artist), NULL },
@@ -319,6 +352,9 @@ static const struct tag_resolver taglist[] = {
319 { "TCOM", 4, offsetof(struct mp3entry, composer), NULL }, 352 { "TCOM", 4, offsetof(struct mp3entry, composer), NULL },
320 { "TCON", 4, offsetof(struct mp3entry, genre_string), &parsegenre }, 353 { "TCON", 4, offsetof(struct mp3entry, genre_string), &parsegenre },
321 { "TCO", 3, offsetof(struct mp3entry, genre_string), &parsegenre }, 354 { "TCO", 3, offsetof(struct mp3entry, genre_string), &parsegenre },
355#if CONFIG_HWCODEC == MASNONE
356 { "TXXX", 4, 0, &parseuser },
357#endif
322}; 358};
323 359
324#define TAGLIST_SIZE ((int)(sizeof(taglist) / sizeof(taglist[0]))) 360#define TAGLIST_SIZE ((int)(sizeof(taglist) / sizeof(taglist[0])))
@@ -327,12 +363,12 @@ static const struct tag_resolver taglist[] = {
327 string. If it is, we attempt to convert it to a 8-bit ASCII string 363 string. If it is, we attempt to convert it to a 8-bit ASCII string
328 (for valid 8-bit ASCII characters). If it's not unicode, we leave 364 (for valid 8-bit ASCII characters). If it's not unicode, we leave
329 it alone. At some point we should fully support unicode strings */ 365 it alone. At some point we should fully support unicode strings */
330static int unicode_munge(char** string, int *len) { 366static int unicode_munge(char* string, int *len) {
331 long tmp; 367 long tmp;
332 bool le = false; 368 bool le = false;
333 int i; 369 int i;
334 char *str = *string; 370 char *str = string;
335 char *outstr = *string; 371 char *outstr = string;
336 bool bom = false; 372 bool bom = false;
337 int outlen; 373 int outlen;
338 374
@@ -343,8 +379,14 @@ static int unicode_munge(char** string, int *len) {
343 379
344 /* Type 0x00 is ordinary ISO 8859-1 */ 380 /* Type 0x00 is ordinary ISO 8859-1 */
345 if(str[0] == 0x00) { 381 if(str[0] == 0x00) {
346 (*len)--; 382 int i = --(*len);
347 (*string)++; /* Skip the encoding type byte */ 383
384 /* We must move the string to the left */
385 while (i--) {
386 string[0] = string[1];
387 string++;
388 }
389
348 return 0; 390 return 0;
349 } 391 }
350 392
@@ -352,53 +394,59 @@ static int unicode_munge(char** string, int *len) {
352 if(str[0] == 0x01 || str[0] == 0x02) { 394 if(str[0] == 0x01 || str[0] == 0x02) {
353 (*len)--; 395 (*len)--;
354 str++; 396 str++;
355 tmp = BYTES2INT(0, 0, str[0], str[1]);
356
357 /* Now check if there is a BOM (zero-width non-breaking space, 0xfeff)
358 and if it is in little or big endian format */
359 if(tmp == 0xfffe) { /* Little endian? */
360 bom = true;
361 le = true;
362 str += 2;
363 (*len)-=2;
364 }
365
366 if(tmp == 0xfeff) { /* Big endian? */
367 bom = true;
368 str += 2;
369 (*len)-=2;
370 }
371
372 /* If there is no BOM (which is a specification violation),
373 let's try to guess it. If one of the bytes is 0x00, it is
374 probably the most significant one. */
375 if(!bom) {
376 if(str[1] == 0)
377 le = true;
378 }
379
380 i = 0; 397 i = 0;
381 398
382 outlen = *len / 2; 399 /* Handle frames with more than one string (needed for TXXX frames).
383 400 */
384 do { 401 do {
385 if(le) { 402 tmp = BYTES2INT(0, 0, str[0], str[1]);
386 if(str[1]) 403
387 outstr[i++] = '.'; 404 /* Now check if there is a BOM (zero-width non-breaking space, 0xfeff)
388 else 405 and if it is in little or big endian format */
389 outstr[i++] = str[0]; 406 if(tmp == 0xfffe) { /* Little endian? */
390 } else { 407 bom = true;
391 if(str[0]) 408 le = true;
392 outstr[i++] = '.'; 409 str += 2;
393 else 410 (*len)-=2;
394 outstr[i++] = str[1]; 411 }
412
413 if(tmp == 0xfeff) { /* Big endian? */
414 bom = true;
415 str += 2;
416 (*len)-=2;
417 }
418
419 /* If there is no BOM (which is a specification violation),
420 let's try to guess it. If one of the bytes is 0x00, it is
421 probably the most significant one. */
422 if(!bom) {
423 if(str[1] == 0)
424 le = true;
395 } 425 }
426
427 outlen = *len / 2;
428
429 do {
430 if(le) {
431 if(str[1])
432 outstr[i++] = '.';
433 else
434 outstr[i++] = str[0];
435 } else {
436 if(str[0])
437 outstr[i++] = '.';
438 else
439 outstr[i++] = str[1];
440 }
441 str += 2;
442 } while((str[0] || str[1]) && (i < outlen));
443
396 str += 2; 444 str += 2;
397 } while((str[0] || str[1]) && (i < outlen)); 445 outstr[i++] = 0; /* Terminate the string */
446 } while(i < outlen);
398 447
399 *len = i; 448 *len = i - 1;
400 449
401 outstr[i] = 0; /* Terminate the string */
402 return 0; 450 return 0;
403 } 451 }
404 452
@@ -686,29 +734,33 @@ static void setid3v2title(int fd, struct mp3entry *entry)
686 734
687 for (i=0; i<TAGLIST_SIZE; i++) { 735 for (i=0; i<TAGLIST_SIZE; i++) {
688 const struct tag_resolver* tr = &taglist[i]; 736 const struct tag_resolver* tr = &taglist[i];
689 char** ptag = (char**) (((char*)entry) + tr->offset); 737 char** ptag = tr->offset ? (char**) (((char*)entry) + tr->offset)
738 : NULL;
690 char* tag; 739 char* tag;
691 740
692 if( !*ptag && !memcmp( header, tr->tag, tr->tag_length ) ) { 741 if( (!ptag || !*ptag) && !memcmp( header, tr->tag, tr->tag_length ) ) {
693 742
694 /* found a tag matching one in tagList, and not yet filled */ 743 /* found a tag matching one in tagList, and not yet filled */
744 tag = buffer + bufferpos;
745
695 if(global_unsynch && version <= ID3_VER_2_3) 746 if(global_unsynch && version <= ID3_VER_2_3)
696 bytesread = read_unsynched(fd, buffer + bufferpos, 747 bytesread = read_unsynched(fd, tag, framelen);
697 framelen);
698 else 748 else
699 bytesread = read(fd, buffer + bufferpos, framelen); 749 bytesread = read(fd, tag, framelen);
700 750
701 if( bytesread != framelen ) 751 if( bytesread != framelen )
702 return; 752 return;
703 753
704 size -= bytesread; 754 size -= bytesread;
705 *ptag = buffer + bufferpos; 755
706
707 if(unsynch || (global_unsynch && version >= ID3_VER_2_4)) 756 if(unsynch || (global_unsynch && version >= ID3_VER_2_4))
708 bytesread = unsynchronize_frame(*ptag, bytesread); 757 bytesread = unsynchronize_frame(tag, bytesread);
709 758
710 unicode_munge( ptag, &bytesread ); 759 unicode_munge( tag, &bytesread );
711 tag = *ptag; 760
761 if (ptag)
762 *ptag = tag;
763
712 /* remove trailing spaces */ 764 /* remove trailing spaces */
713 while ( bytesread > 0 && isspace(tag[bytesread-1])) 765 while ( bytesread > 0 && isspace(tag[bytesread-1]))
714 bytesread--; 766 bytesread--;