jack: handle port registration events for jack clients

The jack client API expects the ports to unregister when a jack client is
deactivated and to register when it is activated. We use pause/resume
for deactivate/activate and don't really destroy the ports.

Track the state of the node (client) and emit port registration when it
changes state. Also make sure we don't emit a port registration when the
node is deactivated.

Fixes #3260
This commit is contained in:
Wim Taymans 2023-08-02 17:30:35 +02:00
parent fac2556404
commit da464853e5

View file

@ -137,6 +137,8 @@ struct object {
char node_name[512];
int32_t priority;
uint32_t client_id;
unsigned is_jack:1;
unsigned is_running:1;
} node;
struct {
uint32_t src;
@ -3061,6 +3063,35 @@ static const struct pw_proxy_events proxy_events = {
.destroy = proxy_destroy,
};
static void node_info(void *data, const struct pw_node_info *info)
{
struct object *n = data;
struct client *c = n->client;
pw_log_info("DSP node %d state change %s", info->id,
pw_node_state_as_string(info->state));
n->node.is_running = (info->state == PW_NODE_STATE_RUNNING);
if (info->change_mask & PW_NODE_CHANGE_MASK_STATE) {
struct object *p;
spa_list_for_each(p, &c->context.objects, link) {
if (p->type != INTERFACE_Port || p->removed ||
p->port.node_id != info->id)
continue;
if (n->node.is_running)
queue_notify(c, NOTIFY_TYPE_PORTREGISTRATION, p, 1, NULL);
else
queue_notify(c, NOTIFY_TYPE_PORTREGISTRATION, p, 0, NULL);
}
}
}
static const struct pw_node_events node_events = {
PW_VERSION_NODE,
.info = node_info,
};
static void port_param(void *data, int seq,
uint32_t id, uint32_t index, uint32_t next,
const struct spa_pod *param)
@ -3105,7 +3136,7 @@ static void registry_event_global(void *data, uint32_t id,
struct client *c = (struct client *) data;
struct object *o, *ot, *op;
const char *str;
bool is_first = true;
bool do_emit = true;
uint32_t serial;
if (props == NULL)
@ -3162,7 +3193,7 @@ static void registry_event_global(void *data, uint32_t id,
snprintf(o->node.name, sizeof(o->node.name), "%.*s-%d",
(int)(sizeof(tmp)-11), tmp, id);
} else {
is_first = ot == NULL;
do_emit = ot == NULL;
snprintf(o->node.name, sizeof(o->node.name), "%s", tmp);
}
if (id == c->node_id) {
@ -3174,9 +3205,21 @@ static void registry_event_global(void *data, uint32_t id,
if ((str = spa_dict_lookup(props, PW_KEY_PRIORITY_SESSION)) != NULL)
o->node.priority = pw_properties_parse_int(str);
if ((str = spa_dict_lookup(props, PW_KEY_CLIENT_API)) != NULL)
o->node.is_jack = spa_streq(str, "jack");
pw_log_debug("%p: add node %d", c, id);
if (o->node.is_jack) {
o->proxy = pw_registry_bind(c->registry,
id, type, PW_VERSION_NODE, 0);
if (o->proxy) {
pw_proxy_add_listener(o->proxy,
&o->proxy_listener, &proxy_events, o);
pw_proxy_add_object_listener(o->proxy,
&o->object_listener, &node_events, o);
}
}
pthread_mutex_lock(&c->context.lock);
spa_list_append(&c->context.objects, &o->link);
pthread_mutex_unlock(&c->context.lock);
@ -3255,6 +3298,8 @@ static void registry_event_global(void *data, uint32_t id,
o->port.latency[SPA_DIRECTION_INPUT] = SPA_LATENCY_INFO(SPA_DIRECTION_INPUT);
o->port.latency[SPA_DIRECTION_OUTPUT] = SPA_LATENCY_INFO(SPA_DIRECTION_OUTPUT);
do_emit = !ot->node.is_jack || ot->node.is_running;
o->proxy = pw_registry_bind(c->registry,
id, type, PW_VERSION_PORT, 0);
if (o->proxy) {
@ -3409,15 +3454,16 @@ static void registry_event_global(void *data, uint32_t id,
switch (o->type) {
case INTERFACE_Node:
if (is_first) {
pw_log_info("%p: client added \"%s\"", c, o->node.name);
pw_log_info("%p: client added \"%s\" emit:%d", c, o->node.name, do_emit);
if (do_emit)
queue_notify(c, NOTIFY_TYPE_REGISTRATION, o, 1, NULL);
}
break;
case INTERFACE_Port:
pw_log_info("%p: port added %u/%u \"%s\"", c, o->id, o->serial, o->port.name);
queue_notify(c, NOTIFY_TYPE_PORTREGISTRATION, o, 1, NULL);
pw_log_info("%p: port added %u/%u \"%s\" emit:%d", c, o->id,
o->serial, o->port.name, do_emit);
if (do_emit)
queue_notify(c, NOTIFY_TYPE_PORTREGISTRATION, o, 1, NULL);
break;
case INTERFACE_Link: