summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--nncmpp.c390
1 files changed, 193 insertions, 197 deletions
diff --git a/nncmpp.c b/nncmpp.c
index 6991481..786a312 100644
--- a/nncmpp.c
+++ b/nncmpp.c
@@ -1467,69 +1467,152 @@ app_process_termo_event (termo_key_t *event)
return true;
}
-// --- Signals -----------------------------------------------------------------
-
-static int g_signal_pipe[2]; ///< A pipe used to signal... signals
+// --- Info tab ----------------------------------------------------------------
-/// Program termination has been requested by a signal
-static volatile sig_atomic_t g_termination_requested;
-/// The window has changed in size
-static volatile sig_atomic_t g_winch_received;
+// TODO: either find something else to put in here or remove the wrapper struct
+static struct
+{
+ struct tab super; ///< Parent class
+}
+g_info_tab;
static void
-signals_postpone_handling (char id)
+info_tab_on_item_draw (struct tab *self, unsigned item_index,
+ struct row_buffer *buffer, int width)
{
- int original_errno = errno;
- if (write (g_signal_pipe[1], &id, 1) == -1)
- soft_assert (errno == EAGAIN);
- errno = original_errno;
+ (void) self;
+ (void) width;
+
+ // TODO
}
+static struct tab *
+info_tab_create (void)
+{
+ struct tab *super = &g_info_tab.super;
+ tab_init (super, "Info");
+ super->on_item_draw = info_tab_on_item_draw;
+ super->item_count = 0;
+ super->item_selected = 0;
+ return super;
+}
+
+// --- Help tab ----------------------------------------------------------------
+
+// TODO: either find something else to put in here or remove the wrapper struct
+static struct
+{
+ struct tab super; ///< Parent class
+}
+g_help_tab;
+
static void
-signals_superhandler (int signum)
+help_tab_on_item_draw (struct tab *self, unsigned item_index,
+ struct row_buffer *buffer, int width)
{
- switch (signum)
- {
- case SIGWINCH:
- g_winch_received = true;
- signals_postpone_handling ('w');
- break;
- case SIGINT:
- case SIGTERM:
- g_termination_requested = true;
- signals_postpone_handling ('t');
- break;
- default:
- hard_assert (!"unhandled signal");
- }
+ (void) self;
+ (void) width;
+
+ // TODO: group them the other way around for clarity
+ hard_assert (item_index < N_ELEMENTS (g_default_bindings));
+ struct binding *binding = &g_default_bindings[item_index];
+ char *text = xstrdup_printf ("%-12s %s",
+ binding->key, g_user_actions[binding->action].description);
+ row_buffer_append (buffer, text, 0);
+ free (text);
}
+static struct tab *
+help_tab_create (void)
+{
+ struct tab *super = &g_help_tab.super;
+ tab_init (super, "Help");
+ super->on_item_draw = help_tab_on_item_draw;
+ super->item_count = N_ELEMENTS (g_default_bindings);
+ super->item_selected = 0;
+ return super;
+}
+
+// --- Debug tab ---------------------------------------------------------------
+
+struct debug_item
+{
+ char *text; ///< Logged line
+ int64_t timestamp; ///< Timestamp
+ chtype attrs; ///< Line attributes
+};
+
+static struct
+{
+ struct tab super; ///< Parent class
+ struct debug_item *items; ///< Items
+ size_t items_alloc; ///< How many items are allocated
+ bool active; ///< The tab is present
+}
+g_debug_tab;
+
static void
-signals_setup_handlers (void)
+debug_tab_on_item_draw (struct tab *self, unsigned item_index,
+ struct row_buffer *buffer, int width)
{
- if (pipe (g_signal_pipe) == -1)
- exit_fatal ("%s: %s", "pipe", strerror (errno));
+ (void) self;
- set_cloexec (g_signal_pipe[0]);
- set_cloexec (g_signal_pipe[1]);
+ hard_assert (item_index <= g_debug_tab.super.item_count);
+ struct debug_item *item = &g_debug_tab.items[item_index];
- // So that the pipe cannot overflow; it would make write() block within
- // the signal handler, which is something we really don't want to happen.
- // The same holds true for read().
- set_blocking (g_signal_pipe[0], false);
- set_blocking (g_signal_pipe[1], false);
+ char buf[16];
+ struct tm tm;
+ time_t when = item->timestamp / 1000;
+ strftime (buf, sizeof buf, "%T", localtime_r (&when, &tm));
- signal (SIGPIPE, SIG_IGN);
+ char *prefix = xstrdup_printf
+ ("%s.%03d", buf, (int) (item->timestamp % 1000));
+ row_buffer_append (buffer, prefix, 0);
+ free (prefix);
- struct sigaction sa;
- sa.sa_flags = SA_RESTART;
- sa.sa_handler = signals_superhandler;
- sigemptyset (&sa.sa_mask);
+ row_buffer_append (buffer, " ", item->attrs);
+ row_buffer_append (buffer, item->text, item->attrs);
- if (sigaction (SIGWINCH, &sa, NULL) == -1
- || sigaction (SIGINT, &sa, NULL) == -1
- || sigaction (SIGTERM, &sa, NULL) == -1)
- exit_fatal ("sigaction: %s", strerror (errno));
+ // We override the formatting including colors -- do it for the whole line
+ if (buffer->total_width > width)
+ row_buffer_ellipsis (buffer, width, item->attrs);
+ while (buffer->total_width < width)
+ row_buffer_append (buffer, " ", item->attrs);
+}
+
+static void
+debug_tab_push (const char *message, chtype attrs)
+{
+ // TODO: uh... aren't we rather going to write our own abstraction?
+ if (g_debug_tab.items_alloc <= g_debug_tab.super.item_count)
+ {
+ g_debug_tab.items = xreallocarray (g_debug_tab.items,
+ sizeof *g_debug_tab.items, (g_debug_tab.items_alloc <<= 1));
+ }
+
+ // TODO: there should be a better, more efficient mechanism for this
+ struct debug_item *item =
+ &g_debug_tab.items[g_debug_tab.super.item_count++];
+ item->text = xstrdup (message);
+ item->attrs = attrs;
+ item->timestamp = clock_msec (CLOCK_REALTIME);
+
+ app_invalidate ();
+}
+
+static struct tab *
+debug_tab_create (void)
+{
+ g_debug_tab.items = xcalloc
+ ((g_debug_tab.items_alloc = 16), sizeof *g_debug_tab.items);
+ g_debug_tab.active = true;
+
+ struct tab *super = &g_debug_tab.super;
+ tab_init (super, "Debug");
+ super->on_item_draw = debug_tab_on_item_draw;
+ super->item_count = 0;
+ super->item_selected = 0;
+ return super;
}
// --- MPD interface -----------------------------------------------------------
@@ -1735,7 +1818,25 @@ mpd_on_failure (void *user_data)
mpd_queue_reconnect ();
}
-static void mpd_on_io_hook (void *user_data, bool outgoing, const char *line);
+static void
+mpd_on_io_hook (void *user_data, bool outgoing, const char *line)
+{
+ (void) user_data;
+
+ struct str s;
+ str_init (&s);
+ if (outgoing)
+ {
+ str_append_printf (&s, "<< %s", line);
+ debug_tab_push (s.str, APP_ATTR (OUTGOING));
+ }
+ else
+ {
+ str_append_printf (&s, ">> %s", line);
+ debug_tab_push (s.str, APP_ATTR (INCOMING));
+ }
+ str_free (&s);
+}
static void
app_on_reconnect (void *user_data)
@@ -1780,174 +1881,69 @@ app_on_reconnect (void *user_data)
free (address);
}
-// --- Help tab ----------------------------------------------------------------
-
-// TODO: either find something else to put in here or remove the wrapper struct
-static struct
-{
- struct tab super; ///< Parent class
-}
-g_help_tab;
-
-static void
-help_tab_on_item_draw (struct tab *self, unsigned item_index,
- struct row_buffer *buffer, int width)
-{
- (void) self;
- (void) width;
-
- // TODO: group them the other way around for clarity
- hard_assert (item_index < N_ELEMENTS (g_default_bindings));
- struct binding *binding = &g_default_bindings[item_index];
- char *text = xstrdup_printf ("%-12s %s",
- binding->key, g_user_actions[binding->action].description);
- row_buffer_append (buffer, text, 0);
- free (text);
-}
-
-static struct tab *
-help_tab_create (void)
-{
- struct tab *super = &g_help_tab.super;
- tab_init (super, "Help");
- super->on_item_draw = help_tab_on_item_draw;
- super->item_count = N_ELEMENTS (g_default_bindings);
- super->item_selected = 0;
- return super;
-}
-
-// --- Info tab ----------------------------------------------------------------
-
-// TODO: either find something else to put in here or remove the wrapper struct
-static struct
-{
- struct tab super; ///< Parent class
-}
-g_info_tab;
-
-static void
-info_tab_on_item_draw (struct tab *self, unsigned item_index,
- struct row_buffer *buffer, int width)
-{
- (void) self;
- (void) width;
-
- // TODO
-}
-
-static struct tab *
-info_tab_create (void)
-{
- struct tab *super = &g_info_tab.super;
- tab_init (super, "Info");
- super->on_item_draw = info_tab_on_item_draw;
- super->item_count = 0;
- super->item_selected = 0;
- return super;
-}
-
-// --- Debug tab ---------------------------------------------------------------
+// --- Signals -----------------------------------------------------------------
-struct debug_item
-{
- char *text; ///< Logged line
- int64_t timestamp; ///< Timestamp
- chtype attrs; ///< Line attributes
-};
+static int g_signal_pipe[2]; ///< A pipe used to signal... signals
-static struct
-{
- struct tab super; ///< Parent class
- struct debug_item *items; ///< Items
- size_t items_alloc; ///< How many items are allocated
- bool active; ///< The tab is present
-}
-g_debug_tab;
+/// Program termination has been requested by a signal
+static volatile sig_atomic_t g_termination_requested;
+/// The window has changed in size
+static volatile sig_atomic_t g_winch_received;
static void
-debug_tab_on_item_draw (struct tab *self, unsigned item_index,
- struct row_buffer *buffer, int width)
+signals_postpone_handling (char id)
{
- (void) self;
-
- hard_assert (item_index <= g_debug_tab.super.item_count);
- struct debug_item *item = &g_debug_tab.items[item_index];
-
- char buf[16];
- struct tm tm;
- time_t when = item->timestamp / 1000;
- strftime (buf, sizeof buf, "%T", localtime_r (&when, &tm));
-
- char *prefix = xstrdup_printf
- ("%s.%03d", buf, (int) (item->timestamp % 1000));
- row_buffer_append (buffer, prefix, 0);
- free (prefix);
-
- row_buffer_append (buffer, " ", item->attrs);
- row_buffer_append (buffer, item->text, item->attrs);
-
- // We override the formatting including colors -- do it for the whole line
- if (buffer->total_width > width)
- row_buffer_ellipsis (buffer, width, item->attrs);
- while (buffer->total_width < width)
- row_buffer_append (buffer, " ", item->attrs);
+ int original_errno = errno;
+ if (write (g_signal_pipe[1], &id, 1) == -1)
+ soft_assert (errno == EAGAIN);
+ errno = original_errno;
}
static void
-debug_tab_push (const char *message, chtype attrs)
+signals_superhandler (int signum)
{
- // TODO: uh... aren't we rather going to write our own abstraction?
- if (g_debug_tab.items_alloc <= g_debug_tab.super.item_count)
+ switch (signum)
{
- g_debug_tab.items = xreallocarray (g_debug_tab.items,
- sizeof *g_debug_tab.items, (g_debug_tab.items_alloc <<= 1));
+ case SIGWINCH:
+ g_winch_received = true;
+ signals_postpone_handling ('w');
+ break;
+ case SIGINT:
+ case SIGTERM:
+ g_termination_requested = true;
+ signals_postpone_handling ('t');
+ break;
+ default:
+ hard_assert (!"unhandled signal");
}
-
- // TODO: there should be a better, more efficient mechanism for this
- struct debug_item *item =
- &g_debug_tab.items[g_debug_tab.super.item_count++];
- item->text = xstrdup (message);
- item->attrs = attrs;
- item->timestamp = clock_msec (CLOCK_REALTIME);
-
- app_invalidate ();
}
-static struct tab *
-debug_tab_create (void)
+static void
+signals_setup_handlers (void)
{
- g_debug_tab.items = xcalloc
- ((g_debug_tab.items_alloc = 16), sizeof *g_debug_tab.items);
- g_debug_tab.active = true;
+ if (pipe (g_signal_pipe) == -1)
+ exit_fatal ("%s: %s", "pipe", strerror (errno));
- struct tab *super = &g_debug_tab.super;
- tab_init (super, "Debug");
- super->on_item_draw = debug_tab_on_item_draw;
- super->item_count = 0;
- super->item_selected = 0;
- return super;
-}
+ set_cloexec (g_signal_pipe[0]);
+ set_cloexec (g_signal_pipe[1]);
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ // So that the pipe cannot overflow; it would make write() block within
+ // the signal handler, which is something we really don't want to happen.
+ // The same holds true for read().
+ set_blocking (g_signal_pipe[0], false);
+ set_blocking (g_signal_pipe[1], false);
-static void
-mpd_on_io_hook (void *user_data, bool outgoing, const char *line)
-{
- (void) user_data;
+ signal (SIGPIPE, SIG_IGN);
- struct str s;
- str_init (&s);
- if (outgoing)
- {
- str_append_printf (&s, "<< %s", line);
- debug_tab_push (s.str, APP_ATTR (OUTGOING));
- }
- else
- {
- str_append_printf (&s, ">> %s", line);
- debug_tab_push (s.str, APP_ATTR (INCOMING));
- }
- str_free (&s);
+ struct sigaction sa;
+ sa.sa_flags = SA_RESTART;
+ sa.sa_handler = signals_superhandler;
+ sigemptyset (&sa.sa_mask);
+
+ if (sigaction (SIGWINCH, &sa, NULL) == -1
+ || sigaction (SIGINT, &sa, NULL) == -1
+ || sigaction (SIGTERM, &sa, NULL) == -1)
+ exit_fatal ("sigaction: %s", strerror (errno));
}
// --- Initialisation, event handling ------------------------------------------