mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-12-16 08:56:45 -05:00
impl-device: add support for adapter
Make it possible to wrap nodes created by a device in a wrapper such as adapter. Update the minimal.conf to use udev to detect and configure devices and nodes. Add a config switch to switch back to hardcoded config.
This commit is contained in:
parent
c08c335264
commit
1dc822c999
2 changed files with 71 additions and 3 deletions
|
|
@ -44,6 +44,10 @@ context.properties = {
|
||||||
vm.overrides = {
|
vm.overrides = {
|
||||||
default.clock.min-quantum = 1024
|
default.clock.min-quantum = 1024
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# This config can use udev or hardcoded ALSA devices. Make sure to
|
||||||
|
# change the alsa device below when disabling udev
|
||||||
|
minimal.use-udev = true
|
||||||
}
|
}
|
||||||
|
|
||||||
context.spa-libs = {
|
context.spa-libs = {
|
||||||
|
|
@ -54,6 +58,7 @@ context.spa-libs = {
|
||||||
# that factory.
|
# that factory.
|
||||||
#
|
#
|
||||||
audio.convert.* = audioconvert/libspa-audioconvert
|
audio.convert.* = audioconvert/libspa-audioconvert
|
||||||
|
audio.adapt = audioconvert/libspa-audioconvert
|
||||||
api.alsa.* = alsa/libspa-alsa
|
api.alsa.* = alsa/libspa-alsa
|
||||||
support.* = support/libspa-support
|
support.* = support/libspa-support
|
||||||
}
|
}
|
||||||
|
|
@ -99,6 +104,8 @@ context.modules = [
|
||||||
# context of the PipeWire server.
|
# context of the PipeWire server.
|
||||||
{ name = libpipewire-module-spa-node-factory }
|
{ name = libpipewire-module-spa-node-factory }
|
||||||
|
|
||||||
|
{ name = libpipewire-module-spa-device-factory }
|
||||||
|
|
||||||
# Allows creating nodes that run in the context of the
|
# Allows creating nodes that run in the context of the
|
||||||
# client. Is used by all clients that want to provide
|
# client. Is used by all clients that want to provide
|
||||||
# data to PipeWire.
|
# data to PipeWire.
|
||||||
|
|
@ -183,6 +190,33 @@ context.objects = [
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# This creates a ALSA udev device that will enumerate all
|
||||||
|
# ALSA devices. Because it is using ACP and has the audio-profile
|
||||||
|
# property set, this will enable a profile and create associated
|
||||||
|
# nodes, which will be automatically configured to their best
|
||||||
|
# configuration.
|
||||||
|
{ factory = spa-device-factory
|
||||||
|
args = {
|
||||||
|
factory.name = api.alsa.enum.udev
|
||||||
|
alsa.use-acp = true
|
||||||
|
device.object.properties = {
|
||||||
|
api.acp.auto-profile = true
|
||||||
|
api.acp.auto-port = true
|
||||||
|
device.object.properties = {
|
||||||
|
node.adapter = audio.adapt
|
||||||
|
resample.disable = true
|
||||||
|
adapter.auto-port-config = {
|
||||||
|
mode = dsp
|
||||||
|
monitor = false
|
||||||
|
control = false
|
||||||
|
position = unknown # unknown, preserve
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
condition = [ { minimal.use-udev = true } ]
|
||||||
|
}
|
||||||
|
|
||||||
# This creates a single PCM source device for the given
|
# This creates a single PCM source device for the given
|
||||||
# alsa device path hw:0. You can change source to sink
|
# alsa device path hw:0. You can change source to sink
|
||||||
# to make a sink in the same way.
|
# to make a sink in the same way.
|
||||||
|
|
@ -222,7 +256,7 @@ context.objects = [
|
||||||
#channelmix.rear-delay = 12.0
|
#channelmix.rear-delay = 12.0
|
||||||
#channelmix.stereo-widen = 0.0
|
#channelmix.stereo-widen = 0.0
|
||||||
#channelmix.hilbert-taps = 0
|
#channelmix.hilbert-taps = 0
|
||||||
channelmix.disable = true
|
#channelmix.disable = false
|
||||||
#dither.noise = 0
|
#dither.noise = 0
|
||||||
#node.param.Props = {
|
#node.param.Props = {
|
||||||
# params = [
|
# params = [
|
||||||
|
|
@ -248,6 +282,7 @@ context.objects = [
|
||||||
# }
|
# }
|
||||||
#}
|
#}
|
||||||
}
|
}
|
||||||
|
condition = [ { minimal.use-udev = false } ]
|
||||||
}
|
}
|
||||||
{ factory = adapter
|
{ factory = adapter
|
||||||
args = {
|
args = {
|
||||||
|
|
@ -284,7 +319,7 @@ context.objects = [
|
||||||
#channelmix.rear-delay = 12.0
|
#channelmix.rear-delay = 12.0
|
||||||
#channelmix.stereo-widen = 0.0
|
#channelmix.stereo-widen = 0.0
|
||||||
#channelmix.hilbert-taps = 0
|
#channelmix.hilbert-taps = 0
|
||||||
channelmix.disable = true
|
#channelmix.disable = false
|
||||||
#dither.noise = 0
|
#dither.noise = 0
|
||||||
#node.param.Props = {
|
#node.param.Props = {
|
||||||
# params = [
|
# params = [
|
||||||
|
|
@ -310,6 +345,7 @@ context.objects = [
|
||||||
# }
|
# }
|
||||||
#}
|
#}
|
||||||
}
|
}
|
||||||
|
condition = [ { minimal.use-udev = false } ]
|
||||||
}
|
}
|
||||||
# This creates a new Source node. It will have input ports
|
# This creates a new Source node. It will have input ports
|
||||||
# that you can link, to provide audio for this source.
|
# that you can link, to provide audio for this source.
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,7 @@ struct object_data {
|
||||||
#define OBJECT_DEVICE 1
|
#define OBJECT_DEVICE 1
|
||||||
uint32_t type;
|
uint32_t type;
|
||||||
struct spa_handle *handle;
|
struct spa_handle *handle;
|
||||||
|
struct spa_handle *subhandle;
|
||||||
void *object;
|
void *object;
|
||||||
struct spa_hook listener;
|
struct spa_hook listener;
|
||||||
};
|
};
|
||||||
|
|
@ -610,6 +611,8 @@ static void on_object_free(void *data)
|
||||||
{
|
{
|
||||||
struct object_data *od = data;
|
struct object_data *od = data;
|
||||||
pw_unload_spa_handle(od->handle);
|
pw_unload_spa_handle(od->handle);
|
||||||
|
if (od->subhandle)
|
||||||
|
pw_unload_spa_handle(od->subhandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct pw_impl_node_events node_object_events = {
|
static const struct pw_impl_node_events node_object_events = {
|
||||||
|
|
@ -765,11 +768,12 @@ static void device_add_object(struct pw_impl_device *device, uint32_t id,
|
||||||
const struct spa_device_object_info *info)
|
const struct spa_device_object_info *info)
|
||||||
{
|
{
|
||||||
struct pw_context *context = device->context;
|
struct pw_context *context = device->context;
|
||||||
struct spa_handle *handle;
|
struct spa_handle *handle, *subhandle = NULL;
|
||||||
spa_autoptr(pw_properties) props = NULL;
|
spa_autoptr(pw_properties) props = NULL;
|
||||||
int res;
|
int res;
|
||||||
void *iface;
|
void *iface;
|
||||||
struct object_data *od = NULL;
|
struct object_data *od = NULL;
|
||||||
|
const char *str;
|
||||||
|
|
||||||
if (info->factory_name == NULL) {
|
if (info->factory_name == NULL) {
|
||||||
pw_log_debug("%p: missing factory name", device);
|
pw_log_debug("%p: missing factory name", device);
|
||||||
|
|
@ -801,6 +805,31 @@ static void device_add_object(struct pw_impl_device *device, uint32_t id,
|
||||||
|
|
||||||
if (spa_streq(info->type, SPA_TYPE_INTERFACE_Node)) {
|
if (spa_streq(info->type, SPA_TYPE_INTERFACE_Node)) {
|
||||||
struct pw_impl_node *node;
|
struct pw_impl_node *node;
|
||||||
|
const struct pw_properties *p;
|
||||||
|
|
||||||
|
p = pw_context_get_properties(context);
|
||||||
|
pw_properties_set(props, "clock.quantum-limit",
|
||||||
|
pw_properties_get(p, "default.clock.quantum-limit"));
|
||||||
|
|
||||||
|
if ((str = pw_properties_get(props, "node.adapter")) != NULL) {
|
||||||
|
char name[64];
|
||||||
|
snprintf(name, sizeof(name), "%s.follower", str);
|
||||||
|
pw_properties_setf(props, name, "pointer:%p", iface);
|
||||||
|
|
||||||
|
subhandle = handle;
|
||||||
|
|
||||||
|
handle = pw_context_load_spa_handle(context, str, &props->dict);
|
||||||
|
if (handle == NULL) {
|
||||||
|
pw_log_warn("%p: can't load handle %s: %m", device, str);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
if ((res = spa_handle_get_interface(handle, info->type, &iface)) < 0) {
|
||||||
|
pw_log_error("%p: can't get %s interface: %s", device, info->type,
|
||||||
|
spa_strerror(res));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
node = pw_context_create_node(context, spa_steal_ptr(props),
|
node = pw_context_create_node(context, spa_steal_ptr(props),
|
||||||
sizeof(struct object_data));
|
sizeof(struct object_data));
|
||||||
if (node == NULL)
|
if (node == NULL)
|
||||||
|
|
@ -830,6 +859,7 @@ static void device_add_object(struct pw_impl_device *device, uint32_t id,
|
||||||
if (od) {
|
if (od) {
|
||||||
od->id = id;
|
od->id = id;
|
||||||
od->handle = handle;
|
od->handle = handle;
|
||||||
|
od->subhandle = subhandle;
|
||||||
spa_list_append(&device->object_list, &od->link);
|
spa_list_append(&device->object_list, &od->link);
|
||||||
if (device->global)
|
if (device->global)
|
||||||
object_register(od, device->info.id);
|
object_register(od, device->info.id);
|
||||||
|
|
@ -839,6 +869,8 @@ static void device_add_object(struct pw_impl_device *device, uint32_t id,
|
||||||
cleanup:
|
cleanup:
|
||||||
if (handle)
|
if (handle)
|
||||||
pw_unload_spa_handle(handle);
|
pw_unload_spa_handle(handle);
|
||||||
|
if (subhandle)
|
||||||
|
pw_unload_spa_handle(subhandle);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue