context: add library.use-fallback option

Normally, when loading a plugin feature, often a library.name property
is given as well. If the feature to load is not explicitly listed in
context.spa-libs, the library.name is used a fallback library.

Add an option to ignore this library.name and only use the
context.spa-libs entries. This makes it possible to only load explicitly
listed features in the config file and makes it possible to lock down
what plugins can be loaded.

Set the option to true by default for now, which keeps the existing
behaviour of using the fallback library. Add some more entries to the
context.spa-libs in case the option is switched off to make things
work.

Set the option to false for the minimal.conf.
This commit is contained in:
Wim Taymans 2026-05-08 09:57:52 +02:00
parent ddab12a5aa
commit b3257ae425
7 changed files with 72 additions and 17 deletions

View file

@ -288,6 +288,12 @@ Default video rate denominator
@PAR@ pipewire.conf library.name.system = support/libspa-support
The name of the shared library to use for the system functions for the main thread.
@PAR@ pipewire.conf library.use-fallback = true
When a plugin feature is not listed in context.spa-libs, a predefined fallback
plugin location is used by default. If this option is set to false, only plugin
features explicitly listed in context.spa-libs will be loadable. This can be used
to lock down what plugins that can be loaded.
@PAR@ pipewire.conf link.max-buffers = 64
The maximum number of buffers to negotiate between nodes. Note that version < 3 clients
can only support 16 buffers. More buffers is almost always worse than less, latency

View file

@ -13,6 +13,7 @@ context.properties = {
#library.name.system = support/libspa-support
#context.data-loop.library.name.system = support/libspa-support
#support.dbus = true
library.use-fallback = false
#link.max-buffers = 64
link.max-buffers = 16 # version < 3 clients can't handle more
#mem.warn-mlock = false
@ -70,10 +71,28 @@ context.spa-libs = {
# regular expression to a library name that should contain
# that factory.
#
support.* = support/libspa-support
audio.convert.* = audioconvert/libspa-audioconvert
audio.adapt = audioconvert/libspa-audioconvert
api.alsa.* = alsa/libspa-alsa
support.* = support/libspa-support
#api.v4l2.* = v4l2/libspa-v4l2
#api.libcamera.* = libcamera/libspa-libcamera
#api.bluez5.* = bluez5/libspa-bluez5
#api.vulkan.* = vulkan/libspa-vulkan
#video.convert.* = videoconvert/libspa-videoconvert
#video.adapt = videoconvert/libspa-videoconvert
audio.mixer.* = audiomixer/libspa-audiomixer
control.mixer = control/libspa-mixer
#audio.aec = aec/libspa-aec-webrtc
#filter.graph.plugin.ffmpeg = filter-graph/libspa-filter-graph-plugin-ffmpeg
#filter.graph.plugin.onnx = filter-graph/libspa-filter-graph-plugin-onnx
#filter.graph.plugin.pipe = blocked
#filter.graph.plugin.ebur128 = filter-graph/libspa-filter-graph-plugin-ebur128
#filter.graph.plugin.sofa = filter-graph/libspa-filter-graph-plugin-sofa
#filter.graph.plugin.ladspa = filter-graph/libspa-filter-graph-plugin-ladspa
#filter.graph.plugin.lv2 = filter-graph/libspa-filter-graph-plugin-lv2
#filter.graph.plugin.builtin = filter-graph/libspa-filter-graph-plugin-builtin
#filter.graph = filter-graph/libspa-filter-graph
}
context.modules = [

View file

@ -15,17 +15,29 @@ context.properties = {
#mem.mlock-all = false
#log.level = 2
#rlimit.nofile = -1
#library.use-fallback = true
#default.clock.quantum-limit = 8192
}
context.spa-libs = {
audio.convert.* = audioconvert/libspa-audioconvert
support.* = support/libspa-support
audio.convert.* = audioconvert/libspa-audioconvert
audio.adapt = audioconvert/libspa-audioconvert
audio.mixer = audiomixer/libspa-audiomixer
audio.aec = aec/libspa-aec-webrtc
# because the pulse server allows dynamic loading of streams and modules
# inside the server, we must be careful with the filter-graph. Only allow
# LADSPA filters.
filter.graph.plugin.pipe = blocked
# inside the server, we must be careful with the filter-graph.
#filter.graph.plugin.ffmpeg = filter-graph/libspa-filter-graph-plugin-ffmpeg
#filter.graph.plugin.onnx = filter-graph/libspa-filter-graph-plugin-onnx
#filter.graph.plugin.pipe = filter-graph/libspa-filter-graph-plugin-pipe
filter.graph.plugin.pipe = blocked
#filter.graph.plugin.ebur128 = filter-graph/libspa-filter-graph-plugin-ebur128
#filter.graph.plugin.sofa = filter-graph/libspa-filter-graph-plugin-sofa
filter.graph.plugin.ladspa = filter-graph/libspa-filter-graph-plugin-ladspa
#filter.graph.plugin.lv2 = filter-graph/libspa-filter-graph-plugin-lv2
filter.graph.plugin.builtin = filter-graph/libspa-filter-graph-plugin-builtin
filter.graph = filter-graph/libspa-filter-graph
}
context.modules = [

View file

@ -12,6 +12,7 @@ context.properties = {
## Configure properties in the system.
#library.name.system = support/libspa-support
#context.data-loop.library.name.system = support/libspa-support
#library.use-fallback = true
#support.dbus = true
#link.max-buffers = 64
link.max-buffers = 16 # version < 3 clients can't handle more
@ -75,17 +76,29 @@ context.spa-libs = {
# regular expression to a library name that should contain
# that factory.
#
support.* = support/libspa-support
audio.convert.* = audioconvert/libspa-audioconvert
avb.* = avb/libspa-avb
audio.adapt = audioconvert/libspa-audioconvert
api.alsa.* = alsa/libspa-alsa
api.v4l2.* = v4l2/libspa-v4l2
api.libcamera.* = libcamera/libspa-libcamera
api.bluez5.* = bluez5/libspa-bluez5
api.vulkan.* = vulkan/libspa-vulkan
api.jack.* = jack/libspa-jack
support.* = support/libspa-support
#api.vulkan.* = vulkan/libspa-vulkan
video.convert.* = videoconvert/libspa-videoconvert
#filter.graph = filter-graph/libspa-filter-graph
video.adapt = videoconvert/libspa-videoconvert
audio.mixer.* = audiomixer/libspa-audiomixer
control.mixer = control/libspa-mixer
audio.aec = aec/libspa-aec-webrtc
#filter.graph.plugin.ffmpeg = filter-graph/libspa-filter-graph-plugin-ffmpeg
filter.graph.plugin.onnx = filter-graph/libspa-filter-graph-plugin-onnx
#filter.graph.plugin.pipe = filter-graph/libspa-filter-graph-plugin-pipe
filter.graph.plugin.pipe = blocked
filter.graph.plugin.ebur128 = filter-graph/libspa-filter-graph-plugin-ebur128
filter.graph.plugin.sofa = filter-graph/libspa-filter-graph-plugin-sofa
filter.graph.plugin.ladspa = filter-graph/libspa-filter-graph-plugin-ladspa
filter.graph.plugin.lv2 = filter-graph/libspa-filter-graph-plugin-lv2
filter.graph.plugin.builtin = filter-graph/libspa-filter-graph-plugin-builtin
filter.graph = filter-graph/libspa-filter-graph
#videotestsrc = videotestsrc/libspa-videotestsrc
#audiotestsrc = audiotestsrc/libspa-audiotestsrc
}

View file

@ -152,7 +152,6 @@ static struct spa_handle *impl_plugin_loader_load(void *object, const char *fact
errno = EINVAL;
return NULL;
}
return pw_context_load_spa_handle(&impl->this, factory_name, info);
}
@ -1057,20 +1056,23 @@ struct spa_handle *pw_context_load_spa_handle(struct pw_context *context,
const char *factory_name,
const struct spa_dict *info)
{
const char *lib;
const char *lib, *fallback_lib = NULL;
const struct spa_support *support;
uint32_t n_support;
struct spa_handle *handle;
pw_log_debug("%p: load factory %s", context, factory_name);
if (info != NULL)
fallback_lib = spa_dict_lookup(info, SPA_KEY_LIBRARY_NAME);
pw_log_info("%p: load factory %s fallback:%s", context, factory_name, fallback_lib);
lib = pw_context_find_spa_lib(context, factory_name);
if (lib == NULL && info != NULL)
lib = spa_dict_lookup(info, SPA_KEY_LIBRARY_NAME);
if (lib == NULL && context->settings.use_fallback)
lib = fallback_lib;
if (lib == NULL || spa_streq(lib, "blocked")) {
errno = lib ? EPERM : ENOENT;
pw_log_warn("%p: no library for %s: %m",
context, factory_name);
pw_log_warn("%p: no library for %s (fallback: %s): %m",
context, factory_name, fallback_lib);
return NULL;
}

View file

@ -52,6 +52,7 @@ struct settings {
unsigned int clock_power_of_two_quantum:1;
unsigned int check_quantum:1;
unsigned int check_rate:1;
unsigned int use_fallback:1;
#define CLOCK_RATE_UPDATE_MODE_HARD 0
#define CLOCK_RATE_UPDATE_MODE_SOFT 1
int clock_rate_update_mode;

View file

@ -37,6 +37,7 @@
#define DEFAULT_MEM_ALLOW_MLOCK true
#define DEFAULT_CHECK_QUANTUM false
#define DEFAULT_CHECK_RATE false
#define DEFAULT_USE_FALLBACK true
struct impl {
struct pw_context *context;
@ -227,6 +228,7 @@ void pw_settings_init(struct pw_context *this)
d->check_quantum = get_default_bool(p, "settings.check-quantum", DEFAULT_CHECK_QUANTUM);
d->check_rate = get_default_bool(p, "settings.check-rate", DEFAULT_CHECK_RATE);
d->use_fallback = get_default_bool(p, "library.use-fallback", DEFAULT_USE_FALLBACK);
d->link_max_buffers = SPA_MAX(d->link_max_buffers, 1u);