Commit 01b708bc authored by Warren Dukes's avatar Warren Dukes

add support for parsing ape tags in musepack files

git-svn-id: https://svn.musicpd.org/mpd/trunk@3030 09075e82-0dd4-0310-85a5-a0d7c8717e4f
parent 32a1f952
......@@ -12,8 +12,6 @@
*) Handle mp1 and mp2 files (including files with mp3 suffixes)
*) add support for playing aac streams (gee, thanks icecast)
*) parsing of lame tags (including getting replaygain and gapless info)
*) implement apev2 and id3v1 tag reader from xmms-musepack plugin
*) only use libid3tag for id3v2 tags, use internal impl for id3v1 tags
*) aduio output
*) allowing "pausing" of audio output devices
......
......@@ -47,7 +47,7 @@ static mpc_int32_t mpc_read_cb(void * vdata, void * ptr, mpc_int32_t size) {
while(1) {
ret = readFromInputStream(data->inStream, ptr, 1, size);
if(ret == 0 && !inputStreamAtEOF(data->inStream) &&
!data->dc->stop)
(data->dc && !data->dc->stop))
{
my_usleep(10000);
}
......@@ -272,17 +272,50 @@ static int mpc_decode(OutputBuffer * cb, DecoderControl * dc,
return 0;
}
static float mpcGetTime(char * file) {
InputStream inStream;
float time = -1;
mpc_reader reader;
mpc_streaminfo info;
MpcCallbackData data;
data.inStream = &inStream;
data.dc = NULL;
reader.read = mpc_read_cb;
reader.seek = mpc_seek_cb;
reader.tell = mpc_tell_cb;
reader.get_size = mpc_getsize_cb;
reader.canseek = mpc_canseek_cb;
reader.data = &data;
mpc_streaminfo_init(&info);
if(openInputStream(&inStream, file) < 0) return -1;
if(mpc_streaminfo_read(&info, &reader) != ERROR_CODE_OK) {
closeInputStream(&inStream);
return -1;
}
time = mpc_streaminfo_get_length(&info);
closeInputStream(&inStream);
return time;
}
static MpdTag * mpcTagDup(char * file) {
MpdTag * ret = NULL;
FILE * fp;
fp = fopen(file,"r");
if(!fp) return NULL;
float time = mpcGetTime(file);
/* get tag info here */
if(time < 0) return NULL;
ret = apeDup(file);
if(!ret) ret = id3Dup(file);
if(!ret) ret = newMpdTag();
ret->time = 0;
ret->time = time;
return ret;
}
......
......@@ -217,6 +217,113 @@ MpdTag * id3Dup(char * file) {
return ret;
}
MpdTag * apeDup(char * file) {
MpdTag * ret = NULL;
FILE * fp = NULL;
int tagCount;
unsigned char * buffer = NULL;
unsigned char * p;
int tagLen;
int size;
unsigned long flags;
int i;
unsigned char * key;
struct {
unsigned char id[8];
unsigned char version[4];
unsigned char length[4];
unsigned char tagCount[4];
unsigned char flags[4];
unsigned char reserved[8];
} footer;
char * apeItems[7] =
{
"title",
"artist",
"album",
"comment",
"genre",
"track",
"year"
};
int tagItems[7] =
{
TAG_ITEM_TITLE,
TAG_ITEM_ARTIST,
TAG_ITEM_ALBUM,
TAG_ITEM_COMMENT,
TAG_ITEM_GENRE,
TAG_ITEM_TRACK,
TAG_ITEM_DATE,
};
fp = fopen(file, "r");
if(!fp) return NULL;
/* determine if file has an apeV2 tag */
if(fseek(fp, 0, SEEK_END)) goto fail;
size = ftell(fp);
if(fseek(fp, size-sizeof(footer), SEEK_SET)) goto fail;
if(fread(&footer, 1, sizeof(footer), fp) != sizeof(footer)) goto fail;
if(memcmp(footer.id, "APETAGEX", sizeof(footer.id)) != 0) goto fail;
if(readLEuint32(footer.version) != 2000) goto fail;
/* find begining of ape tag */
tagLen = readLEuint32(footer.length);
if(tagLen < sizeof(footer)) goto fail;
if(fseek(fp, size-tagLen, SEEK_SET)) goto fail;
/* read tag into buffer */
tagLen -= sizeof(footer);
buffer = malloc(tagLen);
if(fread(buffer, 1, tagLen, fp) != tagLen) goto fail;
/* read tags */
tagCount = readLEuint32(footer.tagCount);
p = buffer;
while(tagCount-- && tagLen > 10) {
size = readLEuint32(p);
p += 4;
tagLen -= 4;
flags = readLEuint32(p);
p += 4;
tagLen -= 4;
/* get the key */
key = p;
while(tagLen-size > 0 && *p != '\0') {
p++;
tagLen--;
}
p++;
tagLen--;
/* get the value */
if(tagLen-size < 0) goto fail;
/* we only care about utf-8 text tags */
if(!(flags & (0x3 << 1))) {
for(i = 0; i < 7; i++) {
if(strcasecmp(key, apeItems[i]) == 0) {
if(!ret) ret = newMpdTag();
addItemToMpdTagWithLen(
ret, tagItems[i], p, size);
}
}
}
p += size;
tagLen -= size;
}
fail:
if(fp) fclose(fp);
if(buffer) free(buffer);
return ret;
}
MpdTag * newMpdTag() {
MpdTag * ret = malloc(sizeof(MpdTag));
ret->items = NULL;
......
......@@ -64,6 +64,8 @@ typedef struct _MpdTag {
MpdTag * parseId3Tag(struct id3_tag *);
#endif
MpdTag * apeDup(char * file);
MpdTag * id3Dup(char * file);
MpdTag * newMpdTag();
......
......@@ -92,3 +92,11 @@ char * appendToString(char * dest, const char * src) {
return dest;
}
unsigned long readLEuint32(const unsigned char *p)
{
return ((unsigned long) p[0] << 0) |
((unsigned long) p[1] << 8) |
((unsigned long) p[2] << 16) | ((unsigned long) p[3] << 24);
}
......@@ -35,4 +35,6 @@ int ipv6Supported();
char * appendToString(char * dest, const char * src);
unsigned long readLEuint32(const unsigned char * p);
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment