diff --git a/src/mpdclient.c b/src/mpdclient.c
index 933a14874772a6890e7cf8b44dde5407c4ebe6c4..1c21785e2054807c6876bac310906f313663a064 100644 (file)
--- a/src/mpdclient.c
+++ b/src/mpdclient.c
#include <time.h>
#include <string.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
-
#define BUFSIZE 1024
static bool
MPD_ERROR(const struct mpdclient *client)
{
- return client->connection == NULL ||
+ return !mpdclient_is_connected(client) ||
mpd_connection_get_error(client->connection) != MPD_ERROR_SUCCESS;
}
/*** mpdclient functions ****************************************************/
/****************************************************************************/
-gint
+bool
mpdclient_handle_error(struct mpdclient *c)
{
enum mpd_error error = mpd_connection_get_error(c->connection);
if (error == MPD_ERROR_SERVER &&
mpd_connection_get_server_error(c->connection) == MPD_SERVER_ERROR_PERMISSION &&
screen_auth(c))
- return 0;
+ return true;
- if (error == MPD_ERROR_SERVER)
- error = error | (mpd_connection_get_server_error(c->connection) << 8);
-
- 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));
- }
+ mpdclient_ui_error(mpd_connection_get_error_message(c->connection));
if (!mpd_connection_clear_error(c->connection))
mpdclient_disconnect(c);
- return error;
+ return false;
}
-static gint
+static bool
mpdclient_finish_command(struct mpdclient *c)
{
return mpd_response_finish(c->connection)
- ? 0 : mpdclient_handle_error(c);
+ ? true : mpdclient_handle_error(c);
}
struct mpdclient *
c = g_new0(struct mpdclient, 1);
playlist_init(&c->playlist);
- c->volume = MPD_STATUS_NO_VOLUME;
+ c->volume = -1;
+ c->events = 0;
return c;
}
mpdclient_playlist_free(&c->playlist);
- g_list_free(c->error_callbacks);
- g_list_free(c->playlist_callbacks);
- g_list_free(c->browse_callbacks);
g_free(c);
}
-gint
+void
mpdclient_disconnect(struct mpdclient *c)
{
if (c->connection)
if (c->song)
c->song = NULL;
-
- return 0;
}
-gint
+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);
g_error("Out of memory");
if (mpd_connection_get_error(c->connection) != MPD_ERROR_SUCCESS) {
- retval = mpdclient_handle_error(c);
- if (retval != 0) {
- mpd_connection_free(c->connection);
- c->connection = NULL;
- }
-
- return retval;
+ mpdclient_handle_error(c);
+ mpdclient_disconnect(c);
+ return false;
}
/* send password */
- if( password ) {
- mpd_send_password(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;
}
- return retval;
+ return true;
}
-gint
+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;
+
+ /* always announce these options as long as we don't have real
+ "idle" support */
+ c->events |= MPD_IDLE_PLAYER|MPD_IDLE_OPTIONS;
/* free the old status */
if (c->status)
if (c->status == NULL)
return mpdclient_handle_error(c);
- if (c->updatingdb &&
- c->updatingdb != mpd_status_get_update_id(c->status))
- mpdclient_browse_callback(c, BROWSE_DB_UPDATED, NULL);
+ if (c->update_id != mpd_status_get_update_id(c->status)) {
+ c->events |= MPD_IDLE_UPDATE;
+
+ if (c->update_id > 0)
+ c->events |= MPD_IDLE_DATABASE;
+ }
+
+ c->update_id = mpd_status_get_update_id(c->status);
+
+ if (c->volume != mpd_status_get_volume(c->status))
+ c->events |= MPD_IDLE_MIXER;
- c->updatingdb = 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 != mpd_status_get_queue_version(c->status)) {
+ if (c->playlist.version != mpd_status_get_queue_version(c->status)) {
+ c->events |= MPD_IDLE_PLAYLIST;
+
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 || mpd_status_get_song_id(c->status)) {
- c->song = playlist_get_song(c, mpd_status_get_song_pos(c->status));
+ c->song = playlist_get_song(&c->playlist,
+ mpd_status_get_song_pos(c->status));
}
return retval;
/*** MPD Commands **********************************************************/
/****************************************************************************/
-gint
+bool
mpdclient_cmd_play(struct mpdclient *c, gint idx)
{
- 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;
+ return false;
if (song)
mpd_send_play_id(c->connection, mpd_song_get_id(song));
return mpdclient_finish_command(c);
}
-gint
-mpdclient_cmd_pause(struct mpdclient *c, gint value)
-{
- if (MPD_ERROR(c))
- return -1;
-
- mpd_send_pause(c->connection, value);
- return mpdclient_finish_command(c);
-}
-
-gint
+bool
mpdclient_cmd_crop(struct mpdclient *c)
{
struct mpd_status *status;
int length, current;
if (MPD_ERROR(c))
- return -1;
+ return false;
status = mpd_run_status(c->connection);
if (status == NULL)
mpd_status_free(status);
if (!playing || length < 2)
- return 0;
+ return true;
mpd_command_list_begin(c->connection, false);
return mpdclient_finish_command(c);
}
-gint
-mpdclient_cmd_stop(struct mpdclient *c)
-{
- if (MPD_ERROR(c))
- return -1;
-
- mpd_send_stop(c->connection);
- return mpdclient_finish_command(c);
-}
-
-gint
-mpdclient_cmd_next(struct mpdclient *c)
-{
- if (MPD_ERROR(c))
- return -1;
-
- mpd_send_next(c->connection);
- return mpdclient_finish_command(c);
-}
-
-gint
-mpdclient_cmd_prev(struct mpdclient *c)
-{
- if (MPD_ERROR(c))
- return -1;
-
- mpd_send_previous(c->connection);
- return mpdclient_finish_command(c);
-}
-
-gint
-mpdclient_cmd_seek(struct mpdclient *c, gint id, gint pos)
-{
- if (MPD_ERROR(c))
- return -1;
-
- mpd_send_seek_id(c->connection, id, pos);
- return mpdclient_finish_command(c);
-}
-
-gint
-mpdclient_cmd_shuffle(struct mpdclient *c)
-{
- if (MPD_ERROR(c))
- return -1;
-
- mpd_send_shuffle(c->connection);
- return mpdclient_finish_command(c);
-}
-
-gint
-mpdclient_cmd_shuffle_range(struct mpdclient *c, guint start, guint end)
-{
- mpd_send_shuffle_range(c->connection, start, end);
- return mpdclient_finish_command(c);
-}
-
-gint
+bool
mpdclient_cmd_clear(struct mpdclient *c)
{
- gint retval = 0;
+ bool retval;
if (MPD_ERROR(c))
- return -1;
+ return false;
mpd_send_clear(c->connection);
retval = mpdclient_finish_command(c);
- /* call playlist updated callback */
- mpdclient_playlist_callback(c, PLAYLIST_EVENT_CLEAR, NULL);
- return retval;
-}
-
-gint
-mpdclient_cmd_repeat(struct mpdclient *c, gint value)
-{
- if (MPD_ERROR(c))
- return -1;
-
- mpd_send_repeat(c->connection, value);
- return mpdclient_finish_command(c);
-}
-
-gint
-mpdclient_cmd_random(struct mpdclient *c, gint value)
-{
- if (MPD_ERROR(c))
- return -1;
-
- mpd_send_random(c->connection, value);
- return mpdclient_finish_command(c);
-}
-
-gint
-mpdclient_cmd_single(struct mpdclient *c, gint value)
-{
- if (MPD_ERROR(c))
- return -1;
-
- mpd_send_single(c->connection, value);
- return mpdclient_finish_command(c);
-}
-
-gint
-mpdclient_cmd_consume(struct mpdclient *c, gint value)
-{
- if (MPD_ERROR(c))
- return -1;
- mpd_send_consume(c->connection, value);
- return mpdclient_finish_command(c);
-}
-
-gint
-mpdclient_cmd_crossfade(struct mpdclient *c, gint value)
-{
- if (MPD_ERROR(c))
- return -1;
+ if (retval)
+ c->events |= MPD_IDLE_PLAYLIST;
- mpd_send_crossfade(c->connection, value);
- return mpdclient_finish_command(c);
+ return retval;
}
-gint
+bool
mpdclient_cmd_volume(struct mpdclient *c, gint value)
{
if (MPD_ERROR(c))
- return -1;
+ return false;
mpd_send_set_volume(c->connection, value);
return mpdclient_finish_command(c);
}
-gint mpdclient_cmd_volume_up(struct mpdclient *c)
+bool
+mpdclient_cmd_volume_up(struct mpdclient *c)
{
if (MPD_ERROR(c))
- return -1;
+ return false;
if (c->status == NULL ||
- mpd_status_get_volume(c->status) == MPD_STATUS_NO_VOLUME)
- return 0;
+ mpd_status_get_volume(c->status) == -1)
+ return true;
- if (c->volume == MPD_STATUS_NO_VOLUME)
+ if (c->volume < 0)
c->volume = mpd_status_get_volume(c->status);
if (c->volume >= 100)
- return 0;
+ return true;
return mpdclient_cmd_volume(c, ++c->volume);
}
-gint mpdclient_cmd_volume_down(struct mpdclient *c)
+bool
+mpdclient_cmd_volume_down(struct mpdclient *c)
{
if (MPD_ERROR(c))
- return -1;
+ return false;
- if (c->status == NULL ||
- mpd_status_get_volume(c->status) == MPD_STATUS_NO_VOLUME)
- return 0;
+ if (c->status == NULL || mpd_status_get_volume(c->status) < 0)
+ return true;
- if (c->volume == MPD_STATUS_NO_VOLUME)
+ if (c->volume < 0)
c->volume = mpd_status_get_volume(c->status);
if (c->volume <= 0)
- return 0;
+ return true;
return mpdclient_cmd_volume(c, --c->volume);
}
-gint
+bool
mpdclient_cmd_add_path(struct mpdclient *c, const gchar *path_utf8)
{
if (MPD_ERROR(c))
- return -1;
+ return false;
mpd_send_add(c->connection, path_utf8);
return mpdclient_finish_command(c);
}
-gint
+bool
mpdclient_cmd_add(struct mpdclient *c, const struct mpd_song *song)
{
- gint retval = 0;
+ struct mpd_status *status;
+ struct mpd_song *new_song;
- if (MPD_ERROR(c))
- return -1;
+ assert(c != NULL);
+ assert(song != NULL);
+
+ if (MPD_ERROR(c) || 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,
+ playlist_length(&c->playlist)) ||
+ !mpd_command_list_end(c->connection) ||
+ !mpd_response_next(c->connection))
+ return mpdclient_handle_error(c);
- if (song == NULL)
- return -1;
+ c->events |= MPD_IDLE_PLAYLIST;
- /* send the add command to mpd */
- mpd_send_add(c->connection, mpd_song_get_uri(song));
- if( (retval=mpdclient_finish_command(c)) )
- return retval;
+ status = mpd_recv_status(c->connection);
+ if (status != NULL) {
+ if (c->status != NULL)
+ mpd_status_free(c->status);
+ c->status = status;
+ }
+
+ if (!mpd_response_next(c->connection))
+ return mpdclient_handle_error(c);
-#ifdef ENABLE_FANCY_PLAYLIST_MANAGMENT_CMD_ADD
- /* add the song to playlist */
- playlist_append(&c->playlist, song);
+ new_song = mpd_recv_song(c->connection);
+ if (!mpd_response_finish(c->connection) || new_song == NULL) {
+ if (new_song != NULL)
+ mpd_song_free(new_song);
- /* increment the playlist id, so we don't retrieve a new playlist */
- c->playlist.id++;
+ return mpd_connection_clear_error(c->connection) ||
+ mpdclient_handle_error(c);
+ }
+
+ if (mpd_status_get_queue_length(status) == playlist_length(&c->playlist) + 1 &&
+ mpd_status_get_queue_version(status) == c->playlist.version + 1) {
+ /* the cheap route: match on the new playlist length
+ and its version, we can keep our local playlist
+ copy in sync */
+ c->playlist.version = mpd_status_get_queue_version(status);
+
+ /* the song we just received has the correct id;
+ append it to the local playlist */
+ playlist_append(&c->playlist, new_song);
+ }
- /* call playlist updated callback */
- mpdclient_playlist_callback(c, PLAYLIST_EVENT_ADD, (gpointer) song);
-#endif
+ mpd_song_free(new_song);
- return 0;
+ return true;
}
-gint
+bool
mpdclient_cmd_delete(struct mpdclient *c, gint idx)
{
- gint retval = 0;
- struct mpd_song *song;
+ const struct mpd_song *song;
+ struct mpd_status *status;
- if (MPD_ERROR(c))
- return -1;
+ if (MPD_ERROR(c) || c->status == NULL)
+ return false;
if (idx < 0 || (guint)idx >= playlist_length(&c->playlist))
- return -1;
+ return false;
song = playlist_get(&c->playlist, idx);
- /* send the delete command to mpd */
- mpd_send_delete_id(c->connection, mpd_song_get_id(song));
- if( (retval=mpdclient_finish_command(c)) )
- return retval;
-
-#ifdef ENABLE_FANCY_PLAYLIST_MANAGMENT_CMD_DELETE
- /* increment the playlist id, so we don't retrieve a new playlist */
- c->playlist.id++;
-
- /* remove the song from the playlist */
- playlist_remove_reuse(&c->playlist, idx);
-
- /* call playlist updated callback */
- mpdclient_playlist_callback(c, PLAYLIST_EVENT_DELETE, (gpointer) song);
+ /* send the delete command to mpd; at the same time, get the
+ new status (to verify the playlist id) */
- /* remove references to the song */
- if (c->song == song)
- c->song = NULL;
+ 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))
+ return mpdclient_handle_error(c);
- mpd_song_free(song);
-#endif
+ c->events |= MPD_IDLE_PLAYLIST;
- return 0;
-}
+ status = mpd_recv_status(c->connection);
+ if (status != NULL) {
+ if (c->status != NULL)
+ mpd_status_free(c->status);
+ c->status = status;
+ }
-gint
-mpdclient_cmd_move(struct mpdclient *c, gint old_index, gint new_index)
-{
- gint n;
- struct mpd_song *song1, *song2;
+ if (!mpd_response_finish(c->connection))
+ return mpdclient_handle_error(c);
- if (MPD_ERROR(c))
- return -1;
+ if (mpd_status_get_queue_length(status) == playlist_length(&c->playlist) - 1 &&
+ mpd_status_get_queue_version(status) == c->playlist.version + 1) {
+ /* the cheap route: match on the new playlist length
+ and its version, we can keep our local playlist
+ copy in sync */
+ c->playlist.version = mpd_status_get_queue_version(status);
- if (old_index == new_index || new_index < 0 ||
- (guint)new_index >= c->playlist.list->len)
- return -1;
+ /* remove the song from the local playlist */
+ playlist_remove(&c->playlist, idx);
- song1 = playlist_get(&c->playlist, old_index);
- song2 = playlist_get(&c->playlist, new_index);
+ /* remove references to the song */
+ if (c->song == song)
+ c->song = NULL;
+ }
- /* send the move command to mpd */
- mpd_send_swap_id(c->connection,
- mpd_song_get_id(song1), mpd_song_get_id(song2));
- if( (n=mpdclient_finish_command(c)) )
- return n;
+ return true;
+}
-#ifdef ENABLE_FANCY_PLAYLIST_MANAGMENT_CMD_MOVE
- /* update the playlist */
- playlist_swap(&c->playlist, old_index, new_index);
+/**
+ * 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);
- /* increment the playlist id, so we don't retrieve a new playlist */
- c->playlist.id++;
-#endif
+ for (; start < end; --end)
+ mpd_send_delete(c->connection, start);
- /* call playlist updated callback */
- mpdclient_playlist_callback(c, PLAYLIST_EVENT_MOVE, (gpointer) &new_index);
+ if (!mpd_command_list_end(c->connection) ||
+ !mpd_response_finish(c->connection))
+ return mpdclient_handle_error(c);
- return 0;
+ return true;
}
-gint
-mpdclient_cmd_save_playlist(struct mpdclient *c, const gchar *filename_utf8)
+bool
+mpdclient_cmd_delete_range(struct mpdclient *c, unsigned start, unsigned end)
{
- gint retval = 0;
+ struct mpd_status *status;
if (MPD_ERROR(c))
- return -1;
+ return false;
- mpd_send_save(c->connection, filename_utf8);
- if ((retval = mpdclient_finish_command(c)) == 0)
- mpdclient_browse_callback(c, BROWSE_PLAYLIST_SAVED, NULL);
- return retval;
-}
+ if (mpd_connection_cmp_server_version(c->connection, 0, 16, 0) < 0)
+ return mpdclient_cmd_delete_range_fallback(c, start, end);
-gint
-mpdclient_cmd_load_playlist(struct mpdclient *c, const gchar *filename_utf8)
-{
- if (MPD_ERROR(c))
- return -1;
+ /* MPD 0.16 supports "delete" with a range argument */
- mpd_send_load(c->connection, filename_utf8);
- return mpdclient_finish_command(c);
-}
+ /* send the delete command to mpd; at the same time, get the
+ new status (to verify the playlist id) */
-gint
-mpdclient_cmd_delete_playlist(struct mpdclient *c, const gchar *filename_utf8)
-{
- gint retval = 0;
+ 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))
+ return mpdclient_handle_error(c);
- if (MPD_ERROR(c))
- return -1;
+ c->events |= MPD_IDLE_PLAYLIST;
- mpd_send_rm(c->connection, filename_utf8);
- if ((retval = mpdclient_finish_command(c)) == 0)
- mpdclient_browse_callback(c, BROWSE_PLAYLIST_DELETED, NULL);
- return retval;
-}
+ status = mpd_recv_status(c->connection);
+ if (status != NULL) {
+ if (c->status != NULL)
+ mpd_status_free(c->status);
+ c->status = status;
+ }
+ if (!mpd_response_finish(c->connection))
+ return mpdclient_handle_error(c);
-/****************************************************************************/
-/*** Callback management functions ******************************************/
-/****************************************************************************/
+ if (mpd_status_get_queue_length(status) == playlist_length(&c->playlist) - (end - start) &&
+ mpd_status_get_queue_version(status) == c->playlist.version + 1) {
+ /* the cheap route: match on the new playlist length
+ and its version, we can keep our local playlist
+ copy in sync */
+ c->playlist.version = mpd_status_get_queue_version(status);
-static void
-do_list_callbacks(struct mpdclient *c, GList *list, gint event, gpointer data)
-{
- while (list) {
- mpdc_list_cb_t fn = list->data;
+ /* remove the song from the local playlist */
+ while (end > start) {
+ --end;
- fn(c, event, data);
- list = list->next;
+ /* remove references to the song */
+ if (c->song == playlist_get(&c->playlist, end))
+ c->song = NULL;
+
+ playlist_remove(&c->playlist, end);
+ }
}
-}
-void
-mpdclient_playlist_callback(struct mpdclient *c, int event, gpointer data)
-{
- do_list_callbacks(c, c->playlist_callbacks, event, data);
+ return true;
}
-void
-mpdclient_install_playlist_callback(struct mpdclient *c,mpdc_list_cb_t cb)
+bool
+mpdclient_cmd_move(struct mpdclient *c, gint old_index, gint new_index)
{
- c->playlist_callbacks = g_list_append(c->playlist_callbacks, cb);
-}
+ const struct mpd_song *song1, *song2;
+ struct mpd_status *status;
-void
-mpdclient_remove_playlist_callback(struct mpdclient *c, mpdc_list_cb_t cb)
-{
- c->playlist_callbacks = g_list_remove(c->playlist_callbacks, cb);
-}
+ if (MPD_ERROR(c))
+ return false;
-void
-mpdclient_browse_callback(struct mpdclient *c, int event, gpointer data)
-{
- do_list_callbacks(c, c->browse_callbacks, event, data);
-}
+ if (old_index == new_index || new_index < 0 ||
+ (guint)new_index >= c->playlist.list->len)
+ return false;
+ song1 = playlist_get(&c->playlist, old_index);
+ song2 = playlist_get(&c->playlist, new_index);
-void
-mpdclient_install_browse_callback(struct mpdclient *c,mpdc_list_cb_t cb)
-{
- c->browse_callbacks = g_list_append(c->browse_callbacks, cb);
-}
+ /* send the delete command to mpd; at the same time, get the
+ new status (to verify the playlist id) */
-void
-mpdclient_remove_browse_callback(struct mpdclient *c, mpdc_list_cb_t cb)
-{
- c->browse_callbacks = g_list_remove(c->browse_callbacks, cb);
-}
+ 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))
+ return mpdclient_handle_error(c);
-void
-mpdclient_install_error_callback(struct mpdclient *c, mpdc_error_cb_t cb)
-{
- c->error_callbacks = g_list_append(c->error_callbacks, cb);
-}
+ c->events |= MPD_IDLE_PLAYLIST;
-void
-mpdclient_remove_error_callback(struct mpdclient *c, mpdc_error_cb_t cb)
-{
- c->error_callbacks = g_list_remove(c->error_callbacks, cb);
+ status = mpd_recv_status(c->connection);
+ if (status != NULL) {
+ if (c->status != NULL)
+ mpd_status_free(c->status);
+ c->status = status;
+ }
+
+ if (!mpd_response_finish(c->connection))
+ return mpdclient_handle_error(c);
+
+ if (mpd_status_get_queue_length(status) == playlist_length(&c->playlist) &&
+ mpd_status_get_queue_version(status) == c->playlist.version + 1) {
+ /* the cheap route: match on the new playlist length
+ and its version, we can keep our local playlist
+ copy in sync */
+ c->playlist.version = mpd_status_get_queue_version(status);
+
+ /* swap songs in the local playlist */
+ playlist_swap(&c->playlist, old_index, new_index);
+ }
+
+ return true;
}
/****************************************************************************/
/* update playlist */
-gint
+bool
mpdclient_playlist_update(struct mpdclient *c)
{
struct mpd_entity *entity;
if (MPD_ERROR(c))
- return -1;
+ return false;
playlist_clear(&c->playlist);
mpd_entity_free(entity);
}
- c->playlist.id = mpd_status_get_queue_version(c->status);
+ c->playlist.version = 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);
}
/* update playlist (plchanges) */
-gint
+bool
mpdclient_playlist_update_changes(struct mpdclient *c)
{
struct mpd_song *song;
guint length;
if (MPD_ERROR(c))
- return -1;
+ return false;
- mpd_send_queue_changes_meta(c->connection, c->playlist.id);
+ mpd_send_queue_changes_meta(c->connection, c->playlist.version);
while ((song = mpd_recv_song(c->connection)) != NULL) {
int pos = mpd_song_get_pos(song);
}
c->song = NULL;
- c->playlist.id = mpd_status_get_queue_version(c->status);
+ c->playlist.version = mpd_status_get_queue_version(c->status);
- mpdclient_playlist_callback(c, PLAYLIST_EVENT_UPDATED, NULL);
-
- return 0;
+ return mpdclient_finish_command(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;
- struct mpd_entity *entity;
if (MPD_ERROR(c))
return NULL;
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_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);
+ filelist = mpdclient_recv_filelist_response(c);
+ if (filelist == NULL)
+ return NULL;
filelist_sort_dir_play(filelist, compare_filelistentry);
mpdclient_recv_filelist_response(struct mpdclient *c)
{
struct filelist *filelist;
- struct mpd_entity *entity;
-
- filelist = filelist_new();
- while ((entity = mpd_recv_entity(c->connection)) != NULL)
- filelist_append(filelist, entity);
+ filelist = filelist_new_recv(c->connection);
- if (mpdclient_finish_command(c)) {
+ if (!mpdclient_finish_command(c)) {
filelist_free(filelist);
return NULL;
}
return mpdclient_recv_filelist_response(c);
}
-int
+bool
mpdclient_filelist_add_all(struct mpdclient *c, struct filelist *fl)
{
guint i;
if (MPD_ERROR(c))
- return -1;
+ return false;
if (filelist_is_empty(fl))
- return 0;
+ return true;
mpd_command_list_begin(c->connection, false);
mpd_return_pair(c->connection, pair);
}
- if (mpdclient_finish_command(c))
+ if (!mpdclient_finish_command(c))
return string_list_free(list);
return list;
mpd_return_pair(c->connection, pair);
}
- if (mpdclient_finish_command(c))
+ if (!mpdclient_finish_command(c))
return string_list_free(list);
return list;