diff options
-rw-r--r-- | apps/playback.c | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/apps/playback.c b/apps/playback.c index 87287e57ab..3a9f229e15 100644 --- a/apps/playback.c +++ b/apps/playback.c | |||
@@ -572,6 +572,9 @@ bool audio_load_track(int offset, bool start_play, int peek_offset) | |||
572 | off_t size; | 572 | off_t size; |
573 | int rc, i; | 573 | int rc, i; |
574 | int copy_n; | 574 | int copy_n; |
575 | /* Used by the FLAC metadata parser */ | ||
576 | unsigned long totalsamples; | ||
577 | unsigned char* buf; | ||
575 | 578 | ||
576 | if (track_count >= MAX_TRACK) | 579 | if (track_count >= MAX_TRACK) |
577 | return false; | 580 | return false; |
@@ -638,6 +641,70 @@ bool audio_load_track(int offset, bool start_play, int peek_offset) | |||
638 | tracks[track_widx].taginfo_ready = true; | 641 | tracks[track_widx].taginfo_ready = true; |
639 | break ; | 642 | break ; |
640 | 643 | ||
644 | case AFMT_FLAC: | ||
645 | /* A simple parser to read vital metadata from a FLAC file - length, frequency, bitrate etc. */ | ||
646 | /* This code should either be moved to a seperate file, or discarded in favour of the libFLAC code */ | ||
647 | /* The FLAC stream specification can be found at http://flac.sourceforge.net/format.html#stream */ | ||
648 | |||
649 | /* Use the trackname part of the id3 structure as a temporary buffer */ | ||
650 | buf=tracks[track_widx].id3.path; | ||
651 | |||
652 | lseek(fd, 0, SEEK_SET); | ||
653 | |||
654 | rc = read(fd, buf, 4); | ||
655 | if (rc < 4) { | ||
656 | close(fd); | ||
657 | return false; | ||
658 | } | ||
659 | |||
660 | if (memcmp(buf,"fLaC",4)!=0) { | ||
661 | logf("%s is not a FLAC file\n",trackname); | ||
662 | close(fd); | ||
663 | return(false); | ||
664 | } | ||
665 | |||
666 | while (1) { | ||
667 | rc = read(fd, buf, 4); | ||
668 | i = (buf[1]<<16)|(buf[2]<<8)|buf[3]; /* The length of the block */ | ||
669 | |||
670 | if ((buf[0]&0x7f)==0) { /* 0 is the STREAMINFO block */ | ||
671 | rc = read(fd, buf, i); /* FIXME: Don't trust the value of i */ | ||
672 | if (rc < 0) { | ||
673 | close(fd); | ||
674 | return false; | ||
675 | } | ||
676 | tracks[track_widx].id3.vbr=true; /* All FLAC files are VBR */ | ||
677 | tracks[track_widx].id3.filesize=filesize(fd); | ||
678 | |||
679 | tracks[track_widx].id3.frequency=(buf[10]<<12)|(buf[11]<<4)|((buf[12]&0xf0)>>4); | ||
680 | |||
681 | /* NOT NEEDED: bitspersample=(((buf[12]&0x01)<<4)|((buf[13]&0xf0)>>4))+1; */ | ||
682 | |||
683 | /* totalsamples is a 36-bit field, but we assume <= 32 bits are used */ | ||
684 | totalsamples=(buf[14]<<24)|(buf[15]<<16)|(buf[16]<<8)|buf[17]; | ||
685 | |||
686 | /* Calculate track length (in ms) and estimate the bitrate (in kbit/s) */ | ||
687 | tracks[track_widx].id3.length=(totalsamples/tracks[track_widx].id3.frequency)*1000; | ||
688 | tracks[track_widx].id3.bitrate=(filesize(fd)*8)/tracks[track_widx].id3.length; | ||
689 | } else if ((buf[0]&0x7f)==4) { /* 4 is the VORBIS_COMMENT block */ | ||
690 | |||
691 | /* The next i bytes of the file contain the VORBIS COMMENTS - just skip them for now. */ | ||
692 | lseek(fd, i, SEEK_CUR); | ||
693 | |||
694 | } else { | ||
695 | if (buf[0]&0x80) { /* If we have reached the last metadata block, abort. */ | ||
696 | break; | ||
697 | } else { | ||
698 | lseek(fd, i, SEEK_CUR); /* Skip to next metadata block */ | ||
699 | } | ||
700 | } | ||
701 | } | ||
702 | |||
703 | lseek(fd, 0, SEEK_SET); | ||
704 | strncpy(tracks[track_widx].id3.path,trackname,sizeof(tracks[track_widx].id3.path)); | ||
705 | tracks[track_widx].taginfo_ready = true; | ||
706 | break; | ||
707 | |||
641 | /* If we don't know how to read the metadata, just store the filename */ | 708 | /* If we don't know how to read the metadata, just store the filename */ |
642 | default: | 709 | default: |
643 | strncpy(tracks[track_widx].id3.path,trackname,sizeof(tracks[track_widx].id3.path)); | 710 | strncpy(tracks[track_widx].id3.path,trackname,sizeof(tracks[track_widx].id3.path)); |