mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-29 05:40:27 -04:00
filter-chain: move sofa and lv2 to external modules
dlopen lv2 and sofa plugin modules instead of hardcoding them into the+ filter-chain. This also makes it possible to add more plugin module types externally.
This commit is contained in:
parent
5d177acc53
commit
98f138dbe0
8 changed files with 145 additions and 65 deletions
|
|
@ -295,7 +295,6 @@ summary({'sndfile': sndfile_dep.found()}, bool_yn: true, section: 'pw-cat/pw-pla
|
|||
cdata.set('HAVE_SNDFILE', sndfile_dep.found())
|
||||
libmysofa_dep = dependency('libmysofa', required : get_option('libmysofa'))
|
||||
summary({'libmysofa': libmysofa_dep.found()}, bool_yn: true, section: 'filter-chain')
|
||||
cdata.set('HAVE_LIBMYSOFA', libmysofa_dep.found())
|
||||
pulseaudio_dep = dependency('libpulse', required : get_option('libpulse'))
|
||||
summary({'libpulse': pulseaudio_dep.found()}, bool_yn: true, section: 'Streaming between daemons')
|
||||
avahi_dep = dependency('avahi-client', required : get_option('avahi'))
|
||||
|
|
@ -403,7 +402,6 @@ summary({'OpenSSL (for raop-sink)': openssl_lib.found()}, bool_yn: true)
|
|||
|
||||
lilv_lib = dependency('lilv-0', required: get_option('lv2'))
|
||||
summary({'lilv (for lv2 plugins)': lilv_lib.found()}, bool_yn: true)
|
||||
cdata.set('HAVE_LILV', lilv_lib.found())
|
||||
|
||||
libffado_dep = dependency('libffado', required: get_option('libffado'))
|
||||
summary({'ffado': libffado_dep.found()}, bool_yn: true)
|
||||
|
|
|
|||
|
|
@ -117,20 +117,12 @@ filter_chain_sources = [
|
|||
'module-filter-chain/biquad.c',
|
||||
'module-filter-chain/ladspa_plugin.c',
|
||||
'module-filter-chain/builtin_plugin.c',
|
||||
'module-filter-chain/sofa_plugin.c',
|
||||
'module-filter-chain/convolver.c'
|
||||
]
|
||||
filter_chain_dependencies = [
|
||||
mathlib, dl_lib, pipewire_dep, sndfile_dep, audioconvert_dep, libmysofa_dep
|
||||
mathlib, dl_lib, pipewire_dep, sndfile_dep, audioconvert_dep
|
||||
]
|
||||
|
||||
if lilv_lib.found()
|
||||
filter_chain_sources += [
|
||||
'module-filter-chain/lv2_plugin.c'
|
||||
]
|
||||
filter_chain_dependencies += [ lilv_lib ]
|
||||
endif
|
||||
|
||||
pipewire_module_filter_chain = shared_library('pipewire-module-filter-chain',
|
||||
filter_chain_sources,
|
||||
include_directories : [configinc],
|
||||
|
|
@ -141,6 +133,31 @@ pipewire_module_filter_chain = shared_library('pipewire-module-filter-chain',
|
|||
dependencies : filter_chain_dependencies,
|
||||
)
|
||||
|
||||
if libmysofa_dep.found()
|
||||
pipewire_module_filter_chain_sofa = shared_library('pipewire-module-filter-chain-sofa',
|
||||
[ 'module-filter-chain/sofa_plugin.c',
|
||||
'module-filter-chain/convolver.c' ],
|
||||
include_directories : [configinc],
|
||||
install : true,
|
||||
install_dir : modules_install_dir,
|
||||
install_rpath: modules_install_dir,
|
||||
link_with : simd_dependencies,
|
||||
dependencies : [ filter_chain_dependencies, libmysofa_dep ]
|
||||
)
|
||||
endif
|
||||
|
||||
if lilv_lib.found()
|
||||
pipewire_module_filter_chain_lv2 = shared_library('pipewire-module-filter-chain-lv2',
|
||||
[ 'module-filter-chain/lv2_plugin.c' ],
|
||||
include_directories : [configinc],
|
||||
install : true,
|
||||
install_dir : modules_install_dir,
|
||||
install_rpath: modules_install_dir,
|
||||
dependencies : [ filter_chain_dependencies, lilv_lib ]
|
||||
)
|
||||
endif
|
||||
|
||||
|
||||
pipewire_module_combine_stream = shared_library('pipewire-module-combine-stream',
|
||||
[ 'module-combine-stream.c' ],
|
||||
include_directories : [configinc],
|
||||
|
|
|
|||
|
|
@ -523,6 +523,11 @@ static const struct spa_dict_item module_props[] = {
|
|||
static float silence_data[MAX_SAMPLES];
|
||||
static float discard_data[MAX_SAMPLES];
|
||||
|
||||
struct fc_plugin *load_ladspa_plugin(const struct spa_support *support, uint32_t n_support,
|
||||
struct dsp_ops *dsp, const char *path, const char *config);
|
||||
struct fc_plugin *load_builtin_plugin(const struct spa_support *support, uint32_t n_support,
|
||||
struct dsp_ops *dsp, const char *path, const char *config);
|
||||
|
||||
struct plugin {
|
||||
struct spa_list link;
|
||||
int ref;
|
||||
|
|
@ -533,6 +538,13 @@ struct plugin {
|
|||
struct spa_list descriptor_list;
|
||||
};
|
||||
|
||||
struct plugin_func {
|
||||
struct spa_list link;
|
||||
char type[256];
|
||||
fc_plugin_load_func *func;
|
||||
void *hndl;
|
||||
};
|
||||
|
||||
struct descriptor {
|
||||
struct spa_list link;
|
||||
int ref;
|
||||
|
|
@ -647,6 +659,7 @@ struct impl {
|
|||
struct dsp_ops dsp;
|
||||
|
||||
struct spa_list plugin_list;
|
||||
struct spa_list plugin_func_list;
|
||||
|
||||
struct pw_properties *capture_props;
|
||||
struct pw_stream *capture;
|
||||
|
|
@ -1348,12 +1361,92 @@ static void plugin_unref(struct plugin *hndl)
|
|||
free(hndl);
|
||||
}
|
||||
|
||||
|
||||
static struct plugin_func *add_plugin_func(struct impl *impl, const char *type,
|
||||
fc_plugin_load_func *func, void *hndl)
|
||||
{
|
||||
struct plugin_func *pl;
|
||||
|
||||
pl = calloc(1, sizeof(*pl));
|
||||
if (pl == NULL)
|
||||
return NULL;
|
||||
|
||||
snprintf(pl->type, sizeof(pl->type), "%s", type);
|
||||
pl->func = func;
|
||||
pl->hndl = hndl;
|
||||
spa_list_append(&impl->plugin_func_list, &pl->link);
|
||||
return pl;
|
||||
}
|
||||
|
||||
static void free_plugin_func(struct plugin_func *pl)
|
||||
{
|
||||
spa_list_remove(&pl->link);
|
||||
if (pl->hndl)
|
||||
dlclose(pl->hndl);
|
||||
free(pl);
|
||||
}
|
||||
|
||||
static fc_plugin_load_func *find_plugin_func(struct impl *impl, const char *type)
|
||||
{
|
||||
fc_plugin_load_func *func = NULL;
|
||||
void *hndl = NULL;
|
||||
int res;
|
||||
struct plugin_func *pl;
|
||||
char module[PATH_MAX];
|
||||
const char *module_dir;
|
||||
const char *state = NULL, *p;
|
||||
size_t len;
|
||||
|
||||
spa_list_for_each(pl, &impl->plugin_func_list, link) {
|
||||
if (spa_streq(pl->type, type))
|
||||
return pl->func;
|
||||
}
|
||||
module_dir = getenv("PIPEWIRE_MODULE_DIR");
|
||||
if (module_dir == NULL)
|
||||
module_dir = MODULEDIR;
|
||||
pw_log_debug("moduledir set to: %s", module_dir);
|
||||
|
||||
while ((p = pw_split_walk(module_dir, ":", &len, &state))) {
|
||||
if ((res = spa_scnprintf(module, sizeof(module),
|
||||
"%.*s/libpipewire-module-filter-chain-%s.so",
|
||||
(int)len, p, type)) <= 0)
|
||||
continue;
|
||||
|
||||
hndl = dlopen(module, RTLD_NOW | RTLD_LOCAL);
|
||||
if (hndl != NULL)
|
||||
break;
|
||||
|
||||
pw_log_debug("open plugin module %s failed: %s", module, dlerror());
|
||||
}
|
||||
if (hndl == NULL) {
|
||||
errno = ENOENT;
|
||||
return NULL;
|
||||
}
|
||||
func = dlsym(hndl, FC_PLUGIN_LOAD_FUNC);
|
||||
if (func != NULL) {
|
||||
pw_log_info("opened plugin module %s", module);
|
||||
pl = add_plugin_func(impl, type, func, hndl);
|
||||
if (pl == NULL)
|
||||
goto error_close;
|
||||
} else {
|
||||
errno = ENOSYS;
|
||||
pw_log_error("%s is not a filter chain plugin: %m", module);
|
||||
goto error_close;
|
||||
}
|
||||
return func;
|
||||
|
||||
error_close:
|
||||
dlclose(hndl);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct plugin *plugin_load(struct impl *impl, const char *type, const char *path)
|
||||
{
|
||||
struct fc_plugin *pl = NULL;
|
||||
struct plugin *hndl;
|
||||
const struct spa_support *support;
|
||||
uint32_t n_support;
|
||||
fc_plugin_load_func *plugin_func;
|
||||
|
||||
spa_list_for_each(hndl, &impl->plugin_list, link) {
|
||||
if (spa_streq(hndl->type, type) &&
|
||||
|
|
@ -1364,27 +1457,12 @@ static struct plugin *plugin_load(struct impl *impl, const char *type, const cha
|
|||
}
|
||||
support = pw_context_get_support(impl->context, &n_support);
|
||||
|
||||
if (spa_streq(type, "builtin")) {
|
||||
pl = load_builtin_plugin(support, n_support, &impl->dsp, path, NULL);
|
||||
}
|
||||
else if (spa_streq(type, "sofa")) {
|
||||
pl = load_sofa_plugin(support, n_support, &impl->dsp, path, NULL);
|
||||
}
|
||||
else if (spa_streq(type, "ladspa")) {
|
||||
pl = load_ladspa_plugin(support, n_support, &impl->dsp, path, NULL);
|
||||
}
|
||||
else if (spa_streq(type, "lv2")) {
|
||||
#ifdef HAVE_LILV
|
||||
pl = load_lv2_plugin(support, n_support, &impl->dsp, path, NULL);
|
||||
#else
|
||||
pw_log_error("filter-chain is compiled without lv2 support");
|
||||
plugin_func = find_plugin_func(impl, type);
|
||||
if (plugin_func == NULL) {
|
||||
pw_log_error("can't load plugin type '%s': %m", type);
|
||||
pl = NULL;
|
||||
errno = ENOTSUP;
|
||||
#endif
|
||||
} else {
|
||||
pw_log_error("invalid plugin type '%s'", type);
|
||||
pl = NULL;
|
||||
errno = EINVAL;
|
||||
pl = plugin_func(support, n_support, &impl->dsp, path, NULL);
|
||||
}
|
||||
if (pl == NULL)
|
||||
goto exit;
|
||||
|
|
@ -1397,7 +1475,7 @@ static struct plugin *plugin_load(struct impl *impl, const char *type, const cha
|
|||
snprintf(hndl->type, sizeof(hndl->type), "%s", type);
|
||||
snprintf(hndl->path, sizeof(hndl->path), "%s", path);
|
||||
|
||||
pw_log_info("successfully opened '%s'", path);
|
||||
pw_log_info("successfully opened '%s':'%s'", type, path);
|
||||
|
||||
hndl->plugin = pl;
|
||||
|
||||
|
|
@ -2374,6 +2452,8 @@ static const struct pw_proxy_events core_proxy_events = {
|
|||
|
||||
static void impl_destroy(struct impl *impl)
|
||||
{
|
||||
struct plugin_func *pl;
|
||||
|
||||
/* disconnect both streams before destroying any of them */
|
||||
if (impl->capture)
|
||||
pw_stream_disconnect(impl->capture);
|
||||
|
|
@ -2391,6 +2471,8 @@ static void impl_destroy(struct impl *impl)
|
|||
pw_properties_free(impl->capture_props);
|
||||
pw_properties_free(impl->playback_props);
|
||||
graph_free(&impl->graph);
|
||||
spa_list_consume(pl, &impl->plugin_func_list, link)
|
||||
free_plugin_func(pl);
|
||||
free(impl);
|
||||
}
|
||||
|
||||
|
|
@ -2502,6 +2584,10 @@ int pipewire__module_init(struct pw_impl_module *module, const char *args)
|
|||
impl->graph.impl = impl;
|
||||
|
||||
spa_list_init(&impl->plugin_list);
|
||||
spa_list_init(&impl->plugin_func_list);
|
||||
|
||||
add_plugin_func(impl, "builtin", load_builtin_plugin, NULL);
|
||||
add_plugin_func(impl, "ladspa", load_ladspa_plugin, NULL);
|
||||
|
||||
support = pw_context_get_support(impl->context, &n_support);
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
#include <sndfile.h>
|
||||
#endif
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include <spa/utils/json.h>
|
||||
#include <spa/utils/result.h>
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include <dlfcn.h>
|
||||
#include <math.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include <spa/utils/defs.h>
|
||||
#include <spa/utils/list.h>
|
||||
|
|
|
|||
|
|
@ -451,7 +451,8 @@ static void lv2_unload(struct fc_plugin *plugin)
|
|||
free(p);
|
||||
}
|
||||
|
||||
struct fc_plugin *load_lv2_plugin(const struct spa_support *support, uint32_t n_support,
|
||||
SPA_EXPORT
|
||||
struct fc_plugin *pipewire__filter_chain_plugin_load(const struct spa_support *support, uint32_t n_support,
|
||||
struct dsp_ops *ops, const char *plugin_uri, const char *config)
|
||||
{
|
||||
struct context *c;
|
||||
|
|
|
|||
|
|
@ -7,14 +7,8 @@
|
|||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include <spa/support/plugin.h>
|
||||
#include <spa/utils/defs.h>
|
||||
#include <spa/utils/list.h>
|
||||
#include <spa/utils/string.h>
|
||||
|
||||
#include "dsp-ops.h"
|
||||
|
||||
|
|
@ -83,13 +77,10 @@ static inline void fc_descriptor_free(const struct fc_descriptor *desc)
|
|||
desc->free(desc);
|
||||
}
|
||||
|
||||
struct fc_plugin *load_ladspa_plugin(const struct spa_support *support, uint32_t n_support,
|
||||
struct dsp_ops *dsp, const char *path, const char *config);
|
||||
struct fc_plugin *load_lv2_plugin(const struct spa_support *support, uint32_t n_support,
|
||||
struct dsp_ops *dsp, const char *path, const char *config);
|
||||
struct fc_plugin *load_builtin_plugin(const struct spa_support *support, uint32_t n_support,
|
||||
struct dsp_ops *dsp, const char *path, const char *config);
|
||||
struct fc_plugin *load_sofa_plugin(const struct spa_support *support, uint32_t n_support,
|
||||
#define FC_PLUGIN_LOAD_FUNC "pipewire__filter_chain_plugin_load"
|
||||
|
||||
typedef struct fc_plugin *(fc_plugin_load_func)(const struct spa_support *support, uint32_t n_support,
|
||||
struct dsp_ops *dsp, const char *path, const char *config);
|
||||
|
||||
|
||||
#endif /* PLUGIN_H */
|
||||
|
|
|
|||
|
|
@ -1,19 +1,20 @@
|
|||
#include "config.h"
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#include <spa/utils/json.h>
|
||||
#include <spa/support/loop.h>
|
||||
|
||||
#include <pipewire/log.h>
|
||||
|
||||
#include "plugin.h"
|
||||
#include "convolver.h"
|
||||
#include "dsp-ops.h"
|
||||
#include "pffft.h"
|
||||
|
||||
#ifdef HAVE_LIBMYSOFA
|
||||
#include <mysofa.h>
|
||||
|
||||
#define MAX_SAMPLES 8192u
|
||||
#endif
|
||||
|
||||
static struct dsp_ops *dsp_ops;
|
||||
static struct spa_loop *data_loop;
|
||||
|
|
@ -25,9 +26,7 @@ struct spatializer_impl {
|
|||
int n_samples, blocksize, tailsize;
|
||||
float *tmp[2];
|
||||
|
||||
#ifdef HAVE_LIBMYSOFA
|
||||
struct MYSOFA_EASY *sofa;
|
||||
#endif
|
||||
unsigned int interpolate:1;
|
||||
struct convolver *l_conv[3];
|
||||
struct convolver *r_conv[3];
|
||||
|
|
@ -36,7 +35,6 @@ struct spatializer_impl {
|
|||
static void * spatializer_instantiate(const struct fc_descriptor * Descriptor,
|
||||
unsigned long SampleRate, int index, const char *config)
|
||||
{
|
||||
#ifdef HAVE_LIBMYSOFA
|
||||
struct spatializer_impl *impl;
|
||||
struct spa_json it[2];
|
||||
const char *val;
|
||||
|
|
@ -115,14 +113,8 @@ error:
|
|||
mysofa_close_cached(impl->sofa);
|
||||
free(impl);
|
||||
return NULL;
|
||||
#else
|
||||
pw_log_error("libmysofa is required for spatializer, but disabled at compile time");
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBMYSOFA
|
||||
static int
|
||||
do_switch(struct spa_loop *loop, bool async, uint32_t seq, const void *data,
|
||||
size_t size, void *user_data)
|
||||
|
|
@ -205,11 +197,9 @@ do_free(struct spa_loop *loop, bool async, uint32_t seq, const void *data,
|
|||
convolver_free(fd->item[1]);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void spatializer_run(void * Instance, unsigned long SampleCount)
|
||||
{
|
||||
#ifdef HAVE_LIBMYSOFA
|
||||
struct spatializer_impl *impl = Instance;
|
||||
|
||||
if (impl->interpolate) {
|
||||
|
|
@ -239,7 +229,6 @@ static void spatializer_run(void * Instance, unsigned long SampleCount)
|
|||
convolver_run(impl->l_conv[0], impl->port[2], impl->port[0], SampleCount);
|
||||
convolver_run(impl->r_conv[0], impl->port[2], impl->port[1], SampleCount);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void spatializer_connect_port(void * Instance, unsigned long Port,
|
||||
|
|
@ -261,10 +250,8 @@ static void spatializer_cleanup(void * Instance)
|
|||
if (impl->r_conv[i])
|
||||
convolver_free(impl->r_conv[i]);
|
||||
}
|
||||
#ifdef HAVE_LIBMYSOFA
|
||||
if (impl->sofa)
|
||||
mysofa_close_cached(impl->sofa);
|
||||
#endif
|
||||
free(impl->tmp[0]);
|
||||
free(impl->tmp[1]);
|
||||
|
||||
|
|
@ -273,10 +260,8 @@ static void spatializer_cleanup(void * Instance)
|
|||
|
||||
static void spatializer_control_changed(void * Instance)
|
||||
{
|
||||
#ifdef HAVE_LIBMYSOFA
|
||||
pw_log_info("control changed");
|
||||
spatializer_reload(Instance);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void spatializer_deactivate(void * Instance)
|
||||
|
|
@ -361,7 +346,8 @@ static struct fc_plugin builtin_plugin = {
|
|||
.make_desc = sofa_make_desc
|
||||
};
|
||||
|
||||
struct fc_plugin *load_sofa_plugin(const struct spa_support *support, uint32_t n_support,
|
||||
SPA_EXPORT
|
||||
struct fc_plugin *pipewire__filter_chain_plugin_load(const struct spa_support *support, uint32_t n_support,
|
||||
struct dsp_ops *dsp, const char *plugin, const char *config)
|
||||
{
|
||||
dsp_ops = dsp;
|
||||
|
|
@ -372,4 +358,3 @@ struct fc_plugin *load_sofa_plugin(const struct spa_support *support, uint32_t n
|
|||
|
||||
return &builtin_plugin;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue