diff options
Diffstat (limited to 'apps')
-rw-r--r-- | apps/codecs/flac.c | 306 | ||||
-rw-r--r-- | apps/codecs/lib/xxx2wav.c | 25 | ||||
-rw-r--r-- | apps/codecs/lib/xxx2wav.h | 6 | ||||
-rw-r--r-- | apps/codecs/libFLAC/SOURCES | 1 | ||||
-rw-r--r-- | apps/codecs/libFLAC/include/FLAC/metadata.h | 8 | ||||
-rw-r--r-- | apps/codecs/vorbis.c | 15 | ||||
-rw-r--r-- | apps/metadata.c | 127 | ||||
-rw-r--r-- | apps/playback.c | 3 |
8 files changed, 310 insertions, 181 deletions
diff --git a/apps/codecs/flac.c b/apps/codecs/flac.c index 259686ed3f..0d21c3cdf1 100644 --- a/apps/codecs/flac.c +++ b/apps/codecs/flac.c @@ -20,6 +20,8 @@ #include "codec.h" #include <codecs/libFLAC/include/FLAC/seekable_stream_decoder.h> +#include <codecs/libFLAC/include/FLAC/format.h> +#include <codecs/libFLAC/include/FLAC/metadata.h> #include "playback.h" #include "lib/codeclib.h" #include "dsp.h" @@ -30,6 +32,10 @@ static struct codec_api* rb; static uint32_t samplesdone; +static FLAC__StreamMetadata *stream_info; +static FLAC__StreamMetadata *seek_table; +unsigned int metadata_length; + /* Called when the FLAC decoder needs some FLAC data to decode */ FLAC__SeekableStreamDecoderReadStatus flac_read_handler(const FLAC__SeekableStreamDecoder *dec, FLAC__byte buffer[], unsigned *bytes, void *data) @@ -49,9 +55,9 @@ static unsigned char pcmbuf[FLAC_MAX_SUPPORTED_BLOCKSIZE*FLAC_MAX_SUPPORTED_CHAN /* Called when the FLAC decoder has some decoded PCM data to write */ FLAC__StreamDecoderWriteStatus flac_write_handler(const FLAC__SeekableStreamDecoder *dec, - const FLAC__Frame *frame, - const FLAC__int32 * const buf[], - void *data) + const FLAC__Frame *frame, + const FLAC__int32 * const buf[], + void *data) { struct codec_api* ci = (struct codec_api*)data; (void)dec; @@ -92,10 +98,23 @@ FLAC__StreamDecoderWriteStatus flac_write_handler(const FLAC__SeekableStreamDeco void flac_metadata_handler(const FLAC__SeekableStreamDecoder *dec, const FLAC__StreamMetadata *meta, void *data) { - /* Ignore metadata for now... */ - (void)dec; - (void)meta; - (void)data; + /* Ignore metadata for now... */ + (void)dec; + (void)data; + + metadata_length += meta->length; + + if ( meta->type == FLAC__METADATA_TYPE_STREAMINFO ) { + stream_info = FLAC__metadata_object_clone( meta ); + if ( stream_info == NULL ) { + //return CODEC_ERROR; + } + } else if ( meta->type == FLAC__METADATA_TYPE_SEEKTABLE ) { + seek_table = FLAC__metadata_object_clone( meta ); + if ( seek_table == NULL ) { + //return CODEC_ERROR; + } + } } @@ -111,47 +130,47 @@ FLAC__SeekableStreamDecoderSeekStatus flac_seek_handler (const FLAC__SeekableStr FLAC__uint64 absolute_byte_offset, void *client_data) { - (void)decoder; - struct codec_api* ci = (struct codec_api*)client_data; + (void)decoder; + struct codec_api* ci = (struct codec_api*)client_data; - if (ci->seek_buffer(absolute_byte_offset)) { + if (ci->seek_buffer(absolute_byte_offset)) { return(FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK); - } else { + } else { return(FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR); - } + } } FLAC__SeekableStreamDecoderTellStatus flac_tell_handler (const FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data) { - struct codec_api* ci = (struct codec_api*)client_data; + struct codec_api* ci = (struct codec_api*)client_data; - (void)decoder; - *absolute_byte_offset=ci->curpos; - return(FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK); + (void)decoder; + *absolute_byte_offset=ci->curpos; + return(FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK); } FLAC__SeekableStreamDecoderLengthStatus flac_length_handler (const FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data) { - struct codec_api* ci = (struct codec_api*)client_data; + struct codec_api* ci = (struct codec_api*)client_data; - (void)decoder; - *stream_length=ci->filesize; - return(FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK); + (void)decoder; + *stream_length=ci->filesize; + return(FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK); } FLAC__bool flac_eof_handler (const FLAC__SeekableStreamDecoder *decoder, void *client_data) { - struct codec_api* ci = (struct codec_api*)client_data; + struct codec_api* ci = (struct codec_api*)client_data; - (void)decoder; - if (ci->curpos >= ci->filesize) { + (void)decoder; + if (ci->curpos >= ci->filesize) { return(true); - } else { + } else { return(false); - } + } } #ifndef SIMULATOR @@ -160,104 +179,193 @@ extern char iramstart[]; extern char iramend[]; #endif +FLAC__uint64 find_sample_number(size_t offset) +{ + FLAC__StreamMetadata_SeekPoint *points; + FLAC__uint64 prev_sample, next_sample; + size_t prev_offset, next_offset; + int percent; + + if ( offset >= (rb->id3->filesize - metadata_length)) { + return stream_info->data.stream_info.total_samples; + } + + prev_offset = 0; + prev_sample = 0; + next_offset = rb->id3->filesize - metadata_length; + next_sample = stream_info->data.stream_info.total_samples; + + if ( seek_table ) { + int left, right, middle; + + middle = 0; /* Silence compiler warnings */ + points = seek_table->data.seek_table.points; + left = 0; + right = seek_table->data.seek_table.num_points - 1; + + /* Do a binary search to find the matching seek point */ + while ( left <= right ) { + middle = (left + right) / 2; + + if ( (FLAC__uint64)offset < points[middle].stream_offset ) { + right = middle - 1; + } else if ( (FLAC__uint64)offset > points[middle].stream_offset ) { + left = middle + 1; + } else { + return points[middle].sample_number; + } + } + + /* Didn't find a matching seek point, so get the sample numbers of the + * seek points to the left and right of offset to make our guess more + * accurate. Accuracy depends on how close these sample numbers are to + * each other. + */ + if ( (unsigned)left >= seek_table->data.seek_table.num_points ) { + prev_offset = points[middle].stream_offset; + prev_sample = points[middle].sample_number; + } else if ( right < 0 ) { + next_offset = points[middle].stream_offset; + next_sample = points[middle].sample_number; + } else { + middle--; + prev_offset = points[middle].stream_offset; + prev_sample = points[middle].sample_number; + next_offset = points[middle+1].stream_offset; + next_sample = points[middle+1].sample_number; + } + } + + /* Either there's no seek table or we didn't find our seek point, so now we + * have to guess. + */ + percent = ((offset - prev_offset) * 100) / (next_offset - prev_offset); + return (FLAC__uint64)(percent * (next_sample - prev_sample) / 100 + prev_sample); +} + /* this is the codec entry point */ enum codec_status codec_start(struct codec_api* api) { struct codec_api* ci = api; FLAC__SeekableStreamDecoder* flacDecoder; + FLAC__uint64 offset; - /* Generic codec initialisation */ - TEST_CODEC_API(api); + /* Generic codec initialisation */ + TEST_CODEC_API(api); - /* if you are using a global api pointer, don't forget to copy it! - otherwise you will get lovely "I04: IllInstr" errors... :-) */ - rb = api; + /* if you are using a global api pointer, don't forget to copy it! + otherwise you will get lovely "I04: IllInstr" errors... :-) */ + rb = api; #ifndef SIMULATOR - rb->memcpy(iramstart, iramcopy, iramend-iramstart); + rb->memcpy(iramstart, iramcopy, iramend-iramstart); #endif - ci->configure(CODEC_SET_FILEBUF_LIMIT, (int *)(1024*1024*10)); - ci->configure(CODEC_SET_FILEBUF_WATERMARK, (int *)(1024*512)); - ci->configure(CODEC_SET_FILEBUF_CHUNKSIZE, (int *)(1024*128)); + ci->configure(CODEC_SET_FILEBUF_LIMIT, (int *)(1024*1024*10)); + ci->configure(CODEC_SET_FILEBUF_WATERMARK, (int *)(1024*512)); + ci->configure(CODEC_SET_FILEBUF_CHUNKSIZE, (int *)(1024*1024)); - ci->configure(DSP_DITHER, (bool *)false); - ci->configure(DSP_SET_STEREO_MODE, (int *)STEREO_INTERLEAVED); - ci->configure(DSP_SET_SAMPLE_DEPTH, (int *)(16)); + ci->configure(CODEC_DSP_ENABLE, (bool *)true); + ci->configure(DSP_DITHER, (bool *)false); + ci->configure(DSP_SET_STEREO_MODE, (int *)STEREO_INTERLEAVED); + ci->configure(DSP_SET_SAMPLE_DEPTH, (int *)(16)); - next_track: + next_track: - if (codec_init(api)) { - return CODEC_ERROR; - } + metadata_length = 0; + seek_table = NULL; + stream_info = NULL; - while (!rb->taginfo_ready) + if (codec_init(api)) { + return CODEC_ERROR; + } + + while (!rb->taginfo_ready) rb->yield(); - if (rb->id3->frequency != NATIVE_FREQUENCY) { - rb->configure(DSP_SET_FREQUENCY, (long *)(rb->id3->frequency)); - rb->configure(CODEC_DSP_ENABLE, (bool *)true); - } else { - rb->configure(CODEC_DSP_ENABLE, (bool *)false); - } + rb->configure(DSP_SET_FREQUENCY, (long *)(rb->id3->frequency)); + codec_set_replaygain(ci->id3); - /* Create a decoder instance */ - - flacDecoder=FLAC__seekable_stream_decoder_new(); - - /* Set up the decoder and the callback functions - this must be done before init */ - - /* The following are required for stream_decoder and higher */ - FLAC__seekable_stream_decoder_set_client_data(flacDecoder,ci); - FLAC__seekable_stream_decoder_set_write_callback(flacDecoder, flac_write_handler); - FLAC__seekable_stream_decoder_set_read_callback(flacDecoder, flac_read_handler); - FLAC__seekable_stream_decoder_set_metadata_callback(flacDecoder, flac_metadata_handler); - FLAC__seekable_stream_decoder_set_error_callback(flacDecoder, flac_error_handler); - FLAC__seekable_stream_decoder_set_metadata_respond(flacDecoder, FLAC__METADATA_TYPE_STREAMINFO); - - /* The following are only for the seekable_stream_decoder */ - FLAC__seekable_stream_decoder_set_seek_callback(flacDecoder, flac_seek_handler); - FLAC__seekable_stream_decoder_set_tell_callback(flacDecoder, flac_tell_handler); - FLAC__seekable_stream_decoder_set_length_callback(flacDecoder, flac_length_handler); - FLAC__seekable_stream_decoder_set_eof_callback(flacDecoder, flac_eof_handler); - - - /* QUESTION: What do we do when the init fails? */ - if (FLAC__seekable_stream_decoder_init(flacDecoder)) { - return CODEC_ERROR; - } - - /* The first thing to do is to parse the metadata */ - FLAC__seekable_stream_decoder_process_until_end_of_metadata(flacDecoder); - - samplesdone=0; - ci->set_elapsed(0); - /* The main decoder loop */ - while (FLAC__seekable_stream_decoder_get_state(flacDecoder)!=FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM) { - rb->yield(); - if (ci->stop_codec || ci->reload_codec) { - break; + /* Create a decoder instance */ + + flacDecoder=FLAC__seekable_stream_decoder_new(); + + /* Set up the decoder and the callback functions - this must be done before init */ + + /* The following are required for stream_decoder and higher */ + FLAC__seekable_stream_decoder_set_client_data(flacDecoder,ci); + FLAC__seekable_stream_decoder_set_write_callback(flacDecoder, flac_write_handler); + FLAC__seekable_stream_decoder_set_read_callback(flacDecoder, flac_read_handler); + FLAC__seekable_stream_decoder_set_metadata_callback(flacDecoder, flac_metadata_handler); + FLAC__seekable_stream_decoder_set_error_callback(flacDecoder, flac_error_handler); + FLAC__seekable_stream_decoder_set_metadata_respond_all(flacDecoder); + + /* The following are only for the seekable_stream_decoder */ + FLAC__seekable_stream_decoder_set_seek_callback(flacDecoder, flac_seek_handler); + FLAC__seekable_stream_decoder_set_tell_callback(flacDecoder, flac_tell_handler); + FLAC__seekable_stream_decoder_set_length_callback(flacDecoder, flac_length_handler); + FLAC__seekable_stream_decoder_set_eof_callback(flacDecoder, flac_eof_handler); + + + /* QUESTION: What do we do when the init fails? */ + if (FLAC__seekable_stream_decoder_init(flacDecoder)) { + return CODEC_ERROR; } - if (ci->seek_time) { - int sample_loc; + /* The first thing to do is to parse the metadata */ + FLAC__seekable_stream_decoder_process_until_end_of_metadata(flacDecoder); - sample_loc = ci->seek_time/1000 * ci->id3->frequency; - if (FLAC__seekable_stream_decoder_seek_absolute(flacDecoder,sample_loc)) { - samplesdone=sample_loc; - ci->set_elapsed(samplesdone/(ci->id3->frequency/1000)); - } - ci->seek_time = 0; + if ( ci->id3->offset && stream_info ) { + FLAC__uint64 sample; + + sample = find_sample_number( ci->id3->offset - metadata_length ); + ci->advance_buffer(ci->id3->offset); + FLAC__seekable_stream_decoder_seek_absolute(flacDecoder, sample); + FLAC__seekable_stream_decoder_get_decode_position(flacDecoder, &offset); + ci->set_offset(offset); + samplesdone=(uint32_t)sample; + ci->set_elapsed(sample/(ci->id3->frequency/1000)); + } else { + samplesdone=0; + ci->set_elapsed(0); } - FLAC__seekable_stream_decoder_process_single(flacDecoder); - } + /* The main decoder loop */ + while (FLAC__seekable_stream_decoder_get_state(flacDecoder)!=FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM) { + rb->yield(); + if (ci->stop_codec || ci->reload_codec) { + break; + } + + if (ci->seek_time) { + int sample_loc; + + sample_loc = ci->seek_time/1000 * ci->id3->frequency; + if (FLAC__seekable_stream_decoder_seek_absolute(flacDecoder,sample_loc)) { + samplesdone=sample_loc; + ci->set_elapsed(samplesdone/(ci->id3->frequency/1000)); + } + ci->seek_time = 0; + } + + FLAC__seekable_stream_decoder_process_single(flacDecoder); + FLAC__seekable_stream_decoder_get_decode_position(flacDecoder, &offset); + ci->set_offset(offset); + } - /* Flush the libFLAC buffers */ - FLAC__seekable_stream_decoder_finish(flacDecoder); + /* Flush the libFLAC buffers */ + FLAC__seekable_stream_decoder_finish(flacDecoder); - if (ci->request_next_track()) - goto next_track; + if (ci->request_next_track()) { + if ( stream_info ) { + FLAC__metadata_object_delete(stream_info); + } + if ( seek_table ) { + FLAC__metadata_object_delete(seek_table); + } + metadata_length = 0; + goto next_track; + } - return CODEC_OK; + return CODEC_OK; } diff --git a/apps/codecs/lib/xxx2wav.c b/apps/codecs/lib/xxx2wav.c index 338f1c41aa..8c6ceed69e 100644 --- a/apps/codecs/lib/xxx2wav.c +++ b/apps/codecs/lib/xxx2wav.c @@ -70,6 +70,31 @@ void* codec_realloc(void* ptr, size_t size) return(x); } +size_t strlen(const char *s) +{ + return(local_rb->strlen(s)); +} + +char *strcpy(char *dest, const char *src) +{ + return(local_rb->strcpy(dest,src)); +} + +char *strcat(char *dest, const char *src) +{ + return(local_rb->strcat(dest,src)); +} + +int strcmp(const char *s1, const char *s2) +{ + return(local_rb->strcmp(s1,s2)); +} + +int strncasecmp(const char *s1, const char *s2, size_t n) +{ + return(local_rb->strncasecmp(s1,s2,n)); +} + void *memcpy(void *dest, const void *src, size_t n) { return(local_rb->memcpy(dest,src,n)); diff --git a/apps/codecs/lib/xxx2wav.h b/apps/codecs/lib/xxx2wav.h index 1cdbc99878..2c9a73729c 100644 --- a/apps/codecs/lib/xxx2wav.h +++ b/apps/codecs/lib/xxx2wav.h @@ -49,6 +49,12 @@ void* codec_calloc(size_t nmemb, size_t size); void* codec_alloca(size_t size); void* codec_realloc(void* ptr, size_t size); void codec_free(void* ptr); +size_t strlen(const char *s); +char *strcpy(char *dest, const char *src); +char *strcat(char *dest, const char *src); +int strcmp(const char *, const char *); +int strcasecmp(const char *, const char *); + void *memcpy(void *dest, const void *src, size_t n); void *memset(void *s, int c, size_t n); int memcmp(const void *s1, const void *s2, size_t n); diff --git a/apps/codecs/libFLAC/SOURCES b/apps/codecs/libFLAC/SOURCES index b6f21dc13f..9d4db2f9c5 100644 --- a/apps/codecs/libFLAC/SOURCES +++ b/apps/codecs/libFLAC/SOURCES @@ -8,6 +8,7 @@ format.c lpc.c md5.c memory.c +metadata_object.c seekable_stream_decoder.c stream_decoder.c #if defined(CPU_COLDFIRE) && !defined(SIMULATOR) diff --git a/apps/codecs/libFLAC/include/FLAC/metadata.h b/apps/codecs/libFLAC/include/FLAC/metadata.h index ff40e6d5ed..be3e6efd79 100644 --- a/apps/codecs/libFLAC/include/FLAC/metadata.h +++ b/apps/codecs/libFLAC/include/FLAC/metadata.h @@ -295,7 +295,7 @@ extern FLAC_API const char * const FLAC__Metadata_SimpleIteratorStatusString[]; * \retval FLAC__Metadata_SimpleIterator* * \c NULL if there was an error allocating memory, else the new instance. */ -FLAC_API FLAC__Metadata_SimpleIterator *FLAC__metadata_simple_iterator_new(); +FLAC_API FLAC__Metadata_SimpleIterator *FLAC__metadata_simple_iterator_new(void); /** Free an iterator instance. Deletes the object pointed to by \a iterator. * @@ -652,7 +652,7 @@ extern FLAC_API const char * const FLAC__Metadata_ChainStatusString[]; * \retval FLAC__Metadata_Chain* * \c NULL if there was an error allocating memory, else the new instance. */ -FLAC_API FLAC__Metadata_Chain *FLAC__metadata_chain_new(); +FLAC_API FLAC__Metadata_Chain *FLAC__metadata_chain_new(void); /** Free a chain instance. Deletes the object pointed to by \a chain. * @@ -899,7 +899,7 @@ FLAC_API void FLAC__metadata_chain_sort_padding(FLAC__Metadata_Chain *chain); * \retval FLAC__Metadata_Iterator* * \c NULL if there was an error allocating memory, else the new instance. */ -FLAC_API FLAC__Metadata_Iterator *FLAC__metadata_iterator_new(); +FLAC_API FLAC__Metadata_Iterator *FLAC__metadata_iterator_new(void); /** Free an iterator instance. Deletes the object pointed to by \a iterator. * @@ -1621,7 +1621,7 @@ FLAC_API int FLAC__metadata_object_vorbiscomment_remove_entries_matching(FLAC__S * \retval FLAC__StreamMetadata_CueSheet_Track* * \c NULL if there was an error allocating memory, else the new instance. */ -FLAC_API FLAC__StreamMetadata_CueSheet_Track *FLAC__metadata_object_cuesheet_track_new(); +FLAC_API FLAC__StreamMetadata_CueSheet_Track *FLAC__metadata_object_cuesheet_track_new(void); /** Create a copy of an existing CUESHEET track object. * diff --git a/apps/codecs/vorbis.c b/apps/codecs/vorbis.c index 2976a05604..e072acccfd 100644 --- a/apps/codecs/vorbis.c +++ b/apps/codecs/vorbis.c @@ -33,21 +33,6 @@ static struct codec_api* rb; int errno; -size_t strlen(const char *s) -{ - return(rb->strlen(s)); -} - -char *strcpy(char *dest, const char *src) -{ - return(rb->strcpy(dest,src)); -} - -char *strcat(char *dest, const char *src) -{ - return(rb->strcat(dest,src)); -} - size_t read_handler(void *ptr, size_t size, size_t nmemb, void *datasource) { (void)datasource; diff --git a/apps/metadata.c b/apps/metadata.c index bbbfe07d66..524f5213dc 100644 --- a/apps/metadata.c +++ b/apps/metadata.c @@ -92,7 +92,7 @@ const long wavpack_sample_rates [] = { 6000, 8000, 9600, 11025, 12000, 16000, static bool get_apetag_info (struct mp3entry *entry, int fd); -static bool get_vorbis_comments (struct mp3entry *entry, int fd); +static bool get_vorbis_comments (struct mp3entry *entry, size_t bytes_remaining, int fd); static void little_endian_to_native (void *data, char *format); @@ -104,6 +104,9 @@ bool get_metadata(struct track_info* track, int fd, const char* trackname, unsigned char* buf; int i,j,eof; int rc; + int segments; /* for Vorbis*/ + size_t bytes_remaining = 0; /* for Vorbis */ + /* Load codec specific track tag information. */ switch (track->id3.codectype) { @@ -215,7 +218,10 @@ bool get_metadata(struct track_info* track, int fd, const char* trackname, } else if ((buf[0]&0x7f)==4) { /* 4 is the VORBIS_COMMENT block */ /* The next i bytes of the file contain the VORBIS COMMENTS - just skip them for now. */ - lseek(fd, i, SEEK_CUR); + //lseek(fd, i, SEEK_CUR); + if (!get_vorbis_comments(&(track->id3), i, fd)) { + return false; + } } else { if (buf[0]&0x80) { /* If we have reached the last metadata block, abort. */ @@ -272,12 +278,61 @@ bool get_metadata(struct track_info* track, int fd, const char* trackname, track->id3.frequency=buf[40]|(buf[41]<<8)|(buf[42]<<16)|(buf[43]<<24); channels=buf[39]; - if ( !get_vorbis_comments(&(track->id3), fd) ) { + /* Comments are in second Ogg page */ + if ( lseek(fd, 58, SEEK_SET) < 0 ) { + return false; + } + + /* Minimum header length for Ogg pages is 27 */ + if (read(fd, buf, 27) < 27) { + return false; + } + + if (memcmp(buf,"OggS",4)!=0) { + logf("1: Not an Ogg Vorbis file"); + return(false); + } + + segments=buf[26]; + /* read in segment table */ + if (read(fd, buf, segments) < segments) { + return false; + } + + /* The second packet in a vorbis stream is the comment packet. It *may* + * extend beyond the second page, but usually does not. Here we find the + * length of the comment packet (or the rest of the page if the comment + * packet extends to the third page). + */ + for (i = 0; i < segments; i++) { + bytes_remaining += buf[i]; + /* The last segment of a packet is always < 255 bytes */ + if (buf[i] < 255) { + break; + } + } + + /* Now read in packet header (type and id string) */ + if(read(fd, buf, 7) < 7) { + return false; + } + + /* The first byte of a packet is the packet type; comment packets are + * type 3. + */ + if ((buf[0] != 3) || (memcmp(buf + 1,"vorbis",6)!=0)) { + logf("Not a vorbis comment packet"); + return false; + } + + bytes_remaining -= 7; + + if ( !get_vorbis_comments(&(track->id3), bytes_remaining, fd) ) { logf("get_vorbis_comments failed"); return(false); } - /* Set id3 genre to something bogus, otherwise vorbis tracks + /* Set id3v1 genre to 255 (effectively 'none'), otherwise vorbis tracks * without genre tags will show up as 'Blues' */ track->id3.genre=255; @@ -780,7 +835,7 @@ static void UTF8ToAnsi (unsigned char *pUTF8) * Additionally, vorbis comments *may* take up more than one Ogg page, and this * only looks at the first page of comments. */ -static bool get_vorbis_comments (struct mp3entry *entry, int fd) +static bool get_vorbis_comments (struct mp3entry *entry, size_t bytes_remaining, int fd) { int vendor_length; int comment_count; @@ -790,58 +845,6 @@ static bool get_vorbis_comments (struct mp3entry *entry, int fd) int buffer_remaining = sizeof(entry->id3v2buf) + sizeof(entry->id3v1buf); char *buffer = entry->id3v2buf; char **p = NULL; - int segments; - int packet_remaining = 0; - - /* Comments are in second Ogg page */ - if ( lseek(fd, 58, SEEK_SET) < 0 ) { - return false; - } - - /* Minimum header length for Ogg pages is 27 */ - if (read(fd, temp, 27) < 27) { - return false; - } - - if (memcmp(temp,"OggS",4)!=0) { - logf("1: Not an Ogg Vorbis file"); - return(false); - } - - segments=temp[26]; - /* read in segment table */ - if (read(fd, temp, segments) < segments) { - return false; - } - - /* The second packet in a vorbis stream is the comment packet. It *may* - * extend beyond the second page, but usually does not. Here we find the - * length of the comment packet (or the rest of the page if the comment - * packet extends to the third page). - */ - for (i = 0; i < segments; i++) { - packet_remaining += temp[i]; - /* The last segment of a packet is always < 255 bytes */ - if (temp[i] < 255) { - break; - } - } - - /* Now read in packet header (type and id string) */ - if(read(fd, temp, 7) < 7) { - return false; - } - - /* The first byte of a packet is the packet type; comment packets are - * type 3. - */ - if ((temp[0] != 3) || (memcmp(temp + 1,"vorbis",6)!=0)) { - logf("Not a vorbis comment packet"); - return false; - } - - packet_remaining -= 7; - /* We've read in all header info, now start reading comments */ @@ -855,8 +858,8 @@ static bool get_vorbis_comments (struct mp3entry *entry, int fd) return false; } little_endian_to_native(&comment_count, "L"); - packet_remaining -= (vendor_length + 8); - if ( packet_remaining <= 0 ) { + bytes_remaining -= (vendor_length + 8); + if ( bytes_remaining <= 0 ) { return true; } @@ -870,8 +873,8 @@ static bool get_vorbis_comments (struct mp3entry *entry, int fd) little_endian_to_native(&comment_length, "L"); /* Quit if we've passed the end of the page */ - packet_remaining -= (comment_length + 4); - if ( packet_remaining <= 0 ) { + bytes_remaining -= (comment_length + 4); + if ( bytes_remaining <= 0 ) { return true; } @@ -929,6 +932,6 @@ static bool get_vorbis_comments (struct mp3entry *entry, int fd) } } } - + return true; } diff --git a/apps/playback.c b/apps/playback.c index 4756c8aed1..c7637f5c71 100644 --- a/apps/playback.c +++ b/apps/playback.c @@ -887,6 +887,7 @@ bool audio_load_track(int offset, bool start_play, int peek_offset) tracks[track_widx].start_pos = offset; break; case AFMT_OGG_VORBIS: + case AFMT_FLAC: tracks[track_widx].id3.offset = offset; break; } @@ -1366,7 +1367,7 @@ static void initiate_track_change(int peek_index) if (!paused) pcm_play_pause(true); - return; + return; } /* Detect if disk is spinning.. */ |