diff options
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | src/libmpdclient.c | 47 | ||||
-rw-r--r-- | src/libmpdclient.h | 17 | ||||
-rw-r--r-- | src/mpc.c | 195 | ||||
-rw-r--r-- | src/mpc.h | 1 |
5 files changed, 247 insertions, 18 deletions
@@ -1,3 +1,7 @@ +2004-06-07 Kalle Wallin <kaw@linux.se> + * configure.ac: disable nls if glib is pre 2.4 + * mpc.c: added support for the PLCHANGES command + 2004-06-06 Kalle Wallin <kaw@linux.se> * i18n: ncmpc is now bilingual (sv) * Moved all locale initialization code to main.c @@ -5,6 +9,7 @@ * Added wreadln.c, wreadln.h a simple line editor * screen_utils.c: use wreadln() instead of curses wgetstr() * Added a history for the find command! + * Added screen_clock.c an optional clock screen (just for fun) 2004-06-05 Kalle Wallin <kaw@linux.se> diff --git a/src/libmpdclient.c b/src/libmpdclient.c index 2e8b579da..a879b53e6 100644 --- a/src/libmpdclient.c +++ b/src/libmpdclient.c @@ -38,7 +38,6 @@ typedef SOCKLEN_T socklen_t; #endif #endif - #ifndef MPD_NO_IPV6 #ifdef AF_INET6 #define MPD_HAVE_IPV6 @@ -386,13 +385,13 @@ void mpd_executeCommand(mpd_Connection * connection, char * command) { void mpd_getNextReturnElement(mpd_Connection * connection) { char * output = NULL; char * rt = NULL; - char * name; - char * value; + char * name = NULL; + char * value = NULL; fd_set fds; struct timeval tv; - char * tok; + char * tok = NULL; int readed; - char * bufferCheck; + char * bufferCheck = NULL; int err; if(connection->returnElement) mpd_freeReturnElement(connection->returnElement); @@ -464,9 +463,24 @@ void mpd_getNextReturnElement(mpd_Connection * connection) { return; } if(strncmp(output,"ACK",strlen("ACK"))==0) { - strcpy(connection->errorStr,output); + char * test; + char * needle; + int val; + + strcpy(connection->errorStr, output); connection->error = MPD_ERROR_ACK; + connection->errorCode = MPD_ERROR_CODE_UNK; + connection->errorAt = MPD_ERROR_AT_UNK; connection->doneProcessing = 1; + + needle = strchr(output, '['); + if(!needle) return; + val = strtol(needle, &test, 10); + if(*test != '@') return; + connection->errorCode = val; + val = strtol(test+1, &test, 10); + if(*test != ']') return; + connection->errorAt = val; return; } @@ -492,7 +506,6 @@ void mpd_finishCommand(mpd_Connection * connection) { while(!connection->doneProcessing) mpd_getNextReturnElement(connection); } - mpd_Status * mpd_getStatus(mpd_Connection * connection) { mpd_Status * status; @@ -696,7 +709,9 @@ void mpd_initSong(mpd_Song * song) { song->album = NULL; song->track = NULL; song->title = NULL; + song->name = NULL; song->time = MPD_SONG_NO_TIME; + song->num = MPD_SONG_NO_NUM; } void mpd_finishSong(mpd_Song * song) { @@ -705,6 +720,7 @@ void mpd_finishSong(mpd_Song * song) { if(song->album) free(song->album); if(song->title) free(song->title); if(song->track) free(song->track); + if(song->name) free(song->name); } mpd_Song * mpd_newSong() { @@ -728,7 +744,9 @@ mpd_Song * mpd_songDup(mpd_Song * song) { if(song->album) ret->album = strdup(song->album); if(song->title) ret->title = strdup(song->title); if(song->track) ret->track = strdup(song->track); + if(song->name) ret->name = strdup(song->name); ret->time = song->time; + ret->num = song->num; return ret; } @@ -891,10 +909,18 @@ mpd_InfoEntity * mpd_getNextInfoEntity(mpd_Connection * connection) { strcmp(re->name,"Track")==0) { entity->info.song->track = strdup(re->value); } + else if(!entity->info.song->name && + strcmp(re->name,"Name")==0) { + entity->info.song->name = strdup(re->value); + } else if(entity->info.song->time==MPD_SONG_NO_TIME && 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->type == MPD_INFO_ENTITY_TYPE_DIRECTORY) { } @@ -938,6 +964,13 @@ void mpd_sendPlaylistInfoCommand(mpd_Connection * connection, int songNum) { free(string); } +void mpd_sendPlChangesCommand(mpd_Connection * connection, long long playlist) { + char * string = malloc(strlen("plchanges")+25); + sprintf(string,"plchanges \"%i\"\n",playlist); + mpd_sendInfoCommand(connection,string); + free(string); +} + void mpd_sendListallCommand(mpd_Connection * connection, const char * dir) { char * sDir = mpd_sanitizeArg(dir); char * string = malloc(strlen("listall")+strlen(sDir)+5); diff --git a/src/libmpdclient.h b/src/libmpdclient.h index e5e58791c..55d2ff077 100644 --- a/src/libmpdclient.h +++ b/src/libmpdclient.h @@ -36,6 +36,9 @@ #define MPD_ERROR_ACK 18 /* ACK returned! */ #define MPD_ERROR_BUFFEROVERRUN 19 /* Buffer was overrun! */ +#define MPD_ERROR_CODE_UNK -1; +#define MPD_ERROR_AT_UNK -1; + #ifdef __cplusplus extern "C" { #endif @@ -55,7 +58,9 @@ typedef struct _mpd_Connection { int version[3]; /* IMPORTANT, you want to get the error messages from here */ char errorStr[MPD_BUFFER_MAX_LENGTH+1]; - /* this will be set to 1 if there is an error, 0 if not */ + int errorCode; + int errorAt; + /* this will be set to MPD_ERROR_* if there is an error, 0 if not */ int error; /* DON'T TOUCH any of the rest of this stuff */ int sock; @@ -168,6 +173,7 @@ void mpd_freeStats(mpd_Stats * stats); /* SONG STUFF */ #define MPD_SONG_NO_TIME -1 +#define MPD_SONG_NO_NUM -1 /* mpd_Song * for storing song info returned by mpd @@ -183,8 +189,14 @@ typedef struct _mpd_Song { char * album; /* track, maybe NULL if there is no tag */ char * track; + /* name, maybe NULL if there is no tag; it's the name of the current + * song, f.e. the icyName of the stream */ + 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 + * the playlist */ + int num; } mpd_Song; /* mpd_newSong @@ -297,6 +309,9 @@ mpd_InfoEntity * mpd_getNextInfoEntity(mpd_Connection * connection); /* songNum of -1, means to display the whole list */ void mpd_sendPlaylistInfoCommand(mpd_Connection * connection, int songNum); +/* use this to get the changes in the playlist since version _playlist_ */ +void mpd_sendPlChangesCommand(mpd_Connection * connection, long long playlist); + void mpd_sendListallCommand(mpd_Connection * connection, const char * dir); void mpd_sendListallInfoCommand(mpd_Connection * connection, const char * dir); @@ -1,3 +1,23 @@ +/* + * $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> @@ -6,6 +26,7 @@ #include <glib.h> #include "config.h" +#include "ncmpc.h" #include "support.h" #include "libmpdclient.h" #include "mpc.h" @@ -13,12 +34,6 @@ #define MAX_SONG_LENGTH 1024 -#ifdef DEBUG -#define D(x) x -#else -#define D(x) -#endif - int mpc_close(mpd_client_t *c) { @@ -136,11 +151,11 @@ mpc_free_playlist(mpd_client_t *c) } int -mpc_update_playlist(mpd_client_t *c) +mpc_get_playlist(mpd_client_t *c) { mpd_InfoEntity *entity; - D(fprintf(stderr, "mpc_update_playlist() [%d]\n", c->status->playlist)); + D(fprintf(stderr, "mpc_get_playlist() [%lld]\n", c->status->playlist)); if( mpc_error(c) ) return -1; @@ -163,6 +178,7 @@ mpc_update_playlist(mpd_client_t *c) } mpd_freeInfoEntity(entity); } + mpd_finishCommand(c->connection); c->playlist_id = c->status->playlist; c->playlist_updated = 1; c->song_id = -1; @@ -173,6 +189,62 @@ mpc_update_playlist(mpd_client_t *c) return 0; } +int +mpc_update_playlist(mpd_client_t *c) +{ + mpd_InfoEntity *entity; + + D(fprintf(stderr, "mpc_update_playlist() [%lld]\n", c->status->playlist)); + + if( mpc_error(c) ) + return -1; + + mpd_sendPlChangesCommand(c->connection, c->playlist_id); + if( mpc_error(c) ) + return -1; + if( (entity=mpd_getNextInfoEntity(c->connection)) == NULL ) + return mpc_get_playlist(c); + while( entity ) + { + if(entity->type==MPD_INFO_ENTITY_TYPE_SONG) + { + mpd_Song *song; + GList *item; + + if( (song=mpd_songDup(entity->info.song)) == NULL ) + return mpc_get_playlist(c); + + item = g_list_nth(c->playlist, song->num); + if( item && item->data) + { + 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 + { + 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); + entity=mpd_getNextInfoEntity(c->connection); + } + mpd_finishCommand(c->connection); + + 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) { @@ -227,6 +299,104 @@ mpc_get_song_name(mpd_Song *song) return buf; } +char * +mpc_get_song_name2(mpd_Song *song) +{ + static char buf[MAX_SONG_LENGTH]; + char *name; + + if( song->name ) + { + name = utf8_to_locale(song->name); + strncpy(buf, name, MAX_SONG_LENGTH); + g_free(name); + return buf; + } + + 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) { @@ -241,9 +411,14 @@ mpc_update(mpd_client_t *c) c->status = mpd_getStatus(c->connection); if( mpc_error(c) ) return -1; - + if( c->playlist_id!=c->status->playlist ) - mpc_update_playlist(c); + { + if( c->playlist_length<2 ) + mpc_get_playlist(c); + else + mpc_update_playlist(c); + } if( !c->song || c->status->song != c->song_id ) { @@ -44,6 +44,7 @@ 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); |