From efae3a330fbfe9b85690b0b01a5b640e95613a6e Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Sat, 25 Mar 2017 20:09:57 +0100 Subject: [PATCH] mpdclient: try IP connect if default local socket path fails This is what libmpdclient does internally, and when ncmpc copied some code from libmpdclient, it did not replicate this implementation detail. https://bugs.musicpd.org/view.php?id=4672 --- NEWS | 1 + src/mpdclient.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ src/mpdclient.h | 18 ++++++++++++++++++ 3 files changed, 66 insertions(+) diff --git a/NEWS b/NEWS index 6956a1e..5b3a4d0 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,5 @@ ncmpc 0.27 - not yet released +* work around connect failure if /var/run/mpd/socket does not exist * remove the status bar clock (option "display-time") * fix assertion failure after connect failure diff --git a/src/mpdclient.c b/src/mpdclient.c index 870839f..ffa1a5d 100644 --- a/src/mpdclient.c +++ b/src/mpdclient.c @@ -153,6 +153,25 @@ 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) @@ -164,6 +183,14 @@ mpdclient_new(const gchar *host, unsigned port, 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; @@ -189,6 +216,11 @@ mpdclient_free(struct mpdclient *c) #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); @@ -320,6 +352,10 @@ mpdclient_connected(struct mpdclient *c, #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; @@ -336,6 +372,14 @@ mpdclient_connect_error(const char *message, void *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(); } @@ -364,6 +408,9 @@ mpdclient_connect(struct mpdclient *c) mpdclient_disconnect(c); #ifdef ENABLE_ASYNC_CONNECT +#ifndef WIN32 + c->connecting2 = false; +#endif mpdclient_aconnect_start(c, c->settings); #else /* connect to MPD */ diff --git a/src/mpdclient.h b/src/mpdclient.h index d51013f..1d3b6e0 100644 --- a/src/mpdclient.h +++ b/src/mpdclient.h @@ -11,7 +11,21 @@ struct filelist; struct mpdclient { #ifdef ENABLE_ASYNC_CONNECT + /** + * These settings are used to connect to MPD asynchronously. + */ struct mpd_settings *settings; + +#ifndef WIN32 + /** + * A second set of settings, just in case #settings did not + * work. This is only used if #settings refers to a local + * socket path, and this one is supposed to be a fallback to + * IP on the default port (6600). + */ + struct mpd_settings *settings2; +#endif + #else const char *host; unsigned port; @@ -58,6 +72,10 @@ struct mpdclient { */ enum mpd_idle events; +#if defined(ENABLE_ASYNC_CONNECT) && !defined(WIN32) + bool connecting2; +#endif + /** * This attribute is true when the connection is currently in * "idle" mode, and the #mpd_glib_source waits for an event. -- 2.11.4.GIT