diff --git a/src/main.c b/src/main.c
index 76fe2354a4c0bc6f0b02c7e3de26948144d8853f..214478e39ded84a53a3ac96591888e7f96c0d19c 100644 (file)
--- a/src/main.c
+++ b/src/main.c
#include "config.h"
#include "ncmpc.h"
#include "mpdclient.h"
-#include "gidle.h"
+#include "callbacks.h"
#include "charset.h"
#include "options.h"
#include "command.h"
#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>
+#ifndef WIN32
+#include <glib-unix.h>
+#endif
+
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
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);
}
#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)
+static gboolean
+handle_quit_signal(gcc_unused gpointer data)
{
g_main_loop_quit(main_loop);
-}
-
-
-static void
-catch_sigcont(gcc_unused int sig)
-{
- char irrelevant = 'a';
- if (1 != write(sigwinch_pipes[1], &irrelevant, 1))
- exit(EXIT_FAILURE);
-}
-
-void
-sigstop(void)
-{
- def_prog_mode(); /* save the tty modes */
- endwin(); /* end curses mode temporarily */
- kill(0, SIGSTOP); /* issue SIGSTOP */
+ return false;
}
static gboolean
}
#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);
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
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
static gboolean
timer_reconnect(gcc_unused gpointer data)
{
- assert(!mpdclient_is_connected(mpd));
+ assert(mpdclient_is_dead(mpd));
reconnect_source_id = 0;
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);
/* 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();
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();
}
auto_update_timer();
}
-int do_input_event(command_t cmd)
+bool
+do_input_event(command_t cmd)
{
if (cmd == CMD_QUIT) {
g_main_loop_quit(main_loop);
- return -1;
+ return false;
}
screen_cmd(mpd, cmd);
/* make sure we don't update the volume yet */
disable_update_timer();
- 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;
+ return true;
}
#ifndef NCMPC_MINI
options_parse(argc, argv);
#ifndef WIN32
- /* setup signal behavior - SIGINT */
+ /* setup quit signals */
+ g_unix_signal_add(SIGTERM, handle_quit_signal, NULL);
+ g_unix_signal_add(SIGINT, handle_quit_signal, NULL);
+ g_unix_signal_add(SIGHUP, handle_quit_signal, NULL);
+
+ /* setup signal behavior - SIGCONT */
+
struct sigaction act;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
- act.sa_handler = catch_sigint;
- if (sigaction(SIGINT, &act, NULL) < 0) {
- perror("signal");
- exit(EXIT_FAILURE);
- }
-
- /* setup signal behavior - SIGTERM */
-
- act.sa_handler = catch_sigint;
- if (sigaction(SIGTERM, &act, NULL) < 0) {
- perror("sigaction()");
- exit(EXIT_FAILURE);
- }
-
- /* setup signal behavior - SIGCONT */
- act.sa_handler = catch_sigcont;
+ act.sa_handler = catch_sigwinch;
if (sigaction(SIGCONT, &act, NULL) < 0) {
perror("sigaction(SIGCONT)");
exit(EXIT_FAILURE);
}
- /* setup signal behaviour - SIGHUP*/
-
- act.sa_handler = catch_sigint;
- if (sigaction(SIGHUP, &act, NULL) < 0) {
- perror("sigaction(SIGHUP)");
- exit(EXIT_FAILURE);
- }
-
/* setup SIGWINCH */
act.sa_flags = SA_RESTART;
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");
screen_paint(mpd);
g_main_loop_run(main_loop);
+ g_main_loop_unref(main_loop);
/* cleanup */
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();