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 allows registering arbitrary objects on the core's registry and
finding them later, without having to add API for each and every object.
I think this is useful enough to have it public, even though it's
probably not going to be used that much... The rationale here is to
allow registering custom component loaders without having to make them
subclass WpPlugin or to create custom API for registering component
loaders specifically.
Also, remove the wp_plugin_register() and wp_si_factory_register()
functions, since they are not going to be used much in the future.
The idea is to let the component loader do the registration under the
scenes, as the component is getting loaded.
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()
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
This change completely refactors the way components are loaded in wireplumber:
- The module_init() function must return a GObject now. This object is either
a WpPlugin or a WpSiFactory in the current modules.
- When the component loader initializes a module, it automatically registers
the WpPlugin or WpSiFactory with their respective methods. There is no need
to register the WpPlugin or WpSiFactory in the module now.
- The wp_core_load_component() API has been refactored to be asynchronows. This
allows the component loader to automatically activate WpPlugin objects, and
therefore allows the application to directly get the WpPlugin without having
to find it. This simplifies a lot of things.
- The 'ifexists' and 'nofail' component flags now work even if the respective
WpPlugin could not be activated.
- The code that loads components in main.c has also been simplified a lot,
and the option to load dangling components has also been removed.
The component loader is a more generic and extensible mechanism
of loading components; modules are one type of component...
The idea is to make scripts and config files also be components,
loaded by plugins that inherit WpComponentLoader
- pw_core_info has data that represent the remote core
- pw_core properties are the properties of its pw_client,
initially inherited from the pw_context, which can be updated either
when calling pw_context_connect() or later at runtime (the pw_core
calls pw_client_update_properties() on its pw_client)
wp_core_update_properties() is made in such a way so that we can do:
```
clone = wp_core_clone(core);
wp_core_update_properties(clone, ...);
wp_core_connect(clone);
```
and get clone to have different properties than the original core,
while they still share the same pw_context underneath
* core no longer exposes create_remote/local_object
* node, device & link have constructor methods
to enable the create_remote_object functionality
* added WpImplNode to wrap pw_impl_node and allow creating
"local" node instances
* added WpSpaDevice to wrap spa_device and allow creating
"local" device instances
* exporting objects in all cases now happens by requesting
FEATURE_BOUND from the proxy, eliminating the need for WpExported
* replaced WpMonitor by new, simpler code directly in module-monitor
* the proxy type lookup table in WpProxy is gone, we now
use a field on the class structure of every WpProxy subclass
and iterate through all the class structures instead; this is
more flexible and extensible
* rework how global objects are stored in the core
* rework how users get notified about global objects
and proxies of remote global objects
The purpose of this change is to have a class that can manage
objects that are registered in the core or signalled through the
registry. This object can declare interest on certain types
of global objects and only keep & signal those objects that it is
interested in. Additionally, it can prepare proxy features and
asynchronously deliver an 'objects-changed' signal, which is
basically telling us that the list of objects has changed.
This is useful to simplify port proxies management in WpAudioStream.
Now the stream object can declare that it is interested in ports
that have "node.id" == X and the object manager will only maintain
a list of those. Additionally, it will emit the 'objects-changed'
signal when the list of ports is complete, so there is no reason to
do complex operations and core syncs in the WpAudioStream class
in order to figure out when the list of ports is ready.
As a side effect, this also reduces resource management. Now we
don't construct a WpProxy for every global that pipewire reports;
we only construct proxies when there is interest in them!
Another interesting side effect is that we can now register an
object manager at any point in time and get immediately notified
about remote globals that already exist. i.e. when you register
an object manager that is interested in nodes, it will be immediately
notified about all the existing nodes in the graph. This is useful
to avoid race conditions between connecting the signal and objects
beting created in pipewire
In practice we always create a remote and connect to pipewire.
Any other scenario is invalid, therefore, it is not justified
to be confused with so many classes for such small functionality.
This simplifies a lot the modules code.
Also, this commit exposes the pw_core and pw_remote objects
out of WpCore. This is in practice useful when dealing with low-level
pw and spa factories, which are used in the monitors. Let's not
add API wrappers for everything... Bindings will never use this
functionality anyway, since it depends on low level pipewire C API.
This is a cleaner way to interface with the remote pipewire daemon.
The WpRemote base class can be subclassed also for interfacing
with other daemons (hardware-specific managers, etc)
and also implement
* global-added/removed signals
* a foreach function to iterate through globals
* registering modules and factories with the same key
After discussing things at the AGL May 2019 F2F meeting
and reflecting on the initial design of WirePlumber,
it became clear that it needed a fresh start.