diff options
-rw-r--r-- | nncmpp.c | 390 |
1 files changed, 193 insertions, 197 deletions
@@ -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 ------------------------------------------ |