ilimination of system code, removal of x-watcher and replacement of it by dmon, fixes in audio code, dynamic asset reload
This commit is contained in:
@ -2,169 +2,111 @@
|
||||
#include "twn_util.h"
|
||||
#include "twn_engine_context_c.h"
|
||||
|
||||
#include <x-watcher.h>
|
||||
#define DMON_IMPL
|
||||
#include <dmon.h>
|
||||
#include <stb_ds.h>
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
|
||||
struct FilewatchPathToCallback {
|
||||
struct FilewatchEntry {
|
||||
char *path;
|
||||
FileatchCallback callback;
|
||||
float tick_last_reported;
|
||||
enum FilewatchAction action_pending : 3;
|
||||
bool action_processed : 1;
|
||||
enum FilewatchAction *actions_pending;
|
||||
};
|
||||
|
||||
static struct FilewatchPathToCallback *filewatch_directories;
|
||||
static struct FilewatchPathToCallback *filewatch_files;
|
||||
static struct FilewatchEntry *filewatch_directories;
|
||||
static struct FilewatchEntry *filewatch_files;
|
||||
/* note: it gets rebuilt on every addition, as api is such */
|
||||
/* TODO: test whether it's possible to miss on update while watcher is being rebuilt */
|
||||
/* we might have to enumerate things, just to make sure */
|
||||
static x_watcher *filewatcher;
|
||||
static SDL_mutex *filewatcher_lock;
|
||||
static bool filewatcher_initialized;
|
||||
|
||||
/* TODO: check whether path and p->path match? */
|
||||
static void filewatch_dispatch(XWATCHER_FILE_EVENT event,
|
||||
const char *path,
|
||||
int context,
|
||||
void *additional_data
|
||||
) {
|
||||
(void)additional_data; (void)path;
|
||||
static void filewatch_callback(dmon_watch_id watch_id,
|
||||
dmon_action action,
|
||||
const char* rootdir,
|
||||
const char* filepath,
|
||||
const char* oldfilepath,
|
||||
void* user)
|
||||
{
|
||||
enum FilewatchAction faction;
|
||||
|
||||
enum FilewatchAction action;
|
||||
|
||||
switch (event) {
|
||||
case XWATCHER_FILE_CREATED:
|
||||
action = FILEWATCH_ACTION_FILE_CREATED;
|
||||
switch (action) {
|
||||
case DMON_ACTION_CREATE:
|
||||
faction = FILEWATCH_ACTION_FILE_CREATED;
|
||||
break;
|
||||
case XWATCHER_FILE_REMOVED:
|
||||
action = FILEWATCH_ACTION_FILE_DELETED;
|
||||
case DMON_ACTION_DELETE:
|
||||
faction = FILEWATCH_ACTION_FILE_DELETED;
|
||||
break;
|
||||
case XWATCHER_FILE_MODIFIED:
|
||||
action = FILEWATCH_ACTION_FILE_MODIFIED;
|
||||
case DMON_ACTION_MODIFY:
|
||||
faction = FILEWATCH_ACTION_FILE_MODIFIED;
|
||||
break;
|
||||
case XWATCHER_FILE_NONE:
|
||||
case XWATCHER_FILE_OPENED:
|
||||
case XWATCHER_FILE_RENAMED:
|
||||
case XWATCHER_FILE_UNSPECIFIED:
|
||||
case XWATCHER_FILE_ATTRIBUTES_CHANGED:
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_LockMutex(filewatcher_lock);
|
||||
|
||||
struct FilewatchPathToCallback *p;
|
||||
intptr_t const context = (intptr_t)user;
|
||||
struct FilewatchEntry *p;
|
||||
|
||||
if (context < 0)
|
||||
p = &filewatch_files[-context - 1];
|
||||
else
|
||||
p = &filewatch_directories[context];
|
||||
|
||||
p->tick_last_reported = ctx.game.frame_number;
|
||||
p->action_processed = false;
|
||||
p->action_pending = action;
|
||||
|
||||
arrpush(p->actions_pending, faction);
|
||||
SDL_UnlockMutex(filewatcher_lock);
|
||||
}
|
||||
|
||||
|
||||
static bool filewatcher_rebuild(void) {
|
||||
if (filewatcher)
|
||||
xWatcher_destroy(filewatcher);
|
||||
|
||||
filewatcher = xWatcher_create();
|
||||
if (!filewatcher) {
|
||||
log_warn("Error creating xWatcher instance, no file watching is done");
|
||||
return false;
|
||||
}
|
||||
|
||||
int const filewatch_directories_len = arrlen(filewatch_directories);
|
||||
for (int i = 0; i < filewatch_directories_len; ++i) {
|
||||
xWatcher_reference ref = {
|
||||
.path = filewatch_directories[i].path,
|
||||
.callback_func = filewatch_dispatch,
|
||||
.context = i,
|
||||
};
|
||||
if (!xWatcher_appendDir(filewatcher, &ref))
|
||||
log_warn("Error watching dir contents: %s", filewatch_directories[i].path);
|
||||
}
|
||||
|
||||
int const filewatch_files_len = arrlen(filewatch_files);
|
||||
for (int i = 0; i < filewatch_files_len; ++i) {
|
||||
xWatcher_reference ref = {
|
||||
.path = filewatch_files[i].path,
|
||||
.callback_func = filewatch_dispatch,
|
||||
.context = -(i + 1), /* in negative range to allow inrefence */
|
||||
};
|
||||
if (!xWatcher_appendDir(filewatcher, &ref))
|
||||
log_warn("Error watching file: %s", filewatch_files[i].path);
|
||||
}
|
||||
|
||||
if (!xWatcher_start(filewatcher)) {
|
||||
log_warn("Error creating xWatcher instance, no file watching is done");
|
||||
xWatcher_destroy(filewatcher);
|
||||
filewatcher = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool filewatch_add_directory(char *dir, FileatchCallback callback) {
|
||||
bool filewatch_add_directory(char const *dir, FileatchCallback callback) {
|
||||
SDL_assert(dir && callback);
|
||||
|
||||
struct FilewatchPathToCallback const w = {
|
||||
if (!filewatcher_initialized) {
|
||||
dmon_init();
|
||||
filewatcher_initialized = true;
|
||||
}
|
||||
|
||||
struct FilewatchEntry const w = {
|
||||
.callback = callback,
|
||||
.path = SDL_strdup(dir),
|
||||
.action_processed = true,
|
||||
.tick_last_reported = ctx.game.frame_number,
|
||||
.path = SDL_strdup(dir), /* TODO: free */
|
||||
};
|
||||
arrpush(filewatch_directories, w);
|
||||
|
||||
return filewatcher_rebuild();
|
||||
dmon_watch(dir, filewatch_callback, DMON_WATCHFLAGS_RECURSIVE, (void *)(intptr_t)(arrlen(filewatch_directories) - 1));
|
||||
}
|
||||
|
||||
|
||||
bool filewatch_add_file(char *filepath, FileatchCallback callback) {
|
||||
bool filewatch_add_file(char const *filepath, FileatchCallback callback) {
|
||||
SDL_assert(filepath && callback);
|
||||
|
||||
struct FilewatchPathToCallback const f = {
|
||||
if (!filewatcher_initialized) {
|
||||
dmon_init();
|
||||
filewatcher_initialized = true;
|
||||
}
|
||||
|
||||
struct FilewatchEntry const f = {
|
||||
.callback = callback,
|
||||
.path = SDL_strdup(filepath),
|
||||
.action_processed = true,
|
||||
.tick_last_reported = ctx.game.frame_number,
|
||||
.path = SDL_strdup(filepath), /* TODO: free */
|
||||
};
|
||||
arrpush(filewatch_files, f);
|
||||
|
||||
return filewatcher_rebuild();
|
||||
dmon_watch("./", filewatch_callback, 0, (void *)(intptr_t)(-arrlen(filewatch_files)));
|
||||
}
|
||||
|
||||
|
||||
void filewatch_poll(void) {
|
||||
SDL_LockMutex(filewatcher_lock);
|
||||
|
||||
int const filewatch_directories_len = arrlen(filewatch_directories);
|
||||
for (int i = 0; i < filewatch_directories_len; ++i) {
|
||||
if (!filewatch_directories[i].action_processed
|
||||
&& (ctx.game.frame_number - filewatch_directories[i].tick_last_reported > FILEWATCH_MODIFIED_TICKS_MERGED)) {
|
||||
SDL_assert(filewatch_directories[i].action_pending != FILEWATCH_ACTION_FILE_NONE);
|
||||
filewatch_directories[i].callback(filewatch_directories[i].path, filewatch_directories[i].action_pending);
|
||||
filewatch_directories[i].action_pending = FILEWATCH_ACTION_FILE_NONE;
|
||||
filewatch_directories[i].action_processed = true;
|
||||
}
|
||||
for (int i = 0; i < arrlen(filewatch_directories); ++i) {
|
||||
for (int u = 0; u < arrlen(filewatch_directories[i].actions_pending); ++u)
|
||||
filewatch_directories[i].callback(filewatch_directories[i].path, filewatch_directories[i].actions_pending[u]);
|
||||
arrfree(filewatch_directories[i].actions_pending);
|
||||
}
|
||||
|
||||
int const filewatch_files_len = arrlen(filewatch_files);
|
||||
for (int i = 0; i < filewatch_files_len; ++i) {
|
||||
if (!filewatch_files[i].action_processed
|
||||
&& (ctx.game.frame_number - filewatch_files[i].tick_last_reported > FILEWATCH_MODIFIED_TICKS_MERGED)) {
|
||||
SDL_assert(filewatch_files[i].action_pending != FILEWATCH_ACTION_FILE_NONE);
|
||||
filewatch_files[i].callback(filewatch_files[i].path, filewatch_files[i].action_pending);
|
||||
filewatch_files[i].action_pending = FILEWATCH_ACTION_FILE_NONE;
|
||||
filewatch_files[i].action_processed = true;
|
||||
}
|
||||
for (int i = 0; i < arrlen(filewatch_files); ++i) {
|
||||
for (int u = 0; u < arrlen(filewatch_files[i].actions_pending); ++u)
|
||||
filewatch_files[i].callback(filewatch_files[i].path, filewatch_files[i].actions_pending[u]);
|
||||
arrfree(filewatch_files[i].actions_pending);
|
||||
}
|
||||
|
||||
SDL_UnlockMutex(filewatcher_lock);
|
||||
|
Reference in New Issue
Block a user