pulse-server: send server change events when default nodes change

Send server change events to subscribers, when default nodes change due
to some nodes being added/removed/changed, also if there is no metadata
change.  Make sure the event is consistent with the result from
find_device at the time.

Previously, these were not necessarily sent, or information from
find_device immediately after the event might not reflect the change
yet.
This commit is contained in:
Pauli Virtanen 2021-01-23 01:37:59 +02:00 committed by Wim Taymans
parent 906a1f5448
commit 59452a0904
4 changed files with 51 additions and 9 deletions

View file

@ -135,7 +135,7 @@ static struct pw_manager_object *select_object(struct pw_manager *m,
const char *str; const char *str;
spa_list_for_each(o, &m->object_list, link) { spa_list_for_each(o, &m->object_list, link) {
if (o->creating) if (o->creating || o->removing)
continue; continue;
if (s->type != NULL && !s->type(o)) if (s->type != NULL && !s->type(o))
continue; continue;

View file

@ -575,6 +575,8 @@ static void registry_event_global_remove(void *object, uint32_t id)
if ((o = find_object(m, id)) == NULL) if ((o = find_object(m, id)) == NULL)
return; return;
o->this.removing = true;
manager_emit_removed(m, &o->this); manager_emit_removed(m, &o->this);
object_destroy(o); object_destroy(o);

View file

@ -84,6 +84,7 @@ struct pw_manager_object {
void *info; void *info;
struct spa_list param_list; struct spa_list param_list;
unsigned int creating:1; unsigned int creating:1;
unsigned int removing:1;
}; };
struct pw_manager *pw_manager_new(struct pw_core *core); struct pw_manager *pw_manager_new(struct pw_core *core);

View file

@ -139,6 +139,9 @@ struct client {
unsigned int disconnect:1; unsigned int disconnect:1;
unsigned int disconnecting:1; unsigned int disconnecting:1;
unsigned int need_flush:1; unsigned int need_flush:1;
struct pw_manager_object *prev_default_sink;
struct pw_manager_object *prev_default_source;
}; };
struct buffer_attr { struct buffer_attr {
@ -718,6 +721,41 @@ static uint32_t get_event_and_id(struct client *client, struct pw_manager_object
return event; return event;
} }
static struct pw_manager_object *find_device(struct client *client,
uint32_t id, const char *name, bool sink);
static void send_default_change_subscribe_event(struct client *client, bool sink, bool source)
{
struct pw_manager_object *def;
bool changed = false;
/* Send the subscribe event only if actually needed */
if (!(client->subscribed & SUBSCRIPTION_MASK_SERVER))
return;
if (sink) {
def = find_device(client, SPA_ID_INVALID, NULL, true);
if (client->prev_default_sink != def) {
client->prev_default_sink = def;
changed = true;
}
}
if (source) {
def = find_device(client, SPA_ID_INVALID, NULL, false);
if (client->prev_default_source != def) {
client->prev_default_source = def;
changed = true;
}
}
if (changed)
send_subscribe_event(client,
SUBSCRIPTION_EVENT_CHANGE |
SUBSCRIPTION_EVENT_SERVER,
-1);
}
static void handle_metadata_added(struct client *client, struct pw_manager_object *o, static void handle_metadata_added(struct client *client, struct pw_manager_object *o,
const char *name) const char *name)
{ {
@ -747,6 +785,9 @@ static void manager_added(void *data, struct pw_manager_object *o)
send_subscribe_event(client, send_subscribe_event(client,
event | SUBSCRIPTION_EVENT_NEW, event | SUBSCRIPTION_EVENT_NEW,
id); id);
/* Adding sinks etc. may also change defaults */
send_default_change_subscribe_event(client, object_is_sink(o), object_is_source_or_monitor(o));
} }
static void manager_updated(void *data, struct pw_manager_object *o) static void manager_updated(void *data, struct pw_manager_object *o)
@ -758,6 +799,8 @@ static void manager_updated(void *data, struct pw_manager_object *o)
send_subscribe_event(client, send_subscribe_event(client,
event | SUBSCRIPTION_EVENT_CHANGE, event | SUBSCRIPTION_EVENT_CHANGE,
id); id);
send_default_change_subscribe_event(client, object_is_sink(o), object_is_source_or_monitor(o));
} }
static void manager_removed(void *data, struct pw_manager_object *o) static void manager_removed(void *data, struct pw_manager_object *o)
@ -769,6 +812,8 @@ static void manager_removed(void *data, struct pw_manager_object *o)
send_subscribe_event(client, send_subscribe_event(client,
event | SUBSCRIPTION_EVENT_REMOVE, event | SUBSCRIPTION_EVENT_REMOVE,
id); id);
send_default_change_subscribe_event(client, object_is_sink(o), object_is_source_or_monitor(o));
} }
static void manager_metadata(void *data, struct pw_manager_object *o, static void manager_metadata(void *data, struct pw_manager_object *o,
@ -791,14 +836,8 @@ static void manager_metadata(void *data, struct pw_manager_object *o,
changed = client->default_source != val; changed = client->default_source != val;
client->default_source = val; client->default_source = val;
} }
if (changed) { if (changed)
if (client->subscribed & SUBSCRIPTION_MASK_SERVER) { send_default_change_subscribe_event(client, true, true);
send_subscribe_event(client,
SUBSCRIPTION_EVENT_CHANGE |
SUBSCRIPTION_EVENT_SERVER,
-1);
}
}
} }
if (subject == PW_ID_CORE && o == client->metadata_routes) { if (subject == PW_ID_CORE && o == client->metadata_routes) {
if (key == NULL) if (key == NULL)