diff --git a/inc/lektor/module/module_sdl2.h b/inc/lektor/module/module_sdl2.h index 9a3b79170c97e1b3ed5c15628637a4189790f402..ae6c58fc8dbeb94c793c877566b7f20256b0f17b 100644 --- a/inc/lektor/module/module_sdl2.h +++ b/inc/lektor/module/module_sdl2.h @@ -24,5 +24,3 @@ bool module_sdl2_set_volume(struct lkt_win *const win, int vol); bool module_sdl2_get_duration(struct lkt_win *const win, int *dur_sec); bool module_sdl2_get_elapsed(struct lkt_win *const win, int *elapsed_sec); - -bool module_sdl2_handle_events(struct lkt_win *const win, volatile sqlite3 *db, mpd_idle_flag *mpd_idle_events); diff --git a/inc/lektor/reg.h b/inc/lektor/reg.h index 1799246981c570d7739a14a146fccc803867242a..0ac197100001c0c4e31ffa5dc87de0d42f72c909 100644 --- a/inc/lektor/reg.h +++ b/inc/lektor/reg.h @@ -2,21 +2,27 @@ struct lkt_state; +#include <stdarg.h> + +typedef int (*reg_func)(va_list *); + /* Store functions with a name, so that all the lib will have acces to it with a name that can be generated or red from a config file. */ struct module_reg { const char *name; union { - void (*func)(void); + reg_func func; void *obj; }; }; #define REG_EXPORT_NAME "__reg__" #define REG_BEGIN(reg) struct module_reg reg[] = { -#define REG_ADD(f) { .name = #f, .func = (void(*)(void)) f }, -#define REG_ADD_NAMED(n, f) { .name = n, .func = (void(*)(void)) f }, -#define REG_END() { .name = NULL, .func = NULL } }; +#define REG_ADD(f) { .name = #f, .func = f }, +#define REG_ADD_NAMED(n, f) { .name = n, .func = f }, +#define REG_REGISTER(n, s) { .name = n, .obj = s }, +#define REG_END() { .name = NULL, .func = NULL } }; +#define REG_DEFINE(reg) struct module_reg reg* = NULL; /* Use only once per .so files or you will have some problems... */ #if ! defined(_STATIC_MODULES) @@ -25,27 +31,22 @@ struct module_reg { #define REG_EXPORT(__reg) #endif -/* If handle is NULL, file is unused and the reg is red. Otherwise, - we use dlfcn to search for the symbol which is returned. If *handle - is NULL, it will be created by opening the file. */ -void *reg_pick(const char *file, void **handle, const char *symbol); +/* Import a reg */ +#define REG_IMPORT(reg, as) \ + extern struct module_reg *reg; \ + static struct module_reg *as = reg; + +/* Call a function from a reg. */ +int reg_call(struct module_reg *reg, const char *name, int count, ...); -/* Get the reg from a .so file. This reg must be exported by the - shared library with REG_EXPORT. Note that this reg is named `__reg__`, - thus no symbol must be named `__reg__` in the .so file. +/* Import a module, from a file (mod is a filepath) or from the __reg__ in the + current file. If the `mod` contains one of the following "/.\'\"\\", it is + treated as a file. The function will first try to treat is as a module in the + __reg__. Returns 0 on success, something else on error. */ -int reg_from_file(const char *file, struct module_reg **ret, void **handle); +int reg_import(const char *mod, struct module_reg **ret, void **handle); /* Set the __reg__ pointer. */ void reg_export(struct module_reg *reg); -/* Get the object named with 'name' from the reg. Returns NULL on error - or 'not found'. */ -void *__reg_get(struct module_reg *reg, const char *name); - -/* Load a module by its name. Also initialize the mod pointer. No check on data - type is done, it is up to the user to check if the structure passed as a - `void*` is the right structure. */ -int load_module_by_name(struct lkt_state *srv, const char *name, void *mod); - #endif diff --git a/src/main/server.c b/src/main/server.c index 33c81c6464c3eee60d9edc1db8fbf818a209ebfe..a7e772c3d81f349ace4135d52053ab39e00660ac 100644 --- a/src/main/server.c +++ b/src/main/server.c @@ -19,21 +19,8 @@ #include <pwd.h> #include <pthread.h> -#ifdef _STATIC_SDL2 -#include <lektor/module/module_sdl2.h> -#endif -#ifdef _STATIC_X11 -#include <lektor/module/module_x11.h> -#endif - REG_BEGIN(server_reg) REG_ADD(load_repo_https) -#ifdef _STATIC_SDL2 -REG_ADD(load_sdl2) -#endif -#ifdef _STATIC_X11 -REG_ADD(load_x11) -#endif REG_END() int @@ -122,8 +109,17 @@ normal_launch: database_queue_clear(srv.db); lkt_queue_make_available(&srv.queue, lkt_event_prop); + char *module = safe_malloc(sizeof(char) * PATH_MAX); + struct module_reg *player_mod; + void *player_handle; + database_config_get_text(srv.db, "player", "module", module, PATH_MAX); + reg_import(module, &player_mod, &player_handle); RETURN_IF(load_module_by_name(&srv, "player", &srv.win), "Can't load module player", 3); RETURN_IF(load_module_by_name(&srv, "repo", &srv.repo), "Can't load module repo", 3); + free(module); + + void *handle = NULL; + reg_call(server_reg, "load_repo_https", 3, &srv.repo, &srv, handle); /* Get ENV */ /* Not working -> race condition with player module */ diff --git a/src/module/module_sdl2.c b/src/module/module_sdl2.c index 86ab4281d1832c690c466f37dff7d17ae3df1da8..0e5a2b623589369329184fe0c278beaa968718e2 100644 --- a/src/module/module_sdl2.c +++ b/src/module/module_sdl2.c @@ -14,6 +14,7 @@ #include <unistd.h> #include <stdlib.h> #include <stdio.h> +#include <stdarg.h> #include <SDL.h> #include <mpv/render_gl.h> #include <mpv/client.h> @@ -363,50 +364,110 @@ module_sdl2_get_elapsed(struct lkt_win *const win, int *elapsed_sec) return true; } -bool -module_sdl2_handle_events(struct lkt_win *const win, volatile sqlite3 *db, - mpd_idle_flag *mpd_idle_events) +/* va_list version of functions. */ + +int +mod_new(va_list *va) { - UNUSED(win, db, mpd_idle_events); - return true; + va_list copy; + va_copy(copy, *va); + struct lkt_win *win = va_arg(copy, struct lkt_win *); + bool ret = module_sdl2_new(win); + va_end(copy); + return ! ret; } -/* The module stuff */ +int +mod_close(va_list *va) +{ + va_list copy; + va_copy(copy, *va); + struct lkt_win *win = va_arg(copy, struct lkt_win *); + module_sdl2_close(win); + va_end(copy); + return 0; +} + +int +mod_free(va_list *va) +{ + va_list copy; + va_copy(copy, *va); + struct lkt_win *win = va_arg(copy, struct lkt_win *); + module_sdl2_free(win); + va_end(copy); + return 0; +} + +int +mod_toggle_pause(va_list *va) +{ + va_list copy; + va_copy(copy, *va); + struct lkt_win *win = va_arg(copy, struct lkt_win *); + bool ret = module_sdl2_toggle_pause(win); + va_end(copy); + return ! ret; +} + +int +mod_load_file(va_list *va) +{ + va_list copy; + va_copy(copy, *va); + struct lkt_win *win = va_arg(copy, struct lkt_win *); + const char *file = va_arg(copy, const char *); + bool ret = module_sdl2_load_file(win, file); + va_end(copy); + return ! ret; +} + +int +mod_set_volume(va_list *va) +{ + va_list copy; + va_copy(copy, *va); + struct lkt_win *win = va_arg(copy, struct lkt_win *); + int volume = va_arg(copy, int); + bool ret = module_sdl2_set_volume(win, volume); + va_end(copy); + return ! ret; +} + +int +mod_get_duration(va_list *va) +{ + va_list copy; + va_copy(copy, *va); + struct lkt_win *win = va_arg(copy, struct lkt_win *); + int *duration = va_arg(copy, int *); + bool ret = module_sdl2_get_duration(win, duration); + va_end(copy); + return ! ret; +} int -#if ! defined(_STATIC_MODULES) -module_set_function(void *arg__, struct lkt_state *srv, void *handle__) -#else -load_sdl2(void *arg__, struct lkt_state *srv, void *handle__) -#endif +mod_get_elapsed(va_list *va) { - RETURN_UNLESS(arg__, "Invalid argument", 1); - struct lkt_win *win = (struct lkt_win *) arg__; - win->srv = srv; - - win->new = module_sdl2_new; - win->close = module_sdl2_close; - win->free = module_sdl2_free; - win->toggle_pause = module_sdl2_toggle_pause; - win->load_file = module_sdl2_load_file; - win->set_volume = module_sdl2_set_volume; - win->get_duration = module_sdl2_get_duration; - win->get_elapsed = module_sdl2_get_elapsed; - win->handle_events = module_sdl2_handle_events; - win->handle = handle__; - - return !module_sdl2_new(&srv->win); + va_list copy; + va_copy(copy, *va); + struct lkt_win *win = va_arg(copy, struct lkt_win *); + int *elapsed = va_arg(copy, int *); + bool ret = module_sdl2_get_elapsed(win, elapsed); + va_end(copy); + return ! ret; } +/* The module stuff */ + REG_BEGIN(sdl2_reg) -REG_ADD_NAMED("new", module_sdl2_new) -REG_ADD_NAMED("free", module_sdl2_free) -REG_ADD_NAMED("handle", module_sdl2_handle_events) -REG_ADD(module_sdl2_close) -REG_ADD(module_sdl2_toggle_pause) -REG_ADD(module_sdl2_load_file) -REG_ADD(module_sdl2_set_volume) -REG_ADD(module_sdl2_get_duration) -REG_ADD(module_sdl2_get_elapsed) +REG_ADD_NAMED("new", mod_new) +REG_ADD_NAMED("free", mod_free) +REG_ADD_NAMED("close", mod_close) +REG_ADD_NAMED("toggle", mod_toggle_pause) +REG_ADD_NAMED("load", mod_load_file) +REG_ADD_NAMED("set_volume", mod_set_volume) +REG_ADD_NAMED("get_duration", mod_get_duration) +REG_ADD_NAMED("get_elapsed", mod_get_elapsed) REG_END() REG_EXPORT(sdl2_reg) diff --git a/src/reg.c b/src/reg.c index d42614021086c358ad72c96ca930d1d85a47d7de..91b44a10b8f7b4f1ea2a385175f98869c7addba5 100644 --- a/src/reg.c +++ b/src/reg.c @@ -9,6 +9,8 @@ #include <stdio.h> #include <strings.h> #include <stddef.h> +#include <stdarg.h> +#include <string.h> struct module_reg *__reg__; @@ -22,24 +24,27 @@ void * __reg_get(struct module_reg *reg, const char *name) { int i; - for (i = 0; reg[i].name && reg[i].func; ++i) + for (i = 0; reg[i].name && reg[i].obj; ++i) { if (STR_MATCH(reg[i].name, name)) - return *(void **) ®[i].func; + return reg[i].obj; + } return NULL; } -void * -reg_pick(const char *file, void **handle, const char *symbol) +reg_func +__reg_func(struct module_reg *reg, const char *name) { - if (!symbol) - return NULL; - - /* Use the register instead of dlfcn? */ - if (!file || file[0] == '\0' || STR_MATCH(file, "STATIC") || handle == NULL) - goto use_reg; + int i; + for (i = 0; reg[i].name && reg[i].func; ++i) { + if (STR_MATCH(reg[i].name, name)) + return reg[i].func; + } + return NULL; +} - /* Use dlsym */ - LOG_INFO("REG", "Using dlfcn to find %s", symbol); +void * +__from_file(const char *file, void **handle, const char *symbol) +{ char *error; *handle = dlopen(file, RTLD_NOW); @@ -59,59 +64,35 @@ reg_pick(const char *file, void **handle, const char *symbol) } return sym; - - /* Read the reg */ -use_reg: - LOG_INFO("REG", "Using the reg structure to find %s", symbol); - return __reg_get(__reg__, symbol); } int -load_so(const char *const mod_path, const char *const mod_init, void *mod, - struct lkt_state *srv) +reg_import(const char *mod, struct module_reg **ret, void **handle) { - /* An init function takes two arguments: the module pointer and a void* - which is the handler for the .so file. It the role of the module to - store the handle pointer. - Uppon successfull completion, the function shall return 0, and return - a non zero value if something bad happened. */ - int (*module_set_function)(void *const, struct lkt_state *, void *const); - void *handle = NULL; - *(void **) (&module_set_function) = reg_pick(mod_path, &handle, mod_init); - - if (module_set_function) - return module_set_function(mod, srv, handle); - else { - LOG_ERROR("LOAD", "Failed to find init symbol %s " - "in file %s", mod_init, mod_path); - return 1; + if (strcspn(mod, "/.\'\"\\") != strlen(mod)) { + LOG_INFO("REG", "Using the dlsym to find '" REG_EXPORT_NAME + "' in %s", mod); + *ret = __from_file(mod, handle, REG_EXPORT_NAME); + } else { + LOG_INFO("REG", "Using the reg structure to find %s", mod); + *ret = __reg_get(__reg__, mod); + if (!*ret) { + LOG_INFO("REG", "Not found in reg '" REG_EXPORT_NAME "', using " + "the dlsym to find reg '" REG_EXPORT_NAME "' in file %s", + mod); + } } + return *ret != NULL; } -int -load_module_by_name(struct lkt_state *srv, const char *name, void *mod) -{ - char mod_path[PATH_MAX], mod_load[INI_MAX_LINE_LEN]; - - /* When, don't mind if its not here */ - if (!database_config_get_text(srv->db, name, "path", mod_path, PATH_MAX)) { - LOG_WARN("CONFIG", "No setting 'path' in section '%s'", name); - mod_path[0] = '\0'; - } - - if (!database_config_get_text(srv->db, name, "load_function", - mod_load, INI_MAX_LINE_LEN)) { - LOG_ERROR("CONFIG", "Module named %s is incomplete or " - "is not defined in config file", name); - return 1; - } - - return load_so(mod_path, mod_load, mod, srv); -} int -reg_from_file(const char *file, struct module_reg **ret, void **handle) +reg_call(struct module_reg *reg, const char *name, int count, ...) { - *ret = reg_pick(file, handle, REG_EXPORT_NAME); - return *ret != NULL; + reg_func func = __reg_func(reg, name); + va_list va; + va_start(va, count); + int ret = func(&va); + va_end(va); + return ret; }