X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fmpdclient.c;h=1e01486a27c8c65bffcfaead13f95a08612a7eaa;hb=f8b97dde278b3f8bb5c996852bfa22e27d40f7ef;hp=1c21785e2054807c6876bac310906f313663a064;hpb=cff9790ef2756708af32dc43ec298126e25a78ca;p=ncmpc.git diff --git a/src/mpdclient.c b/src/mpdclient.c index 1c21785..1e01486 100644 --- a/src/mpdclient.c +++ b/src/mpdclient.c @@ -1,21 +1,21 @@ /* ncmpc (Ncurses MPD Client) - * (c) 2004-2009 The Music Player Daemon Project + * (c) 2004-2010 The Music Player Daemon Project * Project homepage: http://musicpd.org - + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ + */ #include "mpdclient.h" #include "filelist.h" @@ -24,6 +24,7 @@ #include "options.h" #include "strfsong.h" #include "utils.h" +#include "gidle.h" #include @@ -34,60 +35,24 @@ #define BUFSIZE 1024 -static bool -MPD_ERROR(const struct mpdclient *client) -{ - return !mpdclient_is_connected(client) || - mpd_connection_get_error(client->connection) != MPD_ERROR_SUCCESS; -} - -/* filelist sorting functions */ -static gint -compare_filelistentry(gconstpointer filelist_entry1, - gconstpointer filelist_entry2) -{ - const struct mpd_entity *e1, *e2; - int n = 0; - - e1 = ((const struct filelist_entry *)filelist_entry1)->entity; - e2 = ((const struct filelist_entry *)filelist_entry2)->entity; - - 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_ENTITY_TYPE_SONG: - break; - 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; -} - -/* sort by list-format */ +/* sort by song format */ gint compare_filelistentry_format(gconstpointer filelist_entry1, - gconstpointer filelist_entry2) + gconstpointer filelist_entry2, + const char *song_format) { - const struct mpd_entity *e1, *e2; - char key1[BUFSIZE], key2[BUFSIZE]; - int n = 0; - - e1 = ((const struct filelist_entry *)filelist_entry1)->entity; - e2 = ((const struct filelist_entry *)filelist_entry2)->entity; + const struct mpd_entity *e1 = + ((const struct filelist_entry *)filelist_entry1)->entity; + const struct mpd_entity *e2 = + ((const struct filelist_entry *)filelist_entry2)->entity; + int n = 0; if (e1 && e2 && 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)); + char key1[BUFSIZE], key2[BUFSIZE]; + strfsong(key1, BUFSIZE, song_format, mpd_entity_get_song(e1)); + strfsong(key2, BUFSIZE, song_format, mpd_entity_get_song(e2)); n = strcmp(key1,key2); } @@ -119,19 +84,10 @@ mpdclient_handle_error(struct mpdclient *c) return false; } -static bool -mpdclient_finish_command(struct mpdclient *c) -{ - return mpd_response_finish(c->connection) - ? true : mpdclient_handle_error(c); -} - struct mpdclient * mpdclient_new(void) { - struct mpdclient *c; - - c = g_new0(struct mpdclient, 1); + struct mpdclient *c = g_new0(struct mpdclient, 1); playlist_init(&c->playlist); c->volume = -1; c->events = 0; @@ -152,8 +108,16 @@ mpdclient_free(struct mpdclient *c) void mpdclient_disconnect(struct mpdclient *c) { - if (c->connection) + if (c->source != NULL) { + mpd_glib_free(c->source); + c->source = NULL; + c->idle = false; + } + + if (c->connection) { mpd_connection_free(c->connection); + ++c->connection_id; + } c->connection = NULL; if (c->status) @@ -164,21 +128,24 @@ mpdclient_disconnect(struct mpdclient *c) if (c->song) c->song = NULL; + + /* everything has changed after a disconnect */ + c->events |= MPD_IDLE_ALL; } bool mpdclient_connect(struct mpdclient *c, const gchar *host, gint port, - gfloat _timeout, + unsigned timeout_ms, const gchar *password) { /* close any open connection */ - if( c->connection ) + if (c->connection) mpdclient_disconnect(c); /* connect to MPD */ - c->connection = mpd_connection_new(host, port, _timeout * 1000); + c->connection = mpd_connection_new(host, port, timeout_ms); if (c->connection == NULL) g_error("Out of memory"); @@ -195,33 +162,37 @@ mpdclient_connect(struct mpdclient *c, return false; } + ++c->connection_id; + return true; } bool mpdclient_update(struct mpdclient *c) { - bool retval; + struct mpd_connection *connection = mpdclient_get_connection(c); c->volume = -1; - if (MPD_ERROR(c)) + if (connection == NULL) return false; - /* always announce these options as long as we don't have real + /* always announce these options as long as we don't have "idle" support */ - c->events |= MPD_IDLE_PLAYER|MPD_IDLE_OPTIONS; + if (c->source == NULL) + c->events |= MPD_IDLE_PLAYER|MPD_IDLE_OPTIONS; /* free the old status */ if (c->status) mpd_status_free(c->status); /* retrieve new status */ - c->status = mpd_run_status(c->connection); + c->status = mpd_run_status(connection); if (c->status == NULL) return mpdclient_handle_error(c); - if (c->update_id != mpd_status_get_update_id(c->status)) { + if (c->source == NULL && + c->update_id != mpd_status_get_update_id(c->status)) { c->events |= MPD_IDLE_UPDATE; if (c->update_id > 0) @@ -230,83 +201,100 @@ mpdclient_update(struct mpdclient *c) c->update_id = mpd_status_get_update_id(c->status); - if (c->volume != mpd_status_get_volume(c->status)) + if (c->source == NULL && + c->volume != mpd_status_get_volume(c->status)) c->events |= MPD_IDLE_MIXER; c->volume = mpd_status_get_volume(c->status); /* check if the playlist needs an update */ if (c->playlist.version != mpd_status_get_queue_version(c->status)) { - c->events |= MPD_IDLE_PLAYLIST; + bool retval; + + if (c->source == NULL) + c->events |= MPD_IDLE_QUEUE; if (!playlist_is_empty(&c->playlist)) retval = mpdclient_playlist_update_changes(c); else retval = mpdclient_playlist_update(c); - } else - retval = true; + if (!retval) + return false; + } /* update the current song */ - if (!c->song || mpd_status_get_song_id(c->status)) { + if (!c->song || mpd_status_get_song_id(c->status) >= 0) { c->song = playlist_get_song(&c->playlist, mpd_status_get_song_pos(c->status)); } - return retval; + return true; } +struct mpd_connection * +mpdclient_get_connection(struct mpdclient *c) +{ + if (c->source != NULL && c->idle) { + c->idle = false; + mpd_glib_leave(c->source); + } -/****************************************************************************/ -/*** MPD Commands **********************************************************/ -/****************************************************************************/ + return c->connection; +} -bool -mpdclient_cmd_play(struct mpdclient *c, gint idx) +void +mpdclient_put_connection(struct mpdclient *c) { - const struct mpd_song *song = playlist_get_song(&c->playlist, idx); + assert(c->source == NULL || c->connection != NULL); - if (MPD_ERROR(c)) - return false; + if (c->source != NULL && !c->idle) { + c->idle = mpd_glib_enter(c->source); + } +} - if (song) - mpd_send_play_id(c->connection, mpd_song_get_id(song)); - else - mpd_send_play(c->connection); +static struct mpd_status * +mpdclient_recv_status(struct mpdclient *c) +{ + assert(c->connection != NULL); - return mpdclient_finish_command(c); + struct mpd_status *status = mpd_recv_status(c->connection); + if (status == NULL) { + mpdclient_handle_error(c); + return NULL; + } + + if (c->status != NULL) + mpd_status_free(c->status); + return c->status = status; } +/****************************************************************************/ +/*** MPD Commands **********************************************************/ +/****************************************************************************/ + bool mpdclient_cmd_crop(struct mpdclient *c) { - struct mpd_status *status; - bool playing; - int length, current; - - if (MPD_ERROR(c)) + if (!mpdclient_is_playing(c)) return false; - status = mpd_run_status(c->connection); - if (status == NULL) - return mpdclient_handle_error(c); - - 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_status_free(status); - - if (!playing || length < 2) + int length = mpd_status_get_queue_length(c->status); + int current = mpd_status_get_song_pos(c->status); + if (current < 0 || mpd_status_get_queue_length(c->status) < 2) return true; - mpd_command_list_begin(c->connection, false); + struct mpd_connection *connection = mpdclient_get_connection(c); + if (connection == NULL) + return false; + + mpd_command_list_begin(connection, false); - while (--length >= 0) - if (length != current) - mpd_send_delete(c->connection, length); + if (current < length - 1) + mpd_send_delete_range(connection, current + 1, length); + if (current > 0) + mpd_send_delete_range(connection, 0, current); - mpd_command_list_end(c->connection); + mpd_command_list_end(connection); return mpdclient_finish_command(c); } @@ -314,34 +302,57 @@ mpdclient_cmd_crop(struct mpdclient *c) bool mpdclient_cmd_clear(struct mpdclient *c) { - bool retval; + struct mpd_connection *connection = mpdclient_get_connection(c); + if (connection == NULL) + return false; + + /* send "clear" and "status" */ + if (!mpd_command_list_begin(connection, false) || + !mpd_send_clear(connection) || + !mpd_send_status(connection) || + !mpd_command_list_end(connection)) + return mpdclient_handle_error(c); + + /* receive the new status, store it in the mpdclient struct */ - if (MPD_ERROR(c)) + struct mpd_status *status = mpdclient_recv_status(c); + if (status == NULL) return false; - mpd_send_clear(c->connection); - retval = mpdclient_finish_command(c); + if (!mpd_response_finish(connection)) + return mpdclient_handle_error(c); + + /* update mpdclient.playlist */ - if (retval) - c->events |= MPD_IDLE_PLAYLIST; + if (mpd_status_get_queue_length(status) == 0) { + /* after the "clear" command, the queue is really + empty - this means we can clear it locally, + reducing the UI latency */ + playlist_clear(&c->playlist); + c->playlist.version = mpd_status_get_queue_version(status); + c->song = NULL; + } - return retval; + c->events |= MPD_IDLE_QUEUE; + return true; } bool mpdclient_cmd_volume(struct mpdclient *c, gint value) { - if (MPD_ERROR(c)) + struct mpd_connection *connection = mpdclient_get_connection(c); + if (connection == NULL) return false; - mpd_send_set_volume(c->connection, value); + mpd_send_set_volume(connection, value); return mpdclient_finish_command(c); } bool mpdclient_cmd_volume_up(struct mpdclient *c) { - if (MPD_ERROR(c)) + struct mpd_connection *connection = mpdclient_get_connection(c); + if (connection == NULL) return false; if (c->status == NULL || @@ -360,7 +371,8 @@ mpdclient_cmd_volume_up(struct mpdclient *c) bool mpdclient_cmd_volume_down(struct mpdclient *c) { - if (MPD_ERROR(c)) + struct mpd_connection *connection = mpdclient_get_connection(c); + if (connection == NULL) return false; if (c->status == NULL || mpd_status_get_volume(c->status) < 0) @@ -378,56 +390,52 @@ mpdclient_cmd_volume_down(struct mpdclient *c) bool mpdclient_cmd_add_path(struct mpdclient *c, const gchar *path_utf8) { - if (MPD_ERROR(c)) + struct mpd_connection *connection = mpdclient_get_connection(c); + if (connection == NULL) return false; - mpd_send_add(c->connection, path_utf8); - return mpdclient_finish_command(c); + return mpd_send_add(connection, path_utf8)? + mpdclient_finish_command(c) : false; } bool mpdclient_cmd_add(struct mpdclient *c, const struct mpd_song *song) { - struct mpd_status *status; - struct mpd_song *new_song; - assert(c != NULL); assert(song != NULL); - if (MPD_ERROR(c) || c->status == NULL) + struct mpd_connection *connection = mpdclient_get_connection(c); + if (connection == NULL || c->status == NULL) return false; /* send the add command to mpd; at the same time, get the new status (to verify the new playlist id) and the last song (we hope that's the song we just added) */ - if (!mpd_command_list_begin(c->connection, true) || - !mpd_send_add(c->connection, mpd_song_get_uri(song)) || - !mpd_send_status(c->connection) || - !mpd_send_get_queue_song_pos(c->connection, + if (!mpd_command_list_begin(connection, true) || + !mpd_send_add(connection, mpd_song_get_uri(song)) || + !mpd_send_status(connection) || + !mpd_send_get_queue_song_pos(connection, playlist_length(&c->playlist)) || - !mpd_command_list_end(c->connection) || - !mpd_response_next(c->connection)) + !mpd_command_list_end(connection) || + !mpd_response_next(connection)) return mpdclient_handle_error(c); - c->events |= MPD_IDLE_PLAYLIST; + c->events |= MPD_IDLE_QUEUE; - status = mpd_recv_status(c->connection); - if (status != NULL) { - if (c->status != NULL) - mpd_status_free(c->status); - c->status = status; - } + struct mpd_status *status = mpdclient_recv_status(c); + if (status == NULL) + return false; - if (!mpd_response_next(c->connection)) + if (!mpd_response_next(connection)) return mpdclient_handle_error(c); - new_song = mpd_recv_song(c->connection); - if (!mpd_response_finish(c->connection) || new_song == NULL) { + struct mpd_song *new_song = mpd_recv_song(connection); + if (!mpd_response_finish(connection) || new_song == NULL) { if (new_song != NULL) mpd_song_free(new_song); - return mpd_connection_clear_error(c->connection) || + return mpd_connection_clear_error(connection) || mpdclient_handle_error(c); } @@ -451,36 +459,32 @@ mpdclient_cmd_add(struct mpdclient *c, const struct mpd_song *song) bool mpdclient_cmd_delete(struct mpdclient *c, gint idx) { - const struct mpd_song *song; - struct mpd_status *status; + struct mpd_connection *connection = mpdclient_get_connection(c); - if (MPD_ERROR(c) || c->status == NULL) + if (connection == NULL || c->status == NULL) return false; if (idx < 0 || (guint)idx >= playlist_length(&c->playlist)) return false; - song = playlist_get(&c->playlist, idx); + const struct mpd_song *song = playlist_get(&c->playlist, idx); /* send the delete command to mpd; at the same time, get the new status (to verify the playlist id) */ - if (!mpd_command_list_begin(c->connection, false) || - !mpd_send_delete_id(c->connection, mpd_song_get_id(song)) || - !mpd_send_status(c->connection) || - !mpd_command_list_end(c->connection)) + if (!mpd_command_list_begin(connection, false) || + !mpd_send_delete_id(connection, mpd_song_get_id(song)) || + !mpd_send_status(connection) || + !mpd_command_list_end(connection)) return mpdclient_handle_error(c); - c->events |= MPD_IDLE_PLAYLIST; + c->events |= MPD_IDLE_QUEUE; - status = mpd_recv_status(c->connection); - if (status != NULL) { - if (c->status != NULL) - mpd_status_free(c->status); - c->status = status; - } + struct mpd_status *status = mpdclient_recv_status(c); + if (status == NULL) + return false; - if (!mpd_response_finish(c->connection)) + if (!mpd_response_finish(connection)) return mpdclient_handle_error(c); if (mpd_status_get_queue_length(status) == playlist_length(&c->playlist) - 1 && @@ -501,60 +505,34 @@ mpdclient_cmd_delete(struct mpdclient *c, gint idx) return true; } -/** - * Fallback for mpdclient_cmd_delete_range() on MPD older than 0.16. - * It emulates the "delete range" command with a list of simple - * "delete" commands. - */ -static bool -mpdclient_cmd_delete_range_fallback(struct mpdclient *c, - unsigned start, unsigned end) -{ - if (!mpd_command_list_begin(c->connection, false)) - return mpdclient_handle_error(c); - - for (; start < end; --end) - mpd_send_delete(c->connection, start); - - if (!mpd_command_list_end(c->connection) || - !mpd_response_finish(c->connection)) - return mpdclient_handle_error(c); - - return true; -} - bool mpdclient_cmd_delete_range(struct mpdclient *c, unsigned start, unsigned end) { - struct mpd_status *status; + if (end == start + 1) + /* if that's not really a range, we choose to use the + safer "deleteid" version */ + return mpdclient_cmd_delete(c, start); - if (MPD_ERROR(c)) + struct mpd_connection *connection = mpdclient_get_connection(c); + if (connection == NULL) return false; - if (mpd_connection_cmp_server_version(c->connection, 0, 16, 0) < 0) - return mpdclient_cmd_delete_range_fallback(c, start, end); - - /* MPD 0.16 supports "delete" with a range argument */ - /* send the delete command to mpd; at the same time, get the new status (to verify the playlist id) */ - if (!mpd_command_list_begin(c->connection, false) || - !mpd_send_delete_range(c->connection, start, end) || - !mpd_send_status(c->connection) || - !mpd_command_list_end(c->connection)) + if (!mpd_command_list_begin(connection, false) || + !mpd_send_delete_range(connection, start, end) || + !mpd_send_status(connection) || + !mpd_command_list_end(connection)) return mpdclient_handle_error(c); - c->events |= MPD_IDLE_PLAYLIST; + c->events |= MPD_IDLE_QUEUE; - status = mpd_recv_status(c->connection); - if (status != NULL) { - if (c->status != NULL) - mpd_status_free(c->status); - c->status = status; - } + struct mpd_status *status = mpdclient_recv_status(c); + if (status == NULL) + return false; - if (!mpd_response_finish(c->connection)) + if (!mpd_response_finish(connection)) return mpdclient_handle_error(c); if (mpd_status_get_queue_length(status) == playlist_length(&c->playlist) - (end - start) && @@ -580,41 +558,31 @@ mpdclient_cmd_delete_range(struct mpdclient *c, unsigned start, unsigned end) } bool -mpdclient_cmd_move(struct mpdclient *c, gint old_index, gint new_index) +mpdclient_cmd_move(struct mpdclient *c, unsigned dest_pos, unsigned src_pos) { - const struct mpd_song *song1, *song2; - struct mpd_status *status; - - if (MPD_ERROR(c)) - return false; + if (dest_pos == src_pos) + return true; - if (old_index == new_index || new_index < 0 || - (guint)new_index >= c->playlist.list->len) + struct mpd_connection *connection = mpdclient_get_connection(c); + if (connection == NULL) return false; - song1 = playlist_get(&c->playlist, old_index); - song2 = playlist_get(&c->playlist, new_index); - - /* send the delete command to mpd; at the same time, get the + /* send the "move" command to MPD; at the same time, get the new status (to verify the playlist id) */ - if (!mpd_command_list_begin(c->connection, false) || - !mpd_send_swap_id(c->connection, mpd_song_get_id(song1), - mpd_song_get_id(song2)) || - !mpd_send_status(c->connection) || - !mpd_command_list_end(c->connection)) + if (!mpd_command_list_begin(connection, false) || + !mpd_send_move(connection, src_pos, dest_pos) || + !mpd_send_status(connection) || + !mpd_command_list_end(connection)) return mpdclient_handle_error(c); - c->events |= MPD_IDLE_PLAYLIST; + c->events |= MPD_IDLE_QUEUE; - status = mpd_recv_status(c->connection); - if (status != NULL) { - if (c->status != NULL) - mpd_status_free(c->status); - c->status = status; - } + struct mpd_status *status = mpdclient_recv_status(c); + if (status == NULL) + return false; - if (!mpd_response_finish(c->connection)) + if (!mpd_response_finish(connection)) return mpdclient_handle_error(c); if (mpd_status_get_queue_length(status) == playlist_length(&c->playlist) && @@ -625,12 +593,82 @@ mpdclient_cmd_move(struct mpdclient *c, gint old_index, gint new_index) c->playlist.version = mpd_status_get_queue_version(status); /* swap songs in the local playlist */ - playlist_swap(&c->playlist, old_index, new_index); + playlist_move(&c->playlist, dest_pos, src_pos); } return true; } +#if LIBMPDCLIENT_CHECK_VERSION(2,5,0) +/* The client-to-client protocol (MPD 0.17.0) */ + +bool +mpdclient_cmd_subscribe(struct mpdclient *c, const char *channel) +{ + struct mpd_connection *connection = mpdclient_get_connection(c); + + if (connection == NULL) + return false; + + if (!mpd_send_subscribe(connection, channel)) + return mpdclient_handle_error(c); + + return mpdclient_finish_command(c); +} + +bool +mpdclient_cmd_unsubscribe(struct mpdclient *c, const char *channel) +{ + struct mpd_connection *connection = mpdclient_get_connection(c); + if (connection == NULL) + return false; + + if (!mpd_send_unsubscribe(connection, channel)) + return mpdclient_handle_error(c); + + return mpdclient_finish_command(c); +} + +bool +mpdclient_cmd_send_message(struct mpdclient *c, const char *channel, + const char *text) +{ + struct mpd_connection *connection = mpdclient_get_connection(c); + if (connection == NULL) + return false; + + if (!mpd_send_send_message(connection, channel, text)) + return mpdclient_handle_error(c); + + return mpdclient_finish_command(c); +} + +bool +mpdclient_send_read_messages(struct mpdclient *c) +{ + struct mpd_connection *connection = mpdclient_get_connection(c); + if (connection == NULL) + return false; + + return mpd_send_read_messages(connection)? + true : mpdclient_handle_error(c); +} + +struct mpd_message * +mpdclient_recv_message(struct mpdclient *c) +{ + struct mpd_connection *connection = mpdclient_get_connection(c); + if (connection == NULL) + return false; + + struct mpd_message *message = mpd_recv_message(connection); + if (message == NULL && + mpd_connection_get_error(connection) != MPD_ERROR_SUCCESS) + mpdclient_handle_error(c); + + return message; +} +#endif /****************************************************************************/ /*** Playlist management functions ******************************************/ @@ -640,15 +678,16 @@ mpdclient_cmd_move(struct mpdclient *c, gint old_index, gint new_index) bool mpdclient_playlist_update(struct mpdclient *c) { - struct mpd_entity *entity; - - if (MPD_ERROR(c)) + struct mpd_connection *connection = mpdclient_get_connection(c); + if (connection == NULL) return false; playlist_clear(&c->playlist); - mpd_send_list_queue_meta(c->connection); - while ((entity = mpd_recv_entity(c->connection))) { + mpd_send_list_queue_meta(connection); + + struct mpd_entity *entity; + while ((entity = mpd_recv_entity(connection))) { if (mpd_entity_get_type(entity) == MPD_ENTITY_TYPE_SONG) playlist_append(&c->playlist, mpd_entity_get_song(entity)); @@ -665,15 +704,15 @@ mpdclient_playlist_update(struct mpdclient *c) bool mpdclient_playlist_update_changes(struct mpdclient *c) { - struct mpd_song *song; - guint length; + struct mpd_connection *connection = mpdclient_get_connection(c); - if (MPD_ERROR(c)) + if (connection == NULL) return false; - mpd_send_queue_changes_meta(c->connection, c->playlist.version); + mpd_send_queue_changes_meta(connection, c->playlist.version); - while ((song = mpd_recv_song(c->connection)) != NULL) { + struct mpd_song *song; + while ((song = mpd_recv_song(connection)) != NULL) { int pos = mpd_song_get_pos(song); if (pos >= 0 && (guint)pos < c->playlist.list->len) { @@ -689,7 +728,7 @@ mpdclient_playlist_update_changes(struct mpdclient *c) /* remove trailing songs */ - length = mpd_status_get_queue_length(c->status); + unsigned length = mpd_status_get_queue_length(c->status); while (length < c->playlist.list->len) { guint pos = c->playlist.list->len - 1; @@ -708,73 +747,19 @@ mpdclient_playlist_update_changes(struct mpdclient *c) /*** Filelist functions *****************************************************/ /****************************************************************************/ -static struct filelist * -mpdclient_recv_filelist_response(struct mpdclient *c); - -struct filelist * -mpdclient_filelist_get(struct mpdclient *c, const gchar *path) -{ - struct filelist *filelist; - - if (MPD_ERROR(c)) - return NULL; - - mpd_send_list_meta(c->connection, path); - filelist = mpdclient_recv_filelist_response(c); - if (filelist == NULL) - return NULL; - - filelist_sort_dir_play(filelist, compare_filelistentry); - - return filelist; -} - -static struct filelist * -mpdclient_recv_filelist_response(struct mpdclient *c) -{ - struct filelist *filelist; - - filelist = filelist_new_recv(c->connection); - - if (!mpdclient_finish_command(c)) { - filelist_free(filelist); - return NULL; - } - - 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); -} - bool mpdclient_filelist_add_all(struct mpdclient *c, struct filelist *fl) { - guint i; - - if (MPD_ERROR(c)) + struct mpd_connection *connection = mpdclient_get_connection(c); + if (connection == NULL) return false; if (filelist_is_empty(fl)) return true; - mpd_command_list_begin(c->connection, false); + mpd_command_list_begin(connection, false); - for (i = 0; i < filelist_length(fl); ++i) { + for (unsigned i = 0; i < filelist_length(fl); ++i) { struct filelist_entry *entry = filelist_get(fl, i); struct mpd_entity *entity = entry->entity; @@ -782,65 +767,11 @@ mpdclient_filelist_add_all(struct mpdclient *c, struct filelist *fl) 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); - if (uri != NULL) - mpd_send_add(c->connection, uri); + mpd_send_add(connection, mpd_song_get_uri(song)); } } - mpd_command_list_end(c->connection); + mpd_command_list_end(connection); return mpdclient_finish_command(c); } - -GList * -mpdclient_get_artists(struct mpdclient *c) -{ - GList *list = NULL; - struct mpd_pair *pair; - - if (MPD_ERROR(c)) - return NULL; - - 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); - - return list; -} - -GList * -mpdclient_get_albums(struct mpdclient *c, const gchar *artist_utf8) -{ - GList *list = NULL; - struct mpd_pair *pair; - - if (MPD_ERROR(c)) - return NULL; - - 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); - - return list; -}