1
0
Fork 0
forked from len0rd/rockbox

Added comments, Replay Gain, and resume/bookmarks for FLAC.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@7253 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Ryan Jackson 2005-07-28 18:43:33 +00:00
parent 773c28e489
commit b301b43825
8 changed files with 304 additions and 175 deletions

View file

@ -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 */
/* Create a decoder instance */
flacDecoder=FLAC__seekable_stream_decoder_new();
flacDecoder=FLAC__seekable_stream_decoder_new();
/* Set up the decoder and the callback functions - this must be done before init */
/* 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 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);
/* 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;
/* 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));
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);
}
/* 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;
}
ci->seek_time = 0;
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);
}
FLAC__seekable_stream_decoder_process_single(flacDecoder);
}
/* 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()) {
if ( stream_info ) {
FLAC__metadata_object_delete(stream_info);
}
if ( seek_table ) {
FLAC__metadata_object_delete(seek_table);
}
metadata_length = 0;
goto next_track;
}
if (ci->request_next_track())
goto next_track;
return CODEC_OK;
return CODEC_OK;
}

View file

@ -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));

View file

@ -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);

View file

@ -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)

View file

@ -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.
*

View file

@ -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;

View file

@ -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;
}

View file

@ -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.. */