aboutsummaryrefslogtreecommitdiff
path: root/ark/src
diff options
context:
space:
mode:
Diffstat (limited to 'ark/src')
-rw-r--r--ark/src/soul.c198
-rw-r--r--ark/src/wl.c238
-rw-r--r--ark/src/world.c199
-rw-r--r--ark/src/world_load.c (renamed from ark/src/soul_load.c)22
4 files changed, 403 insertions, 254 deletions
diff --git a/ark/src/soul.c b/ark/src/soul.c
deleted file mode 100644
index 4268cd5..0000000
--- a/ark/src/soul.c
+++ /dev/null
@@ -1,198 +0,0 @@
-#include "soul.h"
-
-#include <ctype.h>
-#include <dlfcn.h>
-#include <pthread.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-/* Utility function for showing the marshalled states as hex code */
-static void shx(uint8_t *state, uint32_t sz)
-{
- uint32_t i = 0;
- while (i < sz) {
- for (int j = 0; j < 16; ++j) {
- if (i < sz) {
- printf("%02x ", (unsigned int)state[i]);
- }
- else {
- printf(" ");
- }
- ++i;
- }
-
- i -= 16;
-
- printf(" ");
-
- for (int j = 0; j < 16; ++j) {
- if (i < sz) {
- if (isprint(state[i]) && !isspace(state[i])) {
- printf("%c", state[i]);
- }
- else {
- printf(".");
- }
- }
- else {
- printf(" ");
- }
- ++i;
- }
- printf("\n");
- }
-}
-
-int load_soul_from_dl_(dlhandle_t dl, soul_t *soul);
-
-static void lock(soul_t *soul) { pthread_mutex_lock(&soul->lock); };
-
-static void unlock(soul_t *soul) { pthread_mutex_unlock(&soul->lock); };
-
-static int load_soul_from_file_(int argc, char **argv, const char *filename,
- soul_t *soul)
-{
- dlhandle_t lib = dlopen(filename, RTLD_NOW | RTLD_GLOBAL);
- int ec = 0;
-
- if (!lib) {
- fprintf(stderr, "Failed to open library: %s: %s\n", filename, dlerror());
- ec = 1;
- goto end;
- }
-
- printf("Loading file.\n");
- ec = load_soul_from_dl_(lib, soul);
-
- if (ec) {
- goto end;
- }
-
- strncpy(soul->filename, filename, sizeof(soul->filename));
- soul->argc = argc;
- soul->argv = argv;
-
- soul->arksoul_export_load(soul->argc, soul->argv);
-end:
- return ec;
-}
-
-static void maybe_run_metaload(int argc, char **argv, soul_t *soul)
-{
- static char *loaded_souls[12];
- int i;
- for (i = 0; i < 12 && loaded_souls[i]; ++i) {
- if (strcmp(loaded_souls[i], soul->soul_name) == 0) {
- return; // Soul is already loaded
- }
- }
- loaded_souls[i] = strdup(soul->soul_name);
-
- printf("First time loading %s, running metaload.\n", soul->soul_name);
- if (soul->arksoul_export_metaload) {
- soul->arksoul_export_metaload(argc, argv);
- }
-}
-
-int load_soul_from_file(int argc, char **argv, const char *filename,
- soul_t *soul)
-{
- memset(soul, 0, sizeof(*soul));
-
- pthread_mutexattr_t attr;
- if (pthread_mutexattr_init(&attr)) {
- perror("pthread_mutexattr_init");
- return 1;
- }
-
- if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE)) {
- perror("pthread_mutexattr_settype");
- return 1;
- }
-
- if (pthread_mutex_init(&soul->lock, &attr)) {
- pthread_mutexattr_destroy(&attr);
- perror("pthread_mutexattr_init");
- return 1;
- }
- pthread_mutexattr_destroy(&attr);
- int rc = load_soul_from_file_(argc, argv, filename, soul);
-
- if (rc == 0) {
- maybe_run_metaload(argc, argv, soul);
- }
-
- return rc;
-}
-
-int soul_hot_reload_same_state(soul_t *soul)
-{
- char filename_cpy[PATH_MAX];
- strncpy(filename_cpy, soul->filename, sizeof(filename_cpy));
- return soul_hot_reload(soul->argc, soul->argv, filename_cpy, soul);
-}
-
-int soul_hot_reload(int argc, char **argv, const char *filepath, soul_t *soul)
-{
- int ec = 0;
- uint32_t sz = 0;
- uint8_t *marshalled_state = NULL;
-
- printf("Hot Reloading %s\n", soul->soul_name);
- lock(soul);
-
- printf("Marshalling state ...\n");
- marshalled_state = soul->arksoul_export_preserve(soul->state, &sz);
-
- printf("Calling teardown ...\n");
- soul->arksoul_export_release(soul->state);
-
- printf("State Marshalled:\n");
- shx(marshalled_state, sz);
-
- printf("Unloading old library handle.\n");
- if (dlclose(soul->library_handle)) {
- printf("Could not close library handle: %s\n", dlerror());
- }
-
- if ((ec = load_soul_from_file_(argc, argv, filepath, soul))) {
- goto fail;
- }
-
- printf("Hot starting soul ...\n");
- soul->state = soul->arksoul_export_rebirth(soul, marshalled_state, sz);
-
-fail:
- free(marshalled_state);
- unlock(soul);
- return ec;
-}
-
-void soul_run_requested_actions(soul_t *soul)
-{
- lock(soul);
- requested_action_t requested_actions[MAX_QUEUED_ACTIONS];
- size_t n_requested_actions = soul->n_requested_actions;
- memcpy(&requested_actions, soul->requested_actions,
- sizeof(requested_actions));
- soul->n_requested_actions = 0;
- unlock(soul);
-
- size_t i;
- for (i = 0; i < n_requested_actions; ++i) {
- requested_actions[i].action(soul, requested_actions[i].str_arg);
- if (requested_actions[i].arg_dtor) {
- requested_actions[i].arg_dtor(requested_actions[i].ptr_arg);
- }
- }
-}
-
-void soul_cold_start(soul_t *soul)
-{
- lock(soul);
- soul->state = soul->arksoul_export_ensoul(soul);
- unlock(soul);
-}
diff --git a/ark/src/wl.c b/ark/src/wl.c
index b9ce952..fc0ddc7 100644
--- a/ark/src/wl.c
+++ b/ark/src/wl.c
@@ -9,8 +9,15 @@
#include "xdg-decoration-unstable-v1-client-protocol.h"
-// This macro is responsible for calling a handler on a soul. This macro will
-// acquire the soul's lock, call the member with the arguments and update the
+#include <wlr/interfaces/wlr_buffer.h>
+
+#ifdef ARK_HAVE_CAIRO
+#include <cairo.h>
+#include <drm_fourcc.h>
+#endif
+
+// This macro is responsible for calling a handler on a world. This macro will
+// acquire the world's lock, call the member with the arguments and update the
// state.
//
// This only works on function which have the format:
@@ -18,15 +25,133 @@
// opqst_t function(args ..., opqst_t state);
//
// Note that the state parameter is omitted from this macro.
-#define soul_call_update_state(soul, member, ...) \
+#define world_call_update_state(world, member, ...) \
do { \
- soul_t *sl__ = &(soul); \
+ world_t *sl__ = &(world); \
pthread_mutex_lock(&sl__->lock); \
sl__->state = sl__->member(__VA_ARGS__, sl__->state); \
pthread_mutex_unlock(&sl__->lock); \
- soul_run_requested_actions(sl__); \
+ world_run_requested_actions(sl__); \
} while (0)
+#ifdef ARK_HAVE_CAIRO
+struct montis_image_buffer {
+ struct wlr_buffer base;
+ cairo_surface_t *surface;
+ uint32_t drm_format;
+};
+
+static void image_buffer_destroy(struct wlr_buffer *wlr_buffer)
+{
+ struct montis_image_buffer *buffer =
+ wl_container_of(wlr_buffer, buffer, base);
+ cairo_surface_destroy(buffer->surface);
+ free(buffer);
+}
+
+static bool image_buffer_begin_data_ptr_access(struct wlr_buffer *wlr_buffer,
+ uint32_t flags, void **data,
+ uint32_t *format, size_t *stride)
+{
+ if (flags & WLR_BUFFER_DATA_PTR_ACCESS_WRITE) {
+ return false;
+ }
+ struct montis_image_buffer *buffer =
+ wl_container_of(wlr_buffer, buffer, base);
+ cairo_surface_flush(buffer->surface);
+ *data = cairo_image_surface_get_data(buffer->surface);
+ *stride = cairo_image_surface_get_stride(buffer->surface);
+ *format = buffer->drm_format;
+ return true;
+}
+
+static void image_buffer_end_data_ptr_access(struct wlr_buffer *wlr_buffer) {}
+
+static const struct wlr_buffer_impl image_buffer_impl = {
+ .destroy = image_buffer_destroy,
+ .begin_data_ptr_access = image_buffer_begin_data_ptr_access,
+ .end_data_ptr_access = image_buffer_end_data_ptr_access,
+};
+
+static struct wlr_buffer *load_background_buffer(const char *path)
+{
+ cairo_surface_t *surface = cairo_image_surface_create_from_png(path);
+ if (cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS) {
+ cairo_surface_destroy(surface);
+ wlr_log(WLR_ERROR, "failed to load background image: %s", path);
+ return NULL;
+ }
+
+ cairo_format_t format = cairo_image_surface_get_format(surface);
+ uint32_t drm_format = DRM_FORMAT_ARGB8888;
+ if (format == CAIRO_FORMAT_RGB24) {
+ drm_format = DRM_FORMAT_XRGB8888;
+ }
+ else if (format != CAIRO_FORMAT_ARGB32) {
+ cairo_surface_destroy(surface);
+ wlr_log(WLR_ERROR, "unsupported background image format: %d", format);
+ return NULL;
+ }
+
+ int width = cairo_image_surface_get_width(surface);
+ int height = cairo_image_surface_get_height(surface);
+
+ struct montis_image_buffer *buffer = calloc(1, sizeof(*buffer));
+ if (!buffer) {
+ cairo_surface_destroy(surface);
+ return NULL;
+ }
+
+ wlr_buffer_init(&buffer->base, &image_buffer_impl, width, height);
+ buffer->surface = surface;
+ buffer->drm_format = drm_format;
+ return &buffer->base;
+}
+#else
+static struct wlr_buffer *load_background_buffer(const char *path)
+{
+ (void)path;
+ wlr_log(WLR_ERROR, "backgrounds require cairo support");
+ return NULL;
+}
+#endif
+
+static bool background_accepts_input(struct wlr_scene_buffer *buffer,
+ double *sx, double *sy)
+{
+ (void)buffer;
+ (void)sx;
+ (void)sy;
+ return false;
+}
+
+static void output_update_background(struct montis_output *output)
+{
+ struct montis_server *server = output->server;
+ if (!server->background_buffer) {
+ return;
+ }
+
+ if (!output->background) {
+ output->background = wlr_scene_buffer_create(&server->scene->tree,
+ server->background_buffer);
+ if (!output->background) {
+ wlr_log(WLR_ERROR, "failed to create background node");
+ return;
+ }
+ output->background->point_accepts_input = background_accepts_input;
+ wlr_scene_node_lower_to_bottom(&output->background->node);
+ }
+ else {
+ wlr_scene_buffer_set_buffer(output->background, server->background_buffer);
+ }
+
+ struct wlr_box box;
+ wlr_output_layout_get_box(server->output_layout, output->wlr_output, &box);
+ wlr_scene_node_set_position(&output->background->node, box.x, box.y);
+ wlr_scene_buffer_set_dest_size(output->background, box.width, box.height);
+}
+
static void focus_toplevel(struct montis_toplevel *toplevel,
struct wlr_surface *surface)
{
@@ -113,9 +238,9 @@ static void keyboard_handle_key(struct wl_listener *listener, void *data)
if (nsyms > 0 && syms[0] >= XKB_KEY_XF86Switch_VT_1 &&
syms[0] <= XKB_KEY_XF86Switch_VT_12) {
/* Escape-hatch to change sessions. These should always be available key
- * bindings regardless of what the soul dictates. This allows an escape
- * hatch to edit the soul in a different vterm and then use the escape
- * hatch below to hot-restart the soul if things get borked. */
+ * bindings regardless of what the world dictates. This allows an escape
+ * hatch to edit the world in a different vterm and then use the escape
+ * hatch below to hot-restart the world if things get borked. */
if (event->state == WL_KEYBOARD_KEY_STATE_PRESSED) {
wlr_session_change_vt(server->session,
syms[0] - XKB_KEY_XF86Switch_VT_1 + 1);
@@ -124,26 +249,26 @@ static void keyboard_handle_key(struct wl_listener *listener, void *data)
else if (modifiers ==
(WLR_MODIFIER_SHIFT | WLR_MODIFIER_CTRL | WLR_MODIFIER_ALT) &&
nsyms > 0 && syms[0] == XKB_KEY_Escape) {
- /* Escape-hatch to hot-reload the soul in case the soul got borked and
+ /* Escape-hatch to hot-reload the world in case the world got borked and
* stops accepting keybindings. Ctrl+Shift+Alt+Escape will always reload the
- * soul. */
+ * world. */
if (event->state == WL_KEYBOARD_KEY_STATE_PRESSED) {
- if ((ec = soul_hot_reload_same_state(&server->soul)) != 0) {
- fprintf(stderr, "Failed to hot reload soul");
+ if ((ec = world_hot_reload_same_state(&server->world)) != 0) {
+ fprintf(stderr, "Failed to hot reload world");
exit(1);
}
}
}
else {
- /* Pass the information along to the soul for the soul to handle. The
- * soul will return via 'handled' whether or not the key event was handled
+ /* Pass the information along to the world for the world to handle. The
+ * world will return via 'handled' whether or not the key event was handled
* or not. */
if (nsyms > 0) {
codepoint =
xkb_state_key_get_utf32(keyboard->wlr_keyboard->xkb_state, keycode);
- soul_call_update_state(server->soul, arksoul_export_handle_keybinding,
- keyboard->wlr_keyboard, event, modifiers, syms[0],
- codepoint, &handled);
+ world_call_update_state(server->world, arkworld_export_handle_keybinding,
+ keyboard->wlr_keyboard, event, modifiers, syms[0],
+ codepoint, &handled);
}
}
}
@@ -440,9 +565,8 @@ static void server_cursor_motion(struct wl_listener *listener, void *data)
wlr_cursor_move(server->cursor, &event->pointer->base, event->delta_x,
event->delta_y);
process_cursor_motion(server, event->time_msec);
- soul_call_update_state(server->soul, arksoul_export_handle_motion, event,
- modifiers,
- 0, server->cursor->x, server->cursor->y);
+ world_call_update_state(server->world, arkworld_export_handle_motion, event,
+ modifiers, 0, server->cursor->x, server->cursor->y);
}
static void server_cursor_motion_absolute(struct wl_listener *listener,
@@ -465,9 +589,8 @@ static void server_cursor_motion_absolute(struct wl_listener *listener,
wlr_cursor_warp_absolute(server->cursor, &event->pointer->base, event->x,
event->y);
process_cursor_motion(server, event->time_msec);
- soul_call_update_state(server->soul, arksoul_export_handle_motion, event,
- modifiers,
- 1, server->cursor->x, server->cursor->y);
+ world_call_update_state(server->world, arkworld_export_handle_motion, event,
+ modifiers, 1, server->cursor->x, server->cursor->y);
}
static void server_cursor_button(struct wl_listener *listener, void *data)
@@ -481,8 +604,8 @@ static void server_cursor_button(struct wl_listener *listener, void *data)
struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat);
uint32_t modifiers = wlr_keyboard_get_modifiers(keyboard);
- soul_call_update_state(server->soul, arksoul_export_handle_button, event,
- modifiers);
+ world_call_update_state(server->world, arkworld_export_handle_button, event,
+ modifiers);
/* Notify the client with pointer focus that a button press has occurred */
// wlr_seat_pointer_notify_button(server->seat, event->time_msec,
@@ -553,12 +676,18 @@ static void output_request_state(struct wl_listener *listener, void *data)
wl_container_of(listener, output, request_state);
const struct wlr_output_event_request_state *event = data;
wlr_output_commit_state(output->wlr_output, event->state);
+ output_update_background(output);
}
static void output_destroy(struct wl_listener *listener, void *data)
{
struct montis_output *output = wl_container_of(listener, output, destroy);
+ if (output->background) {
+ wlr_scene_node_destroy(&output->background->node);
+ output->background = NULL;
+ }
+
wl_list_remove(&output->frame.link);
wl_list_remove(&output->request_state.link);
wl_list_remove(&output->destroy.link);
@@ -630,6 +759,8 @@ static void server_new_output(struct wl_listener *listener, void *data)
wlr_scene_output_create(server->scene, wlr_output);
wlr_scene_output_layout_add_output(server->scene_layout, l_output,
scene_output);
+
+ output_update_background(output);
}
static void xdg_toplevel_map(struct wl_listener *listener, void *data)
@@ -640,9 +771,9 @@ static void xdg_toplevel_map(struct wl_listener *listener, void *data)
wl_list_insert(&toplevel->server->toplevels, &toplevel->link);
fprintf(stderr, "Surface map ...\n");
- soul_call_update_state(toplevel->server->soul, arksoul_export_handle_surface,
- toplevel,
- SURFACE_MAP);
+ world_call_update_state(toplevel->server->world,
+ arkworld_export_handle_surface, toplevel,
+ SURFACE_MAP);
fprintf(stderr, "/ Surface map ...\n");
focus_toplevel(toplevel, toplevel->xdg_toplevel->base->surface);
@@ -659,9 +790,9 @@ static void xdg_toplevel_unmap(struct wl_listener *listener, void *data)
}
fprintf(stderr, "Surface unmap ...\n");
- soul_call_update_state(toplevel->server->soul, arksoul_export_handle_surface,
- toplevel,
- SURFACE_UNMAP);
+ world_call_update_state(toplevel->server->world,
+ arkworld_export_handle_surface, toplevel,
+ SURFACE_UNMAP);
fprintf(stderr, "/ Surface map ...\n");
wl_list_remove(&toplevel->link);
@@ -682,9 +813,9 @@ static void xdg_toplevel_destroy(struct wl_listener *listener, void *data)
wl_list_remove(&toplevel->request_fullscreen.link);
fprintf(stderr, "Surface destroy ...\n");
- soul_call_update_state(toplevel->server->soul, arksoul_export_handle_surface,
- toplevel,
- SURFACE_DELETE);
+ world_call_update_state(toplevel->server->world,
+ arkworld_export_handle_surface, toplevel,
+ SURFACE_DELETE);
fprintf(stderr, "/ Surface destroy ...\n");
free(toplevel);
@@ -843,8 +974,7 @@ static void xdg_decoration_request_mode(struct wl_listener *listener,
static void xdg_decoration_destroy(struct wl_listener *listener, void *data)
{
- struct montis_xdg_decoration *dec =
- wl_container_of(listener, dec, destroy);
+ struct montis_xdg_decoration *dec = wl_container_of(listener, dec, destroy);
wl_list_remove(&dec->request_mode.link);
wl_list_remove(&dec->destroy.link);
free(dec);
@@ -927,35 +1057,42 @@ int main(int argc, char *argv[])
{
wlr_log_init(WLR_DEBUG, NULL);
char *startup_cmd = NULL;
- char *soul_path = NULL;
+ char *world_path = NULL;
+ char *background_path = NULL;
int c;
- while ((c = getopt(argc, argv, "s:p:h")) != -1) {
+ while ((c = getopt(argc, argv, "s:p:b:h")) != -1) {
switch (c) {
case 's':
startup_cmd = optarg;
break;
case 'p':
- soul_path = optarg;
+ world_path = optarg;
+ break;
+ case 'b':
+ background_path = optarg;
break;
default:
- printf("Usage: %s -p [soul] [-s startup command]\n", argv[0]);
+ printf("Usage: %s -p [world] [-s startup command] [-b background.png]\n",
+ argv[0]);
return 0;
}
}
- if (optind < argc || !soul_path) {
- printf("Usage: %s -p [soul] [-s startup command]\n", argv[0]);
+ if (optind < argc || !world_path) {
+ printf("Usage: %s -p [world] [-s startup command] [-b background.png]\n",
+ argv[0]);
return 0;
}
struct montis_server server = {0};
+ server.background_path = background_path;
- if (load_soul_from_file(argc, argv, soul_path, &server.soul)) {
- fprintf(stderr, "Failed to read soul from file.\n");
+ if (load_world_from_file(argc, argv, world_path, &server.world)) {
+ fprintf(stderr, "Failed to read world from file.\n");
return 1;
}
- soul_cold_start(&server.soul);
+ world_cold_start(&server.world);
/* The Wayland display is managed by libwayland. It handles accepting
* clients from the Unix socket, manging Wayland globals, and so on. */
@@ -1024,6 +1161,13 @@ int main(int argc, char *argv[])
server.scene_layout =
wlr_scene_attach_output_layout(server.scene, server.output_layout);
+ if (server.background_path) {
+ server.background_buffer = load_background_buffer(server.background_path);
+ if (!server.background_buffer) {
+ wlr_log(WLR_ERROR, "background image disabled");
+ }
+ }
+
/* Set up xdg-shell version 3. The xdg-shell is a Wayland protocol which is
* used for application windows. For more detail on shells, refer to
* https://drewdevault.com/2018/07/29/Wayland-shells.html.
@@ -1133,6 +1277,10 @@ int main(int argc, char *argv[])
* server. */
wl_display_destroy_clients(server.wl_display);
wlr_scene_node_destroy(&server.scene->tree.node);
+ if (server.background_buffer) {
+ wlr_buffer_drop(server.background_buffer);
+ server.background_buffer = NULL;
+ }
wlr_xcursor_manager_destroy(server.cursor_mgr);
wlr_output_layout_destroy(server.output_layout);
wl_display_destroy(server.wl_display);
diff --git a/ark/src/world.c b/ark/src/world.c
new file mode 100644
index 0000000..e7641ed
--- /dev/null
+++ b/ark/src/world.c
@@ -0,0 +1,199 @@
+#include "world.h"
+
+#include <ctype.h>
+#include <dlfcn.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+/* Utility function for showing the marshalled states as hex code */
+static void shx(uint8_t *state, uint32_t sz)
+{
+ uint32_t i = 0;
+ while (i < sz) {
+ for (int j = 0; j < 16; ++j) {
+ if (i < sz) {
+ printf("%02x ", (unsigned int)state[i]);
+ }
+ else {
+ printf(" ");
+ }
+ ++i;
+ }
+
+ i -= 16;
+
+ printf(" ");
+
+ for (int j = 0; j < 16; ++j) {
+ if (i < sz) {
+ if (isprint(state[i]) && !isspace(state[i])) {
+ printf("%c", state[i]);
+ }
+ else {
+ printf(".");
+ }
+ }
+ else {
+ printf(" ");
+ }
+ ++i;
+ }
+ printf("\n");
+ }
+}
+
+int load_world_from_dl_(dlhandle_t dl, world_t *world);
+
+static void lock(world_t *world) { pthread_mutex_lock(&world->lock); };
+
+static void unlock(world_t *world) { pthread_mutex_unlock(&world->lock); };
+
+static int load_world_from_file_(int argc, char **argv, const char *filename,
+ world_t *world)
+{
+ dlhandle_t lib = dlopen(filename, RTLD_NOW | RTLD_GLOBAL);
+ int ec = 0;
+
+ if (!lib) {
+ fprintf(stderr, "Failed to open library: %s: %s\n", filename, dlerror());
+ ec = 1;
+ goto end;
+ }
+
+ printf("Loading file.\n");
+ ec = load_world_from_dl_(lib, world);
+
+ if (ec) {
+ goto end;
+ }
+
+ strncpy(world->filename, filename, sizeof(world->filename));
+ world->argc = argc;
+ world->argv = argv;
+
+ world->arkworld_export_load(world->argc, world->argv);
+end:
+ return ec;
+}
+
+static void maybe_run_metaload(int argc, char **argv, world_t *world)
+{
+ static char *loaded_worlds[12];
+ int i;
+ for (i = 0; i < 12 && loaded_worlds[i]; ++i) {
+ if (strcmp(loaded_worlds[i], world->world_name) == 0) {
+ return; // World is already loaded
+ }
+ }
+ loaded_worlds[i] = strdup(world->world_name);
+
+ printf("First time loading %s, running metaload.\n", world->world_name);
+ if (world->arkworld_export_metaload) {
+ world->arkworld_export_metaload(argc, argv);
+ }
+}
+
+int load_world_from_file(int argc, char **argv, const char *filename,
+ world_t *world)
+{
+ memset(world, 0, sizeof(*world));
+
+ pthread_mutexattr_t attr;
+ if (pthread_mutexattr_init(&attr)) {
+ perror("pthread_mutexattr_init");
+ return 1;
+ }
+
+ if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE)) {
+ perror("pthread_mutexattr_settype");
+ return 1;
+ }
+
+ if (pthread_mutex_init(&world->lock, &attr)) {
+ pthread_mutexattr_destroy(&attr);
+ perror("pthread_mutexattr_init");
+ return 1;
+ }
+ pthread_mutexattr_destroy(&attr);
+ int rc = load_world_from_file_(argc, argv, filename, world);
+
+ if (rc == 0) {
+ maybe_run_metaload(argc, argv, world);
+ }
+
+ return rc;
+}
+
+int world_hot_reload_same_state(world_t *world)
+{
+ char filename_cpy[PATH_MAX];
+ strncpy(filename_cpy, world->filename, sizeof(filename_cpy));
+ return world_hot_reload(world->argc, world->argv, filename_cpy, world);
+}
+
+int world_hot_reload(int argc, char **argv, const char *filepath,
+ world_t *world)
+{
+ int ec = 0;
+ uint32_t sz = 0;
+ uint8_t *marshalled_state = NULL;
+
+ printf("Hot Reloading %s\n", world->world_name);
+ lock(world);
+
+ printf("Marshalling state ...\n");
+ marshalled_state = world->arkworld_export_preserve(world->state, &sz);
+
+ printf("Calling teardown ...\n");
+ world->arkworld_export_release(world->state);
+
+ printf("State Marshalled:\n");
+ shx(marshalled_state, sz);
+
+ printf("Unloading old library handle.\n");
+ if (dlclose(world->library_handle)) {
+ printf("Could not close library handle: %s\n", dlerror());
+ }
+
+ if ((ec = load_world_from_file_(argc, argv, filepath, world))) {
+ goto fail;
+ }
+
+ printf("Hot starting world ...\n");
+ world->state = world->arkworld_export_rebirth(world, marshalled_state, sz);
+
+fail:
+ free(marshalled_state);
+ unlock(world);
+ return ec;
+}
+
+void world_run_requested_actions(world_t *world)
+{
+ lock(world);
+ requested_action_t requested_actions[MAX_QUEUED_ACTIONS];
+ size_t n_requested_actions = world->n_requested_actions;
+ memcpy(&requested_actions, world->requested_actions,
+ sizeof(requested_actions));
+ world->n_requested_actions = 0;
+ unlock(world);
+
+ size_t i;
+ for (i = 0; i < n_requested_actions; ++i) {
+ requested_actions[i].action(world, requested_actions[i].str_arg);
+ if (requested_actions[i].arg_dtor) {
+ requested_actions[i].arg_dtor(requested_actions[i].ptr_arg);
+ }
+ }
+}
+
+void world_cold_start(world_t *world)
+{
+ lock(world);
+ world->state = world->arkworld_export_enworld(world);
+ unlock(world);
+}
diff --git a/ark/src/soul_load.c b/ark/src/world_load.c
index fcf04a9..098c4b0 100644
--- a/ark/src/soul_load.c
+++ b/ark/src/world_load.c
@@ -1,37 +1,37 @@
-#include "soul.h"
+#include "world.h"
#include <dlfcn.h>
#include <stdio.h>
-#include "soul_exports.h"
+#include "world_exports.h"
-int load_soul_from_dl_(dlhandle_t dl, soul_t *soul)
+int load_world_from_dl_(dlhandle_t dl, world_t *world)
{
void *ptr;
int ret = 0;
- const char **name = dlsym(dl, "soul_name");
+ const char **name = dlsym(dl, "world_name");
if (name) {
- soul->soul_name = *name;
+ world->world_name = *name;
}
else {
- soul->soul_name = NULL;
+ world->world_name = NULL;
}
- soul->state = NULL;
- soul->library_handle = dl;
+ world->state = NULL;
+ world->library_handle = dl;
#define LOAD_SYM(ret_type, sym, args) \
do { \
ptr = dlsym(dl, #sym); \
if (!ptr) { \
- fprintf(stderr, "Soul missing %s\n", #sym); \
+ fprintf(stderr, "World missing %s\n", #sym); \
ret |= 1; \
} \
- soul->sym = (ret_type(*) args)ptr; \
+ world->sym = (ret_type(*) args)ptr; \
} while (0);
- ARKSOUL_EXPORTS(LOAD_SYM);
+ ARKWORLD_EXPORTS(LOAD_SYM);
#undef LOAD_SYM