From fc7a264e4d3f6ba93d52722455e6d4ec7ca671fb Mon Sep 17 00:00:00 2001 From: Warren Dukes Date: Sun, 11 Apr 2004 17:37:47 +0000 Subject: incremental updates and command-list/update kung fu this needs some serious cleaning up and testing git-svn-id: https://svn.musicpd.org/mpd/trunk@692 09075e82-0dd4-0310-85a5-a0d7c8717e4f --- src/command.c | 201 ++++++++++++++++++++++++++++++++++++++++++-------------- src/command.h | 4 +- src/directory.c | 55 +++++++++++++++- src/directory.h | 3 +- src/interface.c | 15 +++-- 5 files changed, 217 insertions(+), 61 deletions(-) (limited to 'src') diff --git a/src/command.c b/src/command.c index f61cb7630..5f2ad6eef 100644 --- a/src/command.c +++ b/src/command.c @@ -30,6 +30,7 @@ #include "conf.h" #include "permission.h" #include "audio.h" +#include "buffer2array.h" #include #include @@ -86,17 +87,24 @@ #define COMMAND_STATUS_AUDIO "audio" #define COMMAND_STATUS_UPDATING_DB "updating_db" +typedef struct _CommandEntry CommandEntry; + typedef int (* CommandHandlerFunction)(FILE *, unsigned int *, int, char **); +typedef int (* CommandListHandlerFunction)(FILE *, unsigned int *, int, char **, + ListNode *, CommandEntry *); /* if min: -1 don't check args * * if max: -1 no max args */ -typedef struct _CommandEntry { +struct _CommandEntry { char * cmd; int min; int max; unsigned int reqPermission; CommandHandlerFunction handler; -} CommandEntry; + CommandListHandlerFunction listHandler; +}; + +CommandEntry * getCommandEntryFromString(char * string, int * permission); List * commandList; @@ -106,18 +114,21 @@ CommandEntry * newCommandEntry() { cmd->min = 0; cmd->max = 0; cmd->handler = NULL; + cmd->listHandler = NULL; cmd->reqPermission = 0; return cmd; } void addCommand(char * name, unsigned int reqPermission, int minargs, - int maxargs, CommandHandlerFunction handler_func) + int maxargs, CommandHandlerFunction handler_func, + CommandListHandlerFunction listHandler_func) { CommandEntry * cmd = newCommandEntry(); cmd->cmd = name; cmd->min = minargs; cmd->max = maxargs; cmd->handler = handler_func; + cmd->listHandler = listHandler_func; cmd->reqPermission = reqPermission; insertInList(commandList, cmd->cmd, cmd); @@ -320,10 +331,45 @@ int handleSearch(FILE * fp, unsigned int * permission, int argArrayLength, return searchForSongsIn(fp,NULL,argArray[1],argArray[2]); } +int listHandleUpdate(FILE * fp, unsigned int * permission, int argArrayLength, + char ** argArray, ListNode * commandNode, CommandEntry * cmd) +{ + static List * pathList = NULL; + CommandEntry * nextCmd = NULL; + ListNode * nextNode = commandNode->nextNode;; + + if(!pathList) pathList = makeList(NULL); + + if(argArrayLength==2) insertInList(pathList,argArray[1],NULL); + else insertInList(pathList,"",NULL); + + if(nextNode) { + nextCmd = getCommandEntryFromString((void *)nextNode->data, + permission); + } + + if(cmd!=nextCmd) { + int ret = updateInit(fp,pathList); + freeList(pathList); + pathList = NULL; + return ret; + } + + return 0; +} + int handleUpdate(FILE * fp, unsigned int * permission, int argArrayLength, char ** argArray) { - return updateInit(fp); + if(argArrayLength==2) { + int ret; + List * pathList = makeList(NULL); + insertInList(pathList,argArray[1],NULL); + ret = updateInit(fp,pathList); + freeList(pathList); + return ret; + } + return updateInit(fp,NULL); } int handleNext(FILE * fp, unsigned int * permission, int argArrayLength, @@ -538,42 +584,42 @@ int handleCrossfade(FILE * fp, unsigned int * permission, int argArrayLength, void initCommands() { commandList = makeList(free); - addCommand(COMMAND_PLAY ,PERMISSION_CONTROL, 0, 1,handlePlay); - addCommand(COMMAND_STOP ,PERMISSION_CONTROL, 0, 0,handleStop); - addCommand(COMMAND_PAUSE ,PERMISSION_CONTROL, 0, 1,handlePause); - addCommand(COMMAND_STATUS ,PERMISSION_READ, 0, 0,commandStatus); - addCommand(COMMAND_KILL ,PERMISSION_ADMIN, -1,-1,handleKill); - addCommand(COMMAND_CLOSE ,0, -1,-1,handleClose); - addCommand(COMMAND_ADD ,PERMISSION_ADD, 0, 1,handleAdd); - addCommand(COMMAND_DELETE ,PERMISSION_CONTROL, 1, 1,handleDelete); - addCommand(COMMAND_PLAYLIST ,PERMISSION_READ, 0, 0,handlePlaylist); - addCommand(COMMAND_SHUFFLE ,PERMISSION_CONTROL, 0, 0,handleShuffle); - addCommand(COMMAND_CLEAR ,PERMISSION_CONTROL, 0, 0,handleClear); - addCommand(COMMAND_SAVE ,PERMISSION_CONTROL, 1, 1,handleSave); - addCommand(COMMAND_LOAD ,PERMISSION_ADD, 1, 1,handleLoad); - addCommand(COMMAND_LSINFO ,PERMISSION_READ, 0, 1,handleLsInfo); - addCommand(COMMAND_RM ,PERMISSION_CONTROL, 1, 1,handleRm); - addCommand(COMMAND_PLAYLISTINFO,PERMISSION_READ, 0, 1,handlePlaylistInfo); - addCommand(COMMAND_FIND ,PERMISSION_READ, 2, 2,handleFind); - addCommand(COMMAND_SEARCH ,PERMISSION_READ, 2, 2,handleSearch); - addCommand(COMMAND_UPDATE ,PERMISSION_ADMIN, 0, 0,handleUpdate); - addCommand(COMMAND_NEXT ,PERMISSION_CONTROL, 0, 0,handleNext); - addCommand(COMMAND_PREVIOUS ,PERMISSION_CONTROL, 0, 0,handlePrevious); - addCommand(COMMAND_LISTALL ,PERMISSION_READ, 0, 1,handleListAll); - addCommand(COMMAND_VOLUME ,PERMISSION_CONTROL, 1, 1,handleVolume); - addCommand(COMMAND_REPEAT ,PERMISSION_CONTROL, 1, 1,handleRepeat); - addCommand(COMMAND_RANDOM ,PERMISSION_CONTROL, 1, 1,handleRandom); - addCommand(COMMAND_STATS ,PERMISSION_READ, 0, 0,handleStats); - addCommand(COMMAND_CLEAR_ERROR ,PERMISSION_CONTROL, 0, 0,handleClearError); - addCommand(COMMAND_LIST ,PERMISSION_READ, 1, 2,handleList); - addCommand(COMMAND_MOVE ,PERMISSION_CONTROL, 2, 2,handleMove); - addCommand(COMMAND_SWAP ,PERMISSION_CONTROL, 2, 2,handleSwap); - addCommand(COMMAND_SEEK ,PERMISSION_CONTROL, 2, 2,handleSeek); - addCommand(COMMAND_LISTALLINFO ,PERMISSION_READ, 0, 1,handleListAllInfo); - addCommand(COMMAND_PING ,0, 0, 0,handlePing); - addCommand(COMMAND_SETVOL ,PERMISSION_CONTROL, 1, 1,handleSetVol); - addCommand(COMMAND_PASSWORD ,0, 1, 1,handlePassword); - addCommand(COMMAND_CROSSFADE ,PERMISSION_CONTROL, 1, 1,handleCrossfade); + addCommand(COMMAND_PLAY ,PERMISSION_CONTROL, 0, 1,handlePlay,NULL); + addCommand(COMMAND_STOP ,PERMISSION_CONTROL, 0, 0,handleStop,NULL); + addCommand(COMMAND_PAUSE ,PERMISSION_CONTROL, 0, 1,handlePause,NULL); + addCommand(COMMAND_STATUS ,PERMISSION_READ, 0, 0,commandStatus,NULL); + addCommand(COMMAND_KILL ,PERMISSION_ADMIN, -1,-1,handleKill,NULL); + addCommand(COMMAND_CLOSE ,0, -1,-1,handleClose,NULL); + addCommand(COMMAND_ADD ,PERMISSION_ADD, 0, 1,handleAdd,NULL); + addCommand(COMMAND_DELETE ,PERMISSION_CONTROL, 1, 1,handleDelete,NULL); + addCommand(COMMAND_PLAYLIST ,PERMISSION_READ, 0, 0,handlePlaylist,NULL); + addCommand(COMMAND_SHUFFLE ,PERMISSION_CONTROL, 0, 0,handleShuffle,NULL); + addCommand(COMMAND_CLEAR ,PERMISSION_CONTROL, 0, 0,handleClear,NULL); + addCommand(COMMAND_SAVE ,PERMISSION_CONTROL, 1, 1,handleSave,NULL); + addCommand(COMMAND_LOAD ,PERMISSION_ADD, 1, 1,handleLoad,NULL); + addCommand(COMMAND_LSINFO ,PERMISSION_READ, 0, 1,handleLsInfo,NULL); + addCommand(COMMAND_RM ,PERMISSION_CONTROL, 1, 1,handleRm,NULL); + addCommand(COMMAND_PLAYLISTINFO,PERMISSION_READ, 0, 1,handlePlaylistInfo,NULL); + addCommand(COMMAND_FIND ,PERMISSION_READ, 2, 2,handleFind,NULL); + addCommand(COMMAND_SEARCH ,PERMISSION_READ, 2, 2,handleSearch,NULL); + addCommand(COMMAND_UPDATE ,PERMISSION_ADMIN, 0, 1,handleUpdate,listHandleUpdate); + addCommand(COMMAND_NEXT ,PERMISSION_CONTROL, 0, 0,handleNext,NULL); + addCommand(COMMAND_PREVIOUS ,PERMISSION_CONTROL, 0, 0,handlePrevious,NULL); + addCommand(COMMAND_LISTALL ,PERMISSION_READ, 0, 1,handleListAll,NULL); + addCommand(COMMAND_VOLUME ,PERMISSION_CONTROL, 1, 1,handleVolume,NULL); + addCommand(COMMAND_REPEAT ,PERMISSION_CONTROL, 1, 1,handleRepeat,NULL); + addCommand(COMMAND_RANDOM ,PERMISSION_CONTROL, 1, 1,handleRandom,NULL); + addCommand(COMMAND_STATS ,PERMISSION_READ, 0, 0,handleStats,NULL); + addCommand(COMMAND_CLEAR_ERROR ,PERMISSION_CONTROL, 0, 0,handleClearError,NULL); + addCommand(COMMAND_LIST ,PERMISSION_READ, 1, 2,handleList,NULL); + addCommand(COMMAND_MOVE ,PERMISSION_CONTROL, 2, 2,handleMove,NULL); + addCommand(COMMAND_SWAP ,PERMISSION_CONTROL, 2, 2,handleSwap,NULL); + addCommand(COMMAND_SEEK ,PERMISSION_CONTROL, 2, 2,handleSeek,NULL); + addCommand(COMMAND_LISTALLINFO ,PERMISSION_READ, 0, 1,handleListAllInfo,NULL); + addCommand(COMMAND_PING ,0, 0, 0,handlePing,NULL); + addCommand(COMMAND_SETVOL ,PERMISSION_CONTROL, 1, 1,handleSetVol,NULL); + addCommand(COMMAND_PASSWORD ,0, 1, 1,handlePassword,NULL); + addCommand(COMMAND_CROSSFADE ,PERMISSION_CONTROL, 1, 1,handleCrossfade,NULL); sortList(commandList); } @@ -589,45 +635,98 @@ int checkArgcAndPermission(CommandEntry * cmd, FILE *fp, int max = cmd->max + 1; if (cmd->reqPermission != (permission & cmd->reqPermission)) { - myfprintf(fp,"%s You don't have permission for \"%s\"\n",COMMAND_RESPOND_ERROR,cmd->cmd); + if(fp) { + myfprintf(fp,"%s You don't have permission for " + "\"%s\"\n",COMMAND_RESPOND_ERROR, + cmd->cmd); + } return -1; } if (min == 0) return 0; if (min == max && max != argc) { - myfprintf(fp,"%s Wrong number of arguments for \"%s\"\n",COMMAND_RESPOND_ERROR,argArray[0]); + if(fp) { + myfprintf(fp,"%s Wrong number of arguments for " + "\"%s\"\n",COMMAND_RESPOND_ERROR, + argArray[0]); + } return -1; } else if (argc < min) { - myfprintf(fp,"%s too few arguments for \"%s\"\n",COMMAND_RESPOND_ERROR,argArray[0]); + if(fp) { + myfprintf(fp,"%s too few arguments for \"%s\"\n", + COMMAND_RESPOND_ERROR,argArray[0]); + } return -1; } else if (argc > max && max /* != 0 */) { - myfprintf(fp,"%s too many arguments for \"%s\"\n",COMMAND_RESPOND_ERROR,argArray[0]); + if(fp) { + myfprintf(fp,"%s too many arguments for \"%s\"\n", + COMMAND_RESPOND_ERROR,argArray[0]); + } return -1; } else return 0; } -int processCommand(FILE * fp, unsigned int * permission, int argArrayLength, - char ** argArray) +CommandEntry * getCommandEntryAndCheckArgcAndPermission(FILE * fp, + unsigned int * permission, int argArrayLength, char ** argArray) { CommandEntry * cmd; - if(argArrayLength == 0) return 0; + if(argArrayLength == 0) return NULL; if(!findInList(commandList, argArray[0],(void *)&cmd)) { - myfprintf(fp,"%s Unknown command \"%s\"\n",COMMAND_RESPOND_ERROR, - argArray[0]); - return -1; + if(fp) { + myfprintf(fp,"%s Unknown command \"%s\"\n", + COMMAND_RESPOND_ERROR,argArray[0]); + } + return NULL; } if(checkArgcAndPermission(cmd, fp, *permission, argArrayLength, argArray) < 0) + { + return NULL; + } + + return cmd; +} + +CommandEntry * getCommandEntryFromString(char * string, int * permission) { + CommandEntry * cmd = NULL; + char ** argArray; + int argArrayLength = buffer2array(string,&argArray); + + if(0==argArrayLength) return NULL; + + cmd = getCommandEntryAndCheckArgcAndPermission(NULL,permission, + argArrayLength,argArray); + freeArgArray(argArray,argArrayLength); + + return cmd; +} + +int processCommand(FILE * fp, unsigned int * permission, int argArrayLength, + char ** argArray, ListNode * commandNode) +{ + CommandEntry * cmd; + + if(argArrayLength == 0) return 0; + + if(NULL==(cmd = getCommandEntryAndCheckArgcAndPermission(fp,permission, + argArrayLength,argArray))) { return -1; } - return cmd->handler(fp, permission, argArrayLength, argArray); + if(NULL==commandNode || NULL==cmd->listHandler) { + return cmd->handler(fp, permission, argArrayLength, argArray); + } + else { + return cmd->listHandler(fp, permission, argArrayLength, + argArray, commandNode, cmd); + } } + diff --git a/src/command.h b/src/command.h index 2692c6b58..247bce573 100644 --- a/src/command.h +++ b/src/command.h @@ -21,6 +21,8 @@ #include "../config.h" +#include "list.h" + #include #define COMMAND_RETURN_KILL 10 @@ -30,7 +32,7 @@ #define COMMAND_RESPOND_OK "OK" int processCommand(FILE * fp, unsigned int * permission, int argArrayLength, - char ** argArray); + char ** argArray, ListNode * commandNode); void initCommands(); diff --git a/src/directory.c b/src/directory.c index ec4b1f19d..d34c0d553 100644 --- a/src/directory.c +++ b/src/directory.c @@ -90,8 +90,15 @@ int updateDirectory(Directory * directory); void deleteEmptyDirectoriesInDirectory(Directory * directory); +void removeSongFromDirectory(Directory * directory, char * shortname); + int addSubDirectoryToDirectory(Directory * directory, char * shortname, char * name); +Directory * getDirectory(char * name); + +Song * getSongDetails(char * file, char ** shortnameRet, + Directory ** directoryRet); + int isUpdatingDB() { if(directory_updatePid>0) return directory_updateJobId; return 0; @@ -114,7 +121,7 @@ void directory_sigChldHandler(int pid, int status) { } } -int updateInit(FILE * fp) { +int updateInit(FILE * fp, List * pathList) { if(directory_updatePid > 0) { myfprintf(fp,"%s already updating\n",COMMAND_RESPOND_ERROR); return -1; @@ -137,7 +144,41 @@ int updateInit(FILE * fp) { finishPlaylist(); finishVolume(); - if(updateMp3Directory(stderr)) exit(EXIT_FAILURE); + if(pathList) { + ListNode * node = pathList->firstNode; + Directory * directory; + Song * song; + char * shortname; + + while(node) { + if(NULL==(directory = getDirectory(node->key))) + { + song = getSongDetails(node->key, + &shortname,&directory); + if(song && updateSongInfo(song)<0) { + removeSongFromDirectory( + directory, + shortname); + } + } + else { + if(updateDirectory(directory)<0) { + ERROR("problems updating music " + "db\n"); + exit(EXIT_FAILURE); + } + } + node = node->nextNode; + } + } + else if(updateDirectory(mp3rootDirectory)<0) exit(EXIT_FAILURE); + if(writeDirectoryDB()<0) { + ERROR("problems writing music db file, \"%s\"\n", + directorydb); + myfprintf(fp,"%s problems writing music db\n", + COMMAND_RESPOND_ERROR); + exit(EXIT_FAILURE); + } exit(EXIT_SUCCESS); } else if(directory_updatePid < 0) { @@ -950,7 +991,9 @@ void initMp3Directory() { exploreDirectory(mp3rootDirectory); } -Song * getSong(char * file) { +Song * getSongDetails(char * file, char ** shortnameRet, + Directory ** directoryRet) +{ void * song; Directory * directory; char * dir = NULL; @@ -983,9 +1026,15 @@ Song * getSong(char * file) { } free(dup); + if(shortnameRet) *shortnameRet = shortname; + if(directoryRet) *directoryRet = directory; return (Song *)song; } +Song * getSong(char * file) { + return getSongDetails(file,NULL,NULL); +} + time_t getDbModTime() { time_t mtime = 0; struct stat st; diff --git a/src/directory.h b/src/directory.h index 024790163..c6928f3e6 100644 --- a/src/directory.h +++ b/src/directory.h @@ -22,6 +22,7 @@ #include "../config.h" #include "song.h" +#include "list.h" #include #include @@ -32,7 +33,7 @@ int isUpdatingDB(); void directory_sigChldHandler(int pid, int status); -int updateInit(FILE * fp); +int updateInit(FILE * fp, List * pathList); void initMp3Directory(); diff --git a/src/interface.c b/src/interface.c index 0689e9319..747ac4097 100644 --- a/src/interface.c +++ b/src/interface.c @@ -233,6 +233,7 @@ int interfaceReadInput(Interface * interface) { if(argArrayLength==0); else if(strcmp(argArray[0],INTERFACE_LIST_MODE_END)==0) { ListNode * node = interface->commandList->firstNode; + ListNode * tempNode; ret = 0; while(node!=NULL) { @@ -240,12 +241,16 @@ int interfaceReadInput(Interface * interface) { int argArrayLength; argArrayLength = buffer2array((char *)node->data,&argArray); DEBUG("interface %i: process command \"%s\"\n",interface->num,node->data); - ret = processCommand(interface->fp,&(interface->permission),argArrayLength,argArray); + ret = processCommand(interface->fp,&(interface->permission),argArrayLength,argArray,node); DEBUG("interface %i: command returned %i\n",interface->num,ret); freeArgArray(argArray,argArrayLength); - node = node->nextNode; - if(ret!=0 || - interface->expired) { + tempNode = node->nextNode; + deleteNodeFromList( + interface->commandList, + node); + node = tempNode; + if(ret!=0 || interface->expired) + { node = NULL; } } @@ -295,7 +300,7 @@ int interfaceReadInput(Interface * interface) { } else { DEBUG("interface %i: process command \"%s\"\n",interface->num,interface->buffer); - ret = processCommand(interface->fp,&(interface->permission),argArrayLength,argArray); + ret = processCommand(interface->fp,&(interface->permission),argArrayLength,argArray,NULL); DEBUG("interface %i: command returned %i\n",interface->num,ret); } if(ret==0) { -- cgit v1.2.3