2006-07-13 21:20:34 +02:00
|
|
|
/* the Music Player Daemon (MPD)
|
2006-07-14 21:37:45 +02:00
|
|
|
* (c)2003-2006 by Warren Dukes (warren.dukes@gmail.com)
|
2006-07-13 21:20:34 +02:00
|
|
|
* This project's homepage is: http://www.musicpd.org
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
*/
|
|
|
|
|
2004-11-10 22:58:27 +01:00
|
|
|
#include "tagTracker.h"
|
|
|
|
|
|
|
|
#include "log.h"
|
|
|
|
|
2005-11-16 15:43:04 +01:00
|
|
|
#include <glib/gtree.h>
|
2004-11-10 22:58:27 +01:00
|
|
|
#include <assert.h>
|
2005-11-16 15:43:04 +01:00
|
|
|
#include <stdlib.h>
|
2004-11-10 22:58:27 +01:00
|
|
|
|
2005-11-16 15:43:04 +01:00
|
|
|
static GTree * tagLists[TAG_NUM_OF_ITEM_TYPES] =
|
2004-11-10 22:58:27 +01:00
|
|
|
{
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef struct tagTrackerItem {
|
|
|
|
int count;
|
|
|
|
mpd_sint8 visited;
|
|
|
|
} TagTrackerItem;
|
|
|
|
|
2005-11-16 15:43:04 +01:00
|
|
|
int keyCompare(const void *a, const void *b, void *data) {
|
|
|
|
return strcmp(a,b);
|
|
|
|
}
|
|
|
|
|
2004-11-10 22:58:27 +01:00
|
|
|
char * getTagItemString(int type, char * string) {
|
2005-11-16 15:43:04 +01:00
|
|
|
TagTrackerItem * item;
|
|
|
|
TagTrackerItem ** itemPointer = &item;
|
|
|
|
char *key;
|
|
|
|
char **keyPointer = &key;
|
|
|
|
|
2004-11-10 22:58:27 +01:00
|
|
|
|
2004-11-14 15:58:00 +01:00
|
|
|
/*if(type == TAG_ITEM_TITLE) return strdup(string);*/
|
2004-11-14 15:42:07 +01:00
|
|
|
|
2004-11-10 22:58:27 +01:00
|
|
|
if(tagLists[type] == NULL) {
|
2005-11-16 15:43:04 +01:00
|
|
|
tagLists[type] = g_tree_new_full(keyCompare, NULL, free, free);
|
2004-11-10 22:58:27 +01:00
|
|
|
}
|
|
|
|
|
2005-11-16 15:43:04 +01:00
|
|
|
if((TagTrackerItem *)g_tree_lookup_extended(tagLists[type], string, (void**)keyPointer, (void**)itemPointer )) {
|
|
|
|
item->count++;
|
2004-11-10 22:58:27 +01:00
|
|
|
}
|
|
|
|
else {
|
2005-11-16 15:43:04 +01:00
|
|
|
item = malloc(sizeof(TagTrackerItem));
|
2004-11-10 22:58:27 +01:00
|
|
|
item->count = 1;
|
|
|
|
item->visited = 0;
|
2005-11-16 15:43:04 +01:00
|
|
|
key = strdup(string);
|
|
|
|
g_tree_insert(tagLists[type], key, item);
|
|
|
|
|
2004-11-15 20:29:20 +01:00
|
|
|
|
2004-11-10 22:58:27 +01:00
|
|
|
}
|
|
|
|
|
2005-11-16 15:43:04 +01:00
|
|
|
return key;
|
2004-11-10 22:58:27 +01:00
|
|
|
}
|
|
|
|
|
2005-11-16 15:43:04 +01:00
|
|
|
|
2004-11-10 22:58:27 +01:00
|
|
|
void removeTagItemString(int type, char * string) {
|
2005-11-16 15:43:04 +01:00
|
|
|
TagTrackerItem *item;
|
2004-11-10 22:58:27 +01:00
|
|
|
|
|
|
|
assert(string);
|
|
|
|
|
2004-11-14 15:58:00 +01:00
|
|
|
assert(tagLists[type]);
|
2004-11-10 22:58:27 +01:00
|
|
|
if(tagLists[type] == NULL) return;
|
|
|
|
|
2005-11-16 15:43:04 +01:00
|
|
|
if((item = g_tree_lookup(tagLists[type], string))) {
|
2004-11-10 22:58:27 +01:00
|
|
|
item->count--;
|
2005-11-16 15:43:04 +01:00
|
|
|
if(item->count <= 0) g_tree_remove(tagLists[type], string);
|
2004-11-10 22:58:27 +01:00
|
|
|
}
|
|
|
|
|
2005-11-16 15:43:04 +01:00
|
|
|
/* why would this be done??? free it when mpd quits...
|
|
|
|
if(tagLists[type]->numberOfNodes == 0) {
|
2004-11-10 22:58:27 +01:00
|
|
|
freeList(tagLists[type]);
|
|
|
|
tagLists[type] = NULL;
|
|
|
|
}
|
2005-11-16 15:43:04 +01:00
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
|
|
|
void destroyTagTracker() {
|
|
|
|
int type;
|
|
|
|
for (type=0; type < TAG_NUM_OF_ITEM_TYPES; type ++)
|
|
|
|
if (tagLists[type])
|
|
|
|
g_tree_destroy(tagLists[type]);
|
2004-11-10 22:58:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
int getNumberOfTagItems(int type) {
|
|
|
|
if(tagLists[type] == NULL) return 0;
|
|
|
|
|
2005-11-16 15:43:04 +01:00
|
|
|
return g_tree_nnodes(tagLists[type]);
|
2004-11-10 22:58:27 +01:00
|
|
|
}
|
2005-11-16 15:43:04 +01:00
|
|
|
int calcSavedMemory(char *key, TagTrackerItem* value, int* sum) {
|
2005-11-19 11:52:47 +01:00
|
|
|
*sum -= sizeof(int) + 4*sizeof(void*); /* sizeof(_GTreeNode) */
|
2005-11-16 15:43:04 +01:00
|
|
|
*sum -= sizeof(TagTrackerItem);
|
|
|
|
*sum += (strlen(key)+1)*value->count;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2004-11-10 22:58:27 +01:00
|
|
|
void printMemorySavedByTagTracker() {
|
|
|
|
int i;
|
|
|
|
size_t sum = 0;
|
|
|
|
|
|
|
|
for(i = 0; i < TAG_NUM_OF_ITEM_TYPES; i++) {
|
|
|
|
if(!tagLists[i]) continue;
|
|
|
|
|
2005-11-19 11:52:47 +01:00
|
|
|
sum -= 5*sizeof(void*);/* sizeof(_GTree) */
|
2005-11-16 15:43:04 +01:00
|
|
|
g_tree_foreach(tagLists[i], (GTraverseFunc)calcSavedMemory, &sum);
|
2004-11-10 22:58:27 +01:00
|
|
|
}
|
|
|
|
|
2004-11-11 06:25:05 +01:00
|
|
|
DEBUG("saved memory from tags: %li\n", (long)sum);
|
2004-11-10 22:58:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void sortTagTrackerInfo() {
|
2005-11-16 15:43:04 +01:00
|
|
|
/* implicit sorting
|
2004-11-10 22:58:27 +01:00
|
|
|
int i;
|
|
|
|
|
|
|
|
for(i = 0; i < TAG_NUM_OF_ITEM_TYPES; i++) {
|
|
|
|
if(!tagLists[i]) continue;
|
|
|
|
|
2004-11-14 00:22:22 +01:00
|
|
|
DEBUG("sorting %s info\n", mpdTagItemKeys[i]);
|
|
|
|
|
2004-11-10 22:58:27 +01:00
|
|
|
sortList(tagLists[i]);
|
2005-11-16 15:43:04 +01:00
|
|
|
}*/
|
2004-11-10 22:58:27 +01:00
|
|
|
}
|
|
|
|
|
2005-11-16 15:43:04 +01:00
|
|
|
int resetVisitedFlag(char *key, TagTrackerItem *value, void *data) {
|
|
|
|
value->visited = 0;
|
|
|
|
return FALSE;
|
|
|
|
}
|
2004-11-10 22:58:27 +01:00
|
|
|
void resetVisitedFlagsInTagTracker(int type) {
|
|
|
|
|
|
|
|
if(!tagLists[type]) return;
|
|
|
|
|
2005-11-16 15:43:04 +01:00
|
|
|
g_tree_foreach(tagLists[type], (GTraverseFunc)resetVisitedFlag, NULL);
|
2004-11-10 22:58:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
int wasVisitedInTagTracker(int type, char * str) {
|
2005-11-16 15:43:04 +01:00
|
|
|
TagTrackerItem * item;
|
2004-11-10 22:58:27 +01:00
|
|
|
|
|
|
|
if(!tagLists[type]) return 0;
|
|
|
|
|
2005-11-16 15:43:04 +01:00
|
|
|
if(!(item = g_tree_lookup(tagLists[type], str))) return 0;
|
2004-11-10 22:58:27 +01:00
|
|
|
|
2005-11-16 15:43:04 +01:00
|
|
|
return item->visited;
|
2004-11-11 14:15:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void visitInTagTracker(int type, char * str) {
|
2005-11-16 15:43:04 +01:00
|
|
|
TagTrackerItem * item;
|
2004-11-11 14:15:41 +01:00
|
|
|
|
|
|
|
if(!tagLists[type]) return;
|
|
|
|
|
2005-11-16 15:43:04 +01:00
|
|
|
if(!(item = g_tree_lookup(tagLists[type], str))) return;
|
2004-11-11 14:15:41 +01:00
|
|
|
|
2005-11-16 15:43:04 +01:00
|
|
|
item->visited = 1;
|
2004-11-10 22:58:27 +01:00
|
|
|
}
|
2004-11-11 14:15:41 +01:00
|
|
|
|
2005-11-16 15:43:04 +01:00
|
|
|
struct _PrintVisitedUserdata {
|
|
|
|
FILE *fp;
|
|
|
|
char *type;
|
|
|
|
};
|
2004-11-11 14:15:41 +01:00
|
|
|
|
2005-11-16 15:43:04 +01:00
|
|
|
int printVisitedFlag(char *key, TagTrackerItem* value, struct _PrintVisitedUserdata *data) {
|
|
|
|
if(value->visited) myfprintf(data->fp, "%s: %s\n", data->type, key);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2004-11-11 14:15:41 +01:00
|
|
|
|
2005-11-16 15:43:04 +01:00
|
|
|
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);
|
2004-11-11 14:18:44 +01:00
|
|
|
}
|