Code

Modify version string to post-release version 0.19~git
[ncmpc.git] / src / mpdclient.c
index e380ac0dc8cae56102e4e5fb1fe680a7bcf97ef8..7bf29ea921e20dbda7aae906e7754aaf979e1f20 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -177,7 +177,6 @@ bool
 mpdclient_update(struct mpdclient *c)
 {
        struct mpd_connection *connection = mpdclient_get_connection(c);
-       bool retval;
 
        c->volume = -1;
 
@@ -216,23 +215,26 @@ mpdclient_update(struct mpdclient *c)
 
        /* check if the playlist needs an update */
        if (c->playlist.version != mpd_status_get_queue_version(c->status)) {
+               bool retval;
+
                if (c->source == NULL)
-                       c->events |= MPD_IDLE_PLAYLIST;
+                       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 *
@@ -252,63 +254,61 @@ mpdclient_put_connection(struct mpdclient *c)
        assert(c->source == NULL || c->connection != NULL);
 
        if (c->source != NULL && !c->idle) {
-               c->idle = true;
-               mpd_glib_enter(c->source);
+               c->idle = mpd_glib_enter(c->source);
        }
 }
 
-
-/****************************************************************************/
-/*** MPD Commands  **********************************************************/
-/****************************************************************************/
-
-bool
-mpdclient_cmd_play(struct mpdclient *c, gint idx)
+static struct mpd_status *
+mpdclient_recv_status(struct mpdclient *c)
 {
-       struct mpd_connection *connection = mpdclient_get_connection(c);
-       const struct mpd_song *song = playlist_get_song(&c->playlist, idx);
+       struct mpd_status *status;
 
-       if (connection == NULL)
-               return false;
+       assert(c->connection != NULL);
 
-       if (song)
-               mpd_send_play_id(connection, mpd_song_get_id(song));
-       else
-               mpd_send_play(connection);
+       status = mpd_recv_status(c->connection);
+       if (status == NULL) {
+               mpdclient_handle_error(c);
+               return NULL;
+       }
 
-       return mpdclient_finish_command(c);
+       if (c->status != NULL)
+               mpd_status_free(c->status);
+       return c->status = status;
 }
 
+/****************************************************************************/
+/*** MPD Commands  **********************************************************/
+/****************************************************************************/
+
 bool
 mpdclient_cmd_crop(struct mpdclient *c)
 {
-       struct mpd_connection *connection = mpdclient_get_connection(c);
-       struct mpd_status *status;
-       bool playing;
+       struct mpd_connection *connection;
        int length, current;
 
-       if (connection == NULL)
+       if (!mpdclient_is_playing(c))
                return false;
 
-       status = mpd_run_status(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)
+       length = mpd_status_get_queue_length(c->status);
+       current = mpd_status_get_song_pos(c->status);
+       if (current < 0 || mpd_status_get_queue_length(c->status) < 2)
                return true;
 
+       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(connection, length);
+       if (mpd_connection_cmp_server_version(connection, 0, 16, 0) >= 0) {
+               if (current < length - 1)
+                       mpd_send_delete_range(connection, current + 1, length);
+               if (current > 0)
+                       mpd_send_delete_range(connection, 0, current);
+       } else
+               while (--length >= 0)
+                       if (length != current)
+                               mpd_send_delete(connection, length);
 
        mpd_command_list_end(connection);
 
@@ -319,18 +319,39 @@ bool
 mpdclient_cmd_clear(struct mpdclient *c)
 {
        struct mpd_connection *connection = mpdclient_get_connection(c);
-       bool retval;
+       struct mpd_status *status;
 
        if (connection == NULL)
                return false;
 
-       mpd_send_clear(connection);
-       retval = mpdclient_finish_command(c);
+       /* 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 (retval)
-               c->events |= MPD_IDLE_PLAYLIST;
+       status = mpdclient_recv_status(c);
+       if (status == NULL)
+               return false;
 
-       return retval;
+       if (!mpd_response_finish(connection))
+               return mpdclient_handle_error(c);
+
+       /* update mpdclient.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->events |= MPD_IDLE_QUEUE;
+       return true;
 }
 
 bool
@@ -420,14 +441,11 @@ mpdclient_cmd_add(struct mpdclient *c, const struct mpd_song *song)
            !mpd_response_next(connection))
                return mpdclient_handle_error(c);
 
-       c->events |= MPD_IDLE_PLAYLIST;
+       c->events |= MPD_IDLE_QUEUE;
 
-       status = mpd_recv_status(connection);
-       if (status != NULL) {
-               if (c->status != NULL)
-                       mpd_status_free(c->status);
-               c->status = status;
-       }
+       status = mpdclient_recv_status(c);
+       if (status == NULL)
+               return false;
 
        if (!mpd_response_next(connection))
                return mpdclient_handle_error(c);
@@ -482,14 +500,11 @@ mpdclient_cmd_delete(struct mpdclient *c, gint idx)
            !mpd_command_list_end(connection))
                return mpdclient_handle_error(c);
 
-       c->events |= MPD_IDLE_PLAYLIST;
+       c->events |= MPD_IDLE_QUEUE;
 
-       status = mpd_recv_status(connection);
-       if (status != NULL) {
-               if (c->status != NULL)
-                       mpd_status_free(c->status);
-               c->status = status;
-       }
+       status = mpdclient_recv_status(c);
+       if (status == NULL)
+               return false;
 
        if (!mpd_response_finish(connection))
                return mpdclient_handle_error(c);
@@ -567,14 +582,11 @@ mpdclient_cmd_delete_range(struct mpdclient *c, unsigned start, unsigned end)
            !mpd_command_list_end(connection))
                return mpdclient_handle_error(c);
 
-       c->events |= MPD_IDLE_PLAYLIST;
+       c->events |= MPD_IDLE_QUEUE;
 
-       status = mpd_recv_status(connection);
-       if (status != NULL) {
-               if (c->status != NULL)
-                       mpd_status_free(c->status);
-               c->status = status;
-       }
+       status = mpdclient_recv_status(c);
+       if (status == NULL)
+               return false;
 
        if (!mpd_response_finish(connection))
                return mpdclient_handle_error(c);
@@ -602,40 +614,32 @@ 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)
 {
-       struct mpd_connection *connection = mpdclient_get_connection(c);
-       const struct mpd_song *song1, *song2;
+       struct mpd_connection *connection;
        struct mpd_status *status;
 
-       if (connection == NULL)
-               return false;
+       if (dest_pos == src_pos)
+               return true;
 
-       if (old_index == new_index || new_index < 0 ||
-           (guint)new_index >= c->playlist.list->len)
+       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(connection, false) ||
-           !mpd_send_swap_id(connection, mpd_song_get_id(song1),
-                             mpd_song_get_id(song2)) ||
+           !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(connection);
-       if (status != NULL) {
-               if (c->status != NULL)
-                       mpd_status_free(c->status);
-               c->status = status;
-       }
+       status = mpdclient_recv_status(c);
+       if (status == NULL)
+               return false;
 
        if (!mpd_response_finish(connection))
                return mpdclient_handle_error(c);
@@ -648,7 +652,7 @@ 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;