Code

mpdclient: eliminate redundant mpd_status_get_volume() calls
[ncmpc.git] / src / mpdclient.c
index c1c4a31e6143cfb9ae200d3514d23e61c524c64e..73bb85f337c5679092e07e7526066fa36861676b 100644 (file)
 
 #include <assert.h>
 
+static gboolean
+mpdclient_enter_idle_callback(gpointer user_data)
+{
+       struct mpdclient *c = user_data;
+       assert(c->enter_idle_source_id != 0);
+       assert(c->source != NULL);
+       assert(!c->idle);
+
+       c->enter_idle_source_id = 0;
+       c->idle = mpd_glib_enter(c->source);
+       return false;
+}
+
+static void
+mpdclient_schedule_enter_idle(struct mpdclient *c)
+{
+       assert(c != NULL);
+       assert(c->source != NULL);
+
+       if (c->enter_idle_source_id == 0)
+               /* automatically re-enter MPD "idle" mode */
+               c->enter_idle_source_id =
+                       g_idle_add(mpdclient_enter_idle_callback, c);
+}
+
+static void
+mpdclient_cancel_enter_idle(struct mpdclient *c)
+{
+       if (c->enter_idle_source_id != 0) {
+               g_source_remove(c->enter_idle_source_id);
+               c->enter_idle_source_id = 0;
+       }
+}
+
 static void
 mpdclient_invoke_error_callback(enum mpd_error error,
                                const char *message)
@@ -43,6 +77,21 @@ mpdclient_invoke_error_callback(enum mpd_error error,
        g_free(allocated);
 }
 
+static void
+mpdclient_invoke_error_callback1(struct mpdclient *c)
+{
+       assert(c != NULL);
+       assert(c->connection != NULL);
+
+       struct mpd_connection *connection = c->connection;
+
+       enum mpd_error error = mpd_connection_get_error(connection);
+       assert(error != MPD_ERROR_SUCCESS);
+
+       mpdclient_invoke_error_callback(error,
+                                       mpd_connection_get_error_message(connection));
+}
+
 static void
 mpdclient_gidle_callback(enum mpd_error error,
                         gcc_unused enum mpd_server_error server_error,
@@ -69,7 +118,8 @@ mpdclient_gidle_callback(enum mpd_error error,
 
        c->events = 0;
 
-       mpdclient_put_connection(c);
+       if (c->source != NULL)
+               mpdclient_schedule_enter_idle(c);
 }
 
 /****************************************************************************/
@@ -91,8 +141,10 @@ mpdclient_handle_error(struct mpdclient *c)
        mpdclient_invoke_error_callback(error,
                                        mpd_connection_get_error_message(c->connection));
 
-       if (!mpd_connection_clear_error(c->connection))
+       if (!mpd_connection_clear_error(c->connection)) {
                mpdclient_disconnect(c);
+               mpdclient_lost_callback();
+       }
 
        return false;
 }
@@ -142,6 +194,8 @@ mpdclient_status_free(struct mpdclient *c)
 void
 mpdclient_disconnect(struct mpdclient *c)
 {
+       mpdclient_cancel_enter_idle(c);
+
        if (c->source != NULL) {
                mpd_glib_free(c->source);
                c->source = NULL;
@@ -177,7 +231,7 @@ mpdclient_connect(struct mpdclient *c)
                g_error("Out of memory");
 
        if (mpd_connection_get_error(c->connection) != MPD_ERROR_SUCCESS) {
-               mpdclient_handle_error(c);
+               mpdclient_invoke_error_callback1(c);
                mpdclient_disconnect(c);
                mpdclient_failed_callback();
                return false;
@@ -186,7 +240,7 @@ mpdclient_connect(struct mpdclient *c)
        /* send password */
        if (c->password != NULL &&
            !mpd_run_password(c->connection, c->password)) {
-               mpdclient_handle_error(c);
+               mpdclient_invoke_error_callback1(c);
                mpdclient_disconnect(c);
                mpdclient_failed_callback();
                return false;
@@ -194,6 +248,7 @@ mpdclient_connect(struct mpdclient *c)
 
        c->source = mpd_glib_new(c->connection,
                                 mpdclient_gidle_callback, c);
+       mpdclient_schedule_enter_idle(c);
 
        ++c->connection_id;
 
@@ -248,21 +303,13 @@ mpdclient_get_connection(struct mpdclient *c)
        if (c->source != NULL && c->idle) {
                c->idle = false;
                mpd_glib_leave(c->source);
+
+               mpdclient_schedule_enter_idle(c);
        }
 
        return c->connection;
 }
 
-void
-mpdclient_put_connection(struct mpdclient *c)
-{
-       assert(c->source == NULL || c->connection != NULL);
-
-       if (c->source != NULL && !c->idle) {
-               c->idle = mpd_glib_enter(c->source);
-       }
-}
-
 static struct mpd_status *
 mpdclient_recv_status(struct mpdclient *c)
 {
@@ -362,39 +409,26 @@ mpdclient_cmd_volume(struct mpdclient *c, gint value)
 bool
 mpdclient_cmd_volume_up(struct mpdclient *c)
 {
+       if (c->volume < 0 || c->volume >= 100)
+               return true;
+
        struct mpd_connection *connection = mpdclient_get_connection(c);
        if (connection == NULL)
                return false;
 
-       if (c->status == NULL ||
-           mpd_status_get_volume(c->status) == -1)
-               return true;
-
-       if (c->volume < 0)
-               c->volume = mpd_status_get_volume(c->status);
-
-       if (c->volume >= 100)
-               return true;
-
        return mpdclient_cmd_volume(c, ++c->volume);
 }
 
 bool
 mpdclient_cmd_volume_down(struct mpdclient *c)
 {
+       if (c->volume <= 0)
+               return true;
+
        struct mpd_connection *connection = mpdclient_get_connection(c);
        if (connection == NULL)
                return false;
 
-       if (c->status == NULL || mpd_status_get_volume(c->status) < 0)
-               return true;
-
-       if (c->volume < 0)
-               c->volume = mpd_status_get_volume(c->status);
-
-       if (c->volume <= 0)
-               return true;
-
        return mpdclient_cmd_volume(c, --c->volume);
 }