Code

increment version number to 0.27
[ncmpc.git] / src / mpdclient.c
index 1a059d517e1a3571a66c7c193b2c108bf8695bb7..5903f1430fb3c9288c1c99d1fe208db07990e76f 100644 (file)
 #include "gidle.h"
 #include "charset.h"
 
+#ifdef ENABLE_ASYNC_CONNECT
+#include "aconnect.h"
+#endif
+
 #include <mpd/client.h>
 
 #include <assert.h>
@@ -77,6 +81,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,
@@ -126,8 +145,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;
 }
@@ -138,8 +159,16 @@ mpdclient_new(const gchar *host, unsigned port,
 {
        struct mpdclient *c = g_new0(struct mpdclient, 1);
 
+#ifdef ENABLE_ASYNC_CONNECT
+       c->settings = mpd_settings_new(host, port, timeout_ms,
+                                      NULL, NULL);
+       if (c->settings == NULL)
+               g_error("Out of memory");
+#else
        c->host = host;
        c->port = port;
+#endif
+
        c->timeout_ms = timeout_ms;
        c->password = password;
 
@@ -158,6 +187,10 @@ mpdclient_free(struct mpdclient *c)
 
        mpdclient_playlist_free(&c->playlist);
 
+#ifdef ENABLE_ASYNC_CONNECT
+       mpd_settings_free(c->settings);
+#endif
+
        g_free(c);
 }
 
@@ -177,6 +210,13 @@ mpdclient_status_free(struct mpdclient *c)
 void
 mpdclient_disconnect(struct mpdclient *c)
 {
+#ifdef ENABLE_ASYNC_CONNECT
+       if (c->async_connect != NULL) {
+               aconnect_cancel(c->async_connect);
+               c->async_connect = NULL;
+       }
+#endif
+
        mpdclient_cancel_enter_idle(c);
 
        if (c->source != NULL) {
@@ -202,44 +242,95 @@ mpdclient_disconnect(struct mpdclient *c)
        c->events |= MPD_IDLE_ALL;
 }
 
-bool
-mpdclient_connect(struct mpdclient *c)
+static bool
+mpdclient_connected(struct mpdclient *c,
+                   struct mpd_connection *connection)
 {
-       /* close any open connection */
-       mpdclient_disconnect(c);
+       c->connection = connection;
 
-       /* connect to MPD */
-       c->connection = mpd_connection_new(c->host, c->port, c->timeout_ms);
-       if (c->connection == NULL)
-               g_error("Out of memory");
-
-       if (mpd_connection_get_error(c->connection) != MPD_ERROR_SUCCESS) {
-               mpdclient_handle_error(c);
+       if (mpd_connection_get_error(connection) != MPD_ERROR_SUCCESS) {
+               mpdclient_invoke_error_callback1(c);
                mpdclient_disconnect(c);
                mpdclient_failed_callback();
                return false;
        }
 
+#ifdef ENABLE_ASYNC_CONNECT
+       if (c->timeout_ms > 0)
+               mpd_connection_set_timeout(connection, c->timeout_ms);
+#endif
+
        /* send password */
        if (c->password != NULL &&
-           !mpd_run_password(c->connection, c->password)) {
-               mpdclient_handle_error(c);
+           !mpd_run_password(connection, c->password)) {
+               mpdclient_invoke_error_callback1(c);
                mpdclient_disconnect(c);
                mpdclient_failed_callback();
                return false;
        }
 
-       c->source = mpd_glib_new(c->connection,
+       c->source = mpd_glib_new(connection,
                                 mpdclient_gidle_callback, c);
        mpdclient_schedule_enter_idle(c);
 
        ++c->connection_id;
 
        mpdclient_connected_callback();
-
        return true;
 }
 
+#ifdef ENABLE_ASYNC_CONNECT
+
+static void
+mpdclient_connect_success(struct mpd_connection *connection, void *ctx)
+{
+       struct mpdclient *c = ctx;
+       assert(c->async_connect != NULL);
+       c->async_connect = NULL;
+
+       mpdclient_connected(c, connection);
+}
+
+static void
+mpdclient_connect_error(const char *message, void *ctx)
+{
+       struct mpdclient *c = ctx;
+       assert(c->async_connect != NULL);
+       c->async_connect = NULL;
+
+       mpdclient_error_callback(message);
+       mpdclient_failed_callback();
+}
+
+static const struct aconnect_handler mpdclient_connect_handler = {
+       .success = mpdclient_connect_success,
+       .error = mpdclient_connect_error,
+};
+
+#endif
+
+void
+mpdclient_connect(struct mpdclient *c)
+{
+       /* close any open connection */
+       mpdclient_disconnect(c);
+
+#ifdef ENABLE_ASYNC_CONNECT
+       aconnect_start(&c->async_connect,
+                      mpd_settings_get_host(c->settings),
+                      mpd_settings_get_port(c->settings),
+                      &mpdclient_connect_handler, c);
+#else
+       /* connect to MPD */
+       struct mpd_connection *connection =
+               mpd_connection_new(c->host, c->port, c->timeout_ms);
+       if (connection == NULL)
+               g_error("Out of memory");
+
+       mpdclient_connected(c, connection);
+#endif
+}
+
 bool
 mpdclient_update(struct mpdclient *c)
 {
@@ -392,39 +483,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);
 }