summaryrefslogtreecommitdiff
path: root/src/modules/strobe
diff options
context:
space:
mode:
authorVito Caputo <vcaputo@pengaru.com>2022-09-04 23:32:55 -0700
committerVito Caputo <vcaputo@pengaru.com>2022-09-04 23:44:33 -0700
commitb4c9935b5d167ca2ef69b5a6a81ae207f462b45c (patch)
treeda526ecfbd90215d70420d2dce75d5eed0adfb9b /src/modules/strobe
parentb5a2667f6c94d5a275251bf6cc359480100a651c (diff)
modules/strobe: add rudimentary strobe light module
After reading about the Dreamachine[0], I wanted to experience this phenomenon. The javascript-based web implementations struggled to hold a steady 10Hz rate and would flicker like crazy, so here we are. Only setting right now is period=float_seconds, defaults to .1 for 10Hz. One limitation in the current implementation is when the frame rate can't keep up with the period the strobe will just stick on without ever going off, because the period will always be expired. There should probably be a setting to force turning off for at least one frame when it can't keep up. [0] https://en.wikipedia.org/wiki/Dreamachine
Diffstat (limited to 'src/modules/strobe')
-rw-r--r--src/modules/strobe/Makefile.am3
-rw-r--r--src/modules/strobe/strobe.c155
2 files changed, 158 insertions, 0 deletions
diff --git a/src/modules/strobe/Makefile.am b/src/modules/strobe/Makefile.am
new file mode 100644
index 0000000..8bac057
--- /dev/null
+++ b/src/modules/strobe/Makefile.am
@@ -0,0 +1,3 @@
+noinst_LTLIBRARIES = libstrobe.la
+libstrobe_la_SOURCES = strobe.c
+libstrobe_la_CPPFLAGS = -I@top_srcdir@/src
diff --git a/src/modules/strobe/strobe.c b/src/modules/strobe/strobe.c
new file mode 100644
index 0000000..4616df4
--- /dev/null
+++ b/src/modules/strobe/strobe.c
@@ -0,0 +1,155 @@
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "til.h"
+#include "til_fb.h"
+#include "til_module_context.h"
+
+/* Dead-simple strobe light, initially made to try simulate this contraption:
+ * https://en.wikipedia.org/wiki/Dreamachine
+ *
+ * But it might actually have some general utility in compositing.
+ */
+
+/* Copyright (C) 2022 Vito Caputo <vcaputo@pengaru.com> */
+
+/* TODO:
+ * - Make period setting more flexible
+ * - Currently if the frame rate can't keep up with the period, strobe will
+ * just stick on. There should probably be a force_flash={yes,no} setting
+ * to ensure a flash still occurs when the frame rate can't keep up.
+ */
+
+#define STROBE_DEFAULT_PERIOD .1
+
+typedef struct strobe_setup_t {
+ til_setup_t til_setup;
+ float period;
+} strobe_setup_t;
+
+typedef struct strobe_context_t {
+ til_module_context_t til_module_context;
+ strobe_setup_t setup;
+ unsigned ticks;
+ unsigned flash:1;
+} strobe_context_t;
+
+
+static strobe_setup_t strobe_default_setup = {
+ .period = STROBE_DEFAULT_PERIOD,
+};
+
+
+static til_module_context_t * strobe_create_context(unsigned seed, unsigned ticks, unsigned n_cpus, til_setup_t *setup)
+{
+ strobe_context_t *ctxt;
+
+ if (!setup)
+ setup = &strobe_default_setup.til_setup;
+
+ ctxt = til_module_context_new(sizeof(strobe_context_t), seed, ticks, n_cpus);
+ if (!ctxt)
+ return NULL;
+
+ ctxt->setup = *(strobe_setup_t *)setup;
+ ctxt->ticks = ticks;
+
+ return &ctxt->til_module_context;
+}
+
+
+static void strobe_prepare_frame(til_module_context_t *context, unsigned ticks, til_fb_fragment_t **fragment_ptr, til_frame_plan_t *res_frame_plan)
+{
+ strobe_context_t *ctxt = (strobe_context_t *)context;
+
+ *res_frame_plan = (til_frame_plan_t){ .fragmenter = til_fragmenter_slice_per_cpu };
+
+ if (ticks - ctxt->ticks >= (unsigned)(ctxt->setup.period * 1000.f))
+ ctxt->flash = 1;
+}
+
+
+static void strobe_render_fragment(til_module_context_t *context, unsigned ticks, unsigned cpu, til_fb_fragment_t **fragment_ptr)
+{
+ strobe_context_t *ctxt = (strobe_context_t *)context;
+ til_fb_fragment_t *fragment = *fragment_ptr;
+
+ if (!ctxt->flash)
+ return til_fb_fragment_clear(fragment);
+
+ til_fb_fragment_fill(fragment, TIL_FB_DRAW_FLAG_TEXTURABLE, 0xffffffff);
+}
+
+
+static void strobe_finish_frame(til_module_context_t *context, unsigned int ticks, til_fb_fragment_t **fragment_ptr)
+{
+ strobe_context_t *ctxt = (strobe_context_t *)context;
+
+ if (!ctxt->flash)
+ return;
+
+ ctxt->flash = 0;
+ ctxt->ticks = ticks;
+}
+
+
+static int strobe_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 *period;
+ const char *period_values[] = {
+ ".0166",
+ ".02",
+ ".025",
+ ".05",
+ ".1",
+ ".25",
+ ".5",
+ "1",
+ NULL
+ };
+ int r;
+
+ r = til_settings_get_and_describe_value(settings,
+ &(til_setting_desc_t){
+ .name = "Strobe period",
+ .key = "period",
+ .regex = "\\.[0-9]+",
+ .preferred = TIL_SETTINGS_STR(STROBE_DEFAULT_PERIOD),
+ .values = period_values,
+ .annotations = NULL
+ },
+ &period,
+ res_setting,
+ res_desc);
+ if (r)
+ return r;
+
+ if (res_setup) {
+ strobe_setup_t *setup;
+
+ setup = til_setup_new(sizeof(*setup), (void(*)(til_setup_t *))free);
+ if (!setup)
+ return -ENOMEM;
+
+ sscanf(period, "%f", &setup->period);
+
+ *res_setup = &setup->til_setup;
+ }
+
+ return 0;
+}
+
+
+til_module_t strobe_module = {
+ .create_context = strobe_create_context,
+ .prepare_frame = strobe_prepare_frame,
+ .render_fragment = strobe_render_fragment,
+ .finish_frame = strobe_finish_frame,
+ .setup = strobe_setup,
+ .name = "strobe",
+ .description = "Strobe light (threaded)",
+ .author = "Vito Caputo <vcaputo@pengaru.com>",
+ .flags = TIL_MODULE_OVERLAYABLE,
+};
© All Rights Reserved