jack: improve registration callbacks

Pass the type to the alloc function to make things pretier.

Emit the client added only for the first client and the removed
callback for the last client. Things like pavucontrol will make
many nodes with the same name, which we map to the same client,
only when the last node is gone, we emit the client removed.
This commit is contained in:
Wim Taymans 2021-03-30 12:41:59 +02:00
parent dd6a18d576
commit c50c0b91c5

View file

@ -381,7 +381,7 @@ static void init_port_pool(struct client *c, enum spa_direction direction)
c->n_port_pool[direction] = 0;
}
static struct object * alloc_object(struct client *c)
static struct object * alloc_object(struct client *c, int type)
{
struct object *o;
int i;
@ -394,9 +394,10 @@ static struct object * alloc_object(struct client *c)
spa_list_append(&c->context.free_objects, &o[i].link);
}
o = spa_list_first(&c->context.free_objects, struct object, link);
spa_list_remove(&o->link);
o = spa_list_first(&c->context.free_objects, struct object, link);
spa_list_remove(&o->link);
o->client = c;
o->type = type;
return o;
}
@ -510,8 +511,7 @@ static struct port * alloc_port(struct client *c, enum spa_direction direction)
p = spa_list_first(&c->free_ports[direction], struct port, link);
spa_list_remove(&p->link);
o = alloc_object(c);
o->type = INTERFACE_Port;
o = alloc_object(c, INTERFACE_Port);
o->id = SPA_ID_INVALID;
o->port.node_id = c->node_id;
o->port.port_id = p->id;
@ -2161,8 +2161,8 @@ static void registry_event_global(void *data, uint32_t id,
struct client *c = (struct client *) data;
struct object *o, *ot, *op;
const char *str;
uint32_t object_type;
size_t size;
bool is_first = false;
if (props == NULL)
return;
@ -2171,8 +2171,7 @@ static void registry_event_global(void *data, uint32_t id,
const char *app, *node_name;
char tmp[JACK_CLIENT_NAME_SIZE+1];
o = alloc_object(c);
object_type = INTERFACE_Node;
o = alloc_object(c, INTERFACE_Node);
if ((str = spa_dict_lookup(props, PW_KEY_CLIENT_ID)) != NULL)
o->node.client_id = atoi(str);
@ -2212,11 +2211,13 @@ static void registry_event_global(void *data, uint32_t id,
filter_name(tmp, FILTER_NAME);
ot = find_node(c, tmp);
if (ot != NULL && o->node.client_id != ot->node.client_id)
if (ot != NULL && o->node.client_id != ot->node.client_id) {
snprintf(o->node.name, sizeof(o->node.name), "%.*s-%d",
(int)(sizeof(tmp)-11), tmp, id);
else
} else {
is_first = ot == NULL;
snprintf(o->node.name, sizeof(o->node.name), "%s", tmp);
}
if ((str = spa_dict_lookup(props, PW_KEY_PRIORITY_DRIVER)) != NULL)
o->node.priority = pw_properties_parse_int(str);
@ -2235,7 +2236,6 @@ static void registry_event_global(void *data, uint32_t id,
bool is_monitor = false;
char tmp[REAL_JACK_PORT_NAME_SIZE+1];
object_type = INTERFACE_Port;
if ((str = spa_dict_lookup(props, PW_KEY_FORMAT_DSP)) == NULL)
str = "other";
if ((type_id = string_to_type(str)) == SPA_ID_INVALID)
@ -2285,7 +2285,7 @@ static void registry_event_global(void *data, uint32_t id,
pw_log_debug(NAME" %p: %s found our port %p", c, tmp, o);
}
if (o == NULL) {
o = alloc_object(c);
o = alloc_object(c, INTERFACE_Port);
if (o == NULL)
goto exit;
@ -2339,8 +2339,7 @@ static void registry_event_global(void *data, uint32_t id,
o->port.name, type_id);
}
else if (strcmp(type, PW_TYPE_INTERFACE_Link) == 0) {
o = alloc_object(c);
object_type = INTERFACE_Link;
o = alloc_object(c, INTERFACE_Link);
pthread_mutex_lock(&c->context.lock);
spa_list_append(&c->context.links, &o->link);
@ -2380,7 +2379,6 @@ static void registry_event_global(void *data, uint32_t id,
goto exit;
}
o->type = object_type;
o->id = id;
pthread_mutex_lock(&c->context.lock);
@ -2394,7 +2392,7 @@ static void registry_event_global(void *data, uint32_t id,
switch (o->type) {
case INTERFACE_Node:
if (c->registration_callback)
if (c->registration_callback && is_first)
c->registration_callback(o->node.name, 1, c->registration_arg);
break;
@ -2421,15 +2419,26 @@ static void registry_event_global_remove(void *object, uint32_t id)
{
struct client *c = (struct client *) object;
struct object *o;
bool is_last = false;
pw_log_debug(NAME" %p: removed: %u", c, id);
pthread_mutex_lock(&c->context.lock);
o = pw_map_lookup(&c->context.globals, id);
if (o != NULL)
spa_list_remove(&o->link);
pthread_mutex_unlock(&c->context.lock);
if (o == NULL)
return;
/* JACK clients expect the objects to hang around after
* they are unregistered. We keep the memory around for that
* reason but reuse it when we can. */
spa_list_append(&c->context.free_objects, &o->link);
if (o->type == INTERFACE_Node)
is_last = find_node(c, o->node.name) == NULL;
pw_thread_loop_unlock(c->context.loop);
switch (o->type) {
@ -2440,7 +2449,7 @@ static void registry_event_global_remove(void *object, uint32_t id)
if (strcmp(o->node.node_name, c->metadata->default_audio_source) == 0)
c->metadata->default_audio_source[0] = '\0';
}
if (c->registration_callback)
if (c->registration_callback && is_last)
c->registration_callback(o->node.name, 0, c->registration_arg);
break;
case INTERFACE_Port:
@ -2454,12 +2463,12 @@ static void registry_event_global_remove(void *object, uint32_t id)
}
pw_thread_loop_lock(c->context.loop);
/* JACK clients expect the objects to hang around after
* they are unregistered. We keep them in the map but reuse the
* object when we can
/* we keep the object available with the id because jack clients
* tend to access the objects with it later.
*
* pw_map_insert_at(&c->context.globals, id, NULL);
**/
free_object(c, o);
*/
return;
}