diff options
-rw-r--r-- | brightness.c | 39 | ||||
-rw-r--r-- | dwmstatus.c | 720 | ||||
-rw-r--r-- | fancontrol-ng.c | 48 | ||||
m--------- | liberty | 0 |
4 files changed, 39 insertions, 768 deletions
diff --git a/brightness.c b/brightness.c index 3da1839..3b52fc5 100644 --- a/brightness.c +++ b/brightness.c @@ -55,12 +55,6 @@ log_message_custom (void *user_data, const char *quote, const char *fmt, fputs ("\n", stream); } -#define FAIL(...) \ - BLOCK_START \ - error_set (e, __VA_ARGS__); \ - return false; \ - BLOCK_END - static void wait_ms (long ms) { @@ -122,9 +116,9 @@ check_edid (int fd, struct error **e) data.nmsgs = 2; if (ioctl (fd, I2C_RDWR, &data) < 0) - FAIL ("%s: %s", "ioctl", strerror (errno)); + return error_set (e, "%s: %s", "ioctl", strerror (errno)); if (memcmp ("\x00\xFF\xFF\xFF\xFF\xFF\xFF\x00", buf, sizeof buf)) - FAIL ("invalid EDID"); + return error_set (e, "invalid EDID"); return true; } @@ -133,13 +127,13 @@ is_a_display (int fd, struct error **e) { struct stat st; if (fstat (fd, &st) < 0) - FAIL ("%s: %s", "fstat", strerror (errno)); + return error_set (e, "%s: %s", "fstat", strerror (errno)); unsigned long funcs; if (!(st.st_mode & S_IFCHR) || ioctl (fd, I2C_FUNCS, &funcs) < 0 || !(funcs & I2C_FUNC_I2C)) - FAIL ("not an I2C device"); + return error_set (e, "not an I2C device"); return check_edid (fd, e); } @@ -176,7 +170,7 @@ ddc_send (int fd, unsigned command, void *args, size_t args_len, bool failed = ioctl (fd, I2C_RDWR, &data) < 0; str_free (&buf); if (failed) - FAIL ("%s: %s", "ioctl", strerror (errno)); + return error_set (e, "%s: %s", "ioctl", strerror (errno)); return true; } @@ -197,7 +191,7 @@ ddc_read (int fd, unsigned *command, void *out_buf, size_t *n_read, data.nmsgs = 1; if (ioctl (fd, I2C_RDWR, &data) < 0) - FAIL ("%s: %s", "ioctl", strerror (errno)); + return error_set (e, "%s: %s", "ioctl", strerror (errno)); struct msg_unpacker unpacker; msg_unpacker_init (&unpacker, buf, sizeof buf); @@ -208,9 +202,9 @@ ddc_read (int fd, unsigned *command, void *out_buf, size_t *n_read, (void) msg_unpacker_u8 (&unpacker, &cmd); if (sender != (DDC_ADDRESS_DISPLAY | I2C_WRITE) || !(length & 0x80)) - FAIL ("invalid response"); + return error_set (e, "invalid response"); if (!(length ^= 0x80)) - FAIL ("NULL response"); + return error_set (e, "NULL response"); // TODO: also check the checksum @@ -237,7 +231,7 @@ set_brightness (int fd, long diff, struct error **e) return false; if (command != DDC_GET_VCP_FEATURE_REPLY || len != 7) - FAIL ("invalid response"); + return error_set (e, "invalid response"); struct msg_unpacker unpacker; msg_unpacker_init (&unpacker, buf, len); @@ -249,15 +243,15 @@ set_brightness (int fd, long diff, struct error **e) int16_t cur; msg_unpacker_i16 (&unpacker, &cur); if (result == 0x01) - FAIL ("error reported by monitor"); + return error_set (e, "error reported by monitor"); if (result != 0x00 || vcp_opcode != VCP_BRIGHTNESS) - FAIL ("invalid response"); + return error_set (e, "invalid response"); // These are unsigned but usually just one byte long if (max < 0 || cur < 0) - FAIL ("capability range overflow"); + return error_set (e, "capability range overflow"); int16_t req = (cur * 100 + diff * max + 50) / 100; if (req > max) req = max; @@ -360,10 +354,7 @@ set_backlight (int dir, long diff, struct error **e) } if (cur < 0 || max < 0) - { - error_set (e, "invalid range or current value"); - return false; - } + return error_set (e, "invalid range or current value"); long req = (cur * 100 + diff * max + 50) / 100; if (req > max) req = max; @@ -372,8 +363,8 @@ set_backlight (int dir, long diff, struct error **e) int fd = openat (dir, "brightness", O_WRONLY); if (fd < 0) { - error_set (e, "%s: %s: %s", "brightness", "openat", strerror (errno)); - return false; + return error_set (e, + "%s: %s: %s", "brightness", "openat", strerror (errno)); } struct str s; diff --git a/dwmstatus.c b/dwmstatus.c index 5453202..254f442 100644 --- a/dwmstatus.c +++ b/dwmstatus.c @@ -19,6 +19,7 @@ #define LIBERTY_WANT_POLLER #define LIBERTY_WANT_ASYNC +#define LIBERTY_WANT_PROTO_MPD #define _GNU_SOURCE // openat @@ -28,7 +29,6 @@ #include "liberty/liberty.c" #include <dirent.h> -#include <sys/un.h> #include <spawn.h> #include <X11/Xlib.h> @@ -65,67 +65,6 @@ set_dwm_status (Display *dpy, const char *str) XSync (dpy, False); } -// --- Simple network I/O ------------------------------------------------------ - -enum socket_io_result -{ - SOCKET_IO_OK = 0, ///< Completed successfully - SOCKET_IO_EOF, ///< Connection shut down by peer - SOCKET_IO_ERROR ///< Connection error -}; - -static enum socket_io_result -socket_io_try_read (int socket_fd, struct str *rb) -{ - ssize_t n_read; - while (true) - { - str_ensure_space (rb, 512); - n_read = recv (socket_fd, rb->str + rb->len, - rb->alloc - rb->len - 1 /* null byte */, 0); - - if (n_read > 0) - { - rb->str[rb->len += n_read] = '\0'; - continue; - } - if (n_read == 0) - return SOCKET_IO_EOF; - - if (errno == EAGAIN) - return SOCKET_IO_OK; - if (errno == EINTR) - continue; - - LOG_LIBC_FAILURE ("recv"); - return SOCKET_IO_ERROR; - } -} - -static enum socket_io_result -socket_io_try_write (int socket_fd, struct str *wb) -{ - ssize_t n_written; - while (wb->len) - { - n_written = send (socket_fd, wb->str, wb->len, 0); - if (n_written >= 0) - { - str_remove_slice (wb, 0, n_written); - continue; - } - - if (errno == EAGAIN) - return SOCKET_IO_OK; - if (errno == EINTR) - continue; - - LOG_LIBC_FAILURE ("send"); - return SOCKET_IO_ERROR; - } - return SOCKET_IO_OK; -} - // --- PulseAudio mainloop abstraction ----------------------------------------- struct pa_io_event @@ -467,650 +406,6 @@ poller_pa_run (struct pa_mainloop_api *api) return data->result; } -// --- MPD client interface ---------------------------------------------------- - -// This is a rather thin MPD client interface intended for basic tasks - -#define MPD_SUBSYSTEM_TABLE(XX) \ - XX (DATABASE, 0, "database") \ - XX (UPDATE, 1, "update") \ - XX (STORED_PLAYLIST, 2, "stored_playlist") \ - XX (PLAYLIST, 3, "playlist") \ - XX (PLAYER, 4, "player") \ - XX (MIXER, 5, "mixer") \ - XX (OUTPUT, 6, "output") \ - XX (OPTIONS, 7, "options") \ - XX (STICKER, 8, "sticker") \ - XX (SUBSCRIPTION, 9, "subscription") \ - XX (MESSAGE, 10, "message") - -enum mpd_subsystem -{ -#define XX(a, b, c) MPD_SUBSYSTEM_ ## a = (1 << b), - MPD_SUBSYSTEM_TABLE (XX) -#undef XX - MPD_SUBSYSTEM_MAX -}; - -static const char *mpd_subsystem_names[] = -{ -#define XX(a, b, c) [b] = c, - MPD_SUBSYSTEM_TABLE (XX) -#undef XX -}; - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -enum mpd_client_state -{ - MPD_DISCONNECTED, ///< Not connected - MPD_CONNECTING, ///< Currently connecting - MPD_CONNECTED ///< Connected -}; - -struct mpd_response -{ - bool success; ///< OK or ACK - - // ACK-only fields: - - int error; ///< Numeric error value (ack.h) - int list_offset; ///< Offset of command in list - char *current_command; ///< Name of the erroring command - char *message_text; ///< Error message -}; - -/// Task completion callback -typedef void (*mpd_client_task_cb) (const struct mpd_response *response, - const struct str_vector *data, void *user_data); - -struct mpd_client_task -{ - LIST_HEADER (struct mpd_client_task) - - mpd_client_task_cb callback; ///< Callback on completion - void *user_data; ///< User data -}; - -struct mpd_client -{ - struct poller *poller; ///< Poller - - // Connection: - - enum mpd_client_state state; ///< Connection state - struct connector *connector; ///< Connection establisher - - int socket; ///< MPD socket - struct str read_buffer; ///< Input yet to be processed - struct str write_buffer; ///< Outut yet to be be sent out - struct poller_fd socket_event; ///< We can read from the socket - - struct poller_timer timeout_timer; ///< Connection seems to be dead - - // Protocol: - - bool got_hello; ///< Got the OK MPD hello message - - bool idling; ///< Sent idle as the last command - unsigned idling_subsystems; ///< Subsystems we're idling for - bool in_list; ///< We're inside a command list - - struct mpd_client_task *tasks; ///< Task queue - struct mpd_client_task *tasks_tail; ///< Tail of task queue - struct str_vector data; ///< Data from last command - - // User configuration: - - void *user_data; ///< User data for callbacks - - /// Callback after connection has been successfully established - void (*on_connected) (void *user_data); - - /// Callback for general failures or even normal disconnection; - /// the interface is reinitialized - void (*on_failure) (void *user_data); - - /// Callback to receive "idle" updates. - /// Remember to restart the idle if needed. - void (*on_event) (unsigned subsystems, void *user_data); -}; - -static void mpd_client_reset (struct mpd_client *self); -static void mpd_client_destroy_connector (struct mpd_client *self); - -static void -mpd_client_init (struct mpd_client *self, struct poller *poller) -{ - memset (self, 0, sizeof *self); - - self->poller = poller; - self->socket = -1; - - str_init (&self->read_buffer); - str_init (&self->write_buffer); - - str_vector_init (&self->data); - - poller_fd_init (&self->socket_event, poller, -1); - poller_timer_init (&self->timeout_timer, poller); -} - -static void -mpd_client_free (struct mpd_client *self) -{ - // So that we don't have to repeat most of the stuff - mpd_client_reset (self); - - str_free (&self->read_buffer); - str_free (&self->write_buffer); - - str_vector_free (&self->data); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -/// Reinitialize the interface so that you can reconnect anew -static void -mpd_client_reset (struct mpd_client *self) -{ - if (self->state == MPD_CONNECTING) - mpd_client_destroy_connector (self); - - if (self->socket != -1) - xclose (self->socket); - self->socket = -1; - - self->socket_event.closed = true; - poller_fd_reset (&self->socket_event); - poller_timer_reset (&self->timeout_timer); - - str_reset (&self->read_buffer); - str_reset (&self->write_buffer); - - str_vector_reset (&self->data); - - self->got_hello = false; - self->idling = false; - self->idling_subsystems = 0; - self->in_list = false; - - LIST_FOR_EACH (struct mpd_client_task, iter, self->tasks) - free (iter); - self->tasks = self->tasks_tail = NULL; - - self->state = MPD_DISCONNECTED; -} - -static void -mpd_client_fail (struct mpd_client *self) -{ - mpd_client_reset (self); - if (self->on_failure) - self->on_failure (self->user_data); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -static bool -mpd_client_parse_response (const char *p, struct mpd_response *response) -{ - if (!strcmp (p, "OK")) - return response->success = true; - if (!strcmp (p, "list_OK")) - // TODO: either implement this or fail the connection properly - hard_assert (!"command_list_ok_begin not implemented"); - - char *end = NULL; - if (*p++ != 'A' || *p++ != 'C' || *p++ != 'K' || *p++ != ' ' || *p++ != '[') - return false; - - errno = 0; - response->error = strtoul (p, &end, 10); - if (errno != 0 || end == p) - return false; - p = end; - if (*p++ != '@') - return false; - - errno = 0; - response->list_offset = strtoul (p, &end, 10); - if (errno != 0 || end == p) - return false; - p = end; - if (*p++ != ']' || *p++ != ' ' || *p++ != '{' || !(end = strchr (p, '}'))) - return false; - - response->current_command = xstrndup (p, end - p); - p = end + 1; - - if (*p++ != ' ') - return false; - - response->message_text = xstrdup (p); - response->success = false; - return true; -} - -static void -mpd_client_dispatch (struct mpd_client *self, struct mpd_response *response) -{ - struct mpd_client_task *task; - if (!(task = self->tasks)) - return; - - if (task->callback) - task->callback (response, &self->data, task->user_data); - str_vector_reset (&self->data); - - LIST_UNLINK_WITH_TAIL (self->tasks, self->tasks_tail, task); - free (task); -} - -static bool -mpd_client_parse_hello (struct mpd_client *self, const char *line) -{ - const char hello[] = "OK MPD "; - if (strncmp (line, hello, sizeof hello - 1)) - { - print_debug ("invalid MPD hello message"); - return false; - } - - // TODO: call "on_connected" now. We should however also set up a timer - // so that we don't wait on this message forever. - return self->got_hello = true; -} - -static bool -mpd_client_parse_line (struct mpd_client *self, const char *line) -{ - print_debug ("MPD >> %s", line); - - if (!self->got_hello) - return mpd_client_parse_hello (self, line); - - struct mpd_response response; - memset (&response, 0, sizeof response); - if (mpd_client_parse_response (line, &response)) - { - mpd_client_dispatch (self, &response); - free (response.current_command); - free (response.message_text); - } - else - str_vector_add (&self->data, line); - return true; -} - -/// All output from MPD commands seems to be in a trivial "key: value" format -static char * -mpd_client_parse_kv (char *line, char **value) -{ - char *sep; - if (!(sep = strstr (line, ": "))) - return NULL; - - *sep = 0; - *value = sep + 2; - return line; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -static void -mpd_client_update_poller (struct mpd_client *self) -{ - poller_fd_set (&self->socket_event, - self->write_buffer.len ? (POLLIN | POLLOUT) : POLLIN); -} - -static bool -mpd_client_process_input (struct mpd_client *self) -{ - // Split socket input at newlines and process them separately - struct str *rb = &self->read_buffer; - char *start = rb->str, *end = start + rb->len; - for (char *p = start; p < end; p++) - { - if (*p != '\n') - continue; - - *p = 0; - if (!mpd_client_parse_line (self, start)) - return false; - start = p + 1; - } - - str_remove_slice (rb, 0, start - rb->str); - return true; -} - -static void -mpd_client_on_ready (const struct pollfd *pfd, void *user_data) -{ - (void) pfd; - - struct mpd_client *self = user_data; - if (socket_io_try_read (self->socket, &self->read_buffer) != SOCKET_IO_OK - || !mpd_client_process_input (self) - || socket_io_try_write (self->socket, &self->write_buffer) != SOCKET_IO_OK) - mpd_client_fail (self); - else - mpd_client_update_poller (self); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -static bool -mpd_client_must_quote_char (char c) -{ - return (unsigned char) c <= ' ' || c == '"' || c == '\''; -} - -static bool -mpd_client_must_quote (const char *s) -{ - if (!*s) - return true; - for (; *s; s++) - if (mpd_client_must_quote_char (*s)) - return true; - return false; -} - -static void -mpd_client_quote (const char *s, struct str *output) -{ - str_append_c (output, '"'); - for (; *s; s++) - { - if (mpd_client_must_quote_char (*s)) - str_append_c (output, '\\'); - str_append_c (output, *s); - } - str_append_c (output, '"'); -} - -/// Beware that delivery of the event isn't deferred and you musn't make -/// changes to the interface while processing the event! -static void -mpd_client_add_task - (struct mpd_client *self, mpd_client_task_cb cb, void *user_data) -{ - // This only has meaning with command_list_ok_begin, and then it requires - // special handling (all in-list tasks need to be specially marked and - // later flushed if an early ACK or OK arrives). - hard_assert (!self->in_list); - - struct mpd_client_task *task = xcalloc (1, sizeof *self); - task->callback = cb; - task->user_data = user_data; - LIST_APPEND_WITH_TAIL (self->tasks, self->tasks_tail, task); -} - -/// Send a command. Remember to call mpd_client_add_task() to handle responses, -/// unless the command is being sent in a list. -static void mpd_client_send_command - (struct mpd_client *self, const char *command, ...) ATTRIBUTE_SENTINEL; - -static void -mpd_client_send_commandv (struct mpd_client *self, char **commands) -{ - // Automatically interrupt idle mode - if (self->idling) - { - poller_timer_reset (&self->timeout_timer); - - self->idling = false; - self->idling_subsystems = 0; - mpd_client_send_command (self, "noidle", NULL); - } - - struct str line; - str_init (&line); - - for (; *commands; commands++) - { - if (line.len) - str_append_c (&line, ' '); - - if (mpd_client_must_quote (*commands)) - mpd_client_quote (*commands, &line); - else - str_append (&line, *commands); - } - - print_debug ("MPD << %s", line.str); - str_append_c (&line, '\n'); - str_append_str (&self->write_buffer, &line); - str_free (&line); - - mpd_client_update_poller (self); -} - -static void -mpd_client_send_command (struct mpd_client *self, const char *command, ...) -{ - struct str_vector v; - str_vector_init (&v); - - va_list ap; - va_start (ap, command); - for (; command; command = va_arg (ap, const char *)) - str_vector_add (&v, command); - va_end (ap); - - mpd_client_send_commandv (self, v.vector); - str_vector_free (&v); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -static void -mpd_client_list_begin (struct mpd_client *self) -{ - hard_assert (!self->in_list); - mpd_client_send_command (self, "command_list_begin", NULL); - self->in_list = true; -} - -/// End a list of commands. Remember to call mpd_client_add_task() -/// to handle the summary response. -static void -mpd_client_list_end (struct mpd_client *self) -{ - hard_assert (self->in_list); - mpd_client_send_command (self, "command_list_end", NULL); - self->in_list = false; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -static bool -mpd_resolve_subsystem (const char *name, unsigned *output) -{ - for (size_t i = 0; i < N_ELEMENTS (mpd_subsystem_names); i++) - if (!strcasecmp_ascii (name, mpd_subsystem_names[i])) - { - *output |= 1 << i; - return true; - } - return false; -} - -static void -mpd_client_on_idle_return (const struct mpd_response *response, - const struct str_vector *data, void *user_data) -{ - (void) response; - - struct mpd_client *self = user_data; - unsigned subsystems = 0; - for (size_t i = 0; i < data->len; i++) - { - char *value, *key; - if (!(key = mpd_client_parse_kv (data->vector[i], &value))) - print_debug ("%s: %s", "erroneous MPD output", data->vector[i]); - else if (strcasecmp_ascii (key, "changed")) - print_debug ("%s: %s", "unexpected idle key", key); - else if (!mpd_resolve_subsystem (value, &subsystems)) - print_debug ("%s: %s", "unknown subsystem", value); - } - - // Not resetting "idling" here, we may send an extra "noidle" no problem - if (self->on_event && subsystems) - self->on_event (subsystems, self->user_data); -} - -static void mpd_client_idle (struct mpd_client *self, unsigned subsystems); - -static void -mpd_client_on_timeout (void *user_data) -{ - struct mpd_client *self = user_data; - unsigned subsystems = self->idling_subsystems; - - // Just sending this out should bring a dead connection down over TCP - // TODO: set another timer to make sure the ping reply arrives - mpd_client_send_command (self, "ping", NULL); - mpd_client_add_task (self, NULL, NULL); - - // Restore the incriminating idle immediately - mpd_client_idle (self, subsystems); -} - -/// When not expecting to send any further commands, you should call this -/// in order to keep the connection alive. Or to receive updates. -static void -mpd_client_idle (struct mpd_client *self, unsigned subsystems) -{ - hard_assert (!self->in_list); - - struct str_vector v; - str_vector_init (&v); - - str_vector_add (&v, "idle"); - for (size_t i = 0; i < N_ELEMENTS (mpd_subsystem_names); i++) - if (subsystems & (1 << i)) - str_vector_add (&v, mpd_subsystem_names[i]); - - mpd_client_send_commandv (self, v.vector); - str_vector_free (&v); - - self->timeout_timer.dispatcher = mpd_client_on_timeout; - self->timeout_timer.user_data = self; - poller_timer_set (&self->timeout_timer, 5 * 60 * 1000); - - mpd_client_add_task (self, mpd_client_on_idle_return, self); - self->idling = true; - self->idling_subsystems = subsystems; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -static void -mpd_client_finish_connection (struct mpd_client *self, int socket) -{ - set_blocking (socket, false); - self->socket = socket; - self->state = MPD_CONNECTED; - - poller_fd_init (&self->socket_event, self->poller, self->socket); - self->socket_event.dispatcher = mpd_client_on_ready; - self->socket_event.user_data = self; - - mpd_client_update_poller (self); - - if (self->on_connected) - self->on_connected (self->user_data); -} - -static void -mpd_client_destroy_connector (struct mpd_client *self) -{ - if (self->connector) - connector_free (self->connector); - free (self->connector); - self->connector = NULL; - - // Not connecting anymore - self->state = MPD_DISCONNECTED; -} - -static void -mpd_client_on_connector_failure (void *user_data) -{ - struct mpd_client *self = user_data; - mpd_client_destroy_connector (self); - mpd_client_fail (self); -} - -static void -mpd_client_on_connector_connected - (void *user_data, int socket, const char *host) -{ - (void) host; - - struct mpd_client *self = user_data; - mpd_client_destroy_connector (self); - mpd_client_finish_connection (self, socket); -} - -static bool -mpd_client_connect_unix (struct mpd_client *self, const char *address, - struct error **e) -{ - int fd = socket (AF_UNIX, SOCK_STREAM, 0); - if (fd == -1) - { - error_set (e, "%s: %s", "socket", strerror (errno)); - return false; - } - - // Expand tilde if needed - char *expanded = resolve_filename (address, xstrdup); - - struct sockaddr_un sun; - sun.sun_family = AF_UNIX; - strncpy (sun.sun_path, expanded, sizeof sun.sun_path); - sun.sun_path[sizeof sun.sun_path - 1] = 0; - - free (expanded); - - if (connect (fd, (struct sockaddr *) &sun, sizeof sun)) - { - error_set (e, "%s: %s", "connect", strerror (errno)); - return false; - } - - mpd_client_finish_connection (self, fd); - return true; -} - -static bool -mpd_client_connect (struct mpd_client *self, const char *address, - const char *service, struct error **e) -{ - hard_assert (self->state == MPD_DISCONNECTED); - - // If it looks like a path, assume it's a UNIX socket - if (strchr (address, '/')) - return mpd_client_connect_unix (self, address, e); - - struct connector *connector = xmalloc (sizeof *connector); - connector_init (connector, self->poller); - self->connector = connector; - - connector->user_data = self; - connector->on_connected = mpd_client_on_connector_connected; - connector->on_failure = mpd_client_on_connector_failure; - - connector_add_target (connector, address, service); - self->state = MPD_CONNECTING; - return true; -} - // --- NUT --------------------------------------------------------------------- // More or less copied and pasted from the MPD client. This code doesn't even @@ -2176,6 +1471,16 @@ mpd_on_failure (void *user_data) } static void +mpd_on_io_hook (void *user_data, bool outgoing, const char *line) +{ + (void) user_data; + if (outgoing) + print_debug ("MPD << %s", line); + else + print_debug ("MPD >> %s", line); +} + +static void on_mpd_reconnect (void *user_data) { struct app_context *ctx = user_data; @@ -2185,6 +1490,7 @@ on_mpd_reconnect (void *user_data) c->on_failure = mpd_on_failure; c->on_connected = mpd_on_connected; c->on_event = mpd_on_events; + c->on_io_hook = mpd_on_io_hook; struct error *e = NULL; if (!mpd_client_connect (&ctx->mpd_client, @@ -2262,7 +1568,7 @@ nut_process_ups (struct app_context *ctx, struct str_vector *ups_list, struct str_vector v; str_vector_init (&v); - cstr_split_ignore_empty (status, ' ', &v); + cstr_split (status, " ", true, &v); for (size_t i = 0; i < v.len; i++) { const char *status = v.vector[i]; diff --git a/fancontrol-ng.c b/fancontrol-ng.c index a282013..0b25e28 100644 --- a/fancontrol-ng.c +++ b/fancontrol-ng.c @@ -25,13 +25,6 @@ #define PROGRAM_NAME "fancontrol-ng" #include "liberty/liberty.c" -/// Shorthand to set an error and return failure from the function -#define FAIL(...) \ - BLOCK_START \ - error_set (e, __VA_ARGS__); \ - return false; \ - BLOCK_END - // --- Main program ------------------------------------------------------------ struct device @@ -133,8 +126,7 @@ config_validate_nonnegative (const struct config_item *item, struct error **e) if (item->value.integer >= 0) return true; - error_set (e, "must be non-negative"); - return false; + return error_set (e, "must be non-negative"); } static struct config_schema g_config_device[] = @@ -274,10 +266,12 @@ pwm_update (struct paths *paths, struct config_item *pwm, struct error **e) int64_t min_start = get_config_integer (pwm, "min_start"); int64_t min_stop = get_config_integer (pwm, "min_stop"); +#define FAIL(...) error_set (e, __VA_ARGS__) if (min_temp >= max_temp) FAIL ("min_temp must be less than max_temp"); if (pwm_max > 255) FAIL ("pwm_max must be at most 255"); if (min_stop >= pwm_max) FAIL ("min_stop must be less than pwm_max"); if (min_stop < pwm_min) FAIL ("min_stop must be at least pwm_min"); +#undef FAIL // I'm not sure if this strangely complicated computation is justifiable double where @@ -423,29 +417,6 @@ device_create (struct app_context *ctx, const char *path, // --- Configuration ----------------------------------------------------------- -// TODO: consider moving to liberty, -// degesch and json-rpc-shell have exactly the same function -static struct config_item * -load_configuration_file (const char *filename, struct error **e) -{ - struct config_item *root = NULL; - - struct str data; - str_init (&data); - if (!read_file (filename, &data, e)) - goto end; - - struct error *error = NULL; - if (!(root = config_item_parse (data.str, data.len, false, &error))) - { - error_set (e, "parse error: %s", error->message); - error_free (error); - } -end: - str_free (&data); - return root; -} - // There is no room for errors in the configuration, everything must be valid. // Thus the reset to defaults on invalid values is effectively disabled here. static bool @@ -470,7 +441,7 @@ apply_schema (struct config_schema *schema, struct config_item *object, { // The standard warning is inappropriate here error_free (warning); - FAIL ("invalid item `%s'", schema->name); + return error_set (e, "invalid item `%s'", schema->name); } return true; } @@ -488,9 +459,9 @@ check_device_configuration (struct config_item *subtree, struct error **e) if (!(pwms = config_item_get (subtree, "pwms", e))) return false; if (pwms->type != CONFIG_ITEM_OBJECT) - FAIL ("`%s' is not an object", "pwms"); + return error_set (e, "`%s' is not an object", "pwms"); if (!pwms->value.object.len) - FAIL ("no PWMs defined"); + return error_set (e, "no PWMs defined"); // Check regular fields in all PWM subobjects struct str_map_iter iter; @@ -509,7 +480,10 @@ check_device_configuration (struct config_item *subtree, struct error **e) return false; } if (!get_config_string (pwm, "temp")) - FAIL ("PWM `%s': %s", subpath, "`temp' cannot be null"); + { + return error_set (e, + "PWM `%s': %s", subpath, "`temp' cannot be null"); + } } return true; } @@ -518,7 +492,7 @@ static void load_configuration (struct app_context *ctx, const char *config_path) { struct error *e = NULL; - struct config_item *root = load_configuration_file (config_path, &e); + struct config_item *root = config_read_from_file (config_path, &e); if (e) { diff --git a/liberty b/liberty -Subproject 052d2ffc9a3141ef2bb771f70190ed7a0bb9da4 +Subproject 2a15b1de700eb4e20c6bebb9742c8e20fffc968 |