From 0c14ec769f82df3400c013f84f35b5386d7e91e1 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Fri, 25 Jun 2021 13:23:22 +0200 Subject: [PATCH] pulse-server: improve sink/source state When a sink is RUNNING but there is nothing linked to the input it must be the monitor that is keeping it active, report IDLE for the sink in that case. When a source is RUNNING but there is nothing linked to the output it must be the sink part that is keeping it active, report IDLE for the source. Fixes #1345 --- src/modules/module-protocol-pulse/collect.c | 24 +++++++++++++++++++ src/modules/module-protocol-pulse/collect.h | 1 + .../module-protocol-pulse/pulse-server.c | 22 ++++++++++++++--- 3 files changed, 44 insertions(+), 3 deletions(-) diff --git a/src/modules/module-protocol-pulse/collect.c b/src/modules/module-protocol-pulse/collect.c index f38e7bbe7..2fc3ef948 100644 --- a/src/modules/module-protocol-pulse/collect.c +++ b/src/modules/module-protocol-pulse/collect.c @@ -71,6 +71,30 @@ struct pw_manager_object *select_object(struct pw_manager *m, struct selector *s return s->best; } +bool collect_is_linked(struct pw_manager *m, uint32_t obj_id, enum pw_direction direction) +{ + struct pw_manager_object *o; + const char *str; + uint32_t in_node, out_node; + + spa_list_for_each(o, &m->object_list, link) { + if (o->props == NULL || !pw_manager_object_is_link(o)) + continue; + + if ((str = pw_properties_get(o->props, PW_KEY_LINK_OUTPUT_NODE)) == NULL) + continue; + out_node = pw_properties_parse_int(str); + if ((str = pw_properties_get(o->props, PW_KEY_LINK_INPUT_NODE)) == NULL) + continue; + in_node = pw_properties_parse_int(str); + + if ((direction == PW_DIRECTION_OUTPUT && obj_id == out_node) || + (direction == PW_DIRECTION_INPUT && obj_id == in_node)) + return true; + } + return false; +} + struct pw_manager_object *find_linked(struct pw_manager *m, uint32_t obj_id, enum pw_direction direction) { struct pw_manager_object *o, *p; diff --git a/src/modules/module-protocol-pulse/collect.h b/src/modules/module-protocol-pulse/collect.h index 1f715419f..56bbc4c4a 100644 --- a/src/modules/module-protocol-pulse/collect.h +++ b/src/modules/module-protocol-pulse/collect.h @@ -155,5 +155,6 @@ struct spa_dict *collect_props(struct spa_pod *info, struct spa_dict *dict); uint32_t find_profile_id(struct pw_manager_object *card, const char *name); uint32_t find_port_id(struct pw_manager_object *card, uint32_t direction, const char *port_name); struct pw_manager_object *find_linked(struct pw_manager *m, uint32_t obj_id, enum pw_direction direction); +bool collect_is_linked(struct pw_manager *m, uint32_t obj_id, enum pw_direction direction); #endif diff --git a/src/modules/module-protocol-pulse/pulse-server.c b/src/modules/module-protocol-pulse/pulse-server.c index 5ab23db2f..52b6cb84c 100644 --- a/src/modules/module-protocol-pulse/pulse-server.c +++ b/src/modules/module-protocol-pulse/pulse-server.c @@ -3467,11 +3467,19 @@ static int fill_sink_info(struct client *client, struct message *m, TAG_INVALID); } if (client->version >= 15) { + bool is_linked = collect_is_linked(manager, o->id, SPA_DIRECTION_INPUT); + int state = node_state(info->state); + + /* running with nothing linked is probably the monitor that is + * keeping this sink busy */ + if (state == STATE_RUNNING && !is_linked) + state = STATE_IDLE; + message_put(m, TAG_VOLUME, dev_info.volume_info.base, /* base volume */ - TAG_U32, node_state(info->state), /* state */ + TAG_U32, state, /* state */ TAG_U32, dev_info.volume_info.steps, /* n_volume_steps */ - TAG_U32, card_id, /* card index */ + TAG_U32, card_id, /* card index */ TAG_INVALID); } if (client->version >= 16) { @@ -3611,9 +3619,17 @@ static int fill_source_info(struct client *client, struct message *m, TAG_INVALID); } if (client->version >= 15) { + bool is_linked = collect_is_linked(manager, o->id, SPA_DIRECTION_OUTPUT); + int state = node_state(info->state); + + /* running with nothing linked is probably the sink that is + * keeping this source busy */ + if (state == STATE_RUNNING && !is_linked) + state = STATE_IDLE; + message_put(m, TAG_VOLUME, dev_info.volume_info.base, /* base volume */ - TAG_U32, node_state(info->state), /* state */ + TAG_U32, state, /* state */ TAG_U32, dev_info.volume_info.steps, /* n_volume_steps */ TAG_U32, card_id, /* card index */ TAG_INVALID);