Age | Commit message (Collapse) | Author |
|
This adds a setting value syntax for bypassing checks; ':' prefix
e.g.
--module=:experimental_module
Would result in the value experimental_module added, and no
verification performed of its presence in the module setting's
values list.
Two new til_settings api functions are introduced as well for
setting and getting the raw values including any prefix syntax:
til_setting_get_raw_value()
til_setting_set_raw_value()
these are needed because the til_setting_t.value member will
continue to point at the "cooked" form of the value with the
prefix stripped out, so the general cases of needing the value
won't have to worry about the presence of prefixes. They have
the til_setting_t.nocheck member to see if the setting was a
nocheck-prefixed value.
The nocheck prefix is preserved across serialization as well. So
using a serialized form to seed a derivative settings instance
won't spuriously start failing checks because the ':' prefixes
are gone where they were necessary. They'll be kept wherever
they were previously.
There will probably be some more random fixes needed here and
there where code is directly manipulating til_setting_t.value and
must now go through the "raw" getter/setter api.
|
|
Preparatory commit for rkt_scener scenes editing, which will be
replacing the current scene's settings instance with a newly
constructed one. This enables simply duplicating the existing
scene setting's positional label, which will be identical in the
replacement.
|
|
Most of the time if there are undescribed settings in the
settings hierarchy, they're just noise in the serialized as_arg
form.
So change til_settings_as_arg() to always skip undsecribed
entries, and introduce til_settings_as_arg_unfiltered() for any
use cases that actually want everything included. The unfiltered
variant may just go the way of the dodo if nothing ever makes use
of it.
|
|
There was only til_setting_desc_fprint_path() (for
setup_interactively()), but for rkt_scener this stuff has to go
out the socket and the queueing mechanism is built around
til_str_t so let's get a til_str_t-centric variant in there.
|
|
In rkt_scener it's desirable to fully construct a new settings
instance *before* wiring it into the parent rkt/scenes settings.
But the way these positional settings labels get constructed
depends on the parent's settings entries. So it becomes a
chicken-egg problem to require the proper label @ creation before
its containing setting is even added in the parent's entries.
With this change a temporary WIP label can be used while
constructing the settings instance, then amend it once we know
the settings instance is complete and ready to join the party.
|
|
Introduce til_settings_get_parent(), impetus being so
til_module_setup() can infer if it's hermetic-appropriate or not.
|
|
It's more ergonomic more often to behave consistently with
strlen() here, plus it's just the established mental model.
While here I made til_settings_path_as_buf() private as nothing
external uses it, it's essentially just a logically distinct
private helper function from the public wrappers around it.
Dragged into this changeset due to clarifying some
naming/semantics as it's one of the few til_str_to_buf() callers.
But nobody was actually passing a non-NULL res_bufsz/res_len to
it anyways, as its use is minimal.
|
|
This eliminates more open_memstream() usage in favor of the new
til_str stuff.
While here I've split up the path construction API exposing the
til_str oriented variants, rather than only providing a
FILE*-oriented API. This way you just use the FILE* stuff when
convenient (like printing to stdout/stderr) and go til_str_t when
you're building up a buffer.
Such is life in a sans-open_memstream-world.
Also while here the FILE*-oriented settings path printers were
renamed s/print/fprint/g hence touching setup.c
|
|
Preparatory commit for bridging the gap separating a baked
til_setup_t from a runtime-populated descendant til_settings_t
like modules::rtv produces for its channels via
til_module_setup_randomize().
For these currently orphaned til_settings_t instances we don't
readily have access to the logical ancestor til_settings_t that
was used to produce the module_context's bound til_setup_t. But
we don't really need the ancestor til_settings_t, all we _really_
want is the ancestral path to prefix the orphan til_settings_t
instances.
So this commit introduces supplying a prefix which gets prepended
to paths printed via the settings instance. A later commit will
make use of this in modules::rtv when producing the settings
instance passed to til_module_setup_randomize()
|
|
In a world where "describing" settings is an iterative process,
especially post-nested-settings which are realized via the
desc-applying process, it's better to not even offer desc-setting
while adding a new setting.
This commit just gets rid of that.
The one caller that was passing a non-NULL desc to
til_settings_add_value(), til_module_setup_randomize(), was
redundantly doing so since the subsequent desc-processing was
assigning it again anyways. Future commits will likely change
til_module_setup_randomize() use a non-NULL desc for skipping
desc-applying, which wouldn't even work if it was always setting
the desc @ add time. That becomes necessary for partially
randomizing sparsely-populated settings.
|
|
In situations where modules wish to alias setting values like
expanding "all" -> "mod0,mod1,mod2,mod3" they need a way to
intercept the value-acceptance @ desc-assignment time in the
front-end. This optional override() function does just that when
present in the spec.
The current setting's value is passed to the override, and
if what's returned differs from what was passed (by pointer
value), then the current value is freed and the override takes
its place. The override function is expected to _always_ return
non-NULL; either the value provided, or a newly allocated value
override. The override function must never free the supplied
value, that's the front-end's job in applying the override.
The override() must return NULL on errors, which are assumed to
be limited to ENOMEM failures.
|
|
These print to a stdio FILE*, which for now is harmless since
setup_interactively() will be the only consumer (... for now).
If one needed the path in a buffer, they could use
open_memstream() and pass that FILE* to the printers. And since
commit 40feb61 there's already a dependency on the function, but
it's icky to dig deeper into that portability trap.
Although it seemed like rototiller actually compiled on MacOS at
Gene's house, so maybe open_memstream() isn't as problematic as
it once was.
Anywhow, this commit only adds the path printing helpers, nothing
is using them yet.
|
|
Currently settings instances get labels from three sources:
1. explicitly labeled by a root-level til_settings_new() call,
like main.c::til_settings_new(NULL, "video", args->video);
2. implicitly labeled in a spec.as_nested_settings w/spec.key
3. positionally labeled in a spec.as_nested_settings w/o spec.key
But when constructing setting/desc paths, using strictly these
settings instance labels as the "directory name path component"
equivalent, leaves something to be desired.
Take this hypothetical module setting path for example:
/module/layers/[0]/viscosity
Strictly using settings instance labels as-is, the above is what
you'd get for the drizzle::viscosity setting in something like:
--module=compose,layers=drizzle
Which is really awkward. What's really desired is more like:
/module/compose/layers/[0]/drizzle/viscosity
Now one way to achieve that is to just create more settings
instances to hold these module names as labels and things would
Just Work more or less.
But that would be rather annoying and heavyweight, when what's
_really_ wanted is a way to turn the first entry's value of a
given setting instance into a sort of synthetic directory
component in the path.
So that's what this commit does. When a spec has .as_label
specified, it's saying that path construction should treat this
setting's value as if it were a label on a settings instance.
But it's special cased to only apply to descs hanging off the
first entry of a settings instance, as that's the only scenario
we're making use of, and it avoids having to do crazy things like
search all the entries for specs w/.as_label set.
It feels a bit janky but it does achieve what's needed with
little pain/churn.
|
|
Preparatory for constructing unique paths from a given
setting/settings instance by walking up the tree
|
|
settings->settings[] is obnoxious
largely mechanical rename to settings->entries[]
|
|
When there's a bare-value setting turned into a nested settings
instance, there's no key onhand for labeling the instance.
But such nameless settings are basically array elements only
positionally accessed. This helper produces labels in that style
for such settings by taking the container settings label and
adding [$idx] to the end.
These labels aren't really used as more than a debugging aid at
the moment. But module contexts already have paths in main, and
it seems like these settings instance labels will likely become
the name components in constructing those paths.
|
|
Getter for accessing til_settings_t.num
With recursive settings modules will start using settings
instances to represent things like lists of module names.
(modules/compose::layers for instance)
For those cases they'll want to know the number of settings in
the instance before iterating across getting their values
positionally.
|
|
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.
|
|
The core thing here is rather than turning a bare value into a
key as I was doing before - we just leave the bare value as a
bare value and its setting must be located positionally via
get_value_by_idx since there's no key.
Existing callers that used to get_key() positionally now
get_value_by_idx() positionally all the same, except it's the
value instead of the key. This is mostly done for things like
the module or fb name at the front of a settings instance.
The impetus for this change is partially just
cosmetic/ergonomics, but it's also rather strange for what's
really a key-less value to be treated as a value-less key. It
was also awkward to talk/reason about on the road to recursive
settings where bare values would be supported as a standalone
settings instance if properly escaped...
This also adds unescaping of keys, and adds a dependency on the
somewhat linux-specific open_memstream() which may need changing
in the future (see comments).
|
|
When this is set, the setting is itself to be a settings instance
that the frontend must create and place in the relevant
til_setting_t.value_as_nested_settings.
This commit implements that frontend portion in
setup_interactively() for the rototiller frontend.
No setup_func() yet attempts to make use of this stuff. There's
probably more change needed before that can happen, specifically
the setup_func() likely must always produce a til_settings_t* to
indicate which settings instance is currently relevant to the
frontend. Without setup_func() telling the frontend, the
frontend has basically no other way of knowing when the backend
setup_func() has moved up/down the heirarchy at the current
iteration.
|
|
Preparatory commit for settings hierarchies.
|
|
This adds a mandatory label string to til_setttings_new() and
updates call sites accordingly.
For now the root-level settings created by main.c are simply
named "module" and "video" respectively. Any nested settings
creations on behalf of modules will be labeled using the module's
name the settings are being created for use with.
This might evolve with time, for now it's just a minimum churn
kind of decision. I can see it changing such that the top-level
settings also become labeled by the module/video driver name
rather than the obtuse "module" "video" strings.
How these will be leveraged is unclear presently. At the least
it'll be nice to have a label for debugging til_settings_t
heirarchies once recursive settings support lands. In a sense
this is a preparatory commit for that work. But I could see the
labels ending up in serialization contents as markup/syntactic
sugar just to self-document things as well.
There might also be a need to address til_settings_t instances in
the settings heirarchy, which may be something like a
"label/label/label/label" path style thing - though there'd be a
need to deal with name collisions in that approach.
I'm just thinking a bit about how knobs will become addressed
when those become a real thing. The settings label heirarchy
might be the convenient place to name everything in a tree, which
knobs could then inherit their parent paths from under which
their respective knob labels will reside. For the whole name
collision issue there could just be some builtin settings keys
for overriding the automatic module name labeling, something
like:
--module=compose,layers=checkers\,label=first\,fill_module=shapes:checkers\,label=second\,fill_module=shapes
would result in:
/module/first/shapes
/module/second/shapes
or in a world where the root settings weren't just named "module"
and "video":
/compose/first/shapes
/compose/second/shapes
then if there were knobs under checkers and shapes, say checkers
had a "foo" knob and checkers had a "bar" knob, they'd be under
.knobs in each directory:
/compose/first/.knobs/foo
/compose/first/shapes/.knobs/bar
/compose/second/.knobs/foo
/compose/second/shapes/.knobs/bar
something along those lines, and of course if compose had knobs
they'd be under /compose/.knobs
This is just a brain dump and will surely all change before
implemented.
|
|
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.
|
|
Until now the fb init has been receiving a til_settings_t to
access its setup. Now that there's a til_setup_t for
representing the fully baked setup, let's bring the fb stuff
up to speed so their init() behaves more like
til_module_t.create_context() WRT settings/setup.
This involves some reworking of how settings are handled in
{drm,sdl}_fb.c but nothing majorly different.
The only real funcitonal change that happened in the course of
this work is I made it possible now to actually instruct SDL to
do a more legacy SDL_WINDOW_FULLSCREEN vs.
SDL_WINDOW_FULLSCREEN_DESKTOP where SDL will attempt to switch
the video mode.
This is triggered by specifying both a size=WxH and fullscreen=on
for video=sdl. Be careful though, I've observed some broken
display states when specifying goofy sizes, which look like Xorg
bugs.
|
|
Particularly in implementing a stateful/"retained" GUI it can be
desirable to embed something like a widget pointer in a
til_setting_t once described and shown to the user.
Management of this pointer is largely nonexistant from the
libtil perspective. It's simply initialized to NULL when a new
setting is added, and never accessed again. 100% the caller's
responsibility.
This works fine since libtil/til_settings_t only accumulates
til_setting_t entries and never removes them except when
discarding an entire til_settings_t wholesale.
|
|
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.
|
|
This is helpful for forcing underlying setup methods to
redescribe their settings, regardless of what a til_settings_t's
internal state is.
|
|
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.
|
|
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_.
|