aboutsummaryrefslogtreecommitdiffstats
path: root/src/libmpdclient.c
diff options
context:
space:
mode:
authorKalle Wallin <kaw@linux.se>2004-06-14 18:32:31 +0000
committerKalle Wallin <kaw@linux.se>2004-06-14 18:32:31 +0000
commit39758c8503fb5390afaceeff3dd5b0bca75feb97 (patch)
tree94f42a18c5cb0da8778e8525ded49fb98012bbfc /src/libmpdclient.c
parent7844008980d4d1b9cb7cbd4dda4ae912e12dd7a9 (diff)
downloadmpd-39758c8503fb5390afaceeff3dd5b0bca75feb97.tar.gz
mpd-39758c8503fb5390afaceeff3dd5b0bca75feb97.tar.xz
mpd-39758c8503fb5390afaceeff3dd5b0bca75feb97.zip
Major cleanup of the mpd client code (mpc->mpdclient)
git-svn-id: https://svn.musicpd.org/ncmpc/trunk@1481 09075e82-0dd4-0310-85a5-a0d7c8717e4f
Diffstat (limited to '')
-rw-r--r--src/libmpdclient.c270
1 files changed, 194 insertions, 76 deletions
diff --git a/src/libmpdclient.c b/src/libmpdclient.c
index b61e2d1e9..089e7201f 100644
--- a/src/libmpdclient.c
+++ b/src/libmpdclient.c
@@ -30,13 +30,7 @@
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#ifndef HAVE_SOCKLEN_T
-typedef SOCKLEN_T socklen_t;
-#endif
-#endif
+#include <fcntl.h>
#ifndef MPD_NO_IPV6
#ifdef AF_INET6
@@ -44,6 +38,9 @@ typedef SOCKLEN_T socklen_t;
#endif
#endif
+#define COMMAND_LIST 1
+#define COMMAND_LIST_OK 2
+
#ifdef MPD_HAVE_IPV6
int mpd_ipv6Supported() {
int s;
@@ -104,7 +101,11 @@ mpd_Connection * mpd_newConnection(const char * host, int port, float timeout) {
int err;
struct hostent * he;
struct sockaddr * dest;
+#ifdef MPD_HAVE_SOCKLEN_T
socklen_t destlen;
+#else
+ int destlen;
+#endif
struct sockaddr_in sin;
char * rt;
char * output;
@@ -121,6 +122,8 @@ mpd_Connection * mpd_newConnection(const char * host, int port, float timeout) {
connection->error = 0;
connection->doneProcessing = 0;
connection->commandList = 0;
+ connection->listOks = 0;
+ connection->doneListOk = 0;
connection->returnElement = NULL;
if(!(he=gethostbyname(host))) {
@@ -174,60 +177,22 @@ mpd_Connection * mpd_newConnection(const char * host, int port, float timeout) {
return connection;
}
+ mpd_setConnectionTimeout(connection,timeout);
+
/* connect stuff */
{
-#ifdef SO_RCVTIMEO
- struct timeval rcvoldto;
- struct timeval sndoldto;
- socklen_t oldlen = sizeof(struct timeval);
+ int flags = fcntl(connection->sock, F_GETFL, 0);
+ fcntl(connection->sock, F_SETFL, flags | O_NONBLOCK);
- mpd_setConnectionTimeout(connection,timeout);
-
- tv.tv_sec = connection->timeout.tv_sec;
- tv.tv_usec = connection->timeout.tv_usec;
-
- if(getsockopt(connection->sock,SOL_SOCKET,SO_RCVTIMEO,&rcvoldto,
- &oldlen)<0 ||
- getsockopt(connection->sock,SOL_SOCKET,
- SO_SNDTIMEO,&sndoldto,&oldlen)<0)
+ if(connect(connection->sock,dest,destlen)<0 &&
+ errno!=EINPROGRESS)
{
- strcpy(connection->errorStr,"problems getting socket "
- "timeout\n");
- connection->error = MPD_ERROR_SYSTEM;
- return connection;
- }
- if(setsockopt(connection->sock,SOL_SOCKET,SO_RCVTIMEO,&tv,
- sizeof(struct timeval))<0 ||
- setsockopt(connection->sock,SOL_SOCKET,
- SO_SNDTIMEO,&tv,
- sizeof(struct timeval))<0)
- {
- strcpy(connection->errorStr,"problems setting socket "
- "timeout\n");
- connection->error = MPD_ERROR_SYSTEM;
- return connection;
- }
-#endif
- if(connect(connection->sock,dest,destlen)<0) {
snprintf(connection->errorStr,MPD_BUFFER_MAX_LENGTH,
"problems connecting to \"%s\" on port"
" %i",host,port);
connection->error = MPD_ERROR_CONNPORT;
return connection;
}
-#ifdef SO_RCVTIMEO
- if(setsockopt(connection->sock,SOL_SOCKET,SO_SNDTIMEO,&rcvoldto,
- sizeof(struct timeval))<0 ||
- setsockopt(connection->sock,SOL_SOCKET,
- SO_SNDTIMEO,&sndoldto,
- sizeof(struct timeval))<0)
- {
- strcpy(connection->errorStr,"problems setting socket "
- "timeout\n");
- connection->error = MPD_ERROR_SYSTEM;
- return connection;
- }
-#endif
}
while(!(rt = strstr(connection->buffer,"\n"))) {
@@ -253,7 +218,19 @@ mpd_Connection * mpd_newConnection(const char * host, int port, float timeout) {
tv.tv_sec = connection->timeout.tv_sec;
tv.tv_usec = connection->timeout.tv_usec;
}
- else if(err<0 && errno==EINTR) continue;
+ else if(err<0) {
+ switch(errno) {
+ case EINTR:
+ continue;
+ default:
+ snprintf(connection->errorStr,
+ MPD_BUFFER_MAX_LENGTH,
+ "problems connecting to \"%s\" on port"
+ " %i",host,port);
+ connection->error = MPD_ERROR_CONNPORT;
+ return connection;
+ }
+ }
else {
snprintf(connection->errorStr,MPD_BUFFER_MAX_LENGTH,
"timeout in attempting to get a response from"
@@ -380,6 +357,9 @@ void mpd_executeCommand(mpd_Connection * connection, char * command) {
}
if(!connection->commandList) connection->doneProcessing = 0;
+ else if(connection->commandList == COMMAND_LIST_OK) {
+ connection->listOks++;
+ }
}
void mpd_getNextReturnElement(mpd_Connection * connection) {
@@ -397,7 +377,9 @@ void mpd_getNextReturnElement(mpd_Connection * connection) {
if(connection->returnElement) mpd_freeReturnElement(connection->returnElement);
connection->returnElement = NULL;
- if(connection->doneProcessing) {
+ if(connection->doneProcessing || (connection->listOks &&
+ connection->doneListOk))
+ {
strcpy(connection->errorStr,"already done processing current command");
connection->error = 1;
return;
@@ -459,9 +441,28 @@ void mpd_getNextReturnElement(mpd_Connection * connection) {
connection->bufstart = rt - connection->buffer + 1;
if(strcmp(output,"OK")==0) {
+ if(connection->listOks > 0) {
+ strcpy(connection->errorStr, "expected more list_OK's");
+ connection->error = 1;
+ }
+ connection->listOks = 0;
connection->doneProcessing = 1;
return;
}
+
+ if(strcmp(output, "list_OK") == 0) {
+ if(!connection->listOks) {
+ strcpy(connection->errorStr,
+ "got an unexpected list_OK");
+ connection->error = 1;
+ }
+ else {
+ connection->doneListOk = 1;
+ connection->listOks--;
+ }
+ return;
+ }
+
if(strncmp(output,"ACK",strlen("ACK"))==0) {
char * test;
char * needle;
@@ -503,15 +504,45 @@ void mpd_getNextReturnElement(mpd_Connection * connection) {
}
void mpd_finishCommand(mpd_Connection * connection) {
- while(!connection->doneProcessing) mpd_getNextReturnElement(connection);
+ while(!connection->doneProcessing) {
+ if(connection->doneListOk) connection->doneListOk = 0;
+ mpd_getNextReturnElement(connection);
+ }
+}
+
+void mpd_finishListOkCommand(mpd_Connection * connection) {
+ while(!connection->doneProcessing && connection->listOks &&
+ !connection->doneListOk )
+ {
+ mpd_getNextReturnElement(connection);
+ }
+}
+
+int mpd_nextListOkCommand(mpd_Connection * connection) {
+ mpd_finishListOkCommand(connection);
+ if(!connection->doneProcessing) connection->doneListOk = 0;
+ if(connection->listOks == 0 || connection->doneProcessing) return -1;
+ return 0;
+}
+
+void mpd_sendStatusCommand(mpd_Connection * connection) {
+ mpd_executeCommand(connection,"status\n");
}
mpd_Status * mpd_getStatus(mpd_Connection * connection) {
mpd_Status * status;
- mpd_executeCommand(connection,"status\n");
+ /*mpd_executeCommand(connection,"status\n");
- if(connection->error) return NULL;
+ if(connection->error) return NULL;*/
+
+ if(connection->doneProcessing || (connection->listOks &&
+ connection->doneListOk))
+ {
+ return NULL;
+ }
+
+ if(!connection->returnElement) mpd_getNextReturnElement(connection);
status = malloc(sizeof(mpd_Status));
status->volume = -1;
@@ -531,7 +562,6 @@ mpd_Status * mpd_getStatus(mpd_Connection * connection) {
status->error = NULL;
status->updatingDb = 0;
- mpd_getNextReturnElement(connection);
if(connection->error) {
free(status);
return NULL;
@@ -573,6 +603,9 @@ mpd_Status * mpd_getStatus(mpd_Connection * connection) {
else if(strcmp(re->name,"song")==0) {
status->song = atoi(re->value);
}
+ else if(strcmp(re->name,"songid")==0) {
+ status->songid = atoi(re->value);
+ }
else if(strcmp(re->name,"time")==0) {
char * tok;
char * copy;
@@ -639,12 +672,24 @@ void mpd_freeStatus(mpd_Status * status) {
free(status);
}
+void mpd_sendStatsCommand(mpd_Connection * connection) {
+ mpd_executeCommand(connection,"stats\n");
+}
+
mpd_Stats * mpd_getStats(mpd_Connection * connection) {
mpd_Stats * stats;
- mpd_executeCommand(connection,"stats\n");
+ /*mpd_executeCommand(connection,"stats\n");
- if(connection->error) return NULL;
+ if(connection->error) return NULL;*/
+
+ if(connection->doneProcessing || (connection->listOks &&
+ connection->doneListOk))
+ {
+ return NULL;
+ }
+
+ if(!connection->returnElement) mpd_getNextReturnElement(connection);
stats = malloc(sizeof(mpd_Stats));
stats->numberOfArtists = 0;
@@ -655,7 +700,6 @@ mpd_Stats * mpd_getStats(mpd_Connection * connection) {
stats->playTime = 0;
stats->dbPlayTime = 0;
- mpd_getNextReturnElement(connection);
if(connection->error) {
free(stats);
return NULL;
@@ -711,7 +755,8 @@ void mpd_initSong(mpd_Song * song) {
song->title = NULL;
song->name = NULL;
song->time = MPD_SONG_NO_TIME;
- song->num = MPD_SONG_NO_NUM;
+ song->pos = MPD_SONG_NO_NUM;
+ song->id = MPD_SONG_NO_ID;
}
void mpd_finishSong(mpd_Song * song) {
@@ -746,7 +791,8 @@ mpd_Song * mpd_songDup(mpd_Song * song) {
if(song->track) ret->track = strdup(song->track);
if(song->name) ret->name = strdup(song->name);
ret->time = song->time;
- ret->num = song->num;
+ ret->pos = song->pos;
+ ret->id = song->id;
return ret;
}
@@ -848,7 +894,11 @@ void mpd_sendInfoCommand(mpd_Connection * connection, char * command) {
mpd_InfoEntity * mpd_getNextInfoEntity(mpd_Connection * connection) {
mpd_InfoEntity * entity = NULL;
- if(connection->doneProcessing) return NULL;
+ if(connection->doneProcessing || (connection->listOks &&
+ connection->doneListOk))
+ {
+ return NULL;
+ }
if(!connection->returnElement) mpd_getNextReturnElement(connection);
@@ -917,9 +967,13 @@ mpd_InfoEntity * mpd_getNextInfoEntity(mpd_Connection * connection) {
strcmp(re->name,"Time")==0) {
entity->info.song->time = atoi(re->value);
}
- else if(entity->info.song->num==MPD_SONG_NO_NUM &&
- strcmp(re->name,"Num")==0) {
- entity->info.song->num = atoi(re->value);
+ else if(entity->info.song->pos==MPD_SONG_NO_NUM &&
+ strcmp(re->name,"Pos")==0) {
+ entity->info.song->pos = atoi(re->value);
+ }
+ else if(entity->info.song->id==MPD_SONG_NO_ID &&
+ strcmp(re->name,"Id")==0) {
+ entity->info.song->id = atoi(re->value);
}
}
else if(entity->type == MPD_INFO_ENTITY_TYPE_DIRECTORY) {
@@ -936,7 +990,11 @@ mpd_InfoEntity * mpd_getNextInfoEntity(mpd_Connection * connection) {
char * mpd_getNextReturnElementNamed(mpd_Connection * connection,
const char * name)
{
- if(connection->doneProcessing) return NULL;
+ if(connection->doneProcessing || (connection->listOks &&
+ connection->doneListOk))
+ {
+ return NULL;
+ }
mpd_getNextReturnElement(connection);
while(connection->returnElement) {
@@ -957,13 +1015,20 @@ char * mpd_getNextAlbum(mpd_Connection * connection) {
return mpd_getNextReturnElementNamed(connection,"Album");
}
-void mpd_sendPlaylistInfoCommand(mpd_Connection * connection, int songNum) {
+void mpd_sendPlaylistInfoCommand(mpd_Connection * connection, int songPos) {
char * string = malloc(strlen("playlistinfo")+25);
- sprintf(string,"playlistinfo \"%i\"\n",songNum);
+ sprintf(string,"playlistinfo \"%i\"\n",songPos);
mpd_sendInfoCommand(connection,string);
free(string);
}
+void mpd_sendPlaylistIdCommand(mpd_Connection * connection, int id) {
+ char * string = malloc(strlen("playlistid")+25);
+ sprintf(string, "playlistid \"%i\"\n", id);
+ mpd_sendInfoCommand(connection, string);
+ free(string);
+}
+
void mpd_sendPlChangesCommand(mpd_Connection * connection, long long playlist) {
char * string = malloc(strlen("plchanges")+25);
sprintf(string,"plchanges \"%lld\"\n",playlist);
@@ -998,6 +1063,10 @@ void mpd_sendLsInfoCommand(mpd_Connection * connection, const char * dir) {
free(sDir);
}
+void mpd_sendCurrentSongCommand(mpd_Connection * connection) {
+ mpd_executeCommand(connection,"currentsong\n");
+}
+
void mpd_sendSearchCommand(mpd_Connection * connection, int table,
const char * str)
{
@@ -1076,9 +1145,16 @@ void mpd_sendAddCommand(mpd_Connection * connection, const char * file) {
free(sFile);
}
-void mpd_sendDeleteCommand(mpd_Connection * connection, int songNum) {
+void mpd_sendDeleteCommand(mpd_Connection * connection, int songPos) {
char * string = malloc(strlen("delete")+25);
- sprintf(string,"delete \"%i\"\n",songNum);
+ sprintf(string,"delete \"%i\"\n",songPos);
+ mpd_sendInfoCommand(connection,string);
+ free(string);
+}
+
+void mpd_sendDeleteIdCommand(mpd_Connection * connection, int id) {
+ char * string = malloc(strlen("deleteid")+25);
+ sprintf(string, "deleteid \"%i\"\n", id);
mpd_sendInfoCommand(connection,string);
free(string);
}
@@ -1118,9 +1194,16 @@ void mpd_sendClearCommand(mpd_Connection * connection) {
mpd_executeCommand(connection,"clear\n");
}
-void mpd_sendPlayCommand(mpd_Connection * connection, int songNum) {
+void mpd_sendPlayCommand(mpd_Connection * connection, int songPos) {
char * string = malloc(strlen("play")+25);
- sprintf(string,"play \"%i\"\n",songNum);
+ sprintf(string,"play \"%i\"\n",songPos);
+ mpd_sendInfoCommand(connection,string);
+ free(string);
+}
+
+void mpd_sendPlayIdCommand(mpd_Connection * connection, int id) {
+ char * string = malloc(strlen("playid")+25);
+ sprintf(string,"playid \"%i\"\n",id);
mpd_sendInfoCommand(connection,string);
free(string);
}
@@ -1129,8 +1212,11 @@ void mpd_sendStopCommand(mpd_Connection * connection) {
mpd_executeCommand(connection,"stop\n");
}
-void mpd_sendPauseCommand(mpd_Connection * connection) {
- mpd_executeCommand(connection,"pause\n");
+void mpd_sendPauseCommand(mpd_Connection * connection, int pauseMode) {
+ char * string = malloc(strlen("pause")+25);
+ sprintf(string,"pause \"%i\"\n",pauseMode);
+ mpd_executeCommand(connection,string);
+ free(string);
}
void mpd_sendNextCommand(mpd_Connection * connection) {
@@ -1144,6 +1230,13 @@ void mpd_sendMoveCommand(mpd_Connection * connection, int from, int to) {
free(string);
}
+void mpd_sendMoveIdCommand(mpd_Connection * connection, int id, int to) {
+ char * string = malloc(strlen("moveid")+25);
+ sprintf(string, "moveid \"%i\" \"%i\"\n", id, to);
+ mpd_sendInfoCommand(connection,string);
+ free(string);
+}
+
void mpd_sendSwapCommand(mpd_Connection * connection, int song1, int song2) {
char * string = malloc(strlen("swap")+25);
sprintf(string,"swap \"%i\" \"%i\"\n",song1,song2);
@@ -1151,6 +1244,13 @@ void mpd_sendSwapCommand(mpd_Connection * connection, int song1, int song2) {
free(string);
}
+void mpd_sendSwapIdCommand(mpd_Connection * connection, int id1, int id2) {
+ char * string = malloc(strlen("swapid")+25);
+ sprintf(string, "swapid \"%i\" \"%i\"\n", id1, id2);
+ mpd_sendInfoCommand(connection,string);
+ free(string);
+}
+
void mpd_sendSeekCommand(mpd_Connection * connection, int song, int time) {
char * string = malloc(strlen("seek")+25);
sprintf(string,"seek \"%i\" \"%i\"\n",song,time);
@@ -1158,6 +1258,13 @@ void mpd_sendSeekCommand(mpd_Connection * connection, int song, int time) {
free(string);
}
+void mpd_sendSeekIdCommand(mpd_Connection * connection, int id, int time) {
+ char * string = malloc(strlen("seekid")+25);
+ sprintf(string,"seekid \"%i\" \"%i\"\n",id,time);
+ mpd_sendInfoCommand(connection,string);
+ free(string);
+}
+
void mpd_sendUpdateCommand(mpd_Connection * connection) {
mpd_executeCommand(connection,"update\n");
}
@@ -1229,10 +1336,21 @@ void mpd_sendCommandListBegin(mpd_Connection * connection) {
connection->error = 1;
return;
}
- connection->commandList = 1;
+ connection->commandList = COMMAND_LIST;
mpd_executeCommand(connection,"command_list_begin\n");
}
+void mpd_sendCommandListOkBegin(mpd_Connection * connection) {
+ if(connection->commandList) {
+ strcpy(connection->errorStr,"already in command list mode");
+ connection->error = 1;
+ return;
+ }
+ connection->commandList = COMMAND_LIST_OK;
+ mpd_executeCommand(connection,"command_list_ok_begin\n");
+ connection->listOks = 0;
+}
+
void mpd_sendCommandListEnd(mpd_Connection * connection) {
if(!connection->commandList) {
strcpy(connection->errorStr,"not in command list mode");