diff options
-rw-r--r-- | src/til.c | 136 |
1 files changed, 133 insertions, 3 deletions
@@ -16,6 +16,7 @@ #include "til_fb.h" #include "til_module_context.h" #include "til_settings.h" +#include "til_stream.h" #include "til_threads.h" #include "til_util.h" @@ -107,6 +108,7 @@ void til_shutdown(void) } +/* "blank" built-in module */ static void _blank_prepare_frame(til_module_context_t *context, til_stream_t *stream, unsigned ticks, til_fb_fragment_t **fragment_ptr, til_frame_plan_t *res_frame_plan) { *res_frame_plan = (til_frame_plan_t){ .fragmenter = til_fragmenter_slice_per_cpu }; @@ -128,11 +130,139 @@ static til_module_t _blank_module = { }; +/* "ref" built-in module */ +#include "libs/txt/txt.h" /* for rendering some diagnostics */ + +typedef struct _ref_setup_t { + til_setup_t til_setup; + + char *path; +} _ref_setup_t; + + +typedef struct _ref_context_t { + til_module_context_t til_module_context; + + til_module_context_t *ref; +} _ref_context_t; + + +static til_module_context_t * _ref_create_context(const til_module_t *module, til_stream_t *stream, unsigned seed, unsigned ticks, unsigned n_cpus, til_setup_t *setup) +{ + _ref_context_t *ctxt; + + ctxt = til_module_context_new(module, sizeof(*ctxt), stream, seed, ticks, n_cpus, setup); + if (!ctxt) + return NULL; + + return &ctxt->til_module_context; +} + + +static void _ref_destroy_context(til_module_context_t *context) +{ + _ref_context_t *ctxt = (_ref_context_t *)context; + + ctxt->ref = til_module_context_free(ctxt->ref); + free(context); +} + + +static void _ref_render_fragment(til_module_context_t *context, til_stream_t *stream, unsigned ticks, unsigned cpu, til_fb_fragment_t **fragment_ptr) +{ + _ref_context_t *ctxt = (_ref_context_t *)context; + _ref_setup_t *s = (_ref_setup_t *)context->setup; + + if (!ctxt->ref) { + int r; + + /* TODO: switch to til_stream_find_module_context(), this clones concept is DOA. */ + r = til_stream_find_module_contexts(stream, s->path, 1, &ctxt->ref); + if (r < 0) { + txt_t *msg = txt_newf("%s: BAD PATH \"%s\"", context->setup->path, s->path); + + til_fb_fragment_clear(*fragment_ptr); + txt_render_fragment(msg, *fragment_ptr, 0xffffffff, + 0, 0, + (txt_align_t){ + .horiz = TXT_HALIGN_LEFT, + .vert = TXT_VALIGN_TOP, + }); + txt_free(msg); + /* TODO: maybe print all available contexts into the fragment? */ + return; + } + } + + til_module_render(ctxt->ref, stream, ticks, fragment_ptr); +} + + +static void _ref_setup_free(til_setup_t *setup) +{ + _ref_setup_t *s = (_ref_setup_t *)setup; + + free(s->path); + free(s); +} + + +static int _ref_setup(const til_settings_t *settings, til_setting_t **res_setting, const til_setting_desc_t **res_desc, til_setup_t **res_setup) +{ + const char *path; + int r; + + r = til_settings_get_and_describe_value(settings, + &(til_setting_spec_t){ + .name = "Context path to reference", + .key = "path", + .regex = "[a-zA-Z0-9/_]+", + .preferred = "", + }, + &path, + res_setting, + res_desc); + if (r) + return r; + + if (res_setup) { + _ref_setup_t *setup; + + setup = til_setup_new(settings, sizeof(*setup), _ref_setup_free); + if (!setup) + return -ENOMEM; + + setup->path = strdup(path); + if (!setup->path) { + til_setup_free(&setup->til_setup); + + return -ENOMEM; + } + + *res_setup = &setup->til_setup; + } + + return 0; +} + + +static til_module_t _ref_module = { + .create_context = _ref_create_context, + .destroy_context = _ref_destroy_context, + .render_fragment = _ref_render_fragment, + .setup = _ref_setup, + .name = "ref", + .description = "built-in context referencer", + .author = "built-in", +}; + + const til_module_t * til_lookup_module(const char *name) { - static const til_module_t *builtins[] = { - &_blank_module, - }; + static const til_module_t *builtins[] = { + &_blank_module, + &_ref_module, + }; static struct { const til_module_t **modules; size_t n_modules; |