From 641032e1d5d39a6a8783e9586779b25152434521 Mon Sep 17 00:00:00 2001 From: Andrew Opalach Date: Sat, 19 Oct 2024 15:11:34 -0400 Subject: Watch for config changes Signed-off-by: Andrew Opalach --- taro/config.h | 31 ++++++++++++------------ taro/daemon.c | 75 +++++++++++++++++++++++++++++++++++++++++++---------------- 2 files changed, 70 insertions(+), 36 deletions(-) (limited to 'taro') diff --git a/taro/config.h b/taro/config.h index 5b9a257..a8fffd1 100644 --- a/taro/config.h +++ b/taro/config.h @@ -9,8 +9,10 @@ struct config { str config_dir; + str config_path; str asset_dir; str wallpaper_dir; + bool valid; }; AL_UNUSED_FUNCTION_PUSH @@ -18,6 +20,7 @@ AL_UNUSED_FUNCTION_PUSH static void close_config(struct config *conf) { al_str_free(&conf->config_dir); + al_str_free(&conf->config_path); al_str_free(&conf->asset_dir); al_str_free(&conf->wallpaper_dir); } @@ -37,27 +40,27 @@ static void maybe_replace_home_in_path(str *dest, const char *envhome, const cha } } -static bool parse_config_json(struct config *conf, char *envhome, json_t *root) +static void parse_config_json(struct config *conf, char *envhome, json_t *root) { - bool valid = true; + conf->valid = true; json_t *directories = json_object_get(root, "directories"); if (!directories) { - valid = false; + conf->valid = false; goto out; } json_t *assets = json_object_get(directories, "assets"); if (!assets || !json_is_string(assets) || al_strlen(json_string_value(assets)) == 0) { al_log_error("taro", "asset directory not set or invalid"); - valid = false; + conf->valid = false; goto out; } json_t *wallpapers = json_object_get(directories, "wallpapers"); if (!wallpapers || !json_is_string(wallpapers) || al_strlen(json_string_value(wallpapers)) == 0) { al_log_error("taro", "wallpaper directory not set or invalid"); - valid = false; + conf->valid = false; goto out; } @@ -66,8 +69,6 @@ static bool parse_config_json(struct config *conf, char *envhome, json_t *root) out: json_decref(root); - - return valid; } static bool open_config(struct config *conf, bool create) @@ -85,25 +86,23 @@ static bool open_config(struct config *conf, bool create) } } - str config_path; - al_str_clone(&config_path, &conf->config_dir); - al_str_cat(&config_path, al_str_c("/config.json")); - if (!aki_file_exists(&config_path)) { - if (aki_file_create(&config_path)) { + al_str_clone(&conf->config_path, &conf->config_dir); + al_str_cat(&conf->config_path, al_str_c("/config.json")); + if (!aki_file_exists(&conf->config_path)) { + if (aki_file_create(&conf->config_path)) { json_t *blank = json_object(); json_t *directories = json_object(); json_object_set_new(directories, "assets", json_string_nocheck("")); json_object_set_new(directories, "wallpapers", json_string_nocheck("")); json_object_set_new(blank, "directories", directories); - aki_dump_json_and_decref(&config_path, blank); + aki_dump_json_and_decref(&conf->config_path, blank); } } - json_t *root = aki_file_open_as_json(&config_path); - al_str_free(&config_path); + json_t *root = aki_file_open_as_json(&conf->config_path); if (!root) goto err; - if (!parse_config_json(conf, envhome, root)) goto err; + parse_config_json(conf, envhome, root); return true; err: diff --git a/taro/daemon.c b/taro/daemon.c index 682a8d3..bf7434c 100644 --- a/taro/daemon.c +++ b/taro/daemon.c @@ -16,10 +16,10 @@ struct monitor { struct stl_monitor *os; - struct aki_fs_event fs_event; - bool self_event_skip; str config_dir; str selection_path; + struct aki_fs_event selection_event; + bool self_event_skip; pid_t pid; bool paused; bool covered; @@ -35,7 +35,7 @@ struct daemon { struct aki_poll context_poll; array(struct monitor *) monitors; struct aki_socket ipc_socket; - bool connected; + bool ipc_connected; struct aki_poll ipc_poll; struct { u8 *buf; @@ -49,6 +49,7 @@ struct daemon { ssize_t alloc; } ipc; struct config conf; + struct aki_fs_event conf_event; }; static s32 parse_and_set_props(str *selection, str *wallpaper_path, bool *is_package) @@ -133,6 +134,11 @@ static bool run_wallpaper(struct daemon *dmon, struct monitor *monitor) { maybe_kill_wallpaper(monitor); + if (!dmon->conf.valid) { + al_log_error("tarod", "config invalid, not setting wallpaper on %s", monitor->os->name); + return false; + } + str selection; monitor->self_event_skip = true; if (!aki_file_open_and_read_wholly(&monitor->selection_path, &selection, true)) { @@ -164,6 +170,12 @@ static bool run_wallpaper(struct daemon *dmon, struct monitor *monitor) al_str_cat(&wallpaper_path, al_str_c("/scene.pkg")); } + if ((is_package && !aki_file_exists(&wallpaper_path)) || (!is_package && !aki_dir_exists(&wallpaper_path))) { + al_log_error("tarod", "wallpaper doesn't exist at %.*s", AL_STR_PRINTF(&wallpaper_path)); + al_str_free(&wallpaper_path); + return false; + } + al_log_info("tarod", "setting wallpaper %.*s on %s", AL_STR_PRINTF(&wallpaper_path), monitor->os->name); char width[8], height[8]; @@ -171,7 +183,6 @@ static bool run_wallpaper(struct daemon *dmon, struct monitor *monitor) al_snprintf(height, sizeof(height), "%d", monitor->os->height / monitor->os->scale); char *c_str0 = al_str_to_c_str(&wallpaper_path); - al_str_free(&wallpaper_path); char *c_str1 = al_str_to_c_str(&dmon->conf.asset_dir); if (is_package) { monitor->pid = exec_or_exit((char *[]){ @@ -180,6 +191,7 @@ static bool run_wallpaper(struct daemon *dmon, struct monitor *monitor) monitor->pid = exec_or_exit((char *[]){ "mauri", "-d", c_str0, "-a", c_str1, "-m", monitor->os->name, "-w", width, "-h", height, NULL}); } + al_str_free(&wallpaper_path); al_free(c_str0); al_free(c_str1); @@ -248,17 +260,31 @@ static void output_discovered_callback(void *userdata, struct stl_monitor *os_mo run_wallpaper(dmon, monitor); monitor->self_event_skip = false; - aki_fs_event_init(&monitor->fs_event, &monitor->selection_path, AKI_CLOSE_WRITE, - selection_fs_event_callback, monitor); - aki_fs_event_start(&monitor->fs_event, &monitor->dmon->loop); + aki_fs_event_init(&monitor->selection_event, &monitor->selection_path, + AKI_CLOSE_WRITE, selection_fs_event_callback, monitor); + aki_fs_event_start(&monitor->selection_event, &monitor->dmon->loop); +} + +static void conf_fs_event_callback(void *userdata, struct inotify_event *event) +{ + struct daemon *dmon = (struct daemon *)userdata; + (void)event; + close_config(&dmon->conf); + if (!open_config(&dmon->conf, false)) { + al_log_error("tarod", "config became unavailable, exiting..."); + exit(EXIT_FAILURE); + } + struct monitor *monitor; + al_array_foreach(dmon->monitors, i, monitor) { + run_wallpaper(dmon, monitor); + } } static void close_monitor(struct monitor *monitor) { al_str_free(&monitor->config_dir); al_str_free(&monitor->selection_path); - aki_fs_event_stop(&monitor->fs_event); - aki_fs_event_free(&monitor->fs_event); + aki_fs_event_free(&monitor->selection_event); } static void ipc_handle_subscribe_success(json_t *root) @@ -321,16 +347,14 @@ static void ipc_poll_callback(void *userdata, s32 revents) struct daemon *dmon = (struct daemon *)userdata; if (revents & AKI_POLL_WRITE) { - if (!dmon->connected) { + al_assert(!dmon->ipc_connected); + if (!dmon->ipc_connected) { al_log_info("tarod", "connected to sway ipc socket"); - dmon->connected = true; + dmon->ipc_connected = true; } - if (!dmon->out.buf) return; dmon->out.index += aki_socket_write(&dmon->ipc_socket, dmon->out.buf + dmon->out.index, dmon->out.size - dmon->out.index); if (dmon->out.index == dmon->out.size) { - al_free(dmon->out.buf); - dmon->out.buf = NULL; aki_poll_stop(&dmon->ipc_poll); aki_poll_set(&dmon->ipc_poll, aki_socket_get_fd(&dmon->ipc_socket), AKI_POLL_READ); aki_poll_start(&dmon->ipc_poll, &dmon->loop); @@ -369,7 +393,14 @@ static void context_poll_callback(void *userdata, s32 revents) static void quit_signal_callback(void *userdata) { struct daemon *dmon = (struct daemon *)userdata; - aki_event_loop_break_one(&dmon->loop); + struct monitor *monitor; + al_array_foreach(dmon->monitors, i, monitor) { + aki_fs_event_stop(&monitor->selection_event); + } + aki_fs_event_stop(&dmon->conf_event); + aki_poll_stop(&dmon->ipc_poll); + aki_poll_stop(&dmon->context_poll); + aki_signal_stop(&dmon->quit_signal); } static struct daemon dmon = { 0 }; @@ -389,10 +420,6 @@ static void sigint_handler(s32 signum) aki_signal_send(&dmon.quit_signal); } -// TODO: -// - daemon quit -// - systemd? and related testing - s32 main(void) { if (!aki_common_init() || !open_config(&dmon.conf, true)) return EXIT_FAILURE; @@ -463,7 +490,7 @@ s32 main(void) aki_socket_set_blocking(&dmon.ipc_socket, false); aki_poll_init(&dmon.ipc_poll, ipc_poll_callback, &dmon); aki_poll_set(&dmon.ipc_poll, aki_socket_get_fd(&dmon.ipc_socket), AKI_POLL_WRITE); - dmon.connected = false; + dmon.ipc_connected = false; char *swaysock = getenv("SWAYSOCK"); if (swaysock && aki_socket_connect(&dmon.ipc_socket, al_str_cr(swaysock), 0)) { aki_poll_start(&dmon.ipc_poll, &dmon.loop); @@ -471,13 +498,21 @@ s32 main(void) al_log_warn("tarod", "couldn't connect to sway ipc socket"); } + aki_fs_event_init(&dmon.conf_event, &dmon.conf.config_path, + AKI_CLOSE_WRITE, conf_fs_event_callback, &dmon); + aki_fs_event_start(&dmon.conf_event, &dmon.loop); + aki_event_loop_run(&dmon.loop); al_array_foreach(dmon.monitors, i, monitor) { close_monitor(monitor); + al_free(monitor); } al_array_free(dmon.monitors); + aki_fs_event_free(&dmon.conf_event); + + al_free(dmon.out.buf); al_free(dmon.ipc.buf); aki_socket_close(&dmon.ipc_socket); -- cgit v1.2.3-101-g0448