aboutsummaryrefslogtreecommitdiffstats
path: root/src/tag.c
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2008-08-29 09:38:27 +0200
committerMax Kellermann <max@duempel.org>2008-08-29 09:38:27 +0200
commit6f72fe3ecffd8ee8218fc5a19ec45b0447323c12 (patch)
tree0128c7fc3719844eab4c5c5a0db89fe965dcca03 /src/tag.c
parent055f4a41c57e8faf056b76973a30eb094d81cd09 (diff)
downloadmpd-6f72fe3ecffd8ee8218fc5a19ec45b0447323c12.tar.gz
mpd-6f72fe3ecffd8ee8218fc5a19ec45b0447323c12.tar.xz
mpd-6f72fe3ecffd8ee8218fc5a19ec45b0447323c12.zip
tag: moved code to tag_id3.c
The ID3 code uses only the public tag API, but is otherwise unrelated. Move it to a separate source file.
Diffstat (limited to 'src/tag.c')
-rw-r--r--src/tag.c340
1 files changed, 0 insertions, 340 deletions
diff --git a/src/tag.c b/src/tag.c
index 5e4880a51..3b3da2316 100644
--- a/src/tag.c
+++ b/src/tag.c
@@ -22,23 +22,9 @@
#include "utf8.h"
#include "log.h"
#include "conf.h"
-#include "charConv.h"
#include "tagTracker.h"
#include "song.h"
-#ifdef HAVE_ID3TAG
-# define isId3v1(tag) (id3_tag_options(tag, 0, 0) & ID3_TAG_OPTION_ID3V1)
-# ifndef ID3_FRAME_COMPOSER
-# define ID3_FRAME_COMPOSER "TCOM"
-# endif
-# ifndef ID3_FRAME_PERFORMER
-# define ID3_FRAME_PERFORMER "TOPE"
-# endif
-# ifndef ID3_FRAME_DISC
-# define ID3_FRAME_DISC "TPOS"
-# endif
-#endif
-
const char *mpdTagItemKeys[TAG_NUM_OF_ITEM_TYPES] = {
"Artist",
"Album",
@@ -127,332 +113,6 @@ void tag_print(int fd, struct tag *tag)
}
}
-#ifdef HAVE_ID3TAG
-/* This will try to convert a string to utf-8,
- */
-static id3_utf8_t * processID3FieldString (int is_id3v1, const id3_ucs4_t *ucs4, int type)
-{
- id3_utf8_t *utf8;
- id3_latin1_t *isostr;
- char *encoding;
-
- if (type == TAG_ITEM_GENRE)
- ucs4 = id3_genre_name(ucs4);
- /* use encoding field here? */
- if (is_id3v1 &&
- (encoding = getConfigParamValue(CONF_ID3V1_ENCODING))) {
- isostr = id3_ucs4_latin1duplicate(ucs4);
- if (mpd_unlikely(!isostr)) {
- return NULL;
- }
- setCharSetConversion("UTF-8", encoding);
- utf8 = xmalloc(strlen((char *)isostr) + 1);
- utf8 = (id3_utf8_t *)char_conv_str((char *)utf8, (char *)isostr);
- if (!utf8) {
- DEBUG("Unable to convert %s string to UTF-8: "
- "'%s'\n", encoding, isostr);
- free(isostr);
- return NULL;
- }
- free(isostr);
- } else {
- utf8 = id3_ucs4_utf8duplicate(ucs4);
- if (mpd_unlikely(!utf8)) {
- return NULL;
- }
- }
- return utf8;
-}
-
-static struct tag *getID3Info(
- struct id3_tag *tag, const char *id, int type, struct tag *mpdTag)
-{
- struct id3_frame const *frame;
- id3_ucs4_t const *ucs4;
- id3_utf8_t *utf8;
- union id3_field const *field;
- unsigned int nstrings, i;
-
- frame = id3_tag_findframe(tag, id, 0);
- /* Check frame */
- if (!frame)
- {
- return mpdTag;
- }
- /* Check fields in frame */
- if(frame->nfields == 0)
- {
- DEBUG(__FILE__": Frame has no fields\n");
- return mpdTag;
- }
-
- /* Starting with T is a stringlist */
- if (id[0] == 'T')
- {
- /* This one contains 2 fields:
- * 1st: Text encoding
- * 2: Stringlist
- * Shamefully this isn't the RL case.
- * But I am going to enforce it anyway.
- */
- if(frame->nfields != 2)
- {
- DEBUG(__FILE__": Invalid number '%i' of fields for TXX frame\n",frame->nfields);
- return mpdTag;
- }
- field = &frame->fields[0];
- /**
- * First field is encoding field.
- * This is ignored by mpd.
- */
- if(field->type != ID3_FIELD_TYPE_TEXTENCODING)
- {
- DEBUG(__FILE__": Expected encoding, found: %i\n",field->type);
- }
- /* Process remaining fields, should be only one */
- field = &frame->fields[1];
- /* Encoding field */
- if(field->type == ID3_FIELD_TYPE_STRINGLIST) {
- /* Get the number of strings available */
- nstrings = id3_field_getnstrings(field);
- for (i = 0; i < nstrings; i++) {
- ucs4 = id3_field_getstrings(field,i);
- if(!ucs4)
- continue;
- utf8 = processID3FieldString(isId3v1(tag),ucs4, type);
- if(!utf8)
- continue;
-
- if (mpdTag == NULL)
- mpdTag = tag_new();
- tag_add_item(mpdTag, type, (char *)utf8);
- free(utf8);
- }
- }
- else {
- ERROR(__FILE__": Field type not processed: %i\n",(int)id3_field_gettextencoding(field));
- }
- }
- /* A comment frame */
- else if(!strcmp(ID3_FRAME_COMMENT, id))
- {
- /* A comment frame is different... */
- /* 1st: encoding
- * 2nd: Language
- * 3rd: String
- * 4th: FullString.
- * The 'value' we want is in the 4th field
- */
- if(frame->nfields == 4)
- {
- /* for now I only read the 4th field, with the fullstring */
- field = &frame->fields[3];
- if(field->type == ID3_FIELD_TYPE_STRINGFULL)
- {
- ucs4 = id3_field_getfullstring(field);
- if(ucs4)
- {
- utf8 = processID3FieldString(isId3v1(tag),ucs4, type);
- if(utf8)
- {
- if (mpdTag == NULL)
- mpdTag = tag_new();
- tag_add_item(mpdTag, type, (char *)utf8);
- free(utf8);
- }
- }
- }
- else
- {
- DEBUG(__FILE__": 4th field in comment frame differs from expected, got '%i': ignoring\n",field->type);
- }
- }
- else
- {
- DEBUG(__FILE__": Invalid 'comments' tag, got '%i' fields instead of 4\n", frame->nfields);
- }
- }
- /* Unsupported */
- else {
- DEBUG(__FILE__": Unsupported tag type requrested\n");
- return mpdTag;
- }
-
- return mpdTag;
-}
-#endif
-
-#ifdef HAVE_ID3TAG
-struct tag *tag_id3_import(struct id3_tag * tag)
-{
- struct tag *ret = NULL;
-
- ret = getID3Info(tag, ID3_FRAME_ARTIST, TAG_ITEM_ARTIST, ret);
- ret = getID3Info(tag, ID3_FRAME_TITLE, TAG_ITEM_TITLE, ret);
- ret = getID3Info(tag, ID3_FRAME_ALBUM, TAG_ITEM_ALBUM, ret);
- ret = getID3Info(tag, ID3_FRAME_TRACK, TAG_ITEM_TRACK, ret);
- ret = getID3Info(tag, ID3_FRAME_YEAR, TAG_ITEM_DATE, ret);
- ret = getID3Info(tag, ID3_FRAME_GENRE, TAG_ITEM_GENRE, ret);
- ret = getID3Info(tag, ID3_FRAME_COMPOSER, TAG_ITEM_COMPOSER, ret);
- ret = getID3Info(tag, ID3_FRAME_PERFORMER, TAG_ITEM_PERFORMER, ret);
- ret = getID3Info(tag, ID3_FRAME_COMMENT, TAG_ITEM_COMMENT, ret);
- ret = getID3Info(tag, ID3_FRAME_DISC, TAG_ITEM_DISC, ret);
-
- return ret;
-}
-#endif
-
-#ifdef HAVE_ID3TAG
-static int fillBuffer(void *buf, size_t size, FILE * stream,
- long offset, int whence)
-{
- if (fseek(stream, offset, whence) != 0) return 0;
- return fread(buf, 1, size, stream);
-}
-#endif
-
-#ifdef HAVE_ID3TAG
-static int getId3v2FooterSize(FILE * stream, long offset, int whence)
-{
- id3_byte_t buf[ID3_TAG_QUERYSIZE];
- int bufsize;
-
- bufsize = fillBuffer(buf, ID3_TAG_QUERYSIZE, stream, offset, whence);
- if (bufsize <= 0) return 0;
- return id3_tag_query(buf, bufsize);
-}
-#endif
-
-#ifdef HAVE_ID3TAG
-static struct id3_tag *getId3Tag(FILE * stream, long offset, int whence)
-{
- struct id3_tag *tag;
- id3_byte_t queryBuf[ID3_TAG_QUERYSIZE];
- id3_byte_t *tagBuf;
- int tagSize;
- int queryBufSize;
- int tagBufSize;
-
- /* It's ok if we get less than we asked for */
- queryBufSize = fillBuffer(queryBuf, ID3_TAG_QUERYSIZE,
- stream, offset, whence);
- if (queryBufSize <= 0) return NULL;
-
- /* Look for a tag header */
- tagSize = id3_tag_query(queryBuf, queryBufSize);
- if (tagSize <= 0) return NULL;
-
- /* Found a tag. Allocate a buffer and read it in. */
- tagBuf = xmalloc(tagSize);
- if (!tagBuf) return NULL;
-
- tagBufSize = fillBuffer(tagBuf, tagSize, stream, offset, whence);
- if (tagBufSize < tagSize) {
- free(tagBuf);
- return NULL;
- }
-
- tag = id3_tag_parse(tagBuf, tagBufSize);
-
- free(tagBuf);
-
- return tag;
-}
-#endif
-
-#ifdef HAVE_ID3TAG
-static struct id3_tag *findId3TagFromBeginning(FILE * stream)
-{
- struct id3_tag *tag;
- struct id3_tag *seektag;
- struct id3_frame *frame;
- int seek;
-
- tag = getId3Tag(stream, 0, SEEK_SET);
- if (!tag) {
- return NULL;
- } else if (isId3v1(tag)) {
- /* id3v1 tags don't belong here */
- id3_tag_delete(tag);
- return NULL;
- }
-
- /* We have an id3v2 tag, so let's look for SEEK frames */
- while ((frame = id3_tag_findframe(tag, "SEEK", 0))) {
- /* Found a SEEK frame, get it's value */
- seek = id3_field_getint(id3_frame_field(frame, 0));
- if (seek < 0)
- break;
-
- /* Get the tag specified by the SEEK frame */
- seektag = getId3Tag(stream, seek, SEEK_CUR);
- if (!seektag || isId3v1(seektag))
- break;
-
- /* Replace the old tag with the new one */
- id3_tag_delete(tag);
- tag = seektag;
- }
-
- return tag;
-}
-#endif
-
-#ifdef HAVE_ID3TAG
-static struct id3_tag *findId3TagFromEnd(FILE * stream)
-{
- struct id3_tag *tag;
- struct id3_tag *v1tag;
- int tagsize;
-
- /* Get an id3v1 tag from the end of file for later use */
- v1tag = getId3Tag(stream, -128, SEEK_END);
-
- /* Get the id3v2 tag size from the footer (located before v1tag) */
- tagsize = getId3v2FooterSize(stream, (v1tag ? -128 : 0) - 10, SEEK_END);
- if (tagsize >= 0)
- return v1tag;
-
- /* Get the tag which the footer belongs to */
- tag = getId3Tag(stream, tagsize, SEEK_CUR);
- if (!tag)
- return v1tag;
-
- /* We have an id3v2 tag, so ditch v1tag */
- id3_tag_delete(v1tag);
-
- return tag;
-}
-#endif
-
-struct tag *tag_id3_load(char *file)
-{
- struct tag *ret = NULL;
-#ifdef HAVE_ID3TAG
- struct id3_tag *tag;
- FILE *stream;
-
- stream = fopen(file, "r");
- if (!stream) {
- DEBUG("tag_id3_load: Failed to open file: '%s', %s\n", file,
- strerror(errno));
- return NULL;
- }
-
- tag = findId3TagFromBeginning(stream);
- if (!tag)
- tag = findId3TagFromEnd(stream);
-
- fclose(stream);
-
- if (!tag)
- return NULL;
- ret = tag_id3_import(tag);
- id3_tag_delete(tag);
-#endif
- return ret;
-}
-
struct tag *tag_ape_load(char *file)
{
struct tag *ret = NULL;