X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fmpdclient.c;h=ffa1a5d84408e86757b82d2dbde1617dbf07c583;hb=373736315529f8b760df043a21ee7526941c8bea;hp=a4e165e9b249c419f96e4cace8903fd099126823;hpb=3b7d3e2269094119c48b5a75d41b5c8066097cbd;p=ncmpc.git diff --git a/src/mpdclient.c b/src/mpdclient.c index a4e165e..ffa1a5d 100644 --- a/src/mpdclient.c +++ b/src/mpdclient.c @@ -24,6 +24,10 @@ #include "gidle.h" #include "charset.h" +#ifdef ENABLE_ASYNC_CONNECT +#include "aconnect.h" +#endif + #include #include @@ -149,14 +153,49 @@ mpdclient_handle_error(struct mpdclient *c) return false; } +#ifdef ENABLE_ASYNC_CONNECT +#ifndef WIN32 + +static bool +is_local_socket(const char *host) +{ + return *host == '/' || *host == '@'; +} + +static bool +settings_is_local_socket(const struct mpd_settings *settings) +{ + const char *host = mpd_settings_get_host(settings); + return host != NULL && is_local_socket(host); +} + +#endif +#endif + struct mpdclient * mpdclient_new(const gchar *host, unsigned port, unsigned timeout_ms, const gchar *password) { 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"); + +#ifndef WIN32 + c->settings2 = host == NULL && port == 0 && + settings_is_local_socket(c->settings) + ? mpd_settings_new(host, 6600, timeout_ms, NULL, NULL) + : NULL; +#endif + +#else c->host = host; c->port = port; +#endif + c->timeout_ms = timeout_ms; c->password = password; @@ -175,9 +214,56 @@ mpdclient_free(struct mpdclient *c) mpdclient_playlist_free(&c->playlist); +#ifdef ENABLE_ASYNC_CONNECT + mpd_settings_free(c->settings); + +#ifndef WIN32 + if (c->settings2 != NULL) + mpd_settings_free(c->settings2); +#endif +#endif + g_free(c); } +static char * +settings_name(const struct mpd_settings *settings) +{ + assert(settings != NULL); + + const char *host = mpd_settings_get_host(settings); + if (host == NULL) + host = "unknown"; + + if (host[0] == '/') + return g_strdup(host); + + unsigned port = mpd_settings_get_port(settings); + if (port == 0 || port == 6600) + return g_strdup(host); + + return g_strdup_printf("%s:%u", host, port); +} + +char * +mpdclient_settings_name(const struct mpdclient *c) +{ + assert(c != NULL); + +#ifdef ENABLE_ASYNC_CONNECT + return settings_name(c->settings); +#else + struct mpd_settings *settings = + mpd_settings_new(c->host, c->port, 0, NULL, NULL); + if (settings == NULL) + return g_strdup("unknown"); + + char *name = settings_name(settings); + mpd_settings_free(settings); + return name; +#endif +} + static void mpdclient_status_free(struct mpdclient *c) { @@ -194,6 +280,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) { @@ -219,44 +312,117 @@ 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) { + 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)) { + !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_aconnect_start(struct mpdclient *c, + const struct mpd_settings *settings); + +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; + +#ifndef WIN32 + if (!c->connecting2 && c->settings2 != NULL) { + c->connecting2 = true; + mpdclient_aconnect_start(c, c->settings2); + return; + } +#endif + + mpdclient_error_callback(message); + mpdclient_failed_callback(); +} + +static const struct aconnect_handler mpdclient_connect_handler = { + .success = mpdclient_connect_success, + .error = mpdclient_connect_error, +}; + +static void +mpdclient_aconnect_start(struct mpdclient *c, + const struct mpd_settings *settings) +{ + aconnect_start(&c->async_connect, + mpd_settings_get_host(settings), + mpd_settings_get_port(settings), + &mpdclient_connect_handler, c); +} + +#endif + +void +mpdclient_connect(struct mpdclient *c) +{ + /* close any open connection */ + mpdclient_disconnect(c); + +#ifdef ENABLE_ASYNC_CONNECT +#ifndef WIN32 + c->connecting2 = false; +#endif + mpdclient_aconnect_start(c, c->settings); +#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) { @@ -409,39 +575,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); }