Code

main: move keyboard_event() to keyboard.c
[ncmpc.git] / src / main.c
index 7e5a6cb3000c35605b62eb4728da2898bfe36889..fe696c400ce61d5e91d79f5283335b2fc1f04001 100644 (file)
@@ -1,5 +1,5 @@
 /* ncmpc (Ncurses MPD Client)
- * (c) 2004-2010 The Music Player Daemon Project
+ * (c) 2004-2017 The Music Player Daemon Project
  * Project homepage: http://musicpd.org
  *
  * This program is free software; you can redistribute it and/or modify
@@ -20,7 +20,7 @@
 #include "config.h"
 #include "ncmpc.h"
 #include "mpdclient.h"
-#include "gidle.h"
+#include "callbacks.h"
 #include "charset.h"
 #include "options.h"
 #include "command.h"
@@ -31,6 +31,8 @@
 #include "strfsong.h"
 #include "i18n.h"
 #include "player_command.h"
+#include "keyboard.h"
+#include "lirc.h"
 
 #ifndef NCMPC_MINI
 #include "conf.h"
 #include "lyrics.h"
 #endif
 
-#ifdef ENABLE_LIRC
-#include "lirc.h"
-#endif
-
 #include <mpd/client.h>
 
 #include <stdlib.h>
@@ -74,16 +72,10 @@ static guint check_key_bindings_source_id;
 static void
 update_xterm_title(void)
 {
-       struct mpd_status *status = NULL;
-       const struct mpd_song *song = NULL;
-       if (mpd) {
-               status = mpd->status;
-               song = mpd->song;
-       }
+       const struct mpd_song *song = mpd->song;
 
        char tmp[BUFSIZE];
-       if (options.xterm_title_format && status && song &&
-           mpd_status_get_state(status) == MPD_STATE_PLAY)
+       if (options.xterm_title_format && mpd->playing && song)
                strfsong(tmp, BUFSIZE, options.xterm_title_format, song);
        else
                g_strlcpy(tmp, PACKAGE " version " VERSION, BUFSIZE);
@@ -96,21 +88,6 @@ update_xterm_title(void)
 }
 #endif
 
-static void
-exit_and_cleanup(void)
-{
-       screen_exit();
-#ifndef NCMPC_MINI
-       set_xterm_title("");
-#endif
-       printf("\n");
-
-       if (mpd) {
-               mpdclient_disconnect(mpd);
-               mpdclient_free(mpd);
-       }
-}
-
 #ifndef WIN32
 static void
 catch_sigint(gcc_unused int sig)
@@ -122,8 +99,7 @@ catch_sigint(gcc_unused int sig)
 static void
 catch_sigcont(gcc_unused int sig)
 {
-       char irrelevant = 'a';
-       if (1 != write(sigwinch_pipes[1], &irrelevant, 1))
+       if (1 != write(sigwinch_pipes[1], "", 1))
                exit(EXIT_FAILURE);
 }
 
@@ -153,18 +129,11 @@ sigwinch_event(gcc_unused GIOChannel *source,
 static void
 catch_sigwinch(gcc_unused int sig)
 {
-       char irrelevant = 'a';
-       if (1 != write(sigwinch_pipes[1], &irrelevant, 1))
+       if (1 != write(sigwinch_pipes[1], "", 1))
                exit(EXIT_FAILURE);
 }
 #endif /* WIN32 */
 
-static void
-idle_callback(enum mpd_error error,
-             gcc_unused enum mpd_server_error server_error,
-             const char *message, enum mpd_idle events,
-             gcc_unused void *ctx);
-
 static gboolean
 timer_mpd_update(gpointer data);
 
@@ -191,10 +160,7 @@ disable_update_timer(void)
 static bool
 should_enable_update_timer(void)
 {
-       return (mpdclient_is_connected(mpd) &&
-               (mpd->source == NULL || /* "idle" not supported */
-                (mpd->status != NULL &&
-                 mpd_status_get_state(mpd->status) == MPD_STATE_PLAY)))
+       return mpd->playing
 #ifndef NCMPC_MINI
                || options.display_time
 #endif
@@ -217,9 +183,7 @@ static void
 do_mpd_update(void)
 {
        if (mpdclient_is_connected(mpd) &&
-           (mpd->source == NULL || mpd->events != 0 ||
-            (mpd->status != NULL &&
-             mpd_status_get_state(mpd->status) == MPD_STATE_PLAY)))
+           (mpd->events != 0 || mpd->playing))
                mpdclient_update(mpd);
 
 #ifndef NCMPC_MINI
@@ -273,7 +237,7 @@ default_settings_name(void)
 static gboolean
 timer_reconnect(gcc_unused gpointer data)
 {
-       assert(!mpdclient_is_connected(mpd));
+       assert(mpdclient_is_dead(mpd));
 
        reconnect_source_id = 0;
 
@@ -284,19 +248,30 @@ timer_reconnect(gcc_unused gpointer data)
        doupdate();
 
        mpdclient_disconnect(mpd);
-       if (!mpdclient_connect(mpd, options.host, options.port,
-                              options.timeout_ms,
-                              options.password)) {
-               /* try again in 5 seconds */
-               reconnect_source_id = g_timeout_add(5000,
-                                                   timer_reconnect, NULL);
-               return FALSE;
-       }
+       mpdclient_connect(mpd, options.host, options.port,
+                         options.timeout_ms,
+                         options.password);
 
-       struct mpd_connection *connection = mpdclient_get_connection(mpd);
+       return FALSE;
+}
+
+static void
+check_reconnect(void)
+{
+       if (mpdclient_is_dead(mpd) && reconnect_source_id == 0)
+               /* reconnect when the connection is lost */
+               reconnect_source_id = g_timeout_add(1000, timer_reconnect,
+                                                   NULL);
+}
+
+void
+mpdclient_connected_callback(void)
+{
+       assert(reconnect_source_id == 0);
 
 #ifndef NCMPC_MINI
        /* quit if mpd is pre 0.14 - song id not supported by mpd */
+       struct mpd_connection *connection = mpdclient_get_connection(mpd);
        if (mpd_connection_cmp_server_version(connection, 0, 16, 0) < 0) {
                const unsigned *version =
                        mpd_connection_get_server_version(connection);
@@ -309,13 +284,10 @@ timer_reconnect(gcc_unused gpointer data)
                /* try again after 30 seconds */
                reconnect_source_id = g_timeout_add(30000,
                                                    timer_reconnect, NULL);
-               return FALSE;
+               return;
        }
 #endif
 
-       mpd->source = mpd_glib_new(connection,
-                                  idle_callback, mpd);
-
        screen_status_clear_message();
        doupdate();
 
@@ -325,75 +297,41 @@ timer_reconnect(gcc_unused gpointer data)
        do_mpd_update();
 
        auto_update_timer();
+}
 
-       return FALSE;
+void
+mpdclient_failed_callback(void)
+{
+       assert(reconnect_source_id == 0);
+
+       /* try again in 5 seconds */
+       reconnect_source_id = g_timeout_add(5000,
+                                           timer_reconnect, NULL);
 }
 
-static void
-check_reconnect(void)
+void
+mpdclient_lost_callback(void)
 {
-       if (!mpdclient_is_connected(mpd) && reconnect_source_id == 0)
-               /* reconnect when the connection is lost */
-               reconnect_source_id = g_timeout_add(1000, timer_reconnect,
-                                                   NULL);
+       assert(reconnect_source_id == 0);
+
+       screen_update(mpd);
+
+       reconnect_source_id = g_timeout_add(1000, timer_reconnect, NULL);
 }
 
 /**
  * This function is called by the gidle.c library when MPD sends us an
  * idle event (or when the connection dies).
  */
-static void
-idle_callback(enum mpd_error error, enum mpd_server_error server_error,
-             const char *message, enum mpd_idle events,
-             void *ctx)
+void
+mpdclient_idle_callback(gcc_unused enum mpd_idle events)
 {
-       struct mpdclient *c = ctx;
-
-       c->idle = false;
-
-       assert(mpdclient_is_connected(c));
-
-       if (error != MPD_ERROR_SUCCESS) {
-               if (error == MPD_ERROR_SERVER &&
-                   server_error == MPD_SERVER_ERROR_UNKNOWN_CMD) {
-                       /* the "idle" command is not supported - fall
-                          back to timer based polling */
-                       mpd_glib_free(c->source);
-                       c->source = NULL;
-                       auto_update_timer();
-                       return;
-               }
-
-               char *allocated;
-               if (error == MPD_ERROR_SERVER)
-                       message = allocated = utf8_to_locale(message);
-               else
-                       allocated = NULL;
-               screen_status_message(message);
-               g_free(allocated);
-               screen_bell();
-               doupdate();
-
-               mpdclient_disconnect(c);
-               screen_update(mpd);
-               reconnect_source_id = g_timeout_add(1000, timer_reconnect,
-                                                   NULL);
-               return;
-       }
-
-       c->events |= events;
-       mpdclient_update(c);
-
 #ifndef NCMPC_MINI
        if (options.enable_xterm_title)
                update_xterm_title();
 #endif
 
        screen_update(mpd);
-       c->events = 0;
-
-       mpdclient_put_connection(c);
-       check_reconnect();
        auto_update_timer();
 }
 
@@ -440,22 +378,6 @@ int do_input_event(command_t cmd)
        return 0;
 }
 
-static gboolean
-keyboard_event(gcc_unused GIOChannel *source,
-              gcc_unused GIOCondition condition,
-              gcc_unused gpointer data)
-{
-       begin_input_event();
-
-       command_t cmd = get_keyboard_command();
-       if (cmd != CMD_NONE)
-               if (do_input_event(cmd) != 0)
-                       return FALSE;
-
-       end_input_event();
-       return TRUE;
-}
-
 #ifndef NCMPC_MINI
 /**
  * Check the configured key bindings for errors, and display a status
@@ -608,25 +530,17 @@ main(int argc, const char *argv[])
        main_loop = g_main_loop_new(NULL, FALSE);
 
        /* watch out for keyboard input */
-       GIOChannel *keyboard_channel = g_io_channel_unix_new(STDIN_FILENO);
-       g_io_add_watch(keyboard_channel, G_IO_IN, keyboard_event, NULL);
+       keyboard_init();
 
-#ifdef ENABLE_LIRC
        /* watch out for lirc input */
-       int lirc_socket = ncmpc_lirc_open();
-       GIOChannel *lirc_channel = NULL;
-       if (lirc_socket >= 0) {
-               lirc_channel = g_io_channel_unix_new(lirc_socket);
-               g_io_add_watch(lirc_channel, G_IO_IN, lirc_event, NULL);
-       }
-#endif
+       ncmpc_lirc_init();
 
 #ifndef WIN32
-       GIOChannel *sigwinch_channel = NULL;
        if (!pipe(sigwinch_pipes) &&
                !fcntl(sigwinch_pipes[1], F_SETFL, O_NONBLOCK)) {
-               sigwinch_channel = g_io_channel_unix_new(sigwinch_pipes[0]);
+               GIOChannel *sigwinch_channel = g_io_channel_unix_new(sigwinch_pipes[0]);
                g_io_add_watch(sigwinch_channel, G_IO_IN, sigwinch_event, NULL);
+               g_io_channel_unref(sigwinch_channel);
        }
        else {
                perror("sigwinch pipe creation failed");
@@ -646,6 +560,7 @@ main(int argc, const char *argv[])
        screen_paint(mpd);
 
        g_main_loop_run(main_loop);
+       g_main_loop_unref(main_loop);
 
        /* cleanup */
 
@@ -661,19 +576,18 @@ main(int argc, const char *argv[])
                g_source_remove(check_key_bindings_source_id);
 #endif
 
-       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)
-               g_io_channel_unref(lirc_channel);
-       ncmpc_lirc_close();
+       ncmpc_lirc_deinit();
+
+       screen_exit();
+#ifndef NCMPC_MINI
+       set_xterm_title("");
 #endif
+       printf("\n");
 
-       exit_and_cleanup();
+       mpdclient_free(mpd);
 
 #ifdef ENABLE_LYRICS_SCREEN
        lyrics_deinit();