aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorWarren Dukes <warren.dukes@gmail.com>2004-04-11 17:37:47 +0000
committerWarren Dukes <warren.dukes@gmail.com>2004-04-11 17:37:47 +0000
commitfc7a264e4d3f6ba93d52722455e6d4ec7ca671fb (patch)
treec55738667ba5973be0435fd54048269013ae89c2 /src
parent87f53c94d7361bb3aaa1369d26f76f049905fc82 (diff)
downloadmpd-fc7a264e4d3f6ba93d52722455e6d4ec7ca671fb.tar.gz
mpd-fc7a264e4d3f6ba93d52722455e6d4ec7ca671fb.tar.xz
mpd-fc7a264e4d3f6ba93d52722455e6d4ec7ca671fb.zip
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
Diffstat (limited to '')
-rw-r--r--src/command.c201
-rw-r--r--src/command.h4
-rw-r--r--src/directory.c55
-rw-r--r--src/directory.h3
-rw-r--r--src/interface.c15
5 files changed, 217 insertions, 61 deletions
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 <stdlib.h>
#include <string.h>
@@ -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 <stdio.h>
#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 <stdio.h>
#include <sys/param.h>
@@ -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) {