We should not ignore the returned iterator as it allows users to get the exact
returned params after enumerating them, which might be useful in some cases.
These builders had many bugs:
1. They would longjmp() across the destructor of a g_autoptr() if a Lua
error was thrown. This will leak the memory in the g_autoptr()
unless Lua is compiled with C++ exceptions.
2. They depended on the iteration order of numerical keys in Lua tables.
Lua explicitly does not specify this order.
3. They would produce nonsensical SPA POD array or choice types with
strings or bytes as values. These would cause undefined behavior if
manipulated by naive C code, or assertion failures if
spa_pod_is_array() and spa_pod_is_choice() are modified to check that
the contents of arrays and choices have sensible types.
4. They silently accepted extra arguments, potentially causing confusion
and making it harder to extend the functions in a
backwards-compatible way.
Solve the first problem by calling functions that can raise a Lua error
in a protected environment (with lua_pcall). If there is a Lua error,
rethrow it after the g_autoptr() destructor has run.
Solve the second problem by first obtaining the number of keys in the
table and then iterating over the keys that are expected to be present.
If any of the keys are not contiguious integers starting at 1, the range
[1..number of keys] will include a number that is not a table key. This
will result in lua_rawgeti pushing a nil onto the Lua stack. An
explicit check throws a useful error in this case.
Solve the third problem by explicitly checking that the type is
reasonable before building an array or choice. If it is wrong,
a Lua error is thrown.
Solve the fourth problem by using luaL_checktype (L, 2, LUA_TNONE) to
check that no unwanted values were passed. The C function called with
lua_pcall is passed every argument passed by Lua, followed by a light
userdata that stores a context pointer. After the light userdata is
popped from the Lua stack, the Lua stack is identical to what Lua
created when it called the outer C function, so the type-checking
functions in the auxillary library can be used to enforce that only the
correct number and type of arguments were passed.
Make decision on whether to show code location in journal messages based
on whether the WpLogTopic would enable DEBUG level messages.
Add wp_logt_checked API to take WpLogTopic as input to make this
possible, and deprecate wp_log_checked.
Given that we are allowing Conf() to instantiate a new WpConf,
the methods on the class need to be callable in reference to Self while
maintaining API compatibility with being indexable from the table as a
static method.
Allow this by checking if the first argument passed in is userdata.
Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
This exposes the ability to load a SPA-JSON representation of a WpConf
object from an arbitrary file on disk to the Lua API
Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
These errors are propagated to the caller, so it's the caller's
responsibility to print them appropriately, if necessary. Printing
a notice also here is only confusing.
A debug mesage is still be useful for developers to understand the flow.
Cache the rules in a global variable in each script, as JSON,
and use JsonUtils directly to evaluate them. This will allow us to
close the WpConf in the future after loading the scripts.
Also change the order of the return values of the match_rules_apply_properties
function to be able to easily ignore the number of changed values,
which is useless in most cases.
In some cases we need to get a section as JSON, so that we can pass it
down to the rules parser, while in other cases we neeed to get it as a
table to use it natively, and in that case we even need to differentiate
between it being an object, an array or an object with WpProperties.
Make it also possible to optionally pass tables with default values to
the functions so that we can get rid of cutils.get_config_section()
as well.
We do not use these APIs, so there's no point in keeping them.
Realistically, every component that needs a section just does its
own parsing on it, so the _get_value() functions are not needed.
The fallback in _get_section() is also not needed, as we always
pass NULL and then test for it. In Lua, however, it seems we are
using the fallback to return an empty object, so that getting
a section does not expand to multiple lines of code. For that reason,
I have kept the syntax there and implemented it in the bindings layer.
Changes:
- Configuration files are no longer located by libpipewire,
which allows us to control the paths that are being looked up.
This is a requirement for installations where pipewire and
wireplumber are built using different prefixes, in which case
the configuration files of wireplumber end up being installed in
a place that libpipewire doesn't look into...
- The location of conf files is now again $prefix/share/wireplumber,
/etc/wireplumber and $XDG_CONFIG_HOME/wireplumber, instead of using
the pipewire directories. Also, since the previous commits, we now
also support $XDG_CONFIG_DIRS/wireplumber (typically /etc/xdg/wireplumber)
and $XDG_DATA_DIRS/wireplumber for system-wide configuration.
- Since libpipewire doesn't expose the parser, we now also do the
parsing of sections ourselves. This has the advantage that we can
optimize it a bit for our use case.
- The WpConf API has changed to not be a singleton and it is a
property of WpCore instead. The configuration is now expected
to be opened before the core is created, which allows the caller
to identify configuration errors in advance. By not being a singleton,
we can also reuse the WpConf API to open other SPA-JSON files.
- WpConf also now has a lazy loading mechanism. The configuration
files are mmap'ed and the various sections are located in advance,
but not parsed until they are actually requested. Also, the sections
are not copied in memory, unlike what happens in libpipewire. They
are only copied when merging is needed.
- WpCore now disables loading of a configuration file in pw_context,
if a WpConf is provided. This is to have complete control here.
The 'context.spa-libs' and 'context.modules' sections are still
loaded, but we load them in WpConf and pass them down to pw_context
for parsing. If a WpConf is not provided, pw_context is left to load
the default configuration file (client.conf normally).
This doesn't need to be a singleton, since we have the core registration
API available publicly nowadays. Makes things more clean for the API,
following the pattern of WpPlugin and WpSiFactory and simplifies the
built-in settings component in the internal component loader :)
This allows partially parsing a json object, allowing some parts to be
passed on as strings to another component that does its own parsing
(ex. a pipewire module)
This reverts commit 2ae1b3cbd9.
This is not a good API. It was only allowed temporarily in 0.4.15
to get things done. We should approach this properly in 0.5
In conf_apply_rules, check input argument is a table before assuming it
is and potentially crashing.
Add check also in wplua_table_to_properties to avoid similar bugs.
Each component can optionally "provide" a feature, which is basically
a string that describes the feature (ex. "support.dbus"). If the
component loads successfully, the feature is marked as provided and
can be tested for its presence with wp_core_test_feature()
There is no reason to return the component object... all components
are supposed to be long-lived objects that are referenced by the
registry and there is API to find them. The caller is only interested
in the success or failure of the operation.
Regarding the core parameter, the case used to be that WpComponentLoader
was a WpPlugin, so it had a reference to the core internally, but since
this is no longer a requirement, we need to pass this explicitly