From 32e5f4ca2b43c310ff6639320dec2dd52f159f50 Mon Sep 17 00:00:00 2001 From: Qball Cow Date: Wed, 16 Nov 2005 14:43:04 +0000 Subject: DJWLindenaar balanced tree and master process patch git-svn-id: https://svn.musicpd.org/mpd/trunk@3669 09075e82-0dd4-0310-85a5-a0d7c8717e4f --- src/decode.c | 2 +- src/directory.c | 3 +- src/listen.c | 3 ++ src/listen.h | 1 + src/main.c | 74 +++++++++++++++++++++++------ src/player.c | 68 ++++++++++++++------------- src/playerData.c | 26 +++++++++++ src/playerData.h | 2 + src/sig_handlers.c | 81 ++++++++++++++++++++++++++++++-- src/sig_handlers.h | 4 ++ src/tagTracker.c | 134 +++++++++++++++++++++++++++-------------------------- src/tagTracker.h | 1 + 12 files changed, 284 insertions(+), 115 deletions(-) (limited to 'src') 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 #include -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 #include #include +#include + +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 #include +#include -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); -- cgit v1.2.3