diff --git a/spa/plugins/audioconvert/audioadapter.c b/spa/plugins/audioconvert/audioadapter.c index c4136a161..940b3284e 100644 --- a/spa/plugins/audioconvert/audioadapter.c +++ b/spa/plugins/audioconvert/audioadapter.c @@ -291,6 +291,30 @@ static int impl_node_send_command(void *object, const struct spa_command *comman return res; } +static void convert_node_info(void *data, const struct spa_node_info *info) +{ + struct impl *this = data; + uint32_t i; + + for (i = 0; i < info->n_params; i++) { + uint32_t idx = SPA_ID_INVALID; + + switch (info->params[i].id) { + case SPA_PARAM_PropInfo: + idx = 1; + break; + case SPA_PARAM_Props: + idx = 2; + break; + } + if (idx != SPA_ID_INVALID) { + this->params[idx] = info->params[i]; + this->info.change_mask |= SPA_NODE_CHANGE_MASK_PARAMS; + } + } + emit_node_info(this, false); +} + static void convert_port_info(void *data, enum spa_direction direction, uint32_t port_id, const struct spa_port_info *info) @@ -319,6 +343,7 @@ static void convert_result(void *data, int seq, int res, uint32_t type, const vo static const struct spa_node_events convert_node_events = { SPA_VERSION_NODE_EVENTS, + .info = convert_node_info, .port_info = convert_port_info, .result = convert_result, }; @@ -333,6 +358,9 @@ static void slave_info(void *data, const struct spa_node_info *info) else this->direction = SPA_DIRECTION_OUTPUT; + this->info.max_input_ports = this->direction == SPA_DIRECTION_INPUT ? 128 : 0; + this->info.max_output_ports = this->direction == SPA_DIRECTION_OUTPUT ? 128 : 0; + spa_log_debug(this->log, NAME" %p: slave info %s", this, this->direction == SPA_DIRECTION_INPUT ? "Input" : "Output"); @@ -343,9 +371,33 @@ static void slave_info(void *data, const struct spa_node_info *info) } } +static void slave_port_info(void *data, + enum spa_direction direction, uint32_t port_id, + const struct spa_port_info *info) +{ + struct impl *this = data; + uint32_t i; + + for (i = 0; i < info->n_params; i++) { + uint32_t idx = SPA_ID_INVALID; + + switch (info->params[i].id) { + case SPA_PARAM_Format: + idx = 3; + break; + } + if (idx != SPA_ID_INVALID) { + this->params[idx] = info->params[i]; + this->info.change_mask |= SPA_NODE_CHANGE_MASK_PARAMS; + } + } + emit_node_info(this, false); +} + static const struct spa_node_events slave_node_events = { SPA_VERSION_NODE_EVENTS, .info = slave_info, + .port_info = slave_port_info, }; static int slave_ready(void *data, int status) @@ -354,6 +406,8 @@ static int slave_ready(void *data, int status) spa_log_trace(this->log, NAME " %p: ready %d", this, status); + this->master = true; + if (this->direction == SPA_DIRECTION_OUTPUT) status = spa_node_process(this->convert); @@ -766,8 +820,8 @@ static int impl_node_process(void *object) struct impl *this = object; int status; - spa_log_trace_fp(this->log, "%p: process convert:%u", - this, this->use_converter); + spa_log_trace_fp(this->log, "%p: process convert:%u master:%d", + this, this->use_converter, this->master); if (this->direction == SPA_DIRECTION_INPUT) { if (this->use_converter) @@ -779,6 +833,7 @@ static int impl_node_process(void *object) if (this->direction == SPA_DIRECTION_OUTPUT && !this->master) { if (this->use_converter) status = spa_node_process(this->convert); + this->master = false; } return status; } @@ -901,15 +956,12 @@ impl_init(const struct spa_handle_factory *factory, if (this->slave == NULL) return -EINVAL; - spa_node_add_listener(this->slave, - &this->slave_listener, &slave_node_events, this); - spa_node_set_callbacks(this->slave, &slave_node_callbacks, this); + spa_hook_list_init(&this->hooks); this->node.iface = SPA_INTERFACE_INIT( SPA_TYPE_INTERFACE_Node, SPA_VERSION_NODE, &impl_node, this); - spa_hook_list_init(&this->hooks); this->hnd_convert = SPA_MEMBER(this, sizeof(struct impl), struct spa_handle); spa_handle_factory_init(&spa_audioconvert_factory, @@ -919,18 +971,9 @@ impl_init(const struct spa_handle_factory *factory, spa_handle_get_interface(this->hnd_convert, SPA_TYPE_INTERFACE_Node, &iface); this->convert = iface; this->target = this->convert; - spa_node_add_listener(this->convert, - &this->convert_listener, &convert_node_events, this); - this->use_converter = true; - - configure_adapt(this); - - link_io(this); this->info_all = SPA_NODE_CHANGE_MASK_PARAMS; this->info = SPA_NODE_INFO_INIT(); - this->info.max_input_ports = this->direction == SPA_DIRECTION_INPUT ? 128 : 0; - this->info.max_output_ports = this->direction == SPA_DIRECTION_OUTPUT ? 128 : 0; this->params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ); this->params[1] = SPA_PARAM_INFO(SPA_PARAM_PropInfo, SPA_PARAM_INFO_READ); this->params[2] = SPA_PARAM_INFO(SPA_PARAM_Props, SPA_PARAM_INFO_READWRITE); @@ -939,6 +982,18 @@ impl_init(const struct spa_handle_factory *factory, this->info.params = this->params; this->info.n_params = 5; + spa_node_add_listener(this->slave, + &this->slave_listener, &slave_node_events, this); + spa_node_set_callbacks(this->slave, &slave_node_callbacks, this); + + spa_node_add_listener(this->convert, + &this->convert_listener, &convert_node_events, this); + this->use_converter = true; + + configure_adapt(this); + + link_io(this); + return 0; } diff --git a/spa/plugins/audioconvert/audioconvert.c b/spa/plugins/audioconvert/audioconvert.c index ea2a4164d..2be32592c 100644 --- a/spa/plugins/audioconvert/audioconvert.c +++ b/spa/plugins/audioconvert/audioconvert.c @@ -552,7 +552,37 @@ static struct spa_node_events fmt_output_events = { .result = on_node_result, }; -static struct spa_node_events node_events = { +static void on_channelmix_info(void *data, const struct spa_node_info *info) +{ + struct impl *this = data; + uint32_t i; + + for (i = 0; i < info->n_params; i++) { + uint32_t idx = SPA_ID_INVALID; + + switch (info->params[i].id) { + case SPA_PARAM_PropInfo: + idx = 2; + break; + case SPA_PARAM_Props: + idx = 3; + break; + } + if (idx != SPA_ID_INVALID) { + this->params[idx] = info->params[i]; + this->info.change_mask |= SPA_NODE_CHANGE_MASK_PARAMS; + } + } + emit_node_info(this, false); +} + +static struct spa_node_events channelmix_events = { + SPA_VERSION_NODE_EVENTS, + .info = on_channelmix_info, + .result = on_node_result, +}; + +static struct spa_node_events resample_events = { SPA_VERSION_NODE_EVENTS, .result = on_node_result, }; @@ -774,9 +804,9 @@ impl_node_add_listener(void *object, spa_node_add_listener(this->fmt[SPA_DIRECTION_INPUT], &l[0], &fmt_input_events, this); spa_node_add_listener(this->channelmix, - &l[1], &node_events, this); + &l[1], &channelmix_events, this); spa_node_add_listener(this->resample, - &l[2], &node_events, this); + &l[2], &resample_events, this); spa_node_add_listener(this->fmt[SPA_DIRECTION_OUTPUT], &l[3], &fmt_output_events, this); @@ -1229,9 +1259,9 @@ impl_init(const struct spa_handle_factory *factory, reconfigure_mode(this, SPA_PARAM_PORT_CONFIG_MODE_convert, SPA_DIRECTION_INPUT, false, NULL); spa_node_add_listener(this->channelmix, - &this->listener[0], &node_events, this); + &this->listener[0], &channelmix_events, this); spa_node_add_listener(this->resample, - &this->listener[1], &node_events, this); + &this->listener[1], &resample_events, this); return 0; } diff --git a/spa/plugins/audioconvert/channelmix.c b/spa/plugins/audioconvert/channelmix.c index e38fd67f3..1c1bf69ad 100644 --- a/spa/plugins/audioconvert/channelmix.c +++ b/spa/plugins/audioconvert/channelmix.c @@ -130,6 +130,23 @@ struct impl { #define _MASK(ch) (1ULL << SPA_AUDIO_CHANNEL_ ## ch) #define STEREO (_MASK(FL)|_MASK(FR)) +static void emit_info(struct impl *this, bool full) +{ + if (full) + this->info.change_mask = this->info_all; + if (this->info.change_mask) { + spa_node_emit_info(&this->hooks, &this->info); + this->info.change_mask = 0; + } +} + +static void emit_params_changed(struct impl *this) +{ + this->info.change_mask |= SPA_NODE_CHANGE_MASK_PARAMS; + this->params[1].flags ^= SPA_PARAM_INFO_SERIAL; + emit_info(this, false); +} + static uint64_t default_mask(uint32_t channels) { uint64_t mask = 0; @@ -334,16 +351,6 @@ static int impl_node_set_io(void *object, uint32_t id, void *data, size_t size) return -ENOTSUP; } -static void emit_info(struct impl *this, bool full) -{ - if (full) - this->info.change_mask = this->info_all; - if (this->info.change_mask) { - spa_node_emit_info(&this->hooks, &this->info); - this->info.change_mask = 0; - } -} - static int impl_node_set_param(void *object, uint32_t id, uint32_t flags, const struct spa_pod *param) { @@ -353,11 +360,8 @@ static int impl_node_set_param(void *object, uint32_t id, uint32_t flags, switch (id) { case SPA_PARAM_Props: - if (apply_props(this, param) > 0) { - this->info.change_mask = SPA_NODE_CHANGE_MASK_PARAMS; - this->params[1].flags ^= SPA_PARAM_INFO_SERIAL; - emit_info(this, false); - } + if (apply_props(this, param) > 0) + emit_params_changed(this); break; default: return -ENOENT; diff --git a/src/pipewire/device.c b/src/pipewire/device.c index 42072a0f5..cf4aa445d 100644 --- a/src/pipewire/device.c +++ b/src/pipewire/device.c @@ -370,7 +370,12 @@ int pw_device_register(struct pw_device *device, if (properties == NULL) return -errno; - pw_properties_set(properties, PW_KEY_DEVICE_NAME, device->info.name); + if ((str = pw_properties_get(device->properties, PW_KEY_DEVICE_DESCRIPTION)) != NULL) + pw_properties_set(properties, PW_KEY_DEVICE_DESCRIPTION, str); + if ((str = pw_properties_get(device->properties, PW_KEY_DEVICE_NAME)) != NULL) + pw_properties_set(properties, PW_KEY_DEVICE_NAME, str); + if ((str = pw_properties_get(device->properties, PW_KEY_DEVICE_NICK)) != NULL) + pw_properties_set(properties, PW_KEY_DEVICE_NICK, str); if ((str = pw_properties_get(device->properties, PW_KEY_MEDIA_CLASS)) != NULL) pw_properties_set(properties, PW_KEY_MEDIA_CLASS, str); @@ -445,6 +450,7 @@ static int update_properties(struct pw_device *device, const struct spa_dict *di device->info.props = &device->properties->dict; device->info.change_mask |= PW_DEVICE_CHANGE_MASK_PROPS; + return changed; } diff --git a/src/pipewire/keys.h b/src/pipewire/keys.h index 07087f26a..818261d18 100644 --- a/src/pipewire/keys.h +++ b/src/pipewire/keys.h @@ -104,6 +104,9 @@ extern "C" { /** Node keys */ #define PW_KEY_NODE_ID "node.id" /**< node id */ #define PW_KEY_NODE_NAME "node.name" /**< node name */ +#define PW_KEY_NODE_NICK "node.nick" /**< short node name */ +#define PW_KEY_NODE_DESCRIPTION "node.description" /**< localized human readable node one-line + * description. Ex. "Foobar USB Headset" */ #define PW_KEY_NODE_PLUGGED "node.plugged" /**< when the node was created. As a uint64 in * nanoseconds. */ #define PW_KEY_NODE_SESSION "node.session" /**< the session id this node is part of */ @@ -140,6 +143,7 @@ extern "C" { * does not cause the graph to be * runnable. */ /** device properties */ +#define PW_KEY_DEVICE_ID "device.id" /**< device id */ #define PW_KEY_DEVICE_NAME "device.name" /**< device name */ #define PW_KEY_DEVICE_PLUGGED "device.plugged" /**< when the device was created. As a uint64 in * nanoseconds. */ diff --git a/src/pipewire/node.c b/src/pipewire/node.c index be65ff3e1..6b12abb51 100644 --- a/src/pipewire/node.c +++ b/src/pipewire/node.c @@ -721,7 +721,6 @@ static void check_properties(struct pw_node *node) node->quantum_size = DEFAULT_QUANTUM; pw_log_debug(NAME" %p: driver:%d", node, node->driver); - } static void dump_states(struct pw_node *driver) diff --git a/src/pipewire/port.c b/src/pipewire/port.c index 56a2ce5d6..a28b2db04 100644 --- a/src/pipewire/port.c +++ b/src/pipewire/port.c @@ -680,9 +680,11 @@ int pw_port_register(struct pw_port *port, struct pw_properties *properties) { struct pw_node *node = port->node; - struct pw_core *core = node->core; - port->global = pw_global_new(core, + if (node == NULL) + return -EIO; + + port->global = pw_global_new(node->core, PW_TYPE_INTERFACE_Port, PW_VERSION_PORT_PROXY, properties,