diff options
Diffstat (limited to 'src/tag.c')
-rw-r--r-- | src/tag.c | 305 |
1 files changed, 214 insertions, 91 deletions
@@ -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; +} |