diff --git a/doc/dox/config/pipewire.conf.5.md b/doc/dox/config/pipewire.conf.5.md index 12d2ea855..a1b3564aa 100644 --- a/doc/dox/config/pipewire.conf.5.md +++ b/doc/dox/config/pipewire.conf.5.md @@ -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 diff --git a/src/daemon/minimal.conf.in b/src/daemon/minimal.conf.in index 7ab93e92b..89cbb017f 100644 --- a/src/daemon/minimal.conf.in +++ b/src/daemon/minimal.conf.in @@ -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 = [ diff --git a/src/daemon/pipewire-pulse.conf.in b/src/daemon/pipewire-pulse.conf.in index 5fedd36bf..0b9a31b4d 100644 --- a/src/daemon/pipewire-pulse.conf.in +++ b/src/daemon/pipewire-pulse.conf.in @@ -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 = [ diff --git a/src/daemon/pipewire.conf.in b/src/daemon/pipewire.conf.in index a9142cede..720872aaa 100644 --- a/src/daemon/pipewire.conf.in +++ b/src/daemon/pipewire.conf.in @@ -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 } diff --git a/src/pipewire/context.c b/src/pipewire/context.c index eb89ca752..c4ecaa004 100644 --- a/src/pipewire/context.c +++ b/src/pipewire/context.c @@ -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; } diff --git a/src/pipewire/private.h b/src/pipewire/private.h index dd81178ff..fa562b320 100644 --- a/src/pipewire/private.h +++ b/src/pipewire/private.h @@ -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; diff --git a/src/pipewire/settings.c b/src/pipewire/settings.c index 74d4cfcb2..944fee30c 100644 --- a/src/pipewire/settings.c +++ b/src/pipewire/settings.c @@ -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);