966 lines
28 KiB
C
966 lines
28 KiB
C
/* the Music Player Daemon (MPD)
|
|
* (c)2003-2004 by Warren Dukes (shank@mercury.chem.pitt.edu)
|
|
* 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
|
|
*/
|
|
|
|
#include "command.h"
|
|
#include "player.h"
|
|
#include "playlist.h"
|
|
#include "ls.h"
|
|
#include "directory.h"
|
|
#include "tables.h"
|
|
#include "volume.h"
|
|
#include "path.h"
|
|
#include "stats.h"
|
|
#include "myfprintf.h"
|
|
#include "list.h"
|
|
#include "conf.h"
|
|
#include "permission.h"
|
|
#include "audio.h"
|
|
#include "buffer2array.h"
|
|
#include "log.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
|
|
#define COMMAND_PLAY "play"
|
|
#define COMMAND_PLAYID "playid"
|
|
#define COMMAND_STOP "stop"
|
|
#define COMMAND_PAUSE "pause"
|
|
#define COMMAND_STATUS "status"
|
|
#define COMMAND_KILL "kill"
|
|
#define COMMAND_CLOSE "close"
|
|
#define COMMAND_ADD "add"
|
|
#define COMMAND_DELETE "delete"
|
|
#define COMMAND_DELETEID "deleteid"
|
|
#define COMMAND_PLAYLIST "playlist"
|
|
#define COMMAND_SHUFFLE "shuffle"
|
|
#define COMMAND_CLEAR "clear"
|
|
#define COMMAND_SAVE "save"
|
|
#define COMMAND_LOAD "load"
|
|
#define COMMAND_LSINFO "lsinfo"
|
|
#define COMMAND_RM "rm"
|
|
#define COMMAND_PLAYLISTINFO "playlistinfo"
|
|
#define COMMAND_PLAYLISTID "playlistid"
|
|
#define COMMAND_FIND "find"
|
|
#define COMMAND_SEARCH "search"
|
|
#define COMMAND_UPDATE "update"
|
|
#define COMMAND_NEXT "next"
|
|
#define COMMAND_PREVIOUS "previous"
|
|
#define COMMAND_LISTALL "listall"
|
|
#define COMMAND_VOLUME "volume"
|
|
#define COMMAND_REPEAT "repeat"
|
|
#define COMMAND_RANDOM "random"
|
|
#define COMMAND_STATS "stats"
|
|
#define COMMAND_CLEAR_ERROR "clearerror"
|
|
#define COMMAND_LIST "list"
|
|
#define COMMAND_MOVE "move"
|
|
#define COMMAND_MOVEID "moveid"
|
|
#define COMMAND_SWAP "swap"
|
|
#define COMMAND_SWAPID "swapid"
|
|
#define COMMAND_SEEK "seek"
|
|
#define COMMAND_SEEKID "seekid"
|
|
#define COMMAND_LISTALLINFO "listallinfo"
|
|
#define COMMAND_PING "ping"
|
|
#define COMMAND_SETVOL "setvol"
|
|
#define COMMAND_PASSWORD "password"
|
|
#define COMMAND_CROSSFADE "crossfade"
|
|
#define COMMAND_URL_HANDLERS "urlhandlers"
|
|
#define COMMAND_PLCHANGES "plchanges"
|
|
#define COMMAND_CURRENTSONG "currentsong"
|
|
|
|
#define COMMAND_STATUS_VOLUME "volume"
|
|
#define COMMAND_STATUS_STATE "state"
|
|
#define COMMAND_STATUS_REPEAT "repeat"
|
|
#define COMMAND_STATUS_RANDOM "random"
|
|
#define COMMAND_STATUS_PLAYLIST "playlist"
|
|
#define COMMAND_STATUS_PLAYLIST_LENGTH "playlistlength"
|
|
#define COMMAND_STATUS_SONG "song"
|
|
#define COMMAND_STATUS_SONGID "songid"
|
|
#define COMMAND_STATUS_TIME "time"
|
|
#define COMMAND_STATUS_BITRATE "bitrate"
|
|
#define COMMAND_STATUS_ERROR "error"
|
|
#define COMMAND_STATUS_CROSSFADE "xfade"
|
|
#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 */
|
|
struct _CommandEntry {
|
|
char * cmd;
|
|
int min;
|
|
int max;
|
|
unsigned int reqPermission;
|
|
CommandHandlerFunction handler;
|
|
CommandListHandlerFunction listHandler;
|
|
};
|
|
|
|
char * current_command = NULL;
|
|
int command_listNum = 0;
|
|
|
|
CommandEntry * getCommandEntryFromString(char * string, int * permission);
|
|
|
|
List * commandList;
|
|
|
|
CommandEntry * newCommandEntry() {
|
|
CommandEntry * cmd = malloc(sizeof(CommandEntry));
|
|
cmd->cmd = NULL;
|
|
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,
|
|
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);
|
|
}
|
|
|
|
int handleUrlHandlers(FILE * fp, unsigned int * permission, int argArrayLength,
|
|
char ** argArray)
|
|
{
|
|
return printRemoteUrlHandlers(fp);
|
|
}
|
|
|
|
int handlePlay(FILE * fp, unsigned int * permission, int argArrayLength,
|
|
char ** argArray)
|
|
{
|
|
int song = -1;
|
|
char * test;
|
|
|
|
if(argArrayLength==2) {
|
|
song = strtol(argArray[1],&test,10);
|
|
if(*test!='\0') {
|
|
commandError(fp, ACK_ERROR_ARG,
|
|
"need a positive integer", NULL);
|
|
return -1;
|
|
}
|
|
}
|
|
return playPlaylist(fp,song,0);
|
|
}
|
|
|
|
int handlePlayId(FILE * fp, unsigned int * permission, int argArrayLength,
|
|
char ** argArray)
|
|
{
|
|
int id = -1;
|
|
char * test;
|
|
|
|
if(argArrayLength==2) {
|
|
id = strtol(argArray[1],&test,10);
|
|
if(*test!='\0') {
|
|
commandError(fp, ACK_ERROR_ARG,
|
|
"need a positive integer", NULL);
|
|
return -1;
|
|
}
|
|
}
|
|
return playPlaylistById(fp, id, 0);
|
|
}
|
|
|
|
int handleStop(FILE * fp, unsigned int * permission, int argArrayLength,
|
|
char ** argArray)
|
|
{
|
|
return stopPlaylist(fp);
|
|
}
|
|
|
|
int handleCurrentSong(FILE * fp, unsigned int * permission, int argArrayLength,
|
|
char ** argArray)
|
|
{
|
|
int song = getPlaylistCurrentSong();
|
|
|
|
if(song >= 0) {
|
|
return playlistInfo(fp, song);
|
|
}
|
|
else return 0;
|
|
}
|
|
|
|
int handlePause(FILE * fp, unsigned int * permission,
|
|
int argArrayLength, char ** argArray)
|
|
{
|
|
if(argArrayLength==2) {
|
|
char * test;
|
|
int pause = strtol(argArray[1],&test,10);
|
|
if(*test!='\0' || (pause!=0 && pause!=1)) {
|
|
commandError(fp, ACK_ERROR_ARG, "\%s\" is not 0 or 1", argArray[1]);
|
|
return -1;
|
|
}
|
|
return playerSetPause(fp,pause);
|
|
}
|
|
return playerPause(fp);
|
|
}
|
|
|
|
int commandStatus(FILE * fp, unsigned int * permission, int argArrayLength,
|
|
char ** argArray)
|
|
{
|
|
char * state = NULL;
|
|
int updateJobId;
|
|
int song;
|
|
|
|
/*syncPlayerAndPlaylist();*/
|
|
playPlaylistIfPlayerStopped();
|
|
switch(getPlayerState()) {
|
|
case PLAYER_STATE_STOP:
|
|
state = strdup(COMMAND_STOP);
|
|
break;
|
|
case PLAYER_STATE_PAUSE:
|
|
state = strdup(COMMAND_PAUSE);
|
|
break;
|
|
case PLAYER_STATE_PLAY:
|
|
state = strdup(COMMAND_PLAY);
|
|
break;
|
|
}
|
|
|
|
myfprintf(fp,"%s: %i\n",COMMAND_STATUS_VOLUME,getVolumeLevel());
|
|
myfprintf(fp,"%s: %i\n",COMMAND_STATUS_REPEAT,getPlaylistRepeatStatus());
|
|
myfprintf(fp,"%s: %i\n",COMMAND_STATUS_RANDOM,getPlaylistRandomStatus());
|
|
myfprintf(fp,"%s: %li\n",COMMAND_STATUS_PLAYLIST,getPlaylistVersion());
|
|
myfprintf(fp,"%s: %i\n",COMMAND_STATUS_PLAYLIST_LENGTH,getPlaylistLength());
|
|
myfprintf(fp,"%s: %i\n",COMMAND_STATUS_CROSSFADE,
|
|
(int)(getPlayerCrossFade()+0.5));
|
|
|
|
myfprintf(fp,"%s: %s\n",COMMAND_STATUS_STATE,state);
|
|
|
|
song = getPlaylistCurrentSong();
|
|
if(song >= 0) {
|
|
myfprintf(fp,"%s: %i\n", COMMAND_STATUS_SONG, song);
|
|
myfprintf(fp,"%s: %i\n", COMMAND_STATUS_SONGID,
|
|
getPlaylistSongId(song));
|
|
}
|
|
if(getPlayerState()!=PLAYER_STATE_STOP) {
|
|
myfprintf(fp,"%s: %i:%i\n",COMMAND_STATUS_TIME,getPlayerElapsedTime(),getPlayerTotalTime());
|
|
myfprintf(fp,"%s: %li\n",COMMAND_STATUS_BITRATE,getPlayerBitRate(),getPlayerTotalTime());
|
|
myfprintf(fp,"%s: %u:%i:%i\n",COMMAND_STATUS_AUDIO,getPlayerSampleRate(),getPlayerBits(),getPlayerChannels());
|
|
}
|
|
|
|
if((updateJobId = isUpdatingDB())) {
|
|
myfprintf(fp,"%s: %i\n",COMMAND_STATUS_UPDATING_DB,updateJobId);
|
|
}
|
|
|
|
if(getPlayerError()!=PLAYER_ERROR_NOERROR) {
|
|
myfprintf(fp,"%s: %s\n",COMMAND_STATUS_ERROR,getPlayerErrorStr());
|
|
}
|
|
|
|
free(state);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int handleKill(FILE * fp, unsigned int * permission, int argArrayLength,
|
|
char ** argArray)
|
|
{
|
|
return COMMAND_RETURN_KILL;
|
|
}
|
|
|
|
int handleClose(FILE * fp, unsigned int * permission, int argArrayLength,
|
|
char ** argArray)
|
|
{
|
|
return COMMAND_RETURN_CLOSE;
|
|
}
|
|
|
|
int handleAdd(FILE * fp, unsigned int * permission, int argArrayLength,
|
|
char ** argArray)
|
|
{
|
|
char * path = NULL;
|
|
|
|
if(argArrayLength == 2) {
|
|
path = argArray[1];
|
|
if(isRemoteUrl(path)) return addToPlaylist(fp,path);
|
|
}
|
|
return addAllIn(fp,path);
|
|
}
|
|
|
|
int handleDelete(FILE * fp, unsigned int * permission, int argArrayLength,
|
|
char ** argArray)
|
|
{
|
|
int song;
|
|
char * test;
|
|
|
|
song = strtol(argArray[1],&test,10);
|
|
if(*test!='\0') {
|
|
commandError(fp, ACK_ERROR_ARG,
|
|
"need a positive integer", NULL);
|
|
return -1;
|
|
}
|
|
return deleteFromPlaylist(fp,song);
|
|
}
|
|
|
|
int handleDeleteId(FILE * fp, unsigned int * permission, int argArrayLength,
|
|
char ** argArray)
|
|
{
|
|
int id;
|
|
char * test;
|
|
|
|
id = strtol(argArray[1],&test,10);
|
|
if(*test!='\0') {
|
|
commandError(fp, ACK_ERROR_ARG,
|
|
"need a positive integer", NULL);
|
|
return -1;
|
|
}
|
|
return deleteFromPlaylistById(fp, id);
|
|
}
|
|
|
|
int handlePlaylist(FILE * fp, unsigned int * permission, int argArrayLength,
|
|
char ** argArray)
|
|
{
|
|
return showPlaylist(fp);
|
|
}
|
|
|
|
int handleShuffle(FILE * fp, unsigned int * permission, int argArrayLength,
|
|
char ** argArray)
|
|
{
|
|
return shufflePlaylist(fp);
|
|
}
|
|
|
|
int handleClear(FILE * fp, unsigned int * permission, int argArrayLength,
|
|
char ** argArray)
|
|
{
|
|
return clearPlaylist(fp);
|
|
}
|
|
|
|
int handleSave(FILE * fp, unsigned int * permission, int argArrayLength,
|
|
char ** argArray)
|
|
{
|
|
return savePlaylist(fp,argArray[1]);
|
|
}
|
|
|
|
int handleLoad(FILE * fp, unsigned int * permission, int argArrayLength,
|
|
char ** argArray)
|
|
{
|
|
return loadPlaylist(fp,argArray[1]);
|
|
}
|
|
|
|
int handleLsInfo(FILE * fp, unsigned int * permission, int argArrayLength,
|
|
char ** argArray)
|
|
{
|
|
if(argArrayLength==1) {
|
|
if(printDirectoryInfo(fp,NULL)<0) return -1;
|
|
else return lsPlaylists(fp,"");
|
|
}
|
|
else {
|
|
if(printDirectoryInfo(fp,argArray[1])<0) return -1;
|
|
else return lsPlaylists(fp,argArray[1]);
|
|
}
|
|
}
|
|
|
|
int handleRm(FILE * fp, unsigned int * permission, int argArrayLength,
|
|
char ** argArray)
|
|
{
|
|
return deletePlaylist(fp,argArray[1]);
|
|
}
|
|
|
|
int handlePlaylistChanges(FILE * fp, unsigned int * permission,
|
|
int argArrayLength, char ** argArray)
|
|
{
|
|
unsigned long version;
|
|
char * test;
|
|
|
|
version = strtoul(argArray[1], &test, 10);
|
|
if(*test!='\0') {
|
|
commandError(fp, ACK_ERROR_ARG, "need a positive integer",
|
|
NULL);
|
|
return -1;
|
|
}
|
|
return playlistChanges(fp, version);
|
|
}
|
|
|
|
int handlePlaylistInfo(FILE * fp, unsigned int * permission,
|
|
int argArrayLength, char ** argArray)
|
|
{
|
|
int song = -1;
|
|
char * test;
|
|
|
|
if(argArrayLength == 2) {
|
|
song = strtol(argArray[1],&test,10);
|
|
if(*test!='\0') {
|
|
commandError(fp, ACK_ERROR_ARG,
|
|
"need a positive integer", NULL);
|
|
return -1;
|
|
}
|
|
}
|
|
return playlistInfo(fp,song);
|
|
}
|
|
|
|
int handlePlaylistId(FILE * fp, unsigned int * permission,
|
|
int argArrayLength, char ** argArray)
|
|
{
|
|
int id = -1;
|
|
char * test;
|
|
|
|
if(argArrayLength == 2) {
|
|
id = strtol(argArray[1],&test,10);
|
|
if(*test!='\0') {
|
|
commandError(fp, ACK_ERROR_ARG,
|
|
"need a positive integer", NULL);
|
|
return -1;
|
|
}
|
|
}
|
|
return playlistId(fp, id);
|
|
}
|
|
|
|
int handleFind(FILE * fp, unsigned int * permission, int argArrayLength,
|
|
char ** argArray)
|
|
{
|
|
return findSongsIn(fp,NULL,argArray[1],argArray[2]);
|
|
}
|
|
|
|
int handleSearch(FILE * fp, unsigned int * permission, int argArrayLength,
|
|
char ** argArray)
|
|
{
|
|
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)
|
|
{
|
|
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,
|
|
char ** argArray)
|
|
{
|
|
return nextSongInPlaylist(fp);
|
|
}
|
|
|
|
int handlePrevious(FILE * fp, unsigned int * permission, int argArrayLength,
|
|
char ** argArray)
|
|
{
|
|
return previousSongInPlaylist(fp);
|
|
}
|
|
|
|
int handleListAll(FILE * fp, unsigned int * permission, int argArrayLength,
|
|
char ** argArray)
|
|
{
|
|
char * directory = NULL;
|
|
|
|
if(argArrayLength==2) directory = argArray[1];
|
|
return printAllIn(fp,directory);
|
|
}
|
|
|
|
int handleVolume(FILE * fp, unsigned int * permission, int argArrayLength,
|
|
char ** argArray)
|
|
{
|
|
int change;
|
|
char * test;
|
|
|
|
change = strtol(argArray[1],&test,10);
|
|
if(*test!='\0') {
|
|
commandError(fp, ACK_ERROR_ARG, "need an integer", NULL);
|
|
return -1;
|
|
}
|
|
return changeVolumeLevel(fp,change,1);
|
|
}
|
|
|
|
int handleSetVol(FILE * fp, unsigned int * permission, int argArrayLength,
|
|
char ** argArray)
|
|
{
|
|
int level;
|
|
char * test;
|
|
|
|
level = strtol(argArray[1],&test,10);
|
|
if(*test!='\0') {
|
|
commandError(fp, ACK_ERROR_ARG, "need an integer", NULL);
|
|
return -1;
|
|
}
|
|
return changeVolumeLevel(fp,level,0);
|
|
}
|
|
|
|
int handleRepeat(FILE * fp, unsigned int * permission, int argArrayLength,
|
|
char ** argArray)
|
|
{
|
|
int status;
|
|
char * test;
|
|
|
|
status = strtol(argArray[1],&test,10);
|
|
if(*test!='\0') {
|
|
commandError(fp, ACK_ERROR_ARG, "need an integer", NULL);
|
|
return -1;
|
|
}
|
|
return setPlaylistRepeatStatus(fp,status);
|
|
}
|
|
|
|
int handleRandom(FILE * fp, unsigned int * permission, int argArrayLength,
|
|
char ** argArray)
|
|
{
|
|
int status;
|
|
char * test;
|
|
|
|
status = strtol(argArray[1],&test,10);
|
|
if(*test!='\0') {
|
|
commandError(fp, ACK_ERROR_ARG, "need an integer", NULL);
|
|
return -1;
|
|
}
|
|
return setPlaylistRandomStatus(fp,status);
|
|
}
|
|
|
|
int handleStats(FILE * fp, unsigned int * permission, int argArrayLength,
|
|
char ** argArray)
|
|
{
|
|
return printStats(fp);
|
|
}
|
|
|
|
int handleClearError(FILE * fp, unsigned int * permission, int argArrayLength,
|
|
char ** argArray)
|
|
{
|
|
clearPlayerError();
|
|
return 0;
|
|
}
|
|
|
|
int handleList(FILE * fp, unsigned int * permission, int argArrayLength,
|
|
char ** argArray)
|
|
{
|
|
char * arg1 = NULL;
|
|
|
|
if(argArrayLength==3) arg1 = argArray[2];
|
|
return printAllKeysOfTable(fp,argArray[1],arg1);
|
|
}
|
|
|
|
int handleMove(FILE * fp, unsigned int * permission, int argArrayLength,
|
|
char ** argArray)
|
|
{
|
|
int from;
|
|
int to;
|
|
char * test;
|
|
|
|
from = strtol(argArray[1],&test,10);
|
|
if(*test!='\0') {
|
|
commandError(fp, ACK_ERROR_ARG,
|
|
"\"%s\" is not a integer", argArray[1]);
|
|
return -1;
|
|
}
|
|
to = strtol(argArray[2],&test,10);
|
|
if(*test!='\0') {
|
|
commandError(fp, ACK_ERROR_ARG,
|
|
"\"%s\" is not a integer", argArray[2]);
|
|
return -1;
|
|
}
|
|
return moveSongInPlaylist(fp,from,to);
|
|
}
|
|
|
|
int handleMoveId(FILE * fp, unsigned int * permission, int argArrayLength,
|
|
char ** argArray)
|
|
{
|
|
int id;
|
|
int to;
|
|
char * test;
|
|
|
|
id = strtol(argArray[1],&test,10);
|
|
if(*test!='\0') {
|
|
commandError(fp, ACK_ERROR_ARG,
|
|
"\"%s\" is not a integer", argArray[1]);
|
|
return -1;
|
|
}
|
|
to = strtol(argArray[2],&test,10);
|
|
if(*test!='\0') {
|
|
commandError(fp, ACK_ERROR_ARG,
|
|
"\"%s\" is not a integer", argArray[2]);
|
|
return -1;
|
|
}
|
|
return moveSongInPlaylistById(fp, id, to);
|
|
}
|
|
|
|
int handleSwap(FILE * fp, unsigned int * permission, int argArrayLength,
|
|
char ** argArray)
|
|
{
|
|
int song1;
|
|
int song2;
|
|
char * test;
|
|
|
|
song1 = strtol(argArray[1],&test,10);
|
|
if(*test!='\0') {
|
|
commandError(fp, ACK_ERROR_ARG,
|
|
"\"%s\" is not a integer", argArray[1]);
|
|
return -1;
|
|
}
|
|
song2 = strtol(argArray[2],&test,10);
|
|
if(*test!='\0') {
|
|
commandError(fp, ACK_ERROR_ARG, "\"%s\" is not a integer",
|
|
argArray[2]);
|
|
return -1;
|
|
}
|
|
return swapSongsInPlaylist(fp,song1,song2);
|
|
}
|
|
|
|
int handleSwapId(FILE * fp, unsigned int * permission, int argArrayLength,
|
|
char ** argArray)
|
|
{
|
|
int id1;
|
|
int id2;
|
|
char * test;
|
|
|
|
id1 = strtol(argArray[1],&test,10);
|
|
if(*test!='\0') {
|
|
commandError(fp, ACK_ERROR_ARG,
|
|
"\"%s\" is not a integer", argArray[1]);
|
|
return -1;
|
|
}
|
|
id2 = strtol(argArray[2],&test,10);
|
|
if(*test!='\0') {
|
|
commandError(fp, ACK_ERROR_ARG, "\"%s\" is not a integer",
|
|
argArray[2]);
|
|
return -1;
|
|
}
|
|
return swapSongsInPlaylistById(fp, id1, id2);
|
|
}
|
|
|
|
int handleSeek(FILE * fp, unsigned int * permission, int argArrayLength,
|
|
char ** argArray)
|
|
{
|
|
int song;
|
|
int time;
|
|
char * test;
|
|
|
|
song = strtol(argArray[1],&test,10);
|
|
if(*test!='\0') {
|
|
commandError(fp, ACK_ERROR_ARG,
|
|
"\"%s\" is not a integer", argArray[1]);
|
|
return -1;
|
|
}
|
|
time = strtol(argArray[2],&test,10);
|
|
if(*test!='\0') {
|
|
commandError(fp, ACK_ERROR_ARG,
|
|
"\"%s\" is not a integer", argArray[2]);
|
|
return -1;
|
|
}
|
|
return seekSongInPlaylist(fp,song,time);
|
|
}
|
|
|
|
int handleSeekId(FILE * fp, unsigned int * permission, int argArrayLength,
|
|
char ** argArray)
|
|
{
|
|
int id;
|
|
int time;
|
|
char * test;
|
|
|
|
id = strtol(argArray[1],&test,10);
|
|
if(*test!='\0') {
|
|
commandError(fp, ACK_ERROR_ARG,
|
|
"\"%s\" is not a integer", argArray[1]);
|
|
return -1;
|
|
}
|
|
time = strtol(argArray[2],&test,10);
|
|
if(*test!='\0') {
|
|
commandError(fp, ACK_ERROR_ARG,
|
|
"\"%s\" is not a integer", argArray[2]);
|
|
return -1;
|
|
}
|
|
return seekSongInPlaylistById(fp, id, time);
|
|
}
|
|
|
|
int handleListAllInfo(FILE * fp, unsigned int * permission, int argArrayLength,
|
|
char ** argArray)
|
|
{
|
|
char * directory = NULL;
|
|
|
|
if(argArrayLength==2) directory = argArray[1];
|
|
return printInfoForAllIn(fp,directory);
|
|
}
|
|
|
|
int handlePing(FILE * fp, unsigned int * permission, int argArrayLength,
|
|
char ** argArray)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int handlePassword(FILE * fp, unsigned int * permission, int argArrayLength,
|
|
char ** argArray)
|
|
{
|
|
if(getPermissionFromPassword(argArray[1],permission)<0) {
|
|
commandError(fp, ACK_ERROR_PASSWORD, "incorrect password", NULL);
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int handleCrossfade(FILE * fp, unsigned int * permission, int argArrayLength,
|
|
char ** argArray)
|
|
{
|
|
int time;
|
|
char * test;
|
|
|
|
time = strtol(argArray[1],&test,10);
|
|
if(*test!='\0' || time<0) {
|
|
commandError(fp, ACK_ERROR_ARG,
|
|
"\"%s\" is not a integer >= 0", argArray[1]);
|
|
return -1;
|
|
}
|
|
|
|
setPlayerCrossFade(time);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void initCommands() {
|
|
commandList = makeList(free);
|
|
|
|
addCommand(COMMAND_PLAY ,PERMISSION_CONTROL, 0, 1,handlePlay,NULL);
|
|
addCommand(COMMAND_PLAYID ,PERMISSION_CONTROL, 0, 1,handlePlayId,NULL);
|
|
addCommand(COMMAND_STOP ,PERMISSION_CONTROL, 0, 0,handleStop,NULL);
|
|
addCommand(COMMAND_CURRENTSONG ,PERMISSION_READ , 0, 0,handleCurrentSong,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_DELETEID ,PERMISSION_CONTROL, 1, 1,handleDeleteId,NULL);
|
|
addCommand(COMMAND_PLAYLIST ,PERMISSION_READ, 0, 0,handlePlaylist,NULL);
|
|
addCommand(COMMAND_PLAYLISTID ,PERMISSION_READ, 0, 1,handlePlaylistId,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_MOVEID ,PERMISSION_CONTROL, 2, 2,handleMoveId,NULL);
|
|
addCommand(COMMAND_SWAP ,PERMISSION_CONTROL, 2, 2,handleSwap,NULL);
|
|
addCommand(COMMAND_SWAPID ,PERMISSION_CONTROL, 2, 2,handleSwapId,NULL);
|
|
addCommand(COMMAND_SEEK ,PERMISSION_CONTROL, 2, 2,handleSeek,NULL);
|
|
addCommand(COMMAND_SEEKID ,PERMISSION_CONTROL, 2, 2,handleSeekId,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);
|
|
addCommand(COMMAND_URL_HANDLERS,PERMISSION_READ, 0, 0,handleUrlHandlers,NULL);
|
|
addCommand(COMMAND_PLCHANGES ,PERMISSION_READ, 1, 1,handlePlaylistChanges,NULL);
|
|
|
|
sortList(commandList);
|
|
}
|
|
|
|
void finishCommands() {
|
|
freeList(commandList);
|
|
}
|
|
|
|
int checkArgcAndPermission(CommandEntry * cmd, FILE *fp,
|
|
unsigned int permission, int argc, char** argArray)
|
|
{
|
|
int min = cmd->min + 1;
|
|
int max = cmd->max + 1;
|
|
|
|
if (cmd->reqPermission != (permission & cmd->reqPermission)) {
|
|
if(fp) {
|
|
commandError(fp, ACK_ERROR_PERMISSION,
|
|
"you don't have permission for \"%s\"",
|
|
cmd->cmd);
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
if (min == 0) return 0;
|
|
|
|
if (min == max && max != argc) {
|
|
if(fp) {
|
|
commandError(fp, ACK_ERROR_ARG,
|
|
"wrong number of arguments for \"%s\"",
|
|
argArray[0]);
|
|
}
|
|
return -1;
|
|
}
|
|
else if (argc < min) {
|
|
if(fp) {
|
|
commandError(fp, ACK_ERROR_ARG,
|
|
"too few arguments for \"%s\"",
|
|
argArray[0]);
|
|
}
|
|
return -1;
|
|
}
|
|
else if (argc > max && max /* != 0 */) {
|
|
if(fp) {
|
|
commandError(fp, ACK_ERROR_ARG,
|
|
"too many arguments for \"%s\"",
|
|
argArray[0]);
|
|
}
|
|
return -1;
|
|
}
|
|
else return 0;
|
|
}
|
|
|
|
CommandEntry * getCommandEntryAndCheckArgcAndPermission(FILE * fp,
|
|
unsigned int * permission, int argArrayLength, char ** argArray)
|
|
{
|
|
static char unknown[] = "";
|
|
CommandEntry * cmd;
|
|
|
|
current_command = unknown;
|
|
|
|
if(argArrayLength == 0) return NULL;
|
|
|
|
if(!findInList(commandList, argArray[0],(void *)&cmd)) {
|
|
if(fp) {
|
|
commandError(fp, ACK_ERROR_UNKNOWN,
|
|
"unknown command \"%s\"", argArray[0]);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
current_command = cmd->cmd;
|
|
|
|
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 processCommandInternal(FILE * fp, unsigned int * permission,
|
|
char * commandString,
|
|
ListNode * commandNode)
|
|
{
|
|
int argArrayLength;
|
|
char ** argArray;
|
|
CommandEntry * cmd;
|
|
int ret = -1;
|
|
|
|
argArrayLength = buffer2array(commandString,&argArray);
|
|
|
|
if(argArrayLength == 0) return 0;
|
|
|
|
if((cmd = getCommandEntryAndCheckArgcAndPermission(fp,permission,
|
|
argArrayLength,argArray)))
|
|
{
|
|
if(NULL==commandNode || NULL==cmd->listHandler) {
|
|
ret = cmd->handler(fp, permission, argArrayLength,
|
|
argArray);
|
|
}
|
|
else {
|
|
ret = cmd->listHandler(fp, permission, argArrayLength,
|
|
argArray, commandNode, cmd);
|
|
}
|
|
}
|
|
|
|
freeArgArray(argArray,argArrayLength);
|
|
|
|
current_command = NULL;
|
|
|
|
return ret;
|
|
}
|
|
|
|
int proccessListOfCommands(FILE * fp, int * permission, int * expired,
|
|
int listOK, List * list)
|
|
{
|
|
ListNode * node = list->firstNode;
|
|
ListNode * tempNode;
|
|
int ret = 0;
|
|
|
|
command_listNum = 0;
|
|
|
|
while(node!=NULL) {
|
|
DEBUG("proccesListOfCommands: process command \"%s\"\n",
|
|
node->data);
|
|
ret = processCommandInternal(fp,permission,(char *)node->data,
|
|
node);
|
|
DEBUG("proccessListOfCommands: command returned %i\n",ret);
|
|
tempNode = node->nextNode;
|
|
deleteNodeFromList(list,node);
|
|
node = tempNode;
|
|
if(ret!=0 || (*expired)!=0) node = NULL;
|
|
else if(listOK) myfprintf(fp, "list_OK\n");
|
|
command_listNum++;
|
|
}
|
|
|
|
command_listNum = 0;
|
|
|
|
return ret;
|
|
}
|
|
|
|
int processCommand(FILE * fp, unsigned int * permission, char * commandString) {
|
|
return processCommandInternal(fp,permission,commandString,NULL);
|
|
}
|