aboutsummaryrefslogtreecommitdiffstats
path: root/src/tag.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/tag.c')
-rw-r--r--src/tag.c305
1 files changed, 214 insertions, 91 deletions
diff --git a/src/tag.c b/src/tag.c
index b5c71c500..df066dc03 100644
--- a/src/tag.c
+++ b/src/tag.c
@@ -25,6 +25,8 @@
#include "inputStream.h"
#include "conf.h"
#include "charConv.h"
+#include "tagTracker.h"
+#include "mpd_types.h"
#include <sys/stat.h>
#include <stdlib.h>
@@ -40,91 +42,120 @@
#include <FLAC/metadata.h>
#endif
-void printMpdTag(FILE * fp, MpdTag * tag) {
- if(tag->artist) myfprintf(fp,"Artist: %s\n",tag->artist);
- if(tag->album) myfprintf(fp,"Album: %s\n",tag->album);
- if(tag->track) myfprintf(fp,"Track: %s\n",tag->track);
- if(tag->title) myfprintf(fp,"Title: %s\n",tag->title);
- if(tag->name) myfprintf(fp,"Name: %s\n",tag->name);
- if(tag->time>=0) myfprintf(fp,"Time: %i\n",tag->time);
-}
+char * mpdTagItemKeys[TAG_NUM_OF_ITEM_TYPES] =
+{
+ "Artist",
+ "Album",
+ "Title",
+ "Track",
+ "Name",
+ "Genre",
+ "Date"
+};
+
+static mpd_sint8 ignoreTagItems[TAG_NUM_OF_ITEM_TYPES];
+
+void initTagConfig() {
+ int quit = 0;
+ char * temp;
+ char * s;
+ char * c;
+ ConfigParam * param;
+ int i;
+
+ memset(ignoreTagItems, 0, TAG_NUM_OF_ITEM_TYPES);
+
+ param = getConfigParam(CONF_METADATA_TO_USE);
+
+ if(!param) return;
+
+ memset(ignoreTagItems, 1, TAG_NUM_OF_ITEM_TYPES);
+
+ if(0 == strcasecmp(param->value, "none")) return;
+
+ temp = c = s = strdup(param->value);
+ while(!quit) {
+ if(*s == ',' || *s == '\0') {
+ if(*s == '\0') quit = 1;
+ *s = '\0';
+ for(i = 0; i < TAG_NUM_OF_ITEM_TYPES; i++) {
+ if(strcasecmp(c, mpdTagItemKeys[i]) == 0) {
+ ignoreTagItems[i] = 0;
+ break;
+ }
+ }
+ if(strlen(c) && i == TAG_NUM_OF_ITEM_TYPES) {
+ ERROR("error parsing metadata item \"%s\" at "
+ "line %i\n", c, param->line);
+ exit(EXIT_FAILURE);
+ }
+ s++;
+ c = s;
+ }
+ s++;
+ }
-#define fixUtf8(str) { \
- if(str && !validUtf8String(str)) { \
- char * temp; \
- DEBUG("not valid utf8 in tag: %s\n",str); \
- temp = latin1StrToUtf8Dup(str); \
- free(str); \
- str = temp; \
- } \
+ free(temp);
}
-void validateUtf8Tag(MpdTag * tag) {
- fixUtf8(tag->artist);
- stripReturnChar(tag->artist);
- fixUtf8(tag->album);
- stripReturnChar(tag->album);
- fixUtf8(tag->track);
- stripReturnChar(tag->track);
- fixUtf8(tag->title);
- stripReturnChar(tag->title);
- fixUtf8(tag->name);
- stripReturnChar(tag->name);
+void printMpdTag(FILE * fp, MpdTag * tag) {
+ int i;
+
+ if(tag->time>=0) myfprintf(fp,"Time: %i\n",tag->time);
+
+ for(i = 0; i < tag->numOfItems; i++) {
+ myfprintf(fp, "%s: %s\n", mpdTagItemKeys[tag->items[i].type],
+ tag->items[i].value);
+ }
}
#ifdef HAVE_ID3TAG
-char * getID3Info(struct id3_tag * tag, char * id) {
+MpdTag * getID3Info(struct id3_tag * tag, char * id, int type, MpdTag * mpdTag)
+{
struct id3_frame const * frame;
id3_ucs4_t const * ucs4;
id3_utf8_t * utf8;
union id3_field const * field;
unsigned int nstrings;
+ int i;
frame = id3_tag_findframe(tag, id, 0);
- if(!frame) return NULL;
+ if(!frame) return mpdTag;
field = &frame->fields[1];
nstrings = id3_field_getnstrings(field);
- if(nstrings<1) return NULL;
- ucs4 = id3_field_getstrings(field,0);
- assert(ucs4);
+ for(i = 0; i < nstrings; i++) {
+ ucs4 = id3_field_getstrings(field, i);
+ assert(ucs4);
+
+ if(type == TAG_ITEM_GENRE) {
+ ucs4 = id3_genre_name(ucs4);
+ }
+
+ utf8 = id3_ucs4_utf8duplicate(ucs4);
+ if(!utf8) continue;
- utf8 = id3_ucs4_utf8duplicate(ucs4);
- if(!utf8) return NULL;
+ if( NULL == mpdTag ) mpdTag = newMpdTag();
+ addItemToMpdTag(mpdTag, type, utf8);
+
+ free(utf8);
+ }
- return utf8;
+ return mpdTag;
}
#endif
#ifdef HAVE_ID3TAG
MpdTag * parseId3Tag(struct id3_tag * tag) {
MpdTag * ret = NULL;
- char * str;
- str = getID3Info(tag,ID3_FRAME_ARTIST);
- if(str) {
- if(!ret) ret = newMpdTag();
- ret->artist = str;
- }
-
- str = getID3Info(tag,ID3_FRAME_TITLE);
- if(str) {
- if(!ret) ret = newMpdTag();
- ret->title = str;
- }
-
- str = getID3Info(tag,ID3_FRAME_ALBUM);
- if(str) {
- if(!ret) ret = newMpdTag();
- ret->album = str;
- }
-
- str = getID3Info(tag,ID3_FRAME_TRACK);
- if(str) {
- if(!ret) ret = newMpdTag();
- ret->track = str;
- }
+ 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);
return ret;
}
@@ -158,21 +189,61 @@ MpdTag * id3Dup(char * file) {
MpdTag * newMpdTag() {
MpdTag * ret = malloc(sizeof(MpdTag));
- ret->album = NULL;
- ret->artist = NULL;
- ret->title = NULL;
- ret->track = NULL;
- ret->name = NULL;
+ ret->items = NULL;
ret->time = -1;
+ ret->numOfItems = 0;
return ret;
}
+static void deleteItem(MpdTag * tag, int index) {
+ tag->numOfItems--;
+
+ assert(index < tag->numOfItems);
+
+ removeTagItemString(tag->items[index].type, tag->items[index].value);
+ //free(tag->items[index].value);
+
+ if(tag->numOfItems-index > 0) {
+ memmove(tag->items+index, tag->items+index+1,
+ tag->numOfItems-index);
+ }
+
+ if(tag->numOfItems > 0) {
+ tag->items = realloc(tag->items,
+ tag->numOfItems*sizeof(MpdTagItem));
+ }
+ else {
+ free(tag->items);
+ tag->items = NULL;
+ }
+}
+
+void clearItemsFromMpdTag(MpdTag * tag, int type) {
+ int i = 0;
+
+ for(i = 0; i < tag->numOfItems; i++) {
+ if(tag->items[i].type == type) {
+ deleteItem(tag, i);
+ /* decrement since when just deleted this node */
+ i--;
+ }
+ }
+}
+
void clearMpdTag(MpdTag * tag) {
- if(tag->artist) free(tag->artist);
- if(tag->album) free(tag->album);
- if(tag->title) free(tag->title);
- if(tag->name) free(tag->name);
- if(tag->track) free(tag->track);
+ int i;
+
+ for(i = 0; i < tag->numOfItems; i++) {
+ removeTagItemString(tag->items[i].type, tag->items[i].value);
+ //free(tag->items[i].value);
+ }
+
+ if(tag->items) free(tag->items);
+ tag->items = NULL;
+
+ tag->numOfItems = 0;
+
+ tag->time = -1;
}
void freeMpdTag(MpdTag * tag) {
@@ -182,40 +253,92 @@ void freeMpdTag(MpdTag * tag) {
MpdTag * mpdTagDup(MpdTag * tag) {
MpdTag * ret = NULL;
+ int i;
- if(tag) {
- ret = newMpdTag();
- if(tag->artist) ret->artist = strdup(tag->artist);
- if(tag->album) ret->album = strdup(tag->album);
- if(tag->title) ret->title = strdup(tag->title);
- if(tag->track) ret->track = strdup(tag->track);
- if(tag->name) ret->name = strdup(tag->name);
- ret->time = tag->time;
- }
+ if(!tag) return NULL;
- return ret;
-}
+ ret = newMpdTag();
+ ret->time = tag->time;
-int mpdTagStringsAreEqual(char * s1, char * s2) {
- if(s1 && s2) {
- if(strcmp(s1, s2)) return 0;
- }
- else if(s1 || s2) return 0;
+ for(i = 0; i < tag->numOfItems; i++) {
+ addItemToMpdTag(ret, tag->items[i].type, tag->items[i].value);
+ }
- return 1;
+ return ret;
}
int mpdTagsAreEqual(MpdTag * tag1, MpdTag * tag2) {
+ int i;
+
if(tag1 == NULL && tag2 == NULL) return 1;
else if(!tag1 || !tag2) return 0;
if(tag1->time != tag2->time) return 0;
- if(!mpdTagStringsAreEqual(tag1->artist, tag2->artist)) return 0;
- if(!mpdTagStringsAreEqual(tag1->album, tag2->album)) return 0;
- if(!mpdTagStringsAreEqual(tag1->track, tag2->track)) return 0;
- if(!mpdTagStringsAreEqual(tag1->title, tag2->title)) return 0;
- if(!mpdTagStringsAreEqual(tag1->name, tag2->name)) return 0;
+ if(tag1->numOfItems != tag2->numOfItems) return 0;
+
+ for(i = 0; i < tag1->numOfItems; i++) {
+ if(tag1->items[i].type != tag2->items[i].type) return 0;
+ if(strcmp(tag1->items[i].value, tag2->items[i].value)) {
+ return 0;
+ }
+ }
return 1;
}
+
+#define fixUtf8(str) { \
+ if(str && !validUtf8String(str)) { \
+ char * temp; \
+ DEBUG("not valid utf8 in tag: %s\n",str); \
+ temp = latin1StrToUtf8Dup(str); \
+ free(str); \
+ str = temp; \
+ } \
+}
+
+inline static void appendToTagItems(MpdTag * tag, int type, char * value,
+ int len)
+{
+ int i = tag->numOfItems;
+
+ char * dup;
+ dup = malloc(len+1);
+ strncpy(dup, value, len);
+ dup[len] = '\0';
+
+ fixUtf8(dup);
+
+ tag->numOfItems++;
+ tag->items = realloc(tag->items, tag->numOfItems*sizeof(MpdTagItem));
+
+ tag->items[i].type = type;
+ tag->items[i].value = getTagItemString(type, dup);
+ //tag->items[i].value = strdup(dup);
+
+ free(dup);
+}
+
+void addItemToMpdTagWithLen(MpdTag * tag, int itemType, char * value, int len) {
+ if(ignoreTagItems[itemType]) return;
+
+ if(!value || !len) return;
+
+ appendToTagItems(tag, itemType, value, len);
+}
+
+char * getNextItemFromMpdTag(MpdTag * tag, int itemType, int * last) {
+ int i = 0;
+
+ if(last && *last >=0) i = *last+1;
+
+ for(i = 0; i < tag->numOfItems; i++) {
+ if(itemType == tag->items[i].type) {
+ if(last) *last = i;
+ return tag->items[i].value;
+ }
+ i++;
+ }
+
+ return NULL;
+}