diff --git a/src/daemon/minimal.conf.in b/src/daemon/minimal.conf.in index b4e064b9d..673424d41 100644 --- a/src/daemon/minimal.conf.in +++ b/src/daemon/minimal.conf.in @@ -211,7 +211,14 @@ context.objects = [ control = false position = unknown # unknown, preserve } + #node.param.Props = { + # channelVolumes = [ 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.6 ] + #} } + #device.param.Profile = { + # #idx = 0 + # name = pro-audio + #} } } condition = [ { minimal.use-udev = true } ] @@ -226,7 +233,7 @@ context.objects = [ node.name = "system" node.description = "system" media.class = "Audio/Source" - api.alsa.path = "hw:0" + api.alsa.path = "hw:4" #api.alsa.period-size = 0 #api.alsa.period-num = 0 #api.alsa.headroom = 0 @@ -281,6 +288,9 @@ context.objects = [ # position = [ FL FR RL RR ] # } #} + #node.param.Props = { + # channelVolumes = [ 0.5 0.4 0.3 0.5 ] + #} } condition = [ { minimal.use-udev = false } ] } @@ -290,7 +300,7 @@ context.objects = [ node.name = "system" node.description = "system" media.class = "Audio/Sink" - api.alsa.path = "hw:0" + api.alsa.path = "hw:4" #api.alsa.period-size = 0 #api.alsa.period-num = 0 #api.alsa.headroom = 0 @@ -344,6 +354,9 @@ context.objects = [ # channels = 4 # } #} + #node.param.Props = { + # channelVolumes = [ 0.5 0.4 0.3 0.5 ] + #} } condition = [ { minimal.use-udev = false } ] } diff --git a/src/modules/module-adapter/adapter.c b/src/modules/module-adapter/adapter.c index ec1cd068c..800a3fa1d 100644 --- a/src/modules/module-adapter/adapter.c +++ b/src/modules/module-adapter/adapter.c @@ -70,30 +70,6 @@ static const struct pw_impl_node_events node_events = { .free = node_free, }; -static int handle_node_param(struct pw_impl_node *node, const char *key, const char *value) -{ - const struct spa_type_info *ti; - uint8_t buffer[1024]; - struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer)); - struct spa_pod *pod; - int res; - - ti = spa_debug_type_find_short(spa_type_param, key); - if (ti == NULL) - return -ENOENT; - - if ((res = spa_json_to_pod(&b, 0, ti, value, strlen(value))) < 0) - return res; - - if ((pod = spa_pod_builder_deref(&b, 0)) == NULL) - return -ENOSPC; - - if ((res = pw_impl_node_set_param(node, ti->type, 0, pod)) < 0) - return res; - - return 0; -} - static int find_format(struct spa_node *node, enum pw_direction direction, uint32_t *media_type, uint32_t *media_subtype) { @@ -172,8 +148,6 @@ struct pw_impl_node *pw_adapter_new(struct pw_context *context, enum pw_direction direction; int res; uint32_t media_type, media_subtype; - const struct spa_dict_item *it; - struct pw_properties *copy; struct info_data info; spa_zero(info); @@ -233,16 +207,10 @@ struct pw_impl_node *pw_adapter_new(struct pw_context *context, goto error; } - copy = pw_properties_new(NULL, NULL); - spa_dict_for_each(it, &props->dict) { - if (!spa_strstartswith(it->key, "node.param.") && - !spa_strstartswith(it->key, "port.param.")) - pw_properties_set(copy, it->key, it->value); - } node = pw_spa_node_load(context, factory_name, PW_SPA_NODE_FLAG_ACTIVATE | PW_SPA_NODE_FLAG_NO_REGISTER, - copy, sizeof(struct node) + user_data_size); + pw_properties_copy(props), sizeof(struct node) + user_data_size); if (node == NULL) { res = -errno; pw_log_error("can't load spa node: %m"); @@ -264,12 +232,6 @@ struct pw_impl_node *pw_adapter_new(struct pw_context *context, pw_impl_node_add_listener(node, &n->node_listener, &node_events, n); - spa_dict_for_each(it, &props->dict) { - if (spa_strstartswith(it->key, "node.param.")) { - if ((res = handle_node_param(node, &it->key[11], it->value)) < 0) - pw_log_warn("can't set node param: %s", spa_strerror(res)); - } - } return node; error: diff --git a/src/pipewire/impl-device.c b/src/pipewire/impl-device.c index b090203f5..ff243f7cd 100644 --- a/src/pipewire/impl-device.c +++ b/src/pipewire/impl-device.c @@ -9,6 +9,7 @@ #include #include #include +#include #include "pipewire/impl.h" #include "pipewire/cleanup.h" @@ -361,6 +362,16 @@ int pw_impl_device_for_each_param(struct pw_impl_device *device, return res; } +SPA_EXPORT +int pw_impl_device_set_param(struct pw_impl_device *device, + uint32_t id, uint32_t flags, const struct spa_pod *param) +{ + pw_log_debug("%p: set_param id:%d (%s) flags:%08x param:%p", device, id, + spa_debug_type_find_name(spa_type_param, id), flags, param); + return spa_device_set_param(device->device, id, flags, param); +} + + static int reply_param(void *data, int seq, uint32_t id, uint32_t index, uint32_t next, struct spa_pod *param) { @@ -912,9 +923,36 @@ static const struct spa_device_events device_events = { .object_info = device_object_info, }; +static int handle_device_param(struct pw_impl_device *device, const char *key, const char *value) +{ + const struct spa_type_info *ti; + uint8_t buffer[1024]; + struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer)); + struct spa_pod *pod; + int res; + + ti = spa_debug_type_find_short(spa_type_param, key); + if (ti == NULL) + return -ENOENT; + + if ((res = spa_json_to_pod(&b, 0, ti, value, strlen(value))) < 0) + return res; + + if ((pod = spa_pod_builder_deref(&b, 0)) == NULL) + return -ENOSPC; + + if ((res = pw_impl_device_set_param(device, ti->type, 0, pod)) < 0) + return res; + + return 0; +} + SPA_EXPORT int pw_impl_device_set_implementation(struct pw_impl_device *device, struct spa_device *spa_device) { + int res; + const struct spa_dict_item *it; + pw_log_debug("%p: implementation %p", device, spa_device); if (device->device) { @@ -923,10 +961,19 @@ int pw_impl_device_set_implementation(struct pw_impl_device *device, struct spa_ return -EEXIST; } device->device = spa_device; - spa_device_add_listener(device->device, - &device->listener, &device_events, device); - return 0; +again: + spa_dict_for_each(it, &device->properties->dict) { + if (spa_strstartswith(it->key, "device.param.")) { + if ((res = handle_device_param(device, &it->key[13], it->value)) < 0) + pw_log_warn("can't set device param: %s", spa_strerror(res)); + pw_properties_set(device->properties, it->key, NULL); + goto again; + } + } + res = spa_device_add_listener(device->device, + &device->listener, &device_events, device); + return res; } SPA_EXPORT diff --git a/src/pipewire/impl-node.c b/src/pipewire/impl-node.c index dbb7b21ec..d36ac60a5 100644 --- a/src/pipewire/impl-node.c +++ b/src/pipewire/impl-node.c @@ -18,6 +18,7 @@ #include #include #include +#include #include "pipewire/impl-node.h" #include "pipewire/private.h" @@ -921,6 +922,8 @@ static void check_properties(struct pw_impl_node *node) uint32_t value; bool driver, trigger; + + if ((str = pw_properties_get(node->properties, PW_KEY_PRIORITY_DRIVER))) { value = pw_properties_parse_int(str); if (value != node->priority_driver) { @@ -1937,11 +1940,36 @@ static const struct spa_node_callbacks node_callbacks = { .xrun = node_xrun, }; +static int handle_node_param(struct pw_impl_node *node, const char *key, const char *value) +{ + const struct spa_type_info *ti; + uint8_t buffer[1024]; + struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer)); + struct spa_pod *pod; + int res; + + ti = spa_debug_type_find_short(spa_type_param, key); + if (ti == NULL) + return -ENOENT; + + if ((res = spa_json_to_pod(&b, 0, ti, value, strlen(value))) < 0) + return res; + + if ((pod = spa_pod_builder_deref(&b, 0)) == NULL) + return -ENOSPC; + + if ((res = pw_impl_node_set_param(node, ti->type, 0, pod)) < 0) + return res; + + return 0; +} + SPA_EXPORT int pw_impl_node_set_implementation(struct pw_impl_node *node, struct spa_node *spa_node) { int res; + const struct spa_dict_item *it; pw_log_debug("%p: implementation %p", node, spa_node); @@ -1952,6 +1980,17 @@ int pw_impl_node_set_implementation(struct pw_impl_node *node, node->node = spa_node; spa_node_set_callbacks(node->node, &node_callbacks, node); + +again: + spa_dict_for_each(it, &node->properties->dict) { + if (spa_strstartswith(it->key, "node.param.")) { + if ((res = handle_node_param(node, &it->key[11], it->value)) < 0) + pw_log_warn("can't set node param: %s", spa_strerror(res)); + pw_properties_set(node->properties, it->key, NULL); + goto again; + } + } + res = spa_node_add_listener(node->node, &node->listener, &node_events, node); if (node->registered)