summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVito Caputo <vcaputo@pengaru.com>2023-06-12 15:22:59 -0700
committerVito Caputo <vcaputo@pengaru.com>2023-06-12 17:02:58 -0700
commita56b2c248356ec505f38b88651f26f92c00de981 (patch)
tree1f3b87f93de1b8ad38079db96a5401ac47f63418
parent8b0c8e1e4336ce0c40c467fc86dec40fb2c94128 (diff)
til: introduce "ref" built-in module
This opens up the possibility of referencing contexts on-stream by-path anywhere a module may be used: ref,path=/path/to/existing/context Currently the path lookup is performed @ render time, and a reference is taken on the context found there on the first time it's located. That reference is then held in the ref's context until its context is destroyed. There are more details to flesh out, and what probably needs to happen is some til_stream API for maintaining the reference in the event that the context at that path gets replaced. Due to refcounting, the referenced context will persist even if the stream-resident instance goes away, but there should probably be a way for that replacement to invalidate the existing references so they replace theirs with a fresh lookup at the path... Either way this is a good start. With this addition you can effectively implement scene transitions in rkt, via the mixer module, something like (sans proper escaping): mixer,a_module=ref\,path=/foo/previous/ctxt,b_module=ref\,path=/foo/next/ctxt
-rw-r--r--src/til.c136
1 files changed, 133 insertions, 3 deletions
diff --git a/src/til.c b/src/til.c
index 4241c12..5a9a964 100644
--- a/src/til.c
+++ b/src/til.c
@@ -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;
© All Rights Reserved