mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	jack: move more stuff to nodes and ports
Improve cleanup and registration of jack clients
This commit is contained in:
		
							parent
							
								
									5e593563af
								
							
						
					
					
						commit
						27f811d726
					
				
					 6 changed files with 784 additions and 385 deletions
				
			
		| 
						 | 
				
			
			@ -95,11 +95,31 @@ struct impl {
 | 
			
		|||
 | 
			
		||||
struct client {
 | 
			
		||||
	struct impl *impl;
 | 
			
		||||
 | 
			
		||||
	struct spa_list link;
 | 
			
		||||
 | 
			
		||||
	struct pw_client *client;
 | 
			
		||||
	struct spa_hook client_listener;
 | 
			
		||||
 | 
			
		||||
	int fd;
 | 
			
		||||
	struct spa_source *source;
 | 
			
		||||
 | 
			
		||||
	struct spa_list jack_clients;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct port {
 | 
			
		||||
	struct impl *impl;
 | 
			
		||||
	struct pw_jack_port *port;
 | 
			
		||||
	struct spa_hook port_listener;
 | 
			
		||||
	struct jack_client *jc;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct link {
 | 
			
		||||
	struct impl *impl;
 | 
			
		||||
	struct pw_link *link;
 | 
			
		||||
	struct pw_jack_port *out_port;
 | 
			
		||||
	struct pw_jack_port *in_port;
 | 
			
		||||
	struct spa_hook link_listener;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static bool init_socket_name(struct sockaddr_un *addr, const char *name, bool promiscuous, int which)
 | 
			
		||||
| 
						 | 
				
			
			@ -135,11 +155,11 @@ notify_client(struct jack_client *client, int ref_num, const char *name, int not
 | 
			
		|||
	char _name[JACK_CLIENT_NAME_SIZE+1];
 | 
			
		||||
	char _message[JACK_MESSAGE_SIZE+1];
 | 
			
		||||
 | 
			
		||||
	if (client->fd == 0)
 | 
			
		||||
	if (client->fd == -1)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (name == NULL)
 | 
			
		||||
		name = client->control->name;
 | 
			
		||||
		name = client->node->control->name;
 | 
			
		||||
 | 
			
		||||
	snprintf(_name, sizeof(_name), "%s", name);
 | 
			
		||||
        snprintf(_message, sizeof(_message), "%s", message);
 | 
			
		||||
| 
						 | 
				
			
			@ -173,17 +193,33 @@ notify_add_client(struct impl *impl, struct jack_client *client, const char *nam
 | 
			
		|||
		if (c == NULL || c == client)
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		n = c->control->name;
 | 
			
		||||
		if (notify_client(c, ref_num, name, jack_notify_AddClient, false, "", 0, 0) < 0) {
 | 
			
		||||
			pw_log_warn("module-jack %p: can't notify client", impl);
 | 
			
		||||
		}
 | 
			
		||||
		n = c->node->control->name;
 | 
			
		||||
		if (notify_client(c, ref_num, name, jack_notify_AddClient, false, "", 0, 0) < 0)
 | 
			
		||||
			pw_log_warn("module-jack %p: can't notify add client", impl);
 | 
			
		||||
 | 
			
		||||
		if (notify_client(client, i, n, jack_notify_AddClient, true, "", 0, 0) < 0) {
 | 
			
		||||
			pw_log_error("module-jack %p: can't notify client", impl);
 | 
			
		||||
			pw_log_error("module-jack %p: can't notify add client", impl);
 | 
			
		||||
			return -1;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
static int
 | 
			
		||||
notify_remove_client(struct impl *impl, const char *name, int ref_num)
 | 
			
		||||
{
 | 
			
		||||
	struct jack_server *server = &impl->server;
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < CLIENT_NUM; i++) {
 | 
			
		||||
		struct jack_client *c = server->client_table[i];
 | 
			
		||||
 | 
			
		||||
		if (c == NULL)
 | 
			
		||||
			continue;
 | 
			
		||||
                if (notify_client(c, ref_num, name, jack_notify_RemoveClient, false, "", 0, 0) < 0)
 | 
			
		||||
			pw_log_warn("module-jack %p: can't notify remove client", impl);
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
notify_clients(struct impl *impl, int notify,
 | 
			
		||||
| 
						 | 
				
			
			@ -201,34 +237,39 @@ notify_clients(struct impl *impl, int notify,
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int process_messages(struct client *client);
 | 
			
		||||
 | 
			
		||||
static void client_destroy(void *data)
 | 
			
		||||
static void port_destroy(void *data)
 | 
			
		||||
{
 | 
			
		||||
	struct client *this = data;
 | 
			
		||||
	struct pw_jack_port *port = data;
 | 
			
		||||
	struct port *p = port->user_data;
 | 
			
		||||
	struct impl *impl = p->impl;
 | 
			
		||||
 | 
			
		||||
	pw_loop_destroy_source(pw_core_get_main_loop(this->impl->core), this->source);
 | 
			
		||||
	spa_list_remove(&this->link);
 | 
			
		||||
	pw_log_debug("port %p: destroy", port);
 | 
			
		||||
 | 
			
		||||
	close(this->fd);
 | 
			
		||||
	notify_clients(impl, jack_notify_PortRegistrationOffCallback, false, "", port->port_id, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct pw_jack_port_events port_listener = {
 | 
			
		||||
	PW_VERSION_JACK_PORT_EVENTS,
 | 
			
		||||
	.destroy = port_destroy,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static int process_messages(struct client *client);
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
handle_register_port(struct client *client)
 | 
			
		||||
{
 | 
			
		||||
	struct impl *impl = client->impl;
 | 
			
		||||
	struct jack_server *server = &impl->server;
 | 
			
		||||
	struct jack_graph_manager *mgr = server->graph_manager;
 | 
			
		||||
	struct jack_connection_manager *conn;
 | 
			
		||||
	int result = 0;
 | 
			
		||||
	int result = -1;
 | 
			
		||||
	int ref_num;
 | 
			
		||||
	char name[JACK_PORT_NAME_SIZE + 1];
 | 
			
		||||
	char port_type[JACK_PORT_TYPE_SIZE + 1];
 | 
			
		||||
	unsigned int flags;
 | 
			
		||||
	unsigned int buffer_size;
 | 
			
		||||
	static jack_port_id_t port_index = 0;
 | 
			
		||||
	jack_port_type_id_t type_id;
 | 
			
		||||
	struct jack_client *jc;
 | 
			
		||||
	struct pw_jack_port *port;
 | 
			
		||||
	struct port *p;
 | 
			
		||||
 | 
			
		||||
	CheckSize(kRegisterPort_size);
 | 
			
		||||
	CheckRead(&ref_num, sizeof(int));
 | 
			
		||||
| 
						 | 
				
			
			@ -240,44 +281,25 @@ handle_register_port(struct client *client)
 | 
			
		|||
	pw_log_debug("protocol-jack %p: kRegisterPort %d %s %s %u %u", impl,
 | 
			
		||||
			ref_num, name, port_type, flags, buffer_size);
 | 
			
		||||
 | 
			
		||||
	type_id = jack_port_get_type_id(port_type);
 | 
			
		||||
 | 
			
		||||
	if (jack_graph_manager_find_port(mgr, name) != NO_PORT) {
 | 
			
		||||
		pw_log_error("protocol-jack %p: port_name %s exists", impl, name);
 | 
			
		||||
		result = -1;
 | 
			
		||||
		goto reply;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	port_index = jack_graph_manager_allocate_port(mgr, ref_num, name, type_id, flags);
 | 
			
		||||
	if (port_index == NO_PORT) {
 | 
			
		||||
		pw_log_error("protocol-jack %p: failed to create port name %s", impl, name);
 | 
			
		||||
		result = -1;
 | 
			
		||||
		goto reply;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	jc = server->client_table[ref_num];
 | 
			
		||||
	pw_jack_node_add_port(jc->node,
 | 
			
		||||
			      flags & JackPortIsInput ?
 | 
			
		||||
				PW_DIRECTION_INPUT :
 | 
			
		||||
				PW_DIRECTION_OUTPUT,
 | 
			
		||||
			      port_index);
 | 
			
		||||
 | 
			
		||||
	conn = jack_graph_manager_next_start(mgr);
 | 
			
		||||
 | 
			
		||||
	if (jack_connection_manager_add_port(conn, (flags & JackPortIsInput) ? true : false,
 | 
			
		||||
					     ref_num, port_index) < 0) {
 | 
			
		||||
		pw_log_error("protocol-jack %p: failed to add port", impl);
 | 
			
		||||
		jack_graph_manager_release_port(mgr, port_index);
 | 
			
		||||
		result = -1;
 | 
			
		||||
		goto reply_stop;
 | 
			
		||||
	port = pw_jack_node_add_port(jc->node, name, port_type, flags, sizeof(struct port));
 | 
			
		||||
	if (port == NULL) {
 | 
			
		||||
		pw_log_error("module-jack %p: can't add port", impl);
 | 
			
		||||
		goto reply;
 | 
			
		||||
	}
 | 
			
		||||
	p = port->user_data;
 | 
			
		||||
	p->impl = impl;
 | 
			
		||||
	p->jc = jc;
 | 
			
		||||
	port_index = port->port_id;
 | 
			
		||||
 | 
			
		||||
      reply_stop:
 | 
			
		||||
	jack_graph_manager_next_stop(mgr);
 | 
			
		||||
	pw_jack_port_add_listener(port, &p->port_listener, &port_listener, port);
 | 
			
		||||
 | 
			
		||||
	if (jc->control->active)
 | 
			
		||||
	if (jc->node->control->active)
 | 
			
		||||
		notify_clients(impl, jack_notify_PortRegistrationOnCallback, false, "", port_index, 0);
 | 
			
		||||
 | 
			
		||||
	result = 0;
 | 
			
		||||
 | 
			
		||||
      reply:
 | 
			
		||||
	CheckWrite(&result, sizeof(int));
 | 
			
		||||
	CheckWrite(&port_index, sizeof(jack_port_id_t));
 | 
			
		||||
| 
						 | 
				
			
			@ -291,9 +313,11 @@ handle_activate_client(struct client *client)
 | 
			
		|||
	struct jack_server *server = &impl->server;
 | 
			
		||||
	struct jack_graph_manager *mgr = server->graph_manager;
 | 
			
		||||
	struct jack_connection_manager *conn;
 | 
			
		||||
	int result = 0;
 | 
			
		||||
	int ref_num;
 | 
			
		||||
	struct jack_client *jc;
 | 
			
		||||
	int result = 0, ref_num, i;
 | 
			
		||||
	int is_real_time;
 | 
			
		||||
	jack_int_t input_ports[PORT_NUM_FOR_CLIENT];
 | 
			
		||||
        jack_int_t output_ports[PORT_NUM_FOR_CLIENT];
 | 
			
		||||
 | 
			
		||||
	CheckSize(kActivateClient_size);
 | 
			
		||||
	CheckRead(&ref_num, sizeof(int));
 | 
			
		||||
| 
						 | 
				
			
			@ -307,34 +331,38 @@ handle_activate_client(struct client *client)
 | 
			
		|||
	jack_connection_manager_direct_connect(conn, server->freewheel_ref_num, ref_num);
 | 
			
		||||
	jack_connection_manager_direct_connect(conn, ref_num, server->freewheel_ref_num);
 | 
			
		||||
 | 
			
		||||
	memcpy (input_ports, jack_connection_manager_get_inputs(conn, ref_num), sizeof(input_ports));
 | 
			
		||||
	memcpy (output_ports, jack_connection_manager_get_outputs(conn, ref_num), sizeof(input_ports));
 | 
			
		||||
 | 
			
		||||
	jack_graph_manager_next_stop(mgr);
 | 
			
		||||
 | 
			
		||||
	notify_clients(impl, jack_notify_ActivateClient, true, "", 0, 0);
 | 
			
		||||
	for (i = 0; (i < PORT_NUM_FOR_CLIENT) && (input_ports[i] != EMPTY); i++)
 | 
			
		||||
		notify_clients(impl, jack_notify_PortRegistrationOnCallback, false, "", input_ports[i], 0);
 | 
			
		||||
	for (i = 0; (i < PORT_NUM_FOR_CLIENT) && (output_ports[i] != EMPTY); i++)
 | 
			
		||||
		notify_clients(impl, jack_notify_PortRegistrationOnCallback, false, "", output_ports[i], 0);
 | 
			
		||||
 | 
			
		||||
	jc = server->client_table[ref_num];
 | 
			
		||||
	if (jc)
 | 
			
		||||
		notify_client(jc, ref_num, NULL, jack_notify_ActivateClient, true, "", 0, 0);
 | 
			
		||||
 | 
			
		||||
	CheckWrite(&result, sizeof(int));
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
handle_deactivate_client(struct client *client)
 | 
			
		||||
static int client_deactivate(struct impl *impl, int ref_num)
 | 
			
		||||
{
 | 
			
		||||
	struct impl *impl = client->impl;
 | 
			
		||||
	struct jack_server *server = &impl->server;
 | 
			
		||||
	int fw_ref = server->freewheel_ref_num, i;
 | 
			
		||||
	struct jack_graph_manager *mgr = server->graph_manager;
 | 
			
		||||
	struct jack_connection_manager *conn;
 | 
			
		||||
	int result = 0;
 | 
			
		||||
	int ref_num, fw_ref;
 | 
			
		||||
 | 
			
		||||
	CheckSize(kDeactivateClient_size);
 | 
			
		||||
	CheckRead(&ref_num, sizeof(int));
 | 
			
		||||
 | 
			
		||||
	pw_log_debug("protocol-jack %p: kDeactivateClient %d", client->impl,
 | 
			
		||||
			ref_num);
 | 
			
		||||
 | 
			
		||||
	fw_ref = server->freewheel_ref_num;
 | 
			
		||||
	jack_int_t input_ports[PORT_NUM_FOR_CLIENT];
 | 
			
		||||
        jack_int_t output_ports[PORT_NUM_FOR_CLIENT];
 | 
			
		||||
 | 
			
		||||
	conn = jack_graph_manager_next_start(mgr);
 | 
			
		||||
 | 
			
		||||
	memcpy (input_ports, jack_connection_manager_get_inputs(conn, ref_num), sizeof(input_ports));
 | 
			
		||||
	memcpy (output_ports, jack_connection_manager_get_outputs(conn, ref_num), sizeof(input_ports));
 | 
			
		||||
 | 
			
		||||
	if (jack_connection_manager_is_direct_connection(conn, fw_ref, ref_num))
 | 
			
		||||
		jack_connection_manager_direct_disconnect(conn, fw_ref, ref_num);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -343,6 +371,29 @@ handle_deactivate_client(struct client *client)
 | 
			
		|||
 | 
			
		||||
	jack_graph_manager_next_stop(mgr);
 | 
			
		||||
 | 
			
		||||
	for (i = 0; (i < PORT_NUM_FOR_CLIENT) && (input_ports[i] != EMPTY); i++)
 | 
			
		||||
		notify_clients(impl, jack_notify_PortRegistrationOffCallback, false, "", input_ports[i], 0);
 | 
			
		||||
	for (i = 0; (i < PORT_NUM_FOR_CLIENT) && (output_ports[i] != EMPTY); i++)
 | 
			
		||||
		notify_clients(impl, jack_notify_PortRegistrationOffCallback, false, "", output_ports[i], 0);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
handle_deactivate_client(struct client *client)
 | 
			
		||||
{
 | 
			
		||||
	struct impl *impl = client->impl;
 | 
			
		||||
	int result = 0;
 | 
			
		||||
	int ref_num;
 | 
			
		||||
 | 
			
		||||
	CheckSize(kDeactivateClient_size);
 | 
			
		||||
	CheckRead(&ref_num, sizeof(int));
 | 
			
		||||
 | 
			
		||||
	pw_log_debug("protocol-jack %p: kDeactivateClient %d", client->impl,
 | 
			
		||||
			ref_num);
 | 
			
		||||
 | 
			
		||||
	result = client_deactivate(impl, ref_num);
 | 
			
		||||
 | 
			
		||||
	CheckWrite(&result, sizeof(int));
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -388,44 +439,84 @@ handle_client_check(struct client *client)
 | 
			
		|||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void node_destroy(void *data)
 | 
			
		||||
{
 | 
			
		||||
	struct jack_client *jc = data;
 | 
			
		||||
	struct impl *impl = jc->data;
 | 
			
		||||
	struct jack_server *server = &impl->server;
 | 
			
		||||
	int ref_num = jc->node->control->ref_num;
 | 
			
		||||
 | 
			
		||||
	pw_log_debug("module-jack %p: jack_client %p destroy", impl, jc);
 | 
			
		||||
 | 
			
		||||
	client_deactivate(impl, ref_num);
 | 
			
		||||
 | 
			
		||||
	spa_list_remove(&jc->client_link);
 | 
			
		||||
	spa_list_remove(&jc->node->graph_link);
 | 
			
		||||
 | 
			
		||||
	jack_server_free_ref_num(server, ref_num);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void node_free(void *data)
 | 
			
		||||
{
 | 
			
		||||
	struct jack_client *jc = data;
 | 
			
		||||
	struct impl *impl = jc->data;
 | 
			
		||||
	struct jack_server *server = &impl->server;
 | 
			
		||||
	int ref_num = jc->node->control->ref_num;
 | 
			
		||||
 | 
			
		||||
	notify_remove_client(impl, jc->node->control->name, ref_num);
 | 
			
		||||
 | 
			
		||||
	jack_synchro_close(&server->synchro_table[ref_num]);
 | 
			
		||||
	if (jc->fd != -1)
 | 
			
		||||
		close(jc->fd);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct pw_jack_node_events node_events = {
 | 
			
		||||
	PW_VERSION_JACK_NODE_EVENTS,
 | 
			
		||||
	.destroy = node_destroy,
 | 
			
		||||
	.free = node_free,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
handle_client_open(struct client *client)
 | 
			
		||||
{
 | 
			
		||||
	struct impl *impl = client->impl;
 | 
			
		||||
	struct jack_server *server = &impl->server;
 | 
			
		||||
	struct jack_graph_manager *mgr = server->graph_manager;
 | 
			
		||||
	struct jack_connection_manager *conn;
 | 
			
		||||
	int PID, UUID;
 | 
			
		||||
	char name[JACK_CLIENT_NAME_SIZE+1];
 | 
			
		||||
	int result = -1, ref_num, shared_engine, shared_client, shared_graph;
 | 
			
		||||
	struct jack_client *jc;
 | 
			
		||||
	const struct ucred *ucred;
 | 
			
		||||
	struct sockaddr_un addr;
 | 
			
		||||
	struct pw_jack_node *node;
 | 
			
		||||
 | 
			
		||||
	CheckSize(kClientOpen_size);
 | 
			
		||||
	CheckRead(&PID, sizeof(int));
 | 
			
		||||
	CheckRead(&UUID, sizeof(int));
 | 
			
		||||
	CheckRead(name, sizeof(name));
 | 
			
		||||
 | 
			
		||||
	ref_num = jack_server_allocate_ref_num(server);
 | 
			
		||||
	if (ref_num == -1) {
 | 
			
		||||
		pw_log_error("module-jack %p: can't allocated ref_num", impl);
 | 
			
		||||
	ucred = pw_client_get_ucred(client->client);
 | 
			
		||||
 | 
			
		||||
	node = pw_jack_node_new(impl->core,
 | 
			
		||||
				pw_module_get_global(impl->module),
 | 
			
		||||
				server,
 | 
			
		||||
				name,
 | 
			
		||||
				ucred ? ucred->pid : PID,
 | 
			
		||||
				NULL,
 | 
			
		||||
				sizeof(struct jack_client));
 | 
			
		||||
	if (node == NULL) {
 | 
			
		||||
		pw_log_error("module-jack %p: can't create node", impl);
 | 
			
		||||
		goto reply;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	jc = calloc(1,sizeof(struct jack_client));
 | 
			
		||||
	ref_num = node->control->ref_num;
 | 
			
		||||
 | 
			
		||||
	jc = node->user_data;
 | 
			
		||||
	jc->fd = -1;
 | 
			
		||||
	jc->data = impl;
 | 
			
		||||
	jc->owner = client;
 | 
			
		||||
	jc->ref_num = ref_num;
 | 
			
		||||
	jc->node = node;
 | 
			
		||||
 | 
			
		||||
	if (jack_synchro_init(&server->synchro_table[ref_num],
 | 
			
		||||
			      name,
 | 
			
		||||
			      server->engine_control->server_name,
 | 
			
		||||
			      0,
 | 
			
		||||
			      false,
 | 
			
		||||
			      server->promiscuous) < 0) {
 | 
			
		||||
		pw_log_error("module-jack %p: can't init synchro", impl);
 | 
			
		||||
		goto reply;
 | 
			
		||||
	}
 | 
			
		||||
	pw_jack_node_add_listener(node, &jc->node_listener, &node_events, jc);
 | 
			
		||||
 | 
			
		||||
	if ((jc->fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
 | 
			
		||||
		pw_log_error("module-jack %p: can't create socket %s", impl, strerror(errno));
 | 
			
		||||
| 
						 | 
				
			
			@ -440,33 +531,19 @@ handle_client_open(struct client *client)
 | 
			
		|||
		goto reply;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ucred = pw_client_get_ucred(client->client);
 | 
			
		||||
 | 
			
		||||
	jc->control = jack_client_control_alloc(name, ucred ? ucred->pid : 0, ref_num, -1);
 | 
			
		||||
	if (jc->control == NULL) {
 | 
			
		||||
		pw_log_error("module-jack %p: can't create control", impl);
 | 
			
		||||
		goto reply;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	server->client_table[ref_num] = jc;
 | 
			
		||||
	pw_log_debug("module-jack %p: Added client %d \"%s\"", impl, ref_num, name);
 | 
			
		||||
 | 
			
		||||
	conn = jack_graph_manager_next_start(mgr);
 | 
			
		||||
	jack_connection_manager_init_ref_num(conn, ref_num);
 | 
			
		||||
	jack_graph_manager_next_stop(mgr);
 | 
			
		||||
 | 
			
		||||
	jc->node = pw_jack_node_new(impl->core, pw_module_get_global(impl->module),
 | 
			
		||||
				    server, ref_num, NULL);
 | 
			
		||||
	spa_list_append(&client->jack_clients, &jc->client_link);
 | 
			
		||||
	spa_list_append(&impl->rt.nodes, &jc->node->graph_link);
 | 
			
		||||
 | 
			
		||||
	if (notify_add_client(impl, jc, name, ref_num) < 0) {
 | 
			
		||||
		pw_log_error("module-jack %p: can't notify add_client", impl);
 | 
			
		||||
		goto reply;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	spa_list_append(&impl->rt.nodes, &jc->node->graph_link);
 | 
			
		||||
 | 
			
		||||
	shared_engine = impl->server.engine_control->info.index;
 | 
			
		||||
	shared_client = jc->control->info.index;
 | 
			
		||||
	shared_client = jc->node->control->info.index;
 | 
			
		||||
	shared_graph = impl->server.graph_manager->info.index;
 | 
			
		||||
 | 
			
		||||
	result = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -488,10 +565,38 @@ handle_client_close(struct client *client)
 | 
			
		|||
	CheckRead(&ref_num, sizeof(int));
 | 
			
		||||
	int result = 0;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	CheckWrite(&result, sizeof(int));
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void link_destroy(void *data)
 | 
			
		||||
{
 | 
			
		||||
	struct link *ld = data;
 | 
			
		||||
	struct impl *impl = ld->impl;
 | 
			
		||||
	struct pw_jack_port *out_port = ld->out_port, *in_port = ld->in_port;
 | 
			
		||||
	struct jack_server *server = &impl->server;
 | 
			
		||||
	struct jack_graph_manager *mgr = server->graph_manager;
 | 
			
		||||
	struct jack_connection_manager *conn;
 | 
			
		||||
	jack_port_id_t src_id = out_port->port_id, dst_id = in_port->port_id;
 | 
			
		||||
 | 
			
		||||
	pw_log_debug("module-jack %p: link %p destroy", impl, ld->link);
 | 
			
		||||
 | 
			
		||||
	conn = jack_graph_manager_next_start(mgr);
 | 
			
		||||
	if (jack_connection_manager_disconnect_ports(conn, src_id, dst_id)) {
 | 
			
		||||
		pw_log_warn("module-jack %p: ports can't disconnect", impl);
 | 
			
		||||
	}
 | 
			
		||||
	jack_graph_manager_next_stop(mgr);
 | 
			
		||||
 | 
			
		||||
	notify_clients(impl, jack_notify_PortDisconnectCallback, false, "", src_id, dst_id);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct pw_link_events link_events = {
 | 
			
		||||
	PW_VERSION_LINK_EVENTS,
 | 
			
		||||
	.destroy = link_destroy,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
handle_connect_name_ports(struct client *client)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -506,8 +611,9 @@ handle_connect_name_ports(struct client *client)
 | 
			
		|||
	int result = -1, in_ref, out_ref;
 | 
			
		||||
	jack_port_id_t src_id, dst_id;
 | 
			
		||||
	struct jack_port *src_port, *dst_port;
 | 
			
		||||
	struct pw_port *out_port, *in_port;
 | 
			
		||||
	struct pw_jack_port *out_port, *in_port;
 | 
			
		||||
	struct pw_link *link;
 | 
			
		||||
	struct link *ld;
 | 
			
		||||
 | 
			
		||||
	CheckSize(kConnectNamePorts_size);
 | 
			
		||||
	CheckRead(&ref_num, sizeof(int));
 | 
			
		||||
| 
						 | 
				
			
			@ -557,7 +663,7 @@ handle_connect_name_ports(struct client *client)
 | 
			
		|||
		pw_log_error("protocol-jack %p: unknown client %d", impl, out_ref);
 | 
			
		||||
		goto reply_stop;
 | 
			
		||||
	}
 | 
			
		||||
	if (!jc->control->active) {
 | 
			
		||||
	if (!jc->node->control->active) {
 | 
			
		||||
		pw_log_error("protocol-jack %p: can't connect ports of inactive client", impl);
 | 
			
		||||
		goto reply_stop;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -572,39 +678,32 @@ handle_connect_name_ports(struct client *client)
 | 
			
		|||
		pw_log_error("protocol-jack %p: unknown client %d", impl, in_ref);
 | 
			
		||||
		goto reply_stop;
 | 
			
		||||
	}
 | 
			
		||||
	if (!jc->control->active) {
 | 
			
		||||
	if (!jc->node->control->active) {
 | 
			
		||||
		pw_log_error("protocol-jack %p: can't connect ports of inactive client", impl);
 | 
			
		||||
		goto reply_stop;
 | 
			
		||||
	}
 | 
			
		||||
	in_port = pw_jack_node_find_port(jc->node, PW_DIRECTION_INPUT, dst_id);
 | 
			
		||||
 | 
			
		||||
	if (jack_connection_manager_is_connected(conn, src_id, dst_id)) {
 | 
			
		||||
		pw_log_error("protocol-jack %p: ports are already connected", impl);
 | 
			
		||||
	if (jack_connection_manager_connect_ports(conn, src_id, dst_id)) {
 | 
			
		||||
		pw_log_error("protocol-jack %p: ports can't connect", impl);
 | 
			
		||||
		goto reply_stop;
 | 
			
		||||
	}
 | 
			
		||||
	if (jack_connection_manager_connect(conn, src_id, dst_id) < 0) {
 | 
			
		||||
		pw_log_error("protocol-jack %p: connection table is full", impl);
 | 
			
		||||
		goto reply_stop;
 | 
			
		||||
	}
 | 
			
		||||
	if (jack_connection_manager_connect(conn, dst_id, src_id) < 0) {
 | 
			
		||||
		pw_log_error("protocol-jack %p: connection table is full", impl);
 | 
			
		||||
		goto reply_stop;
 | 
			
		||||
	}
 | 
			
		||||
	if (jack_connection_manager_is_loop_path(conn, src_id, dst_id) < 0)
 | 
			
		||||
		jack_connection_manager_inc_feedback_connection(conn, src_id, dst_id);
 | 
			
		||||
	else
 | 
			
		||||
		jack_connection_manager_inc_direct_connection(conn, src_id, dst_id);
 | 
			
		||||
 | 
			
		||||
	pw_log_debug("%p %p", out_port, in_port);
 | 
			
		||||
	pw_log_debug("protocol-jack %p: connected ports %p %p", impl, out_port, in_port);
 | 
			
		||||
 | 
			
		||||
	link = pw_link_new(impl->core,
 | 
			
		||||
			   pw_module_get_global(impl->module),
 | 
			
		||||
			   out_port,
 | 
			
		||||
			   in_port,
 | 
			
		||||
			   out_port->port,
 | 
			
		||||
			   in_port->port,
 | 
			
		||||
			   NULL,
 | 
			
		||||
			   NULL,
 | 
			
		||||
			   NULL,
 | 
			
		||||
			   0);
 | 
			
		||||
			   sizeof(struct link));
 | 
			
		||||
	ld = pw_link_get_user_data(link);
 | 
			
		||||
	ld->impl = impl;
 | 
			
		||||
	ld->link = link;
 | 
			
		||||
	ld->out_port = out_port;
 | 
			
		||||
	ld->in_port = in_port;
 | 
			
		||||
	pw_link_add_listener(link, &ld->link_listener, &link_events, ld);
 | 
			
		||||
	pw_link_activate(link);
 | 
			
		||||
 | 
			
		||||
	notify_clients(impl, jack_notify_PortConnectCallback, false, "", src_id, dst_id);
 | 
			
		||||
| 
						 | 
				
			
			@ -736,6 +835,17 @@ client_busy_changed(void *data, bool busy)
 | 
			
		|||
		process_messages(c);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void client_killed(struct client *client)
 | 
			
		||||
{
 | 
			
		||||
	struct jack_client *jc;
 | 
			
		||||
 | 
			
		||||
	spa_list_for_each(jc, &client->jack_clients, client_link) {
 | 
			
		||||
		close(jc->fd);
 | 
			
		||||
		jc->fd = -1;
 | 
			
		||||
	}
 | 
			
		||||
	pw_client_destroy(client->client);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
connection_data(void *data, int fd, enum spa_io mask)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -743,7 +853,7 @@ connection_data(void *data, int fd, enum spa_io mask)
 | 
			
		|||
 | 
			
		||||
	if (mask & (SPA_IO_ERR | SPA_IO_HUP)) {
 | 
			
		||||
		pw_log_error("protocol-native %p: got connection error", client->impl);
 | 
			
		||||
		pw_client_destroy(client->client);
 | 
			
		||||
		client_killed(client);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -751,6 +861,20 @@ connection_data(void *data, int fd, enum spa_io mask)
 | 
			
		|||
		process_messages(client);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void client_destroy(void *data)
 | 
			
		||||
{
 | 
			
		||||
	struct client *this = data;
 | 
			
		||||
	struct jack_client *jc, *t;
 | 
			
		||||
 | 
			
		||||
	pw_loop_destroy_source(pw_core_get_main_loop(this->impl->core), this->source);
 | 
			
		||||
	spa_list_remove(&this->link);
 | 
			
		||||
 | 
			
		||||
	spa_list_for_each_safe(jc, t, &this->jack_clients, client_link)
 | 
			
		||||
		pw_jack_node_destroy(jc->node);
 | 
			
		||||
 | 
			
		||||
	close(this->fd);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct pw_client_events client_events = {
 | 
			
		||||
	PW_VERSION_CLIENT_EVENTS,
 | 
			
		||||
	.destroy = client_destroy,
 | 
			
		||||
| 
						 | 
				
			
			@ -778,6 +902,7 @@ static struct client *client_new(struct impl *impl, int fd)
 | 
			
		|||
		goto no_client;
 | 
			
		||||
 | 
			
		||||
	this = pw_client_get_user_data(client);
 | 
			
		||||
	this->client = client;
 | 
			
		||||
	this->impl = impl;
 | 
			
		||||
	this->fd = fd;
 | 
			
		||||
	this->source = pw_loop_add_io(pw_core_get_main_loop(impl->core),
 | 
			
		||||
| 
						 | 
				
			
			@ -786,8 +911,7 @@ static struct client *client_new(struct impl *impl, int fd)
 | 
			
		|||
	if (this->source == NULL)
 | 
			
		||||
		goto no_source;
 | 
			
		||||
 | 
			
		||||
	this->client = client;
 | 
			
		||||
 | 
			
		||||
	spa_list_init(&this->jack_clients);
 | 
			
		||||
	spa_list_insert(impl->client_list.prev, &this->link);
 | 
			
		||||
 | 
			
		||||
	pw_client_add_listener(client, &this->client_listener, &client_events, this);
 | 
			
		||||
| 
						 | 
				
			
			@ -894,63 +1018,35 @@ static int
 | 
			
		|||
make_audio_client(struct impl *impl)
 | 
			
		||||
{
 | 
			
		||||
	struct jack_server *server = &impl->server;
 | 
			
		||||
	struct jack_graph_manager *mgr = server->graph_manager;
 | 
			
		||||
	struct jack_connection_manager *conn;
 | 
			
		||||
	int ref_num;
 | 
			
		||||
	struct jack_client *jc;
 | 
			
		||||
	jack_port_id_t port_id;
 | 
			
		||||
	struct pw_jack_node *node;
 | 
			
		||||
 | 
			
		||||
	ref_num = jack_server_allocate_ref_num(server);
 | 
			
		||||
	if (ref_num == -1)
 | 
			
		||||
		return -1;
 | 
			
		||||
 | 
			
		||||
	if (jack_synchro_init(&server->synchro_table[ref_num],
 | 
			
		||||
			      "system",
 | 
			
		||||
			      server->engine_control->server_name,
 | 
			
		||||
			      0,
 | 
			
		||||
			      false,
 | 
			
		||||
			      server->promiscuous) < 0) {
 | 
			
		||||
	node = pw_jack_driver_new(impl->core,
 | 
			
		||||
				  pw_module_get_global(impl->module),
 | 
			
		||||
				  server,
 | 
			
		||||
				  "system",
 | 
			
		||||
				  0, 2,
 | 
			
		||||
				  NULL,
 | 
			
		||||
				  sizeof(struct jack_client));
 | 
			
		||||
	if (node == NULL) {
 | 
			
		||||
		pw_log_error("module-jack %p: can't create driver node", impl);
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	jc = calloc(1,sizeof(struct jack_client));
 | 
			
		||||
	ref_num = node->control->ref_num;
 | 
			
		||||
 | 
			
		||||
	jc = node->user_data;
 | 
			
		||||
	jc->fd = -1;
 | 
			
		||||
	jc->data = impl;
 | 
			
		||||
	jc->ref_num = ref_num;
 | 
			
		||||
	jc->control = jack_client_control_alloc("system", -1, ref_num, -1);
 | 
			
		||||
	jc->control->active = true;
 | 
			
		||||
	jc->node = node;
 | 
			
		||||
	pw_jack_node_add_listener(node, &jc->node_listener, &jack_node_events, jc);
 | 
			
		||||
 | 
			
		||||
	server->client_table[ref_num] = jc;
 | 
			
		||||
 | 
			
		||||
	impl->server.engine_control->driver_num++;
 | 
			
		||||
 | 
			
		||||
	conn = jack_graph_manager_next_start(mgr);
 | 
			
		||||
 | 
			
		||||
	jack_connection_manager_init_ref_num(conn, ref_num);
 | 
			
		||||
	jack_connection_manager_direct_connect(conn, ref_num, ref_num);
 | 
			
		||||
 | 
			
		||||
	port_id = jack_graph_manager_allocate_port(mgr,
 | 
			
		||||
						   ref_num, "system:playback_1", 0,
 | 
			
		||||
						   JackPortIsInput |
 | 
			
		||||
						   JackPortIsPhysical |
 | 
			
		||||
						   JackPortIsTerminal);
 | 
			
		||||
	jack_connection_manager_add_port(conn, true, ref_num, port_id);
 | 
			
		||||
 | 
			
		||||
	port_id = jack_graph_manager_allocate_port(mgr,
 | 
			
		||||
						   ref_num, "system:playback_2", 0,
 | 
			
		||||
						   JackPortIsInput |
 | 
			
		||||
						   JackPortIsPhysical |
 | 
			
		||||
						   JackPortIsTerminal);
 | 
			
		||||
	jack_connection_manager_add_port(conn, true, ref_num, port_id);
 | 
			
		||||
 | 
			
		||||
	jack_graph_manager_next_stop(mgr);
 | 
			
		||||
 | 
			
		||||
	server->audio_ref_num = ref_num;
 | 
			
		||||
	server->audio_node = pw_jack_node_new(impl->core, pw_module_get_global(impl->module),
 | 
			
		||||
					      server, ref_num, NULL);
 | 
			
		||||
	server->audio_node_node = pw_jack_node_get_node(server->audio_node);
 | 
			
		||||
	jc->node = server->audio_node;
 | 
			
		||||
 | 
			
		||||
	pw_jack_node_add_listener(server->audio_node, &jc->node_listener, &jack_node_events, jc);
 | 
			
		||||
	server->audio_node = node;
 | 
			
		||||
	server->audio_node_node = node->node;
 | 
			
		||||
 | 
			
		||||
	pw_log_debug("module-jack %p: Added audio driver %d", impl, ref_num);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -961,41 +1057,31 @@ static int
 | 
			
		|||
make_freewheel_client(struct impl *impl)
 | 
			
		||||
{
 | 
			
		||||
	struct jack_server *server = &impl->server;
 | 
			
		||||
	struct jack_graph_manager *mgr = server->graph_manager;
 | 
			
		||||
	struct jack_connection_manager *conn;
 | 
			
		||||
	int ref_num;
 | 
			
		||||
	struct jack_client *jc;
 | 
			
		||||
	struct pw_jack_node *node;
 | 
			
		||||
 | 
			
		||||
	ref_num = jack_server_allocate_ref_num(server);
 | 
			
		||||
	if (ref_num == -1)
 | 
			
		||||
		return -1;
 | 
			
		||||
 | 
			
		||||
	if (jack_synchro_init(&server->synchro_table[ref_num],
 | 
			
		||||
			      "freewheel",
 | 
			
		||||
			      server->engine_control->server_name,
 | 
			
		||||
			      0,
 | 
			
		||||
			      false,
 | 
			
		||||
			      server->promiscuous) < 0) {
 | 
			
		||||
	node = pw_jack_driver_new(impl->core,
 | 
			
		||||
				  pw_module_get_global(impl->module),
 | 
			
		||||
				  server,
 | 
			
		||||
				  "freewheel",
 | 
			
		||||
				  0, 0,
 | 
			
		||||
				  NULL,
 | 
			
		||||
				  sizeof(struct jack_client));
 | 
			
		||||
	if (node == NULL) {
 | 
			
		||||
		pw_log_error("module-jack %p: can't create driver node", impl);
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	jc = calloc(1,sizeof(struct jack_client));
 | 
			
		||||
	ref_num = node->control->ref_num;
 | 
			
		||||
 | 
			
		||||
	jc = node->user_data;
 | 
			
		||||
	jc->fd = -1;
 | 
			
		||||
	jc->data = impl;
 | 
			
		||||
	jc->ref_num = ref_num;
 | 
			
		||||
	jc->control = jack_client_control_alloc("freewheel", -1, ref_num, -1);
 | 
			
		||||
	jc->control->active = true;
 | 
			
		||||
	jc->node = node;
 | 
			
		||||
 | 
			
		||||
	server->client_table[ref_num] = jc;
 | 
			
		||||
 | 
			
		||||
	impl->server.engine_control->driver_num++;
 | 
			
		||||
 | 
			
		||||
	conn = jack_graph_manager_next_start(mgr);
 | 
			
		||||
 | 
			
		||||
	jack_connection_manager_init_ref_num(conn, ref_num);
 | 
			
		||||
	jack_connection_manager_direct_connect(conn, ref_num, ref_num);
 | 
			
		||||
 | 
			
		||||
	jack_graph_manager_next_stop(mgr);
 | 
			
		||||
 | 
			
		||||
	server->freewheel_ref_num = ref_num;
 | 
			
		||||
	pw_log_debug("module-jack %p: Added freewheel driver %d", impl, ref_num);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1009,6 +1095,7 @@ static bool on_global(void *data, struct pw_global *global)
 | 
			
		|||
	struct pw_node *node;
 | 
			
		||||
	const struct pw_properties *properties;
 | 
			
		||||
	const char *str;
 | 
			
		||||
	struct pw_port *in_port, *out_port;
 | 
			
		||||
 | 
			
		||||
	if (pw_global_get_type(global) != impl->t->node)
 | 
			
		||||
		return true;
 | 
			
		||||
| 
						 | 
				
			
			@ -1022,9 +1109,14 @@ static bool on_global(void *data, struct pw_global *global)
 | 
			
		|||
	if (strcmp(str, "Audio/Sink") != 0)
 | 
			
		||||
		return true;
 | 
			
		||||
 | 
			
		||||
	out_port = pw_node_get_free_port(impl->server.audio_node_node, PW_DIRECTION_OUTPUT);
 | 
			
		||||
	in_port = pw_node_get_free_port(node, PW_DIRECTION_INPUT);
 | 
			
		||||
	if (out_port == NULL || in_port == NULL)
 | 
			
		||||
		return true;
 | 
			
		||||
 | 
			
		||||
	impl->sink_link = pw_link_new(impl->core, pw_module_get_global(impl->module),
 | 
			
		||||
		    pw_node_get_free_port(impl->server.audio_node_node, PW_DIRECTION_OUTPUT),
 | 
			
		||||
		    pw_node_get_free_port(node, PW_DIRECTION_INPUT),
 | 
			
		||||
		    out_port,
 | 
			
		||||
		    in_port,
 | 
			
		||||
		    NULL,
 | 
			
		||||
		    NULL,
 | 
			
		||||
		    NULL,
 | 
			
		||||
| 
						 | 
				
			
			@ -1034,42 +1126,6 @@ static bool on_global(void *data, struct pw_global *global)
 | 
			
		|||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
static void on_timeout(void *data, uint64_t expirations)
 | 
			
		||||
{
 | 
			
		||||
	struct impl *impl = data;
 | 
			
		||||
	struct jack_server *server = &impl->server;
 | 
			
		||||
	struct jack_graph_manager *mgr = server->graph_manager;
 | 
			
		||||
	struct jack_connection_manager *conn;
 | 
			
		||||
	struct jack_client *client;
 | 
			
		||||
	int activation;
 | 
			
		||||
 | 
			
		||||
	client = server->client_table[server->freewheel_ref_num];
 | 
			
		||||
 | 
			
		||||
	conn = jack_graph_manager_try_switch(mgr);
 | 
			
		||||
 | 
			
		||||
	jack_connection_manager_reset(conn, mgr->client_timing);
 | 
			
		||||
 | 
			
		||||
	activation = jack_connection_manager_get_activation(conn, server->freewheel_ref_num);
 | 
			
		||||
	if (activation == 0)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	pw_log_trace("resume %d", activation);
 | 
			
		||||
	jack_connection_manager_resume_ref_num(conn,
 | 
			
		||||
					       client->control,
 | 
			
		||||
					       server->synchro_table,
 | 
			
		||||
					       mgr->client_timing);
 | 
			
		||||
 | 
			
		||||
	if (server->engine_control->sync_mode) {
 | 
			
		||||
		pw_log_trace("suspend");
 | 
			
		||||
		jack_connection_manager_suspend_ref_num(conn,
 | 
			
		||||
						        client->control,
 | 
			
		||||
						        server->synchro_table,
 | 
			
		||||
						        mgr->client_timing);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static bool init_nodes(struct impl *impl)
 | 
			
		||||
{
 | 
			
		||||
	struct pw_core *core = impl->core;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -54,14 +54,6 @@ struct type {
 | 
			
		|||
        struct spa_type_audio_format audio_format;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct impl {
 | 
			
		||||
	struct pw_jack_node node;
 | 
			
		||||
 | 
			
		||||
	struct type type;
 | 
			
		||||
 | 
			
		||||
	int status;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static inline void init_type(struct type *type, struct spa_type_map *map)
 | 
			
		||||
{
 | 
			
		||||
        type->format = spa_type_map_get_id(map, SPA_TYPE__Format);
 | 
			
		||||
| 
						 | 
				
			
			@ -72,6 +64,22 @@ static inline void init_type(struct type *type, struct spa_type_map *map)
 | 
			
		|||
        spa_type_audio_format_map(map, &type->audio_format);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct node_data {
 | 
			
		||||
	struct pw_jack_node node;
 | 
			
		||||
	struct spa_hook node_listener;
 | 
			
		||||
 | 
			
		||||
	struct type type;
 | 
			
		||||
 | 
			
		||||
	int n_capture_channels;
 | 
			
		||||
	int n_playback_channels;
 | 
			
		||||
 | 
			
		||||
	struct spa_hook_list listener_list;
 | 
			
		||||
 | 
			
		||||
	int port_count;
 | 
			
		||||
 | 
			
		||||
	int status;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct buffer {
 | 
			
		||||
        struct spa_list link;
 | 
			
		||||
	struct spa_buffer *outbuf;
 | 
			
		||||
| 
						 | 
				
			
			@ -79,12 +87,14 @@ struct buffer {
 | 
			
		|||
};
 | 
			
		||||
 | 
			
		||||
struct port_data {
 | 
			
		||||
	struct impl *impl;
 | 
			
		||||
	enum pw_direction direction;
 | 
			
		||||
	struct pw_jack_port port;
 | 
			
		||||
	struct spa_hook port_listener;
 | 
			
		||||
 | 
			
		||||
	int jack_port_id;
 | 
			
		||||
	struct jack_port *port;
 | 
			
		||||
	float *ptr;
 | 
			
		||||
	struct node_data *node;
 | 
			
		||||
 | 
			
		||||
	struct spa_hook_list listener_list;
 | 
			
		||||
 | 
			
		||||
	bool driver_port;
 | 
			
		||||
 | 
			
		||||
	struct spa_port_info info;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -148,7 +158,7 @@ static int driver_process_input(void *data)
 | 
			
		|||
	struct spa_graph_node *node = &this->node->rt.node;
 | 
			
		||||
	struct spa_graph_port *p;
 | 
			
		||||
	struct buffer *out;
 | 
			
		||||
	struct port_data *opd = pw_port_get_user_data(this->otherport);
 | 
			
		||||
	struct port_data *opd = SPA_CONTAINER_OF(this->driverport, struct port_data, port);
 | 
			
		||||
	struct spa_port_io *out_io = opd->io;
 | 
			
		||||
 | 
			
		||||
	pw_log_trace("process input");
 | 
			
		||||
| 
						 | 
				
			
			@ -197,10 +207,11 @@ static void fill_s16(int16_t *out, int n_samples, int stride)
 | 
			
		|||
 | 
			
		||||
static int driver_process_output(void *data)
 | 
			
		||||
{
 | 
			
		||||
	struct pw_jack_node *this = data;
 | 
			
		||||
	struct node_data *nd = data;
 | 
			
		||||
	struct pw_jack_node *this = &nd->node;
 | 
			
		||||
	struct spa_graph_node *node = &this->node->rt.node;
 | 
			
		||||
	struct spa_graph_port *p;
 | 
			
		||||
	struct port_data *opd = pw_port_get_user_data(this->otherport);
 | 
			
		||||
	struct port_data *opd = SPA_CONTAINER_OF(this->driverport, struct port_data, port);
 | 
			
		||||
	struct spa_port_io *out_io = opd->io;
 | 
			
		||||
	struct jack_engine_control *ctrl = this->server->engine_control;
 | 
			
		||||
	struct buffer *out;
 | 
			
		||||
| 
						 | 
				
			
			@ -225,7 +236,7 @@ static int driver_process_output(void *data)
 | 
			
		|||
 | 
			
		||||
	op = out->ptr;
 | 
			
		||||
 | 
			
		||||
	spa_hook_list_call(&this->listener_list, struct pw_jack_node_events, pull);
 | 
			
		||||
	spa_hook_list_call(&nd->listener_list, struct pw_jack_node_events, pull);
 | 
			
		||||
 | 
			
		||||
	spa_list_for_each(p, &node->ports[SPA_DIRECTION_INPUT], link) {
 | 
			
		||||
		struct pw_port *port = p->callbacks_data;
 | 
			
		||||
| 
						 | 
				
			
			@ -246,7 +257,7 @@ static int driver_process_output(void *data)
 | 
			
		|||
	}
 | 
			
		||||
	out->outbuf->datas[0].chunk->size = ctrl->buffer_size * sizeof(int16_t) * 2;
 | 
			
		||||
 | 
			
		||||
	spa_hook_list_call(&this->listener_list, struct pw_jack_node_events, push);
 | 
			
		||||
	spa_hook_list_call(&nd->listener_list, struct pw_jack_node_events, push);
 | 
			
		||||
	node->ready_in = node->required_in;
 | 
			
		||||
 | 
			
		||||
	return SPA_RESULT_HAVE_BUFFER;
 | 
			
		||||
| 
						 | 
				
			
			@ -264,18 +275,18 @@ static const struct pw_node_implementation driver_impl = {
 | 
			
		|||
 | 
			
		||||
static int node_process_input(void *data)
 | 
			
		||||
{
 | 
			
		||||
	struct impl *impl = data;
 | 
			
		||||
	struct pw_jack_node *this = &impl->node;
 | 
			
		||||
	struct node_data *nd = data;
 | 
			
		||||
	struct pw_jack_node *this = &nd->node;
 | 
			
		||||
	struct spa_graph_node *node = &this->node->rt.node;
 | 
			
		||||
	struct spa_graph_port *p;
 | 
			
		||||
        struct jack_server *server = this->server;
 | 
			
		||||
        struct jack_graph_manager *mgr = server->graph_manager;
 | 
			
		||||
	struct jack_connection_manager *conn;
 | 
			
		||||
	jack_time_t current_date = 0;
 | 
			
		||||
	int ref_num = this->ref_num;
 | 
			
		||||
	int ref_num = this->control->ref_num;
 | 
			
		||||
 | 
			
		||||
	pw_log_trace(NAME " %p: process input", impl);
 | 
			
		||||
	if (impl->status == SPA_RESULT_HAVE_BUFFER)
 | 
			
		||||
	pw_log_trace(NAME " %p: process input", nd);
 | 
			
		||||
	if (nd->status == SPA_RESULT_HAVE_BUFFER)
 | 
			
		||||
                return SPA_RESULT_HAVE_BUFFER;
 | 
			
		||||
 | 
			
		||||
	mgr->client_timing[ref_num].status = Triggered;
 | 
			
		||||
| 
						 | 
				
			
			@ -292,28 +303,28 @@ static int node_process_input(void *data)
 | 
			
		|||
		struct spa_port_io *out_io = opd->io;
 | 
			
		||||
		out_io->buffer_id = 0;
 | 
			
		||||
		out_io->status = SPA_RESULT_HAVE_BUFFER;
 | 
			
		||||
		pw_log_trace(NAME " %p: port %p: %d %d", impl, p, out_io->buffer_id, out_io->status);
 | 
			
		||||
		pw_log_trace(NAME " %p: port %p: %d %d", nd, p, out_io->buffer_id, out_io->status);
 | 
			
		||||
	}
 | 
			
		||||
	return impl->status = SPA_RESULT_HAVE_BUFFER;
 | 
			
		||||
	return nd->status = SPA_RESULT_HAVE_BUFFER;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int node_process_output(void *data)
 | 
			
		||||
{
 | 
			
		||||
	struct impl *impl = data;
 | 
			
		||||
	struct pw_jack_node *this = &impl->node;
 | 
			
		||||
	struct node_data *nd = data;
 | 
			
		||||
	struct pw_jack_node *this = &nd->node;
 | 
			
		||||
	struct spa_graph_node *node = &this->node->rt.node;
 | 
			
		||||
	struct spa_graph_port *p;
 | 
			
		||||
 | 
			
		||||
	pw_log_trace(NAME " %p: process output", impl);
 | 
			
		||||
	pw_log_trace(NAME " %p: process output", nd);
 | 
			
		||||
	spa_list_for_each(p, &node->ports[SPA_DIRECTION_INPUT], link) {
 | 
			
		||||
		struct pw_port *port = p->callbacks_data;
 | 
			
		||||
		struct port_data *ipd = pw_port_get_user_data(port);
 | 
			
		||||
		struct spa_port_io *in_io = ipd->io;
 | 
			
		||||
		in_io->buffer_id = 0;
 | 
			
		||||
		in_io->status = SPA_RESULT_NEED_BUFFER;
 | 
			
		||||
		pw_log_trace(NAME " %p: port %p: %d %d", impl, p, in_io->buffer_id, in_io->status);
 | 
			
		||||
		pw_log_trace(NAME " %p: port %p: %d %d", nd, p, in_io->buffer_id, in_io->status);
 | 
			
		||||
	}
 | 
			
		||||
	return impl->status = SPA_RESULT_NEED_BUFFER;
 | 
			
		||||
	return nd->status = SPA_RESULT_NEED_BUFFER;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct pw_node_implementation node_impl = {
 | 
			
		||||
| 
						 | 
				
			
			@ -342,25 +353,25 @@ static int port_enum_formats(void *data,
 | 
			
		|||
                             int32_t index)
 | 
			
		||||
{
 | 
			
		||||
	struct port_data *pd = data;
 | 
			
		||||
	struct type *t = &pd->impl->type;
 | 
			
		||||
	struct type *t = &pd->node->type;
 | 
			
		||||
        struct spa_pod_builder b = { NULL, };
 | 
			
		||||
        struct spa_pod_frame f[2];
 | 
			
		||||
	struct jack_engine_control *ctrl = pd->impl->node.server->engine_control;
 | 
			
		||||
	struct jack_engine_control *ctrl = pd->node->node.server->engine_control;
 | 
			
		||||
 | 
			
		||||
	if (index > 0)
 | 
			
		||||
		return SPA_RESULT_ENUM_END;
 | 
			
		||||
 | 
			
		||||
        spa_pod_builder_init(&b, pd->buffer, sizeof(pd->buffer));
 | 
			
		||||
 | 
			
		||||
	if (pd->port) {
 | 
			
		||||
		if (pd->port->type_id == 0) {
 | 
			
		||||
	if (pd->port.jack_port) {
 | 
			
		||||
		if (pd->port.jack_port->type_id == 0) {
 | 
			
		||||
			spa_pod_builder_format(&b, &f[0], t->format,
 | 
			
		||||
	                        t->media_type.audio, t->media_subtype.raw,
 | 
			
		||||
	                        PROP(&f[1], t->format_audio.format, SPA_POD_TYPE_ID, t->audio_format.F32),
 | 
			
		||||
	                        PROP(&f[1], t->format_audio.rate, SPA_POD_TYPE_INT, ctrl->sample_rate),
 | 
			
		||||
	                        PROP(&f[1], t->format_audio.channels, SPA_POD_TYPE_INT, 1));
 | 
			
		||||
		}
 | 
			
		||||
		else if (pd->port->type_id == 1) {
 | 
			
		||||
		else if (pd->port.jack_port->type_id == 1) {
 | 
			
		||||
			return SPA_RESULT_ENUM_END;
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
| 
						 | 
				
			
			@ -395,12 +406,13 @@ static int port_get_format(void *data, const struct spa_format **format)
 | 
			
		|||
static int port_get_info(void *data, const struct spa_port_info **info)
 | 
			
		||||
{
 | 
			
		||||
	struct port_data *pd = data;
 | 
			
		||||
	struct pw_jack_port *port = &pd->port;
 | 
			
		||||
 | 
			
		||||
	pd->info.flags = SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS | SPA_PORT_INFO_FLAG_LIVE;
 | 
			
		||||
	if (pd->direction == PW_DIRECTION_OUTPUT && pd->impl->node.otherport == NULL)
 | 
			
		||||
	if (port->direction == PW_DIRECTION_OUTPUT && port->jack_port != NULL)
 | 
			
		||||
		pd->info.flags |= SPA_PORT_INFO_FLAG_CAN_ALLOC_BUFFERS;
 | 
			
		||||
 | 
			
		||||
	pd->info.rate = pd->impl->node.server->engine_control->sample_rate;
 | 
			
		||||
	pd->info.rate = pd->node->node.server->engine_control->sample_rate;
 | 
			
		||||
	*info = &pd->info;
 | 
			
		||||
 | 
			
		||||
	return SPA_RESULT_OK;
 | 
			
		||||
| 
						 | 
				
			
			@ -419,7 +431,7 @@ static int port_set_param(void *data, struct spa_param *param)
 | 
			
		|||
static int port_use_buffers(void *data, struct spa_buffer **buffers, uint32_t n_buffers)
 | 
			
		||||
{
 | 
			
		||||
	struct port_data *pd = data;
 | 
			
		||||
	struct type *t = &pd->impl->type;
 | 
			
		||||
	struct type *t = &pd->node->type;
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < n_buffers; i++) {
 | 
			
		||||
| 
						 | 
				
			
			@ -448,7 +460,7 @@ static int port_alloc_buffers(void *data,
 | 
			
		|||
                              struct spa_buffer **buffers, uint32_t *n_buffers)
 | 
			
		||||
{
 | 
			
		||||
	struct port_data *pd = data;
 | 
			
		||||
	struct type *t = &pd->impl->type;
 | 
			
		||||
	struct type *t = &pd->node->type;
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < *n_buffers; i++) {
 | 
			
		||||
| 
						 | 
				
			
			@ -458,7 +470,7 @@ static int port_alloc_buffers(void *data,
 | 
			
		|||
                b = &pd->buffers[i];
 | 
			
		||||
		b->outbuf = buffers[i];
 | 
			
		||||
		d[0].type = t->data.MemPtr;
 | 
			
		||||
		b->ptr = d[0].data = pd->ptr;
 | 
			
		||||
		b->ptr = d[0].data = pd->port.ptr;
 | 
			
		||||
                spa_list_append(&pd->empty, &b->link);
 | 
			
		||||
	}
 | 
			
		||||
	pd->n_buffers = *n_buffers;
 | 
			
		||||
| 
						 | 
				
			
			@ -491,97 +503,294 @@ static const struct pw_port_implementation port_impl = {
 | 
			
		|||
	.send_command = port_send_command,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static struct pw_port *make_port(struct pw_jack_node *node, enum pw_direction direction,
 | 
			
		||||
				 int port_id, int jack_port_id, struct jack_port *jp, bool autoconnect)
 | 
			
		||||
static void port_destroy(void *data)
 | 
			
		||||
{
 | 
			
		||||
	struct impl *impl = SPA_CONTAINER_OF(node, struct impl, node);
 | 
			
		||||
	struct pw_port *port;
 | 
			
		||||
	struct port_data *pd = data;
 | 
			
		||||
	struct pw_jack_port *port = &pd->port;
 | 
			
		||||
	struct pw_jack_node *node = &pd->node->node;
 | 
			
		||||
	struct jack_server *server = node->server;
 | 
			
		||||
	struct jack_graph_manager *mgr = server->graph_manager;
 | 
			
		||||
        struct jack_connection_manager *conn;
 | 
			
		||||
	int ref_num = node->control->ref_num;
 | 
			
		||||
	jack_port_id_t port_id = port->port_id;
 | 
			
		||||
 | 
			
		||||
	if (port->jack_port == NULL)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	spa_hook_list_call(&pd->listener_list, struct pw_jack_port_events, destroy);
 | 
			
		||||
 | 
			
		||||
        conn = jack_graph_manager_next_start(mgr);
 | 
			
		||||
 | 
			
		||||
	if (port->direction == PW_DIRECTION_INPUT)
 | 
			
		||||
		jack_connection_manager_remove_inport(conn, ref_num, port_id);
 | 
			
		||||
	else
 | 
			
		||||
		jack_connection_manager_remove_outport(conn, ref_num, port_id);
 | 
			
		||||
        jack_graph_manager_next_stop(mgr);
 | 
			
		||||
 | 
			
		||||
	jack_graph_manager_release_port(mgr, port->port_id);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct pw_port_events port_events = {
 | 
			
		||||
	PW_VERSION_PORT_EVENTS,
 | 
			
		||||
	.destroy = port_destroy,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct pw_jack_port *
 | 
			
		||||
alloc_port(struct pw_jack_node *node, enum pw_direction direction, uint32_t port_id, size_t user_data_size)
 | 
			
		||||
{
 | 
			
		||||
	struct node_data *nd = SPA_CONTAINER_OF(node, struct node_data, node);
 | 
			
		||||
	struct pw_port *p;
 | 
			
		||||
	struct port_data *pd;
 | 
			
		||||
	struct pw_properties *properties = NULL;
 | 
			
		||||
	struct pw_jack_port *port;
 | 
			
		||||
 | 
			
		||||
	if (autoconnect)
 | 
			
		||||
		properties = pw_properties_new("pipewire.autoconnect", "1", NULL);
 | 
			
		||||
	p = pw_port_new(direction, port_id, NULL, sizeof(struct port_data) + user_data_size);
 | 
			
		||||
	if (p == NULL)
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	port = pw_port_new(direction, port_id, properties, sizeof(struct port_data));
 | 
			
		||||
	pd = pw_port_get_user_data(port);
 | 
			
		||||
	pd->direction = direction;
 | 
			
		||||
	pd->impl = impl;
 | 
			
		||||
	pd->jack_port_id = jack_port_id;
 | 
			
		||||
	pd->port = jp;
 | 
			
		||||
	pd->ptr = (float *)((uintptr_t)jp->buffer & ~31L) + 8;
 | 
			
		||||
	pd = pw_port_get_user_data(p);
 | 
			
		||||
	pd->node = nd;
 | 
			
		||||
        spa_hook_list_init(&pd->listener_list);
 | 
			
		||||
	spa_list_init(&pd->empty);
 | 
			
		||||
	pw_port_set_implementation(port, &port_impl, pd);
 | 
			
		||||
	pw_port_add(port, node->node);
 | 
			
		||||
	port = &pd->port;
 | 
			
		||||
 | 
			
		||||
	port->node = node;
 | 
			
		||||
	port->direction = direction;
 | 
			
		||||
	port->port = p;
 | 
			
		||||
 | 
			
		||||
	if (user_data_size > 0)
 | 
			
		||||
		port->user_data = SPA_MEMBER(pd, sizeof(struct port_data), void);
 | 
			
		||||
 | 
			
		||||
	pw_port_add_listener(p, &pd->port_listener, &port_events, pd);
 | 
			
		||||
 | 
			
		||||
	pw_port_set_implementation(p, &port_impl, pd);
 | 
			
		||||
	pw_port_add(p, node->node);
 | 
			
		||||
 | 
			
		||||
	return port;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct pw_jack_port *
 | 
			
		||||
pw_jack_node_add_port(struct pw_jack_node *node,
 | 
			
		||||
		      const char *name,
 | 
			
		||||
		      const char *type,
 | 
			
		||||
		      unsigned int flags,
 | 
			
		||||
		      size_t user_data_size)
 | 
			
		||||
{
 | 
			
		||||
	struct node_data *nd = SPA_CONTAINER_OF(node, struct node_data, node);
 | 
			
		||||
	struct jack_server *server = node->server;
 | 
			
		||||
	struct jack_graph_manager *mgr = server->graph_manager;
 | 
			
		||||
        struct jack_connection_manager *conn;
 | 
			
		||||
	struct pw_jack_port *port;
 | 
			
		||||
        jack_port_type_id_t type_id;
 | 
			
		||||
	jack_port_id_t port_id;
 | 
			
		||||
	enum pw_direction direction;
 | 
			
		||||
	int ref_num;
 | 
			
		||||
 | 
			
		||||
        type_id = jack_port_get_type_id(type);
 | 
			
		||||
 | 
			
		||||
	if (jack_graph_manager_find_port(mgr, name) != NO_PORT) {
 | 
			
		||||
                pw_log_error(NAME " %p: port_name %s exists", node, name);
 | 
			
		||||
                return NULL;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
	direction = flags & JackPortIsInput ? PW_DIRECTION_INPUT : PW_DIRECTION_OUTPUT;
 | 
			
		||||
	ref_num = node->control->ref_num;
 | 
			
		||||
 | 
			
		||||
	port_id = jack_graph_manager_allocate_port(mgr, ref_num, name, type_id, flags);
 | 
			
		||||
	if (port_id == NO_PORT) {
 | 
			
		||||
                pw_log_error(NAME " %p: failed to create port name %s", node, name);
 | 
			
		||||
                return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	port = alloc_port(node, direction, nd->port_count++, user_data_size);
 | 
			
		||||
	if (port == NULL)
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	port->port_id = port_id;
 | 
			
		||||
	port->jack_port = jack_graph_manager_get_port(mgr, port_id);
 | 
			
		||||
	port->ptr = (float *)((uintptr_t)port->jack_port->buffer & ~31L) + 8;
 | 
			
		||||
 | 
			
		||||
        conn = jack_graph_manager_next_start(mgr);
 | 
			
		||||
	if (direction == PW_DIRECTION_INPUT)
 | 
			
		||||
		jack_connection_manager_add_inport(conn, ref_num, port_id);
 | 
			
		||||
	else
 | 
			
		||||
		jack_connection_manager_add_outport(conn, ref_num, port_id);
 | 
			
		||||
        jack_graph_manager_next_stop(mgr);
 | 
			
		||||
 | 
			
		||||
	return port;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void pw_jack_port_add_listener(struct pw_jack_port *port,
 | 
			
		||||
			       struct spa_hook *listener,
 | 
			
		||||
			       const struct pw_jack_port_events *events,
 | 
			
		||||
			       void *data)
 | 
			
		||||
{
 | 
			
		||||
	struct port_data *pd = SPA_CONTAINER_OF(port, struct port_data, port);
 | 
			
		||||
	spa_hook_list_append(&pd->listener_list, listener, events, data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void node_destroy(void *data)
 | 
			
		||||
{
 | 
			
		||||
	struct node_data *nd = data;
 | 
			
		||||
	spa_hook_list_call(&nd->listener_list, struct pw_jack_node_events, destroy);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void node_free(void *data)
 | 
			
		||||
{
 | 
			
		||||
	struct node_data *nd = data;
 | 
			
		||||
	spa_hook_list_call(&nd->listener_list, struct pw_jack_node_events, free);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct pw_node_events node_events = {
 | 
			
		||||
	PW_VERSION_NODE_EVENTS,
 | 
			
		||||
	.destroy = node_destroy,
 | 
			
		||||
	.free = node_free,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct pw_jack_node *pw_jack_node_new(struct pw_core *core,
 | 
			
		||||
				      struct pw_global *parent,
 | 
			
		||||
				      struct jack_server *server,
 | 
			
		||||
				      int ref_num,
 | 
			
		||||
				      struct pw_properties *properties)
 | 
			
		||||
				      const char *name,
 | 
			
		||||
				      int pid,
 | 
			
		||||
				      struct pw_properties *properties,
 | 
			
		||||
				      size_t user_data_size)
 | 
			
		||||
{
 | 
			
		||||
	struct impl *impl;
 | 
			
		||||
	struct pw_jack_node *this;
 | 
			
		||||
	struct node_data *nd;
 | 
			
		||||
	int ref_num;
 | 
			
		||||
	struct pw_node *node;
 | 
			
		||||
	struct jack_client *client = server->client_table[ref_num];
 | 
			
		||||
	struct pw_jack_node *this;
 | 
			
		||||
	struct jack_graph_manager *mgr = server->graph_manager;
 | 
			
		||||
	struct jack_connection_manager *conn;
 | 
			
		||||
	int i;
 | 
			
		||||
	jack_int_t *p;
 | 
			
		||||
	bool make_input = false, make_output = false;
 | 
			
		||||
        struct jack_connection_manager *conn;
 | 
			
		||||
 | 
			
		||||
	node = pw_node_new(core, NULL, parent, client->control->name,
 | 
			
		||||
			   properties, sizeof(struct impl));
 | 
			
		||||
	ref_num = jack_server_allocate_ref_num(server);
 | 
			
		||||
	if (ref_num == -1) {
 | 
			
		||||
                pw_log_error(NAME " %p: can't allocated ref_num", core);
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
        if (jack_synchro_init(&server->synchro_table[ref_num],
 | 
			
		||||
                              name,
 | 
			
		||||
                              server->engine_control->server_name,
 | 
			
		||||
                              0,
 | 
			
		||||
                              server->promiscuous) < 0) {
 | 
			
		||||
                pw_log_error(NAME " %p: can't init synchro", core);
 | 
			
		||||
                return NULL;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
	node = pw_node_new(core, NULL, parent, name, properties, sizeof(struct node_data) + user_data_size);
 | 
			
		||||
	if (node == NULL)
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	impl = pw_node_get_user_data(node);
 | 
			
		||||
	this = &impl->node;
 | 
			
		||||
	nd = pw_node_get_user_data(node);
 | 
			
		||||
        spa_hook_list_init(&nd->listener_list);
 | 
			
		||||
	init_type(&nd->type, pw_core_get_type(core)->map);
 | 
			
		||||
 | 
			
		||||
	pw_node_add_listener(node, &nd->node_listener, &node_events, nd);
 | 
			
		||||
	pw_node_set_implementation(node, &node_impl, nd);
 | 
			
		||||
 | 
			
		||||
	this = &nd->node;
 | 
			
		||||
	pw_log_debug("jack-node %p: new", this);
 | 
			
		||||
 | 
			
		||||
	if (user_data_size > 0)
 | 
			
		||||
		this->user_data = SPA_MEMBER(nd, sizeof(struct node_data), void);
 | 
			
		||||
 | 
			
		||||
	this->node = node;
 | 
			
		||||
	this->core = core;
 | 
			
		||||
        spa_hook_list_init(&this->listener_list);
 | 
			
		||||
	this->server = server;
 | 
			
		||||
	this->client = client;
 | 
			
		||||
	this->ref_num = ref_num;
 | 
			
		||||
	init_type(&impl->type, pw_core_get_type(core)->map);
 | 
			
		||||
 | 
			
		||||
	conn = jack_graph_manager_next_start(mgr);
 | 
			
		||||
 | 
			
		||||
	p = GET_ITEMS_FIXED_ARRAY1(conn->input_port[ref_num]);
 | 
			
		||||
	for (i = 0; i < PORT_NUM_FOR_CLIENT && p[i] != EMPTY; i++) {
 | 
			
		||||
		struct jack_port *jp = jack_graph_manager_get_port(mgr, p[i]);
 | 
			
		||||
 | 
			
		||||
		if (jp->flags & JackPortIsPhysical)
 | 
			
		||||
			make_output = true;
 | 
			
		||||
 | 
			
		||||
		make_port(this, PW_DIRECTION_INPUT, i, p[i], jp, false);
 | 
			
		||||
	this->control = jack_client_control_alloc(name, pid, ref_num, -1);
 | 
			
		||||
	if (this->control == NULL) {
 | 
			
		||||
		pw_log_error(NAME " %p: can't create control", nd);
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	p = GET_ITEMS_FIXED_ARRAY(conn->output_port[ref_num]);
 | 
			
		||||
	for (i = 0; i < PORT_NUM_FOR_CLIENT && p[i] != EMPTY; i++) {
 | 
			
		||||
		struct jack_port *jp = jack_graph_manager_get_port(mgr, p[i]);
 | 
			
		||||
        conn = jack_graph_manager_next_start(mgr);
 | 
			
		||||
        jack_connection_manager_init_ref_num(conn, ref_num);
 | 
			
		||||
        jack_graph_manager_next_stop(mgr);
 | 
			
		||||
 | 
			
		||||
		if (jp->flags & JackPortIsPhysical)
 | 
			
		||||
			make_input = true;
 | 
			
		||||
	pw_node_register(node);
 | 
			
		||||
 | 
			
		||||
		make_port(this, PW_DIRECTION_OUTPUT, i, p[i], jp, false);
 | 
			
		||||
	return this;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct pw_jack_node *
 | 
			
		||||
pw_jack_driver_new(struct pw_core *core,
 | 
			
		||||
		   struct pw_global *parent,
 | 
			
		||||
		   struct jack_server *server,
 | 
			
		||||
		   const char *name,
 | 
			
		||||
		   int n_capture_channels,
 | 
			
		||||
		   int n_playback_channels,
 | 
			
		||||
		   struct pw_properties *properties,
 | 
			
		||||
		   size_t user_data_size)
 | 
			
		||||
{
 | 
			
		||||
	struct node_data *nd;
 | 
			
		||||
	int ref_num, i;
 | 
			
		||||
	struct pw_node *node;
 | 
			
		||||
	struct pw_jack_node *this;
 | 
			
		||||
	struct jack_graph_manager *mgr = server->graph_manager;
 | 
			
		||||
        struct jack_connection_manager *conn;
 | 
			
		||||
        char n[REAL_JACK_PORT_NAME_SIZE];
 | 
			
		||||
 | 
			
		||||
	ref_num = jack_server_allocate_ref_num(server);
 | 
			
		||||
	if (ref_num == -1) {
 | 
			
		||||
                pw_log_error(NAME " %p: can't allocated ref_num", core);
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
	jack_graph_manager_next_stop(mgr);
 | 
			
		||||
 | 
			
		||||
	if (make_output)
 | 
			
		||||
		this->otherport = make_port(this, PW_DIRECTION_OUTPUT, 0, -1, NULL, true);
 | 
			
		||||
	if (make_input)
 | 
			
		||||
		this->otherport = make_port(this, PW_DIRECTION_INPUT, 0, -1, NULL, true);
 | 
			
		||||
        if (jack_synchro_init(&server->synchro_table[ref_num],
 | 
			
		||||
                              name,
 | 
			
		||||
                              server->engine_control->server_name,
 | 
			
		||||
                              0,
 | 
			
		||||
                              server->promiscuous) < 0) {
 | 
			
		||||
                pw_log_error(NAME " %p: can't init synchro", core);
 | 
			
		||||
                return NULL;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
	if (make_output || make_input)
 | 
			
		||||
		pw_node_set_implementation(node, &driver_impl, this);
 | 
			
		||||
	else
 | 
			
		||||
		pw_node_set_implementation(node, &node_impl, this);
 | 
			
		||||
	node = pw_node_new(core, NULL, parent, name, properties, sizeof(struct node_data) + user_data_size);
 | 
			
		||||
	if (node == NULL)
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	nd = pw_node_get_user_data(node);
 | 
			
		||||
        spa_hook_list_init(&nd->listener_list);
 | 
			
		||||
	init_type(&nd->type, pw_core_get_type(core)->map);
 | 
			
		||||
 | 
			
		||||
	pw_node_set_implementation(node, &driver_impl, nd);
 | 
			
		||||
 | 
			
		||||
	this = &nd->node;
 | 
			
		||||
	this->node = node;
 | 
			
		||||
	this->core = core;
 | 
			
		||||
	this->server = server;
 | 
			
		||||
	this->control = jack_client_control_alloc(name, -1, ref_num, -1);
 | 
			
		||||
	this->control->active = true;
 | 
			
		||||
 | 
			
		||||
	if (user_data_size > 0)
 | 
			
		||||
		this->user_data = SPA_MEMBER(nd, sizeof(struct node_data), void);
 | 
			
		||||
 | 
			
		||||
        server->engine_control->driver_num++;
 | 
			
		||||
 | 
			
		||||
        conn = jack_graph_manager_next_start(mgr);
 | 
			
		||||
        jack_connection_manager_init_ref_num(conn, ref_num);
 | 
			
		||||
        jack_connection_manager_direct_connect(conn, ref_num, ref_num);
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < n_capture_channels; i++) {
 | 
			
		||||
		snprintf(n, sizeof(n), "%s:capture_%d", name, i);
 | 
			
		||||
		pw_jack_node_add_port(this, n, JACK_DEFAULT_AUDIO_TYPE,
 | 
			
		||||
				      JackPortIsOutput |
 | 
			
		||||
				      JackPortIsPhysical |
 | 
			
		||||
				      JackPortIsTerminal, 0);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < n_playback_channels; i++) {
 | 
			
		||||
		snprintf(n, sizeof(n), "%s:playback_%d", name, i);
 | 
			
		||||
		pw_jack_node_add_port(this, n, JACK_DEFAULT_AUDIO_TYPE,
 | 
			
		||||
				      JackPortIsInput |
 | 
			
		||||
				      JackPortIsPhysical |
 | 
			
		||||
				      JackPortIsTerminal, 0);
 | 
			
		||||
	}
 | 
			
		||||
        jack_graph_manager_next_stop(mgr);
 | 
			
		||||
 | 
			
		||||
	if (n_capture_channels > 0)
 | 
			
		||||
		this->driverport = alloc_port(this, PW_DIRECTION_INPUT, 0, 0);
 | 
			
		||||
	if (n_playback_channels > 0)
 | 
			
		||||
		this->driverport = alloc_port(this, PW_DIRECTION_OUTPUT, 0, 0);
 | 
			
		||||
 | 
			
		||||
	pw_node_register(node);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -592,12 +801,6 @@ void pw_jack_node_destroy(struct pw_jack_node *node)
 | 
			
		|||
{
 | 
			
		||||
	pw_log_debug("jack-node %p: destroy", node);
 | 
			
		||||
	pw_node_destroy(node->node);
 | 
			
		||||
	free(node);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct pw_node *pw_jack_node_get_node(struct pw_jack_node *node)
 | 
			
		||||
{
 | 
			
		||||
	return node->node;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void pw_jack_node_add_listener(struct pw_jack_node *node,
 | 
			
		||||
| 
						 | 
				
			
			@ -605,12 +808,13 @@ void pw_jack_node_add_listener(struct pw_jack_node *node,
 | 
			
		|||
			       const struct pw_jack_node_events *events,
 | 
			
		||||
			       void *data)
 | 
			
		||||
{
 | 
			
		||||
	spa_hook_list_append(&node->listener_list, listener, events, data);
 | 
			
		||||
	struct node_data *nd = SPA_CONTAINER_OF(node, struct node_data, node);
 | 
			
		||||
	spa_hook_list_append(&nd->listener_list, listener, events, data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct find_data {
 | 
			
		||||
	jack_port_id_t port_id;
 | 
			
		||||
	struct pw_port *result;
 | 
			
		||||
	struct pw_jack_port *result;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static bool find_port(void *data, struct pw_port *port)
 | 
			
		||||
| 
						 | 
				
			
			@ -618,26 +822,17 @@ static bool find_port(void *data, struct pw_port *port)
 | 
			
		|||
	struct find_data *d = data;
 | 
			
		||||
	struct port_data *pd = pw_port_get_user_data(port);
 | 
			
		||||
 | 
			
		||||
	if (pd->jack_port_id == d->port_id) {
 | 
			
		||||
		d->result = port;
 | 
			
		||||
	if (pd->port.port_id == d->port_id) {
 | 
			
		||||
		d->result = &pd->port;
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct pw_port *pw_jack_node_add_port(struct pw_jack_node *node,
 | 
			
		||||
				      enum pw_direction direction,
 | 
			
		||||
				      jack_port_id_t port_id)
 | 
			
		||||
{
 | 
			
		||||
	struct jack_server *server = node->server;
 | 
			
		||||
	struct jack_graph_manager *mgr = server->graph_manager;
 | 
			
		||||
	struct jack_port *jp = jack_graph_manager_get_port(mgr, port_id);
 | 
			
		||||
	return make_port(node, direction, port_id, port_id, jp, false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct pw_port *pw_jack_node_find_port(struct pw_jack_node *node,
 | 
			
		||||
				       enum pw_direction direction,
 | 
			
		||||
				       jack_port_id_t port_id)
 | 
			
		||||
struct pw_jack_port *
 | 
			
		||||
pw_jack_node_find_port(struct pw_jack_node *node,
 | 
			
		||||
		       enum pw_direction direction,
 | 
			
		||||
		       jack_port_id_t port_id)
 | 
			
		||||
{
 | 
			
		||||
	struct find_data data = { port_id, };
 | 
			
		||||
	if (!pw_node_for_each_port(node->node, direction, find_port, &data))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,25 +20,29 @@
 | 
			
		|||
#ifndef __PIPEWIRE_JACK_NODE_H__
 | 
			
		||||
#define __PIPEWIRE_JACK_NODE_H__
 | 
			
		||||
 | 
			
		||||
#include <spa/buffer.h>
 | 
			
		||||
 | 
			
		||||
#include <pipewire/node.h>
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
struct pw_jack_port;
 | 
			
		||||
 | 
			
		||||
struct pw_jack_node {
 | 
			
		||||
	struct pw_core *core;
 | 
			
		||||
	struct pw_node *node;
 | 
			
		||||
 | 
			
		||||
	struct spa_hook_list listener_list;
 | 
			
		||||
 | 
			
		||||
	struct pw_core *core;
 | 
			
		||||
	struct jack_server *server;
 | 
			
		||||
	struct jack_client *client;
 | 
			
		||||
	int ref_num;
 | 
			
		||||
 | 
			
		||||
	struct pw_port *otherport;
 | 
			
		||||
        struct jack_client_control *control;
 | 
			
		||||
 | 
			
		||||
	struct pw_jack_port *driverport;
 | 
			
		||||
 | 
			
		||||
	struct spa_list graph_link;
 | 
			
		||||
 | 
			
		||||
	void *user_data;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct pw_jack_node_events {
 | 
			
		||||
| 
						 | 
				
			
			@ -46,36 +50,76 @@ struct pw_jack_node_events {
 | 
			
		|||
        uint32_t version;
 | 
			
		||||
 | 
			
		||||
        void (*destroy) (void *data);
 | 
			
		||||
        void (*free) (void *data);
 | 
			
		||||
 | 
			
		||||
        void (*pull) (void *data);
 | 
			
		||||
 | 
			
		||||
        void (*push) (void *data);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct pw_jack_port {
 | 
			
		||||
	struct pw_jack_node *node;
 | 
			
		||||
 | 
			
		||||
	enum pw_direction direction;
 | 
			
		||||
	struct pw_port *port;
 | 
			
		||||
 | 
			
		||||
	jack_port_id_t port_id;
 | 
			
		||||
	struct jack_port *jack_port;
 | 
			
		||||
	float *ptr;
 | 
			
		||||
 | 
			
		||||
	void *user_data;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct pw_jack_port_events {
 | 
			
		||||
#define PW_VERSION_JACK_PORT_EVENTS 0
 | 
			
		||||
        uint32_t version;
 | 
			
		||||
 | 
			
		||||
        void (*destroy) (void *data);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct pw_jack_node *
 | 
			
		||||
pw_jack_node_new(struct pw_core *core,
 | 
			
		||||
		 struct pw_global *parent,
 | 
			
		||||
		 struct jack_server *server,
 | 
			
		||||
		 int ref_num,
 | 
			
		||||
		 struct pw_properties *properties);
 | 
			
		||||
		 const char *name,
 | 
			
		||||
		 int pid,
 | 
			
		||||
		 struct pw_properties *properties,
 | 
			
		||||
		 size_t user_data_size);
 | 
			
		||||
 | 
			
		||||
struct pw_jack_node *
 | 
			
		||||
pw_jack_driver_new(struct pw_core *core,
 | 
			
		||||
		   struct pw_global *parent,
 | 
			
		||||
		   struct jack_server *server,
 | 
			
		||||
		   const char *name,
 | 
			
		||||
		   int n_capture_channels,
 | 
			
		||||
		   int n_playback_channels,
 | 
			
		||||
		   struct pw_properties *properties,
 | 
			
		||||
		   size_t user_data_size);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
pw_jack_node_destroy(struct pw_jack_node *node);
 | 
			
		||||
 | 
			
		||||
struct pw_node *pw_jack_node_get_node(struct pw_jack_node *node);
 | 
			
		||||
 | 
			
		||||
void pw_jack_node_add_listener(struct pw_jack_node *node,
 | 
			
		||||
			       struct spa_hook *listener,
 | 
			
		||||
			       const struct pw_jack_node_events *events,
 | 
			
		||||
			       void *data);
 | 
			
		||||
 | 
			
		||||
struct pw_port *pw_jack_node_add_port(struct pw_jack_node *node,
 | 
			
		||||
				      enum pw_direction direction,
 | 
			
		||||
				      jack_port_id_t port_id);
 | 
			
		||||
struct pw_jack_port *
 | 
			
		||||
pw_jack_node_add_port(struct pw_jack_node *node,
 | 
			
		||||
		      const char *name,
 | 
			
		||||
		      const char *type,
 | 
			
		||||
                      unsigned int flags,
 | 
			
		||||
                      size_t user_data_size);
 | 
			
		||||
 | 
			
		||||
struct pw_port *pw_jack_node_find_port(struct pw_jack_node *node,
 | 
			
		||||
				       enum pw_direction direction, jack_port_id_t port_id);
 | 
			
		||||
void pw_jack_port_add_listener(struct pw_jack_port *port,
 | 
			
		||||
			       struct spa_hook *listener,
 | 
			
		||||
			       const struct pw_jack_port_events *events,
 | 
			
		||||
			       void *data);
 | 
			
		||||
 | 
			
		||||
struct pw_jack_port *
 | 
			
		||||
pw_jack_node_find_port(struct pw_jack_node *node,
 | 
			
		||||
		       enum pw_direction direction,
 | 
			
		||||
		       jack_port_id_t port_id);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,15 +17,15 @@
 | 
			
		|||
 * Boston, MA 02110-1301, USA.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
struct jack_server;
 | 
			
		||||
 | 
			
		||||
struct jack_client {
 | 
			
		||||
	int ref_num;
 | 
			
		||||
	void *data;
 | 
			
		||||
	struct client *owner;
 | 
			
		||||
	struct jack_client_control *control;
 | 
			
		||||
	struct pw_jack_node *node;
 | 
			
		||||
	int fd; /* notify fd */
 | 
			
		||||
	struct spa_hook node_listener;
 | 
			
		||||
	struct spa_list graph_link;
 | 
			
		||||
	struct spa_list client_link;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct jack_server {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -211,9 +211,10 @@ struct {					\
 | 
			
		|||
	INIT_FIXED_ARRAY(arr.array);		\
 | 
			
		||||
	arr.used = false;			\
 | 
			
		||||
})
 | 
			
		||||
#define GET_ITEMS_FIXED_ARRAY1(arr) GET_ITEMS_FIXED_ARRAY(arr.array)
 | 
			
		||||
#define ADD_FIXED_ARRAY1(arr,item) ADD_FIXED_ARRAY(arr.array,item)
 | 
			
		||||
#define GET_FIXED_ARRAY1(arr,item) GET_FIXED_ARRAY(arr.array,item)
 | 
			
		||||
#define GET_ITEMS_FIXED_ARRAY1(arr) GET_ITEMS_FIXED_ARRAY(arr.array)
 | 
			
		||||
#define REMOVE_FIXED_ARRAY1(arr,item) REMOVE_FIXED_ARRAY(arr.array,item)
 | 
			
		||||
 | 
			
		||||
#define MAKE_FIXED_MATRIX(size)			\
 | 
			
		||||
PRE_PACKED_STRUCTURE				\
 | 
			
		||||
| 
						 | 
				
			
			@ -341,7 +342,7 @@ struct {					\
 | 
			
		|||
		res = ADD_LOOP_FEEDBACK(arr,ref1,ref2);		\
 | 
			
		||||
	res;							\
 | 
			
		||||
})
 | 
			
		||||
#define DEC_LOOP_FEEDBACK(arr,idx) ({				\
 | 
			
		||||
#define DEC_LOOP_FEEDBACK(arr,ref1,ref2) ({			\
 | 
			
		||||
	int res = true, idx = GET_LOOP_FEEDBACK(arr,ref1,ref2);	\
 | 
			
		||||
	if (idx >= 0) {						\
 | 
			
		||||
		if (--arr.table[idx][2] == 0)			\
 | 
			
		||||
| 
						 | 
				
			
			@ -397,15 +398,43 @@ jack_connection_manager_reset(struct jack_connection_manager *conn,
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static inline int
 | 
			
		||||
jack_connection_manager_add_port(struct jack_connection_manager *conn, bool input,
 | 
			
		||||
				 int ref_num, jack_port_id_t port_id)
 | 
			
		||||
jack_connection_manager_add_inport(struct jack_connection_manager *conn,
 | 
			
		||||
				   int ref_num, jack_port_id_t port_id)
 | 
			
		||||
{
 | 
			
		||||
	if (input) {
 | 
			
		||||
		return ADD_FIXED_ARRAY1(conn->input_port[ref_num], port_id);
 | 
			
		||||
	}
 | 
			
		||||
	else {
 | 
			
		||||
		return ADD_FIXED_ARRAY(conn->output_port[ref_num], port_id);
 | 
			
		||||
	}
 | 
			
		||||
	return ADD_FIXED_ARRAY1(conn->input_port[ref_num], port_id);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int
 | 
			
		||||
jack_connection_manager_remove_inport(struct jack_connection_manager *conn,
 | 
			
		||||
				      int ref_num, jack_port_id_t port_id)
 | 
			
		||||
{
 | 
			
		||||
	return REMOVE_FIXED_ARRAY1(conn->input_port[ref_num], port_id);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int
 | 
			
		||||
jack_connection_manager_add_outport(struct jack_connection_manager *conn,
 | 
			
		||||
				    int ref_num, jack_port_id_t port_id)
 | 
			
		||||
{
 | 
			
		||||
	return ADD_FIXED_ARRAY(conn->output_port[ref_num], port_id);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int
 | 
			
		||||
jack_connection_manager_remove_outport(struct jack_connection_manager *conn,
 | 
			
		||||
				       int ref_num, jack_port_id_t port_id)
 | 
			
		||||
{
 | 
			
		||||
	return REMOVE_FIXED_ARRAY(conn->output_port[ref_num], port_id);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline const jack_int_t *
 | 
			
		||||
jack_connection_manager_get_inputs(struct jack_connection_manager *conn, int ref_num)
 | 
			
		||||
{
 | 
			
		||||
	return GET_ITEMS_FIXED_ARRAY1(conn->input_port[ref_num]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline const jack_int_t *
 | 
			
		||||
jack_connection_manager_get_outputs(struct jack_connection_manager *conn, int ref_num)
 | 
			
		||||
{
 | 
			
		||||
	return GET_ITEMS_FIXED_ARRAY(conn->output_port[ref_num]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int
 | 
			
		||||
| 
						 | 
				
			
			@ -497,6 +526,19 @@ jack_connection_manager_inc_feedback_connection(struct jack_connection_manager *
 | 
			
		|||
	return INC_LOOP_FEEDBACK(conn->loop_feedback, ref1, ref2);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline bool
 | 
			
		||||
jack_connection_manager_dec_feedback_connection(struct jack_connection_manager *conn,
 | 
			
		||||
						jack_port_id_t src_id, jack_port_id_t dst_id)
 | 
			
		||||
{
 | 
			
		||||
	int ref1 = jack_connection_manager_get_output_refnum(conn, src_id);
 | 
			
		||||
	int ref2 = jack_connection_manager_get_input_refnum(conn, dst_id);
 | 
			
		||||
 | 
			
		||||
	if (ref1 != ref2)
 | 
			
		||||
		jack_connection_manager_direct_disconnect(conn, ref2, ref1);
 | 
			
		||||
 | 
			
		||||
	return DEC_LOOP_FEEDBACK(conn->loop_feedback, ref1, ref2);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void
 | 
			
		||||
jack_connection_manager_inc_direct_connection(struct jack_connection_manager *conn,
 | 
			
		||||
					      jack_port_id_t src_id, jack_port_id_t dst_id)
 | 
			
		||||
| 
						 | 
				
			
			@ -517,6 +559,55 @@ jack_connection_manager_dec_direct_connection(struct jack_connection_manager *co
 | 
			
		|||
	jack_connection_manager_direct_disconnect(conn, ref1, ref2);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int
 | 
			
		||||
jack_connection_manager_connect_ports(struct jack_connection_manager *conn,
 | 
			
		||||
				      jack_port_id_t src_id, jack_port_id_t dst_id)
 | 
			
		||||
{
 | 
			
		||||
	if (jack_connection_manager_is_connected(conn, src_id, dst_id)) {
 | 
			
		||||
                pw_log_error("connection %p: ports are already connected", conn);
 | 
			
		||||
                return -1;
 | 
			
		||||
        }
 | 
			
		||||
        if (jack_connection_manager_connect(conn, src_id, dst_id) < 0) {
 | 
			
		||||
                pw_log_error("connection %p: connection table is full", conn);
 | 
			
		||||
                return -1;
 | 
			
		||||
        }
 | 
			
		||||
        if (jack_connection_manager_connect(conn, dst_id, src_id) < 0) {
 | 
			
		||||
                pw_log_error("connection %p: connection table is full", conn);
 | 
			
		||||
                return -1;
 | 
			
		||||
        }
 | 
			
		||||
        if (jack_connection_manager_is_loop_path(conn, src_id, dst_id) < 0)
 | 
			
		||||
                jack_connection_manager_inc_feedback_connection(conn, src_id, dst_id);
 | 
			
		||||
        else
 | 
			
		||||
                jack_connection_manager_inc_direct_connection(conn, src_id, dst_id);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int
 | 
			
		||||
jack_connection_manager_disconnect_ports(struct jack_connection_manager *conn,
 | 
			
		||||
					 jack_port_id_t src_id, jack_port_id_t dst_id)
 | 
			
		||||
{
 | 
			
		||||
	if (!jack_connection_manager_is_connected(conn, src_id, dst_id)) {
 | 
			
		||||
                pw_log_error("connection %p: ports are not connected", conn);
 | 
			
		||||
                return -1;
 | 
			
		||||
        }
 | 
			
		||||
        if (jack_connection_manager_disconnect(conn, src_id, dst_id) < 0) {
 | 
			
		||||
                pw_log_error("connection %p: connection table is full", conn);
 | 
			
		||||
                return -1;
 | 
			
		||||
        }
 | 
			
		||||
        if (jack_connection_manager_disconnect(conn, dst_id, src_id) < 0) {
 | 
			
		||||
                pw_log_error("connection %p: connection table is full", conn);
 | 
			
		||||
                return -1;
 | 
			
		||||
        }
 | 
			
		||||
        if (jack_connection_manager_is_loop_path(conn, src_id, dst_id) < 0)
 | 
			
		||||
                jack_connection_manager_dec_feedback_connection(conn, src_id, dst_id);
 | 
			
		||||
        else
 | 
			
		||||
                jack_connection_manager_dec_direct_connection(conn, src_id, dst_id);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static inline int
 | 
			
		||||
jack_connection_manager_get_activation(struct jack_connection_manager *conn, int ref_num)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -918,7 +1009,7 @@ jack_engine_control_alloc(const char* name)
 | 
			
		|||
        ctrl = (struct jack_engine_control *)jack_shm_addr(&info);
 | 
			
		||||
        ctrl->info = info;
 | 
			
		||||
 | 
			
		||||
	ctrl->buffer_size = 128;
 | 
			
		||||
	ctrl->buffer_size = 64;
 | 
			
		||||
        ctrl->sample_rate = 48000;
 | 
			
		||||
	ctrl->sync_mode = false;
 | 
			
		||||
	ctrl->temporary = false;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -31,7 +31,7 @@ static inline int
 | 
			
		|||
jack_synchro_init(struct jack_synchro *synchro,
 | 
			
		||||
		  const char *client_name,
 | 
			
		||||
		  const char *server_name,
 | 
			
		||||
		  int value, bool internal,
 | 
			
		||||
		  int value,
 | 
			
		||||
		  bool promiscuous)
 | 
			
		||||
{
 | 
			
		||||
	if (promiscuous)
 | 
			
		||||
| 
						 | 
				
			
			@ -43,12 +43,25 @@ jack_synchro_init(struct jack_synchro *synchro,
 | 
			
		|||
 | 
			
		||||
	synchro->flush = false;
 | 
			
		||||
	if ((synchro->semaphore = sem_open(synchro->name, O_CREAT | O_RDWR, 0777, value)) == (sem_t*)SEM_FAILED) {
 | 
			
		||||
		pw_log_error("can't check in named semaphore name = %s err = %s", synchro->name, strerror(errno));
 | 
			
		||||
		pw_log_error("can't check semaphore %s: %s", synchro->name, strerror(errno));
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline bool
 | 
			
		||||
jack_synchro_close(struct jack_synchro *synchro)
 | 
			
		||||
{
 | 
			
		||||
	if (synchro->semaphore == NULL)
 | 
			
		||||
		return true;
 | 
			
		||||
 | 
			
		||||
	if (sem_close(synchro->semaphore) < 0) {
 | 
			
		||||
		pw_log_warn("can't close semaphore %s: %s", synchro->name, strerror(errno));
 | 
			
		||||
	}
 | 
			
		||||
	synchro->semaphore = NULL;
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline bool
 | 
			
		||||
jack_synchro_signal(struct jack_synchro *synchro)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue