mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-07 13:30:09 -05:00
modules: more ladspa improvements
Run multiple instances to fill requested channels. Improve media name.
This commit is contained in:
parent
3272344df4
commit
a36e5b2c0d
1 changed files with 74 additions and 48 deletions
|
|
@ -120,6 +120,7 @@ struct impl {
|
||||||
unsigned long control[MAX_PORTS];
|
unsigned long control[MAX_PORTS];
|
||||||
unsigned long notify[MAX_PORTS];
|
unsigned long notify[MAX_PORTS];
|
||||||
const LADSPA_Descriptor *desc;
|
const LADSPA_Descriptor *desc;
|
||||||
|
uint32_t n_hndl;
|
||||||
LADSPA_Handle hndl[MAX_PORTS];
|
LADSPA_Handle hndl[MAX_PORTS];
|
||||||
LADSPA_Data control_data[MAX_PORTS];
|
LADSPA_Data control_data[MAX_PORTS];
|
||||||
LADSPA_Data notify_data[MAX_PORTS];
|
LADSPA_Data notify_data[MAX_PORTS];
|
||||||
|
|
@ -149,8 +150,7 @@ static void capture_process(void *d)
|
||||||
{
|
{
|
||||||
struct impl *impl = d;
|
struct impl *impl = d;
|
||||||
struct pw_buffer *in, *out;
|
struct pw_buffer *in, *out;
|
||||||
uint32_t i;
|
uint32_t i, size = 0, n_hndl = impl->n_hndl;
|
||||||
uint32_t size = 0;
|
|
||||||
int32_t stride = 0;
|
int32_t stride = 0;
|
||||||
const LADSPA_Descriptor *desc = impl->desc;
|
const LADSPA_Descriptor *desc = impl->desc;
|
||||||
|
|
||||||
|
|
@ -165,20 +165,23 @@ static void capture_process(void *d)
|
||||||
|
|
||||||
for (i = 0; i < in->buffer->n_datas; i++) {
|
for (i = 0; i < in->buffer->n_datas; i++) {
|
||||||
struct spa_data *ds = &in->buffer->datas[i];
|
struct spa_data *ds = &in->buffer->datas[i];
|
||||||
desc->connect_port(impl->hndl[0], impl->input[i],
|
desc->connect_port(impl->hndl[i % n_hndl],
|
||||||
SPA_MEMBER(ds->data, ds->chunk->offset, void));
|
impl->input[i % impl->n_input],
|
||||||
|
SPA_MEMBER(ds->data, ds->chunk->offset, void));
|
||||||
size = SPA_MAX(size, ds->chunk->size);
|
size = SPA_MAX(size, ds->chunk->size);
|
||||||
stride = SPA_MAX(stride, ds->chunk->stride);
|
stride = SPA_MAX(stride, ds->chunk->stride);
|
||||||
}
|
}
|
||||||
for (i = 0; i < out->buffer->n_datas; i++) {
|
for (i = 0; i < out->buffer->n_datas; i++) {
|
||||||
struct spa_data *dd = &out->buffer->datas[i];
|
struct spa_data *dd = &out->buffer->datas[i];
|
||||||
desc->connect_port(impl->hndl[0], impl->output[i], dd->data);
|
desc->connect_port(impl->hndl[i % n_hndl],
|
||||||
|
impl->output[i % impl->n_output], dd->data);
|
||||||
dd->chunk->offset = 0;
|
dd->chunk->offset = 0;
|
||||||
dd->chunk->size = size;
|
dd->chunk->size = size;
|
||||||
dd->chunk->stride = stride;
|
dd->chunk->stride = stride;
|
||||||
}
|
}
|
||||||
|
|
||||||
desc->run(impl->hndl[0], size / sizeof(float));
|
for (i = 0; i < n_hndl; i++)
|
||||||
|
desc->run(impl->hndl[i], size / sizeof(float));
|
||||||
|
|
||||||
done:
|
done:
|
||||||
if (in != NULL)
|
if (in != NULL)
|
||||||
|
|
@ -260,7 +263,7 @@ static int setup_streams(struct impl *impl)
|
||||||
struct spa_pod_builder b;
|
struct spa_pod_builder b;
|
||||||
|
|
||||||
impl->capture = pw_stream_new(impl->core,
|
impl->capture = pw_stream_new(impl->core,
|
||||||
"loopback capture", impl->capture_props);
|
"ladspa capture", impl->capture_props);
|
||||||
impl->capture_props = NULL;
|
impl->capture_props = NULL;
|
||||||
if (impl->capture == NULL)
|
if (impl->capture == NULL)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
@ -270,7 +273,7 @@ static int setup_streams(struct impl *impl)
|
||||||
&in_stream_events, impl);
|
&in_stream_events, impl);
|
||||||
|
|
||||||
impl->playback = pw_stream_new(impl->core,
|
impl->playback = pw_stream_new(impl->core,
|
||||||
"loopback playback", impl->playback_props);
|
"ladspa playback", impl->playback_props);
|
||||||
impl->playback_props = NULL;
|
impl->playback_props = NULL;
|
||||||
if (impl->playback == NULL)
|
if (impl->playback == NULL)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
@ -388,21 +391,21 @@ static const LADSPA_Descriptor *find_descriptor(LADSPA_Descriptor_Function desc_
|
||||||
static int load_ladspa(struct impl *impl, struct pw_properties *props)
|
static int load_ladspa(struct impl *impl, struct pw_properties *props)
|
||||||
{
|
{
|
||||||
char path[PATH_MAX];
|
char path[PATH_MAX];
|
||||||
const char *e, *p, *label;
|
const char *e, *plugin, *label;
|
||||||
LADSPA_Descriptor_Function desc_func;
|
LADSPA_Descriptor_Function desc_func;
|
||||||
const LADSPA_Descriptor *d;
|
const LADSPA_Descriptor *d;
|
||||||
uint32_t i, j;
|
uint32_t i, j, p;
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
if ((e = getenv("LADSPA_PATH")) == NULL)
|
if ((e = getenv("LADSPA_PATH")) == NULL)
|
||||||
e = "/usr/lib64/ladspa";
|
e = "/usr/lib64/ladspa";
|
||||||
|
|
||||||
if ((p = pw_properties_get(props, "ladspa.plugin")) == NULL)
|
if ((plugin = pw_properties_get(props, "ladspa.plugin")) == NULL)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if ((label = pw_properties_get(props, "ladspa.label")) == NULL)
|
if ((label = pw_properties_get(props, "ladspa.label")) == NULL)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
snprintf(path, sizeof(path), "%s/%s.so", e, p);
|
snprintf(path, sizeof(path), "%s/%s.so", e, plugin);
|
||||||
|
|
||||||
impl->handle = dlopen(path, RTLD_NOW);
|
impl->handle = dlopen(path, RTLD_NOW);
|
||||||
if (impl->handle == NULL) {
|
if (impl->handle == NULL) {
|
||||||
|
|
@ -425,25 +428,24 @@ static int load_ladspa(struct impl *impl, struct pw_properties *props)
|
||||||
res = -ENOENT;
|
res = -ENOENT;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
pw_properties_setf(props, "ladspa.unique-id", "%lu", d->UniqueID);
|
|
||||||
pw_properties_setf(props, "ladspa.name", "%s", d->Name);
|
|
||||||
pw_properties_setf(props, "ladspa.maker", "%s", d->Maker);
|
|
||||||
pw_properties_setf(props, "ladspa.copyright", "%s", d->Copyright);
|
|
||||||
|
|
||||||
impl->desc = d;
|
impl->desc = d;
|
||||||
|
|
||||||
for (i = 0; i < d->PortCount; i++) {
|
pw_properties_setf(props, "ladspa.unique-id", "%lu", impl->desc->UniqueID);
|
||||||
if (LADSPA_IS_PORT_AUDIO(d->PortDescriptors[i])) {
|
pw_properties_setf(props, "ladspa.name", "%s", impl->desc->Name);
|
||||||
if (LADSPA_IS_PORT_INPUT(d->PortDescriptors[i]))
|
pw_properties_setf(props, "ladspa.maker", "%s", impl->desc->Maker);
|
||||||
impl->input[impl->n_input++] = i;
|
pw_properties_setf(props, "ladspa.copyright", "%s", impl->desc->Copyright);
|
||||||
else if (LADSPA_IS_PORT_OUTPUT(d->PortDescriptors[i]))
|
|
||||||
impl->output[impl->n_output++] = i;
|
for (p = 0; p < d->PortCount; p++) {
|
||||||
} else if (LADSPA_IS_PORT_CONTROL(d->PortDescriptors[i])) {
|
if (LADSPA_IS_PORT_AUDIO(d->PortDescriptors[p])) {
|
||||||
if (LADSPA_IS_PORT_INPUT(d->PortDescriptors[i]))
|
if (LADSPA_IS_PORT_INPUT(d->PortDescriptors[p]))
|
||||||
impl->control[impl->n_control++] = i;
|
impl->input[impl->n_input++] = p;
|
||||||
else if (LADSPA_IS_PORT_OUTPUT(d->PortDescriptors[i]))
|
else if (LADSPA_IS_PORT_OUTPUT(d->PortDescriptors[p]))
|
||||||
impl->notify[impl->n_notify++] = i;
|
impl->output[impl->n_output++] = p;
|
||||||
|
} else if (LADSPA_IS_PORT_CONTROL(d->PortDescriptors[p])) {
|
||||||
|
if (LADSPA_IS_PORT_INPUT(d->PortDescriptors[p]))
|
||||||
|
impl->control[impl->n_control++] = p;
|
||||||
|
else if (LADSPA_IS_PORT_OUTPUT(d->PortDescriptors[p]))
|
||||||
|
impl->notify[impl->n_notify++] = p;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (impl->n_input == 0 || impl->n_output == 0) {
|
if (impl->n_input == 0 || impl->n_output == 0) {
|
||||||
|
|
@ -451,30 +453,43 @@ static int load_ladspa(struct impl *impl, struct pw_properties *props)
|
||||||
res = -ENOTSUP;
|
res = -ENOTSUP;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
for (j = 0; j < impl->n_control; j++) {
|
||||||
|
p = impl->control[j];
|
||||||
|
impl->control_data[j] = get_default(impl, p);
|
||||||
|
pw_log_info("control (%s) %d set to %f", d->PortNames[p], p, impl->control_data[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (impl->capture_info.channels == 0)
|
||||||
|
impl->capture_info.channels = impl->n_input;
|
||||||
|
if (impl->playback_info.channels == 0)
|
||||||
|
impl->playback_info.channels = impl->n_output;
|
||||||
|
|
||||||
|
impl->n_hndl = impl->capture_info.channels / impl->n_input;
|
||||||
|
if (impl->n_hndl != impl->playback_info.channels / impl->n_output) {
|
||||||
if ((impl->hndl[0] = d->instantiate(d, impl->rate)) == NULL) {
|
pw_log_error("invalid channels");
|
||||||
pw_log_error("cannot create plugin instance");
|
res = -EINVAL;
|
||||||
res = -ENOMEM;
|
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
for (i = 0; i < impl->n_control; i++) {
|
pw_log_info("using %d instances", impl->n_hndl);
|
||||||
j = impl->control[i];
|
|
||||||
impl->control_data[i] = get_default(impl, j);
|
for (i = 0; i < impl->n_hndl;i++) {
|
||||||
pw_log_info("control (%s) %d set to %f", d->PortNames[j], i, impl->control_data[i]);
|
if ((impl->hndl[i] = d->instantiate(d, impl->rate)) == NULL) {
|
||||||
d->connect_port(impl->hndl[0], j, &impl->control_data[i]);
|
pw_log_error("cannot create plugin instance");
|
||||||
|
res = -ENOMEM;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j = 0; j < impl->n_control; j++) {
|
||||||
|
p = impl->control[j];
|
||||||
|
d->connect_port(impl->hndl[i], p, &impl->control_data[j]);
|
||||||
|
}
|
||||||
|
for (j = 0; j < impl->n_notify; j++) {
|
||||||
|
p = impl->notify[j];
|
||||||
|
d->connect_port(impl->hndl[i], p, &impl->notify_data[j]);
|
||||||
|
}
|
||||||
|
if (d->activate)
|
||||||
|
d->activate(impl->hndl[i]);
|
||||||
}
|
}
|
||||||
for (i = 0; i < impl->n_notify; i++) {
|
|
||||||
j = impl->notify[i];
|
|
||||||
d->connect_port(impl->hndl[0], j, &impl->notify_data[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (d->activate)
|
|
||||||
d->activate(impl->hndl[0]);
|
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
|
|
@ -658,6 +673,17 @@ int pipewire__module_init(struct pw_impl_module *module, const char *args)
|
||||||
pw_log_error("can't load ladspa: %s", spa_strerror(res));
|
pw_log_error("can't load ladspa: %s", spa_strerror(res));
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
copy_props(impl, props, "ladspa.unique-id");
|
||||||
|
copy_props(impl, props, "ladspa.name");
|
||||||
|
copy_props(impl, props, "ladspa.maker");
|
||||||
|
copy_props(impl, props, "ladspa.copyright");
|
||||||
|
|
||||||
|
if (pw_properties_get(impl->capture_props, PW_KEY_MEDIA_NAME) == NULL)
|
||||||
|
pw_properties_setf(impl->capture_props, PW_KEY_MEDIA_NAME, "%s input",
|
||||||
|
impl->desc->Name);
|
||||||
|
if (pw_properties_get(impl->playback_props, PW_KEY_MEDIA_NAME) == NULL)
|
||||||
|
pw_properties_setf(impl->playback_props, PW_KEY_MEDIA_NAME, "%s output",
|
||||||
|
impl->desc->Name);
|
||||||
|
|
||||||
impl->core = pw_context_get_object(impl->context, PW_TYPE_INTERFACE_Core);
|
impl->core = pw_context_get_object(impl->context, PW_TYPE_INTERFACE_Core);
|
||||||
if (impl->core == NULL) {
|
if (impl->core == NULL) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue