summaryrefslogtreecommitdiff
path: root/taro
diff options
context:
space:
mode:
Diffstat (limited to 'taro')
-rw-r--r--taro/config.h31
-rw-r--r--taro/daemon.c75
2 files changed, 70 insertions, 36 deletions
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);