pipewire: Improve handling of node switching

When switching to a node that has a missing property, yambar didn't
reset its internal state to the default value, causing outdated
information to be displayed.
This commit is contained in:
Alexey Yerin 2024-11-23 20:10:14 +03:00
parent 3e0083c9f2
commit b15714b38a
2 changed files with 33 additions and 24 deletions

View file

@ -50,9 +50,11 @@
* mpd: yambar never attempting to reconnect after MPD closed the * mpd: yambar never attempting to reconnect after MPD closed the
connection (for example, when MPD is restarted). connection (for example, when MPD is restarted).
* Bar positioning on multi-monitor setups, when `location=bottom`. * Bar positioning on multi-monitor setups, when `location=bottom`.
* pipewire: Improve handling of node switching ([#424][424]).
[377]: https://codeberg.org/dnkl/yambar/issues/377 [377]: https://codeberg.org/dnkl/yambar/issues/377
[300]: https://codeberg.org/dnkl/yambar/issues/300 [300]: https://codeberg.org/dnkl/yambar/issues/300
[424]: https://codeberg.org/dnkl/yambar/pulls/424
### Security ### Security

View file

@ -45,6 +45,16 @@ struct output_informations {
}; };
static struct output_informations const output_informations_null; static struct output_informations const output_informations_null;
static void
output_informations_destroy(struct output_informations *output_informations)
{
free(output_informations->name);
free(output_informations->description);
free(output_informations->icon);
free(output_informations->form_factor);
free(output_informations->bus);
}
struct data; struct data;
struct private struct private
{ {
@ -213,18 +223,23 @@ node_find_route(struct data *data, bool is_sink)
static void static void
node_unhook_binded_node(struct data *data, bool is_sink) node_unhook_binded_node(struct data *data, bool is_sink)
{ {
struct private *private = data->module->private;
struct node **target_node = NULL; struct node **target_node = NULL;
struct spa_hook *target_listener = NULL; struct spa_hook *target_listener = NULL;
void **target_proxy = NULL; void **target_proxy = NULL;
struct output_informations *output_informations = NULL;
if (is_sink) { if (is_sink) {
target_node = &data->binded_sink; target_node = &data->binded_sink;
target_listener = &data->node_sink_listener; target_listener = &data->node_sink_listener;
target_proxy = &data->node_sink; target_proxy = &data->node_sink;
output_informations = &private->sink_informations;
} else { } else {
target_node = &data->binded_source; target_node = &data->binded_source;
target_listener = &data->node_source_listener; target_listener = &data->node_source_listener;
target_proxy = &data->node_source; target_proxy = &data->node_source;
output_informations = &private->source_informations;
} }
if (*target_node == NULL) if (*target_node == NULL)
@ -235,6 +250,9 @@ node_unhook_binded_node(struct data *data, bool is_sink)
*target_node = NULL; *target_node = NULL;
*target_proxy = NULL; *target_proxy = NULL;
output_informations_destroy(output_informations);
*output_informations = output_informations_null;
} }
static void static void
@ -398,18 +416,18 @@ node_events_info(void *userdata, struct pw_node_info const *info)
struct spa_dict_item const *item = NULL; struct spa_dict_item const *item = NULL;
item = spa_dict_lookup_item(info->props, "node.name"); item = spa_dict_lookup_item(info->props, "node.name");
if (item != NULL) X_FREE_SET(output_informations->name, item != NULL ? X_STRDUP(item->value) : NULL);
X_FREE_SET(output_informations->name, X_STRDUP(item->value));
item = spa_dict_lookup_item(info->props, "node.description"); item = spa_dict_lookup_item(info->props, "node.description");
if (item != NULL) X_FREE_SET(output_informations->description, item != NULL ? X_STRDUP(item->value) : NULL);
X_FREE_SET(output_informations->description, X_STRDUP(item->value));
item = spa_dict_lookup_item(info->props, "device.id"); item = spa_dict_lookup_item(info->props, "device.id");
if (item != NULL) { if (item != NULL) {
uint32_t value = 0; uint32_t value = 0;
spa_atou32(item->value, &value, 10); spa_atou32(item->value, &value, 10);
output_informations->device_id = value; output_informations->device_id = value;
} else {
output_informations->device_id = 0;
} }
item = spa_dict_lookup_item(info->props, "card.profile.device"); item = spa_dict_lookup_item(info->props, "card.profile.device");
@ -417,30 +435,29 @@ node_events_info(void *userdata, struct pw_node_info const *info)
uint32_t value = 0; uint32_t value = 0;
spa_atou32(item->value, &value, 10); spa_atou32(item->value, &value, 10);
output_informations->card_profile_device_id = value; output_informations->card_profile_device_id = value;
} else {
output_informations->card_profile_device_id = 0;
} }
/* Device's information has an more important priority than node's information */ /* Device's information has an more important priority than node's information */
/* icon_name */ /* icon_name */
struct route *route = node_find_route(data, node_data->is_sink); struct route *route = node_find_route(data, node_data->is_sink);
if (route != NULL && route->icon_name != NULL) if (route != NULL && route->icon_name != NULL)
output_informations->icon = X_STRDUP(route->icon_name); X_FREE_SET(output_informations->icon, X_STRDUP(route->icon_name));
else { else {
item = spa_dict_lookup_item(info->props, "device.icon-name"); item = spa_dict_lookup_item(info->props, "device.icon-name");
if (item != NULL) X_FREE_SET(output_informations->icon, item != NULL ? X_STRDUP(item->value) : NULL);
X_FREE_SET(output_informations->icon, X_STRDUP(item->value));
} }
/* form_factor */ /* form_factor */
if (route != NULL && route->form_factor != NULL) if (route != NULL && route->form_factor != NULL)
output_informations->form_factor = X_STRDUP(route->form_factor); X_FREE_SET(output_informations->form_factor, X_STRDUP(route->form_factor));
else { else {
item = spa_dict_lookup_item(info->props, "device.form-factor"); item = spa_dict_lookup_item(info->props, "device.form-factor");
if (item != NULL) X_FREE_SET(output_informations->form_factor, item != NULL ? X_STRDUP(item->value) : NULL);
X_FREE_SET(output_informations->form_factor, X_STRDUP(item->value));
} }
item = spa_dict_lookup_item(info->props, "device.bus"); item = spa_dict_lookup_item(info->props, "device.bus");
if (item != NULL) X_FREE_SET(output_informations->bus, item != NULL ? X_STRDUP(item->value) : NULL);
X_FREE_SET(output_informations->bus, X_STRDUP(item->value));
data->module->bar->refresh(data->module->bar); data->module->bar->refresh(data->module->bar);
} }
@ -827,18 +844,8 @@ destroy(struct module *module)
pipewire_deinit(private->data); pipewire_deinit(private->data);
private->label->destroy(private->label); private->label->destroy(private->label);
/* sink */ output_informations_destroy(&private->sink_informations);
free(private->sink_informations.name); output_informations_destroy(&private->source_informations);
free(private->sink_informations.description);
free(private->sink_informations.icon);
free(private->sink_informations.form_factor);
free(private->sink_informations.bus);
/* source */
free(private->source_informations.name);
free(private->source_informations.description);
free(private->source_informations.icon);
free(private->source_informations.form_factor);
free(private->source_informations.bus);
free(private); free(private);
module_default_destroy(module); module_default_destroy(module);