From 3386dd7be90f4f4a23d36359f2052fa834fb20e7 Mon Sep 17 00:00:00 2001 From: Brandon Low Date: Wed, 28 Nov 2007 04:58:16 +0000 Subject: Fix FS8069, because Nico_P made it easy git-svn-id: svn://svn.rockbox.org/rockbox/trunk@15840 a1c6a512-1295-4272-9138-f99709370657 --- apps/buffering.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ apps/buffering.h | 7 +++++++ apps/metadata.c | 42 ++++++++++++++++++++++++++++++++++++++++++ apps/metadata.h | 1 + apps/playback.c | 4 ++++ 5 files changed, 107 insertions(+) (limited to 'apps') diff --git a/apps/buffering.c b/apps/buffering.c index f0a50c274c..f5bc2eeb19 100644 --- a/apps/buffering.c +++ b/apps/buffering.c @@ -657,6 +657,7 @@ static bool buffer_handle(int handle_id) /* finished buffering the file */ close(h->fd); h->fd = -1; + call_buffering_callbacks(EVENT_HANDLE_FINISHED, h->id); } return true; @@ -1138,6 +1139,58 @@ ssize_t bufgetdata(int handle_id, size_t size, void **data) return size; } +ssize_t bufgettail(int handle_id, size_t size, void **data) +{ + size_t tidx; + + const struct memory_handle *h; + + h = find_handle(handle_id); + + if (!h) + return ERR_HANDLE_NOT_FOUND; + + if (h->filerem) + return ERR_HANDLE_NOT_DONE; + + /* We don't support tail requests of > guardbuf_size, for simplicity */ + if (size > GUARD_BUFSIZE) + return ERR_INVALID_VALUE; + + tidx = RINGBUF_SUB(h->widx, size); + + if (tidx + size > buffer_len) + { + size_t copy_n = tidx + size - buffer_len; + memcpy(guard_buffer, (unsigned char *)buffer, copy_n); + } + + *data = &buffer[tidx]; + return size; +} + +ssize_t bufcuttail(int handle_id, size_t size) +{ + struct memory_handle *h; + + h = find_handle(handle_id); + + if (!h) + return ERR_HANDLE_NOT_FOUND; + + if (h->filerem) + return ERR_HANDLE_NOT_DONE; + + if (h->available < size) + size = h->available; + + h->available -= size; + h->filesize -= size; + h->widx = RINGBUF_SUB(h->widx, size); + return size; +} + + /* SECONDARY EXPORTED FUNCTIONS ============================ diff --git a/apps/buffering.h b/apps/buffering.h index f6a9f7883b..bc61ec5e6d 100644 --- a/apps/buffering.h +++ b/apps/buffering.h @@ -41,6 +41,7 @@ enum callback_event { EVENT_HANDLE_REBUFFER, EVENT_HANDLE_CLOSED, EVENT_HANDLE_MOVED, + EVENT_HANDLE_FINISHED, }; /* Error return values */ @@ -48,6 +49,7 @@ enum callback_event { #define ERR_BUFFER_FULL -2 #define ERR_INVALID_VALUE -3 #define ERR_FILE_ERROR -4 +#define ERR_HANDLE_NOT_DONE -5 /* Initialise the buffering subsystem */ @@ -68,9 +70,12 @@ bool buffering_reset(char *buf, size_t buflen); * bufadvance: Move handle reading index, relatively to current position * bufread : Copy data from a handle to a buffer * bufgetdata: Obtain a pointer for linear access to a "size" amount of data + * bufgettail: Out-of-band get the last size bytes of a handle. + * bufcuttail: Out-of-band remove the trailing 'size' bytes of a handle. * * NOTE: bufread and bufgetdata will block the caller until the requested * amount of data is ready (unless EOF is reached). + * NOTE: Tail operations are only legal when the end of the file is buffered. ****************************************************************************/ #define BUF_MAX_HANDLES 256 @@ -82,6 +87,8 @@ int bufseek(int handle_id, size_t newpos); int bufadvance(int handle_id, off_t offset); ssize_t bufread(int handle_id, size_t size, void *dest); ssize_t bufgetdata(int handle_id, size_t size, void **data); +ssize_t bufgettail(int handle_id, size_t size, void **data); +ssize_t bufcuttail(int handle_id, size_t size); /*************************************************************************** diff --git a/apps/metadata.c b/apps/metadata.c index 66719754ad..3a0ff574bf 100644 --- a/apps/metadata.c +++ b/apps/metadata.c @@ -30,6 +30,9 @@ #if CONFIG_CODEC == SWCODEC +/* For trailing tag stripping */ +#include "buffering.h" + #include "metadata/metadata_common.h" #include "metadata/metadata_parsers.h" @@ -322,3 +325,42 @@ bool get_metadata(struct mp3entry* id3, int fd, const char* trackname) return true; } +void strip_tags(int handle_id) +{ + int i; + static const unsigned char tag[] = "TAG"; + static const unsigned char apetag[] = "APETAGEX"; + size_t len, version; + unsigned char *tail; + + if (bufgettail(handle_id, 128, (void **)&tail) != 128) + return; + + for(i = 0;i < 3;i++) + if(tail[i] != tag[i]) + goto strip_ape_tag; + + /* Skip id3v1 tag */ + logf("Cutting off ID3v1 tag"); + bufcuttail(handle_id, 128); + +strip_ape_tag: + /* Check for APE tag (look for the APE tag footer) */ + + if (bufgettail(handle_id, 32, (void **)&tail) != 32) + return; + + for(i = 0;i < 8;i++) + if(tail[i] != apetag[i]) + return; + + /* Read the version and length from the footer */ + version = tail[8] | (tail[9] << 8) | (tail[10] << 16) | (tail[11] << 24); + len = tail[12] | (tail[13] << 8) | (tail[14] << 16) | (tail[15] << 24); + if (version == 2000) + len += 32; /* APEv2 has a 32 byte header */ + + /* Skip APE tag */ + logf("Cutting off APE tag (%ldB)", len); + bufcuttail(handle_id, len); +} diff --git a/apps/metadata.h b/apps/metadata.h index f07209f2dc..11d85942ed 100644 --- a/apps/metadata.h +++ b/apps/metadata.h @@ -24,6 +24,7 @@ unsigned int probe_file_format(const char *filename); bool get_metadata(struct mp3entry* id3, int fd, const char* trackname); +void strip_tags(int handle_id); #endif diff --git a/apps/playback.c b/apps/playback.c index a19c2d745a..8467614329 100644 --- a/apps/playback.c +++ b/apps/playback.c @@ -1485,6 +1485,10 @@ static void buffering_audio_callback(enum callback_event ev, int value) queue_send(&audio_queue, Q_AUDIO_FLUSH, 0); break; + case EVENT_HANDLE_FINISHED: + strip_tags(value); + break; + default: break; } -- cgit v1.2.3