aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--configure.ac4
-rw-r--r--src/decode.c2
-rw-r--r--src/directory.c3
-rw-r--r--src/listen.c3
-rw-r--r--src/listen.h1
-rw-r--r--src/main.c74
-rw-r--r--src/player.c68
-rw-r--r--src/playerData.c26
-rw-r--r--src/playerData.h2
-rw-r--r--src/sig_handlers.c81
-rw-r--r--src/sig_handlers.h4
-rw-r--r--src/tagTracker.c134
-rw-r--r--src/tagTracker.h1
13 files changed, 288 insertions, 115 deletions
diff --git a/configure.ac b/configure.ac
index 26219464b..264fcc707 100644
--- a/configure.ac
+++ b/configure.ac
@@ -84,6 +84,10 @@ AC_CHECK_LIB(nsl,gethostbyname,MPD_LIBS="$MPD_LIBS -lnsl",)
AC_CHECK_LIB(m,exp,MPD_LIBS="$MPD_LIBS -lm",)
+PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.0, [MPD_LIBS="$MPD_LIBS $GLIB_LIBS" MPD_CFLAGS="$MPD_CFLAGS $GLIB_CFLAGS"],[echo "Unable to find glib-2.0 of version 2.0 or above"])
+
+
+
dnl doesn't work for systems that don't have CODESET like OpenBSD
dnl AC_CHECK_HEADER(langinfo.h,[enable_langinfo=yes;AC_DEFINE(HAVE_LANGINFO,1,[Define if nl_langinfo.h is present])],enable_langinfo=no)
AM_LANGINFO_CODESET
diff --git a/src/decode.c b/src/decode.c
index 56fdb1979..9af2c7e4f 100644
--- a/src/decode.c
+++ b/src/decode.c
@@ -399,7 +399,7 @@ int decoderInit(PlayerControl * pc, OutputBuffer * cb, DecoderControl * dc) {
pc->error = PLAYER_ERROR_SYSTEM;
return -1;
}
-
+ DEBUG("decoder PID: %d\n", decode_pid);
getPlayerData()->playerControl.decode_pid = decode_pid;
unblockSignals();
diff --git a/src/directory.c b/src/directory.c
index 694ffc08a..8f884f9c3 100644
--- a/src/directory.c
+++ b/src/directory.c
@@ -178,7 +178,7 @@ int updateInit(FILE * fp, List * pathList) {
if(directory_updatePid==0) {
/* child */
int dbUpdated = 0;
- clearPlayerPid();
+ //clearPlayerPid();
unblockSignals();
@@ -784,6 +784,7 @@ int addToDirectory(Directory * directory, char * shortname, char * name) {
void closeMp3Directory() {
freeDirectory(mp3rootDirectory);
+ destroyTagTracker();
}
Directory * findSubDirectory(Directory * directory,char * name) {
diff --git a/src/listen.c b/src/listen.c
index a951595fc..bea0be9bb 100644
--- a/src/listen.c
+++ b/src/listen.c
@@ -213,7 +213,10 @@ void closeAllListenSockets() {
DEBUG("closing listen socket %i\n", i);
while(close(listenSockets[i]) < 0 && errno==EINTR);
}
+ freeAllListenSockets();
+}
+void freeAllListenSockets() {
numberOfListenSockets = 0;
free(listenSockets);
listenSockets = NULL;
diff --git a/src/listen.h b/src/listen.h
index ff889320f..1238a2f62 100644
--- a/src/listen.h
+++ b/src/listen.h
@@ -33,6 +33,7 @@ void getConnections(fd_set * fds);
int isAListenSocket(int sock);
void closeAllListenSockets();
+void freeAllListenSockets();
/* fdmax should be initialized to something */
void addListenSocketsToFdSet(fd_set * fds, int * fdmax);
diff --git a/src/main.c b/src/main.c
index 67c76a981..4c6ef9c26 100644
--- a/src/main.c
+++ b/src/main.c
@@ -54,6 +54,9 @@
#define SYSTEM_CONFIG_FILE_LOCATION "/etc/mpd.conf"
#define USER_CONFIG_FILE_LOCATION "/.mpdconf"
+volatile int masterPid = 0;
+volatile int mainPid = 0;
+
typedef struct _Options {
int kill;
int daemon;
@@ -288,6 +291,45 @@ void openDB(Options * options, char * argv0) {
}
}
+void startMainProcess() {
+ int pid;
+ fflush(0);
+ pid = fork();
+ if(pid>0) {
+ initInputStream();
+ initReplayGainState();
+ /* qball crappy code */
+ readAudioDevicesState();
+
+ /* free stuff we don't need */
+ freeAllListenSockets();
+
+ mainPid = pid;
+ masterInitSigHandlers();
+ while (masterHandlePendingSignals()!=COMMAND_RETURN_KILL)
+ waitOnSignals();
+ /* we're killed */
+ playerKill();
+
+ finishAudioConfig();
+ finishAudioDriver();
+
+ /* qball crappy code */
+ saveAudioDevicesState();
+
+ finishPaths();
+
+ kill(mainPid, SIGTERM);
+ exit(EXIT_SUCCESS);
+
+ } else if(pid<0) {
+ ERROR("problems fork'ing main process!\n");
+ exit(EXIT_FAILURE);
+ }
+
+ DEBUG("main process started!\n");
+}
+
void daemonize(Options * options) {
FILE * fp;
ConfigParam * pidFileParam = parseConfigFilePath(CONF_PID_FILE, 1);
@@ -338,6 +380,7 @@ void daemonize(Options * options) {
DEBUG("writing pid file\n");
fprintf(fp, "%lu\n", (unsigned long)getpid());
fclose(fp);
+ masterPid = getpid();
}
void setupLogOutput(Options * options, FILE * out, FILE * err) {
@@ -451,6 +494,7 @@ int main(int argc, char * argv[]) {
parseOptions(argc, argv, &options);
if(options.kill) killFromPidFile(argv[0], options.kill);
+
initStats();
initTagConfig();
@@ -459,31 +503,39 @@ int main(int argc, char * argv[]) {
if(options.createDB <= 0 && !options.updateDB) listenOnPort();
changeToUser();
-
+
openLogFiles(&options, &out, &err);
+ initPlayerData();
+
+ daemonize(&options);
+
+ initInputPlugins();
initPaths();
+ initAudioConfig();
+ initAudioDriver();
+
+ startMainProcess();
+ /* This is the main process which has
+ * been forked from the master process.
+ */
+
+
+
initPermissions();
- initReplayGainState();
initPlaylist();
- initInputPlugins();
openDB(&options, argv[0]);
initCommands();
- initPlayerData();
- initAudioConfig();
- initAudioDriver();
initVolume();
initInterfaces();
- initInputStream();
printMemorySavedByTagTracker();
printSavedMemoryFromFilenames();
/*printSavedMemoryFromDirectoryNames();*/
- daemonize(&options);
setupLogOutput(&options, out, err);
@@ -491,8 +543,6 @@ int main(int argc, char * argv[]) {
initSigHandlers();
readPlaylistState();
- /* qball crappy code */
- readAudioDevicesState();
while(COMMAND_RETURN_KILL!=doIOForInterfaces()) {
if(COMMAND_RETURN_KILL==handlePendingSignals()) break;
@@ -502,12 +552,8 @@ int main(int argc, char * argv[]) {
}
savePlaylistState();
- /* qball crappy code */
- saveAudioDevicesState();
- playerKill();
-
freeAllInterfaces();
closeAllListenSockets();
closeMp3Directory();
diff --git a/src/player.c b/src/player.c
index e398323e8..7ae814f98 100644
--- a/src/player.c
+++ b/src/player.c
@@ -43,11 +43,7 @@
#include <errno.h>
#include <fcntl.h>
-volatile int player_pid = 0;
-
-void clearPlayerPid() {
- player_pid = 0;
-}
+extern int masterPid;
static void resetPlayerMetadata() {
PlayerControl * pc = &(getPlayerData()->playerControl);
@@ -60,7 +56,7 @@ static void resetPlayerMetadata() {
void resetPlayer() {
int pid;
- clearPlayerPid();
+ setPlayerPid(0);
getPlayerData()->playerControl.stop = 0;
getPlayerData()->playerControl.play = 0;
getPlayerData()->playerControl.pause = 0;
@@ -77,7 +73,7 @@ void resetPlayer() {
}
void player_sigChldHandler(int pid, int status) {
- if(player_pid==pid) {
+ if(getPlayerPid()==pid) {
DEBUG("SIGCHLD caused by player process\n");
if(WIFSIGNALED(status) && WTERMSIG(status)!=SIGTERM &&
WTERMSIG(status)!=SIGINT)
@@ -87,7 +83,7 @@ void player_sigChldHandler(int pid, int status) {
}
resetPlayer();
}
- else if(pid==getPlayerData()->playerControl.decode_pid && player_pid<=0)
+ else if(pid==getPlayerData()->playerControl.decode_pid && getPlayerPid()<=0)
{
if(WIFSIGNALED(status) && WTERMSIG(status)!=SIGTERM) {
ERROR("(caught by master parent) "
@@ -100,24 +96,31 @@ void player_sigChldHandler(int pid, int status) {
}
int playerInit() {
+ kill(masterPid, SIGUSR2);
+ while (getPlayerPid()==0) my_usleep(10000); //we need to wait for the signal to take effect
+ return 0;
+}
+
+int playerInitReal() {
+ int player_pid;
blockSignals();
player_pid = fork();
if(player_pid==0) {
PlayerControl * pc = &(getPlayerData()->playerControl);
- clearUpdatePid();
+ //clearUpdatePid();
unblockSignals();
setSigHandlersForDecoder();
- closeAllListenSockets();
- freeAllInterfaces();
- closeMp3Directory();
- finishPlaylist();
- finishPermissions();
- finishCommands();
- finishVolume();
+ //closeAllListenSockets();
+ //freeAllInterfaces();
+ //closeMp3Directory();
+ //finishPlaylist();
+ //finishPermissions();
+ //finishCommands();
+ //finishVolume();
while(1) {
if(pc->play) decode();
@@ -148,10 +151,13 @@ int playerInit() {
else if(player_pid<0) {
unblockSignals();
ERROR("player Problems fork()'ing\n");
+ setPlayerPid(0);
player_pid = 0;
-
return -1;
}
+ else
+ setPlayerPid(player_pid);
+
unblockSignals();
return 0;
@@ -183,13 +189,13 @@ int playerPlay(FILE * fp, Song * song) {
pc->utf8url[MAXPATHLEN] = '\0';
pc->play = 1;
- if(player_pid==0 && playerInit()<0) {
+ if(getPlayerPid()==0 && playerInit()<0) {
pc->play = 0;
return -1;
}
resetPlayerMetadata();
- while(player_pid>0 && pc->play) my_usleep(1000);
+ while(getPlayerPid()>0 && pc->play) my_usleep(1000);
return 0;
}
@@ -197,9 +203,9 @@ int playerPlay(FILE * fp, Song * song) {
int playerStop(FILE * fp) {
PlayerControl * pc = &(getPlayerData()->playerControl);
- if(player_pid>0 && pc->state!=PLAYER_STATE_STOP) {
+ if(getPlayerPid()>0 && pc->state!=PLAYER_STATE_STOP) {
pc->stop = 1;
- while(player_pid>0 && pc->stop) my_usleep(1000);
+ while(getPlayerPid()>0 && pc->stop) my_usleep(1000);
}
pc->queueState = PLAYER_QUEUE_BLANK;
@@ -216,16 +222,16 @@ void playerKill() {
playerCloseAudio(stderr);
if(player_pid>0 && pc->closeAudio) sleep(1);*/
- pid = player_pid;
+ pid = getPlayerPid();
if(pid>0) kill(pid,SIGTERM);
}
int playerPause(FILE * fp) {
PlayerControl * pc = &(getPlayerData()->playerControl);
- if(player_pid>0 && pc->state!=PLAYER_STATE_STOP) {
+ if(getPlayerPid()>0 && pc->state!=PLAYER_STATE_STOP) {
pc->pause = 1;
- while(player_pid>0 && pc->pause) my_usleep(1000);
+ while(getPlayerPid()>0 && pc->pause) my_usleep(1000);
}
return 0;
@@ -234,7 +240,7 @@ int playerPause(FILE * fp) {
int playerSetPause(FILE * fp, int pause) {
PlayerControl * pc = &(getPlayerData()->playerControl);
- if(player_pid<=0) return 0;
+ if(getPlayerPid()<=0) return 0;
switch(pc->state) {
case PLAYER_STATE_PLAY:
@@ -314,7 +320,7 @@ char * getPlayerErrorStr() {
void playerCloseAudio() {
PlayerControl * pc = &(getPlayerData()->playerControl);
- if(player_pid>0) {
+ if(getPlayerPid()>0) {
if(playerStop(stderr)<0) return;
pc->closeAudio = 1;
}
@@ -354,20 +360,20 @@ void setQueueState(int queueState) {
void playerQueueLock() {
PlayerControl * pc = &(getPlayerData()->playerControl);
- if(player_pid>0 && pc->queueLockState==PLAYER_QUEUE_UNLOCKED)
+ if(getPlayerPid()>0 && pc->queueLockState==PLAYER_QUEUE_UNLOCKED)
{
pc->lockQueue = 1;
- while(player_pid>0 && pc->lockQueue) my_usleep(1000);
+ while(getPlayerPid()>0 && pc->lockQueue) my_usleep(1000);
}
}
void playerQueueUnlock() {
PlayerControl * pc = &(getPlayerData()->playerControl);
- if(player_pid>0 && pc->queueLockState==PLAYER_QUEUE_LOCKED)
+ if(getPlayerPid()>0 && pc->queueLockState==PLAYER_QUEUE_LOCKED)
{
pc->unlockQueue = 1;
- while(player_pid>0 && pc->unlockQueue) my_usleep(1000);
+ while(getPlayerPid()>0 && pc->unlockQueue) my_usleep(1000);
}
}
@@ -394,7 +400,7 @@ int playerSeek(FILE * fp, Song * song, float time) {
resetPlayerMetadata();
pc->seekWhere = time;
pc->seek = 1;
- while(player_pid>0 && pc->seek) my_usleep(1000);
+ while(getPlayerPid()>0 && pc->seek) my_usleep(1000);
}
return 0;
diff --git a/src/playerData.c b/src/playerData.c
index 281453548..060227f4b 100644
--- a/src/playerData.c
+++ b/src/playerData.c
@@ -34,6 +34,7 @@ int buffered_chunks;
#define DEFAULT_BUFFER_BEFORE_PLAY 0
PlayerData * playerData_pd;
+int * player_pid;
void initPlayerData() {
float perc = DEFAULT_BUFFER_BEFORE_PLAY;
@@ -102,6 +103,22 @@ void initPlayerData() {
ERROR("problems shmctl'ing\n");
exit(EXIT_FAILURE);
}
+ /* maybe the following should be put in the same shm block as the previous
+ * or maybe even made a part of the playerData struct
+ */
+ allocationSize = sizeof(int);
+ if((shmid = shmget(IPC_PRIVATE,allocationSize,IPC_CREAT|0600))<0) {
+ ERROR("problems shmget'ing\n");
+ exit(EXIT_FAILURE);
+ }
+ if((player_pid = shmat(shmid,NULL,0))<0) {
+ ERROR("problems shmat'ing\n");
+ exit(EXIT_FAILURE);
+ }
+ if (shmctl(shmid, IPC_RMID, 0)<0) {
+ ERROR("problems shmctl'ing\n");
+ exit(EXIT_FAILURE);
+ }
buffer = &(playerData_pd->buffer);
@@ -147,6 +164,15 @@ PlayerData * getPlayerData() {
return playerData_pd;
}
+int getPlayerPid() {
+ return *player_pid;
+}
+
+void setPlayerPid(int pid) {
+ *player_pid = pid;
+}
+
void freePlayerData() {
shmdt(playerData_pd);
+ shmdt(player_pid);
}
diff --git a/src/playerData.h b/src/playerData.h
index b8fdf1a2b..40a9d687e 100644
--- a/src/playerData.h
+++ b/src/playerData.h
@@ -43,6 +43,8 @@ typedef struct _PlayerData {
void initPlayerData();
PlayerData * getPlayerData();
+int getPlayerPid();
+void setPlayerPid(int pid);
void freePlayerData();
diff --git a/src/sig_handlers.c b/src/sig_handlers.c
index a3bf93050..364636e7c 100644
--- a/src/sig_handlers.c
+++ b/src/sig_handlers.c
@@ -19,6 +19,7 @@
#include "sig_handlers.h"
#include "player.h"
+#include "playerData.h"
#include "playlist.h"
#include "directory.h"
#include "command.h"
@@ -33,10 +34,30 @@
#include <sys/resource.h>
#include <sys/wait.h>
#include <errno.h>
+#include <unistd.h>
+
+extern volatile int masterPid;
+extern volatile int mainPid;
+
+int masterHandlePendingSignals() {
+ if(signal_is_pending(SIGINT) || signal_is_pending(SIGTERM)) {
+ DEBUG("master process got SIGINT or SIGTERM, exiting\n");
+ return COMMAND_RETURN_KILL;
+ }
+
+ if(signal_is_pending(SIGHUP)) {
+ signal_clear(SIGHUP);
+ /* Forward it to the main process, which will update the DB */
+ kill(mainPid, SIGHUP);
+ }
+
+
+ return 0;
+}
int handlePendingSignals() {
if(signal_is_pending(SIGINT) || signal_is_pending(SIGTERM)) {
- DEBUG("got SIGINT or SIGTERM, exiting\n");
+ DEBUG("main process got SIGINT or SIGTERM, exiting\n");
return COMMAND_RETURN_KILL;
}
@@ -57,17 +78,55 @@ int handlePendingSignals() {
void chldSigHandler(int signal) {
int status;
int pid;
- DEBUG("got SIGCHLD\n");
+ DEBUG("main process got SIGCHLD\n");
while(0 != (pid = wait3(&status,WNOHANG,NULL))) {
if(pid<0) {
if(errno==EINTR) continue;
else break;
}
- player_sigChldHandler(pid,status);
directory_sigChldHandler(pid,status);
}
}
+void masterChldSigHandler(int signal) {
+ int status;
+ int pid;
+ DEBUG("master process got SIGCHLD\n");
+ while(0 != (pid = wait3(&status,WNOHANG,NULL))) {
+ if(pid<0) {
+ if(errno==EINTR) continue;
+ else break;
+ }
+ DEBUG("PID: %d\n",pid);
+ if (pid == mainPid) kill(getpid(), SIGTERM);
+ player_sigChldHandler(pid,status);
+ }
+}
+
+int playerInitReal();
+
+void masterSigUsr2Handler(int signal) {
+ DEBUG("Master process got SIGUSR2 starting a new player process\n");
+ if (getPlayerPid() <= 0)
+ playerInitReal();
+}
+
+void masterInitSigHandlers() {
+ struct sigaction sa;
+
+ sa.sa_flags = 0;
+ sa.sa_handler = SIG_IGN;
+ while(sigaction(SIGPIPE,&sa,NULL)<0 && errno==EINTR);
+ sa.sa_handler = masterChldSigHandler;
+ while(sigaction(SIGCHLD,&sa,NULL)<0 && errno==EINTR);
+ sa.sa_handler = masterSigUsr2Handler;
+ while(sigaction(SIGUSR2,&sa,NULL)<0 && errno==EINTR);
+ signal_handle(SIGUSR1);
+ signal_handle(SIGINT);
+ signal_handle(SIGTERM);
+ signal_handle(SIGHUP);
+}
+
void initSigHandlers() {
struct sigaction sa;
@@ -114,17 +173,32 @@ void ignoreSignals() {
while(sigaction(SIGPIPE,&sa,NULL)<0 && errno==EINTR);
while(sigaction(SIGCHLD,&sa,NULL)<0 && errno==EINTR);
while(sigaction(SIGUSR1,&sa,NULL)<0 && errno==EINTR);
+ while(sigaction(SIGUSR2,&sa,NULL)<0 && errno==EINTR);
while(sigaction(SIGINT,&sa,NULL)<0 && errno==EINTR);
while(sigaction(SIGTERM,&sa,NULL)<0 && errno==EINTR);
while(sigaction(SIGHUP,&sa,NULL)<0 && errno==EINTR);
}
+void waitOnSignals() {
+ sigset_t sset;
+
+ sigfillset(&sset);
+ sigdelset(&sset,SIGCHLD);
+ sigdelset(&sset,SIGUSR1);
+ sigdelset(&sset,SIGUSR2);
+ sigdelset(&sset,SIGHUP);
+ sigdelset(&sset,SIGINT);
+ sigdelset(&sset,SIGTERM);
+ sigsuspend(&sset);
+}
+
void blockSignals() {
sigset_t sset;
sigemptyset(&sset);
sigaddset(&sset,SIGCHLD);
sigaddset(&sset,SIGUSR1);
+ sigaddset(&sset,SIGUSR2);
sigaddset(&sset,SIGHUP);
sigaddset(&sset,SIGINT);
sigaddset(&sset,SIGTERM);
@@ -137,6 +211,7 @@ void unblockSignals() {
sigemptyset(&sset);
sigaddset(&sset,SIGCHLD);
sigaddset(&sset,SIGUSR1);
+ sigaddset(&sset,SIGUSR2);
sigaddset(&sset,SIGHUP);
sigaddset(&sset,SIGINT);
sigaddset(&sset,SIGTERM);
diff --git a/src/sig_handlers.h b/src/sig_handlers.h
index 59031afa7..1bdce07d6 100644
--- a/src/sig_handlers.h
+++ b/src/sig_handlers.h
@@ -22,8 +22,10 @@
#include "../config.h"
int handlePendingSignals();
+int masterHandlePendingSignals();
void initSigHandlers();
+void masterInitSigHandlers();
void finishSigHandlers();
@@ -31,6 +33,8 @@ void setSigHandlersForDecoder();
void ignoreSignals();
+void waitOnSignals();
+
void blockSignals();
void unblockSignals();
diff --git a/src/tagTracker.c b/src/tagTracker.c
index 57a96c70b..4fb326535 100644
--- a/src/tagTracker.c
+++ b/src/tagTracker.c
@@ -1,11 +1,12 @@
#include "tagTracker.h"
-#include "list.h"
#include "log.h"
+#include <glib/gtree.h>
#include <assert.h>
+#include <stdlib.h>
-static List * tagLists[TAG_NUM_OF_ITEM_TYPES] =
+static GTree * tagLists[TAG_NUM_OF_ITEM_TYPES] =
{
NULL,
NULL,
@@ -21,89 +22,96 @@ typedef struct tagTrackerItem {
mpd_sint8 visited;
} TagTrackerItem;
+int keyCompare(const void *a, const void *b, void *data) {
+ return strcmp(a,b);
+}
+
char * getTagItemString(int type, char * string) {
- ListNode * node;
- int pos;
+ TagTrackerItem * item;
+ TagTrackerItem ** itemPointer = &item;
+ char *key;
+ char **keyPointer = &key;
+
/*if(type == TAG_ITEM_TITLE) return strdup(string);*/
if(tagLists[type] == NULL) {
- tagLists[type] = makeList(free, 1);
- sortList(tagLists[type]);
+ tagLists[type] = g_tree_new_full(keyCompare, NULL, free, free);
}
- if(findNodeInList(tagLists[type], string, &node, &pos)) {
- ((TagTrackerItem *)node->data)->count++;
+ if((TagTrackerItem *)g_tree_lookup_extended(tagLists[type], string, (void**)keyPointer, (void**)itemPointer )) {
+ item->count++;
}
else {
- TagTrackerItem * item = malloc(sizeof(TagTrackerItem));
+ item = malloc(sizeof(TagTrackerItem));
item->count = 1;
item->visited = 0;
- node = insertInListBeforeNode(tagLists[type], node, pos,
- string, item);
+ key = strdup(string);
+ g_tree_insert(tagLists[type], key, item);
+
}
- return node->key;
+ return key;
}
+
void removeTagItemString(int type, char * string) {
- ListNode * node;
- int pos;
+ TagTrackerItem *item;
assert(string);
assert(tagLists[type]);
if(tagLists[type] == NULL) return;
- /*if(!node) {
- free(string);
- return;
- }*/
-
- if(findNodeInList(tagLists[type], string, &node, &pos)) {
- TagTrackerItem * item = node->data;
+ if((item = g_tree_lookup(tagLists[type], string))) {
item->count--;
- if(item->count <= 0) deleteNodeFromList(tagLists[type], node);
+ if(item->count <= 0) g_tree_remove(tagLists[type], string);
}
- if(tagLists[type]->numberOfNodes == 0) {
+/* 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 tagLists[type]->numberOfNodes;
+ 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;
- ListNode * node;
size_t sum = 0;
for(i = 0; i < TAG_NUM_OF_ITEM_TYPES; i++) {
if(!tagLists[i]) continue;
- sum -= sizeof(List);
-
- node = tagLists[i]->firstNode;
-
- while(node != NULL) {
- sum -= sizeof(ListNode);
- sum -= sizeof(TagTrackerItem);
- sum -= sizeof(node->key);
- sum += (strlen(node->key)+1)*(*((int *)node->data));
- node = node->nextNode;
- }
+ 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++) {
@@ -112,56 +120,52 @@ void sortTagTrackerInfo() {
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) {
- ListNode * node;
if(!tagLists[type]) return;
- node = tagLists[type]->firstNode;
-
- while(node) {
- ((TagTrackerItem *)node->data)->visited = 0;
- node = node->nextNode;
- }
+ g_tree_foreach(tagLists[type], (GTraverseFunc)resetVisitedFlag, NULL);
}
int wasVisitedInTagTracker(int type, char * str) {
- void * item;
+ TagTrackerItem * item;
if(!tagLists[type]) return 0;
- if(!findInList(tagLists[type], str, &item)) return 0;
+ if(!(item = g_tree_lookup(tagLists[type], str))) return 0;
- return ((TagTrackerItem *)item)->visited;
+ return item->visited;
}
void visitInTagTracker(int type, char * str) {
- void * item;
+ TagTrackerItem * item;
if(!tagLists[type]) return;
- if(!findInList(tagLists[type], str, &item)) return;
+ if(!(item = g_tree_lookup(tagLists[type], str))) return;
- ((TagTrackerItem *)item)->visited = 1;
+ item->visited = 1;
}
-void printVisitedInTagTracker(FILE * fp, int type) {
- ListNode * node;
- TagTrackerItem * item;
-
- if(!tagLists[type]) return;
+struct _PrintVisitedUserdata {
+ FILE *fp;
+ char *type;
+};
- node = tagLists[type]->firstNode;
+int printVisitedFlag(char *key, TagTrackerItem* value, struct _PrintVisitedUserdata *data) {
+ if(value->visited) myfprintf(data->fp, "%s: %s\n", data->type, key);
+ return FALSE;
+}
- while(node) {
- item = node->data;
- if(item->visited) {
- myfprintf(fp, "%s: %s\n", mpdTagItemKeys[type],
- node->key);
- }
- node = node->nextNode;
- }
+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);
}
diff --git a/src/tagTracker.h b/src/tagTracker.h
index 60713b0da..de5828203 100644
--- a/src/tagTracker.h
+++ b/src/tagTracker.h
@@ -6,6 +6,7 @@
char * getTagItemString(int type, char * string);
void removeTagItemString(int type, char * string);
+void destroyTagTracker();
int getNumberOfTagItems(int type);