X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fmain.c;h=ffc310fcee2b183d862c77e9c2bf83f8166929df;hb=c9310836deb2b8961c0b7f1cc847c527cb84116e;hp=8464035f1c0bcbf9f6cdbc918af9a524e2f12dba;hpb=4032f6c7c6a1a68aacf5ca6caaaf840b33cee6ce;p=ncmpc.git diff --git a/src/main.c b/src/main.c index 8464035..ffc310f 100644 --- a/src/main.c +++ b/src/main.c @@ -1,21 +1,21 @@ /* 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 * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ + */ #include "config.h" #include "ncmpc.h" @@ -27,7 +27,7 @@ #include "ncu.h" #include "screen.h" #include "screen_utils.h" -#include "screen_message.h" +#include "screen_status.h" #include "strfsong.h" #include "i18n.h" #include "player_command.h" @@ -48,6 +48,7 @@ #include #include +#include #include #include @@ -55,7 +56,7 @@ #include #endif -/* time between mpd updates [s] */ +/* time between mpd updates [ms] */ static const guint update_interval = 500; #define BUFSIZE 1024 @@ -63,6 +64,7 @@ static const guint update_interval = 500; static struct mpdclient *mpd = NULL; static GMainLoop *main_loop; static guint reconnect_source_id, update_source_id; +static int sigwinch_pipes[2]; #ifndef NCMPC_MINI static guint check_key_bindings_source_id; @@ -110,6 +112,7 @@ exit_and_cleanup(void) } } +#ifndef WIN32 static void catch_sigint(G_GNUC_UNUSED int sig) { @@ -120,7 +123,9 @@ catch_sigint(G_GNUC_UNUSED int sig) static void catch_sigcont(G_GNUC_UNUSED int sig) { - screen_resize(mpd); + char irrelevant = 'a'; + if (1 != write(sigwinch_pipes[1], &irrelevant, 1)) + exit(EXIT_FAILURE); } void @@ -131,30 +136,29 @@ sigstop(void) kill(0, SIGSTOP); /* issue SIGSTOP */ } -static guint timer_sigwinch_id; - static gboolean -timer_sigwinch(G_GNUC_UNUSED gpointer data) +sigwinch_event(G_GNUC_UNUSED GIOChannel *source, + G_GNUC_UNUSED GIOCondition condition, G_GNUC_UNUSED gpointer data) { - /* the following causes the screen to flicker. There might be - better solutions, but I believe it isn't all that - important. */ + char ignoreme[64]; + if (1 > read(sigwinch_pipes[0], ignoreme, 64)) + exit(EXIT_FAILURE); endwin(); refresh(); screen_resize(mpd); - return FALSE; + return TRUE; } static void catch_sigwinch(G_GNUC_UNUSED int sig) { - if (timer_sigwinch_id != 0) - g_source_remove(timer_sigwinch_id); - - timer_sigwinch_id = g_timeout_add(100, timer_sigwinch, NULL); + char irrelevant = 'a'; + if (1 != write(sigwinch_pipes[1], &irrelevant, 1)) + exit(EXIT_FAILURE); } +#endif /* WIN32 */ static void idle_callback(enum mpd_error error, @@ -231,6 +235,68 @@ do_mpd_update(void) check_reconnect(); } +#if LIBMPDCLIENT_CHECK_VERSION(2,4,0) + +static char * +settings_name(const struct mpd_settings *settings) +{ + 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); +} + +#endif + +static char * +default_settings_name(void) +{ +#if LIBMPDCLIENT_CHECK_VERSION(2,4,0) + struct mpd_settings *settings = + mpd_settings_new(options.host, options.port, 0, + NULL, options.password); + if (settings == NULL) + return g_strdup(_("unknown")); + + char *name = settings_name(settings); + mpd_settings_free(settings); + + return name; +#else + /* + * localhost is actually not correct, we only know that + * mpd_connection_new() has connected to the "default host". + */ + const char *name = options.host ?: "localhost"; + return g_strdup(name); +#endif +} + +static char * +connection_settings_name(const struct mpd_connection *connection) +{ +#if LIBMPDCLIENT_CHECK_VERSION(2,4,0) + const struct mpd_settings *settings = + mpd_connection_get_settings(connection); + if (settings == NULL) + return g_strdup(_("unknown")); + + return settings_name(settings); +#else + (void)connection; + + return default_settings_name(); +#endif +} + /** * This timer is installed when the connection to the MPD server is * broken. It tries to recover by reconnecting periodically. @@ -245,14 +311,16 @@ timer_reconnect(G_GNUC_UNUSED gpointer data) reconnect_source_id = 0; + char *name = default_settings_name(); screen_status_printf(_("Connecting to %s... [Press %s to abort]"), - options.host, get_key_names(CMD_QUIT,0) ); + name, get_key_names(CMD_QUIT, false)); + g_free(name); doupdate(); mpdclient_disconnect(mpd); success = mpdclient_connect(mpd, options.host, options.port, - 1.5, + options.timeout_ms, options.password); if (!success) { /* try again in 5 seconds */ @@ -286,15 +354,13 @@ timer_reconnect(G_GNUC_UNUSED gpointer data) mpd->source = mpd_glib_new(connection, idle_callback, mpd); - screen_status_printf(_("Connected to %s"), - options.host != NULL - ? options.host : "localhost"); + name = connection_settings_name(connection); + screen_status_printf(_("Connected to %s"), name); + g_free(name); doupdate(); /* update immediately */ - mpd->events = MPD_IDLE_DATABASE|MPD_IDLE_STORED_PLAYLIST| - MPD_IDLE_QUEUE|MPD_IDLE_PLAYER|MPD_IDLE_MIXER|MPD_IDLE_OUTPUT| - MPD_IDLE_OPTIONS|MPD_IDLE_UPDATE; + mpd->events = MPD_IDLE_ALL; do_mpd_update(); @@ -314,7 +380,7 @@ check_reconnect(void) /** * This function is called by the gidle.c library when MPD sends us an - * idle event (or when the connectiond dies). + * idle event (or when the connection dies). */ static void idle_callback(enum mpd_error error, enum mpd_server_error server_error, @@ -322,12 +388,10 @@ idle_callback(enum mpd_error error, enum mpd_server_error server_error, void *ctx) { struct mpdclient *c = ctx; - struct mpd_connection *connection; c->idle = false; - connection = mpdclient_get_connection(c); - assert(connection != NULL); + assert(mpdclient_is_connected(c)); if (error != MPD_ERROR_SUCCESS) { char *allocated; @@ -352,6 +416,7 @@ idle_callback(enum mpd_error error, enum mpd_server_error server_error, doupdate(); mpdclient_disconnect(c); + screen_update(mpd); reconnect_source_id = g_timeout_add(1000, timer_reconnect, NULL); return; @@ -462,7 +527,7 @@ timer_check_key_bindings(G_GNUC_UNUSED gpointer data) and this is a hint for the user what to press to correct that */ g_snprintf(comment, sizeof(comment), _("press %s for the key editor"), - get_key_names(CMD_SCREEN_KEYDEF, 0)); + get_key_names(CMD_SCREEN_KEYDEF, false)); g_strlcat(buf, comment, sizeof(buf)); g_strlcat(buf, ")", sizeof(buf)); #endif @@ -477,8 +542,13 @@ timer_check_key_bindings(G_GNUC_UNUSED gpointer data) int main(int argc, const char *argv[]) { +#ifndef WIN32 struct sigaction act; +#endif #ifdef ENABLE_LOCALE +#ifndef ENABLE_NLS + G_GNUC_UNUSED +#endif const char *charset = NULL; #endif GIOChannel *keyboard_channel; @@ -486,6 +556,7 @@ main(int argc, const char *argv[]) int lirc_socket; GIOChannel *lirc_channel = NULL; #endif + GIOChannel *sigwinch_channel = NULL; #ifdef ENABLE_LOCALE /* time and date formatting */ @@ -526,6 +597,7 @@ main(int argc, const char *argv[]) /* parse command line options - 2 pass */ options_parse(argc, argv); +#ifndef WIN32 /* setup signal behavior - SIGINT */ sigemptyset(&act.sa_mask); act.sa_flags = 0; @@ -575,6 +647,7 @@ main(int argc, const char *argv[]) perror("sigaction(SIGPIPE)"); exit(EXIT_FAILURE); } +#endif ncu_init(); @@ -604,6 +677,18 @@ main(int argc, const char *argv[]) } #endif +#ifndef WIN32 + if (!pipe(sigwinch_pipes) && + !fcntl(sigwinch_pipes[1], F_SETFL, O_NONBLOCK)) { + sigwinch_channel = g_io_channel_unix_new(sigwinch_pipes[0]); + g_io_add_watch(sigwinch_channel, G_IO_IN, sigwinch_event, NULL); + } + else { + perror("sigwinch pipe creation failed"); + exit(EXIT_FAILURE); + } +#endif + /* attempt to connect */ reconnect_source_id = g_timeout_add(1, timer_reconnect, NULL); @@ -633,6 +718,9 @@ main(int argc, const char *argv[]) g_main_loop_unref(main_loop); g_io_channel_unref(keyboard_channel); + g_io_channel_unref(sigwinch_channel); + close(sigwinch_pipes[0]); + close(sigwinch_pipes[1]); #ifdef ENABLE_LIRC if (lirc_socket >= 0)