From 6b7a0cdb5bbdae6c75b612357e8df0f9ad761482 Mon Sep 17 00:00:00 2001 From: Vito Caputo Date: Mon, 25 Apr 2022 15:33:35 -0700 Subject: modules/blinds: add count and orientation settings This adds count=N and orientation={horizontal,vertical} settings. Which was precipitated by the introduction of a vertical blinds mode. e.g.: --module=blinds,count=32,orientation=vertical or for a quick tour of the possibilities: --module=rtv,channels=blinds,duration=1,context_duration=1,snow_duration=0 weeeee --- src/modules/blinds/blinds.c | 166 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 159 insertions(+), 7 deletions(-) diff --git a/src/modules/blinds/blinds.c b/src/modules/blinds/blinds.c index 7ce0a92..c0ae079 100644 --- a/src/modules/blinds/blinds.c +++ b/src/modules/blinds/blinds.c @@ -1,5 +1,7 @@ +#include #include #include +#include #include #include "til.h" @@ -7,12 +9,61 @@ /* Copyright (C) 2017-2022 Vito Caputo */ -#define NUM_BLINDS 16 +#define BLINDS_DEFAULT_COUNT 16 +#define BLINDS_DEFAULT_ORIENTATION BLINDS_ORIENTATION_HORIZONTAL -/* draw a blind over fragment */ -static inline void draw_blind(til_fb_fragment_t *fragment, unsigned row, float t) + +typedef enum blinds_orientation_t { + BLINDS_ORIENTATION_HORIZONTAL, + BLINDS_ORIENTATION_VERTICAL, +} blinds_orientation_t; + +typedef struct blinds_setup_t { + til_setup_t til_setup; + unsigned count; + blinds_orientation_t orientation; +} blinds_setup_t; + +typedef struct blinds_context_t { + blinds_setup_t setup; +} blinds_context_t; + + +static blinds_setup_t blinds_default_setup = { + .count = BLINDS_DEFAULT_COUNT, + .orientation = BLINDS_DEFAULT_ORIENTATION, +}; + + +static void * blinds_create_context(unsigned ticks, unsigned num_cpus, til_setup_t *setup) +{ + blinds_context_t *ctxt; + + if (!setup) + setup = &blinds_default_setup.til_setup; + + ctxt = calloc(1, sizeof(blinds_context_t)); + if (!ctxt) + return NULL; + + ctxt->setup = *(blinds_setup_t *)setup; + + return ctxt; +} + + +static void blinds_destroy_context(void *context) +{ + blinds_context_t *ctxt = context; + + free(ctxt); +} + + +/* draw a horizontal blind over fragment */ +static inline void draw_blind_horizontal(til_fb_fragment_t *fragment, unsigned row, unsigned count, float t) { - unsigned row_height = fragment->frame_height / NUM_BLINDS; + unsigned row_height = fragment->frame_height / count; unsigned height = roundf(t * (float)row_height); for (unsigned y = 0; y < height; y++) @@ -20,25 +71,126 @@ static inline void draw_blind(til_fb_fragment_t *fragment, unsigned row, float t } +/* draw a vertical blind over fragment */ +static inline void draw_blind_vertical(til_fb_fragment_t *fragment, unsigned column, unsigned count, float t) +{ + unsigned column_width = fragment->frame_width / count; + unsigned width = roundf(t * (float)column_width); + + for (unsigned y = 0; y < fragment->height; y++) + memset(fragment->buf + y * (fragment->pitch >> 2) + column * column_width, 0xff, width * 4); +} + + /* draw blinds over the fragment */ static void blinds_render_fragment(void *context, unsigned ticks, unsigned cpu, til_fb_fragment_t *fragment) { + blinds_context_t *ctxt = context; + static float rr; - unsigned row; + unsigned blind; float r; til_fb_fragment_clear(fragment); - for (r = rr, row = 0; row < NUM_BLINDS; row++, r += .1) - draw_blind(fragment, row, 1.f - fabsf(cosf(r))); + for (r = rr, blind = 0; blind < ctxt->setup.count; blind++, r += .1) { + switch (ctxt->setup.orientation) { + case BLINDS_ORIENTATION_HORIZONTAL: + draw_blind_horizontal(fragment, blind, ctxt->setup.count, 1.f - fabsf(cosf(r))); + break; + case BLINDS_ORIENTATION_VERTICAL: + draw_blind_vertical(fragment, blind, ctxt->setup.count, 1.f - fabsf(cosf(r))); + break; + } + } rr += .01; } +static int blinds_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 *orientation; + const char *count; + const char *orientation_values[] = { + "horizontal", + "vertical", + NULL + }; + const char *count_values[] = { + "2", + "4", + "8", + "12", + "16", + "24", + "32", + NULL + }; + int r; + + r = til_settings_get_and_describe_value(settings, + &(til_setting_desc_t){ + .name = "Blinds orientation", + .key = "orientation", + .regex = "^(horizontal|vertical)", + .preferred = orientation_values[BLINDS_DEFAULT_ORIENTATION], + .values = orientation_values, + .annotations = NULL + }, + &orientation, + res_setting, + res_desc); + if (r) + return r; + + r = til_settings_get_and_describe_value(settings, + &(til_setting_desc_t){ + .name = "Blinds count", + .key = "count", + .regex = "\\.[0-9]+", + .preferred = TIL_SETTINGS_STR(BLINDS_DEFAULT_COUNT), + .values = count_values, + .annotations = NULL + }, + &count, + res_setting, + res_desc); + if (r) + return r; + + if (res_setup) { + blinds_setup_t *setup; + + setup = til_setup_new(sizeof(*setup), (void(*)(til_setup_t *))free); + if (!setup) + return -ENOMEM; + + sscanf(count, "%u", &setup->count); + + if (!strcasecmp(orientation, "horizontal")) { + setup->orientation = BLINDS_ORIENTATION_HORIZONTAL; + } else if (!strcasecmp(orientation, "vertical")) { + setup->orientation = BLINDS_ORIENTATION_VERTICAL; + } else { + til_setup_free(&setup->til_setup); + + return -EINVAL; + } + + *res_setup = &setup->til_setup; + } + + return 0; +} + + til_module_t blinds_module = { + .create_context = blinds_create_context, + .destroy_context = blinds_destroy_context, .render_fragment = blinds_render_fragment, + .setup = blinds_setup, .name = "blinds", .description = "Retro 80s-inspired window blinds", .author = "Vito Caputo ", -- cgit v1.2.1