summaryrefslogtreecommitdiff
path: root/src/modules/rtv
AgeCommit message (Collapse)Author
2023-05-11modules/*: remove use of static default setupsVito Caputo
There was a time when it made sense for context creates needing setups but not receiving them to still be functional with some sane defaults. But with recursive settings, we really shouldn't ever have orphaned nested module uses unreachable by a proper setup. So let's just get rid of this fallback, and exclusively rely on the baked setups provided by the .setup() methods. They still have preferred defaults, and the proper setup production machinery is what should be responsible for applying those at runtime where they may also be overridden or otherwise influenced.
2023-05-11modules/rtv: add basic log_channels= settingVito Caputo
This introduces a boolean style log_channels= setting for enabling logging of channel settings on channel switch. It might be nice to change this to accept stdout/stderr/fdnum as the setting instead of always directing at stderr. This also doesn't capture the seed state so it's not exactly logging everything needed to reproduce wholly what is being shown. Some compositions depend more on rand than others, so it matters at varying degrees. It'd be nice for settings syntax to have some global syntax supported where a seed can always be embedded to be loaded. Introducing such things as global settings to the settings syntax is a pending TODO item... right now the only way to load seed state is at startup passed to main as --seed=. That's not gonna cut it long-term. This is an easy big step in the right direction though. Trying to make sense of what's on-screen from the truncated captions is impossible. Even if the captions wrapped the settings, it would be tricky to catch the settings without recording the output or screenshotting. This also immediately makes me wonder about the voting system for rtv where we log settings of favorites... then roll those into playlists.
2023-05-11til_settings: introduce til_setting_spec_t concept vs. descVito Caputo
For recursive settings the individual setting being described needs to get added to a potentially different settings instance than the one being operated on at the top of the current setup_func phase. The settings instance being passed around for a setup_func to operate on is constified, mainly to try ensure modules don't start directly mucking with the settings. They're supposed to just describe what they want next and iterate back and forth, with the front-end creating the settings from the returned descs however is appropriate, eventually building up the settings to completion. But since it's the setup_func that decides which settings instance is appropriate for containing the setting.. at some point it must associate a settings instance with the desc it's producing, one that is going to be necessarily written to. So here I'm just turning the existing til_setting_desc_t to a "spec", unchanged. And introducing a new til_setting_desc_t embedding the spec, accompanied by a non-const til_settings_t* "container". Now what setup_funcs use to express settings are a spec, otherwise identically to before. Instead of cloning a desc to allocate it for returning to the front-end, the desc is created from a spec with the target settings instance passed in. This turns the desc step where we take a constified settings instance and cast it into a non-const a more formal act of going from spec->desc, binding the spec to a specific settings instance. It will also serve to isolate that hacky cast to a til_settings function, and all the accessors of til_setting_desc_t needing to operate on the containing settings instance can just do so. As of this commit, the container pointer is just sitting in the desc_t but isn't being made use of or even assigned yet. This is just to minimize the amount of churn happening in this otherwise mostly mechanical and sprawling commit. There's also been some small changes surrounding the desc generators and plumbing of the settings instance where there previously wasn't any. It's unclear to me if desc generators will stay desc generators or turn into spec generators. For now those are mostly just used by the drm_fb stuff anyways, modules haven't made use of them, so they can stay a little crufty harmlessly for now.
2023-01-20til: pass module to .context_create()/til_module_context_new()Vito Caputo
Let's make it so til_module_context_t as returned from til_module_context_new() can immediately be freed via til_module_context_free(). Previously it was only after the context propagated out to til_module_context_create() that it could be freed that way, as that was where the module member was being assigned. With this change, and wiring up the module pointer into til_module_t.create_context() as well for convenient providing to til_module_context_new(), til_module_t.create_context() error paths can easily cleanup via `return til_module_context_free()` But this does require the til_module_t.destroy_context() be able to safely handle partially constructed contexts, since the mid-create failure freeing won't necessarily have all the members initialized. There will probably be some NULL derefs to fix up, but at least the contexts are zero-initialized @ new.
2023-01-11modules/rtv: skip hermetic/experimental modules for "all"Vito Caputo
This allows explicit listing of such modules as channels, while protecting the automagic/defaults scenario. If there's a future --experimental flag or such added, then the TIL_MODULE_EXPERIMENTAL check will have to become conditional on it.
2023-01-11* turn til_fb_fragment_t.stream into a discrete parameterVito Caputo
This was mostly done out of convenience at the expense of turning the fragment struct into more of a junk drawer. But properly cleaning up owned stream pipes on context destroy makes the inappropriateness of being part of til_fb_fragment_t glaringly apparent. Now the stream is just a separate thing passed to context create, with a reference kept in the context for use throughout. Cleanup of the owned pipes on the stream supplied to context create is automagic when the context gets destroyed. Note that despite there being a stream in the module context, the stream to use is still supplied to all the rendering family functions (prepare/render/finish) and it's the passed-in stream which should be used by these functions. This is done to support the possibility of switching out the stream frame-to-frame, which may be interesting. Imagine doing things like a latent stream and a future stream and switching between them on the fly for instance. If there's a sequencing composite module, it could flip between multiple sets of tracks or jump around multiple streams with the visuals immediately flipping accordingly. This should fix the --print-pipes crashing issues caused by lack of cleanup when contexts were removed (like rtv does so often).
2023-01-10*: introduce paths for module contextsVito Caputo
There needs to be a way to address module context instances by name externally, in a manner complementary to settings and taps. This commit adds a string-based path to til_module_context_t, and modifies til_module_create_context() to accept a parent path which is then concatenated with the name of the module to produce the module instance's new path. The name separator used in the paths is '/' just like filesystem paths, but these paths have no relationship to filesystems or files. The root module context creation in rototiller's main simply passes "" as the parent path, resulting in a "/" root as one would expect. There are some obvious complications introduced here however: - checkers in particular creates a context per cpu, simply using the same seed and setup to try make the contexts identical at the same ticks value. With this commit I'm simply passing the incoming path as the parent for creating those contexts, but it's unclear to me if that will work OK. With an eye towards taps deriving their parent path from the context path, I guess these taps would all get the same parent and hash to the same value despite being duplicated. Maybe it Just Works, but one thing is clear - there won't be any way to address the per-cpu taps as-is. Maybe that's desirable though, there's probably not much use in trying to control the taps at the CPU granularity. - when the recursive settings stuff lands, it should bring along the ability to explicitly name settings blocks. Those names should override the module name in constructing the path. I've noted as such in the code. - these paths probably need to be hashed @ initialization time so there needs to be a hash function added to til, and a hash value accompanying the name in the module context. It'd be dumb to keep recomputing the hash when these paths get used for hash table lookups multiple times per frame... there's probably more I'm forgetting right now, but this seems like a good first step. fixup root path
2022-08-07til: til_fb_fragment_t **fragment_ptr all the thingsVito Caputo
Preparatory commit for enabling cloneable/swappable fragments There's an outstanding issue with the til_fb_page_t submission, see comments. Doesn't matter for now since cloning doesn't happen yet, but will need to be addressed before they do.
2022-07-21modules/{compose,rtv}: s/prepare_frame/render_fragment/Vito Caputo
These modules have been doing their work in prepare_frame(), but aren't actually threaded modules and don't return a frame plan from prepare_frame() nor do they provide a render_fragment() to complement the prepare_frame(). The convention thus far has been that single-threaded modules just provide a render_fragment and by not providing a prepare_frame they will be executed serially. These two modules break the contract in a sense by using prepare_frame() without following up with render_fragment(). I'm not sure why it happened that way, maybe at one time prepare_frame() had access to some things that render_fragment() didn't. In any case, just make these use render_fragment() like any other simple non-threaded module would. This was actually causing a crash when n_cpus=1 because module_render_fragment() was assuming the prepare_frame() branch would include a render_fragment(). It should probably be asserting as such.
2022-07-18modules/rtv: s/rand/rand_r/Vito Caputo
just fixing up some vestigial rand() invocations to use the seed
2022-07-18til: wire seed up to til randomizersVito Caputo
til_setting_desc_t.random() and til_module_randomize_setup() now take seeds. Note they are not taking a pointer to a shared seed, but instead receive the seed by value. If a caller wishes the seed to evolve on every invocation into these functions, it should simply insert a rand_r(&seed) in producing the supplied seed value. Within a given randomizer, the seed evolves when appropriate. But isolating the effects by default seems appropriate, so callers can easily have determinism within their respective scope regardless of how much nested random use occurs.
2022-06-10til: introduce til_frame_plan_t and .cpu_affinityVito Caputo
modules/checkers w/fill_module=$module requires a consistent mapping of cpu to fragnum since it creates a per-cpu til_module_context_t for the fill_module. The existing implementation for threaded rendering maximizes performance by letting *any* scheduled to run thread advance fragnum atomically and render the acquired fragnum indiscriminately. A side effect of this is any given frame, even rendered by the same module, will have a random mapping of cpus/threads to fragnums. With this change, the simple til_module_t.prepare_frame() API of returning a bare fragmenter function is changed to instead return a "frame plan" in til_frame_plan_t. Right now til_frame_plan_t just contains the same fragmenter as before, but also has a .cpu_affinity member for setting if the frame requires a stable relationship of cpu/thread to fragnum. Setting .cpu_affinity should be avoided if unnecessary, and that is the default if you don't mention .cpu_affinity at all when initializing the plan in the ergonomic manner w/designated initializers. This is because the way .cpu_affinity is implemented will leave threads spinning while they poll for *their* next fragnum using atomic intrinsics. There's probably some room for improvement here, but this is good enough for now to get things working and correct.
2022-06-10til: add ticks to til_module_context_tVito Caputo
Also wire this up to the til_module_context_new() helper and all its callers. This is in preparation for modules doing more correct delta-T derived animation.
2022-05-29*: pivot to til_module_context_tVito Caputo
- modules now allocate their contexts using til_module_context_new() instead of [cm]alloc(). - modules simply embed til_module_context_t at the start of their respective private context structs, if they do anything with contexts - modules that do nothing with contexts (lack a create_context() method), will now *always* get a til_module_context_t supplied to their other methods regardless of their create_context() presence. So even if you don't have a create_context(), your prepare_frame() and/or render_fragment() methods can still access seed and n_cpus from within the til_module_context_t passed in as context, *always*. - modules that *do* have a create_context() method, implying they have their own private context type, will have to cast the til_module_context_t supplied to the other methods to their private context type. By embedding the til_module_context_t at the *start* of their private context struct, a simple cast is all that's needed. If it's placed somewhere else, more annoying container_of() style macros are needed - this is strongly discouraged, just put it at the start of struct. - til_module_create_context() now takes n_cpus, which may be set to 0 for automatically assigning the number of threads in its place. Any non-zero value is treated as an explicit n_cpus, primarily intended for setting it to 1 for single-threaded contexts necessary when embedded within an already-threaded composite module. - modules like montage which open-coded a single-threaded render are now using the same til_module_render_fragment() as everything else, since til_module_create_context() is accepting n_cpus. - til_module_create_context() now produces a real type, not void *, that is til_module_context_t *. All the other module context functions now operate on this type, and since til_module_context_t.module tracks the module this context relates to, those functions no longer require both the module and context be passed in. This is especially helpful for compositing modules which do a lot of module context creation and destruction; the module handle is now only needed to create the contexts. Everything else operating on that context only needs the single context pointer, not module+context pairs, which was unnecessarily annoying. - if your module's context can be destroyed with a simple free(), without any deeper knowledge or freeing of nested pointers, you can now simply omit destroy_context() altogether. When destroy_context() is missing, til_module_context_free() will automatically use libc's free() on the pointer returned from your create_context() (or on the pointer that was automatically created if you omitted create_context() too, for the bare til_module_context_t that got created on your behalf anyways). For the most part, these changes don't affect module creation. In some ways this eases module creation by making it more convenient access seed and n_cpus if you had no further requirement for a context struct. In other ways it's slightly annoying to have to do type-casts when you're working with your own context type, since before it was all void* and didn't require casts when assigning to your typed context variables. The elimination for requiring a destroy_context() method in simple free() of private context scenarios removes some boilerplate in simple cases. I think it's a wash for module writers, or maybe a slight win for the simple cases.
2022-05-25*: normalize on all case-insensitive comparisonsVito Caputo
I don't think rototiller is an appropriate place for being so uncooperative, if someone gets the case wrong anywhere just make it work. We should avoid making different things so subtly different that case alone is the distinction anyways, so I don't see this creating any future namespace collision problems.
2022-05-21modules/*: first stab at utilizing supplied seedsVito Caputo
This is a mostly mechanical change of using rand_r() in place of rand(), using the provided seed as the seed state. There's some outstanding rand()s outside of create_context() which should probably get switched over, with the seed being stowed in the context struct. I didn't bother going deeper on this at the moment in the interests of getting to sleep soon.
2022-05-21til: supply a seed to til_module_t.create_context()Vito Caputo
In the recent surge of ADD-style rtv+compose focused development, a bunch of modules were changed to randomize initial states at context_create() so they wouldn't be so repetitive. But the way this was done in a way that made it impossible to suppress the randomized initial state, which sometimes may be desirable in compositions. Imagine for instance something like the checkers module, rendering one module in the odd cells, and another module into the even cells. Imagine if these modules are actually the same, but if checkers used one seed for all the odd cells and another seed for all the even cells. If the modules used actually utilized the seed provided, checkers would be able to differentiate the odd from even by seeding them differently even when the modules are the same. This commit is a step in that direction, but rototiller and all the composite modules (rtv,compose,montage) are simply passing rand() as the seeds. Also none of the modules have yet been modified to actually make use of these seeds. Subsequent commits will update modules to seed their pseudo-randomized initial state from the seed value rather than always calling things like rand() themselves.
2022-05-02modules/rtv: silence compiler warning about parensVito Caputo
2022-05-02modules/rtv: plug big channel leak on context destroyVito Caputo
There's more to cleanup in rtv destruction, but this is the major one.
2022-05-01modules/rtv: make "compose" the default channelVito Caputo
Also shortened the durations across the board, and defaulted snow to "none". With "compose" being another meta module, and the randomized settings, this actually gives a more interesting grand tour of everything possible.
2022-05-01modules/rtv: snow_module=blank is blanking, "none" for disabledVito Caputo
It's no longer necessary to specify both snow_duration=0 AND snow_module=none to disable snow, just specify snow_module=none. A future commit should really make describing the "snow_duration" setting contingent on snow_module != "none".
2022-05-01modules/*: make use of generic fragmentersVito Caputo
Just one case, modules/submit, was using 32x32 tiles and is now using 64x64. I don't expect it to make any difference. While here I fixed up the num_cpus/n_cpus naming inconsistencies, normalizing on n_cpus.
2022-04-29modules/rtv: except snow_module=none,snow_duration=0Vito Caputo
The code was deliberately showing a single frame of snow when snow_duration=0, since the durations are integral seconds ther was no way to have a sub 1-second snow otherwise. snow_module=none just means cleared for the snow_duration, not no snow mechanism whatsoever. So the combination of 0 duration and "none" was still flashing a single blank frame. With this commit the combination of "none" and 0 snow_duration prevents even a single frame of blank snow from being rendered.
2022-04-29modules/rtv: align all struct membersVito Caputo
cosmetic indentation fixup
2022-04-29modules/rtv: rtv_channel_t: s/settings/settings_as_arg/Vito Caputo
Mechanical rename to something less ambiguous in a world with til_settings_t, til_setting_t, and til_setup_t etc.
2022-04-24*: free setup allocations via til_setup_free()Vito Caputo
This should plug a bulk of the setup leaks. Some of the free_funcs still need to be changed to bespoke ones in modules that allocate nested things in their respective setup, so those are still leaking the nested things which are usually just a small strdup of some kind.
2022-04-24*: s/void */til_setup_t */Vito Caputo
This brings something resembling an actual type to the private objects returrned in *res_setup. Internally libtil/rototiller wants this to be a til_setup_t, and it's up to the private users of what's returned in *res_setup to embed this appropriately and either use container_of() or casting when simply embedded at the start to go between til_setup_t and their private containing struct. Everywhere *res_setup was previously allocated using calloc() is now using til_setup_new() with a free_func, which til_setup_new() will initialize appropriately. There's still some remaining work to do with the supplied free_func in some modules, where free() isn't quite appropriate. Setup freeing isn't actually being performed yet, but this sets the foundation for that to happen in a subsequent commit that cleans up the setup leaks. Many modules use a static default setup for when no setup has been provided. In those cases, the free_func would be NULL, which til_setup_new() refuses to do. When setup freeing actually starts happening, it'll simply skip freeing when til_setup_t.free_func is NULL.
2022-04-22til: make til_module_randomize_setup() return -errnoVito Caputo
This makes the arg return optional by using a res_arg pointer, instead returning -ENOMEM when it would have returned NULL on allocation failures. This also makes it possible to detect when no setup was performed, by returning 0 in such a case. Now returns 1 when setup occurs and res pointers populated.
2022-04-22til: add til_module_randomize_setup() from rtvVito Caputo
This commit pulls the setup randomizer out of rtv into libtil proper, so other modules may make use of it. Other than adding an assert no functional changes occurred. It may make sense to split this into two functions; one which takes a til_module_t as-is, and a lower-level bare setup function callback based function that doesn't know about til_module_t the former would call into. That way generic setup randomization can occur (the same setup machinery is used in video contexts for example) without necessarily having a til_module_t on hand.
2022-04-19*: s/til_fb_fragment_zero/til_fb_fragment_clear/Vito Caputo
Mechanical renaming of "zero" to "clear" throughout for this context.
2022-04-01modules/*: instantiate and use setupsVito Caputo
Now modules allocate and return an opaque setup pointer in res_setup when they implement a setup method. Defaults are utilized when ${module}_create_context() receives a NULL setup. The default setup used in this case should match the defaults/preferred values emitted by the module's setup method. But performing setup should always be optional, so a NULL setup provided to create_context() is to be expected. No cleanup of these setup instances is currently performed, so it's a small memory leak for now. Since these are opaque and may contain nested references to other allocations, simply using free() somewhere in the frontend is insufficient. There will probably need to be something like a til_module_t.setup_free() method added in the future which modules may assign libc's free() to when appropriate, or their own more elaborate version. Lifecycle for the settings is very simple; the setup method returns an instance, the caller is expected to free it when no longer needed (once free is implemented). The create_context consumer of a given setup must make its own copy of the settings if necessary, and may not keep a reference - it must assume the setup will be freed immediately after create_context() returns. This enables the ability to reuse a setup instance across multiple create_context() calls if desired, one can imagine something like running the same module with the same settings multiple times across multiple displays for instance. If the module has significant entropy the output will differ despite being configured identically... With this commit one may change settings for any of the modules *while* the modules are actively rendering a given context, and the settings should *not* be visible. They should only affect the context they're supplied to.
2022-03-30*: wire up context-specific setup instancesVito Caputo
This is a preparatory commit for cleaning up the existing sloppy global-ish application of settings during the iterative _setup() call sequences. Due to how this has evolved from a very rudimentary thing enjoying many assumptions about there ever only being a single module instance being configured by the settings, there's a lot of weirdness and inconsistency surrounding module setup WRT changes being applied instantaneously to /all/ existing and future context's renderings of a given module vs. requiring a new context be created to realize changes. This commit doesn't actually change any of that, but puts the plumbing in place for the setup methods to allocate and initialize a private struct encapsulating the parsed and validated setup once the settings are complete. This opaque setup pointer will then be provided to the associated create_context() method as the setup pointer. Then the created context can configure itself using the provided setup when non-NULL, or simply use defaults when NULL. A future commit will update the setup methods to allocate and populate their respective setup structs, adding the structs as needed, as well as updating their create_context() methods to utilize those setups. One consequence of these changes when fully realized will be that every setting change will require a new context be created from the changed settings for the change to be realized. For settings appropriately manipulated at runtime the concept of knobs was introduced but never finished. That will have to be finished in the future to enable more immediate/interactive changing of settings-like values appropriate for interactive manipulation
2022-03-30*: use til_module_create_context() in more placesVito Caputo
Just mechanical replacement of some remaining ad-hoc til_module_t.create_context() calls. The montage module continues using an ad-hoc call because it forces num_cpus=1 since it's already a threaded using a fragment per module's tile. This suggests the til_module_create_context() call should probably accept a num_cpus parameter, perhaps treating a 0 value as the "automagic" discover value so callers can explicitly set it when necessary.
2022-03-19*: de-constify til_setting_t throughoutVito Caputo
Now that til_setting_t.desc is not only a thing, but a thing that is intended to be refreshed regularly in the course of things like GUI interactive settings construction, it's not really appropriate to try even act like this these are const anymore.
2022-03-19*: use til_module_destroy_context()Vito Caputo
Mechanically replaced ad-hoc til_module_t.destroy_context() invocations with helper calls.
2022-03-19*: normalize setting description capitalizationsVito Caputo
Always only capitalize the first letter, never capitalize like titles.
2022-03-19*: drop til_module_t.licenseVito Caputo
Originally the thinking was that rototiller modules would become dlopen()ed shared objects, and that it would make sense to let them be licensed differently. At this time only some modules I have written were gplv3, Phil's modules are all gplv2, and I'm not inclined to pivot towards a dlopen model. So this commit drops the license field from til_module_t, relicenses my v3 code to v2, and adds a gplv2 LICENSE file to the source root dir. As of now rototiller+libtil and all its modules are simply gplv2, and anything linking in libtil must use a gplv2 compatible license - the expectation is that you just use gplv2.
2022-03-12til_settings: always describe relevant settingsVito Caputo
The existing iterative *_setup() interface only described settings not found, quietly accepting usable settings already present in the til_settings_t. This worked fine for the existing interactive text setup thing, but it's especially problematic for providing a GUI setup frontend. This commit makes it so the *_setup() methods always describe undescribed settings they recognize, leaving the setup frontend loop calling into the *_setup() methods to both apply the description validation if wanted and actually tie the description to respective setting returned by the _setup() methods as being related to the returned description. A new helper called til_settings_get_and_describe_value() has been introduced primarily for use of module setup methods to simplify this nonsense, replacing the til_settings_get_value() calls and surrounding logic, but retaining the til_setting_desc_t definitions largely verbatim. This also results in discarding of some ad-hoc til_setting_desc_check() calls, now that there's a centralized place where settings become "described" (setup_interactively in the case of rototiller). Now a GUI frontend (like glimmer) would just provide its own setup_interactively() equivalent for constructing its widgets for a given *_setup() method's chain of returned descs. Whereas in the past this wasn't really feasible unless there was never going to be pre-supplied settings. I suspect the til_setting_desc_check() integration into setup_interactively() needs more work, but I think this is good enough for now and I'm out of spare time for the moment.
2021-10-01*: librototiller->libtilVito Caputo
Largely mechanical rename of librototiller -> libtil, but introducing a til_ prefix to all librototiller (now libtil) functions and types where a rototiller prefix was absent. This is just a step towards a more libized librototiller, and til is just a nicer to type/read prefix than rototiller_.
2021-02-18modules/rtv: fix "none" snow to actually blankVito Caputo
This manifests in the current unconfigured rtv glimmer shows, since the default is a the "none" module when no settings are applied. But it turns out this isn't just a glimmer problem, "none" is advertised in the settings as a blanking alternative to snow. So it's actually broken in rototiller as well. This fixes it by detecting the nil "none" module's lack of any prepare_frame or render_fragment methods, and open coding the blanker with a fb_fragment_zero() inline.
2021-02-14*: split rototiller.[ch] into lib and mainVito Caputo
This is a first approximation of separating the core modules and threaded rendering from the cli-centric rototiller program and its sdl+drm video backends. Unfortunately this seemed to require switching over to libtool archives (.la) to permit consolidating the per-lib and per-module .a files into the librototiller.a and linking just with librototiller.a to depend on the aggregate of libs+modules+librototiller-glue in a simple fashion. If an alternative to .la comes up I will switch over to it, using libtool really slows down the build process. Those are implementation/build system details though. What's important in these changes is establishing something resembling a librototiller API boundary, enabling creating alternative frontends which vendor this tree as a submodule and link just to librototiller.{la,a} for all the modules+threaded rendering of them, while providing their own fb_ops_t for outputting into, and their own settings applicators for driving the modules setup.
2021-02-14compose,montage,rtv: drop author and license fieldsVito Caputo
These modules are meta modules, and the only place this information is presented currently is in the rtv module captions overlaying the visual output of unrelated modules. So it's rather misleading to put the meta module's author and license on-screen when what's being shown is arguably just a tiny fraction of the meta module's contribution. Rather than bother with constructing license and author lists at runtime from the modules incorporated by these meta modules, let's instead adopt a policy of meta modules omit any declaration of license or authorship outside of the source. This is a simple solution for now, it can be revisited later if necessary. Changing the .author member of rototiller_module_t to an .authors() function pointer wouldn't be difficult. But it does open up something of a can of worms when considering recursive dependencies and needing to construct unique authors and licenses lists from things like nested meta modules. Obviously there can't be infinite recursion as that would manifest in the rendering path as well, but what I'm more concerned about is properly handling potentialy quite long lists. It's already annoying when rtv has to deal with a long settings string, which I believe currently is just truncated. The same would have to be done with long authors/licenses I guess. In any case, I think it's probably fine to just leave authorship and license ambiguous when a meta module is shown in rtv. It's certainly preferable to vcaputo@pengaru.com getting credit for everything shown in the three meta modules currently implemented, or more specifically, the two shown in rtv; compose and montage. Note this required making rtv tolerante of NULL .license and .author rototiller_module_t members.
2020-09-13modules/rtv: implement snow_module settingVito Caputo
This takes a module name or "none", to use the specified module or do nothing during the channel switching snow_duration. The default is "snow" like before.
2020-09-12modules/rtv: implement context_duration settingVito Caputo
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.
2020-09-12modules/rtv: s/ticket/order/Vito Caputo
Ticket is unnecessarily abstract/opaque of a name for this, it's simply the sort order. No point making the reader grok whatever model I was thinking when I wrote it at the time, i.e. tickets at a butcher counter.
2020-09-12modules/rtv: rename rtv_skip_module()Vito Caputo
Purely cosmetic change renaming to rtv_should_skip_module() since the function doesn't actually skip anything, it just determines the skip.
2020-09-11modules/rtv: make channels set configurableVito Caputo
This adds a colon-separated channels setting, with a setting of "all" for the existing all-modules behavior. Colon was used since comma is already taken by the settings separator, maybe in the future comma escaping can be added everywhere relevant but for now just keep it simple. The immediate value of this setting is telling rtv to limit itself to a single module, and using its setting randomizer to automatically observe a variety of the available settings in action on a specific module, especially during development. If knobs ever get added in the future I expect this will become even more interesting for watching specific modules under their various settings permutations in combination with their knobs being twisted - especially if rtv reconstructs random signal generator chains for the "knob-twisters" on every channel switch. An immediately interesting TODO complementing this particular change would be optionally preserving module contexts across channel switches, so when the same module is revisited it resumes where it was last seen. But this conflicts with settings changes on channel switching, since contexts should probably always be recreated when settings change - but that's probably a module-specific detail that modules should just be robust enough to tolerate as in they'd safely ignore settings changes without a context recreate, or apply them if they safely can without a context recreate... TODO.
2020-09-11modules/rtv: make durations configurableVito Caputo
This adds three rtv settings: duration, caption_duration, snow_duration
2020-01-25rototiller: introduce ticks and wire up to modulesVito Caputo
Most modules find themselves wanting some kind of "t" value increasing with time or frames rendered. It's common for them to create and maintain this variable locally, incrementing it with every frame rendered. It may be interesting to introduce a global notion of ticks since rototiller started, and have all modules derive their "t" value from this instead of having their own private versions of it. In future modules and general innovations it seems likely that playing with time, like jumping it forwards and backwards to achieve some visual effects, will be desirable. This isn't applicable to all modules, but for many their entire visible state is derived from their "t" value, making them entirely reversible. This commit doesn't change any modules functionally, it only adds the plumbing to pull a ticks value down to the modules from the core. A ticks offset has also been introduced in preparation for supporting dynamic shifting of the ticks value, though no API is added for doing so yet. It also seems likely an API will be needed for disabling the time-based ticks advancement, with functions for explicitly setting its value. If modules are created for incorporating external sequencers and music coordination, they will almost certainly need to manage the ticks value explicitly. When a sequencer jumps forwards/backwards in the creative process, the module glue responsible will need to keep ticks synchronized with the sequencer/editor tool. Before any of this can happen, we need ticks as a first-class core thing shared by all modules. Future commits will have to modify existing modules to use the ticks appropriately, replacing their bespoke variants.
2020-01-06rtv: rework randomized module selectionVito Caputo
Switch to working through the set of modules in a random order, randomizing the order once per cycle. This way no modules get starved for display, which was pretty common in the old method.
© All Rights Reserved