Code

Major cleanup of the mpd client code (mpc->mpdclient)
authorKalle Wallin <kaw@linux.se>
Mon, 14 Jun 2004 18:32:31 +0000 (18:32 +0000)
committerKalle Wallin <kaw@linux.se>
Mon, 14 Jun 2004 18:32:31 +0000 (18:32 +0000)
git-svn-id: https://svn.musicpd.org/ncmpc/trunk@1481 09075e82-0dd4-0310-85a5-a0d7c8717e4f

28 files changed:
src/Makefile.am
src/colors.c
src/conf.c
src/libmpdclient.c
src/libmpdclient.h
src/main.c
src/mpc.c [deleted file]
src/mpc.h [deleted file]
src/mpdclient.c [new file with mode: 0644]
src/mpdclient.h [new file with mode: 0644]
src/ncmpc.h
src/screen.c
src/screen.h
src/screen_clock.c
src/screen_file.c
src/screen_file.h [deleted file]
src/screen_help.c
src/screen_help.h [deleted file]
src/screen_keydef.c
src/screen_play.c
src/screen_play.h [deleted file]
src/screen_search.c
src/screen_search.h [deleted file]
src/screen_utils.c
src/screen_utils.h
src/strfsong.c [new file with mode: 0644]
src/strfsong.h [new file with mode: 0644]
src/support.c

index 0554098b92762611838ede0fda85885705dd2b37..2d99bc103761b3a14014d3b57e8721893772c4f6 100644 (file)
@@ -9,15 +9,15 @@ ncmpc_LDADD = $(GLIB_LIBS)
 AM_CPPFLAGS = $(GLIB_CFLAGS) -DLOCALE_DIR=\""$(datadir)/locale"\" -DSYSCONFDIR=\""$(sysconfdir)"\"
 
 
-ncmpc_headers = libmpdclient.h mpc.h options.h conf.h command.h screen.h \
-                screen_utils.h screen_play.h screen_file.h screen_search.h \
-               screen_help.h list_window.h colors.h support.h \
-                wreadln.h ncmpc.h
+ncmpc_headers = libmpdclient.h mpdclient.h options.h conf.h command.h \
+                screen.h screen_utils.h list_window.h colors.h support.h \
+                wreadln.h strfsong.h ncmpc.h
 
-ncmpc_SOURCES = libmpdclient.c main.c mpc.c options.c conf.c command.c \
+ncmpc_SOURCES = libmpdclient.c main.c mpdclient.c options.c conf.c command.c \
                screen.c screen_utils.c screen_play.c screen_file.c \
                screen_search.c screen_help.c screen_keydef.c screen_clock.c \
-                list_window.c colors.c support.c wreadln.c $(ncmpc_headers)
+                list_window.c colors.c support.c wreadln.c strfsong.c \
+                $(ncmpc_headers)
 
 
 
index bfb4c316cc77626386314a36261c93db78a22315..2a1c04c030c6a9380b768ea224f7456e946291ce 100644 (file)
@@ -1,5 +1,7 @@
 /* 
- * (c) 2004 by Kalle Wallin (kaw@linux.se)
+ * $Id$
+ *
+ * (c) 2004 by Kalle Wallin <kaw@linux.se>
  *
  * 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
 #include "support.h"
 #include "colors.h"
 
-#ifdef DEBUG
-#define D(x) x
-#else
-#define D(x)
-#endif
-
 #define COLOR_BRIGHT_MASK   (1<<7)
 
 #define COLOR_BRIGHT_BLACK    (COLOR_BLACK | COLOR_BRIGHT_MASK)
index cb8ba0eb247e17ea115376a24fa1ecb08042aa93..0d6d96834d517743783798a1ce87e653b8eca560 100644 (file)
@@ -1,5 +1,7 @@
 /* 
- * (c) 2004 by Kalle Wallin (kaw@linux.se)
+ * $Id$
+ *
+ * (c) 2004 by Kalle Wallin <kaw@linux.se>
  *
  * 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
@@ -308,7 +310,7 @@ read_rc_file(char *filename, options_t *options)
   if( filename==NULL )
     return -1;
 
-  D(printf("Reading configuration file %s\n", filename));
+  D("Reading configuration file %s\n", filename);
   if( (fd=open(filename,O_RDONLY)) <0 )
     {
       perror(filename);
@@ -480,7 +482,7 @@ read_rc_file(char *filename, options_t *options)
        }         
     }
 
-  D(printf( "--\n\n" ));
+  D("--\n\n");
 
   if( free_filename )
     g_free(filename);
index b61e2d1e9e33bf6dbfb33ac4e17df470f92c70e7..089e7201faa70d62c305a2f3e95e0511d7fe437b 100644 (file)
 #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");
index c4b022cd9e88442515418f4ffb2125e4cbbcb88a..1b5f02dfe4c2533b4cf1e54cf0a1ab1db91f42f5 100644 (file)
@@ -43,7 +43,7 @@
 #define MPD_ACK_ERROR_ARG                      2
 #define MPD_ACK_ERROR_PASSWORD                 3
 #define MPD_ACK_ERROR_PERMISSION               4
-#define MPD_ACK_ERROR_UNKNOWN                  5
+#define MPD_ACK_ERROR_UNKNOWN_CMD              5
 #define MPD_ACK_ERROR_NO_EXIST                 6
 #define MPD_ACK_ERROR_PLAYLIST_MAX             7
 #define MPD_ACK_ERROR_SYSTEM                   8
@@ -80,6 +80,8 @@ typedef struct _mpd_Connection {
        int buflen;
        int bufstart;
        int doneProcessing;
+       int listOks;
+       int doneListOk;
        int commandList;
        mpd_ReturnElement * returnElement;
        struct timeval timeout;
@@ -134,10 +136,11 @@ typedef struct mpd_Status {
        int state;
        /* crossfade setting in seconds */
        int crossfade;
-       /* if in PLAY or PAUSE state, this is the number of the currently
+       /* if in PLAY or PAUSE state, this is the position of the currently
         * playing song in the playlist, beginning with 0
         */
        int song;
+       int songid;
        /* time in seconds that have elapsed in the currently playing/paused
         * song
         */
@@ -158,6 +161,8 @@ typedef struct mpd_Status {
        char * error;
 } mpd_Status;
 
+void mpd_sendStatusCommand(mpd_Connection * connection);
+
 /* mpd_getStatus
  * returns status info, be sure to free it with mpd_freeStatus()
  */
@@ -178,6 +183,8 @@ typedef struct _mpd_Stats {
        unsigned long dbPlayTime;
 } mpd_Stats;
 
+void mpd_sendStatsCommand(mpd_Connection * connection);
+
 mpd_Stats * mpd_getStats(mpd_Connection * connection);
 
 void mpd_freeStats(mpd_Stats * stats);
@@ -186,6 +193,7 @@ void mpd_freeStats(mpd_Stats * stats);
 
 #define MPD_SONG_NO_TIME       -1
 #define MPD_SONG_NO_NUM                -1
+#define MPD_SONG_NO_ID         -1
 
 /* mpd_Song
  * for storing song info returned by mpd
@@ -206,9 +214,10 @@ typedef struct _mpd_Song {
        char * name;
        /* length of song in seconds, check that it is not MPD_SONG_NO_TIME  */
        int time;
-       /* if plchanges or playlistinfo used, is the number of the song in
+       /* if plchanges or playlistinfo used, is the position of the song in
         * the playlist */
-       int num;
+       int pos;
+       int id;
 } mpd_Song;
 
 /* mpd_newSong
@@ -318,6 +327,8 @@ void mpd_freeInfoEntity(mpd_InfoEntity * entity);
 /* use this function to loop over after calling Info/Listall functions */
 mpd_InfoEntity * mpd_getNextInfoEntity(mpd_Connection * connection);
 
+void mpd_sendCurrentSongCommand(mpd_Connection * connection);
+
 /* songNum of -1, means to display the whole list */
 void mpd_sendPlaylistInfoCommand(mpd_Connection * connection, int songNum);
 
@@ -362,6 +373,8 @@ void mpd_sendAddCommand(mpd_Connection * connection, const char * file);
 
 void mpd_sendDeleteCommand(mpd_Connection * connection, int songNum);
 
+void mpd_sendDeleteIdCommand(mpd_Connection * connection, int songNum);
+
 void mpd_sendSaveCommand(mpd_Connection * connection, const char * name);
 
 void mpd_sendLoadCommand(mpd_Connection * connection, const char * name);
@@ -377,9 +390,11 @@ void mpd_sendClearCommand(mpd_Connection * connection);
 
 void mpd_sendPlayCommand(mpd_Connection * connection, int songNum);
 
+void mpd_sendPlayIdCommand(mpd_Connection * connection, int songNum);
+
 void mpd_sendStopCommand(mpd_Connection * connection);
 
-void mpd_sendPauseCommand(mpd_Connection * connection);
+void mpd_sendPauseCommand(mpd_Connection * connection, int pauseMode);
 
 void mpd_sendNextCommand(mpd_Connection * connection);
 
@@ -387,10 +402,16 @@ void mpd_sendPrevCommand(mpd_Connection * connection);
 
 void mpd_sendMoveCommand(mpd_Connection * connection, int from, int to);
 
+void mpd_sendMoveIdCommand(mpd_Connection * connection, int from, int to);
+
 void mpd_sendSwapCommand(mpd_Connection * connection, int song1, int song2);
 
+void mpd_sendSwapIdCommand(mpd_Connection * connection, int song1, int song2);
+
 void mpd_sendSeekCommand(mpd_Connection * connection, int song, int time);
 
+void mpd_sendSeekIdCommand(mpd_Connection * connection, int song, int time);
+
 void mpd_sendRepeatCommand(mpd_Connection * connection, int repeatMode);
 
 void mpd_sendRandomCommand(mpd_Connection * connection, int randomMode);
@@ -417,8 +438,12 @@ void mpd_finishCommand(mpd_Connection * connection);
 /* command list stuff, use this to do things like add files very quickly */
 void mpd_sendCommandListBegin(mpd_Connection * connection);
 
+void mpd_sendCommandListOkBegin(mpd_Connection * connection);
+
 void mpd_sendCommandListEnd(mpd_Connection * connection);
 
+int mpd_nextListOkCommand(mpd_Connection * connection);
+
 #ifdef __cplusplus
 }
 #endif
index 7a44f09851b876957898c01af199573c510bc2c3..8d3a82fd2f90e2f2703d0b3395469a18e2b5bc64 100644 (file)
 
 #include "config.h"
 #include "ncmpc.h"
-#include "libmpdclient.h"
+#include "mpdclient.h"
 #include "support.h"
-#include "mpc.h"
 #include "options.h"
 #include "command.h"
 #include "screen.h"
 #include "conf.h"
 
-static mpd_client_t *mpc = NULL;
-static GTimer       *timer = NULL;
+static mpdclient_t   *mpd = NULL;
+static gboolean connected = FALSE;
+static GTimer      *timer = NULL;
+
+static void
+error_callback(mpdclient_t *c, int error, char *msg)
+{
+  D("error_callback> error=%d errorCode=%d errorAt=%d\n", 
+    error, c->connection->errorCode, c->connection->errorAt);
+  D("error_callback> \"%s\"\n", msg);
+  switch(error)
+    {
+    case MPD_ERROR_ACK:
+      screen_status_printf("%s", msg);
+      break;
+    default:
+      screen_status_printf(_("Lost connection to %s"), options.host);
+      connected = FALSE;
+    }
+  doupdate();
+}
 
 void
 exit_and_cleanup(void)
 {
   screen_exit();
   printf("\n");
-  if( mpc )
+  if( mpd )
     {
-      if( mpc_error(mpc) )
-       fprintf(stderr,"Error: %s\n", mpc_error_str(mpc));
-      mpc_close(mpc);
+      mpdclient_disconnect(mpd);
+      mpd = mpdclient_free(mpd);
     }
   g_free(options.host);
   g_free(options.password);
@@ -57,7 +74,7 @@ exit_and_cleanup(void)
 void
 catch_sigint( int sig )
 {
-  printf( _("\nExiting...\n"));
+  printf("\n%s\n", _("Exiting..."));
   exit(EXIT_SUCCESS);
 }
 
@@ -66,7 +83,6 @@ main(int argc, const char *argv[])
 {
   options_t *options;
   struct sigaction act;
-  gboolean connected;
   const char *charset = NULL;
 
 #ifdef HAVE_LOCALE_H
@@ -76,7 +92,7 @@ main(int argc, const char *argv[])
   setlocale(LC_CTYPE,"");
   /* initialize charset conversions */
   charset_init(g_get_charset(&charset));
-  D(printf("charset: %s\n", charset));
+  D("charset: %s\n", charset);
 #endif
 
   /* initialize i18n support */
@@ -133,12 +149,26 @@ main(int argc, const char *argv[])
   atexit(exit_and_cleanup);
 
   /* connect to our music player daemon */
-  mpc = mpc_connect(options->host, options->port, options->password);
-  if( mpc_error(mpc) )
-    exit(EXIT_FAILURE);
+  mpd = mpdclient_new();
+  if( mpdclient_connect(mpd, 
+                       options->host, 
+                       options->port, 
+                       10.0, 
+                       options->password) )
+    {
+      exit(EXIT_FAILURE);
+    }
+  connected = TRUE;
+  D("Connected to MPD version %d.%d.%d\n",
+    mpd->connection->version[0],
+    mpd->connection->version[1],
+    mpd->connection->version[2]);
 
   /* initialize curses */
-  screen_init();
+  screen_init(mpd);
+
+  /* install error callback function */
+  mpdclient_install_error_callback(mpd, error_callback);
 
   /* initialize timer */
   timer = g_timer_new();
@@ -148,27 +178,9 @@ main(int argc, const char *argv[])
     {
       static gdouble t = G_MAXDOUBLE;
 
-      if( connected && t>=MPD_UPDATE_TIME )
+      if( connected && (t>=MPD_UPDATE_TIME || mpd->need_update) )
        {
-         mpc_update(mpc);
-         if( mpc_error(mpc) == MPD_ERROR_ACK )
-           {
-             screen_status_printf("%s", mpc_error_str(mpc));
-             mpd_clearError(mpc->connection);
-             mpd_finishCommand(mpc->connection);
-           }
-         else if( mpc_error(mpc) )
-           {
-             screen_status_printf(_("Lost connection to %s"), options->host);
-             connected = FALSE;         
-             doupdate();
-             mpd_clearError(mpc->connection);
-             mpd_closeConnection(mpc->connection);
-             mpc->connection = NULL;
-           }
-         else  
-           mpd_finishCommand(mpc->connection);
-
+         mpdclient_update(mpd);
          g_timer_start(timer);
        }
 
@@ -176,36 +188,39 @@ main(int argc, const char *argv[])
        {
          command_t cmd;
 
-         screen_update(mpc);
+         screen_update(mpd);
          if( (cmd=get_keyboard_command()) != CMD_NONE )
            {
-             screen_cmd(mpc, cmd);
+             screen_cmd(mpd, cmd);
              if( cmd==CMD_VOLUME_UP || cmd==CMD_VOLUME_DOWN)
                /* make shure we dont update the volume yet */
                g_timer_start(timer);
            }
          else
-           screen_idle(mpc);
+           screen_idle(mpd);
        }
       else if( options->reconnect )
        {
-         if( get_keyboard_command_with_timeout(MPD_RECONNECT_TIME)==CMD_QUIT)
-           exit(EXIT_SUCCESS);
          screen_status_printf(_("Connecting to %s...  [Press %s to abort]"), 
                               options->host, get_key_names(CMD_QUIT,0) );
-         if( mpc_reconnect(mpc, 
-                           options->host, 
-                           options->port, 
-                           options->password) == 0 )
+         doupdate();
+
+         if( get_keyboard_command_with_timeout(MPD_RECONNECT_TIME)==CMD_QUIT)
+           exit(EXIT_SUCCESS);
+         
+         if( mpdclient_connect(mpd,
+                               options->host,
+                               options->port, 
+                               1.0,
+                               options->password) == 0 )
            {
              screen_status_printf(_("Connected to %s!"), options->host);
+             doupdate();
              connected = TRUE;
-           }
-         doupdate();
+           }     
        }
 
       t = g_timer_elapsed(timer, NULL);
     }
-
   exit(EXIT_FAILURE);
 }
diff --git a/src/mpc.c b/src/mpc.c
deleted file mode 100644 (file)
index e5b6a2e..0000000
--- a/src/mpc.c
+++ /dev/null
@@ -1,559 +0,0 @@
-/* 
- * $Id$
- *
- * (c) 2004 by Kalle Wallin <kaw@linux.se>
- *
- * 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 <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <time.h>
-#include <string.h>
-#include <glib.h>
-
-#include "config.h"
-#include "ncmpc.h"
-#include "support.h"
-#include "libmpdclient.h"
-#include "mpc.h"
-#include "options.h"
-
-#define MAX_SONG_LENGTH 1024
-
-int 
-mpc_close(mpd_client_t *c)
-{
-  if( c->connection )
-    mpd_closeConnection(c->connection);
-  if( c->cwd )
-    g_free( c->cwd );
-  
-  return 0;
-}
-
-mpd_client_t *
-mpc_connect(char *host, int port, char *password)
-{
-  mpd_Connection *connection;
-  mpd_client_t *c;
-
-  connection =  mpd_newConnection(host, port, 10);
-  if( connection==NULL )
-    {
-      fprintf(stderr, "mpd_newConnection to %s:%d failed!\n", host, port);
-      exit(EXIT_FAILURE);
-    }
-  
-  c = g_malloc(sizeof(mpd_client_t));
-  memset(c, 0, sizeof(mpd_client_t));
-  c->connection = connection;
-  c->cwd = g_strdup("");
-
-  if( password )
-    {
-      mpd_sendPasswordCommand(connection, password);
-      mpd_finishCommand(connection);
-    }
-
-  return c;
-}
-
-int
-mpc_reconnect(mpd_client_t *c, char *host, int port, char *password)
-{
-  mpd_Connection *connection;
-
-  connection =  mpd_newConnection(host, port, 1);
-  if( connection==NULL )
-    return -1;
-  if( connection->error )
-    {
-      mpd_closeConnection(connection);
-      return -1;
-    }
-  
-  c->connection = connection;
-
-  if( password )
-    {
-      mpd_sendPasswordCommand(connection, password);
-      mpd_finishCommand(connection);
-    }
-
-  return 0;
-}
-
-
-int
-mpc_error(mpd_client_t *c)
-{
-  if( c == NULL || c->connection == NULL )
-    return 1;
-
-  if( c->connection->error )
-      return c->connection->error;
-
-  return 0;
-}
-
-char *
-mpc_error_str(mpd_client_t *c)
-{
-  if( c == NULL || c->connection == NULL )
-    return "Not connected";
-
-  if( c->connection && c->connection->errorStr )
-    return c->connection->errorStr;
-
-  return NULL;
-}
-
-
-
-int
-mpc_free_playlist(mpd_client_t *c)
-{
-  GList *list;
-
-  if( c==NULL || c->playlist==NULL )
-    return -1;
-
-  list=g_list_first(c->playlist);
-
-  while( list!=NULL )
-    {
-      mpd_Song *song = (mpd_Song *) list->data;
-
-      mpd_freeSong(song);
-      list=list->next;
-    }
-  g_list_free(c->playlist);
-  c->playlist=NULL;
-  c->playlist_length=0;
-
-  c->song_id = -1;
-  c->song = NULL;
-
-  return 0;
-}
-
-int 
-mpc_get_playlist(mpd_client_t *c)
-{
-  mpd_InfoEntity *entity;
-
-  D(fprintf(stderr, "mpc_get_playlist() [%lld]\n", c->status->playlist));
-
-  if( mpc_error(c) )
-    return -1;
-
-  if( c->playlist )
-    mpc_free_playlist(c);
-
-  c->playlist_length=0;
-  mpd_sendPlaylistInfoCommand(c->connection,-1);
-  if( mpc_error(c) )
-    return -1;
-  while( (entity=mpd_getNextInfoEntity(c->connection)) ) 
-    {
-      if(entity->type==MPD_INFO_ENTITY_TYPE_SONG) 
-       {
-         mpd_Song *song = mpd_songDup(entity->info.song);
-
-         c->playlist = g_list_append(c->playlist, (gpointer) song);
-         c->playlist_length++;
-       }
-      mpd_freeInfoEntity(entity);
-    }
-  mpd_finishCommand(c->connection);
-  c->playlist_id = c->status->playlist;
-  c->playlist_updated = 1;
-  c->song_id = -1;
-  c->song = NULL;
-
-  mpc_filelist_set_selected(c);
-
-  return 0;
-}
-
-int 
-mpc_update_playlist(mpd_client_t *c)
-{
-  mpd_InfoEntity *entity;
-
-  D(fprintf(stderr, "mpc_update_playlist() [%lld -> %lld]\n", 
-           c->status->playlist, c->playlist_id));
-
-  if( mpc_error(c) )
-    return -1;
-
-  mpd_sendPlChangesCommand(c->connection, c->playlist_id);
-  if( mpc_error(c) )
-    return -1;
-
-  while( (entity=mpd_getNextInfoEntity(c->connection)) != NULL   ) 
-    {
-      if(entity->type==MPD_INFO_ENTITY_TYPE_SONG) 
-       {
-         mpd_Song *song;
-         GList *item;
-
-         if( (song=mpd_songDup(entity->info.song)) == NULL )
-           {
-             D(fprintf(stderr, "song==NULL\n"));
-             return mpc_get_playlist(c);
-           }
-
-         item =  g_list_nth(c->playlist, song->num);
-         if( item && item->data)
-           {
-             /* Update playlist entry */
-             mpd_freeSong((mpd_Song *) item->data);
-             item->data = song;
-             if( c->song_id == song->num )
-               c->song = song;
-             D(fprintf(stderr, "Changing num %d to %s\n",
-                       song->num, mpc_get_song_name(song)));
-           }
-         else
-           {
-             /* Add a new  playlist entry */
-             D(fprintf(stderr, "Adding num %d - %s\n",
-                       song->num, mpc_get_song_name(song)));
-             c->playlist = g_list_append(c->playlist, 
-                                         (gpointer) song);
-             c->playlist_length++;
-           }
-       }
-      mpd_freeInfoEntity(entity);      
-    }
-  mpd_finishCommand(c->connection);
-  
-  while( g_list_length(c->playlist) > c->status->playlistLength )
-    {
-      GList *item = g_list_last(c->playlist);
-
-      /* Remove the last playlist entry */
-      mpd_freeSong((mpd_Song *) item->data);
-      c->playlist = g_list_delete_link(c->playlist, item);
-      c->playlist_length--;      
-      D(fprintf(stderr, "Removed the last playlist entryn\n"));
-    }
-
-  c->playlist_id = c->status->playlist;
-  c->playlist_updated = 1;
-  mpc_filelist_set_selected(c);
-
-  return 0;
-}
-
-int
-mpc_playlist_get_song_index(mpd_client_t *c, char *filename)
-{
-  GList *list = c->playlist;
-  int i=0;
-
-  while( list )
-    {
-      mpd_Song *song = (mpd_Song *) list->data;
-      if( strcmp(song->file, filename ) == 0 ) 
-       return i;
-      list=list->next;
-      i++;
-    }
-  return -1;
-}
-
-mpd_Song *
-mpc_playlist_get_song(mpd_client_t *c, int n)
-{
-  return (mpd_Song *) g_list_nth_data(c->playlist, n);
-}
-
-
-char *
-mpc_get_song_name(mpd_Song *song)
-{
-  static char buf[MAX_SONG_LENGTH];
-  char *name;
-  
-  if( song->title )
-    {
-      if( song->artist )
-       {
-         snprintf(buf, MAX_SONG_LENGTH, "%s - %s", song->artist, song->title);
-         name = utf8_to_locale(buf);
-         strncpy(buf, name, MAX_SONG_LENGTH);
-         g_free(name);
-         return buf;
-       }
-      else
-       {
-         name = utf8_to_locale(song->title);
-         strncpy(buf, name, MAX_SONG_LENGTH);
-         g_free(name);
-         return buf;
-       }
-    }
-  name = utf8_to_locale(basename(song->file));
-  strncpy(buf, name, MAX_SONG_LENGTH);
-  g_free(name);
-  return buf;
-}
-
-char *
-mpc_get_song_name2(mpd_Song *song)
-{
-  static char buf[MAX_SONG_LENGTH];
-  char *name;
-
-  /* streams */
-  if( song->name )
-    {
-      name = utf8_to_locale(song->name);
-      strncpy(buf, name, MAX_SONG_LENGTH);
-      g_free(name);
-      return buf;
-    }
-  else if( strstr(song->file, "://") )
-    {
-      name = utf8_to_locale(song->file);
-      strncpy(buf, name, MAX_SONG_LENGTH);
-      g_free(name);
-      
-      return buf;
-    }
-
-  /* regular songs */
-  if( song->title )
-    {      
-      if( song->artist )
-       {
-         snprintf(buf, MAX_SONG_LENGTH, "%s - %s", song->artist, song->title);
-         name = utf8_to_locale(buf);
-         strncpy(buf, name, MAX_SONG_LENGTH);
-         g_free(name);
-         return buf;
-       }
-      else
-       {
-         name = utf8_to_locale(song->title);
-         strncpy(buf, name, MAX_SONG_LENGTH);
-         g_free(name);
-         return buf;
-       }
-    }
-  name = utf8_to_locale(basename(song->file));
-  strncpy(buf, name, MAX_SONG_LENGTH);
-  g_free(name);
-  return buf;
-}
-
-#if 0
-size_t
-strfsong(char *s, size_t max, const char *format, mpd_Song *song)
-{
-  size_t i, len, format_len;
-  char prev;
-
-  void sappend(char *utfstr) {
-    char *tmp = utf8_to_locale(utfstr);
-    size_t tmplen = strlen(tmp);
-    if( i+tmplen < max )
-      strcat(s, tmp);
-    else
-      strncat(s, tmp, max-i);
-    i = strlen(s);
-    g_free(tmp);
-  }
-
-  i = 0;
-  len = 0;
-  format_len = strlen(format);
-  memset(s, 0, max);
-  while(i<format_len && len<max)
-    {
-      if( i>0 && format[i-1]=='%' )
-       {
-         char *tmp;
-         size_t tmplen;
-
-         switch(format[i])
-           {
-           case '%':
-             s[len++] = format[i];
-             break;
-           case 'a':
-             sappend(song->artist);
-             break;
-           case 't':
-             sappend(song->title);
-             break;
-           case 'n':
-             sappend(song->name);
-             break;
-           case 'f':
-             sappend(song->file);
-             break;
-           }
-       }
-      else if( format[i]!='%' )
-       {
-         s[len] = format[i++];
-       }
-      len++;
-    }
-
-  return len;
-}
-#endif
-
-
-int 
-mpc_update(mpd_client_t *c)
-{
-  if( mpc_error(c) )
-    return -1;
-
-  if( c->status )
-    {
-      mpd_freeStatus(c->status);
-    }
-
-  c->status = mpd_getStatus(c->connection);
-  if( mpc_error(c) )
-    return -1;
-
-  if( c->playlist_id!=c->status->playlist )
-    {
-      if( c->playlist_length<2 )
-       mpc_get_playlist(c);
-      else
-       mpc_update_playlist(c);
-    }
-  
-  if( !c->song || c->status->song != c->song_id )
-    {
-      c->song = mpc_playlist_get_song(c, c->status->song);
-      c->song_id = c->status->song;
-      c->song_updated = 1;
-    }
-
-  return 0;
-}
-
-
-
-
-
-
-int
-mpc_free_filelist(mpd_client_t *c)
-{
-  GList *list;
-
-  if( c==NULL || c->filelist==NULL )
-    return -1;
-
-  list=g_list_first(c->filelist);
-
-  while( list!=NULL )
-    {
-      filelist_entry_t *entry = list->data;
-
-      if( entry->entity )
-       mpd_freeInfoEntity(entry->entity);
-      g_free(entry);
-      list=list->next;
-    }
-  g_list_free(c->filelist);
-  c->filelist=NULL;
-  c->filelist_length=0;
-
-  return 0;
-}
-
-
-
-int 
-mpc_update_filelist(mpd_client_t *c)
-{
-  mpd_InfoEntity *entity;
-
-  if( mpc_error(c) )
-    return -1;
-
-  if( c->filelist )
-    mpc_free_filelist(c);
-
-  c->filelist_length=0;
-
-  mpd_sendLsInfoCommand(c->connection, c->cwd);
-  
-  if( c->cwd && c->cwd[0] )
-    {
-      /* add a dummy entry for ./.. */
-      filelist_entry_t *entry = g_malloc(sizeof(filelist_entry_t));
-      memset(entry, 0, sizeof(filelist_entry_t));
-      entry->entity = NULL;
-      c->filelist = g_list_append(c->filelist, (gpointer) entry);
-      c->filelist_length++;
-    }
-
-  while( (entity=mpd_getNextInfoEntity(c->connection)) ) 
-    {
-      filelist_entry_t *entry = g_malloc(sizeof(filelist_entry_t));
-      
-      memset(entry, 0, sizeof(filelist_entry_t));
-      entry->entity = entity;
-      c->filelist = g_list_append(c->filelist, (gpointer) entry);
-      c->filelist_length++;
-    }
-  
-  c->filelist_updated = 1;
-
-  mpd_finishCommand(c->connection);
-
-  mpc_filelist_set_selected(c);
-
-  return 0;
-}
-
-int 
-mpc_filelist_set_selected(mpd_client_t *c)
-{
-  GList *list = c->filelist;
-
-  while( list )
-    {
-      filelist_entry_t *entry = list->data;
-      mpd_InfoEntity *entity = entry->entity ;      
-      
-      if( entity && entity->type==MPD_INFO_ENTITY_TYPE_SONG )
-       {
-         mpd_Song *song = entity->info.song;
-
-         if( mpc_playlist_get_song_index(c, song->file) >= 0 )
-           entry->selected = 1;
-         else
-           entry->selected = 0;
-       }
-
-      list=list->next;
-    }
-  return 0;
-}
diff --git a/src/mpc.h b/src/mpc.h
deleted file mode 100644 (file)
index 152f153..0000000
--- a/src/mpc.h
+++ /dev/null
@@ -1,51 +0,0 @@
-
-typedef struct
-{
-  char selected;
-  mpd_InfoEntity *entity;
-} filelist_entry_t;
-
-typedef struct
-{
-  mpd_Connection *connection;
-  mpd_Status     *status;
-
-  mpd_Song       *song;
-  int            song_id;
-  int            song_updated;
-
-  int            seek_song_id;
-  int            seek_target_time;
-
-  GList         *playlist;
-  int            playlist_length;
-  long long      playlist_id;
-  int            playlist_updated;
-
-  char           *cwd;
-  GList          *filelist;
-  int            filelist_length;
-  int            filelist_updated;
-
-} mpd_client_t;
-
-
-int mpc_close(mpd_client_t *c);
-
-mpd_client_t *mpc_connect(char *host, int port, char *passwd);
-int mpc_reconnect(mpd_client_t *c, char *host, int port, char *passwd);
-
-int mpc_update(mpd_client_t *c);
-int mpc_update_playlist(mpd_client_t *c);
-
-int mpc_update_filelist(mpd_client_t *c);
-int mpc_filelist_set_selected(mpd_client_t *c);
-int mpc_set_cwd(mpd_client_t *c, char *dir);
-
-mpd_Song *mpc_playlist_get_song(mpd_client_t *c, int n);
-char *mpc_get_song_name(mpd_Song *song);
-char *mpc_get_song_name2(mpd_Song *song);
-int mpc_playlist_get_song_index(mpd_client_t *c, char *filename);
-
-int   mpc_error(mpd_client_t *c);
-char *mpc_error_str(mpd_client_t *c);
diff --git a/src/mpdclient.c b/src/mpdclient.c
new file mode 100644 (file)
index 0000000..af6476f
--- /dev/null
@@ -0,0 +1,868 @@
+/* 
+ * $Id$
+ *
+ * (c) 2004 by Kalle Wallin <kaw@linux.se>
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+#include <string.h>
+#include <glib.h>
+
+#include "config.h"
+#include "ncmpc.h"
+#include "support.h"
+#include "mpdclient.h"
+#include "options.h"
+
+#undef  ENABLE_FANCY_PLAYLIST_MANAGMENT_CMD_ADD /* broken with song id's */
+#define ENABLE_FANCY_PLAYLIST_MANAGMENT_CMD_DELETE
+#define ENABLE_FANCY_PLAYLIST_MANAGMENT_CMD_MOVE
+#undef  ENABLE_SONG_ID
+
+#define MPD_ERROR(c) (c==NULL || c->connection==NULL || c->connection->error)
+
+
+/* Error callbacks */
+static gint
+error_cb(mpdclient_t *c, gint error, gchar *msg)
+{
+  GList *list = c->error_callbacks;
+  
+  if( list==NULL )
+    fprintf(stderr, "error [%d]: %s\n", error, msg);
+
+  while(list)
+    {
+      mpdc_error_cb_t cb = list->data;
+      if( cb )
+       cb(c, error, msg);
+      list=list->next;
+    }
+  mpd_clearError(c->connection);
+  return error;
+}
+
+#ifdef DEBUG
+#include "strfsong.h"
+
+static gchar *
+get_song_name(mpd_Song *song)
+{
+  static gchar name[256];
+
+  strfsong(name, 256, "[%artist% - ]%title%|%file%", song);
+  return name;
+}
+
+#endif
+
+/****************************************************************************/
+/*** mpdclient functions ****************************************************/
+/****************************************************************************/
+
+gint
+mpdclient_finish_command(mpdclient_t *c) 
+{
+  mpd_finishCommand(c->connection);
+
+  if( c->connection->error )
+    {
+      gchar *msg = locale_to_utf8(c->connection->errorStr);
+      gint retval = c->connection->error;
+
+      error_cb(c, c->connection->error, msg);
+      g_free(msg);
+      return retval;
+    }
+
+  return 0;
+}
+
+mpdclient_t *
+mpdclient_new(void)
+{
+  mpdclient_t *c;
+
+  c = g_malloc0(sizeof(mpdclient_t));
+
+  return c;
+}
+
+mpdclient_t *
+mpdclient_free(mpdclient_t *c)
+{
+  mpdclient_disconnect(c);
+  g_list_free(c->error_callbacks);
+  g_list_free(c->playlist_callbacks);
+  g_list_free(c->browse_callbacks);
+  g_free(c);
+
+  return NULL;
+}
+
+gint
+mpdclient_disconnect(mpdclient_t *c)
+{
+  D("mpdclient_disconnect()...\n");
+  if( c->connection )
+    mpd_closeConnection(c->connection);
+  c->connection = NULL;
+
+  if( c->status )
+    mpd_freeStatus(c->status);
+  c->status = NULL;
+
+  if( c->playlist.list )
+    mpdclient_playlist_free(&c->playlist);
+
+  if( c->song )
+    c->song = NULL;
+  
+  return 0;
+}
+
+gint
+mpdclient_connect(mpdclient_t *c, 
+                 gchar *host, 
+                 gint port, 
+                 gfloat timeout,
+                 gchar *password)
+{
+  gint retval = 0;
+  
+  /* close any open connection */
+  if( c->connection )
+    mpdclient_disconnect(c);
+
+  /* connect to MPD */
+  D("mpdclient_connect(%s, %d)...\n", host, port);
+  c->connection = mpd_newConnection(host, port, timeout);
+  if( c->connection->error )
+    return error_cb(c, c->connection->error, c->connection->errorStr);
+
+  /* send password */
+  if( password )
+    {
+      mpd_sendPasswordCommand(c->connection, password);
+      retval = mpdclient_finish_command(c);
+    }
+
+  return retval;
+}
+
+gint
+mpdclient_update(mpdclient_t *c)
+{
+  gint retval = 0;
+
+  if( MPD_ERROR(c) )
+    return -1;
+
+  /* free the old status */
+  if( c->status )
+    mpd_freeStatus(c->status);
+  
+  /* retreive new status */
+  mpd_sendStatusCommand(c->connection);
+  c->status = mpd_getStatus(c->connection);
+  if( (retval=mpdclient_finish_command(c)) )
+    return retval;
+#ifdef DEBUG
+  if( c->status->error )
+    D("status> %s\n", c->status->error);
+#endif
+
+  /* check if the playlist needs an update */
+  if( c->playlist.id != c->status->playlist )
+    {
+      if( c->playlist.list )
+       retval = mpdclient_playlist_update_changes(c);
+      else
+       retval = mpdclient_playlist_update(c);
+    }
+
+  /* update the current song */
+  if( !c->song || c->status->songid != c->song->id )
+    {
+      c->song = playlist_get_song(c, c->status->song);
+    }
+
+  c->need_update = FALSE;
+
+  return retval;
+}
+
+
+/****************************************************************************/
+/*** MPD Commands  **********************************************************/
+/****************************************************************************/
+
+gint 
+mpdclient_cmd_play(mpdclient_t *c, gint index)
+{
+#ifdef ENABLE_SONG_ID
+  mpd_Song *song = playlist_get_song(c, index);
+
+  if( song )
+    mpd_sendPlayIdCommand(c->connection, song->id);
+  else
+    mpd_sendPlayIdCommand(c->connection, MPD_PLAY_AT_BEGINNING);
+#else
+  mpd_sendPlayCommand(c->connection, index);
+#endif
+  c->need_update = TRUE;
+  return mpdclient_finish_command(c);
+}
+
+gint 
+mpdclient_cmd_pause(mpdclient_t *c, gint value)
+{
+  mpd_sendPauseCommand(c->connection, value);
+  return mpdclient_finish_command(c);
+}
+
+gint 
+mpdclient_cmd_stop(mpdclient_t *c)
+{
+  mpd_sendStopCommand(c->connection);
+  return mpdclient_finish_command(c);
+}
+
+gint 
+mpdclient_cmd_next(mpdclient_t *c)
+{
+  mpd_sendNextCommand(c->connection);
+  c->need_update = TRUE;
+  return mpdclient_finish_command(c);
+}
+
+gint 
+mpdclient_cmd_prev(mpdclient_t *c)
+{
+  mpd_sendPrevCommand(c->connection);
+  c->need_update = TRUE;
+  return mpdclient_finish_command(c);
+}
+
+gint 
+mpdclient_cmd_seek(mpdclient_t *c, gint id, gint pos)
+{
+  mpd_sendSeekIdCommand(c->connection, id, pos);
+  return mpdclient_finish_command(c);
+}
+
+gint 
+mpdclient_cmd_shuffle(mpdclient_t *c)
+{
+  mpd_sendShuffleCommand(c->connection);
+  c->need_update = TRUE;
+  return mpdclient_finish_command(c);
+}
+
+gint 
+mpdclient_cmd_clear(mpdclient_t *c)
+{
+  gint retval = 0;
+
+  mpd_sendClearCommand(c->connection);
+  retval = mpdclient_finish_command(c);
+  /* call playlist updated callback */
+  mpdclient_playlist_callback(c, PLAYLIST_EVENT_CLEAR, NULL);
+  c->need_update = TRUE;
+  return retval;
+}
+
+gint 
+mpdclient_cmd_repeat(mpdclient_t *c, gint value)
+{
+  mpd_sendRepeatCommand(c->connection, value);
+  return mpdclient_finish_command(c);
+}
+
+gint 
+mpdclient_cmd_random(mpdclient_t *c, gint value)
+{
+  mpd_sendRandomCommand(c->connection, value);
+  return mpdclient_finish_command(c);
+}
+
+gint 
+mpdclient_cmd_crossfade(mpdclient_t *c, gint value)
+{
+  mpd_sendCrossfadeCommand(c->connection, value);
+  return mpdclient_finish_command(c);
+}
+
+gint 
+mpdclient_cmd_db_update(mpdclient_t *c)
+{
+  mpd_sendUpdateCommand(c->connection);
+  return mpdclient_finish_command(c);
+}
+
+gint 
+mpdclient_cmd_volume(mpdclient_t *c, gint value)
+{
+  mpd_sendSetvolCommand(c->connection, value);
+  return mpdclient_finish_command(c);
+}
+
+gint 
+mpdclient_cmd_add(mpdclient_t *c, mpd_Song *song)
+{ 
+  gint retval = 0;
+
+  if( !song || !song->file )
+    return -1;
+
+  /* send the add command to mpd */
+  mpd_sendAddCommand(c->connection, song->file);
+  if( (retval=mpdclient_finish_command(c)) )
+    return retval;
+
+#ifdef ENABLE_FANCY_PLAYLIST_MANAGMENT_CMD_ADD
+  /* add the song to playlist */
+  c->playlist.list = g_list_append(c->playlist.list, mpd_songDup(song));
+  c->playlist.length++;
+
+  /* increment the playlist id, so we dont retrives a new playlist */
+  c->playlist.id++;
+
+  /* call playlist updated callback */
+  mpdclient_playlist_callback(c, PLAYLIST_EVENT_ADD, (gpointer) song);
+#else
+  c->need_update = TRUE;
+#endif
+
+  return 0;
+}
+
+gint
+mpdclient_cmd_delete(mpdclient_t *c, gint index)
+{
+  gint retval = 0;
+  mpd_Song *song = playlist_get_song(c, index);
+
+  if( !song )
+    return -1;
+
+  /* send the delete command to mpd */
+#ifdef ENABLE_SONG_ID
+  mpd_sendDeleteIdCommand(c->connection, song->id);
+#else
+  mpd_sendDeleteCommand(c->connection, index);
+#endif
+  if( (retval=mpdclient_finish_command(c)) )
+    return retval;
+
+#ifdef ENABLE_FANCY_PLAYLIST_MANAGMENT_CMD_DELETE
+  /* increment the playlist id, so we dont retrive a new playlist */
+  c->playlist.id++;
+
+  /* remove the song from the playlist */
+  c->playlist.list = g_list_remove(c->playlist.list, (gpointer) song);
+  c->playlist.length = g_list_length(c->playlist.list);
+
+  /* call playlist updated callback */
+  mpdclient_playlist_callback(c, PLAYLIST_EVENT_DELETE, (gpointer) song);
+
+  /* remove references to the song */
+  if( c->song == song )
+    {
+      c->song = NULL;   
+      c->need_update = TRUE;
+    }
+
+  /* free song */
+  mpd_freeSong(song);  
+
+#else
+  c->need_update = TRUE;
+#endif
+
+  return 0;
+}
+
+gint
+mpdclient_cmd_move(mpdclient_t *c, gint old_index, gint new_index)
+{
+  gint retval, index1, index2;
+  GList *item1, *item2;
+  gpointer data1, data2;
+  mpd_Song *song1, *song2;
+
+  if( old_index==new_index || new_index<0 || new_index>=c->playlist.length )
+    return -1;
+
+  song1 = playlist_get_song(c, old_index);
+  song2 = playlist_get_song(c, new_index);
+
+  /* send the move command to mpd */  
+#ifdef ENABLE_SONG_ID
+  mpd_sendMoveIdCommand(c->connection, song1->id, song2->id);
+#else
+  mpd_sendMoveCommand(c->connection, old_index, new_index);
+#endif
+  if( (retval=mpdclient_finish_command(c)) )
+    return retval;
+
+#ifdef ENABLE_FANCY_PLAYLIST_MANAGMENT_CMD_MOVE
+  index1 = MIN(old_index, new_index);
+  index2 = MAX(old_index, new_index);
+  item1 = g_list_nth(c->playlist.list, index1);
+  item2 = g_list_nth(c->playlist.list, index2);
+  data1 = item1->data;
+  data2 = item2->data;
+
+  /* move the second item */
+  c->playlist.list = g_list_remove(c->playlist.list, data2);
+  c->playlist.list = g_list_insert_before(c->playlist.list, item1, data2);
+
+  /* move the first item */
+  if( index2-index1 >1 )
+    {
+      item2 = g_list_nth(c->playlist.list, index2);
+      c->playlist.list = g_list_remove(c->playlist.list, data1);
+      c->playlist.list = g_list_insert_before(c->playlist.list, item2, data1);
+    }
+
+  /* increment the playlist id, so we dont retrives a new playlist */
+  c->playlist.id++;
+
+  /* call playlist updated callback */
+  mpdclient_playlist_callback(c, PLAYLIST_EVENT_MOVE, (gpointer) &new_index);
+#else
+  c->need_update = TRUE;
+#endif 
+
+  return 0;
+}
+
+gint 
+mpdclient_cmd_save_playlist(mpdclient_t *c, gchar *filename)
+{
+  gint retval = 0;
+  gchar *filename_utf8 = locale_to_utf8(filename);
+
+  mpd_sendSaveCommand(c->connection, filename_utf8);
+  if( (retval=mpdclient_finish_command(c)) == 0 )
+    mpdclient_browse_callback(c, BROWSE_PLAYLIST_SAVED, NULL);
+  g_free(filename_utf8);
+  return retval;
+}
+
+gint 
+mpdclient_cmd_load_playlist(mpdclient_t *c, gchar *filename_utf8)
+{
+  mpd_sendLoadCommand(c->connection, filename_utf8);
+  c->need_update = TRUE;
+  return mpdclient_finish_command(c);
+}
+
+gint 
+mpdclient_cmd_delete_playlist(mpdclient_t *c, gchar *filename_utf8)
+{
+  gint retval = 0;
+
+  mpd_sendRmCommand(c->connection, filename_utf8);
+  if( (retval=mpdclient_finish_command(c)) == 0 )
+    mpdclient_browse_callback(c, BROWSE_PLAYLIST_DELETED, NULL);
+  return retval;
+}
+
+
+/****************************************************************************/
+/*** Callback managment functions *******************************************/
+/****************************************************************************/
+static void
+do_list_callbacks(mpdclient_t *c, GList *list, gint event, gpointer data)
+{
+  while(list)
+    {
+      mpdc_list_cb_t fn = list->data;
+
+      fn(c, event, data);
+      list=list->next;
+    }
+}
+
+void
+mpdclient_playlist_callback(mpdclient_t *c, int event, gpointer data)
+{
+  do_list_callbacks(c, c->playlist_callbacks, event, data);
+}
+
+void
+mpdclient_install_playlist_callback(mpdclient_t *c,mpdc_list_cb_t cb)
+{
+  c->playlist_callbacks = g_list_append(c->playlist_callbacks, cb);
+}
+
+void
+mpdclient_remove_playlist_callback(mpdclient_t *c, mpdc_list_cb_t cb)
+{
+  c->playlist_callbacks = g_list_remove(c->playlist_callbacks, cb);
+}
+
+void
+mpdclient_browse_callback(mpdclient_t *c, int event, gpointer data)
+{
+  do_list_callbacks(c, c->browse_callbacks, event, data);
+}
+
+
+void
+mpdclient_install_browse_callback(mpdclient_t *c,mpdc_list_cb_t cb)
+{
+  c->browse_callbacks = g_list_append(c->browse_callbacks, cb);
+}
+
+void
+mpdclient_remove_browse_callback(mpdclient_t *c, mpdc_list_cb_t cb)
+{
+  c->browse_callbacks = g_list_remove(c->browse_callbacks, cb);
+}
+
+void
+mpdclient_install_error_callback(mpdclient_t *c, mpdc_error_cb_t cb)
+{
+  c->error_callbacks = g_list_append(c->error_callbacks, cb);
+}
+
+void
+mpdclient_remove_error_callback(mpdclient_t *c, mpdc_error_cb_t cb)
+{
+  c->error_callbacks = g_list_remove(c->error_callbacks, cb);
+}
+
+/****************************************************************************/
+/*** Playlist managment functions *******************************************/
+/****************************************************************************/
+
+gint
+mpdclient_playlist_free(mpdclient_playlist_t *playlist)
+{
+  GList *list = g_list_first(playlist->list);
+
+  while(list)
+    {
+      mpd_Song *song = (mpd_Song *) list->data;
+      mpd_freeSong(song);
+      list=list->next;
+    }
+  g_list_free(playlist->list);
+  playlist->list   = NULL;
+  playlist->length = 0;
+  return 0;
+}
+
+/* update playlist */
+gint 
+mpdclient_playlist_update(mpdclient_t *c)
+{
+  mpd_InfoEntity *entity;
+
+  D("mpdclient_playlist_update() [%lld]\n", c->status->playlist);
+
+  if( MPD_ERROR(c) )
+    return -1;
+
+  if( c->playlist.list )
+    mpdclient_playlist_free(&c->playlist);
+
+  c->song = NULL;
+  c->playlist.updated = TRUE;
+
+  mpd_sendPlaylistInfoCommand(c->connection,-1);
+  while( (entity=mpd_getNextInfoEntity(c->connection)) ) 
+    {
+      if(entity->type==MPD_INFO_ENTITY_TYPE_SONG) 
+       {
+         mpd_Song *song = mpd_songDup(entity->info.song);
+
+         c->playlist.list = g_list_append(c->playlist.list, (gpointer) song);
+         c->playlist.length++;
+       }
+      mpd_freeInfoEntity(entity);
+    }
+  c->playlist.id = c->status->playlist;
+  c->song = NULL;
+
+  /* call playlist updated callbacks */
+  mpdclient_playlist_callback(c, PLAYLIST_EVENT_UPDATED, NULL);
+
+  return mpdclient_finish_command(c);
+}
+
+/* update playlist (plchanges) */
+gint 
+mpdclient_playlist_update_changes(mpdclient_t *c)
+{
+  mpd_InfoEntity *entity;
+
+  D("mpdclient_playlist_update_changes() [%lld -> %lld]\n", 
+    c->status->playlist, c->playlist.id);
+
+  if( MPD_ERROR(c) )
+    return -1;
+
+  mpd_sendPlChangesCommand(c->connection, c->playlist.id); 
+
+  while( (entity=mpd_getNextInfoEntity(c->connection)) != NULL   ) 
+    {
+      if(entity->type==MPD_INFO_ENTITY_TYPE_SONG) 
+       {
+         mpd_Song *song;
+         GList *item;
+
+         if( (song=mpd_songDup(entity->info.song)) == NULL )
+           {
+             D("song==NULL => calling mpdclient_playlist_update()\n");
+             return mpdclient_playlist_update(c);
+           }
+
+         item =  playlist_lookup(c, song->id);
+
+         if( item && item->data)
+           {
+             /* Update playlist entry */
+             mpd_freeSong((mpd_Song *) item->data);
+             item->data = song;
+             if( c->song && c->song->id == song->id )
+               c->song = song;
+             D("Changing num %d [%d] to %s\n",
+               song->pos, song->id, get_song_name(song));
+           }
+         else
+           {
+             /* Add a new  playlist entry */
+             D("Adding pos:%d, id;%d - %s\n",
+               song->pos, song->id, get_song_name(song));
+             c->playlist.list = g_list_append(c->playlist.list, 
+                                         (gpointer) song);
+             c->playlist.length++;
+           }
+       }
+      mpd_freeInfoEntity(entity);      
+    }
+  mpd_finishCommand(c->connection);
+  
+  while( g_list_length(c->playlist.list) > c->status->playlistLength )
+    {
+      GList *item = g_list_last(c->playlist.list);
+
+      /* Remove the last playlist entry */
+      mpd_freeSong((mpd_Song *) item->data);
+      c->playlist.list = g_list_delete_link(c->playlist.list, item);
+      c->playlist.length--;      
+      D("Removed the last playlist entry\n");
+    }
+
+  c->playlist.id = c->status->playlist;
+  c->playlist.updated = TRUE;
+
+  mpdclient_playlist_callback(c, PLAYLIST_EVENT_UPDATED, NULL);
+
+  return 0;
+}
+
+mpd_Song *
+playlist_get_song(mpdclient_t *c, gint index)
+{
+  return (mpd_Song *) g_list_nth_data(c->playlist.list, index);
+}
+
+GList *
+playlist_lookup(mpdclient_t *c, gint id)
+{
+  GList *list = c->playlist.list;
+
+  while( list )
+    {
+      mpd_Song *song = (mpd_Song *) list->data;
+      if( song->id == id )
+       return list;
+      list=list->next;
+    }
+  return NULL;
+}
+
+mpd_Song *
+playlist_lookup_song(mpdclient_t *c, gint id)
+{
+  GList *list = c->playlist.list;
+
+  while( list )
+    {
+      mpd_Song *song = (mpd_Song *) list->data;
+      if( song->id == id )
+       return song;
+      list=list->next;
+    }
+  return NULL;
+}
+
+gint 
+playlist_get_index(mpdclient_t *c, mpd_Song *song)
+{
+  return g_list_index(c->playlist.list, song);
+}
+
+gint 
+playlist_get_index_from_id(mpdclient_t *c, gint id)
+{
+  return g_list_index(c->playlist.list, playlist_lookup_song(c, id));
+}
+
+gint
+playlist_get_index_from_file(mpdclient_t *c, gchar *filename)
+{
+  GList *list = c->playlist.list;
+  gint i=0;
+
+  while( list )
+    {
+      mpd_Song *song = (mpd_Song *) list->data;
+      if( strcmp(song->file, filename ) == 0 ) 
+       return i;
+      list=list->next;
+      i++;
+    }
+  return -1;
+}
+
+
+/****************************************************************************/
+/*** Filelist functions *****************************************************/
+/****************************************************************************/
+
+mpdclient_filelist_t *
+mpdclient_filelist_free(mpdclient_filelist_t *filelist)
+{
+  GList *list = g_list_first(filelist->list);
+
+  while( list!=NULL )
+    {
+      filelist_entry_t *entry = list->data;
+
+      if( entry->entity )
+       mpd_freeInfoEntity(entry->entity);
+      g_free(entry);
+      list=list->next;
+    }
+  g_list_free(filelist->list);
+  g_free(filelist->path);
+  filelist->path = NULL;
+  filelist->list = NULL;
+  filelist->length = 0;
+  g_free(filelist);
+
+  return NULL;
+}
+
+
+mpdclient_filelist_t *
+mpdclient_filelist_get(mpdclient_t *c, gchar *path)
+{
+  mpdclient_filelist_t *filelist;
+  mpd_InfoEntity *entity;
+  gchar *path_utf8 = locale_to_utf8(path);
+
+  mpd_sendLsInfoCommand(c->connection, path_utf8);
+  filelist = g_malloc0(sizeof(mpdclient_filelist_t));
+  if( path && path[0] && strcmp(path, "/") )
+    {
+      /* add a dummy entry for ./.. */
+      filelist_entry_t *entry = g_malloc0(sizeof(filelist_entry_t));
+      entry->entity = NULL;
+      filelist->list = g_list_append(filelist->list, (gpointer) entry);
+      filelist->length++;
+    }
+
+  while( (entity=mpd_getNextInfoEntity(c->connection)) ) 
+    {
+      filelist_entry_t *entry = g_malloc0(sizeof(filelist_entry_t));
+      
+      entry->entity = entity;
+      filelist->list = g_list_append(filelist->list, (gpointer) entry);
+      filelist->length++;
+    }
+  
+  if( mpdclient_finish_command(c) )
+    {
+      g_free(path_utf8);
+      return mpdclient_filelist_free(filelist);
+    }
+  
+  g_free(path_utf8);
+  filelist->path = g_strdup(path);
+  filelist->updated = TRUE;
+
+  return filelist;
+}
+
+mpdclient_filelist_t *
+mpdclient_filelist_update(mpdclient_t *c, mpdclient_filelist_t *filelist)
+{
+  if( filelist == NULL )
+    {    
+      gchar *path = g_strdup(filelist->path);
+
+      filelist = mpdclient_filelist_free(filelist);
+      filelist = mpdclient_filelist_get(c, path);
+      g_free(path);
+      return filelist;
+    }
+  return NULL;
+}
+
+filelist_entry_t *
+mpdclient_filelist_find_song(mpdclient_filelist_t *fl, mpd_Song *song)
+{
+  GList *list = g_list_first(fl->list);
+
+  while( list && song)
+    {
+      filelist_entry_t *entry = list->data;
+      mpd_InfoEntity *entity  = entry->entity;
+
+      if( entity && entity->type==MPD_INFO_ENTITY_TYPE_SONG )
+       {
+         mpd_Song *song2 = entity->info.song;
+
+         if( strcmp(song->file, song2->file) == 0 )
+           {
+             return entry;
+           }
+       }
+      list = list->next;
+    }
+  return NULL;
+}
+
+
+
+
+
+
+
+
+
+
diff --git a/src/mpdclient.h b/src/mpdclient.h
new file mode 100644 (file)
index 0000000..86f1b0c
--- /dev/null
@@ -0,0 +1,173 @@
+#ifndef MPDCLIENT_H
+#define MPDCLIENT_H
+#include "libmpdclient.h"
+
+/****************************************************************************/
+/* Playlist */
+/****************************************************************************/
+
+typedef struct
+{
+  /* playlist id */
+  long long id;
+  /* list length */
+  guint length;
+  /* true if the list is updated */
+  gboolean updated;
+  /* the list */
+  GList *list;
+
+} mpdclient_playlist_t;
+
+
+typedef struct
+{
+  guint flags;
+  mpd_InfoEntity *entity;
+} filelist_entry_t;
+
+typedef struct
+{
+  /* path */
+  gchar *path;
+  /* list length */
+  guint length;
+  /* true if the list is updated */
+  gboolean updated;
+  /* the list */
+  GList *list;
+
+} mpdclient_filelist_t;
+
+typedef struct
+{
+  /* playlist */
+  mpdclient_playlist_t playlist;
+
+  /* Callbacks */
+  GList *error_callbacks;
+  GList *playlist_callbacks;
+  GList *browse_callbacks;
+
+  mpd_Connection *connection;
+  mpd_Status     *status;
+  mpd_Song       *song;
+
+  gboolean       need_update;
+
+} mpdclient_t;
+
+/** functions ***************************************************************/
+mpdclient_t *mpdclient_new(void);
+mpdclient_t *mpdclient_free(mpdclient_t *c);
+gint mpdclient_connect(mpdclient_t *c, gchar *host, gint port,
+                      gfloat timeout, gchar *password);
+gint mpdclient_disconnect(mpdclient_t *c);
+gint mpdclient_update(mpdclient_t *c);
+
+
+/*** MPD Commands  **********************************************************/
+gint mpdclient_cmd_play(mpdclient_t *c, gint index);
+gint mpdclient_cmd_pause(mpdclient_t *c, gint value);
+gint mpdclient_cmd_stop(mpdclient_t *c);
+gint mpdclient_cmd_next(mpdclient_t *c);
+gint mpdclient_cmd_prev(mpdclient_t *c);
+gint mpdclient_cmd_seek(mpdclient_t *c, gint id, gint pos);
+gint mpdclient_cmd_shuffle(mpdclient_t *c);
+gint mpdclient_cmd_clear(mpdclient_t *c);
+gint mpdclient_cmd_repeat(mpdclient_t *c, gint value);
+gint mpdclient_cmd_random(mpdclient_t *c, gint value);
+gint mpdclient_cmd_crossfade(mpdclient_t *c, gint value);
+gint mpdclient_cmd_db_update(mpdclient_t *c);
+gint mpdclient_cmd_volume(mpdclient_t *c, gint value);
+
+gint mpdclient_cmd_add(mpdclient_t *c, mpd_Song *song);
+gint mpdclient_cmd_delete(mpdclient_t *c, gint index);
+gint mpdclient_cmd_move(mpdclient_t *c, gint old_index, gint new_index);
+
+gint mpdclient_cmd_save_playlist(mpdclient_t *c, gchar *filename);
+gint mpdclient_cmd_load_playlist(mpdclient_t *c, gchar *filename_utf8);
+gint mpdclient_cmd_delete_playlist(mpdclient_t *c, gchar *filename_utf8);
+
+
+/*** error callbacks *****************************************************/ 
+typedef void (*mpdc_error_cb_t) (mpdclient_t *c, gint error, gchar *msg);
+
+void mpdclient_install_error_callback(mpdclient_t *c, mpdc_error_cb_t cb);
+void mpdclient_remove_error_callback(mpdclient_t *c, mpdc_error_cb_t cb);
+
+/*** playlist functions  **************************************************/
+
+/* free a playlist */
+gint mpdclient_playlist_free(mpdclient_playlist_t *playlist);
+/* update the complete playlist */
+gint mpdclient_playlist_update(mpdclient_t *c);
+/* get playlist changes */
+gint mpdclient_playlist_update_changes(mpdclient_t *c);
+
+GList *playlist_lookup(mpdclient_t *c, gint id);
+mpd_Song *playlist_lookup_song(mpdclient_t *c, gint id);
+mpd_Song *playlist_get_song(mpdclient_t *c, gint index);
+gint playlist_get_index(mpdclient_t *c, mpd_Song *song);
+gint playlist_get_index_from_id(mpdclient_t *c, gint id);
+gint playlist_get_index_from_file(mpdclient_t *c, gchar *filename);
+
+
+
+/*** mpdclient playlist callbacks *****************************************/
+
+#define PLAYLIST_EVENT_UPDATED     0x01
+#define PLAYLIST_EVENT_CLEAR       0x02
+#define PLAYLIST_EVENT_DELETE      0x03
+#define PLAYLIST_EVENT_ADD         0x04
+#define PLAYLIST_EVENT_MOVE        0x05
+
+
+typedef void (*mpdc_list_cb_t) (mpdclient_t *c, int event, gpointer data);
+
+/* install a playlist callback function */
+void mpdclient_install_playlist_callback(mpdclient_t *c, mpdc_list_cb_t cb);
+
+/* remove a playlist callback function */
+void mpdclient_remove_playlist_callback(mpdclient_t *c, mpdc_list_cb_t cb);
+
+
+/* issue a playlist callback */
+void mpdclient_playlist_callback(mpdclient_t *c, int event, gpointer data);
+
+
+/*** filelist functions  ***************************************************/
+mpdclient_filelist_t *mpdclient_filelist_free(mpdclient_filelist_t *filelist);
+mpdclient_filelist_t *mpdclient_filelist_get(mpdclient_t *c, gchar *path);
+mpdclient_filelist_t *mpdclient_filelist_update(mpdclient_t *c, 
+                                               mpdclient_filelist_t *flist);
+
+#define HIGHLIGHT  (0x01)
+void mpdclient_filelist_set_flags(mpdclient_filelist_t *flist, 
+                                 mpd_Song *song,
+                                 guint flags);
+
+void mpdclient_filelist_clear_flags(mpdclient_filelist_t *flist);
+void mpdclient_filelist_clear_flags(mpdclient_filelist_t *flist);
+filelist_entry_t *mpdclient_filelist_find_song(mpdclient_filelist_t *flist,
+                                              mpd_Song *song);
+
+/*** mpdclient browse callbacks ********************************************/
+
+#define BROWSE_DB_UPDATED          0x01
+#define BROWSE_PLAYLIST_SAVED      0x02
+#define BROWSE_PLAYLIST_DELETED    0x03
+
+
+/* install a playlist callback function */
+void mpdclient_install_browse_callback(mpdclient_t *c, mpdc_list_cb_t cb);
+
+/* remove a playlist callback function */
+void mpdclient_remove_browse_callback(mpdclient_t *c, mpdc_list_cb_t cb);
+
+
+/* issue a playlist callback */
+void mpdclient_browse_callback(mpdclient_t *c, int event, gpointer data);
+
+
+#endif
index 93e48d541235219e97e75dc4fcd98cebe6b0fe8d..6bbb745fbbcee19bb081d67a8c3a6dca464b3b20 100644 (file)
@@ -6,9 +6,9 @@
 #endif
 
 #ifdef DEBUG
-#define D(x) x
+#define D(x, args...) fprintf(stderr, x,  ##args)
 #else
-#define D(x)
+#define D(x,...)
 #endif
 
 /* i18n */
 /* time in milliseconds before trying to reconnect (int) */
 #define MPD_RECONNECT_TIME  1000
 
+/* song format - list window */
+#define LIST_FORMAT "%name%|[%artist% - ]%title%|%file%"
+
+/* song format - status window */
+#define STATUS_FORMAT "[%artist% - ]%title%|%basename%"
 
 #endif /* NCMPC_H */
index d50e5925feff28e4b916595cd0549a14b7eb322e..76d04fa2241cbc48fdff03a543475fddf555ae74 100644 (file)
 #include "config.h"
 #include "ncmpc.h"
 #include "support.h"
-#include "libmpdclient.h"
-#include "mpc.h"
+#include "mpdclient.h"
 #include "command.h"
 #include "options.h"
 #include "colors.h"
+#include "strfsong.h"
 #include "wreadln.h"
 #include "screen.h"
-#include "screen_play.h"
-#include "screen_file.h"
-#include "screen_help.h"
-#include "screen_search.h"
 #include "screen_utils.h"
 
 #define ENABLE_STATUS_LINE_CLOCK
 #define ENABLE_SCROLLING
 
-#define DEFAULT_CROSSFADE_TIME 10
+#define CROSSFADE_TIME 10
 
 #define STATUS_MESSAGE_TIMEOUT 3
 #define STATUS_LINE_MAX_SIZE   512
 
+/* screens */
+extern screen_functions_t *get_screen_playlist(void);
+extern screen_functions_t *get_screen_browse(void);
+extern screen_functions_t *get_screen_help(void);
+
 #ifdef ENABLE_KEYDEF_SCREEN
 extern screen_functions_t *get_screen_keydef(void);
 #endif
@@ -58,13 +59,15 @@ extern screen_functions_t *get_screen_keydef(void);
 extern screen_functions_t *get_screen_clock(void);
 #endif
 
-
 static gboolean welcome = TRUE;
 static screen_t *screen = NULL;
 static screen_functions_t *mode_fn = NULL;
+static int seek_id = -1;
+static int seek_target_time = 0;
+
 
 static void
-switch_screen_mode(screen_mode_t new_mode, mpd_client_t *c)
+switch_screen_mode(screen_mode_t new_mode, mpdclient_t *c)
 {
   if( new_mode == screen->mode )
     return;
@@ -80,7 +83,7 @@ switch_screen_mode(screen_mode_t new_mode, mpd_client_t *c)
       mode_fn = get_screen_playlist();
       break;
     case SCREEN_FILE_WINDOW:
-      mode_fn = get_screen_file();
+      mode_fn = get_screen_browse();
       break;
     case SCREEN_HELP_WINDOW:
       mode_fn = get_screen_help();
@@ -110,7 +113,7 @@ switch_screen_mode(screen_mode_t new_mode, mpd_client_t *c)
 }
 
 static void
-paint_top_window(char *header, mpd_client_t *c, int clear)
+paint_top_window(char *header, mpdclient_t *c, int clear)
 {
   char flags[4];
   static int prev_volume = -1;
@@ -189,7 +192,7 @@ paint_top_window(char *header, mpd_client_t *c, int clear)
 }
 
 static void
-paint_progress_window(mpd_client_t *c)
+paint_progress_window(mpdclient_t *c)
 {
   double p;
   int width;
@@ -203,8 +206,8 @@ paint_progress_window(mpd_client_t *c)
       return;
     }
 
-  if( c->seek_song_id == c->song_id )
-    elapsedTime = c->seek_target_time;
+  if( c->song && seek_id == c->song->id )
+    elapsedTime = seek_target_time;
 
   p = ((double) elapsedTime) / ((double) c->status->totalTime);
   
@@ -219,12 +222,13 @@ paint_progress_window(mpd_client_t *c)
 }
 
 static void 
-paint_status_window(mpd_client_t *c)
+paint_status_window(mpdclient_t *c)
 {
   WINDOW *w = screen->status_window.w;
   mpd_Status *status = c->status;
   mpd_Song *song   = c->song;
   int elapsedTime = c->status->elapsedTime;
+  char *str = NULL;
   int x = 0;
 
   if( time(NULL) - screen->status_timestamp <= STATUS_MESSAGE_TIMEOUT )
@@ -238,16 +242,21 @@ paint_status_window(mpd_client_t *c)
   switch(status->state)
     {
     case MPD_STATUS_STATE_PLAY:
-      waddstr(w, _("Playing:"));
+      str = _("Playing:");
       break;
     case MPD_STATUS_STATE_PAUSE:
-      waddstr(w, _("[Paused]"));
+      str = _("[Paused]");
       break;
     case MPD_STATUS_STATE_STOP:
     default:
       break;
     }
-  x += 9;
+
+  if( str )
+    {
+      waddstr(w, str);
+      x += strlen(str)+1;
+    }
 
   /* create time string */
   memset(screen->buf, 0, screen->buf_size);
@@ -255,8 +264,8 @@ paint_status_window(mpd_client_t *c)
     {
       if( status->totalTime > 0 )
        {
-         if( c->seek_song_id == c->song_id )
-           elapsedTime = c->seek_target_time;
+         if( seek_id == c->song->id )
+           elapsedTime = seek_target_time;
          snprintf(screen->buf, screen->buf_size, 
                   " [%i:%02i/%i:%02i]",
                   elapsedTime/60, elapsedTime%60,
@@ -273,18 +282,21 @@ paint_status_window(mpd_client_t *c)
       time_t timep;
 
       time(&timep);
-      /* Note: setlocale(LC_TIME,"") should be used first */
-      //strftime(screen->buf, screen->buf_size, "%x  - %X ",localtime(&timep));
       strftime(screen->buf, screen->buf_size, "%X ",localtime(&timep));
     }
 #endif
 
   /* display song */
-  if( (IS_PLAYING(status->state) || IS_PAUSED(status->state)) &&  song )
+  if( (IS_PLAYING(status->state) || IS_PAUSED(status->state)) )
     {
-      char *songname = mpc_get_song_name(song);
+      char songname[STATUS_LINE_MAX_SIZE];
       int width = COLS-x-strlen(screen->buf);
 
+      if( song )
+       strfsong(songname, STATUS_LINE_MAX_SIZE, STATUS_FORMAT, song);
+      else
+       songname[0] = '\0';
+
       colors_use(w, COLOR_STATUS);
 #ifdef ENABLE_SCROLLING
       if( strlen(songname) > width )
@@ -361,12 +373,7 @@ screen_resize(void)
 {
   GList *list;
 
-#ifdef DEBUG
-  fprintf(stderr, "Resize rows %d->%d, cols %d->%d\n",
-         screen->rows, LINES,
-         screen->cols, COLS);
-#endif
-      
+  D("Resize rows %d->%d, cols %d->%d\n",screen->rows,LINES,screen->cols,COLS);
   if( COLS<SCREEN_MIN_COLS || LINES<SCREEN_MIN_ROWS )
     {
       screen_exit();
@@ -447,7 +454,7 @@ screen_status_printf(char *format, ...)
 }
 
 int
-screen_init(void)
+screen_init(mpdclient_t *c)
 {
   GList *list;
 
@@ -544,7 +551,7 @@ screen_init(void)
   screen->screen_list = g_list_append(screen->screen_list, 
                                      (gpointer) get_screen_playlist());
   screen->screen_list = g_list_append(screen->screen_list, 
-                                     (gpointer) get_screen_file());
+                                     (gpointer) get_screen_browse());
   screen->screen_list = g_list_append(screen->screen_list, 
                                      (gpointer) get_screen_help());
 #ifdef ENABLE_KEYDEF_SCREEN
@@ -570,6 +577,8 @@ screen_init(void)
     }
 
   mode_fn = get_screen_playlist();
+  if( mode_fn && mode_fn->open )
+    mode_fn->open(screen, c);
 
   /* initialize wreadln */
   wrln_resize_callback = screen_resize;
@@ -579,7 +588,7 @@ screen_init(void)
 }
 
 void 
-screen_paint(mpd_client_t *c)
+screen_paint(mpdclient_t *c)
 {
   /* paint the title/header window */
   if( mode_fn && mode_fn->get_title )
@@ -602,7 +611,7 @@ screen_paint(mpd_client_t *c)
 }
 
 void 
-screen_update(mpd_client_t *c)
+screen_update(mpdclient_t *c)
 {
   static int repeat = -1;
   static int random = -1;
@@ -633,7 +642,10 @@ screen_update(mpd_client_t *c)
   if( crossfade != c->status->crossfade )
     screen_status_printf(_("Crossfade %d seconds"), c->status->crossfade);
   if( dbupdate && dbupdate != c->status->updatingDb )
-    screen_status_printf(_("Database updated!"));
+    {
+      screen_status_printf(_("Database updated!"));
+      mpdclient_browse_callback(c, BROWSE_DB_UPDATED, NULL);
+    }
 
   repeat = c->status->repeat;
   random = c->status->random;
@@ -677,26 +689,22 @@ screen_update(mpd_client_t *c)
 }
 
 void
-screen_idle(mpd_client_t *c)
+screen_idle(mpdclient_t *c)
 {
-  if( c->seek_song_id ==  c->song_id &&
+  if( c->song && seek_id ==  c->song->id &&
       (screen->last_cmd == CMD_SEEK_FORWARD || 
        screen->last_cmd == CMD_SEEK_BACKWARD) )
     {
-      mpd_sendSeekCommand(c->connection, 
-                         c->seek_song_id, 
-                         c->seek_target_time);
-      mpd_finishCommand(c->connection);
+      mpdclient_cmd_seek(c, seek_id, seek_target_time);
     }
 
   screen->last_cmd = CMD_NONE;
-  c->seek_song_id = -1;
+  seek_id = -1;
 }
 
 void 
-screen_cmd(mpd_client_t *c, command_t cmd)
+screen_cmd(mpdclient_t *c, command_t cmd)
 {
-  int n = 0;
   screen_mode_t new_mode = screen->mode;
 
   screen->input_timestamp = time(NULL);
@@ -709,118 +717,82 @@ screen_cmd(mpd_client_t *c, command_t cmd)
   switch(cmd)
     {
     case CMD_PLAY:
-      if( screen->mode == SCREEN_PLAY_WINDOW )
-       n = play_get_selected();
-      else
-       n = -1;
-      mpd_sendPlayCommand(c->connection, n);
-      mpd_finishCommand(c->connection);
+      mpdclient_cmd_play(c, MPD_PLAY_AT_BEGINNING);
       break;
     case CMD_PAUSE:
-      mpd_sendPauseCommand(c->connection);
-      mpd_finishCommand(c->connection);
+      mpdclient_cmd_pause(c, !IS_PAUSED(c->status->state));
       break;
     case CMD_STOP:
-      mpd_sendStopCommand(c->connection);
-      mpd_finishCommand(c->connection);
+      mpdclient_cmd_stop(c);
       break;
     case CMD_SEEK_FORWARD:
       if( !IS_STOPPED(c->status->state) )
        {
-         if( c->seek_song_id != c->song_id )
+         if( c->song && seek_id != c->song->id )
            {
-             c->seek_song_id = c->song_id;
-             c->seek_target_time = c->status->elapsedTime;
+             seek_id = c->song->id;
+             seek_target_time = c->status->elapsedTime;
            }
-         c->seek_target_time++;
-         if( c->seek_target_time < c->status->totalTime )
+         seek_target_time++;
+         if( seek_target_time < c->status->totalTime )
            break;
-         c->seek_target_time=0;
+         seek_target_time=0;
        }
       /* fall through... */
     case CMD_TRACK_NEXT:
       if( !IS_STOPPED(c->status->state) )
-       {
-         mpd_sendNextCommand(c->connection);
-         mpd_finishCommand(c->connection);
-       }
+       mpdclient_cmd_next(c);
       break;
     case CMD_SEEK_BACKWARD:
       if( !IS_STOPPED(c->status->state) )
        {
-         if( c->seek_song_id != c->song_id )
+         if( seek_id != c->song->id )
            {
-             c->seek_song_id = c->song_id;
-             c->seek_target_time = c->status->elapsedTime;
+             seek_id = c->song->id;
+             seek_target_time = c->status->elapsedTime;
            }
-         c->seek_target_time--;
-         if( c->seek_target_time < 0 )
-           c->seek_target_time=0;
+         seek_target_time--;
+         if( seek_target_time < 0 )
+           seek_target_time=0;
        }
       break;
     case CMD_TRACK_PREVIOUS:
       if( !IS_STOPPED(c->status->state) )
-       {
-         mpd_sendPrevCommand(c->connection);
-         mpd_finishCommand(c->connection);
-       }
+       mpdclient_cmd_prev(c);
       break;   
     case CMD_SHUFFLE:
-      mpd_sendShuffleCommand(c->connection);
-      mpd_finishCommand(c->connection);
-      screen_status_message(_("Shuffled playlist!"));
+      if( mpdclient_cmd_shuffle(c) == 0 )
+       screen_status_message(_("Shuffled playlist!"));
       break;
     case CMD_CLEAR:
-      mpd_sendClearCommand(c->connection);
-      mpd_finishCommand(c->connection);
-      file_clear_highlights(c);
-      screen_status_message(_("Cleared playlist!"));
+      if( mpdclient_cmd_clear(c) == 0 )
+       screen_status_message(_("Cleared playlist!"));
       break;
     case CMD_REPEAT:
-      n = !c->status->repeat;
-      mpd_sendRepeatCommand(c->connection, n);
-      mpd_finishCommand(c->connection);
+      mpdclient_cmd_repeat(c, !c->status->repeat);
       break;
     case CMD_RANDOM:
-      n = !c->status->random;
-      mpd_sendRandomCommand(c->connection, n);
-      mpd_finishCommand(c->connection);
+      mpdclient_cmd_random(c, !c->status->random);
       break;
     case CMD_CROSSFADE:
-      if( c->status->crossfade )
-       n = 0;
-      else
-       n = DEFAULT_CROSSFADE_TIME;
-      mpd_sendCrossfadeCommand(c->connection, n);
-      mpd_finishCommand(c->connection);
+      mpdclient_cmd_crossfade(c, c->status->crossfade ? 0 : CROSSFADE_TIME);
       break;
     case CMD_DB_UPDATE:
       if( !c->status->updatingDb )
        {
-         mpd_sendUpdateCommand(c->connection);
-         n = mpd_getUpdateId(c->connection);
-         mpd_finishCommand(c->connection);
-         if( !mpc_error(c) )
-           screen_status_printf(_("Database update started [%d]"), n);
+         if( mpdclient_cmd_db_update(c)==0 )
+           screen_status_printf(_("Database update started!"));
        }
       else
        screen_status_printf(_("Database update running..."));
       break;
     case CMD_VOLUME_UP:
       if( c->status->volume!=MPD_STATUS_NO_VOLUME && c->status->volume<100 )
-       {
-         c->status->volume=c->status->volume+1;
-         mpd_sendSetvolCommand(c->connection, c->status->volume  );
-         mpd_finishCommand(c->connection);
-       }
+       mpdclient_cmd_volume(c, ++c->status->volume);
       break;
     case CMD_VOLUME_DOWN:
       if( c->status->volume!=MPD_STATUS_NO_VOLUME && c->status->volume>0 )
-       {
-         c->status->volume=c->status->volume-1;
-         mpd_sendSetvolCommand(c->connection, c->status->volume  );
-         mpd_finishCommand(c->connection);
-       }
+       mpdclient_cmd_volume(c, --c->status->volume);
       break;
     case CMD_TOGGLE_FIND_WRAP:
       options.find_wrap = !options.find_wrap;
index fe843daa6d2c14f524b69be1688374b237fda28b..262c6bd7edf4457d70b0d7d0546af7840fb269cb 100644 (file)
@@ -63,12 +63,12 @@ typedef struct
 
 typedef void (*screen_init_fn_t)   (WINDOW *w, int cols, int rows);
 typedef void (*screen_exit_fn_t)   (void);
-typedef void (*screen_open_fn_t)   (screen_t *screen, mpd_client_t *c);
+typedef void (*screen_open_fn_t)   (screen_t *screen, mpdclient_t *c);
 typedef void (*screen_close_fn_t)  (void);
 typedef void (*screen_resize_fn_t)   (int cols, int rows);
-typedef void (*screen_paint_fn_t)  (screen_t *screen, mpd_client_t *c);
-typedef void (*screen_update_fn_t) (screen_t *screen, mpd_client_t *c);
-typedef int (*screen_cmd_fn_t) (screen_t *scr, mpd_client_t *c, command_t cmd);
+typedef void (*screen_paint_fn_t)  (screen_t *screen, mpdclient_t *c);
+typedef void (*screen_update_fn_t) (screen_t *screen, mpdclient_t *c);
+typedef int (*screen_cmd_fn_t) (screen_t *scr, mpdclient_t *c, command_t cmd);
 typedef char * (*screen_title_fn_t) (char *s, size_t size);
 typedef list_window_t * (*screen_get_lw_fn_t) (void);
 
@@ -88,15 +88,15 @@ typedef struct
 } screen_functions_t;
 
 
-int screen_init(void);
+int screen_init(mpdclient_t *c);
 int screen_exit(void);
 void screen_resize(void);
 void screen_status_message(char *msg);
 void screen_status_printf(char *format, ...);
 char *screen_error(void);
-void screen_paint(mpd_client_t *c);
-void screen_update(mpd_client_t *c);
-void screen_idle(mpd_client_t *c);
-void screen_cmd(mpd_client_t *c, command_t cmd);
+void screen_paint(mpdclient_t *c);
+void screen_update(mpdclient_t *c);
+void screen_idle(mpdclient_t *c);
+void screen_cmd(mpdclient_t *c, command_t cmd);
 
 #endif
index 3fe2ec1c910dfa9687f8e1e6fde951eb43186ca5..d3d4925592a7aab55559842166736ad78b77e568 100644 (file)
@@ -1,4 +1,6 @@
 /*
+ * $Id$
+ *
  * This file is based on the 'Grand digital clock' (gdc.c) shipped with 
  * ncurses. 
  */
@@ -13,9 +15,8 @@
 
 #ifdef  ENABLE_CLOCK_SCREEN
 #include "ncmpc.h"
-#include "libmpdclient.h"
+#include "mpdclient.h"
 #include "options.h"
-#include "mpc.h"
 #include "command.h"
 #include "screen.h"
 #include "screen_utils.h"
@@ -133,7 +134,7 @@ clock_exit(void)
 }
 
 static void 
-clock_open(screen_t *screen, mpd_client_t *c)
+clock_open(screen_t *screen, mpdclient_t *c)
 {
   int j;
 
@@ -154,7 +155,7 @@ clock_title(char *str, size_t size)
 }
 
 static void 
-clock_update(screen_t *screen, mpd_client_t *c)
+clock_update(screen_t *screen, mpdclient_t *c)
 {  
   time_t now;
   struct tm *tm;
@@ -228,7 +229,7 @@ clock_update(screen_t *screen, mpd_client_t *c)
 }
 
 static void 
-clock_paint(screen_t *screen, mpd_client_t *c)
+clock_paint(screen_t *screen, mpdclient_t *c)
 {
   /* this seems to be a better way to clear the window than wclear() ?! */
   wmove(win.w, 0, 0);
@@ -239,7 +240,7 @@ clock_paint(screen_t *screen, mpd_client_t *c)
 
 
 static int 
-clock_cmd(screen_t *screen, mpd_client_t *c, command_t cmd)
+clock_cmd(screen_t *screen, mpdclient_t *c, command_t cmd)
 {
   return 0;
 }
index 8b7577fdfde71c5a4cefe41b0a1dc4b0342edf10..f4a8c3dc0212043e3b80cd443c076dc618bb035b 100644 (file)
 #include "config.h"
 #include "ncmpc.h"
 #include "support.h"
-#include "libmpdclient.h"
-#include "mpc.h"
+#include "mpdclient.h"
+#include "strfsong.h"
 #include "command.h"
 #include "screen.h"
 #include "screen_utils.h"
-#include "screen_play.h"
-#include "screen_file.h"
 
-#define BUFSIZE 1024
-#define TITLESIZE 256
 
 #define USE_OLD_LAYOUT
 
-static list_window_t *lw;
-static mpd_client_t *mpc = NULL;
+#define BUFSIZE 1024
+
+#define HIGHLIGHT  (0x01)
+
+
+static list_window_t *lw = NULL;
+static GList *lw_state_list = NULL;
+static mpdclient_filelist_t *filelist = NULL;
+
+
+
+/* clear the highlight flag for all items in the filelist */
+static void
+clear_highlights(mpdclient_filelist_t *filelist)
+{
+  GList *list = g_list_first(filelist->list);
+  
+  while( list )
+    {
+      filelist_entry_t *entry = list->data;
+
+      entry->flags &= ~HIGHLIGHT;
+      list = list->next;
+    }
+}
+
+/* change the highlight flag for a song */
+static void
+set_highlight(mpdclient_filelist_t *filelist, mpd_Song *song, int highlight)
+{
+  GList *list = g_list_first(filelist->list);
+
+  if( !song )
+    return;
+
+  while( list )
+    {
+      filelist_entry_t *entry = list->data;
+      mpd_InfoEntity *entity  = entry->entity;
+
+      if( entity && entity->type==MPD_INFO_ENTITY_TYPE_SONG )
+       {
+         mpd_Song *song2 = entity->info.song;
+
+         if( strcmp(song->file, song2->file) == 0 )
+           {
+             if(highlight)
+               entry->flags |= HIGHLIGHT;
+             else
+               entry->flags &= ~HIGHLIGHT;
+           }
+       }
+      list = list->next;
+    }
+}
+
+/* sync highlight flags with playlist */
+static void
+sync_highlights(mpdclient_t *c, mpdclient_filelist_t *filelist)
+{
+  GList *list = g_list_first(filelist->list);
+
+  while(list)
+    {
+      filelist_entry_t *entry = list->data;
+      mpd_InfoEntity *entity = entry->entity;
+
+      if( entity && entity->type==MPD_INFO_ENTITY_TYPE_SONG )
+       {
+         mpd_Song *song = entity->info.song;
+         
+         if( playlist_get_index_from_file(c, song->file) >= 0 )
+           entry->flags |= HIGHLIGHT;
+         else
+           entry->flags &= ~HIGHLIGHT;
+       }
+      list=list->next;
+    }
+}
+
+/* the db have changed -> update the filelist */
+static void 
+file_changed_callback(mpdclient_t *c, int event, gpointer data)
+{
+  D("screen_file.c> filelist_callback() [%d]\n", event);
+  filelist = mpdclient_filelist_update(c, filelist);
+  sync_highlights(c, filelist);
+  list_window_check_selected(lw, filelist->length);
+}
+
+/* the playlist have been updated -> fix highlights */
+static void 
+playlist_changed_callback(mpdclient_t *c, int event, gpointer data)
+{
+  D("screen_file.c> playlist_callback() [%d]\n", event);
+  switch(event)
+    {
+    case PLAYLIST_EVENT_CLEAR:
+      clear_highlights(filelist);
+      break;
+    case PLAYLIST_EVENT_ADD:
+      set_highlight(filelist, (mpd_Song *) data, 1); 
+      break;
+    case PLAYLIST_EVENT_DELETE:
+      set_highlight(filelist, (mpd_Song *) data, 0); 
+      break;
+    case PLAYLIST_EVENT_MOVE:
+      break;
+    default:
+      sync_highlights(c, filelist);
+      break;
+    }
+}
+
+/* store current state when entering a subdirectory */
+static void
+push_lw_state(void)
+{
+  list_window_t *tmp = g_malloc(sizeof(list_window_t));
+
+  memcpy(tmp, lw, sizeof(list_window_t));
+  lw_state_list = g_list_prepend(lw_state_list, (gpointer) tmp);
+}
+
+/* get previous state when leaving a directory */
+static void
+pop_lw_state(void)
+{
+  if( lw_state_list )
+    {
+      list_window_t *tmp = lw_state_list->data;
+
+      memcpy(lw, tmp, sizeof(list_window_t));
+      g_free(tmp);
+      lw_state_list->data = NULL;
+      lw_state_list = g_list_delete_link(lw_state_list, lw_state_list);
+    }
+}
 
+/* list_window callback */
 static char *
 list_callback(int index, int *highlight, void *data)
 {
   static char buf[BUFSIZE];
-  mpd_client_t *c = (mpd_client_t *) data;
+  //mpdclient_t *c = (mpdclient_t *) data;
   filelist_entry_t *entry;
   mpd_InfoEntity *entity;
 
   *highlight = 0;
-  if( (entry=(filelist_entry_t *) g_list_nth_data(c->filelist, index))==NULL )
+  if( (entry=(filelist_entry_t *)g_list_nth_data(filelist->list,index))==NULL )
     return NULL;
 
   entity = entry->entity;
-  *highlight = entry->selected;
+  *highlight = (entry->flags & HIGHLIGHT);
 
   if( entity == NULL )
     {
-#ifdef USE_OLD_LAYOUT
       return "[..]";
-#else
-      return "d ..";
-#endif
     }
   if( entity->type==MPD_INFO_ENTITY_TYPE_DIRECTORY ) 
     {
       mpd_Directory *dir = entity->info.directory;
       char *dirname = utf8_to_locale(basename(dir->path));
 
-#ifdef USE_OLD_LAYOUT
       snprintf(buf, BUFSIZE, "[%s]", dirname);
-#else
-      snprintf(buf, BUFSIZE, "d %s", dirname);
-#endif
       g_free(dirname);
       return buf;
     }
@@ -83,13 +208,8 @@ list_callback(int index, int *highlight, void *data)
     {
       mpd_Song *song = entity->info.song;
 
-#ifdef USE_OLD_LAYOUT      
-      return mpc_get_song_name(song);
-#else
-      snprintf(buf, BUFSIZE, "m %s", mpc_get_song_name(song));
+      strfsong(buf, BUFSIZE, LIST_FORMAT, song);
       return buf;
-#endif
-
     }
   else if( entity->type==MPD_INFO_ENTITY_TYPE_PLAYLISTFILE )
     {
@@ -98,8 +218,8 @@ list_callback(int index, int *highlight, void *data)
 
 #ifdef USE_OLD_LAYOUT      
       snprintf(buf, BUFSIZE, "*%s*", filename);
-#else      
-      snprintf(buf, BUFSIZE, "p %s", filename);
+#else 
+      snprintf(buf, BUFSIZE, "<Playlist> %s", filename);
 #endif
       g_free(filename);
       return buf;
@@ -107,56 +227,62 @@ list_callback(int index, int *highlight, void *data)
   return "Error: Unknow entry!";
 }
 
+/* chdir */
 static int
-change_directory(screen_t *screen, mpd_client_t *c, filelist_entry_t *entry)
+change_directory(screen_t *screen, mpdclient_t *c, filelist_entry_t *entry)
 {
   mpd_InfoEntity *entity = entry->entity;
+  gchar *path = NULL;
 
   if( entity==NULL )
     {
-      char *parent = g_path_get_dirname(c->cwd);
-
-      if( strcmp(parent,".") == 0 )
+      /* return to parent */
+      char *parent = g_path_get_dirname(filelist->path);
+      if( strcmp(parent, ".") == 0 )
        {
          parent[0] = '\0';
        }
-      if( c->cwd )
-       g_free(c->cwd);
-      c->cwd = parent;
+      path = g_strdup(parent);
+      list_window_reset(lw);
+      /* restore previous list window state */
+      pop_lw_state(); 
     }
   else
     if( entity->type==MPD_INFO_ENTITY_TYPE_DIRECTORY)
       {
+       /* enter sub */
        mpd_Directory *dir = entity->info.directory;
-       if( c->cwd )
-         g_free(c->cwd);
-       c->cwd = g_strdup(dir->path);      
+       path = utf8_to_locale(dir->path);      
+       /* save current list window state */
+       push_lw_state(); 
+       list_window_reset(lw);
       }
     else
       return -1;
-  
-  mpc_update_filelist(c);
-  list_window_reset(lw);
+
+  filelist = mpdclient_filelist_free(filelist);
+  filelist = mpdclient_filelist_get(c, path);
+  sync_highlights(c, filelist);
+  list_window_check_selected(lw, filelist->length);
+  g_free(path);
   return 0;
 }
 
 static int
-load_playlist(screen_t *screen, mpd_client_t *c, filelist_entry_t *entry)
+load_playlist(screen_t *screen, mpdclient_t *c, filelist_entry_t *entry)
 {
   mpd_InfoEntity *entity = entry->entity;
   mpd_PlaylistFile *plf = entity->info.playlistFile;
-  char *filename = utf8_to_locale(basename(plf->path));
-
-  mpd_sendLoadCommand(c->connection, plf->path);
-  mpd_finishCommand(c->connection);
+  char *filename = utf8_to_locale(plf->path);
 
-  screen_status_printf(_("Loading playlist %s..."), filename);
+  if( mpdclient_cmd_load_playlist(c, plf->path) == 0 )
+    screen_status_printf(_("Loading playlist %s..."), basename(filename));
   g_free(filename);
   return 0;
 }
 
 static int 
-handle_delete(screen_t *screen, mpd_client_t *c)
+handle_delete(screen_t *screen, mpdclient_t *c)
 {
   filelist_entry_t *entry;
   mpd_InfoEntity *entity;
@@ -164,7 +290,7 @@ handle_delete(screen_t *screen, mpd_client_t *c)
   char *str, buf[BUFSIZE];
   int key;
 
-  entry = ( filelist_entry_t *) g_list_nth_data(c->filelist, lw->selected);
+  entry=( filelist_entry_t *) g_list_nth_data(filelist->list,lw->selected);
   if( entry==NULL || entry->entity==NULL )
     return -1;
 
@@ -190,30 +316,23 @@ handle_delete(screen_t *screen, mpd_client_t *c)
       return 0;
     }
 
-  mpd_sendRmCommand(c->connection, plf->path);
-  mpd_finishCommand(c->connection);
-  if( mpc_error(c))
+  if( mpdclient_cmd_delete_playlist(c, plf->path) )
     {
-      str = utf8_to_locale(mpc_error_str(c));
-      screen_status_printf("Error: %s", str);
-      g_free(str);
       beep();
       return -1;
     }
   screen_status_printf(_("Playlist deleted!"));
-  mpc_update_filelist(c);
-  list_window_check_selected(lw, c->filelist_length);
   return 0;
 }
 
 
 static int
-handle_play_cmd(screen_t *screen, mpd_client_t *c)
+handle_enter(screen_t *screen, mpdclient_t *c)
 {
   filelist_entry_t *entry;
   mpd_InfoEntity *entity;
   
-  entry = ( filelist_entry_t *) g_list_nth_data(c->filelist, lw->selected);
+  entry = ( filelist_entry_t *) g_list_nth_data(filelist->list, lw->selected);
   if( entry==NULL )
     return -1;
 
@@ -225,8 +344,12 @@ handle_play_cmd(screen_t *screen, mpd_client_t *c)
   return -1;
 }
 
+
+/* NOTE - The add_directory functions should move to mpdclient.c */
+extern gint mpdclient_finish_command(mpdclient_t *c);
+
 static int
-add_directory(mpd_client_t *c, char *dir)
+add_directory(mpdclient_t *c, char *dir)
 {
   mpd_InfoEntity *entity;
   GList *subdir_list = NULL;
@@ -257,7 +380,8 @@ add_directory(mpd_client_t *c, char *dir)
        mpd_freeInfoEntity(entity);
     }
   mpd_sendCommandListEnd(c->connection);
-  mpd_finishCommand(c->connection);
+  mpdclient_finish_command(c);
+  c->need_update = TRUE;
   
   list = g_list_first(subdir_list);
   while( list!=NULL )
@@ -276,14 +400,17 @@ add_directory(mpd_client_t *c, char *dir)
 }
 
 static int
-handle_select(screen_t *screen, mpd_client_t *c)
+handle_select(screen_t *screen, mpdclient_t *c)
 {
   filelist_entry_t *entry;
 
-  entry = ( filelist_entry_t *) g_list_nth_data(c->filelist, lw->selected);
+  entry=( filelist_entry_t *) g_list_nth_data(filelist->list, lw->selected);
   if( entry==NULL || entry->entity==NULL)
     return -1;
 
+  if( entry->entity->type==MPD_INFO_ENTITY_TYPE_PLAYLISTFILE )
+    return load_playlist(screen, c, entry);
+
   if( entry->entity->type==MPD_INFO_ENTITY_TYPE_DIRECTORY )
     {
       mpd_Directory *dir = entry->entity->info.directory;
@@ -294,18 +421,24 @@ handle_select(screen_t *screen, mpd_client_t *c)
   if( entry->entity->type!=MPD_INFO_ENTITY_TYPE_SONG )
     return -1; 
 
-  entry->selected = !entry->selected;
+  if( entry->flags & HIGHLIGHT )
+    entry->flags &= ~HIGHLIGHT;
+  else
+    entry->flags |= HIGHLIGHT;
 
-  if( entry->selected )
+  if( entry->flags & HIGHLIGHT )
     {
       if( entry->entity->type==MPD_INFO_ENTITY_TYPE_SONG )
        {
          mpd_Song *song = entry->entity->info.song;
 
-         playlist_add_song(c, song);
-
-         screen_status_printf(_("Adding \'%s\' to playlist\n"), 
-                              mpc_get_song_name(song));
+         if( mpdclient_cmd_add(c, song) == 0 )
+           {
+             char buf[BUFSIZE];
+             
+             strfsong(buf, BUFSIZE, LIST_FORMAT, song);
+             screen_status_printf(_("Adding \'%s\' to playlist\n"), buf);
+           }
        }
     }
   else
@@ -317,10 +450,10 @@ handle_select(screen_t *screen, mpd_client_t *c)
 
          if( song )
            {
-             int index = mpc_playlist_get_song_index(c, song->file);
+             int index = playlist_get_index_from_file(c, song->file);
              
-             while( (index=mpc_playlist_get_song_index(c, song->file))>=0 )
-               playlist_delete_song(c, index);
+             while( (index=playlist_get_index_from_file(c, song->file))>=0 )
+               mpdclient_cmd_delete(c, index);
            }
        }
     }
@@ -328,53 +461,64 @@ handle_select(screen_t *screen, mpd_client_t *c)
 }
 
 static void
-file_init(WINDOW *w, int cols, int rows)
+browse_init(WINDOW *w, int cols, int rows)
 {
   lw = list_window_init(w, cols, rows);
 }
 
 static void
-file_resize(int cols, int rows)
+browse_resize(int cols, int rows)
 {
   lw->cols = cols;
   lw->rows = rows;
 }
 
 static void
-file_exit(void)
+browse_exit(void)
 {
+  if( lw_state_list )
+    {
+      GList *list = lw_state_list;
+      while( list )
+       {
+         g_free(list->data);
+         list->data = NULL;
+         list = list->next;
+       }
+      g_list_free(lw_state_list);
+      lw_state_list = NULL;
+
+    }
+  if( filelist )
+    filelist = mpdclient_filelist_free(filelist);
   list_window_free(lw);
 }
 
 static void 
-file_open(screen_t *screen, mpd_client_t *c)
+browse_open(screen_t *screen, mpdclient_t *c)
 {
-  if( c->filelist == NULL )
+  if( filelist == NULL )
     {
-      mpc_update_filelist(c);
+      filelist = mpdclient_filelist_get(c, "");
+      mpdclient_install_playlist_callback(c, playlist_changed_callback);
+      mpdclient_install_browse_callback(c, file_changed_callback);
     }
-  mpc = c;
 }
 
 static void
-file_close(void)
+browse_close(void)
 {
 }
 
 static char *
-file_title(char *str, size_t size)
+browse_title(char *str, size_t size)
 {
-  char *tmp;
-
-  tmp = utf8_to_locale(basename(mpc->cwd));
-  snprintf(str, size, _("Browse: %s"), tmp);
-  g_free(tmp);
-
+  snprintf(str, size, _("Browse: %s"), basename(filelist->path));
   return str;
 }
 
 static void 
-file_paint(screen_t *screen, mpd_client_t *c)
+browse_paint(screen_t *screen, mpdclient_t *c)
 {
   lw->clear = 1;
   
@@ -383,12 +527,12 @@ file_paint(screen_t *screen, mpd_client_t *c)
 }
 
 static void 
-file_update(screen_t *screen, mpd_client_t *c)
+browse_update(screen_t *screen, mpdclient_t *c)
 {
-  if( c->filelist_updated )
+  if( filelist->updated )
     {
-      file_paint(screen, c);
-      c->filelist_updated = 0;
+      browse_paint(screen, c);
+      filelist->updated = FALSE;
       return;
     }
   list_window_paint(lw, list_callback, (void *) c);
@@ -397,12 +541,12 @@ file_update(screen_t *screen, mpd_client_t *c)
 
 
 static int 
-file_cmd(screen_t *screen, mpd_client_t *c, command_t cmd)
+browse_cmd(screen_t *screen, mpdclient_t *c, command_t cmd)
 {
   switch(cmd)
     {
     case CMD_PLAY:
-      handle_play_cmd(screen, c);
+      handle_enter(screen, c);
       return 1;
     case CMD_SELECT:
       if( handle_select(screen, c) == 0 )
@@ -415,8 +559,8 @@ file_cmd(screen_t *screen, mpd_client_t *c, command_t cmd)
       handle_delete(screen, c);
       break;
     case CMD_SCREEN_UPDATE:
-      mpc_update_filelist(c);
-      list_window_check_selected(lw, c->filelist_length);
+      filelist = mpdclient_filelist_update(c, filelist);
+      list_window_check_selected(lw, filelist->length);
       screen_status_printf(_("Screen updated!"));
       return 1;
     case CMD_LIST_FIND:
@@ -424,12 +568,12 @@ file_cmd(screen_t *screen, mpd_client_t *c, command_t cmd)
     case CMD_LIST_FIND_NEXT:
     case CMD_LIST_RFIND_NEXT:
       return screen_find(screen, c, 
-                        lw, c->filelist_length,
+                        lw, filelist->length,
                         cmd, list_callback);
     default:
       break;
     }
-  return list_window_cmd(lw, c->filelist_length, cmd);
+  return list_window_cmd(lw, filelist->length, cmd);
 }
 
 
@@ -440,62 +584,24 @@ get_filelist_window()
 }
 
 
-void
-file_clear_highlights(mpd_client_t *c)
-{
-  GList *list = g_list_first(c->filelist);
-  
-  while( list )
-    {
-      filelist_entry_t *entry = list->data;
-
-      entry->selected = 0;
-      list = list->next;
-    }
-}
-
-void
-file_set_highlight(mpd_client_t *c, mpd_Song *song, int highlight)
-{
-  GList *list = g_list_first(c->filelist);
-
-  if( !song )
-    return;
-
-  while( list )
-    {
-      filelist_entry_t *entry = list->data;
-      mpd_InfoEntity *entity  = entry->entity;
 
-      if( entity && entity->type==MPD_INFO_ENTITY_TYPE_SONG )
-       {
-         mpd_Song *song2 = entity->info.song;
-
-         if( strcmp(song->file, song2->file) == 0 )
-           {
-             entry->selected = highlight;
-           }
-       }
-      list = list->next;
-    }
-}
 
 screen_functions_t *
-get_screen_file(void)
+get_screen_browse(void)
 {
   static screen_functions_t functions;
 
   memset(&functions, 0, sizeof(screen_functions_t));
-  functions.init   = file_init;
-  functions.exit   = file_exit;
-  functions.open   = file_open;
-  functions.close  = file_close;
-  functions.resize = file_resize;
-  functions.paint  = file_paint;
-  functions.update = file_update;
-  functions.cmd    = file_cmd;
+  functions.init   = browse_init;
+  functions.exit   = browse_exit;
+  functions.open   = browse_open;
+  functions.close  = browse_close;
+  functions.resize = browse_resize;
+  functions.paint  = browse_paint;
+  functions.update = browse_update;
+  functions.cmd    = browse_cmd;
   functions.get_lw = get_filelist_window;
-  functions.get_title = file_title;
+  functions.get_title = browse_title;
 
   return &functions;
 }
diff --git a/src/screen_file.h b/src/screen_file.h
deleted file mode 100644 (file)
index a7199a6..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-
-void file_set_highlight(mpd_client_t *c, mpd_Song *song, int hightlight);
-void file_clear_highlights(mpd_client_t *c);
-
-list_window_t *get_filelist_window(void);
-
-screen_functions_t *get_screen_file(void);
index 8584bb7c9a107001b4d2276673fd625647b8b7b5..2f042499f158b5700c3d3882d1281cba64b8fb2f 100644 (file)
 
 #include "config.h"
 #include "ncmpc.h"
-#include "libmpdclient.h"
-#include "mpc.h"
+#include "mpdclient.h"
 #include "command.h"
 #include "screen.h"
 #include "screen_utils.h"
-#include "screen_help.h"
 
 
 typedef struct
@@ -212,7 +210,7 @@ help_title(char *str, size_t size)
 }
 
 static void 
-help_paint(screen_t *screen, mpd_client_t *c)
+help_paint(screen_t *screen, mpdclient_t *c)
 {
   lw->clear = 1;
   list_window_paint(lw, list_callback, NULL);
@@ -220,7 +218,7 @@ help_paint(screen_t *screen, mpd_client_t *c)
 }
 
 static void 
-help_update(screen_t *screen, mpd_client_t *c)
+help_update(screen_t *screen, mpdclient_t *c)
 {  
   if( lw->repaint )
     {
@@ -232,7 +230,7 @@ help_update(screen_t *screen, mpd_client_t *c)
 
 
 static int 
-help_cmd(screen_t *screen, mpd_client_t *c, command_t cmd)
+help_cmd(screen_t *screen, mpdclient_t *c, command_t cmd)
 {
   int retval;
 
diff --git a/src/screen_help.h b/src/screen_help.h
deleted file mode 100644 (file)
index ba2c57c..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-
-screen_functions_t *get_screen_help(void);
index 2dda43db9225fcfeee086e97fb35a97a5a8221f9..809561b80bea1709478bff0706bacdaf759c9504 100644 (file)
 
 #ifdef  ENABLE_KEYDEF_SCREEN
 #include "ncmpc.h"
-#include "libmpdclient.h"
+#include "mpdclient.h"
 #include "options.h"
 #include "conf.h"
-#include "mpc.h"
 #include "command.h"
 #include "screen.h"
 #include "screen_utils.h"
@@ -238,7 +237,7 @@ keydef_exit(void)
 }
 
 static void 
-keydef_open(screen_t *screen, mpd_client_t *c)
+keydef_open(screen_t *screen, mpdclient_t *c)
 {
   if( cmds == NULL )
     {
@@ -283,7 +282,7 @@ keydef_title(char *str, size_t size)
 }
 
 static void 
-keydef_paint(screen_t *screen, mpd_client_t *c)
+keydef_paint(screen_t *screen, mpdclient_t *c)
 {
   lw->clear = 1;
   list_window_paint(lw, list_callback, NULL);
@@ -291,7 +290,7 @@ keydef_paint(screen_t *screen, mpd_client_t *c)
 }
 
 static void 
-keydef_update(screen_t *screen, mpd_client_t *c)
+keydef_update(screen_t *screen, mpdclient_t *c)
 {  
   if( lw->repaint )
     {
@@ -302,7 +301,7 @@ keydef_update(screen_t *screen, mpd_client_t *c)
 }
 
 static int 
-keydef_cmd(screen_t *screen, mpd_client_t *c, command_t cmd)
+keydef_cmd(screen_t *screen, mpdclient_t *c, command_t cmd)
 {
   int length = LIST_LENGTH();
 
index 9dc2a9651a982b3b1093be517004e1ec37240320..73c0bc679e46537f3db5bd6cb86c0594378c597b 100644 (file)
 #include "ncmpc.h"
 #include "options.h"
 #include "support.h"
-#include "libmpdclient.h"
-#include "mpc.h"
+#include "mpdclient.h"
+#include "strfsong.h"
 #include "command.h"
 #include "screen.h"
 #include "screen_utils.h"
-#include "screen_file.h"
-#include "screen_play.h"
 
-#define BUFSIZE 256
+#define MAX_SONG_LENGTH 512
 
 static list_window_t *lw = NULL;
 
+static void 
+playlist_changed_callback(mpdclient_t *c, int event, gpointer data)
+{
+  D("screen_play.c> playlist_callback() [%d]\n", event);
+  switch(event)
+    {
+    case PLAYLIST_EVENT_DELETE:
+      break;
+    case PLAYLIST_EVENT_MOVE:
+      lw->selected = *((int *) data);
+      break;
+    default:
+      break;
+    }
+  /* make shure the playlist is repainted */
+  lw->clear = 1;
+  lw->repaint = 1;
+  list_window_check_selected(lw, c->playlist.length);
+}
+
 static char *
 list_callback(int index, int *highlight, void *data)
 {
-  mpd_client_t *c = (mpd_client_t *) data;
+  static char songname[MAX_SONG_LENGTH];
+  mpdclient_t *c = (mpdclient_t *) data;
   mpd_Song *song;
 
   *highlight = 0;
-  if( (song=mpc_playlist_get_song(c, index)) == NULL )
+  if( (song=playlist_get_song(c, index)) == NULL )
     {
       return NULL;
     }
 
-  if( index==c->song_id && !IS_STOPPED(c->status->state) )
+  if( c->song && song->id==c->song->id && !IS_STOPPED(c->status->state) )
     {
       *highlight = 1;
     }
-
-  return mpc_get_song_name2(song);
+  strfsong(songname, MAX_SONG_LENGTH, LIST_FORMAT, song);
+  return songname;
 }
 
 static int
-center_playing_item(screen_t *screen, mpd_client_t *c)
+center_playing_item(screen_t *screen, mpdclient_t *c)
 {
-  int length = c->playlist_length;
+  int length = c->playlist.length;
   int offset = lw->selected-lw->start;
+  int index;
   
-  if( !lw || length<lw->rows || IS_STOPPED(c->status->state) )
+  if( !lw || !c->song || length<lw->rows || IS_STOPPED(c->status->state) )
     return 0;
 
   /* try to center the song that are playing */
-  lw->start = c->song_id-(lw->rows/2);
+  index = playlist_get_index(c, c->song);
+  D("Autocenter song id:%d pos:%d index:%d\n", c->song->id,c->song->pos,index);
+  lw->start = index-(lw->rows/2);
   if( lw->start+lw->rows > length )
     lw->start = length-lw->rows;
   if( lw->start<0 )
@@ -86,47 +108,23 @@ center_playing_item(screen_t *screen, mpd_client_t *c)
 }
 
 static int
-handle_save_playlist(screen_t *screen, mpd_client_t *c)
+handle_save_playlist(screen_t *screen, mpdclient_t *c)
 {
-  char *filename, *filename_utf8;
+  char *filename;
 
   filename=screen_getstr(screen->status_window.w, _("Save playlist as: "));
   filename=trim(filename);
   if( filename==NULL || filename[0]=='\0' )
     return -1;
-  /* convert filename to utf-8 */
-  filename_utf8 = locale_to_utf8(filename);
   /* send save command to mpd */
-  mpd_sendSaveCommand(c->connection, filename_utf8);
-  mpd_finishCommand(c->connection);
-  g_free(filename_utf8);
-  /* handle errors */
-  if( mpc_error(c))
+  if( mpdclient_cmd_save_playlist(c, filename) )
     {
-      if(  mpc_error_str(c) )
-       {
-         char *str = utf8_to_locale(mpc_error_str(c));
-         screen_status_message(str);
-         g_free(str);
-       }
-      else
-       screen_status_printf(_("Error: Unable to save playlist as %s"), 
-                            filename);
-      mpd_clearError(c->connection);
       beep();
       return -1;
     }
   /* success */
   screen_status_printf(_("Saved %s"), filename);
   g_free(filename);
-  /* update the file list if it has been initalized */
-  if( c->filelist )
-    {
-      list_window_t *file_lw = get_filelist_window();
-
-      mpc_update_filelist(c);
-      list_window_check_selected(file_lw, c->filelist_length);
-    }
   return 0;
 }
 
@@ -136,6 +134,18 @@ play_init(WINDOW *w, int cols, int rows)
   lw = list_window_init(w, cols, rows);
 }
 
+static void
+play_open(screen_t *screen, mpdclient_t *c)
+{
+  static gboolean install_cb = TRUE;
+
+  if( install_cb )
+    {
+      mpdclient_install_playlist_callback(c, playlist_changed_callback);
+      install_cb = FALSE;
+    }
+}
+
 static void
 play_resize(int cols, int rows)
 {
@@ -162,7 +172,7 @@ play_title(char *str, size_t size)
 }
 
 static void
-play_paint(screen_t *screen, mpd_client_t *c)
+play_paint(screen_t *screen, mpdclient_t *c)
 { 
   lw->clear = 1;
 
@@ -171,28 +181,28 @@ play_paint(screen_t *screen, mpd_client_t *c)
 }
 
 static void
-play_update(screen_t *screen, mpd_client_t *c)
+play_update(screen_t *screen, mpdclient_t *c)
 {
   if( options.auto_center )
     {
       static int prev_song_id = 0;
       
-      if( prev_song_id != c->song_id ) 
+      if( c->song && prev_song_id != c->song->id )     
        {
          center_playing_item(screen, c);
-         prev_song_id = c->song_id;
+         prev_song_id = c->song->id;
        }
     }
 
-  if( c->playlist_updated )
+  if( c->playlist.updated )
     {
-      if( lw->selected >= c->playlist_length )
-       lw->selected = c->playlist_length-1;
-      if( lw->start    >= c->playlist_length )
+      if( lw->selected >= c->playlist.length )
+       lw->selected = c->playlist.length-1;
+      if( lw->start    >= c->playlist.length )
        list_window_reset(lw);
 
       play_paint(screen, c);
-      c->playlist_updated = 0;
+      c->playlist.updated = FALSE;
     }
   else if( lw->repaint || 1)
     {
@@ -203,12 +213,15 @@ play_update(screen_t *screen, mpd_client_t *c)
 }
 
 static int
-play_cmd(screen_t *screen, mpd_client_t *c, command_t cmd)
+play_cmd(screen_t *screen, mpdclient_t *c, command_t cmd)
 {
   switch(cmd)
     {
+    case CMD_PLAY:
+      mpdclient_cmd_play(c, lw->selected);
+      break;
     case CMD_DELETE:
-      playlist_delete_song(c, lw->selected);
+      mpdclient_cmd_delete(c, lw->selected);
       return 1;
     case CMD_SAVE_PLAYLIST:
       handle_save_playlist(screen, c);
@@ -217,22 +230,22 @@ play_cmd(screen_t *screen, mpd_client_t *c, command_t cmd)
       center_playing_item(screen, c);
       return 1;
     case CMD_LIST_MOVE_UP:
-      playlist_move_song(c, lw->selected, lw->selected-1);
+      mpdclient_cmd_move(c, lw->selected, lw->selected-1);
       break;
     case CMD_LIST_MOVE_DOWN:
-      playlist_move_song(c, lw->selected, lw->selected+1);
+      mpdclient_cmd_move(c, lw->selected, lw->selected+1);
       break;
     case CMD_LIST_FIND:
     case CMD_LIST_RFIND:
     case CMD_LIST_FIND_NEXT:
     case CMD_LIST_RFIND_NEXT:
       return screen_find(screen, c, 
-                        lw, c->playlist_length,
+                        lw, c->playlist.length,
                         cmd, list_callback);
     default:
       break;
     }
-  return list_window_cmd(lw, c->playlist_length, cmd) ;
+  return list_window_cmd(lw, c->playlist.length, cmd) ;
 }
 
 
@@ -243,134 +256,6 @@ play_lw(void)
   return lw;
 }
 
-int 
-play_get_selected(void)
-{
-  return lw->selected;
-}
-
-int
-playlist_move_song(mpd_client_t *c, int old_index, int new_index)
-{
-  int index1, index2;
-  GList *item1, *item2;
-  gpointer data1, data2;
-
-  if( old_index==new_index || new_index<0 || new_index>=c->playlist_length )
-    return -1;
-
-  /* send the move command to mpd */
-  mpd_sendMoveCommand(c->connection, old_index, new_index);
-  mpd_finishCommand(c->connection);
-  if( mpc_error(c) )
-    return -1;
-
-  index1 = MIN(old_index, new_index);
-  index2 = MAX(old_index, new_index);
-  item1 = g_list_nth(c->playlist, index1);
-  item2 = g_list_nth(c->playlist, index2);
-  data1 = item1->data;
-  data2 = item2->data;
-
-  /* move the second item */
-  D(fprintf(stderr, "move second item [%d->%d]...\n", index2, index1));
-  c->playlist = g_list_remove(c->playlist, data2);
-  c->playlist = g_list_insert_before(c->playlist, item1, data2);
-
-  /* move the first item */
-  if( index2-index1 >1 )
-    {
-      D(fprintf(stderr, "move first item [%d->%d]...\n", index1, index2));
-      item2 = g_list_nth(c->playlist, index2);
-      c->playlist = g_list_remove(c->playlist, data1);
-      c->playlist = g_list_insert_before(c->playlist, item2, data1);
-    }
-  
-  /* increment the playlist id, so we dont retrives a new playlist */
-  c->playlist_id++;
-
-  /* make shure the playlist is repainted */
-  lw->clear = 1;
-  lw->repaint = 1;
-
-  /* keep song selected */
-  lw->selected = new_index;
-
-  return 0;
-}
-
-int
-playlist_add_song(mpd_client_t *c, mpd_Song *song)
-{
-  if( !song || !song->file )
-    return -1;
-
-  /* send the add command to mpd */
-  mpd_sendAddCommand(c->connection, song->file);
-  mpd_finishCommand(c->connection);
-  if( mpc_error(c) )
-    return -1;
-
-  /* add the song to playlist */
-  c->playlist = g_list_append(c->playlist, (gpointer) mpd_songDup(song));
-  c->playlist_length++;
-
-  /* increment the playlist id, so we dont retrives a new playlist */
-  c->playlist_id++;
-
-  /* make shure the playlist is repainted */
-  lw->clear = 1;
-  lw->repaint = 1;
-
-  /* set selected highlight in the browse screen */
-  file_set_highlight(c, song, 1);
-
-  return 0;
-}
-
-int
-playlist_delete_song(mpd_client_t *c, int index)
-{
-  mpd_Song *song = mpc_playlist_get_song(c, index);
-
-  if( !song )
-    return -1;
-
-  /* send the delete command to mpd */
-  mpd_sendDeleteCommand(c->connection, index);
-  mpd_finishCommand(c->connection); 
-  if( mpc_error(c) )
-    return -1;
-
-  /* print a status message */
-  screen_status_printf(_("Removed \'%s\' from playlist!"),
-                      mpc_get_song_name2(song));
-  /* clear selected highlight in the browse screen */
-  file_set_highlight(c, song, 0);
-
-  /* increment the playlist id, so we dont retrives a new playlist */
-  c->playlist_id++;
-
-  /* remove references to the song */
-  if( c->song == song )
-    {
-      c->song = NULL;
-      c->song_id = -1;
-    }
-  
-  /* remove the song from the playlist */
-  c->playlist = g_list_remove(c->playlist, (gpointer) song);
-  c->playlist_length = g_list_length(c->playlist);
-  mpd_freeSong(song);
-
-  /* make shure the playlist is repainted */
-  lw->clear = 1;
-  lw->repaint = 1;
-  list_window_check_selected(lw, c->playlist_length);
-
-  return 0;
-}
-
 
 screen_functions_t *
 get_screen_playlist(void)
@@ -380,7 +265,7 @@ get_screen_playlist(void)
   memset(&functions, 0, sizeof(screen_functions_t));
   functions.init   = play_init;
   functions.exit   = play_exit;
-  functions.open   = NULL;
+  functions.open   = play_open;
   functions.close  = NULL;
   functions.resize = play_resize;
   functions.paint  = play_paint;
diff --git a/src/screen_play.h b/src/screen_play.h
deleted file mode 100644 (file)
index 2155ae5..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-
-int play_get_selected(void);
-
-int playlist_move_song(mpd_client_t *c, int old_index, int new_index);
-int playlist_add_song(mpd_client_t *c, mpd_Song *song);
-int playlist_delete_song(mpd_client_t *c, int index);
-
-screen_functions_t *get_screen_playlist(void);
-
index 6b6719e301710692133c0d6e293373bfc8803cdf..d82a049ef9ae5efebdc1ac04abcdaa06d0b924e6 100644 (file)
@@ -3,10 +3,8 @@
 #include <glib.h>
 #include <ncurses.h>
 
-#include "libmpdclient.h"
 #include "config.h"
-#include "mpc.h"
+#include "mpdclient.h"
 #include "command.h"
 #include "screen.h"
-#include "screen_search.h"
 
diff --git a/src/screen_search.h b/src/screen_search.h
deleted file mode 100644 (file)
index e69de29..0000000
index b14b2a0ee156b0b8c36ab0ed54893d6ee60df215..6473244bbce7534dcbe4281ca51ee381e3e7d333 100644 (file)
@@ -26,8 +26,7 @@
 
 #include "config.h"
 #include "ncmpc.h"
-#include "libmpdclient.h"
-#include "mpc.h"
+#include "mpdclient.h"
 #include "support.h"
 #include "command.h"
 #include "options.h"
@@ -55,7 +54,9 @@ screen_getch(WINDOW *w, char *prompt)
   curs_set(1);
   timeout(-1);
 
-  key = wgetch(w);
+  while( (key=wgetch(w)) == ERR )
+    ;
+  
   if( key==KEY_RESIZE )
     screen_resize();
 
@@ -92,7 +93,7 @@ screen_getstr(WINDOW *w, char *prompt)
 /* query user for a string and find it in a list window */
 int 
 screen_find(screen_t *screen,
-           mpd_client_t *c,
+           mpdclient_t *c,
            list_window_t *lw, 
            int rows,
            command_t findcmd,
index 30c58bfca1072d190d522d797b1a083f0fb71266..b6e8d11712ded8d83a5ba0bc441c64c6bae2394f 100644 (file)
@@ -7,7 +7,7 @@ char *screen_getstr(WINDOW *w, char *prompt);
 
 /* query user for a string and find it in a list window */
 int screen_find(screen_t *screen,
-               mpd_client_t *c,
+               mpdclient_t *c,
                list_window_t *lw, 
                int rows,
                command_t findcmd,
diff --git a/src/strfsong.c b/src/strfsong.c
new file mode 100644 (file)
index 0000000..a7eb011
--- /dev/null
@@ -0,0 +1,214 @@
+/* 
+ * $Id$
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <glib.h>
+
+#include "config.h"
+#include "libmpdclient.h"
+#include "ncmpc.h"
+#include "support.h"
+#include "strfsong.h"
+
+static char * 
+skip(char * p) 
+{
+  int stack = 0;
+  while (*p != '\0') {
+    if(*p == '[') stack++;
+    if(*p == '#' && p[1] != '\0') {
+      /* skip escaped stuff */
+      ++p;
+    }
+    else if(stack) {
+      if(*p == ']') stack--;
+    }
+    else {
+      if(*p == '&' || *p == '|' || *p == ']') {
+       break;
+      }
+    }
+    ++p;
+  }
+
+  return p;
+}
+
+static gsize
+_strfsong(gchar *s, 
+         gsize max, 
+         const gchar *format, 
+         mpd_Song *song, 
+         gchar **last)
+{
+  gchar *p, *end;
+  gchar *temp;
+  gsize n, length = 0;
+  gboolean found = FALSE;
+
+  memset(s, 0, max);
+  if( song==NULL )
+    return 0;
+  
+  for( p=(gchar *) format; *p != '\0' && length<max; )
+    {
+      /* OR */
+      if (p[0] == '|') 
+       {
+         ++p;
+         if(!found) 
+           {
+             memset(s, 0, max);
+             length = 0;
+           }
+         else 
+           {
+             p = skip(p);
+           }
+         continue;
+       }
+
+      /* AND */
+      if (p[0] == '&') 
+       {
+         ++p;
+         if(!found) 
+           {
+             p = skip(p);
+           }
+         else 
+           {
+             found = FALSE;
+           }
+         continue;
+       }
+
+      /* EXPRESSION START */
+      if (p[0] == '[')
+       {
+         temp = g_malloc0(max);
+         if( _strfsong(temp, max, p+1, song, &p) >0 )
+           {
+             strncat(s, temp, max-length);
+             length = strlen(s);
+             found = TRUE;
+           }
+         g_free(temp);
+         continue;
+       }
+
+      /* EXPRESSION END */
+      if (p[0] == ']')
+       {
+         if(last) *last = p+1;
+         if(!found && length) 
+           {
+             memset(s, 0, max);
+             length = 0;
+           }
+         return length;
+       }
+
+      /* pass-through non-escaped portions of the format string */
+      if (p[0] != '#' && p[0] != '%' && length<max)
+       {
+         strncat(s, p, 1);
+         length++;
+         ++p;
+         continue;
+       }
+
+      /* let the escape character escape itself */
+      if (p[0] == '#' && p[1] != '\0' && length<max)
+       {
+         strncat(s, p+1, 1);
+         length++;
+         p+=2;
+         continue;
+       }
+
+      /* advance past the esc character */
+
+      /* find the extent of this format specifier (stop at \0, ' ', or esc) */
+      temp = NULL;
+      end  = p+1;
+      while(*end >= 'a' && *end <= 'z')
+       {
+         end++;
+       }
+      n = end - p + 1;
+      if(*end != '%')
+       n--;
+      else if (strncmp("%basename%", p, n) == 0)
+       temp = utf8_to_locale(basename(song->file));
+      else if (strncmp("%file%", p, n) == 0)
+       temp = utf8_to_locale(song->file);
+      else if (strncmp("%artist%", p, n) == 0)
+       temp = song->artist ? utf8_to_locale(song->artist) : NULL;
+      else if (strncmp("%title%", p, n) == 0)
+       temp = song->title ? utf8_to_locale(song->title) : NULL;
+      else if (strncmp("%album%", p, n) == 0)
+       temp = song->album ? utf8_to_locale(song->album) : NULL;
+      else if (strncmp("%track%", p, n) == 0)
+       temp = song->track ? utf8_to_locale(song->track) : NULL;
+      else if (strncmp("%name%", p, n) == 0)
+       temp = song->name ? utf8_to_locale(song->name) : NULL;
+      else if (strncmp("%time%", p, n) == 0)
+       {
+         if (song->time != MPD_SONG_NO_TIME) {
+           gchar s[10];
+           snprintf(s, 9, "%d:%d", song->time / 60, 
+                    song->time % 60 + 1);
+           /* nasty hack to use static buffer */
+           temp = g_strdup(s);
+         }
+       }
+
+      if( temp == NULL)
+       {
+         gsize templen=n;
+         /* just pass-through any unknown specifiers (including esc) */
+         /* drop a null char in so printf stops at the end of this specifier,
+            but put the real character back in (pseudo-const) */
+         if( length+templen > max )
+           templen = max-length;
+         strncat(s, p, templen);
+         length+=templen;
+       }
+      else {
+       gsize templen = strlen(temp);
+
+       found = TRUE;
+       if( length+templen > max )
+         templen = max-length;
+       strncat(s, temp, templen);
+       length+=templen;
+       g_free(temp);
+      }
+
+      /* advance past the specifier */
+      p += n;
+    }
+
+  if(last) *last = p;
+
+  return length;
+}
+
+
+/* a modified version of mpc's songToFormatedString (util.c) 
+ * added - %basename%
+ */
+
+gsize
+strfsong(gchar *s, gsize max, const gchar *format, mpd_Song *song)
+{
+  return _strfsong(s, max, format, song, NULL);
+}
+     
diff --git a/src/strfsong.h b/src/strfsong.h
new file mode 100644 (file)
index 0000000..74f9d73
--- /dev/null
@@ -0,0 +1,3 @@
+
+gsize strfsong(gchar *s, gsize max, const gchar *format, mpd_Song *song);
+
index 23b67d3e71e9b180b6fb5ec4c1af1f84ee9dec3e..90ecb8b0d444a5b11df1395887b36521952f81ec 100644 (file)
@@ -1,7 +1,7 @@
 /* 
  * $Id$
  *
- * (c) 2004 by Kalle Wallin (kaw@linux.se)
+ * (c) 2004 by Kalle Wallin <kaw@linux.se>
  *
  * 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
@@ -18,6 +18,7 @@
  *
  */
 
+#include <time.h>
 #include <ctype.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -184,7 +185,7 @@ utf8_to_locale(char *utf8str)
       g_get_charset(&charset);
       screen_status_printf(_("Error: Unable to convert characters to %s"),
                           charset);
-      D(g_printerr("utf8_to_locale(): %s\n", error->message));
+      D("utf8_to_locale(): %s\n", error->message);
       g_error_free(error);
       return g_strdup(utf8str);
     }
@@ -212,7 +213,7 @@ locale_to_utf8(char *localestr)
   if( error )
     {
       screen_status_printf(_("Error: Unable to convert characters to UTF-8"));
-      D(g_printerr("locale_to_utf8: %s\n", error->message));
+      D("locale_to_utf8: %s\n", error->message);
       g_error_free(error);
       return g_strdup(localestr);
     }