#include "tagTracker.h" #include "log.h" #include #include #include static GTree * tagLists[TAG_NUM_OF_ITEM_TYPES] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL }; typedef struct tagTrackerItem { int count; mpd_sint8 visited; } TagTrackerItem; int keyCompare(const void *a, const void *b, void *data) { return strcmp(a,b); } char * getTagItemString(int type, char * string) { TagTrackerItem * item; TagTrackerItem ** itemPointer = &item; char *key; char **keyPointer = &key; /*if(type == TAG_ITEM_TITLE) return strdup(string);*/ if(tagLists[type] == NULL) { tagLists[type] = g_tree_new_full(keyCompare, NULL, free, free); } if((TagTrackerItem *)g_tree_lookup_extended(tagLists[type], string, (void**)keyPointer, (void**)itemPointer )) { item->count++; } else { item = malloc(sizeof(TagTrackerItem)); item->count = 1; item->visited = 0; key = strdup(string); g_tree_insert(tagLists[type], key, item); } return key; } void removeTagItemString(int type, char * string) { TagTrackerItem *item; assert(string); assert(tagLists[type]); if(tagLists[type] == NULL) return; if((item = g_tree_lookup(tagLists[type], string))) { item->count--; if(item->count <= 0) g_tree_remove(tagLists[type], string); } /* why would this be done??? free it when mpd quits... if(tagLists[type]->numberOfNodes == 0) { freeList(tagLists[type]); tagLists[type] = NULL; } */ } void destroyTagTracker() { int type; for (type=0; type < TAG_NUM_OF_ITEM_TYPES; type ++) if (tagLists[type]) g_tree_destroy(tagLists[type]); } int getNumberOfTagItems(int type) { if(tagLists[type] == NULL) return 0; return g_tree_nnodes(tagLists[type]); } int calcSavedMemory(char *key, TagTrackerItem* value, int* sum) { *sum -= sizeof(int) + 4*sizeof(void*); //sizeof(_GTreeNode) *sum -= sizeof(TagTrackerItem); *sum += (strlen(key)+1)*value->count; return FALSE; } void printMemorySavedByTagTracker() { int i; size_t sum = 0; for(i = 0; i < TAG_NUM_OF_ITEM_TYPES; i++) { if(!tagLists[i]) continue; sum -= 5*sizeof(void*);//sizeof(_GTree) g_tree_foreach(tagLists[i], (GTraverseFunc)calcSavedMemory, &sum); } DEBUG("saved memory from tags: %li\n", (long)sum); } void sortTagTrackerInfo() { /* implicit sorting int i; for(i = 0; i < TAG_NUM_OF_ITEM_TYPES; i++) { if(!tagLists[i]) continue; DEBUG("sorting %s info\n", mpdTagItemKeys[i]); sortList(tagLists[i]); }*/ } int resetVisitedFlag(char *key, TagTrackerItem *value, void *data) { value->visited = 0; return FALSE; } void resetVisitedFlagsInTagTracker(int type) { if(!tagLists[type]) return; g_tree_foreach(tagLists[type], (GTraverseFunc)resetVisitedFlag, NULL); } int wasVisitedInTagTracker(int type, char * str) { TagTrackerItem * item; if(!tagLists[type]) return 0; if(!(item = g_tree_lookup(tagLists[type], str))) return 0; return item->visited; } void visitInTagTracker(int type, char * str) { TagTrackerItem * item; if(!tagLists[type]) return; if(!(item = g_tree_lookup(tagLists[type], str))) return; item->visited = 1; } struct _PrintVisitedUserdata { FILE *fp; char *type; }; int printVisitedFlag(char *key, TagTrackerItem* value, struct _PrintVisitedUserdata *data) { if(value->visited) myfprintf(data->fp, "%s: %s\n", data->type, key); return FALSE; } void printVisitedInTagTracker(FILE * fp, int type) { struct _PrintVisitedUserdata data = {fp, mpdTagItemKeys[type]}; if(!tagLists[type]) return; g_tree_foreach( tagLists[type], (GTraverseFunc)printVisitedFlag, (void*)&data); }