summaryrefslogtreecommitdiff
path: root/src/til_builtins.c
diff options
context:
space:
mode:
authorVito Caputo <vcaputo@pengaru.com>2023-11-18 16:11:34 -0800
committerVito Caputo <vcaputo@pengaru.com>2023-11-18 16:11:34 -0800
commitcc15fd679c9d3c94bdcfe970bc7d3c03bc8994ef (patch)
treeccb4eaf5d8700ac1a5c8df2e31b86a3a0a6f1afa /src/til_builtins.c
parent9f7209dae9b45a26e501559fbefbb9037cada890 (diff)
til_builtins/pre: introduce "pre" pre-render hook module
This adds a new "meta" module which registers itself as a pre-render context on the stream, to render whatever module is specified as the "module=" setting. The impetus for this is background music in rkt creations, so one can avoid enduring the rigamarole of plugging something like a "playit" instance into every scene. With this "pre" builtin one can just use something like "pre,module=playit,itfile=music.it" as a scene, and that will get the playit module playing music.it hooked into the stream, without the need to always have it present in every scene's settings. There's a TODO item noting the need for taps to control the active/inactive state of the pre instance this adds. For now, once you have a "pre", whatever module it contains will be rendered before the main stream context set w/til_stream_set_module_context() gets rendered. That's fine for now, but there will need to be more control especially as more complex productions happen involving multiple songs.
Diffstat (limited to 'src/til_builtins.c')
-rw-r--r--src/til_builtins.c152
1 files changed, 152 insertions, 0 deletions
diff --git a/src/til_builtins.c b/src/til_builtins.c
index 466c09d..4a011cc 100644
--- a/src/til_builtins.c
+++ b/src/til_builtins.c
@@ -242,3 +242,155 @@ static int _none_setup(const til_settings_t *settings, til_setting_t **res_setti
return 0;
}
+
+
+/* "pre" built-in module */
+typedef struct _pre_setup_t {
+ til_setup_t til_setup;
+
+ til_setup_t *module_setup;
+} _pre_setup_t;
+
+
+typedef struct _pre_context_t {
+ til_module_context_t til_module_context;
+
+ til_module_context_t *module_ctxt;
+} _pre_context_t;
+
+
+#define _PRE_DEFAULT_MODULE "none"
+
+
+static til_module_context_t * _pre_create_context(const til_module_t *module, til_stream_t *stream, unsigned seed, unsigned ticks, unsigned n_cpus, til_setup_t *setup)
+{
+ _pre_setup_t *s = (_pre_setup_t *)setup;
+ _pre_context_t *ctxt;
+
+ ctxt = til_module_context_new(module, sizeof(*ctxt), stream, seed, ticks, n_cpus, setup);
+ if (!ctxt)
+ return NULL;
+
+ if (s->module_setup) {
+ const til_module_t *m = s->module_setup->creator;
+
+ if (til_module_create_context(m, stream, rand_r(&seed), ticks, n_cpus, s->module_setup, &ctxt->module_ctxt) < 0)
+ return til_module_context_free(&ctxt->til_module_context);
+ }
+
+ if (til_stream_add_pre_module_context(stream, &ctxt->til_module_context) < 0)
+ return til_module_context_free(&ctxt->til_module_context);
+
+ return &ctxt->til_module_context;
+}
+
+
+static void _pre_destroy_context(til_module_context_t *context)
+{
+ _pre_context_t *ctxt = (_pre_context_t *)context;
+
+ til_stream_del_pre_module_context(context->stream, context);
+ til_module_context_free(ctxt->module_ctxt);
+ free(context);
+}
+
+
+static void _pre_render_proxy(til_module_context_t *context, til_stream_t *stream, unsigned ticks, til_fb_fragment_t **fragment_ptr)
+{
+ _pre_context_t *ctxt = (_pre_context_t *)context;
+
+ /* TODO: introduce taps toggling the render */
+
+ if (ctxt->module_ctxt)
+ til_module_render(ctxt->module_ctxt, stream, ticks, fragment_ptr);
+}
+
+
+static void _pre_setup_free(til_setup_t *setup)
+{
+ _pre_setup_t *s = (_pre_setup_t *)setup;
+
+ til_setup_free(s->module_setup);
+ free(s);
+}
+
+
+static int _pre_setup(const til_settings_t *settings, til_setting_t **res_setting, const til_setting_desc_t **res_desc, til_setup_t **res_setup);
+
+
+til_module_t _pre_module = {
+ .create_context = _pre_create_context,
+ .destroy_context = _pre_destroy_context,
+ .render_proxy = _pre_render_proxy,
+ .setup = _pre_setup,
+ .name = "pre",
+ .description = "Pre-render hook registration (built-in)",
+ .author = "built-in",
+ .flags = TIL_MODULE_BUILTIN,
+};
+
+
+static int _pre_module_setup(const til_settings_t *settings, til_setting_t **res_setting, const til_setting_desc_t **res_desc, til_setup_t **res_setup)
+{
+ return til_module_setup_full(settings,
+ res_setting,
+ res_desc,
+ res_setup,
+ "Pre-rendering module name",
+ _PRE_DEFAULT_MODULE,
+ (TIL_MODULE_EXPERIMENTAL | TIL_MODULE_HERMETIC),
+ NULL);
+}
+
+
+static int _pre_setup(const til_settings_t *settings, til_setting_t **res_setting, const til_setting_desc_t **res_desc, til_setup_t **res_setup)
+{
+ const til_settings_t *module_settings;
+ til_setting_t *module;
+ int r;
+
+ r = til_settings_get_and_describe_setting(settings,
+ &(til_setting_spec_t){
+ .name = "Module to hook for pre-rendering",
+ .key = "module",
+ .preferred = _PRE_DEFAULT_MODULE,
+ .as_nested_settings = 1,
+ .as_label = 1,
+ },
+ &module,
+ res_setting,
+ res_desc);
+ if (r)
+ return r;
+
+ module_settings = module->value_as_nested_settings;
+ assert(module_settings);
+
+ r = _pre_module_setup(module_settings,
+ res_setting,
+ res_desc,
+ NULL); /* XXX: note no res_setup, must defer finalize */
+ if (r)
+ return r;
+
+ if (res_setup) {
+ _pre_setup_t *setup;
+
+ setup = til_setup_new(settings, sizeof(*setup), _pre_setup_free, &_pre_module);
+ if (!setup)
+ return -ENOMEM;
+
+ r = _pre_module_setup(module_settings,
+ res_setting,
+ res_desc,
+ &setup->module_setup); /* finalize! */
+ if (r < 0)
+ return til_setup_free_with_ret_err(&setup->til_setup, r);
+
+ assert(r == 0);
+
+ *res_setup = &setup->til_setup;
+ }
+
+ return 0;
+}
© All Rights Reserved