X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fmpdclient.c;h=e331544be34a3e3168ad25fcea6df859fefe8aa6;hb=6e166433ef87e8c1e7778d1c497729d92206b04c;hp=0897e8607471bba86dbee1bf26dced9e7527b5f2;hpb=74f964eff234bba4cf6f04fdf4ae31a673839176;p=ncmpc.git diff --git a/src/mpdclient.c b/src/mpdclient.c index 0897e86..e331544 100644 --- a/src/mpdclient.c +++ b/src/mpdclient.c @@ -18,12 +18,15 @@ */ #include "mpdclient.h" -#include "screen_utils.h" +#include "filelist.h" +#include "screen_client.h" #include "config.h" #include "options.h" #include "strfsong.h" #include "utils.h" +#include + #include #include #include @@ -32,15 +35,14 @@ #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 -#define ENABLE_SONG_ID -#define ENABLE_PLCHANGES #define BUFSIZE 1024 static bool MPD_ERROR(const struct mpdclient *client) { - return client->connection == NULL; + return client->connection == NULL || + mpd_connection_get_error(client->connection) != MPD_ERROR_SUCCESS; } /* filelist sorting functions */ @@ -48,23 +50,26 @@ static gint compare_filelistentry(gconstpointer filelist_entry1, gconstpointer filelist_entry2) { - const mpd_InfoEntity *e1, *e2; + const struct mpd_entity *e1, *e2; int n = 0; - e1 = ((const filelist_entry_t *)filelist_entry1)->entity; - e2 = ((const filelist_entry_t *)filelist_entry2)->entity; + e1 = ((const struct filelist_entry *)filelist_entry1)->entity; + e2 = ((const struct filelist_entry *)filelist_entry2)->entity; - if (e1 && e2 && e1->type == e2->type) { - switch (e1->type) { - case MPD_INFO_ENTITY_TYPE_DIRECTORY: - n = g_utf8_collate(e1->info.directory->path, - e2->info.directory->path); + if (e1 != NULL && e2 != NULL && + mpd_entity_get_type(e1) == mpd_entity_get_type(e2)) { + switch (mpd_entity_get_type(e1)) { + case MPD_ENTITY_TYPE_UNKNOWN: + break; + case MPD_ENTITY_TYPE_DIRECTORY: + n = g_utf8_collate(mpd_directory_get_path(mpd_entity_get_directory(e1)), + mpd_directory_get_path(mpd_entity_get_directory(e2))); break; - case MPD_INFO_ENTITY_TYPE_SONG: + case MPD_ENTITY_TYPE_SONG: break; - case MPD_INFO_ENTITY_TYPE_PLAYLISTFILE: - n = g_utf8_collate(e1->info.playlistFile->path, - e2->info.playlistFile->path); + case MPD_ENTITY_TYPE_PLAYLIST: + n = g_utf8_collate(mpd_playlist_get_path(mpd_entity_get_playlist(e1)), + mpd_playlist_get_path(mpd_entity_get_playlist(e2))); } } return n; @@ -75,18 +80,18 @@ gint compare_filelistentry_format(gconstpointer filelist_entry1, gconstpointer filelist_entry2) { - const mpd_InfoEntity *e1, *e2; + const struct mpd_entity *e1, *e2; char key1[BUFSIZE], key2[BUFSIZE]; int n = 0; - e1 = ((const filelist_entry_t *)filelist_entry1)->entity; - e2 = ((const filelist_entry_t *)filelist_entry2)->entity; + e1 = ((const struct filelist_entry *)filelist_entry1)->entity; + e2 = ((const struct filelist_entry *)filelist_entry2)->entity; if (e1 && e2 && - e1->type == MPD_INFO_ENTITY_TYPE_SONG && - e2->type == MPD_INFO_ENTITY_TYPE_SONG) { - strfsong(key1, BUFSIZE, options.list_format, e1->info.song); - strfsong(key2, BUFSIZE, options.list_format, e2->info.song); + mpd_entity_get_type(e1) == MPD_ENTITY_TYPE_SONG && + mpd_entity_get_type(e2) == MPD_ENTITY_TYPE_SONG) { + strfsong(key1, BUFSIZE, options.list_format, mpd_entity_get_song(e1)); + strfsong(key2, BUFSIZE, options.list_format, mpd_entity_get_song(e2)); n = strcmp(key1,key2); } @@ -94,77 +99,58 @@ compare_filelistentry_format(gconstpointer filelist_entry1, } -/* Error callbacks */ -static gint -error_cb(mpdclient_t *c, gint error, const gchar *msg) -{ - GList *list = c->error_callbacks; - - if (list == NULL) - fprintf(stderr, "error [%d]: %s\n", (error & 0xFF), 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; -} - - /****************************************************************************/ /*** mpdclient functions ****************************************************/ /****************************************************************************/ -static gint -mpdclient_handle_error(mpdclient_t *c) +gint +mpdclient_handle_error(struct mpdclient *c) { - enum mpd_error error = c->connection->error; - bool is_fatal = error != MPD_ERROR_ACK; + enum mpd_error error = mpd_connection_get_error(c->connection); - if (error == MPD_ERROR_SUCCESS) - return 0; + assert(error != MPD_ERROR_SUCCESS); - if (error == MPD_ERROR_ACK && - c->connection->errorCode == MPD_ACK_ERROR_PERMISSION && - screen_auth(c) == 0) + if (error == MPD_ERROR_SERVER && + mpd_connection_get_server_error(c->connection) == MPD_SERVER_ERROR_PERMISSION && + screen_auth(c)) return 0; - if (error == MPD_ERROR_ACK) - error = error | (c->connection->errorCode << 8); + if (error == MPD_ERROR_SERVER) + error = error | (mpd_connection_get_server_error(c->connection) << 8); - error_cb(c, error, c->connection->errorStr); + for (GList *list = c->error_callbacks; list != NULL; + list = list->next) { + mpdc_error_cb_t cb = list->data; + cb(c, error, mpd_connection_get_error_message(c->connection)); + } - if (is_fatal) + if (!mpd_connection_clear_error(c->connection)) mpdclient_disconnect(c); return error; } -gint -mpdclient_finish_command(mpdclient_t *c) +static gint +mpdclient_finish_command(struct mpdclient *c) { - mpd_finishCommand(c->connection); - return mpdclient_handle_error(c); + return mpd_response_finish(c->connection) + ? 0 : mpdclient_handle_error(c); } -mpdclient_t * +struct mpdclient * mpdclient_new(void) { - mpdclient_t *c; + struct mpdclient *c; - c = g_malloc0(sizeof(mpdclient_t)); + c = g_new0(struct mpdclient, 1); playlist_init(&c->playlist); - c->volume = MPD_STATUS_NO_VOLUME; + c->volume = -1; return c; } void -mpdclient_free(mpdclient_t *c) +mpdclient_free(struct mpdclient *c) { mpdclient_disconnect(c); @@ -176,102 +162,96 @@ mpdclient_free(mpdclient_t *c) g_free(c); } -gint -mpdclient_disconnect(mpdclient_t *c) +void +mpdclient_disconnect(struct mpdclient *c) { if (c->connection) - mpd_closeConnection(c->connection); + mpd_connection_free(c->connection); c->connection = NULL; if (c->status) - mpd_freeStatus(c->status); + mpd_status_free(c->status); c->status = NULL; playlist_clear(&c->playlist); if (c->song) c->song = NULL; - - return 0; } -gint -mpdclient_connect(mpdclient_t *c, +bool +mpdclient_connect(struct mpdclient *c, const gchar *host, gint port, gfloat _timeout, const gchar *password) { - gint retval = 0; - /* close any open connection */ if( c->connection ) mpdclient_disconnect(c); /* connect to MPD */ - c->connection = mpd_newConnection(host, port, _timeout); - if (c->connection->error) { - retval = error_cb(c, c->connection->error, - c->connection->errorStr); - if (retval != 0) { - mpd_closeConnection(c->connection); - c->connection = NULL; - } + c->connection = mpd_connection_new(host, port, _timeout * 1000); + if (c->connection == NULL) + g_error("Out of memory"); - return retval; + if (mpd_connection_get_error(c->connection) != MPD_ERROR_SUCCESS) { + mpdclient_handle_error(c); + mpdclient_disconnect(c); + return false; } /* send password */ - if( password ) { - mpd_sendPasswordCommand(c->connection, password); - retval = mpdclient_finish_command(c); + if (password != NULL && !mpd_run_password(c->connection, password)) { + mpdclient_handle_error(c); + mpdclient_disconnect(c); + return false; } - c->need_update = TRUE; - return retval; + return true; } -gint -mpdclient_update(mpdclient_t *c) +bool +mpdclient_update(struct mpdclient *c) { - gint retval = 0; + bool retval; - c->volume = MPD_STATUS_NO_VOLUME; + c->volume = -1; if (MPD_ERROR(c)) - return -1; + return false; /* free the old status */ if (c->status) - mpd_freeStatus(c->status); + mpd_status_free(c->status); /* retrieve new status */ - mpd_sendStatusCommand(c->connection); - c->status = mpd_getStatus(c->connection); - if ((retval=mpdclient_finish_command(c))) - return retval; + c->status = mpd_run_status(c->connection); + if (c->status == NULL) + return mpdclient_handle_error(c) == 0; - if (c->updatingdb && c->updatingdb != c->status->updatingDb) + if (c->update_id > 0 && + c->update_id != mpd_status_get_update_id(c->status)) mpdclient_browse_callback(c, BROWSE_DB_UPDATED, NULL); - c->updatingdb = c->status->updatingDb; - c->volume = c->status->volume; + c->update_id = mpd_status_get_update_id(c->status); + c->volume = mpd_status_get_volume(c->status); /* check if the playlist needs an update */ - if (c->playlist.id != c->status->playlist) { - if (playlist_is_empty(&c->playlist)) + if (c->playlist.id != mpd_status_get_queue_version(c->status)) { + if (!playlist_is_empty(&c->playlist)) retval = mpdclient_playlist_update_changes(c); else retval = mpdclient_playlist_update(c); - } + } else + retval = true; /* update the current song */ - if (!c->song || c->status->songid != c->song->id) { - c->song = playlist_get_song(c, c->status->song); + if (!c->song || mpd_status_get_song_id(c->status)) { + c->song = playlist_get_song(&c->playlist, + mpd_status_get_song_pos(c->status)); } - c->need_update = FALSE; - return retval; } @@ -281,230 +261,85 @@ mpdclient_update(mpdclient_t *c) /****************************************************************************/ gint -mpdclient_cmd_play(mpdclient_t *c, gint idx) +mpdclient_cmd_play(struct mpdclient *c, gint idx) { -#ifdef ENABLE_SONG_ID - struct mpd_song *song = playlist_get_song(c, idx); + const struct mpd_song *song = playlist_get_song(&c->playlist, idx); if (MPD_ERROR(c)) return -1; if (song) - mpd_sendPlayIdCommand(c->connection, song->id); + mpd_send_play_id(c->connection, mpd_song_get_id(song)); else - mpd_sendPlayIdCommand(c->connection, MPD_PLAY_AT_BEGINNING); -#else - if (MPD_ERROR(c)) - return -1; - - mpd_sendPlayCommand(c->connection, idx); -#endif - c->need_update = TRUE; - return mpdclient_finish_command(c); -} - -gint -mpdclient_cmd_pause(mpdclient_t *c, gint value) -{ - if (MPD_ERROR(c)) - return -1; + mpd_send_play(c->connection); - mpd_sendPauseCommand(c->connection, value); return mpdclient_finish_command(c); } gint -mpdclient_cmd_crop(mpdclient_t *c) +mpdclient_cmd_crop(struct mpdclient *c) { - gint error; - mpd_Status *status; + struct mpd_status *status; bool playing; int length, current; if (MPD_ERROR(c)) return -1; - mpd_sendStatusCommand(c->connection); - status = mpd_getStatus(c->connection); - error = mpdclient_finish_command(c); - if (error) - return error; + status = mpd_run_status(c->connection); + if (status == NULL) + return mpdclient_handle_error(c); - playing = status->state == MPD_STATUS_STATE_PLAY || - status->state == MPD_STATUS_STATE_PAUSE; - length = status->playlistLength; - current = status->song; + playing = mpd_status_get_state(status) == MPD_STATE_PLAY || + mpd_status_get_state(status) == MPD_STATE_PAUSE; + length = mpd_status_get_queue_length(status); + current = mpd_status_get_song_pos(status); - mpd_freeStatus(status); + mpd_status_free(status); if (!playing || length < 2) return 0; - mpd_sendCommandListBegin( c->connection ); + mpd_command_list_begin(c->connection, false); while (--length >= 0) if (length != current) - mpd_sendDeleteCommand(c->connection, length); + mpd_send_delete(c->connection, length); - mpd_sendCommandListEnd(c->connection); + mpd_command_list_end(c->connection); return mpdclient_finish_command(c); } gint -mpdclient_cmd_stop(mpdclient_t *c) +mpdclient_cmd_shuffle_range(struct mpdclient *c, guint start, guint end) { - if (MPD_ERROR(c)) - return -1; - - mpd_sendStopCommand(c->connection); + mpd_send_shuffle_range(c->connection, start, end); return mpdclient_finish_command(c); } gint -mpdclient_cmd_next(mpdclient_t *c) -{ - if (MPD_ERROR(c)) - return -1; - - mpd_sendNextCommand(c->connection); - c->need_update = TRUE; - return mpdclient_finish_command(c); -} - -gint -mpdclient_cmd_prev(mpdclient_t *c) -{ - if (MPD_ERROR(c)) - return -1; - - mpd_sendPrevCommand(c->connection); - c->need_update = TRUE; - return mpdclient_finish_command(c); -} - -gint -mpdclient_cmd_seek(mpdclient_t *c, gint id, gint pos) -{ - if (MPD_ERROR(c)) - return -1; - - mpd_sendSeekIdCommand(c->connection, id, pos); - return mpdclient_finish_command(c); -} - -gint -mpdclient_cmd_shuffle(mpdclient_t *c) -{ - if (MPD_ERROR(c)) - return -1; - - mpd_sendShuffleCommand(c->connection); - c->need_update = TRUE; - return mpdclient_finish_command(c); -} - -gint -mpdclient_cmd_shuffle_range(mpdclient_t *c, guint start, guint end) -{ - mpd_sendShuffleRangeCommand(c->connection, start, end); - c->need_update = TRUE; - return mpdclient_finish_command(c); -} - -gint -mpdclient_cmd_clear(mpdclient_t *c) +mpdclient_cmd_clear(struct mpdclient *c) { gint retval = 0; if (MPD_ERROR(c)) return -1; - mpd_sendClearCommand(c->connection); + mpd_send_clear(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) -{ - if (MPD_ERROR(c)) - return -1; - - mpd_sendRepeatCommand(c->connection, value); - return mpdclient_finish_command(c); -} - -gint -mpdclient_cmd_random(mpdclient_t *c, gint value) +mpdclient_cmd_volume(struct mpdclient *c, gint value) { if (MPD_ERROR(c)) return -1; - mpd_sendRandomCommand(c->connection, value); - return mpdclient_finish_command(c); -} - -gint -mpdclient_cmd_single(mpdclient_t *c, gint value) -{ - if (MPD_ERROR(c)) - return -1; - - mpd_sendSingleCommand(c->connection, value); - return mpdclient_finish_command(c); -} - -gint -mpdclient_cmd_consume(mpdclient_t *c, gint value) -{ - if (MPD_ERROR(c)) - return -1; - - mpd_sendConsumeCommand(c->connection, value); - return mpdclient_finish_command(c); -} - -gint -mpdclient_cmd_crossfade(mpdclient_t *c, gint value) -{ - if (MPD_ERROR(c)) - return -1; - - mpd_sendCrossfadeCommand(c->connection, value); - return mpdclient_finish_command(c); -} - -gint -mpdclient_cmd_db_update(mpdclient_t *c, const gchar *path) -{ - gint ret; - - if (MPD_ERROR(c)) - return -1; - - mpd_sendUpdateCommand(c->connection, path ? path : ""); - ret = mpdclient_finish_command(c); - - if (ret == 0) - /* set updatingDb to make sure the browse callback - gets called even if the update has finished before - status is updated */ - c->updatingdb = 1; - - return ret; -} - -gint -mpdclient_cmd_volume(mpdclient_t *c, gint value) -{ - if (MPD_ERROR(c)) - return -1; - - mpd_sendSetvolCommand(c->connection, value); + mpd_send_set_volume(c->connection, value); return mpdclient_finish_command(c); } @@ -513,11 +348,12 @@ gint mpdclient_cmd_volume_up(struct mpdclient *c) if (MPD_ERROR(c)) return -1; - if (c->status == NULL || c->status->volume == MPD_STATUS_NO_VOLUME) + if (c->status == NULL || + mpd_status_get_volume(c->status) == -1) return 0; - if (c->volume == MPD_STATUS_NO_VOLUME) - c->volume = c->status->volume; + if (c->volume < 0) + c->volume = mpd_status_get_volume(c->status); if (c->volume >= 100) return 0; @@ -530,11 +366,11 @@ gint mpdclient_cmd_volume_down(struct mpdclient *c) if (MPD_ERROR(c)) return -1; - if (c->status == NULL || c->status->volume == MPD_STATUS_NO_VOLUME) + if (c->status == NULL || mpd_status_get_volume(c->status) < 0) return 0; - if (c->volume == MPD_STATUS_NO_VOLUME) - c->volume = c->status->volume; + if (c->volume < 0) + c->volume = mpd_status_get_volume(c->status); if (c->volume <= 0) return 0; @@ -543,28 +379,28 @@ gint mpdclient_cmd_volume_down(struct mpdclient *c) } gint -mpdclient_cmd_add_path(mpdclient_t *c, const gchar *path_utf8) +mpdclient_cmd_add_path(struct mpdclient *c, const gchar *path_utf8) { if (MPD_ERROR(c)) return -1; - mpd_sendAddCommand(c->connection, path_utf8); + mpd_send_add(c->connection, path_utf8); return mpdclient_finish_command(c); } gint -mpdclient_cmd_add(mpdclient_t *c, const struct mpd_song *song) +mpdclient_cmd_add(struct mpdclient *c, const struct mpd_song *song) { gint retval = 0; if (MPD_ERROR(c)) return -1; - if( !song || !song->file ) + if (song == NULL) return -1; /* send the add command to mpd */ - mpd_sendAddCommand(c->connection, song->file); + mpd_send_add(c->connection, mpd_song_get_uri(song)); if( (retval=mpdclient_finish_command(c)) ) return retval; @@ -577,15 +413,13 @@ mpdclient_cmd_add(mpdclient_t *c, const struct mpd_song *song) /* 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 idx) +mpdclient_cmd_delete(struct mpdclient *c, gint idx) { gint retval = 0; struct mpd_song *song; @@ -599,11 +433,7 @@ mpdclient_cmd_delete(mpdclient_t *c, gint idx) song = playlist_get(&c->playlist, idx); /* send the delete command to mpd */ -#ifdef ENABLE_SONG_ID - mpd_sendDeleteIdCommand(c->connection, song->id); -#else - mpd_sendDeleteCommand(c->connection, idx); -#endif + mpd_send_delete_id(c->connection, mpd_song_get_id(song)); if( (retval=mpdclient_finish_command(c)) ) return retval; @@ -618,22 +448,17 @@ mpdclient_cmd_delete(mpdclient_t *c, gint idx) mpdclient_playlist_callback(c, PLAYLIST_EVENT_DELETE, (gpointer) song); /* remove references to the song */ - if (c->song == song) { + if (c->song == song) c->song = NULL; - c->need_update = TRUE; - } - - mpd_freeSong(song); -#else - c->need_update = TRUE; + mpd_song_free(song); #endif return 0; } gint -mpdclient_cmd_move(mpdclient_t *c, gint old_index, gint new_index) +mpdclient_cmd_move(struct mpdclient *c, gint old_index, gint new_index) { gint n; struct mpd_song *song1, *song2; @@ -649,11 +474,8 @@ mpdclient_cmd_move(mpdclient_t *c, gint old_index, gint new_index) song2 = playlist_get(&c->playlist, new_index); /* send the move command to mpd */ -#ifdef ENABLE_SONG_ID - mpd_sendSwapIdCommand(c->connection, song1->id, song2->id); -#else - mpd_sendMoveCommand(c->connection, old_index, new_index); -#endif + mpd_send_swap_id(c->connection, + mpd_song_get_id(song1), mpd_song_get_id(song2)); if( (n=mpdclient_finish_command(c)) ) return n; @@ -663,9 +485,6 @@ mpdclient_cmd_move(mpdclient_t *c, gint old_index, gint new_index) /* increment the playlist id, so we don't retrieve a new playlist */ c->playlist.id++; - -#else - c->need_update = TRUE; #endif /* call playlist updated callback */ @@ -675,39 +494,38 @@ mpdclient_cmd_move(mpdclient_t *c, gint old_index, gint new_index) } gint -mpdclient_cmd_save_playlist(mpdclient_t *c, const gchar *filename_utf8) +mpdclient_cmd_save_playlist(struct mpdclient *c, const gchar *filename_utf8) { gint retval = 0; if (MPD_ERROR(c)) return -1; - mpd_sendSaveCommand(c->connection, filename_utf8); + mpd_send_save(c->connection, filename_utf8); if ((retval = mpdclient_finish_command(c)) == 0) mpdclient_browse_callback(c, BROWSE_PLAYLIST_SAVED, NULL); return retval; } gint -mpdclient_cmd_load_playlist(mpdclient_t *c, const gchar *filename_utf8) +mpdclient_cmd_load_playlist(struct mpdclient *c, const gchar *filename_utf8) { if (MPD_ERROR(c)) return -1; - mpd_sendLoadCommand(c->connection, filename_utf8); - c->need_update = TRUE; + mpd_send_load(c->connection, filename_utf8); return mpdclient_finish_command(c); } gint -mpdclient_cmd_delete_playlist(mpdclient_t *c, const gchar *filename_utf8) +mpdclient_cmd_delete_playlist(struct mpdclient *c, const gchar *filename_utf8) { gint retval = 0; if (MPD_ERROR(c)) return -1; - mpd_sendRmCommand(c->connection, filename_utf8); + mpd_send_rm(c->connection, filename_utf8); if ((retval = mpdclient_finish_command(c)) == 0) mpdclient_browse_callback(c, BROWSE_PLAYLIST_DELETED, NULL); return retval; @@ -719,7 +537,7 @@ mpdclient_cmd_delete_playlist(mpdclient_t *c, const gchar *filename_utf8) /****************************************************************************/ static void -do_list_callbacks(mpdclient_t *c, GList *list, gint event, gpointer data) +do_list_callbacks(struct mpdclient *c, GList *list, gint event, gpointer data) { while (list) { mpdc_list_cb_t fn = list->data; @@ -730,50 +548,50 @@ do_list_callbacks(mpdclient_t *c, GList *list, gint event, gpointer data) } void -mpdclient_playlist_callback(mpdclient_t *c, int event, gpointer data) +mpdclient_playlist_callback(struct mpdclient *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) +mpdclient_install_playlist_callback(struct mpdclient *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) +mpdclient_remove_playlist_callback(struct mpdclient *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) +mpdclient_browse_callback(struct mpdclient *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) +mpdclient_install_browse_callback(struct mpdclient *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) +mpdclient_remove_browse_callback(struct mpdclient *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) +mpdclient_install_error_callback(struct mpdclient *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) +mpdclient_remove_error_callback(struct mpdclient *c, mpdc_error_cb_t cb) { c->error_callbacks = g_list_remove(c->error_callbacks, cb); } @@ -784,62 +602,63 @@ mpdclient_remove_error_callback(mpdclient_t *c, mpdc_error_cb_t cb) /****************************************************************************/ /* update playlist */ -gint -mpdclient_playlist_update(mpdclient_t *c) +bool +mpdclient_playlist_update(struct mpdclient *c) { - mpd_InfoEntity *entity; + struct mpd_entity *entity; if (MPD_ERROR(c)) - return -1; + return false; playlist_clear(&c->playlist); - mpd_sendPlaylistInfoCommand(c->connection,-1); - while ((entity = mpd_getNextInfoEntity(c->connection))) { - if (entity->type == MPD_INFO_ENTITY_TYPE_SONG) - playlist_append(&c->playlist, entity->info.song); + mpd_send_list_queue_meta(c->connection); + while ((entity = mpd_recv_entity(c->connection))) { + if (mpd_entity_get_type(entity) == MPD_ENTITY_TYPE_SONG) + playlist_append(&c->playlist, mpd_entity_get_song(entity)); - mpd_freeInfoEntity(entity); + mpd_entity_free(entity); } - c->playlist.id = c->status->playlist; + c->playlist.id = mpd_status_get_queue_version(c->status); c->song = NULL; /* call playlist updated callbacks */ mpdclient_playlist_callback(c, PLAYLIST_EVENT_UPDATED, NULL); - return mpdclient_finish_command(c); + return mpdclient_finish_command(c) == 0; } -#ifdef ENABLE_PLCHANGES - /* update playlist (plchanges) */ -gint -mpdclient_playlist_update_changes(mpdclient_t *c) +bool +mpdclient_playlist_update_changes(struct mpdclient *c) { - mpd_InfoEntity *entity; + struct mpd_song *song; + guint length; if (MPD_ERROR(c)) - return -1; + return false; - mpd_sendPlChangesCommand(c->connection, c->playlist.id); + mpd_send_queue_changes_meta(c->connection, c->playlist.id); - while ((entity = mpd_getNextInfoEntity(c->connection)) != NULL) { - struct mpd_song *song = entity->info.song; + while ((song = mpd_recv_song(c->connection)) != NULL) { + int pos = mpd_song_get_pos(song); - if (song->pos >= 0 && (guint)song->pos < c->playlist.list->len) { + if (pos >= 0 && (guint)pos < c->playlist.list->len) { /* update song */ - playlist_replace(&c->playlist, song->pos, song); + playlist_replace(&c->playlist, pos, song); } else { /* add a new song */ playlist_append(&c->playlist, song); } - mpd_freeInfoEntity(entity); + mpd_song_free(song); } /* remove trailing songs */ - while ((guint)c->status->playlistLength < c->playlist.list->len) { + + length = mpd_status_get_queue_length(c->status); + while (length < c->playlist.list->len) { guint pos = c->playlist.list->len - 1; /* Remove the last playlist entry */ @@ -847,44 +666,35 @@ mpdclient_playlist_update_changes(mpdclient_t *c) } c->song = NULL; - c->playlist.id = c->status->playlist; + c->playlist.id = mpd_status_get_queue_version(c->status); mpdclient_playlist_callback(c, PLAYLIST_EVENT_UPDATED, NULL); - return 0; -} - -#else -gint -mpdclient_playlist_update_changes(mpdclient_t *c) -{ - return mpdclient_playlist_update(c); + return mpdclient_finish_command(c) == 0; } -#endif /****************************************************************************/ /*** Filelist functions *****************************************************/ /****************************************************************************/ -mpdclient_filelist_t * -mpdclient_filelist_get(mpdclient_t *c, const gchar *path) +struct filelist * +mpdclient_filelist_get(struct mpdclient *c, const gchar *path) { - mpdclient_filelist_t *filelist; - mpd_InfoEntity *entity; + struct filelist *filelist; + struct mpd_entity *entity; if (MPD_ERROR(c)) return NULL; - mpd_sendLsInfoCommand(c->connection, path); + mpd_send_list_meta(c->connection, path); filelist = filelist_new(); if (path && path[0] && strcmp(path, "/")) /* add a dummy entry for ./.. */ filelist_append(filelist, NULL); - while ((entity=mpd_getNextInfoEntity(c->connection))) { + while ((entity = mpd_recv_entity(c->connection)) != NULL) filelist_append(filelist, entity); - } /* If there's an error, ignore it. We'll return an empty filelist. */ mpdclient_finish_command(c); @@ -894,25 +704,15 @@ mpdclient_filelist_get(mpdclient_t *c, const gchar *path) return filelist; } -mpdclient_filelist_t * -mpdclient_filelist_search(mpdclient_t *c, - int exact_match, - int table, - gchar *filter_utf8) +static struct filelist * +mpdclient_recv_filelist_response(struct mpdclient *c) { - mpdclient_filelist_t *filelist; - mpd_InfoEntity *entity; + struct filelist *filelist; + struct mpd_entity *entity; - if (MPD_ERROR(c)) - return NULL; - - if (exact_match) - mpd_sendFindCommand(c->connection, table, filter_utf8); - else - mpd_sendSearchCommand(c->connection, table, filter_utf8); filelist = filelist_new(); - while ((entity=mpd_getNextInfoEntity(c->connection))) + while ((entity = mpd_recv_entity(c->connection)) != NULL) filelist_append(filelist, entity); if (mpdclient_finish_command(c)) { @@ -923,8 +723,25 @@ mpdclient_filelist_search(mpdclient_t *c, return filelist; } +struct filelist * +mpdclient_filelist_search(struct mpdclient *c, + int exact_match, + enum mpd_tag_type tag, + gchar *filter_utf8) +{ + if (MPD_ERROR(c)) + return NULL; + + mpd_search_db_songs(c->connection, exact_match); + mpd_search_add_tag_constraint(c->connection, MPD_OPERATOR_DEFAULT, + tag, filter_utf8); + mpd_search_commit(c->connection); + + return mpdclient_recv_filelist_response(c); +} + int -mpdclient_filelist_add_all(mpdclient_t *c, mpdclient_filelist_t *fl) +mpdclient_filelist_add_all(struct mpdclient *c, struct filelist *fl) { guint i; @@ -934,35 +751,44 @@ mpdclient_filelist_add_all(mpdclient_t *c, mpdclient_filelist_t *fl) if (filelist_is_empty(fl)) return 0; - mpd_sendCommandListBegin(c->connection); + mpd_command_list_begin(c->connection, false); for (i = 0; i < filelist_length(fl); ++i) { - filelist_entry_t *entry = filelist_get(fl, i); - mpd_InfoEntity *entity = entry->entity; + struct filelist_entry *entry = filelist_get(fl, i); + struct mpd_entity *entity = entry->entity; - if (entity && entity->type == MPD_INFO_ENTITY_TYPE_SONG) { - struct mpd_song *song = entity->info.song; + if (entity != NULL && + mpd_entity_get_type(entity) == MPD_ENTITY_TYPE_SONG) { + const struct mpd_song *song = + mpd_entity_get_song(entity); + const char *uri = mpd_song_get_uri(song); - mpd_sendAddCommand(c->connection, song->file); + if (uri != NULL) + mpd_send_add(c->connection, uri); } } - mpd_sendCommandListEnd(c->connection); + mpd_command_list_end(c->connection); return mpdclient_finish_command(c); } GList * -mpdclient_get_artists(mpdclient_t *c) +mpdclient_get_artists(struct mpdclient *c) { - gchar *str = NULL; GList *list = NULL; + struct mpd_pair *pair; if (MPD_ERROR(c)) return NULL; - mpd_sendListCommand(c->connection, MPD_TABLE_ARTIST, NULL); - while ((str = mpd_getNextArtist(c->connection))) - list = g_list_append(list, (gpointer) str); + mpd_search_db_tags(c->connection, MPD_TAG_ARTIST); + mpd_search_commit(c->connection); + + while ((pair = mpd_recv_pair_tag(c->connection, + MPD_TAG_ARTIST)) != NULL) { + list = g_list_append(list, g_strdup(pair->value)); + mpd_return_pair(c->connection, pair); + } if (mpdclient_finish_command(c)) return string_list_free(list); @@ -971,17 +797,26 @@ mpdclient_get_artists(mpdclient_t *c) } GList * -mpdclient_get_albums(mpdclient_t *c, const gchar *artist_utf8) +mpdclient_get_albums(struct mpdclient *c, const gchar *artist_utf8) { - gchar *str = NULL; GList *list = NULL; + struct mpd_pair *pair; if (MPD_ERROR(c)) return NULL; - mpd_sendListCommand(c->connection, MPD_TABLE_ALBUM, artist_utf8); - while ((str = mpd_getNextAlbum(c->connection))) - list = g_list_append(list, (gpointer) str); + mpd_search_db_tags(c->connection, MPD_TAG_ALBUM); + if (artist_utf8 != NULL) + mpd_search_add_tag_constraint(c->connection, + MPD_OPERATOR_DEFAULT, + MPD_TAG_ARTIST, artist_utf8); + mpd_search_commit(c->connection); + + while ((pair = mpd_recv_pair_tag(c->connection, + MPD_TAG_ALBUM)) != NULL) { + list = g_list_append(list, g_strdup(pair->value)); + mpd_return_pair(c->connection, pair); + } if (mpdclient_finish_command(c)) return string_list_free(list);