summaryrefslogtreecommitdiff
path: root/src/modules/rtv/rtv.c
diff options
context:
space:
mode:
authorVito Caputo <vcaputo@pengaru.com>2019-11-14 21:35:25 -0800
committerVito Caputo <vcaputo@pengaru.com>2019-11-14 21:44:15 -0800
commitaeb6fc5986757b0186634f7106d32861dbf55c54 (patch)
tree9780f85688a6c94ea2ca5763e1bc8c433e1d997f /src/modules/rtv/rtv.c
parent3f260bcbcd9d29457d9dbd4f27a913c8d2e5d555 (diff)
rtv: implement "Rototiller TV" renderer
This is sort of a meta renderer, as it simply renders other modules in its prepare_frame() stage. They're still threaded as the newly public rototiller_module_render() utilizes the threading machinery, it just needs to be called from the serial phase @ prepare_frame(). I'm pretty sure this module will leak memory every time it changes modules, since the existing cleanup paths for the modules hasn't needed to be thorough in the least. So that's something to fix in a later commit, go through all the modules and make sure their destroy_context() entrypoints actually cleans everything up. See the source for some rtv-specific TODOs.
Diffstat (limited to 'src/modules/rtv/rtv.c')
-rw-r--r--src/modules/rtv/rtv.c114
1 files changed, 114 insertions, 0 deletions
diff --git a/src/modules/rtv/rtv.c b/src/modules/rtv/rtv.c
new file mode 100644
index 0000000..da6ae52
--- /dev/null
+++ b/src/modules/rtv/rtv.c
@@ -0,0 +1,114 @@
+#include <stdlib.h>
+#include <time.h>
+
+#include "fb.h"
+#include "rototiller.h"
+#include "util.h"
+
+/* Copyright (C) 2019 - Vito Caputo <vcaputo@pengaru.com> */
+
+/* This implements an MTV-inspired random slideshow of rototiller modules.
+ *
+ * Eventually it'd be nice to have it show a caption every time a new
+ * module starts overlaying the name, author, license, etc.
+ *
+ * Some TODO items:
+ * - show captions (need text rendering)
+ * - optionally persist module contexts so they resume rather than restart
+ * - runtime-configurable duration
+ * - randomize runtime settings of shown modules
+ * - redo the next module selection from random to
+ * walking the list and randomizing the list every
+ * time it completes a cycle. The current dumb
+ * random technique will happily keep showing you the
+ * same thing over and over.
+ */
+
+#define RTV_DURATION_SECS 15
+
+typedef struct rtv_context_t {
+ const rototiller_module_t **modules;
+ size_t n_modules;
+
+ time_t last_switch;
+ const rototiller_module_t *module;
+ void *module_ctxt;
+} rtv_context_t;
+
+static void setup_next_module(rtv_context_t *ctxt);
+static void * rtv_create_context(void);
+static void rtv_destroy_context(void *context);
+static void rtv_prepare_frame(void *context, unsigned n_cpus, fb_fragment_t *fragment, rototiller_fragmenter_t *res_fragmenter);
+static void rtv_finish_frame(void *context, fb_fragment_t *fragment);
+
+
+rototiller_module_t rtv_module = {
+ .create_context = rtv_create_context,
+ .destroy_context = rtv_destroy_context,
+ .prepare_frame = rtv_prepare_frame,
+ .finish_frame = rtv_finish_frame,
+ .name = "rtv",
+ .description = "Rototiller TV",
+ .author = "Vito Caputo <vcaputo@pengaru.com>",
+ .license = "GPLv2",
+};
+
+
+static void setup_next_module(rtv_context_t *ctxt)
+{
+ int i;
+
+ /* TODO: most of this module stuff should probably be
+ * in rototiller.c helpers, but it's harmless for now.
+ */
+ if (ctxt->module) {
+ if (ctxt->module->destroy_context)
+ ctxt->module->destroy_context(ctxt->module_ctxt);
+
+ ctxt->module_ctxt = NULL;
+ }
+
+ do {
+ i = rand() % ctxt->n_modules;
+ } while (ctxt->modules[i] == &rtv_module || ctxt->modules[i] == ctxt->module);
+
+ ctxt->module = ctxt->modules[i];
+ if (ctxt->module->create_context)
+ ctxt->module_ctxt = ctxt->module->create_context();
+
+ ctxt->last_switch = time(NULL);
+}
+
+
+static void * rtv_create_context(void)
+{
+ rtv_context_t *ctxt = calloc(1, sizeof(rtv_context_t));
+
+ rototiller_get_modules(&ctxt->modules, &ctxt->n_modules);
+ setup_next_module(ctxt);
+
+ return ctxt;
+}
+
+
+static void rtv_destroy_context(void *context)
+{
+ free(context);
+}
+
+
+static void rtv_prepare_frame(void *context, unsigned n_cpus, fb_fragment_t *fragment, rototiller_fragmenter_t *res_fragmenter)
+{
+ rtv_context_t *ctxt = context;
+
+ if (!ctxt->last_switch || time(NULL) - ctxt->last_switch > RTV_DURATION_SECS)
+ setup_next_module(ctxt);
+
+ rototiller_module_render(ctxt->module, ctxt->module_ctxt, fragment);
+}
+
+
+static void rtv_finish_frame(void *context, fb_fragment_t *fragment)
+{
+ /* TODO: this is stubbed here for drawing the caption overlay */
+}
© All Rights Reserved