summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
Diffstat (limited to 'apps')
-rw-r--r--apps/codecs/flac.c306
-rw-r--r--apps/codecs/lib/xxx2wav.c25
-rw-r--r--apps/codecs/lib/xxx2wav.h6
-rw-r--r--apps/codecs/libFLAC/SOURCES1
-rw-r--r--apps/codecs/libFLAC/include/FLAC/metadata.h8
-rw-r--r--apps/codecs/vorbis.c15
-rw-r--r--apps/metadata.c127
-rw-r--r--apps/playback.c3
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.. */