diff options
author | Vito Caputo <vcaputo@pengaru.com> | 2023-06-15 17:12:51 -0700 |
---|---|---|
committer | Vito Caputo <vcaputo@pengaru.com> | 2023-06-15 17:15:38 -0700 |
commit | c98f43460ce84f3646f554fe250a10f452121079 (patch) | |
tree | f526143a6b512320a9429272b9366faa5479ea48 /src/modules/rkt | |
parent | c7cf0555e273f47827bdea12a823de49da323951 (diff) |
modules/rkt: handle stream taps @ context create
It's problematic getting this stuff online at render time,
because the modules end up rendering with uninitialized tap
values in that first frame.
With this change modules can get their taps on-stream at context
create, and we'll notice and do the initial rocket update just
before returning the rkt context to prime everyone on-stream.
Diffstat (limited to 'src/modules/rkt')
-rw-r--r-- | src/modules/rkt/rkt.c | 134 |
1 files changed, 71 insertions, 63 deletions
diff --git a/src/modules/rkt/rkt.c b/src/modules/rkt/rkt.c index 257671a..2cc031d 100644 --- a/src/modules/rkt/rkt.c +++ b/src/modules/rkt/rkt.c @@ -79,63 +79,6 @@ static const struct sync_track * sync_get_trackf(struct sync_device *device, con } -static til_module_context_t * rkt_create_context(const til_module_t *module, til_stream_t *stream, unsigned seed, unsigned ticks, unsigned n_cpus, til_setup_t *setup) -{ - rkt_setup_t *s = (rkt_setup_t *)setup; - rkt_context_t *ctxt; - - ctxt = til_module_context_new(module, sizeof(rkt_context_t) + s->n_scenes * sizeof(*ctxt->scenes), stream, seed, ticks, n_cpus, setup); - if (!ctxt) - return NULL; - - ctxt->sync_device = sync_create_device(s->base); - if (!ctxt->sync_device) - return til_module_context_free(&ctxt->til_module_context); - - if (s->connect) { - /* XXX: it'd be better if we just reconnected periodically instead of hard failing */ - if (sync_tcp_connect(ctxt->sync_device, s->host, s->port)) - return til_module_context_free(&ctxt->til_module_context); - } - - ctxt->scene_track = sync_get_trackf(ctxt->sync_device, "%s:scene", setup->path); - if (!ctxt->scene_track) - return til_module_context_free(&ctxt->til_module_context); - - for (size_t i = 0; i < s->n_scenes; i++) { - int r; - - /* FIXME TODO: this needs to be handle-aware so scenes can directly reference existing contexts */ - ctxt->scenes[i].module = til_lookup_module(s->scenes[i].module_name); - if (!ctxt->scenes[i].module) /* this isn't really expected since setup already does this */ - return til_module_context_free(&ctxt->til_module_context); - - r = til_module_create_context(ctxt->scenes[i].module, stream, rand_r(&seed), ticks, 0, s->scenes[i].setup, &ctxt->scenes[i].module_ctxt); - if (r < 0) - return til_module_context_free(&ctxt->til_module_context); - } - - ctxt->rows_per_ms = s->rows_per_ms; - ctxt->last_ticks = ticks; - - return &ctxt->til_module_context; -} - - -static void rkt_destroy_context(til_module_context_t *context) -{ - rkt_context_t *ctxt = (rkt_context_t *)context; - - if (ctxt->sync_device) - sync_destroy_device(ctxt->sync_device); - - for (size_t i = 0; i < ((rkt_setup_t *)context->setup)->n_scenes; i++) - til_module_context_free(ctxt->scenes[i].module_ctxt); - - free(context); -} - - static void rkt_sync_pause(void *context, int flag) { rkt_context_t *ctxt = context; @@ -267,20 +210,85 @@ static int rkt_pipe_update(void *context, til_stream_pipe_t *pipe, const void *o } -static void rkt_render_fragment(til_module_context_t *context, til_stream_t *stream, unsigned ticks, unsigned cpu, til_fb_fragment_t **fragment_ptr) +static void rkt_update_rocket(rkt_context_t *ctxt, unsigned ticks) { - rkt_context_t *ctxt = (rkt_context_t *)context; - if (!ctxt->paused) ctxt->rocket_row += ((double)(ticks - ctxt->last_ticks)) * ctxt->rows_per_ms; ctxt->last_ticks = ticks; - /* hooks-setting is idempotent and cheap so we just always do it, and technicallly the stream can get changed out on us frame-to-frame */ - til_stream_set_hooks(stream, &rkt_stream_hooks, ctxt); - /* ctxt->rocket_row needs to be updated */ sync_update(ctxt->sync_device, ctxt->rocket_row, &rkt_sync_cb, ctxt); +} + + +static til_module_context_t * rkt_create_context(const til_module_t *module, til_stream_t *stream, unsigned seed, unsigned ticks, unsigned n_cpus, til_setup_t *setup) +{ + rkt_setup_t *s = (rkt_setup_t *)setup; + rkt_context_t *ctxt; + + ctxt = til_module_context_new(module, sizeof(rkt_context_t) + s->n_scenes * sizeof(*ctxt->scenes), stream, seed, ticks, n_cpus, setup); + if (!ctxt) + return NULL; + + ctxt->sync_device = sync_create_device(s->base); + if (!ctxt->sync_device) + return til_module_context_free(&ctxt->til_module_context); + + if (s->connect) { + /* XXX: it'd be better if we just reconnected periodically instead of hard failing */ + if (sync_tcp_connect(ctxt->sync_device, s->host, s->port)) + return til_module_context_free(&ctxt->til_module_context); + } + + ctxt->scene_track = sync_get_trackf(ctxt->sync_device, "%s:scene", setup->path); + if (!ctxt->scene_track) + return til_module_context_free(&ctxt->til_module_context); + + /* set the stream hooks early so context creates can establish taps early */ + til_stream_set_hooks(stream, &rkt_stream_hooks, ctxt); + + for (size_t i = 0; i < s->n_scenes; i++) { + int r; + + /* FIXME TODO: this needs to be handle-aware so scenes can directly reference existing contexts */ + ctxt->scenes[i].module = til_lookup_module(s->scenes[i].module_name); + if (!ctxt->scenes[i].module) /* this isn't really expected since setup already does this */ + return til_module_context_free(&ctxt->til_module_context); + + r = til_module_create_context(ctxt->scenes[i].module, stream, rand_r(&seed), ticks, 0, s->scenes[i].setup, &ctxt->scenes[i].module_ctxt); + if (r < 0) + return til_module_context_free(&ctxt->til_module_context); + } + + ctxt->rows_per_ms = s->rows_per_ms; + ctxt->last_ticks = ticks; + + rkt_update_rocket(ctxt, ticks); + + return &ctxt->til_module_context; +} + + +static void rkt_destroy_context(til_module_context_t *context) +{ + rkt_context_t *ctxt = (rkt_context_t *)context; + + if (ctxt->sync_device) + sync_destroy_device(ctxt->sync_device); + + for (size_t i = 0; i < ((rkt_setup_t *)context->setup)->n_scenes; i++) + til_module_context_free(ctxt->scenes[i].module_ctxt); + + free(context); +} + + +static void rkt_render_fragment(til_module_context_t *context, til_stream_t *stream, unsigned ticks, unsigned cpu, til_fb_fragment_t **fragment_ptr) +{ + rkt_context_t *ctxt = (rkt_context_t *)context; + + rkt_update_rocket(ctxt, ticks); /* this drives our per-rocket-track updates, with the tracks registered as owner_foo on the pipes, respectively */ til_stream_for_each_pipe(stream, rkt_pipe_update, ctxt); |