diff options
author | Vito Caputo <vcaputo@pengaru.com> | 2020-09-12 19:50:56 -0700 |
---|---|---|
committer | Vito Caputo <vcaputo@pengaru.com> | 2020-09-12 19:50:56 -0700 |
commit | 44b32d60501cc5320de4b34d34c9de3d5f4c11bf (patch) | |
tree | 051d3289c4ecce2146d5785b0619c6c5f606da0b /src/modules/rtv/rtv.c | |
parent | c829689a9b285db0243880d020a727f664d41e74 (diff) |
modules/rtv: implement context_duration setting
This renames rtv_channel_t to rtv_module_t and modules to
channels in various places, which arguably should have been in a
separate commit but I'm not up for separating that out at the
moment.
Fundamentally what's happening is every channel is getting its
own context which may persist across channel switches, this
allows watching a variety of channels in a stateful manner before
they get their contexts recreated with re-randomized settings.
For modules without settings it's not terribly interesting, and
I'm thinking modules should probably start deriving some of their
state more directly from the global ticks rather than their own
per-context counters and timers. That way even when their
contexts get recreated with re-randomized settings, there can be
some continuity for ticks-derived state. Deriving position for
instance mathematically from ticks would allow things to be
located continuously despite having their contexts and even
settings changed, which may be interesting.
Anyhow, if you want the previous behavior where contexts are
always recreated on channel switch, just set the value to be
contxt_duration equal to duration.
Diffstat (limited to 'src/modules/rtv/rtv.c')
-rw-r--r-- | src/modules/rtv/rtv.c | 144 |
1 files changed, 93 insertions, 51 deletions
diff --git a/src/modules/rtv/rtv.c b/src/modules/rtv/rtv.c index be974d1..3aaad65 100644 --- a/src/modules/rtv/rtv.c +++ b/src/modules/rtv/rtv.c @@ -18,27 +18,31 @@ #define RTV_SNOW_DURATION_SECS 1 #define RTV_DURATION_SECS 15 #define RTV_CAPTION_DURATION_SECS 5 +#define RTV_CONTEXT_DURATION_SECS 60 -typedef struct rtv_module_t { +typedef struct rtv_channel_t { const rototiller_module_t *module; + void *module_ctxt; + time_t last_on_time, cumulative_time; + char *settings; + txt_t *caption; unsigned order; -} rtv_module_t; +} rtv_channel_t; typedef struct rtv_context_t { unsigned n_cpus; time_t next_switch, next_hide_caption; - const rototiller_module_t *module, *last_module; - void *module_ctxt; + rtv_channel_t *channel, *last_channel; txt_t *caption; - const rototiller_module_t *snow_module; + rtv_channel_t snow_channel; - size_t n_modules; - rtv_module_t modules[]; + size_t n_channels; + rtv_channel_t channels[]; } rtv_context_t; -static void setup_next_module(rtv_context_t *ctxt, unsigned ticks); +static void setup_next_channel(rtv_context_t *ctxt, unsigned ticks); static void * rtv_create_context(unsigned ticks, unsigned num_cpus); static void rtv_destroy_context(void *context); static void rtv_prepare_frame(void *context, unsigned ticks, unsigned n_cpus, fb_fragment_t *fragment, rototiller_fragmenter_t *res_fragmenter); @@ -46,6 +50,7 @@ static void rtv_finish_frame(void *context, unsigned ticks, fb_fragment_t *fragm static int rtv_setup(const settings_t *settings, setting_desc_t **next_setting); static unsigned rtv_duration = RTV_DURATION_SECS; +static unsigned rtv_context_duration = RTV_CONTEXT_DURATION_SECS; static unsigned rtv_snow_duration = RTV_SNOW_DURATION_SECS; static unsigned rtv_caption_duration = RTV_CAPTION_DURATION_SECS; static char **rtv_channels; @@ -64,26 +69,26 @@ rototiller_module_t rtv_module = { }; -static int cmp_modules(const void *p1, const void *p2) +static int cmp_channels(const void *p1, const void *p2) { - const rtv_module_t *m1 = p1, *m2 = p2; + const rtv_channel_t *c1 = p1, *c2 = p2; - if (m1->order < m2->order) + if (c1->order < c2->order) return -1; - if (m1->order > m2->order) + if (c1->order > c2->order) return 1; return 0; } -static void randomize_modules(rtv_context_t *ctxt) +static void randomize_channels(rtv_context_t *ctxt) { - for (size_t i = 0; i < ctxt->n_modules; i++) - ctxt->modules[i].order = rand(); + for (size_t i = 0; i < ctxt->n_channels; i++) + ctxt->channels[i].order = rand(); - qsort(ctxt->modules, ctxt->n_modules, sizeof(rtv_module_t), cmp_modules); + qsort(ctxt->channels, ctxt->n_channels, sizeof(rtv_channel_t), cmp_channels); } @@ -129,69 +134,84 @@ static char * randomize_module_setup(const rototiller_module_t *module) } -static void setup_next_module(rtv_context_t *ctxt, unsigned ticks) +static void setup_next_channel(rtv_context_t *ctxt, unsigned ticks) { time_t now = time(NULL); /* 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); + if (ctxt->channel) { + ctxt->channel->cumulative_time += now - ctxt->channel->last_on_time; + if (ctxt->channel->cumulative_time >= rtv_context_duration) { + ctxt->channel->cumulative_time = 0; + + if (ctxt->channel->module->destroy_context) + ctxt->channel->module->destroy_context(ctxt->channel->module_ctxt); + ctxt->channel->module_ctxt = NULL; + + free(ctxt->channel->settings); + ctxt->channel->settings = NULL; - ctxt->module_ctxt = NULL; - ctxt->caption = txt_free(ctxt->caption); + ctxt->caption = ctxt->channel->caption = txt_free(ctxt->channel->caption); + } } - if (!ctxt->n_modules || ctxt->module != ctxt->snow_module) { - ctxt->last_module = ctxt->module; - ctxt->module = ctxt->snow_module; + if (!ctxt->n_channels || ctxt->channel != &ctxt->snow_channel) { + ctxt->last_channel = ctxt->channel; + ctxt->channel = &ctxt->snow_channel; + ctxt->caption = NULL; ctxt->next_switch = now + rtv_snow_duration; } else { - char *setup; size_t i; - for (i = 0; i < ctxt->n_modules; i++) { - if (ctxt->modules[i].module == ctxt->last_module) { + for (i = 0; i < ctxt->n_channels; i++) { + if (&ctxt->channels[i] == ctxt->last_channel) { i++; break; } } - if (i >= ctxt->n_modules) { - randomize_modules(ctxt); - ctxt->last_module = NULL; + if (i >= ctxt->n_channels) { + randomize_channels(ctxt); + ctxt->last_channel = NULL; i = 0; } - ctxt->module = ctxt->modules[i].module; + ctxt->channel = &ctxt->channels[i]; - setup = randomize_module_setup(ctxt->module); + if (!ctxt->channel->settings) { + char *settings; + txt_t *caption; - ctxt->caption = txt_newf("Title: %s\nAuthor: %s\nDescription: %s\nLicense: %s%s%s", - ctxt->module->name, - ctxt->module->author, - ctxt->module->description, - ctxt->module->license, - setup ? "\nSettings: " : "", - setup ? setup : ""); + settings = randomize_module_setup(ctxt->channel->module); + caption = txt_newf("Title: %s\nAuthor: %s\nDescription: %s\nLicense: %s%s%s", + ctxt->channel->module->name, + ctxt->channel->module->author, + ctxt->channel->module->description, + ctxt->channel->module->license, + settings ? "\nSettings: " : "", + settings ? settings : ""); - free(setup); + ctxt->caption = ctxt->channel->caption = caption; + ctxt->channel->settings = settings ? settings : strdup(""); + } ctxt->next_switch = now + rtv_duration; ctxt->next_hide_caption = now + rtv_caption_duration; } - if (ctxt->module->create_context) - ctxt->module_ctxt = ctxt->module->create_context(ticks, ctxt->n_cpus); + if (!ctxt->channel->module_ctxt && ctxt->channel->module->create_context) + ctxt->channel->module_ctxt = ctxt->channel->module->create_context(ticks, ctxt->n_cpus); + + ctxt->channel->last_on_time = now; } static int rtv_should_skip_module(const rtv_context_t *ctxt, const rototiller_module_t *module) { if (module == &rtv_module || - module == ctxt->snow_module) + module == ctxt->snow_channel.module) return 1; if (!rtv_channels) @@ -214,21 +234,24 @@ static void * rtv_create_context(unsigned ticks, unsigned num_cpus) rototiller_get_modules(&modules, &n_modules); - ctxt = calloc(1, sizeof(rtv_context_t) + n_modules * sizeof(rtv_module_t)); + ctxt = calloc(1, sizeof(rtv_context_t) + n_modules * sizeof(rtv_channel_t)); if (!ctxt) return NULL; ctxt->n_cpus = num_cpus; - ctxt->snow_module = rototiller_lookup_module("snow"); + + ctxt->snow_channel.module = rototiller_lookup_module("snow"); + if (ctxt->snow_channel.module->create_context) + ctxt->snow_channel.module_ctxt = ctxt->snow_channel.module->create_context(ticks, ctxt->n_cpus); for (size_t i = 0; i < n_modules; i++) { if (rtv_should_skip_module(ctxt, modules[i])) continue; - ctxt->modules[ctxt->n_modules++].module = modules[i]; + ctxt->channels[ctxt->n_channels++].module = modules[i]; } - setup_next_module(ctxt, ticks); + setup_next_channel(ctxt, ticks); return ctxt; } @@ -246,12 +269,12 @@ static void rtv_prepare_frame(void *context, unsigned ticks, unsigned n_cpus, fb time_t now = time(NULL); if (now >= ctxt->next_switch) - setup_next_module(ctxt, ticks); + setup_next_channel(ctxt, ticks); if (now >= ctxt->next_hide_caption) - ctxt->caption = txt_free(ctxt->caption); + ctxt->caption = NULL; - rototiller_module_render(ctxt->module, ctxt->module_ctxt, ticks, fragment); + rototiller_module_render(ctxt->channel->module, ctxt->channel->module_ctxt, ticks, fragment); } @@ -280,6 +303,7 @@ static void rtv_finish_frame(void *context, unsigned ticks, fb_fragment_t *fragm static int rtv_setup(const settings_t *settings, setting_desc_t **next_setting) { const char *duration; + const char *context_duration; const char *caption_duration; const char *snow_duration; const char *channels; @@ -317,6 +341,23 @@ static int rtv_setup(const settings_t *settings, setting_desc_t **next_setting) return 1; } + context_duration = settings_get_value(settings, "context_duration"); + if (!context_duration) { + int r; + + r = setting_desc_clone(&(setting_desc_t){ + .name = "Context Duration In Seconds", + .key = "context_duration", + .regex = "\\.[0-9]+", + .preferred = SETTINGS_STR(RTV_CONTEXT_DURATION_SECS), + .annotations = NULL + }, next_setting); + if (r < 0) + return r; + + return 1; + } + caption_duration = settings_get_value(settings, "caption_duration"); if (!caption_duration) { int r; @@ -391,6 +432,7 @@ static int rtv_setup(const settings_t *settings, setting_desc_t **next_setting) /* TODO FIXME: parse errors */ sscanf(duration, "%u", &rtv_duration); + sscanf(context_duration, "%u", &rtv_context_duration); sscanf(caption_duration, "%u", &rtv_caption_duration); sscanf(snow_duration, "%u", &rtv_snow_duration); |