diff --git a/src/modules/meson.build b/src/modules/meson.build index 2ab26c7b1..33db36407 100644 --- a/src/modules/meson.build +++ b/src/modules/meson.build @@ -102,20 +102,6 @@ pipewire_module_audio_dsp = shared_library('pipewire-module-audio-dsp', dependencies : [mathlib, dl_lib, rt_lib, pipewire_dep], ) -if jack_dep.found() -pipewire_module_jack = shared_library('pipewire-module-jack', - [ 'module-jack.c', - 'module-jack/shm.c', - 'module-jack/jack-node.c' ], - c_args : pipewire_module_c_args, - include_directories : [configinc, spa_inc], - link_with : spalib, - install : true, - install_dir : modules_install_dir, - dependencies : [jack_dep, mathlib, dl_lib, rt_lib, pipewire_dep], -) -endif - pipewire_module_suspend_on_idle = shared_library('pipewire-module-suspend-on-idle', [ 'module-suspend-on-idle.c' ], c_args : pipewire_module_c_args, include_directories : [configinc, spa_inc], diff --git a/src/modules/module-jack.c b/src/modules/module-jack.c deleted file mode 100644 index da285324e..000000000 --- a/src/modules/module-jack.c +++ /dev/null @@ -1,1581 +0,0 @@ -/* PipeWire - * Copyright (C) 2015 Wim Taymans - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "config.h" - -#include "pipewire/pipewire.h" -#include "pipewire/log.h" -#include "pipewire/interfaces.h" - -#include "pipewire/core.h" -#include "pipewire/node.h" -#include "pipewire/module.h" -#include "pipewire/client.h" -#include "pipewire/resource.h" -#include "pipewire/private.h" -#include "pipewire/link.h" -#include "pipewire/factory.h" -#include "pipewire/data-loop.h" -#include "pipewire/main-loop.h" - -#include "modules/module-jack/jack.h" -#include "modules/module-jack/jack-node.h" - -#ifndef UNIX_PATH_MAX -#define UNIX_PATH_MAX 108 -#endif - -#define LOCK_SUFFIX ".lock" -#define LOCK_SUFFIXLEN 5 - -int segment_num = 0; - -struct socket { - int fd; - struct sockaddr_un addr; - char lock_addr[UNIX_PATH_MAX + LOCK_SUFFIXLEN]; - - struct pw_loop *loop; - struct spa_source *source; - struct spa_list link; -}; - -struct impl { - uint32_t prop_min_latency; - - struct pw_core *core; - struct pw_type *t; - struct pw_module *module; - struct spa_hook module_listener; - - struct spa_source *timer; - - struct pw_properties *properties; - - struct spa_list socket_list; - struct spa_list client_list; - struct spa_list link_list; - struct spa_list node_list; - - struct spa_loop_control_hooks hooks; - - struct jack_server server; - - struct pw_link *sink_link; - - struct { - struct spa_list nodes; - } rt; -}; - -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; - struct spa_list link_link; -}; - -static bool init_socket_name(struct sockaddr_un *addr, const char *name, bool promiscuous, int which) -{ - int name_size, i; - const char *runtime_dir; - char cname[SYNC_MAX_NAME_SIZE+1]; - - for (i = 0; name[i] != '\0'; i++) { - if (name[i] == '/' || name[i] == '\\') - cname[i] = '_'; - else - cname[i] = name[i]; - } - cname[i] = name[i]; - - runtime_dir = JACK_SOCKET_DIR; - - addr->sun_family = AF_UNIX; - if (promiscuous) { - name_size = snprintf(addr->sun_path, sizeof(addr->sun_path), - "%s/jack_%s_%d", runtime_dir, cname, which) + 1; - } else { - name_size = snprintf(addr->sun_path, sizeof(addr->sun_path), - "%s/jack_%s_%d_%d", runtime_dir, cname, getuid(), which) + 1; - } - - if (name_size > (int) sizeof(addr->sun_path)) { - pw_log_error("socket path \"%s/%s\" plus null terminator exceeds 108 bytes", - runtime_dir, cname); - *addr->sun_path = 0; - return false; - } - return true; -} - -static int -notify_client(struct jack_client *client, int ref_num, const char *name, int notify, - int sync, const char* message, int value1, int value2) -{ - int size, result = 0; - char _name[JACK_CLIENT_NAME_SIZE+1]; - char _message[JACK_MESSAGE_SIZE+1]; - - if (client->fd == -1) - return 0; - - if (!client->node->control->callback[notify]) - return 0; - - if (name == NULL) - name = client->node->control->name; - - snprintf(_name, sizeof(_name), "%s", name); - snprintf(_message, sizeof(_message), "%s", message); - - size = sizeof(int) + sizeof(_name) + 5 * sizeof(int) + sizeof(_message); - CheckWrite(&size, sizeof(int)); - CheckWrite(_name, sizeof(_name)); - CheckWrite(&ref_num, sizeof(int)); - CheckWrite(¬ify, sizeof(int)); - CheckWrite(&value1, sizeof(int)); - CheckWrite(&value2, sizeof(int)); - CheckWrite(&sync, sizeof(int)); - CheckWrite(_message, sizeof(_message)); - - if (sync) - CheckRead(&result, sizeof(int)); - - return result; -} - -static int -notify_add_client(struct impl *impl, struct jack_client *client, 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]; - const char *n; - - if (c == NULL || c == client) - continue; - - 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 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, - int sync, const char* message, int value1, int value2) -{ - 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; - notify_client(c, i, NULL, notify, sync, message, value1, value2); - } -} - -static void port_free(void *data) -{ - struct pw_jack_port *port = data; - struct port *p = port->user_data; - struct impl *impl = p->impl; - struct jack_client *jc = p->jc; - pw_log_debug("port %p: free", port); - - if (jc->node->control->active) - 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, - .free = port_free, -}; - -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; - 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; - struct jack_client *jc; - struct pw_jack_port *port; - struct port *p; - - CheckSize(kRegisterPort_size); - CheckRead(&ref_num, sizeof(int)); - CheckRead(name, sizeof(name)); - CheckRead(port_type, sizeof(port_type)); - CheckRead(&flags, sizeof(unsigned int)); - CheckRead(&buffer_size, sizeof(unsigned int)); - - pw_log_debug("protocol-jack %p: kRegisterPort %d %s %s %u %u", impl, - ref_num, name, port_type, flags, buffer_size); - - jc = server->client_table[ref_num]; - - 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; - - pw_jack_port_add_listener(port, &p->port_listener, &port_listener, port); - - 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)); - return 0; -} - -static int do_add_node(struct spa_loop *loop, bool async, uint32_t seq, const void *data, size_t size, - void *user_data) -{ - struct jack_client *jc = user_data; - struct impl *impl = jc->data; - spa_list_append(&impl->rt.nodes, &jc->node->graph_link); - return 0; -} - -static int do_remove_node(struct spa_loop *loop, bool async, uint32_t seq, const void *data, size_t size, - void *user_data) -{ - struct jack_client *jc = user_data; - spa_list_remove(&jc->node->graph_link); - return 0; -} - -static int -handle_activate_client(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; - 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)); - CheckRead(&is_real_time, sizeof(int)); - - pw_log_debug("protocol-jack %p: kActivateClient %d %d", client->impl, - ref_num, is_real_time); - - conn = jack_graph_manager_next_start(mgr); - - if (is_real_time) { - 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); - - jc = server->client_table[ref_num]; - if (jc) { - notify_client(jc, ref_num, NULL, jack_notify_ActivateClient, true, "", 0, 0); - jc->activated = true; - jc->realtime = is_real_time; - if (is_real_time) - pw_loop_invoke(jc->node->node->data_loop, - do_add_node, 0, NULL, 0, false, jc); - } - - 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); - - CheckWrite(&result, sizeof(int)); - return 0; -} - -static int client_deactivate(struct impl *impl, int ref_num) -{ - struct jack_server *server = &impl->server; - int fw_ref = server->freewheel_ref_num, i, j; - struct jack_graph_manager *mgr = server->graph_manager; - struct jack_connection_manager *conn; - struct jack_client *jc; - const jack_int_t *inputs, *outputs; - jack_int_t conns[CONNECTION_NUM_FOR_PORT]; - - jc = server->client_table[ref_num]; - if (jc) { - jc->activated = false; - if (jc->realtime) - pw_loop_invoke(jc->node->node->data_loop, - do_remove_node, 0, NULL, 0, false, jc); - } - - conn = jack_graph_manager_next_start(mgr); - - if (jack_connection_manager_is_direct_connection(conn, fw_ref, ref_num)) - jack_connection_manager_direct_disconnect(conn, fw_ref, ref_num); - - if (jack_connection_manager_is_direct_connection(conn, ref_num, fw_ref)) - jack_connection_manager_direct_disconnect(conn, ref_num, fw_ref); - - inputs = jack_connection_manager_get_inputs(conn, ref_num); - outputs = jack_connection_manager_get_outputs(conn, ref_num); - - for (i = 0; (i < PORT_NUM_FOR_CLIENT) && (inputs[i] != EMPTY); i++) { - memcpy(conns, jack_connection_manager_get_connections(conn, inputs[i]), sizeof(conns)); - for (j = 0; (j < CONNECTION_NUM_FOR_PORT) && (conns[j] != EMPTY); j++) { - jack_connection_manager_disconnect_ports(conn, conns[j], inputs[i]); - notify_clients(impl, jack_notify_PortDisconnectCallback, - false, "", conns[j], inputs[i]); - } - } - for (i = 0; (i < PORT_NUM_FOR_CLIENT) && (outputs[i] != EMPTY); i++) { - memcpy(conns, jack_connection_manager_get_connections(conn, outputs[i]), sizeof(conns)); - for (j = 0; (j < CONNECTION_NUM_FOR_PORT) && (conns[j] != EMPTY); j++) { - jack_connection_manager_disconnect_ports(conn, outputs[i], conns[j]); - notify_clients(impl, jack_notify_PortDisconnectCallback, - false, "", outputs[i], conns[j]); - } - } - - for (i = 0; (i < PORT_NUM_FOR_CLIENT) && (inputs[i] != EMPTY); i++) - notify_clients(impl, jack_notify_PortRegistrationOffCallback, false, "", inputs[i], 0); - for (i = 0; (i < PORT_NUM_FOR_CLIENT) && (outputs[i] != EMPTY); i++) - notify_clients(impl, jack_notify_PortRegistrationOffCallback, false, "", outputs[i], 0); - - jack_graph_manager_next_stop(mgr); - - 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; -} - -static int -handle_set_timebase_callback(struct client *client) -{ - struct impl *impl = client->impl; - struct jack_server *server = &impl->server; - int result = 0; - int ref_num, conditional, tbm; - - CheckSize(kSetTimebaseCallback_size); - CheckRead(&ref_num, sizeof(int)); - CheckRead(&conditional, sizeof(int)); - - pw_log_debug("protocol-jack %p: kSetTimebaseCallback %d", client->impl, ref_num); - - tbm = server->engine_control->transport.time_base_master; - - if (conditional && tbm > 0) { - if (ref_num != tbm) { - pw_log_error("ref = %d failed: %d is already the master", ref_num, tbm); - result = EBUSY; - } else { - pw_log_debug("ref = %d was already timebase master", ref_num); - } - } else { - server->engine_control->transport.time_base_master = ref_num; - server->engine_control->transport.conditional = conditional; - pw_log_debug("new timebase master: ref = %d", ref_num); - } - CheckWrite(&result, sizeof(int)); - return 0; -} - -static int -handle_client_check(struct client *client) -{ - char name[JACK_CLIENT_NAME_SIZE+1]; - int protocol; - int options; - int UUID; - int open; - int result = 0; - int status; - - CheckSize(kClientCheck_size); - CheckRead(name, sizeof(name)); - CheckRead(&protocol, sizeof(int)); - CheckRead(&options, sizeof(int)); - CheckRead(&UUID, sizeof(int)); - CheckRead(&open, sizeof(int)); - - pw_log_debug("protocol-jack %p: kClientCheck %s %d %d %d %d", client->impl, - name, protocol, options, UUID, open); - - status = 0; - if (protocol != JACK_PROTOCOL_VERSION) { - status |= (JackFailure | JackVersionError); - pw_log_error("protocol-jack: protocol mismatch (%d vs %d)", protocol, JACK_PROTOCOL_VERSION); - result = -1; - goto reply; - } - /* TODO check client name and uuid */ - - reply: - CheckWrite(&result, sizeof(int)); - CheckWrite(name, sizeof(name)); - CheckWrite(&status, sizeof(int)); - - if (open) - return process_messages(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); - - if (jc->activated) { - client_deactivate(impl, ref_num); - if (jc->realtime) - spa_list_remove(&jc->node->graph_link); - } - spa_list_remove(&jc->client_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; - 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; - struct pw_properties *properties; - - CheckSize(kClientOpen_size); - CheckRead(&PID, sizeof(int)); - CheckRead(&UUID, sizeof(int)); - CheckRead(name, sizeof(name)); - - ucred = pw_client_get_ucred(client->client); - - properties = pw_properties_new(NULL, NULL); - pw_properties_setf(properties, "application.jack.PID", "%d", PID); - pw_properties_setf(properties, "application.jack.UUID", "%d", UUID); - - node = pw_jack_node_new(impl->core, - pw_client_get_global(client->client), - server, - name, - ucred ? ucred->pid : PID, - properties, - sizeof(struct jack_client)); - if (node == NULL) { - pw_log_error("module-jack %p: can't create node", impl); - goto reply; - } - - ref_num = node->control->ref_num; - - jc = node->user_data; - jc->fd = -1; - jc->data = impl; - jc->owner = client; - jc->node = node; - - 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)); - goto reply; - } - - if (!init_socket_name(&addr, name, server->promiscuous, 0)) - goto reply; - - if (connect(jc->fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) { - pw_log_error("module-jack %p: can't connect socket %s", impl, strerror(errno)); - goto reply; - } - - server->client_table[ref_num] = jc; - pw_log_debug("module-jack %p: Added client %d \"%s\"", impl, ref_num, name); - - spa_list_append(&client->jack_clients, &jc->client_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; - } - - shared_engine = impl->server.engine_control->info.index; - shared_client = jc->node->control->info.index; - shared_graph = impl->server.graph_manager->info.index; - - result = 0; - - reply: - CheckWrite(&result, sizeof(int)); - CheckWrite(&shared_engine, sizeof(int)); - CheckWrite(&shared_client, sizeof(int)); - CheckWrite(&shared_graph, sizeof(int)); - - return 0; -} - -static int -handle_client_close(struct client *client) -{ - int ref_num; - CheckSize(kClientClose_size); - 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); - - spa_list_remove(&ld->link_link); - - conn = jack_graph_manager_next_start(mgr); - if (jack_connection_manager_is_connected(conn, src_id, dst_id)) { - if (jack_connection_manager_disconnect_ports(conn, src_id, dst_id)) { - pw_log_warn("module-jack %p: ports can't disconnect", impl); - } - notify_clients(impl, jack_notify_PortDisconnectCallback, false, "", src_id, dst_id); - } - jack_graph_manager_next_stop(mgr); - -} - -static const struct pw_link_events link_events = { - PW_VERSION_LINK_EVENTS, - .destroy = link_destroy, -}; - -static int -handle_connect_name_ports(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; - struct jack_client *jc; - int ref_num; - char src[REAL_JACK_PORT_NAME_SIZE+1]; - char dst[REAL_JACK_PORT_NAME_SIZE+1]; - int result = -1, in_ref, out_ref; - jack_port_id_t src_id, dst_id; - struct jack_port *src_port, *dst_port; - struct pw_jack_port *out_port, *in_port; - struct pw_link *link; - struct link *ld; - - CheckSize(kConnectNamePorts_size); - CheckRead(&ref_num, sizeof(int)); - CheckRead(src, sizeof(src)); - CheckRead(dst, sizeof(dst)); - - src_id = jack_graph_manager_find_port(mgr, src); - if (src_id == NO_PORT) { - pw_log_error("protocol-jack %p: port_name %s does not exist", impl, src); - goto reply; - } - dst_id = jack_graph_manager_find_port(mgr, dst); - if (dst_id == NO_PORT) { - pw_log_error("protocol-jack %p: port_name %s does not exist", impl, dst); - goto reply; - } - - pw_log_debug("protocol-jack %p: kConnectNamePort %d %s %s %u %u", impl, - ref_num, src, dst, src_id, dst_id); - - src_port = jack_graph_manager_get_port(mgr, src_id); - dst_port = jack_graph_manager_get_port(mgr, dst_id); - - if (((src_port->flags & JackPortIsOutput) == 0) || - ((dst_port->flags & JackPortIsInput) == 0)) { - pw_log_error("protocol-jack %p: ports are not input and output", impl); - goto reply; - } - - if (!src_port->in_use || !dst_port->in_use) { - pw_log_error("protocol-jack %p: ports are not in use", impl); - goto reply; - } - if (src_port->type_id != dst_port->type_id) { - pw_log_error("protocol-jack %p: ports are not of the same type", impl); - goto reply; - } - - conn = jack_graph_manager_next_start(mgr); - - out_ref = jack_connection_manager_get_output_refnum(conn, src_id); - if (out_ref == -1) { - pw_log_error("protocol-jack %p: unknown port_id %d", impl, src_id); - goto reply_stop; - } - if ((jc = server->client_table[out_ref]) == NULL) { - pw_log_error("protocol-jack %p: unknown client %d", impl, out_ref); - goto reply_stop; - } - if (!jc->node->control->active) { - pw_log_error("protocol-jack %p: can't connect ports of inactive client", impl); - goto reply_stop; - } - out_port = pw_jack_node_find_port(jc->node, PW_DIRECTION_OUTPUT, src_id); - - in_ref = jack_connection_manager_get_input_refnum(conn, dst_id); - if (in_ref == -1) { - pw_log_error("protocol-jack %p: unknown port_id %d", impl, dst_id); - goto reply_stop; - } - if ((jc = server->client_table[in_ref]) == NULL) { - pw_log_error("protocol-jack %p: unknown client %d", impl, in_ref); - goto reply_stop; - } - 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_connect_ports(conn, src_id, dst_id)) { - pw_log_error("protocol-jack %p: ports can't connect", impl); - goto reply_stop; - } - pw_log_debug("protocol-jack %p: connected ports %p %p", impl, out_port, in_port); - - link = pw_link_new(impl->core, - out_port->port, - in_port->port, - NULL, - NULL, - NULL, - 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; - spa_list_append(&impl->link_list, &ld->link_link); - pw_link_add_listener(link, &ld->link_listener, &link_events, ld); - pw_link_register(link, NULL, pw_module_get_global(impl->module), NULL); - - notify_clients(impl, jack_notify_PortConnectCallback, false, "", src_id, dst_id); - - result = 0; - reply_stop: - jack_graph_manager_next_stop(mgr); - - reply: - CheckWrite(&result, sizeof(int)); - return 0; -} - -static int -handle_disconnect_name_ports(struct client *client) -{ - struct link *link, *t; - struct impl *impl = client->impl; - int result = -1; - int ref_num; - char src[REAL_JACK_PORT_NAME_SIZE+1]; - char dst[REAL_JACK_PORT_NAME_SIZE+1]; - - CheckSize(kDisconnectNamePorts_size); - CheckRead(&ref_num, sizeof(int)); - CheckRead(src, sizeof(src)); - CheckRead(dst, sizeof(dst)); - - spa_list_for_each_safe(link, t, &impl->link_list, link_link) { - if ((strcmp(link->out_port->jack_port->name, src) == 0) && - (strcmp(link->in_port->jack_port->name, dst) == 0)) { - pw_link_destroy(link->link); - result = 0; - break; - } - } - - CheckWrite(&result, sizeof(int)); - return 0; -} - -static int -handle_get_UUID_by_client(struct client *client) -{ - char name[JACK_CLIENT_NAME_SIZE+1]; - char UUID[JACK_UUID_SIZE]; - int result = 0; - - CheckSize(kGetUUIDByClient_size); - CheckRead(name, sizeof(name)); - - CheckWrite(&result, sizeof(int)); - CheckWrite(UUID, sizeof(UUID)); - - return 0; -} - -static int -process_messages(struct client *client) -{ - struct pw_client *c = client->client; - struct pw_core *core = c->core; - int type, res = -1; - - core->current_client = c; - - if (read(client->fd, &type, sizeof(enum jack_request_type)) != sizeof(enum jack_request_type)) { - pw_log_error("protocol-jack %p: failed to read type", client->impl); - goto error; - } - pw_log_info("protocol-jack %p: got type %d", client->impl, type); - - switch(type) { - case jack_request_RegisterPort: - res = handle_register_port(client); - break; - case jack_request_UnRegisterPort: - break; - case jack_request_ConnectPorts: - break; - case jack_request_DisconnectPorts: - break; - case jack_request_SetTimeBaseClient: - break; - case jack_request_ActivateClient: - res = handle_activate_client(client); - break; - case jack_request_DeactivateClient: - res = handle_deactivate_client(client); - break; - case jack_request_DisconnectPort: - break; - case jack_request_SetClientCapabilities: - case jack_request_GetPortConnections: - case jack_request_GetPortNConnections: - case jack_request_ReleaseTimebase: - case jack_request_SetTimebaseCallback: - res = handle_set_timebase_callback(client); - break; - case jack_request_SetBufferSize: - case jack_request_SetFreeWheel: - break; - case jack_request_ClientCheck: - res = handle_client_check(client); - break; - case jack_request_ClientOpen: - res = handle_client_open(client); - break; - case jack_request_ClientClose: - res = handle_client_close(client); - break; - case jack_request_ConnectNamePorts: - res = handle_connect_name_ports(client); - break; - case jack_request_DisconnectNamePorts: - res = handle_disconnect_name_ports(client); - break; - case jack_request_GetInternalClientName: - case jack_request_InternalClientHandle: - case jack_request_InternalClientLoad: - case jack_request_InternalClientUnload: - case jack_request_PortRename: - case jack_request_Notification: - case jack_request_SessionNotify: - case jack_request_SessionReply: - case jack_request_GetClientByUUID: - case jack_request_ReserveClientName: - break; - case jack_request_GetUUIDByClient: - res = handle_get_UUID_by_client(client); - break; - case jack_request_ClientHasSessionCallback: - case jack_request_ComputeTotalLatencies: - break; - default: - pw_log_error("protocol-jack %p: invalid type %d", client->impl, type); - goto error; - } - if (res != 0) - goto error; - - exit: - core->current_client = NULL; - return res; - - error: - pw_log_error("protocol-jack %p: error handling type %d", client->impl, type); - pw_client_destroy(c); - res = -EIO; - goto exit; - -} - -static void -client_busy_changed(void *data, bool busy) -{ - struct client *c = data; - enum spa_io mask = SPA_IO_ERR | SPA_IO_HUP; - - if (!busy) - mask |= SPA_IO_IN; - - pw_loop_update_io(pw_core_get_main_loop(c->impl->core), c->source, mask); - - if (!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) -{ - struct client *client = data; - - if (mask & (SPA_IO_ERR | SPA_IO_HUP)) { - pw_log_error("jack %p: got connection error", client->impl); - client_killed(client); - return; - } - - if (mask & SPA_IO_IN) - 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, - .busy_changed = client_busy_changed, -}; - -static struct client *client_new(struct impl *impl, int fd) -{ - struct client *this; - struct pw_client *client; - socklen_t len; - struct ucred ucred, *ucredp; - struct pw_properties *properties; - - len = sizeof(ucred); - if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len) < 0) { - pw_log_error("no peercred: %m"); - ucredp = NULL; - } else { - ucredp = &ucred; - } - - properties = pw_properties_new(PW_CLIENT_PROP_PROTOCOL, "protocol-jack", NULL); - if (properties == NULL) - goto no_props; - - client = pw_client_new(impl->core, ucredp, properties, sizeof(struct client)); - if (client == NULL) - 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), - this->fd, - SPA_IO_ERR | SPA_IO_HUP, false, connection_data, this); - if (this->source == NULL) - goto no_source; - - spa_list_init(&this->jack_clients); - spa_list_append(&impl->client_list, &this->link); - - pw_client_add_listener(client, &this->client_listener, &client_events, this); - - pw_client_register(client, NULL, pw_module_get_global(impl->module), NULL); - - pw_log_debug("module-jack %p: added new client", impl); - - return this; - - no_source: - free(this); - no_props: - no_client: - return NULL; -} - -static int do_graph_order_changed(struct spa_loop *loop, - bool async, - uint32_t seq, - const void *data, - size_t size, - void *user_data) -{ - struct impl *impl = user_data; - 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, i, NULL, jack_notify_LatencyCallback, true, "", 0, 0) < 0) - pw_log_warn("module-jack %p: can't notify capture latency", impl); - } - for (i = 0; i < CLIENT_NUM; i++) { - struct jack_client *c = server->client_table[i]; - if (c == NULL) - continue; - if (notify_client(c, i, NULL, jack_notify_LatencyCallback, true, "", 1, 0) < 0) - pw_log_warn("module-jack %p: can't notify playback latency", impl); - } - - notify_clients(impl, jack_notify_GraphOrderCallback, false, "", 0, 0); - return 0; -} - -static void jack_node_pull(void *data) -{ - struct jack_client *jc = data; - struct impl *impl = jc->data; - struct jack_server *server = &impl->server; - struct jack_graph_manager *mgr = server->graph_manager; - struct spa_graph_node *n = &jc->node->node->rt.node, *pn; - struct spa_graph_port *p, *pp; - bool res; - - jack_graph_manager_try_switch(mgr, &res); - if (res) { - pw_loop_invoke(pw_core_get_main_loop(impl->core), - do_graph_order_changed, 0, NULL, 0, false, impl); - } - - /* mix all input */ - spa_list_for_each(p, &n->ports[SPA_DIRECTION_INPUT], link) { - if ((pp = p->peer) == NULL || ((pn = pp->node) == NULL)) - continue; - pn->state = spa_node_process_input(pn->implementation); - } -} - -static void jack_node_push(void *data) -{ - struct jack_client *jc = data; - struct impl *impl = jc->data; - struct jack_server *server = &impl->server; - struct jack_graph_manager *mgr = server->graph_manager; - struct jack_connection_manager *conn; - int activation; - struct pw_jack_node *node; - struct spa_graph_node *n = &jc->node->node->rt.node, *pn; - struct spa_graph_port *p, *pp; - - conn = jack_graph_manager_get_current(mgr); - - activation = jack_connection_manager_get_activation(conn, server->freewheel_ref_num); - if (activation != 0) - pw_log_warn("resume %d, some client did not complete", activation); - - jack_connection_manager_reset(conn, mgr->client_timing); - - jack_activation_count_signal(&conn->input_counter[server->freewheel_ref_num], - &server->synchro_table[server->freewheel_ref_num]); - - spa_list_for_each(p, &n->ports[SPA_DIRECTION_INPUT], link) { - if ((pp = p->peer) == NULL || ((pn = pp->node) == NULL)) - continue; - pn->state = spa_node_process_output(pn->implementation); - } - - spa_list_for_each(node, &impl->rt.nodes, graph_link) { - n = &node->node->rt.node; - - spa_list_for_each(p, &n->ports[SPA_DIRECTION_OUTPUT], link) { - if ((pp = p->peer) == NULL || ((pn = pp->node) == NULL)) - continue; - pn->state = spa_node_process_output(pn->implementation); - } - n->state = spa_node_process_output(n->implementation); - - /* mix inputs */ - spa_list_for_each(p, &n->ports[SPA_DIRECTION_INPUT], link) { - if ((pp = p->peer) == NULL || ((pn = pp->node) == NULL)) - continue; - pn->state = spa_node_process_output(pn->implementation); - pn->state = spa_node_process_input(pn->implementation); - } - - n->state = spa_node_process_input(n->implementation); - - /* tee outputs */ - spa_list_for_each(p, &n->ports[SPA_DIRECTION_OUTPUT], link) { - if ((pp = p->peer) == NULL || ((pn = pp->node) == NULL)) - continue; - pn->state = spa_node_process_input(pn->implementation); - } - } - - -#if 0 - 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 const struct pw_jack_node_events jack_node_events = { - PW_VERSION_JACK_NODE_EVENTS, - .pull = jack_node_pull, - .push = jack_node_push, -}; - -static int -make_audio_client(struct impl *impl) -{ - struct jack_server *server = &impl->server; - int ref_num; - struct jack_client *jc; - struct pw_jack_node *node; - - 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; - } - - ref_num = node->control->ref_num; - - jc = node->user_data; - jc->fd = -1; - jc->data = impl; - jc->node = node; - pw_jack_node_add_listener(node, &jc->node_listener, &jack_node_events, jc); - - server->client_table[ref_num] = jc; - - server->audio_ref_num = ref_num; - server->audio_node = node; - - spa_list_append(&impl->node_list, &jc->link); - - pw_log_debug("module-jack %p: Added audio driver %d", impl, ref_num); - - return 0; -} - -static int -make_freewheel_client(struct impl *impl) -{ - struct jack_server *server = &impl->server; - int ref_num; - struct jack_client *jc; - struct pw_jack_node *node; - - 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; - } - - ref_num = node->control->ref_num; - - jc = node->user_data; - jc->fd = -1; - jc->data = impl; - jc->node = node; - - server->client_table[ref_num] = jc; - - server->freewheel_ref_num = ref_num; - pw_log_debug("module-jack %p: Added freewheel driver %d", impl, ref_num); - - spa_list_append(&impl->node_list, &jc->link); - - return 0; -} - -static int on_global(void *data, struct pw_global *global) -{ - struct impl *impl = data; - struct pw_node *node; - const struct pw_properties *properties; - const char *str; - char *error; - struct pw_port *in_port, *out_port; - uint32_t index = 0; - uint8_t buf[2048]; - struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buf, sizeof(buf)); - struct spa_pod *props; - - if (pw_global_get_type(global) != impl->t->node) - return 0; - - node = pw_global_get_object(global); - - if (impl->properties && - (str = pw_properties_get(impl->properties, "jack.node"))) { - if (pw_global_get_id(global) != atoi(str)) - return 0; - } else { - properties = pw_node_get_properties(node); - if ((str = pw_properties_get(properties, "media.class")) == NULL) - return 0; - - if (strcmp(str, "Audio/Sink") != 0) - return 0; - } - - pw_log_debug("try link with node %d", pw_global_get_id(global)); - - 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 0; - - impl->sink_link = pw_link_new(impl->core, - out_port, - in_port, - NULL, - pw_properties_new(PW_LINK_PROP_PASSIVE, "true", NULL), - &error, - 0); - if (impl->sink_link == NULL) { - pw_log_warn("can't link ports: %s", error); - free(error); - return 0; - } - - if (spa_node_enum_params(node->node, impl->t->param.idProps, &index, NULL, &props, &b) == 1) { - int min_latency = -1; - - spa_pod_object_parse(props, - ":", impl->prop_min_latency, "?i", &min_latency, NULL); - - if (min_latency != -1) - jack_engine_control_set_buffer_size(impl->server.engine_control, min_latency); - } - pw_log_debug("module-jack %p: using buffer_size %d", impl, - impl->server.engine_control->buffer_size); - - pw_link_register(impl->sink_link, NULL, pw_module_get_global(impl->module), NULL); - - return 1; -} - -static bool init_nodes(struct impl *impl) -{ - struct pw_core *core = impl->core; - - make_audio_client(impl); - make_freewheel_client(impl); - - pw_core_for_each_global(core, on_global, impl); - - return true; -} - -static struct socket *create_socket(void) -{ - struct socket *s; - - if ((s = calloc(1, sizeof(struct socket))) == NULL) - return NULL; - - s->fd = -1; - return s; -} - -static void destroy_socket(struct socket *s) -{ - if (s->source) - pw_loop_destroy_source(s->loop, s->source); - if (s->addr.sun_path[0]) - unlink(s->addr.sun_path); - if (s->fd >= 0) - close(s->fd); - if (s->lock_addr[0]) - unlink(s->lock_addr); - free(s); -} - -static void -socket_data(void *data, int fd, enum spa_io mask) -{ - struct impl *impl = data; - struct client *client; - struct sockaddr_un name; - socklen_t length; - int client_fd; - - length = sizeof(name); - client_fd = accept4(fd, (struct sockaddr *) &name, &length, SOCK_CLOEXEC); - if (client_fd < 0) { - pw_log_error("failed to accept: %m"); - return; - } - - client = client_new(impl, client_fd); - if (client == NULL) { - pw_log_error("failed to create client"); - close(client_fd); - return; - } - - pw_loop_update_io(pw_core_get_main_loop(impl->core), - client->source, SPA_IO_IN | SPA_IO_ERR | SPA_IO_HUP); -} - -static bool add_socket(struct impl *impl, struct socket *s) -{ - socklen_t size; - - if ((s->fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0)) < 0) - return false; - - size = offsetof(struct sockaddr_un, sun_path) + strlen(s->addr.sun_path); - if (bind(s->fd, (struct sockaddr *) &s->addr, size) < 0) { - pw_log_error("bind() failed with error: %m"); - return false; - } - - if (listen(s->fd, 100) < 0) { - pw_log_error("listen() failed with error: %m"); - return false; - } - - s->loop = pw_core_get_main_loop(impl->core); - s->source = pw_loop_add_io(s->loop, s->fd, SPA_IO_IN, false, socket_data, impl); - if (s->source == NULL) - return false; - - spa_list_append(&impl->socket_list, &s->link); - - return true; -} - -static int init_server(struct impl *impl, const char *name, bool promiscuous) -{ - struct jack_server *server = &impl->server; - int i; - struct socket *s; - - pthread_mutex_init(&server->lock, NULL); - - if (jack_register_server(name, 1) != 0) - return -1; - - jack_cleanup_shm(); - - server->promiscuous = promiscuous; - - /* graph manager */ - server->graph_manager = jack_graph_manager_alloc(2048); - - /* engine control */ - server->engine_control = jack_engine_control_alloc(name); - - for (i = 0; i < CLIENT_NUM; i++) - server->synchro_table[i] = JACK_SYNCHRO_INIT; - - s = create_socket(); - - if (!init_socket_name(&s->addr, name, promiscuous, 0)) - goto error; - - if (!add_socket(impl, s)) - goto error; - - if (!init_nodes(impl)) - goto error; - - return 0; - - error: - destroy_socket(s); - return -1; -} - -static void module_destroy(void *data) -{ - struct impl *impl = data; - struct link *ld, *t; - struct jack_client *jc, *tc; - - spa_hook_remove(&impl->module_listener); - - spa_list_for_each_safe(ld, t, &impl->link_list, link_link) - pw_link_destroy(ld->link); - - spa_list_for_each_safe(jc, tc, &impl->node_list, link) - pw_jack_node_destroy(jc->node); - - if (impl->properties) - pw_properties_free(impl->properties); - - free(impl); -} - -static const struct pw_module_events module_events = { - PW_VERSION_MODULE_EVENTS, - .destroy = module_destroy, -}; - -static int module_init(struct pw_module *module, struct pw_properties *properties) -{ - struct pw_core *core = pw_module_get_core(module); - struct impl *impl; - const char *name, *str; - bool promiscuous; - - impl = calloc(1, sizeof(struct impl)); - if (impl == NULL) - return -ENOMEM; - - pw_log_debug("protocol-jack %p: new", impl); - - impl->core = core; - impl->t = pw_core_get_type(core); - impl->module = module; - impl->properties = properties; - impl->prop_min_latency = spa_type_map_get_id(impl->t->map, SPA_TYPE_PROPS__minLatency); - - spa_list_init(&impl->socket_list); - spa_list_init(&impl->client_list); - spa_list_init(&impl->link_list); - spa_list_init(&impl->node_list); - spa_list_init(&impl->rt.nodes); - - str = NULL; - if (impl->properties) - str = pw_properties_get(impl->properties, "jack.default.server"); - if (str == NULL) - str = getenv("JACK_DEFAULT_SERVER"); - - name = str ? str : JACK_DEFAULT_SERVER_NAME; - - str = NULL; - if (impl->properties) - str = pw_properties_get(impl->properties, "jack.promiscuous.server"); - if (str == NULL) - str = getenv("JACK_PROMISCUOUS_SERVER"); - - - promiscuous = str ? atoi(str) != 0 : false; - - if (init_server(impl, name, promiscuous) < 0) - goto error; - - pw_module_add_listener(module, &impl->module_listener, &module_events, impl); - - return 0; - - error: - free(impl); - return -ENOMEM; -} - -int pipewire__module_init(struct pw_module *module, const char *args) -{ - struct pw_properties *props = NULL; - - if (args) - props = pw_properties_new_string(args); - - return module_init(module, props); -} diff --git a/src/modules/module-jack/defs.h b/src/modules/module-jack/defs.h deleted file mode 100644 index 1bf4a952b..000000000 --- a/src/modules/module-jack/defs.h +++ /dev/null @@ -1,144 +0,0 @@ -/* PipeWire - * Copyright (C) 2017 Wim Taymans - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "pipewire/log.h" - -#define USE_POSIX_SHM -#undef JACK_MONITOR - -#define JACK_DEFAULT_SERVER_NAME "default" -#define JACK_SOCKET_DIR "/dev/shm" -#define JACK_SHM_DIR "/dev/shm" -#define JACK_SERVER_NAME_SIZE 256 -#define JACK_CLIENT_NAME_SIZE 64 -#define JACK_PORT_NAME_SIZE 256 -#define JACK_PORT_TYPE_SIZE 32 -#define JACK_PROTOCOL_VERSION 8 -#define JACK_MESSAGE_SIZE 256 - -#define PORT_NUM_MAX 4096 -#define PORT_NUM_FOR_CLIENT 2048 -#define CONNECTION_NUM_FOR_PORT PORT_NUM_FOR_CLIENT - -#define REAL_JACK_PORT_NAME_SIZE JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE - -#define BUFFER_SIZE_MAX 8192 - -#define CLIENT_NUM 256 - -#define JACK_ENGINE_ROLLING_COUNT 32 -#define JACK_ENGINE_ROLLING_INTERVAL 1024 - -#define TIME_POINTS 100000 -#define FAILURE_TIME_POINTS 10000 -#define FAILURE_WINDOW 10 -#define MEASURED_CLIENTS 32 - -#define SYNC_MAX_NAME_SIZE 256 - -#define JACK_UUID_SIZE 36 -#define JACK_UUID_STRING_SIZE (JACK_UUID_SIZE+1) - -#define JACK_SESSION_COMMAND_SIZE 256 - -#define NO_PORT 0xFFFE -#define EMPTY 0xFFFD -#define FREE 0xFFFC - -typedef enum { - JACK_TIMER_SYSTEM_CLOCK, - JACK_TIMER_HPET, -} jack_timer_type_t; - -enum jack_request_type { - jack_request_RegisterPort = 1, - jack_request_UnRegisterPort = 2, - jack_request_ConnectPorts = 3, - jack_request_DisconnectPorts = 4, - jack_request_SetTimeBaseClient = 5, - jack_request_ActivateClient = 6, - jack_request_DeactivateClient = 7, - jack_request_DisconnectPort = 8, - jack_request_SetClientCapabilities = 9, - jack_request_GetPortConnections = 10, - jack_request_GetPortNConnections = 11, - jack_request_ReleaseTimebase = 12, - jack_request_SetTimebaseCallback = 13, - jack_request_SetBufferSize = 20, - jack_request_SetFreeWheel = 21, - jack_request_ClientCheck = 22, - jack_request_ClientOpen = 23, - jack_request_ClientClose = 24, - jack_request_ConnectNamePorts = 25, - jack_request_DisconnectNamePorts = 26, - jack_request_GetInternalClientName = 27, - jack_request_InternalClientHandle = 28, - jack_request_InternalClientLoad = 29, - jack_request_InternalClientUnload = 30, - jack_request_PortRename = 31, - jack_request_Notification = 32, - jack_request_SessionNotify = 33, - jack_request_SessionReply = 34, - jack_request_GetClientByUUID = 35, - jack_request_ReserveClientName = 36, - jack_request_GetUUIDByClient = 37, - jack_request_ClientHasSessionCallback = 38, - jack_request_ComputeTotalLatencies = 39 -}; - -enum jack_notification_type { - jack_notify_AddClient = 0, - jack_notify_RemoveClient = 1, - jack_notify_ActivateClient = 2, - jack_notify_XRunCallback = 3, - jack_notify_GraphOrderCallback = 4, - jack_notify_BufferSizeCallback = 5, - jack_notify_SampleRateCallback = 6, - jack_notify_StartFreewheelCallback = 7, - jack_notify_StopFreewheelCallback = 8, - jack_notify_PortRegistrationOnCallback = 9, - jack_notify_PortRegistrationOffCallback = 10, - jack_notify_PortConnectCallback = 11, - jack_notify_PortDisconnectCallback = 12, - jack_notify_PortRenameCallback = 13, - jack_notify_RealTimeCallback = 14, - jack_notify_ShutDownCallback = 15, - jack_notify_QUIT = 16, - jack_notify_SessionCallback = 17, - jack_notify_LatencyCallback = 18, - jack_notify_max = 64 // To keep some room in JackClientControl fCallback table -}; - -#define kActivateClient_size (2*sizeof(int)) -#define kDeactivateClient_size (sizeof(int)) -#define kSetTimebaseCallback_size (sizeof(int) + sizeof(int)) -#define kRegisterPort_size (sizeof(int) + JACK_PORT_NAME_SIZE+1 + JACK_PORT_TYPE_SIZE+1 + 2*sizeof(unsigned int)) -#define kClientCheck_size (JACK_CLIENT_NAME_SIZE+1 + 4 * sizeof(int)) -#define kClientOpen_size (JACK_CLIENT_NAME_SIZE+1 + 2 * sizeof(int)) -#define kClientClose_size (sizeof(int)) -#define kConnectNamePorts_size (sizeof(int) + REAL_JACK_PORT_NAME_SIZE+1 + REAL_JACK_PORT_NAME_SIZE+1) -#define kDisconnectNamePorts_size (sizeof(int) + REAL_JACK_PORT_NAME_SIZE+1 + REAL_JACK_PORT_NAME_SIZE+1) -#define kGetUUIDByClient_size (JACK_CLIENT_NAME_SIZE+1) - -#define CheckRead(var,size) if(read(client->fd,var,size)!=size) {pw_log_error("read error"); return -1; } -#define CheckWrite(var,size) if(send(client->fd,var,size,MSG_NOSIGNAL)!=size) {pw_log_error("write error"); return -1; } -#define CheckSize(expected) { int __size; CheckRead(&__size, sizeof(int)); if (__size != expected) { pw_log_error("CheckSize error size %d != %d", __size, (int)expected); return -1; } } - -#define jack_error pw_log_error -#define jack_log pw_log_info diff --git a/src/modules/module-jack/jack-node.c b/src/modules/module-jack/jack-node.c deleted file mode 100644 index 05236ab32..000000000 --- a/src/modules/module-jack/jack-node.c +++ /dev/null @@ -1,1093 +0,0 @@ -/* PipeWire - * Copyright (C) 2015 Wim Taymans - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - -#include "pipewire/pipewire.h" -#include "pipewire/core.h" -#include "pipewire/private.h" - -#include "jack.h" -#include "jack-node.h" - -#define NAME "jack-node" - -/** \cond */ - -struct type { - uint32_t format; - struct spa_type_io io; - struct spa_type_param param; - struct spa_type_data data; - struct spa_type_media_type media_type; - struct spa_type_media_subtype media_subtype; - struct spa_type_format_audio format_audio; - struct spa_type_audio_format audio_format; - struct spa_type_media_subtype_audio media_subtype_audio; -}; - -static inline void init_type(struct type *type, struct spa_type_map *map) -{ - type->format = spa_type_map_get_id(map, SPA_TYPE__Format); - spa_type_io_map(map, &type->io); - spa_type_param_map(map, &type->param); - spa_type_data_map(map, &type->data); - spa_type_media_type_map(map, &type->media_type); - spa_type_media_subtype_map(map, &type->media_subtype); - spa_type_format_audio_map(map, &type->format_audio); - spa_type_audio_format_map(map, &type->audio_format); - spa_type_media_subtype_audio_map(map, &type->media_subtype_audio); -} - -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; - - struct spa_node node_impl; - struct port_data *port_data[2][PORT_NUM_FOR_CLIENT]; - int port_count[2]; - - int status; -}; - -struct buffer { - struct spa_list link; - struct spa_buffer *outbuf; - void *ptr; -}; - -struct port_data { - struct pw_jack_port port; - struct spa_hook port_listener; - - struct node_data *node; - - struct spa_hook_list listener_list; - - bool driver_port; - - struct spa_node mix_node; - - struct spa_port_info info; - - struct spa_io_buffers *io; - - bool have_buffers; - struct buffer buffers[64]; - uint32_t n_buffers; - struct spa_list empty; - - struct spa_buffer *bufs[1]; - struct spa_buffer buf; - struct spa_data data[1]; - struct spa_chunk chunk[1]; - - uint8_t buffer[1024]; -}; - -/** \endcond */ - -static int node_enum_params(struct spa_node *node, - uint32_t id, uint32_t *index, - const struct spa_pod *filter, - struct spa_pod **param, - struct spa_pod_builder *builder) -{ - return -ENOTSUP; -} - -static int node_set_param(struct spa_node *node, - uint32_t id, uint32_t flags, - const struct spa_pod *param) -{ - return -ENOTSUP; -} - -static int node_send_command(struct spa_node *node, - const struct spa_command *command) -{ - return 0; -} - -static int node_set_callbacks(struct spa_node *node, - const struct spa_node_callbacks *callbacks, void *data) -{ - return 0; -} - -static int node_get_n_ports(struct spa_node *node, - uint32_t *n_input_ports, - uint32_t *max_input_ports, - uint32_t *n_output_ports, - uint32_t *max_output_ports) -{ - struct node_data *nd = SPA_CONTAINER_OF(node, struct node_data, node_impl); - - if (n_input_ports) - *n_input_ports = nd->port_count[SPA_DIRECTION_INPUT]; - if (max_input_ports) - *max_input_ports = PORT_NUM_FOR_CLIENT / 2; - if (n_output_ports) - *n_output_ports = nd->port_count[SPA_DIRECTION_OUTPUT]; - if (max_output_ports) - *max_output_ports = PORT_NUM_FOR_CLIENT / 2; - - return 0; -} - -static int node_get_port_ids(struct spa_node *node, - uint32_t *input_ids, - uint32_t n_input_ids, - uint32_t *output_ids, - uint32_t n_output_ids) -{ - struct node_data *nd = SPA_CONTAINER_OF(node, struct node_data, node_impl); - int i, c; - - for (c = i = 0; i < PORT_NUM_FOR_CLIENT && c < n_input_ids; i++) { - if (nd->port_data[SPA_DIRECTION_INPUT][i]) - input_ids[c++] = nd->port_data[SPA_DIRECTION_INPUT][i]->port.port->port_id; - } - for (c = i = 0; i < PORT_NUM_FOR_CLIENT && c < n_output_ids; i++) { - if (nd->port_data[SPA_DIRECTION_OUTPUT][i]) - output_ids[c++] = nd->port_data[SPA_DIRECTION_OUTPUT][i]->port.port->port_id; - } - return 0; -} - -static int node_add_port(struct spa_node *node, enum spa_direction direction, uint32_t port_id) -{ - return -ENOTSUP; -} - -static int node_remove_port(struct spa_node *node, enum spa_direction direction, uint32_t port_id) -{ - return -ENOTSUP; -} - -static struct buffer *buffer_dequeue(struct pw_jack_node *this, struct port_data *pd) -{ - struct buffer *b; - - if (spa_list_is_empty(&pd->empty)) - return NULL; - - b = spa_list_first(&pd->empty, struct buffer, link); - spa_list_remove(&b->link); - - return b; -} - -static void recycle_buffer(struct pw_jack_node *this, struct port_data *pd, uint32_t id) -{ - struct buffer *b = &pd->buffers[id]; - pw_log_trace("recycle buffer %d", id); - spa_list_append(&pd->empty, &b->link); -} - -static int driver_process_input(struct spa_node *node) -{ - return -ENOTSUP; -} - -static void conv_f32_s16(int16_t *out, float *in, int n_samples, int stride) -{ - int i; - for (i = 0; i < n_samples; i++) { - if (in[i] < -1.0f) - *out = -32767; - else if (in[i] >= 1.0f) - *out = 32767; - else - *out = lrintf(in[i] * 32767.0f); - out += stride; - } -} -static void fill_s16(int16_t *out, int n_samples, int stride) -{ - int i; - for (i = 0; i < n_samples; i++) { - *out = 0; - out += stride; - } -} -static void add_f32(float *out, float *in, int n_samples) -{ - int i; - for (i = 0; i < n_samples; i++) - out[i] += in[i]; -} - -static int driver_process_output(struct spa_node *node) -{ - struct node_data *nd = SPA_CONTAINER_OF(node, struct node_data, node_impl); - struct pw_jack_node *this = &nd->node; - struct spa_graph_node *gn = &this->node->rt.node; - struct spa_graph_port *p; - struct port_data *opd = SPA_CONTAINER_OF(this->driver_out, struct port_data, port); - struct spa_io_buffers *out_io = opd->io; - struct jack_engine_control *ctrl = this->server->engine_control; - struct buffer *out; - int16_t *op; - - pw_log_trace(NAME "%p: process output", this); - - if (out_io->status == SPA_STATUS_HAVE_BUFFER) - return SPA_STATUS_HAVE_BUFFER; - - if (out_io->buffer_id < opd->n_buffers) { - recycle_buffer(this, opd, out_io->buffer_id); - out_io->buffer_id = SPA_ID_INVALID; - } - - out = buffer_dequeue(this, opd); - if (out == NULL) - return -EPIPE; - - out_io->buffer_id = out->outbuf->id; - out_io->status = SPA_STATUS_HAVE_BUFFER; - - op = out->ptr; - - spa_hook_list_call(&nd->listener_list, struct pw_jack_node_events, pull); - - spa_list_for_each(p, &gn->ports[SPA_DIRECTION_INPUT], link) { - struct pw_port *port = p->scheduler_data; - struct port_data *ipd = pw_port_get_user_data(port); - struct spa_io_buffers *in_io = ipd->io; - struct buffer *in; - int stride = 2; - - if (in_io->buffer_id < ipd->n_buffers && in_io->status == SPA_STATUS_HAVE_BUFFER) { - in = &ipd->buffers[in_io->buffer_id]; - conv_f32_s16(op, in->ptr, ctrl->buffer_size, stride); - } - else { - fill_s16(op, ctrl->buffer_size, stride); - } - op++; - in_io->status = SPA_STATUS_NEED_BUFFER; - } - - out->outbuf->datas[0].chunk->offset = 0; - out->outbuf->datas[0].chunk->size = ctrl->buffer_size * sizeof(int16_t) * 2; - out->outbuf->datas[0].chunk->stride = 0; - - spa_hook_list_call(&nd->listener_list, struct pw_jack_node_events, push); - gn->ready[SPA_DIRECTION_INPUT] = gn->required[SPA_DIRECTION_OUTPUT] = 0; - - return SPA_STATUS_HAVE_BUFFER; -} - -static int node_process_input(struct spa_node *node) -{ - struct node_data *nd = SPA_CONTAINER_OF(node, struct node_data, node_impl); - struct pw_jack_node *this = &nd->node; - struct spa_graph_node *gn = &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->control->ref_num; - - pw_log_trace(NAME " %p: process input", nd); - if (nd->status == SPA_STATUS_HAVE_BUFFER) - return SPA_STATUS_HAVE_BUFFER; - - mgr->client_timing[ref_num].status = Triggered; - mgr->client_timing[ref_num].signaled_at = current_date; - - conn = jack_graph_manager_get_current(mgr); - - jack_activation_count_signal(&conn->input_counter[ref_num], - &server->synchro_table[ref_num]); - - spa_list_for_each(p, &gn->ports[SPA_DIRECTION_OUTPUT], link) { - struct pw_port *port = p->scheduler_data; - struct port_data *opd = pw_port_get_user_data(port); - struct spa_io_buffers *out_io = opd->io; - out_io->buffer_id = 0; - out_io->status = SPA_STATUS_HAVE_BUFFER; - pw_log_trace(NAME " %p: port %p: %d %d", nd, p, out_io->buffer_id, out_io->status); - } - return nd->status = SPA_STATUS_HAVE_BUFFER; -} - -static int node_process_output(struct spa_node *node) -{ - struct node_data *nd = SPA_CONTAINER_OF(node, struct node_data, node_impl); - struct pw_jack_node *this = &nd->node; - struct spa_graph_node *gn = &this->node->rt.node; - struct spa_graph_port *p; - - pw_log_trace(NAME " %p: process output", nd); - spa_list_for_each(p, &gn->ports[SPA_DIRECTION_INPUT], link) { - struct pw_port *port = p->scheduler_data; - struct port_data *ipd = pw_port_get_user_data(port); - struct spa_io_buffers *in_io = ipd->io; - in_io->buffer_id = 0; - in_io->status = SPA_STATUS_NEED_BUFFER; - pw_log_trace(NAME " %p: port %p: %d %d", nd, p, in_io->buffer_id, in_io->status); - } - return nd->status = SPA_STATUS_NEED_BUFFER; -} - - -static int port_set_io(struct spa_node *node, - enum spa_direction direction, uint32_t port_id, - uint32_t id, void *data, size_t size) -{ - struct node_data *nd = SPA_CONTAINER_OF(node, struct node_data, node_impl); - struct port_data *pd = nd->port_data[direction][port_id]; - struct type *t = &pd->node->type; - - if (id == t->io.Buffers) - pd->io = data; - else - return -ENOENT; - - return 0; -} - -static int port_get_info(struct spa_node *node, enum spa_direction direction, uint32_t port_id, - const struct spa_port_info **info) -{ - struct node_data *nd = SPA_CONTAINER_OF(node, struct node_data, node_impl); - struct port_data *pd = nd->port_data[direction][port_id]; - struct pw_jack_port *port = &pd->port; - - pd->info.flags = SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS | SPA_PORT_INFO_FLAG_LIVE; - if (port->direction == PW_DIRECTION_OUTPUT && port->jack_port != NULL) - pd->info.flags |= SPA_PORT_INFO_FLAG_CAN_ALLOC_BUFFERS; - - pd->info.rate = pd->node->node.server->engine_control->sample_rate; - *info = &pd->info; - - return 0; -} - -static int port_enum_formats(struct spa_node *node, - enum spa_direction direction, uint32_t port_id, - uint32_t *index, - const struct spa_pod *filter, - struct spa_pod **param, - struct spa_pod_builder *builder) -{ - struct node_data *nd = SPA_CONTAINER_OF(node, struct node_data, node_impl); - struct port_data *pd = nd->port_data[direction][port_id]; - struct type *t = &pd->node->type; - struct jack_engine_control *ctrl = pd->node->node.server->engine_control; - - if (*index > 0) - return 0; - - if (pd->port.jack_port) { - if (pd->port.jack_port->type_id == 0) { - *param = spa_pod_builder_object(builder, - t->param.idEnumFormat, t->format, - "I", t->media_type.audio, - "I", t->media_subtype.raw, - ":", t->format_audio.format, "I", t->audio_format.F32, - ":", t->format_audio.rate, "i", ctrl->sample_rate, - ":", t->format_audio.channels, "i", 1); - } - else if (pd->port.jack_port->type_id == 1) { - *param = spa_pod_builder_object(builder, - t->param.idEnumFormat, t->format, - "I", t->media_type.audio, - "I", t->media_subtype_audio.midi); - } - else - return 0; - } - else { - *param = spa_pod_builder_object(builder, - t->param.idEnumFormat, t->format, - "I", t->media_type.audio, - "I", t->media_subtype.raw, - ":", t->format_audio.format, "I", t->audio_format.S16, - ":", t->format_audio.rate, "i", ctrl->sample_rate, - ":", t->format_audio.channels, "i", 2); - } - - return 1; -} - -static int port_enum_params(struct spa_node *node, - enum spa_direction direction, uint32_t port_id, - uint32_t id, uint32_t *index, - const struct spa_pod *filter, - struct spa_pod **result, - struct spa_pod_builder *builder) -{ - struct node_data *nd = SPA_CONTAINER_OF(node, struct node_data, node_impl); - struct type *t = &nd->type; - struct spa_pod *param; - struct spa_pod_builder b = { 0 }; - uint8_t buffer[1024]; - int res; - - next: - spa_pod_builder_init(&b, buffer, sizeof(buffer)); - - if (id == t->param.idEnumFormat) { - if ((res = port_enum_formats(node, direction, port_id, index, filter, ¶m, &b)) <= 0) - return res; - } - else if (id == t->param.idFormat) { - if ((res = port_enum_formats(node, direction, port_id, index, filter, ¶m, &b)) <= 0) - return res; - } - else - return -ENOENT; - - (*index)++; - - if ((res = spa_pod_filter(builder, result, param, filter)) < 0) - goto next; - - return 1; -} - -static int port_set_param(struct spa_node *node, - enum spa_direction direction, uint32_t port_id, - uint32_t id, uint32_t flags, - const struct spa_pod *param) -{ - return 0; -} - -static int port_use_buffers(struct spa_node *node, enum spa_direction direction, uint32_t port_id, - struct spa_buffer **buffers, uint32_t n_buffers) -{ - struct node_data *nd = SPA_CONTAINER_OF(node, struct node_data, node_impl); - struct port_data *pd = nd->port_data[direction][port_id]; - struct type *t = &pd->node->type; - int i; - - if (pd->have_buffers) - return 0; - - pw_log_debug("use_buffers %d", n_buffers); - for (i = 0; i < n_buffers; i++) { - struct buffer *b; - struct spa_data *d = buffers[i]->datas; - - b = &pd->buffers[i]; - b->outbuf = buffers[i]; - if ((d[0].type == t->data.MemPtr || - d[0].type == t->data.MemFd || - d[0].type == t->data.DmaBuf) && d[0].data != NULL) { - b->ptr = d[0].data; - } else { - pw_log_error(NAME " %p: invalid memory on buffer %p", pd, buffers[i]); - return -EINVAL; - } - spa_list_append(&pd->empty, &b->link); - } - pd->n_buffers = n_buffers; - - return 0; -} - -static int port_alloc_buffers(struct spa_node *node, enum spa_direction direction, uint32_t port_id, - struct spa_pod **params, uint32_t n_params, - struct spa_buffer **buffers, uint32_t *n_buffers) -{ - struct node_data *nd = SPA_CONTAINER_OF(node, struct node_data, node_impl); - struct port_data *pd = nd->port_data[direction][port_id]; - struct type *t = &pd->node->type; - int i; - - pw_log_debug("alloc %d", *n_buffers); - for (i = 0; i < *n_buffers; i++) { - struct buffer *b; - struct spa_data *d = buffers[i]->datas; - - b = &pd->buffers[i]; - b->outbuf = buffers[i]; - d[0].type = t->data.MemPtr; - d[0].maxsize = pd->node->node.server->engine_control->buffer_size; - b->ptr = d[0].data = pd->port.ptr; - spa_list_append(&pd->empty, &b->link); - } - pd->n_buffers = *n_buffers; - - return 0; -} - -static int port_reuse_buffer(struct spa_node *node, uint32_t port_id, uint32_t buffer_id) -{ - return 0; -} - -static int driver_reuse_buffer(struct spa_node *node, uint32_t port_id, uint32_t buffer_id) -{ - struct node_data *nd = SPA_CONTAINER_OF(node, struct node_data, node_impl); - struct pw_jack_node *this = &nd->node; - struct port_data *opd = SPA_CONTAINER_OF(this->driver_out, struct port_data, port); - - recycle_buffer(this, opd, buffer_id); - - return 0; -} - -static int port_send_command(struct spa_node *node, enum spa_direction direction, uint32_t port_id, - const struct spa_command *command) -{ - return 0; -} - -static const struct spa_node driver_impl = { - SPA_VERSION_NODE, - NULL, - .enum_params = node_enum_params, - .set_param = node_set_param, - .send_command = node_send_command, - .set_callbacks = node_set_callbacks, - .get_n_ports = node_get_n_ports, - .get_port_ids = node_get_port_ids, - .add_port = node_add_port, - .remove_port = node_remove_port, - .port_get_info = port_get_info, - .port_enum_params = port_enum_params, - .port_set_param = port_set_param, - .port_use_buffers = port_use_buffers, - .port_alloc_buffers = port_alloc_buffers, - .port_set_io = port_set_io, - .port_reuse_buffer = driver_reuse_buffer, - .port_send_command = port_send_command, - .process_input = driver_process_input, - .process_output = driver_process_output, -}; - -static const struct spa_node node_impl = { - SPA_VERSION_NODE, - NULL, - .enum_params = node_enum_params, - .set_param = node_set_param, - .send_command = node_send_command, - .set_callbacks = node_set_callbacks, - .get_n_ports = node_get_n_ports, - .get_port_ids = node_get_port_ids, - .add_port = node_add_port, - .remove_port = node_remove_port, - .port_get_info = port_get_info, - .port_enum_params = port_enum_params, - .port_set_param = port_set_param, - .port_use_buffers = port_use_buffers, - .port_alloc_buffers = port_alloc_buffers, - .port_set_io = port_set_io, - .port_reuse_buffer = port_reuse_buffer, - .port_send_command = port_send_command, - .process_input = node_process_input, - .process_output = node_process_output, -}; - -static int schedule_mix_input(struct spa_node *_node) -{ - struct port_data *pd = SPA_CONTAINER_OF(_node, struct port_data, mix_node); - struct pw_jack_port *this = &pd->port; - struct spa_graph_node *node = &this->port->rt.mix_node; - struct spa_graph_port *p; - struct spa_io_buffers *io = this->port->rt.mix_port.io; - size_t buffer_size = pd->node->node.server->engine_control->buffer_size; - int layer = 0; - - spa_list_for_each(p, &node->ports[SPA_DIRECTION_INPUT], link) { - struct pw_link *link = p->scheduler_data; - struct spa_buffer *inbuf; - - pw_log_trace("mix %p: input %d %d", node, p->io->buffer_id, link->output->n_buffers); - - if (!(p->io->buffer_id < link->output->n_buffers && p->io->status == SPA_STATUS_HAVE_BUFFER)) - continue; - - inbuf = link->output->buffers[p->io->buffer_id]; - - if (layer++ == 0) - memcpy(pd->buffers[0].ptr, inbuf->datas[0].data, buffer_size * sizeof(float)); - else - add_f32(pd->buffers[0].ptr, inbuf->datas[0].data, buffer_size); - - pw_log_trace("mix %p: input %p %p->%p %d %d", node, - p, p->io, io, p->io->status, p->io->buffer_id); - *io = *p->io; - io->buffer_id = 0; - p->io->status = SPA_STATUS_OK; - p->io->buffer_id = SPA_ID_INVALID; - } - return SPA_STATUS_HAVE_BUFFER; -} - -static int schedule_mix_output(struct spa_node *_node) -{ - struct port_data *pd = SPA_CONTAINER_OF(_node, struct port_data, mix_node); - struct pw_jack_port *this = &pd->port; - struct spa_graph_node *node = &this->port->rt.mix_node; - struct spa_graph_port *p; - struct spa_io_buffers *io = this->port->rt.mix_port.io; - - spa_list_for_each(p, &node->ports[SPA_DIRECTION_INPUT], link) - *p->io = *io; - return io->status; -} - -static const struct spa_node schedule_mix_node = { - SPA_VERSION_NODE, - NULL, - .process_input = schedule_mix_input, - .process_output = schedule_mix_output, -}; - -static void port_destroy(void *data) -{ - 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 void port_free(void *data) -{ - struct port_data *pd = data; - struct node_data *nd = pd->node; - struct pw_port *port = pd->port.port; - - nd->port_data[port->direction][port->port_id] = NULL; - nd->port_count[port->direction]--; - - spa_hook_list_call(&pd->listener_list, struct pw_jack_port_events, free); -} - -static const struct pw_port_events port_events = { - PW_VERSION_PORT_EVENTS, - .destroy = port_destroy, - .free = port_free, -}; - -struct pw_jack_port * -alloc_port(struct pw_jack_node *node, enum pw_direction direction, 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_jack_port *port; - uint32_t port_id; - - port_id = pw_node_get_free_port_id(node->node, direction); - if (port_id == SPA_ID_INVALID) - return NULL; - - p = pw_port_new(direction, port_id, NULL, sizeof(struct port_data) + user_data_size); - if (p == NULL) - return NULL; - - pd = pw_port_get_user_data(p); - pd->node = nd; - spa_hook_list_init(&pd->listener_list); - spa_list_init(&pd->empty); - - nd->port_data[direction][port_id] = pd; - nd->port_count[direction]++; - - port = &pd->port; - port->node = node; - 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); - - 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 jack_server *server = node->server; - struct jack_graph_manager *mgr = server->graph_manager; - struct jack_connection_manager *conn; - struct pw_jack_port *port; - struct port_data *pd; - 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, 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; - - pd = SPA_CONTAINER_OF(port, struct port_data, port); - - 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); - - pw_port_add(port->port, node->node); - - pd->mix_node = schedule_mix_node; - - - { - struct spa_buffer *b = &pd->buf; - struct type *t = &pd->node->type; - - pd->bufs[0] = b; - b->id = 0; - b->n_metas = 0; - b->metas = NULL; - b->n_datas = 1; - b->datas = pd->data; - pd->data[0].data = pd->port.ptr; - pd->data[0].chunk = pd->chunk; - pd->data[0].type = t->data.MemPtr; - pd->data[0].maxsize = pd->node->node.server->engine_control->buffer_size; - - port->port->state = PW_PORT_STATE_READY; - pw_port_use_buffers(port->port, pd->bufs, 1); - pd->have_buffers = true; - port->port->state = PW_PORT_STATE_PAUSED; - } - if (direction == PW_DIRECTION_INPUT) { - spa_graph_node_set_implementation(&port->port->rt.mix_node, &pd->mix_node); - } - - - 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 void node_state_changed(void *data, enum pw_node_state old, - enum pw_node_state state, const char *error) -{ - struct node_data *nd = data; - spa_hook_list_call(&nd->listener_list, struct pw_jack_node_events, state_changed, old, state, error); -} - -static const struct pw_node_events node_events = { - PW_VERSION_NODE_EVENTS, - .state_changed = node_state_changed, - .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, - const char *name, - int pid, - struct pw_properties *properties, - size_t user_data_size) -{ - struct node_data *nd; - int ref_num; - struct pw_node *node; - struct pw_jack_node *this; - struct jack_graph_manager *mgr = server->graph_manager; - struct jack_connection_manager *conn; - - if (properties == NULL) - properties = pw_properties_new("jack.server.name", server->engine_control->server_name, - "jack.name", name, NULL); - - 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; - } - pw_properties_setf(properties, "jack.ref-num", "%d", ref_num); - - node = pw_node_new(core, 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); - nd->node_impl = node_impl; - - pw_node_add_listener(node, &nd->node_listener, &node_events, nd); - pw_node_set_implementation(node, &nd->node_impl); - - 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; - this->server = server; - 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; - } - - conn = jack_graph_manager_next_start(mgr); - jack_connection_manager_init_ref_num(conn, ref_num); - jack_graph_manager_next_stop(mgr); - - pw_node_register(node, NULL, parent, NULL); - pw_node_set_active(node, true); - - 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]; - - if (properties == NULL) - properties = pw_properties_new("jack.server.name", server->engine_control->server_name, - "jack.name", name, NULL); - - 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; - } - pw_properties_setf(properties, "jack.ref-num", "%d", ref_num); - - node = pw_node_new(core, 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); - nd->node_impl = driver_impl; - - pw_node_add_listener(node, &nd->node_listener, &node_events, nd); - pw_node_set_implementation(node, &nd->node_impl); - - 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->driver_in = alloc_port(this, PW_DIRECTION_INPUT, 0); - pw_port_add(this->driver_in->port, node); - } - if (n_playback_channels > 0) { - this->driver_out = alloc_port(this, PW_DIRECTION_OUTPUT, 0); - pw_port_add(this->driver_out->port, node); - } - pw_node_register(node, NULL, parent, NULL); - pw_node_set_active(node, true); - - return this; -} - -void pw_jack_node_destroy(struct pw_jack_node *node) -{ - pw_log_debug("jack-node %p: destroy", node); - pw_node_destroy(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 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_jack_port *result; -}; - -static int 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->port.port_id == d->port_id) { - d->result = &pd->port; - return 1; - } - return 0; -} - -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) == 1) - return data.result; - return NULL; -} diff --git a/src/modules/module-jack/jack-node.h b/src/modules/module-jack/jack-node.h deleted file mode 100644 index 0c9f0585c..000000000 --- a/src/modules/module-jack/jack-node.h +++ /dev/null @@ -1,134 +0,0 @@ -/* PipeWire - * Copyright (C) 2015 Wim Taymans - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __PIPEWIRE_JACK_NODE_H__ -#define __PIPEWIRE_JACK_NODE_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -struct pw_jack_port; - -struct pw_jack_node { - struct pw_node *node; - - struct pw_core *core; - struct jack_server *server; - - struct jack_client_control *control; - - struct pw_jack_port *driver_out; - struct pw_jack_port *driver_in; - - struct spa_list graph_link; - - void *user_data; -}; - -struct pw_jack_node_events { -#define PW_VERSION_JACK_NODE_EVENTS 0 - uint32_t version; - - void (*destroy) (void *data); - - void (*free) (void *data); - - /** the state of the node changed */ - void (*state_changed) (void *data, enum pw_node_state old, - enum pw_node_state state, const char *error); - - 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); - - void (*free) (void *data); -}; - -struct pw_jack_node * -pw_jack_node_new(struct pw_core *core, - struct pw_global *parent, - struct jack_server *server, - 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); - -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_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); - -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 -} -#endif - -#endif /* __PIPEWIRE_JACK_NODE_H__ */ diff --git a/src/modules/module-jack/jack.h b/src/modules/module-jack/jack.h deleted file mode 100644 index 6fc721937..000000000 --- a/src/modules/module-jack/jack.h +++ /dev/null @@ -1,28 +0,0 @@ -/* PipeWire - * Copyright (C) 2015 Wim Taymans - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include -#include - -#include "modules/module-jack/defs.h" -#include "modules/module-jack/synchro.h" -#include "modules/module-jack/shm.h" -#include "modules/module-jack/shared.h" -#include "modules/module-jack/port.h" -#include "modules/module-jack/server.h" diff --git a/src/modules/module-jack/port.h b/src/modules/module-jack/port.h deleted file mode 100644 index 064b618a5..000000000 --- a/src/modules/module-jack/port.h +++ /dev/null @@ -1,28 +0,0 @@ -/* PipeWire - * Copyright (C) 2017 Wim Taymans - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -static inline jack_port_type_id_t -jack_port_get_type_id(const char *type) -{ - if (strcmp(type, JACK_DEFAULT_AUDIO_TYPE) == 0) - return 0; - else if (strcmp(type, JACK_DEFAULT_MIDI_TYPE) == 0) - return 1; - return 2; -} diff --git a/src/modules/module-jack/server.h b/src/modules/module-jack/server.h deleted file mode 100644 index 2a7326677..000000000 --- a/src/modules/module-jack/server.h +++ /dev/null @@ -1,67 +0,0 @@ -/* PipeWire - * Copyright (C) 2017 Wim Taymans - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -struct jack_server; - -struct jack_client { - struct spa_list link; - void *data; - struct client *owner; - struct pw_jack_node *node; - int fd; /* notify fd */ - struct spa_hook node_listener; - struct spa_list client_link; - bool activated; - bool realtime; -}; - -struct jack_server { - pthread_mutex_t lock; - - bool promiscuous; - - struct jack_graph_manager *graph_manager; - struct jack_engine_control *engine_control; - - struct jack_client* client_table[CLIENT_NUM]; - struct jack_synchro synchro_table[CLIENT_NUM]; - - int audio_ref_num; - int freewheel_ref_num; - - struct pw_jack_node *audio_node; - int audio_used; -}; - -static inline int -jack_server_allocate_ref_num(struct jack_server *server) -{ - int i; - - for (i = 0; i < CLIENT_NUM; i++) - if (server->client_table[i] == NULL) - return i; - return -1; -} - -static inline void -jack_server_free_ref_num(struct jack_server *server, int ref_num) -{ - server->client_table[ref_num] = NULL; -} diff --git a/src/modules/module-jack/shared.h b/src/modules/module-jack/shared.h deleted file mode 100644 index a2f12fe65..000000000 --- a/src/modules/module-jack/shared.h +++ /dev/null @@ -1,1063 +0,0 @@ -/* PipeWire - * Copyright (C) 2015 Wim Taymans - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include - -extern int segment_num; - -static inline int jack_shm_alloc(size_t size, jack_shm_info_t *info, int num) -{ - char name[64]; - - snprintf(name, sizeof(name), "/jack_shared%d", num); - - if (jack_shmalloc(name, size, info)) { - pw_log_error("Cannot create shared memory segment of size = %zd (%s)", size, strerror(errno)); - return -1; - } - - if (jack_attach_shm(info)) { - jack_error("Cannot attach shared memory segment name = %s err = %s", name, strerror(errno)); - jack_destroy_shm(info); - return -1; - } - info->size = size; - return 0; -} - -typedef uint16_t jack_int_t; // Internal type for ports and refnum - -typedef enum { - NotTriggered, - Triggered, - Running, - Finished, -} jack_client_state_t; - -PRE_PACKED_STRUCTURE -struct jack_client_timing { - jack_time_t signaled_at; - jack_time_t awake_at; - jack_time_t finished_at; - jack_client_state_t status; -} POST_PACKED_STRUCTURE; - -#define JACK_CLIENT_TIMING_INIT (struct jack_client_timing) { 0, 0, 0, NotTriggered } - -PRE_PACKED_STRUCTURE -struct jack_port { - int type_id; - enum JackPortFlags flags; - char name[REAL_JACK_PORT_NAME_SIZE]; - char alias1[REAL_JACK_PORT_NAME_SIZE]; - char alias2[REAL_JACK_PORT_NAME_SIZE]; - int ref_num; - - jack_nframes_t latency; - jack_nframes_t total_latency; - jack_latency_range_t playback_latency; - jack_latency_range_t capture_latency; - uint8_t monitor_requests; - - bool in_use; - jack_port_id_t tied; - jack_default_audio_sample_t buffer[BUFFER_SIZE_MAX + 8]; -} POST_PACKED_STRUCTURE; - -static inline void jack_port_init(struct jack_port *port, int ref_num, - const char* port_name, int type_id, enum JackPortFlags flags) -{ - port->type_id = type_id; - port->flags = flags; - strcpy(port->name, port_name); - port->alias1[0] = '\0'; - port->alias2[0] = '\0'; - port->ref_num = ref_num; - port->latency = 0; - port->total_latency = 0; - port->playback_latency.min = port->playback_latency.max = 0; - port->capture_latency.min = port->capture_latency.max = 0; - port->monitor_requests = 0; - port->in_use = true; - port->tied = NO_PORT; -} - -static inline void jack_port_release(struct jack_port *port) { - port->in_use = false; -} - -PRE_PACKED_STRUCTURE -struct jack_client_control { - jack_shm_info_t info; - char name[JACK_CLIENT_NAME_SIZE+1]; - bool callback[jack_notify_max]; - volatile jack_transport_state_t transport_state; - volatile bool transport_sync; - volatile bool transport_timebase; - int ref_num; - int PID; - bool active; - - int session_ID; - char session_command[JACK_SESSION_COMMAND_SIZE]; - jack_session_flags_t session_flags; -} POST_PACKED_STRUCTURE; - -static inline struct jack_client_control * -jack_client_control_alloc(const char* name, int pid, int ref_num, int uuid) -{ - struct jack_client_control *ctrl; - jack_shm_info_t info; - size_t size; - - size = sizeof(struct jack_client_control); - if (jack_shm_alloc(size, &info, segment_num++) < 0) - return NULL; - - ctrl = (struct jack_client_control *)jack_shm_addr(&info); - ctrl->info = info; - - strcpy(ctrl->name, name); - for (int i = 0; i < jack_notify_max; i++) - ctrl->callback[i] = false; - - // Always activated - ctrl->callback[jack_notify_AddClient] = true; - ctrl->callback[jack_notify_RemoveClient] = true; - ctrl->callback[jack_notify_ActivateClient] = true; - ctrl->callback[jack_notify_LatencyCallback] = true; - // So that driver synchro are correctly setup in "flush" or "normal" mode - ctrl->callback[jack_notify_StartFreewheelCallback] = true; - ctrl->callback[jack_notify_StopFreewheelCallback] = true; - ctrl->ref_num = ref_num; - ctrl->PID = pid; - ctrl->transport_state = JackTransportStopped; - ctrl->transport_sync = false; - ctrl->transport_timebase = false; - ctrl->active = false; - ctrl->session_ID = uuid; - - return ctrl; -} - -#define MAKE_FIXED_ARRAY(size) \ -PRE_PACKED_STRUCTURE \ -struct { \ - jack_int_t table[size]; \ - uint32_t counter; \ -} POST_PACKED_STRUCTURE - -#define INIT_FIXED_ARRAY(arr) ({ \ - int _i; \ - for (_i = 0; _i < SPA_N_ELEMENTS(arr.table); _i++) \ - arr.table[_i] = EMPTY; \ - arr.counter = 0; \ -}) -#define GET_ITEMS_FIXED_ARRAY(arr) ({ \ - arr.table; \ -}) -#define ADD_FIXED_ARRAY(arr,item) ({ \ - int _ret = -1; \ - if (arr.counter < SPA_N_ELEMENTS(arr.table)) { \ - _ret = arr.counter++; \ - arr.table[_ret] = item; \ - } \ - _ret; \ -}) -#define GET_FIXED_ARRAY(arr,item) ({ \ - int _i,_ret = -1; \ - for (_i = 0; _i < arr.counter; _i++) { \ - if (arr.table[_i] == item) { \ - _ret = _i; \ - break; \ - } \ - } \ - _ret; \ -}) -#define REMOVE_FIXED_ARRAY(arr,item) ({ \ - int _ret = GET_FIXED_ARRAY(arr,item); \ - if (_ret >= 0) { \ - arr.counter--; \ - arr.table[_ret] = arr.table[arr.counter]; \ - arr.table[arr.counter] = EMPTY; \ - } \ - _ret; \ -}) - -#define MAKE_FIXED_ARRAY1(size) \ -PRE_PACKED_STRUCTURE \ -struct { \ - MAKE_FIXED_ARRAY(size) array; \ - bool used; \ -} POST_PACKED_STRUCTURE - -#define INIT_FIXED_ARRAY1(arr) ({ \ - 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 REMOVE_FIXED_ARRAY1(arr,item) REMOVE_FIXED_ARRAY(arr.array,item) - -#define MAKE_FIXED_MATRIX(size) \ -PRE_PACKED_STRUCTURE \ -struct { \ - jack_int_t table[size][size]; \ -} POST_PACKED_STRUCTURE - -#define INIT_FIXED_MATRIX(mat,idx) ({ \ - int i; \ - for (i = 0; i < SPA_N_ELEMENTS(mat.table[0]); i++){ \ - mat.table[idx][i] = 0; \ - mat.table[i][idx] = 0; \ - } \ -}) -#define GET_ITEMS_FIXED_MATRIX(mat,idx1) ({ \ - mat.table[idx1]; \ -}) -#define INC_FIXED_MATRIX(mat,idx1,idx2) ({ \ - ++mat.table[idx1][idx2]; \ -}) -#define DEC_FIXED_MATRIX(mat,idx1,idx2) ({ \ - --mat.table[idx1][idx2]; \ -}) -#define GET_FIXED_MATRIX(mat,idx1,idx2) ({ \ - mat.table[idx1][idx2]; \ -}) -#define CLEAR_FIXED_MATRIX(mat,idx1,idx2) ({ \ - mat.table[idx1][idx2] = 0; \ -}) - -PRE_PACKED_STRUCTURE -struct jack_activation_count { - int32_t value; - int32_t count; -} POST_PACKED_STRUCTURE; - -static inline void jack_activation_count_set_value(struct jack_activation_count *cnt, int32_t val) { - cnt->value = val; -} -static inline int32_t jack_activation_count_get_value(struct jack_activation_count *cnt) { - return cnt->value; -} -static inline int32_t jack_activation_count_get_count(struct jack_activation_count *cnt) { - return cnt->count; -} -static inline void jack_activation_count_reset(struct jack_activation_count *cnt) { - cnt->value = cnt->count; -} -static inline void jack_activation_count_inc_value(struct jack_activation_count *cnt) { - cnt->count++; -} -static inline void jack_activation_count_dec_value(struct jack_activation_count *cnt) { - cnt->count--; -} -static inline bool jack_activation_count_signal(struct jack_activation_count *cnt, - struct jack_synchro *synchro) -{ - bool res = true; - - if (cnt->value == 0) { - pw_log_error("activation == 0"); - res = jack_synchro_signal(synchro); - } - else if (__atomic_sub_fetch(&cnt->value, 1, __ATOMIC_SEQ_CST) == 0) - res = jack_synchro_signal(synchro); - - return res; -} - -#define MAKE_LOOP_FEEDBACK(size) \ -PRE_PACKED_STRUCTURE \ -struct { \ - int table[size][3]; \ -} POST_PACKED_STRUCTURE - -#define INIT_LOOP_FEEDBACK(arr,size) ({ \ - int i; \ - for (i = 0; i < size; i++) { \ - arr.table[i][0] = EMPTY; \ - arr.table[i][1] = EMPTY; \ - arr.table[i][2] = 0; \ - } \ -}) -#define ADD_LOOP_FEEDBACK(arr,ref1,ref2) ({ \ - int i,res = false; \ - for (i = 0; i < SPA_N_ELEMENTS(arr.table); i++) { \ - if (arr.table[i][0] == EMPTY) { \ - arr.table[i][0] = ref1; \ - arr.table[i][1] = ref2; \ - arr.table[i][2] = 1; \ - res = true; \ - break; \ - } \ - } \ - res; \ -}) -#define DEL_LOOP_FEEDBACK(arr,ref1,ref2) ({ \ - int i,res = false; \ - for (i = 0; i < SPA_N_ELEMENTS(arr.table); i++) { \ - if (arr.table[i][0] == ref1 && \ - arr.table[i][1] == ref2) { \ - arr.table[i][0] = EMPTY; \ - arr.table[i][1] = EMPTY; \ - arr.table[i][2] = 0; \ - res = true; \ - break; \ - } \ - } \ - res; \ -}) -#define GET_LOOP_FEEDBACK(arr,ref1,ref2) ({ \ - int i,res = 1; \ - for (i = 0; i < SPA_N_ELEMENTS(arr.table); i++) { \ - if (arr.table[i][0] == ref1 && \ - arr.table[i][1] == ref2) { \ - res = i; \ - break; \ - } \ - } \ - res; \ -}) -#define INC_LOOP_FEEDBACK(arr,ref1,ref2) ({ \ - int res = true, idx = GET_LOOP_FEEDBACK(arr,ref1,ref2); \ - if (idx >= 0) \ - arr.table[idx][2]++; \ - else \ - res = ADD_LOOP_FEEDBACK(arr,ref1,ref2); \ - res; \ -}) -#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) \ - res = DEL_LOOP_FEEDBACK(arr,ref1,ref2); \ - } \ - else \ - res = false; \ - res; \ -}) - -PRE_PACKED_STRUCTURE -struct jack_connection_manager { - MAKE_FIXED_ARRAY(CONNECTION_NUM_FOR_PORT) connection[PORT_NUM_MAX]; - MAKE_FIXED_ARRAY1(PORT_NUM_FOR_CLIENT) input_port[CLIENT_NUM]; - MAKE_FIXED_ARRAY(PORT_NUM_FOR_CLIENT) output_port[CLIENT_NUM]; - MAKE_FIXED_MATRIX(CLIENT_NUM) connection_ref; - struct jack_activation_count input_counter[CLIENT_NUM]; - MAKE_LOOP_FEEDBACK(CONNECTION_NUM_FOR_PORT) loop_feedback; -} POST_PACKED_STRUCTURE; - -static inline void -jack_connection_manager_init_ref_num(struct jack_connection_manager *conn, int ref_num) -{ - INIT_FIXED_ARRAY1(conn->input_port[ref_num]); - INIT_FIXED_ARRAY(conn->output_port[ref_num]); - INIT_FIXED_MATRIX(conn->connection_ref, ref_num); - conn->input_counter[ref_num].count = 0; - jack_activation_count_set_value(&conn->input_counter[ref_num], 0); -} - -static inline void -jack_connection_manager_init(struct jack_connection_manager *conn) -{ - int i; - for (i = 0; i < PORT_NUM_MAX; i++) - INIT_FIXED_ARRAY(conn->connection[i]); - - INIT_LOOP_FEEDBACK(conn->loop_feedback, CONNECTION_NUM_FOR_PORT); - - for (i = 0; i < CLIENT_NUM; i++) - jack_connection_manager_init_ref_num(conn, i); -} - -static inline void -jack_connection_manager_reset(struct jack_connection_manager *conn, - struct jack_client_timing *timing) -{ - int i; - for (i = 0; i < CLIENT_NUM; i++) { - jack_activation_count_reset(&conn->input_counter[i]); - timing[i].status = NotTriggered; - } -} - -static inline int -jack_connection_manager_add_inport(struct jack_connection_manager *conn, - int ref_num, jack_port_id_t 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 const jack_int_t * -jack_connection_manager_get_connections(struct jack_connection_manager *conn, int port_index) -{ - return GET_ITEMS_FIXED_ARRAY(conn->connection[port_index]); -} - -static inline int -jack_connection_manager_get_output_refnum(struct jack_connection_manager *conn, - jack_port_id_t port_index) -{ - int i; - for (i = 0; i < CLIENT_NUM; i++) { - if (GET_FIXED_ARRAY(conn->output_port[i], port_index) != -1) - return i; - } - return -1; -} - -static inline int -jack_connection_manager_get_input_refnum(struct jack_connection_manager *conn, - jack_port_id_t port_index) -{ - int i; - for (i = 0; i < CLIENT_NUM; i++) { - if (GET_FIXED_ARRAY1(conn->input_port[i], port_index) != -1) - return i; - } - return -1; -} - -static inline bool -jack_connection_manager_is_connected(struct jack_connection_manager *conn, - jack_port_id_t src_id, jack_port_id_t dst_id) -{ - return GET_FIXED_ARRAY(conn->connection[src_id], dst_id) != -1; -} - -static inline int -jack_connection_manager_connect(struct jack_connection_manager *conn, - jack_port_id_t src_id, jack_port_id_t dst_id) -{ - return ADD_FIXED_ARRAY(conn->connection[src_id], dst_id); -} - -static inline int -jack_connection_manager_disconnect(struct jack_connection_manager *conn, - jack_port_id_t src_id, jack_port_id_t dst_id) -{ - return REMOVE_FIXED_ARRAY(conn->connection[src_id], dst_id); -} - -static inline int -jack_connection_manager_is_loop_path(struct jack_connection_manager *conn, - jack_port_id_t src_id, jack_port_id_t dst_id) -{ - /* FIXME */ - return false; -} - -static inline void -jack_connection_manager_direct_connect(struct jack_connection_manager *conn, - int ref1, int ref2) -{ - if (INC_FIXED_MATRIX(conn->connection_ref, ref1, ref2) == 1) - jack_activation_count_inc_value(&conn->input_counter[ref2]); -} - -static inline bool -jack_connection_manager_is_direct_connection(struct jack_connection_manager *conn, - int ref1, int ref2) -{ - return GET_FIXED_MATRIX(conn->connection_ref, ref1, ref2) > 0; -} - -static inline void -jack_connection_manager_direct_disconnect(struct jack_connection_manager *conn, - int ref1, int ref2) -{ - if (DEC_FIXED_MATRIX(conn->connection_ref, ref1, ref2) == 0) - jack_activation_count_dec_value(&conn->input_counter[ref2]); -} - -static inline bool -jack_connection_manager_inc_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_connect(conn, ref2, ref1); - - 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) -{ - int ref1 = jack_connection_manager_get_output_refnum(conn, src_id); - int ref2 = jack_connection_manager_get_input_refnum(conn, dst_id); - - jack_connection_manager_direct_connect(conn, ref1, ref2); -} - -static inline void -jack_connection_manager_dec_direct_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); - - 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; - } - - jack_connection_manager_disconnect(conn, src_id, dst_id); - jack_connection_manager_disconnect(conn, dst_id, src_id); - - 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) -{ - return jack_activation_count_get_value(&conn->input_counter[ref_num]); -} - -static inline int -jack_connection_manager_suspend_ref_num(struct jack_connection_manager *conn, - struct jack_client_control *control, - struct jack_synchro *synchro, - struct jack_client_timing *timing) -{ - int res = 0, ref_num = control->ref_num; - jack_time_t current_date = 0; - - if (jack_synchro_wait(&synchro[ref_num])) { - timing[ref_num].status = Finished; - timing[ref_num].awake_at = current_date; - } - return res ? 0 : -1; -} - - -static inline int -jack_connection_manager_resume_ref_num(struct jack_connection_manager *conn, - struct jack_client_control *control, - struct jack_synchro *synchro, - struct jack_client_timing *timing) -{ - int i, res = 0, ref_num = control->ref_num; - const jack_int_t* output_ref = GET_ITEMS_FIXED_MATRIX(conn->connection_ref, ref_num); - jack_time_t current_date = 0; - - timing[ref_num].status = Finished; - timing[ref_num].finished_at = current_date; - - for (i = 0; i < CLIENT_NUM; i++) { - if (output_ref[i] <= 0) - continue; - - timing[i].status = Triggered; - timing[i].signaled_at = current_date; - - if (!jack_activation_count_signal(&conn->input_counter[i], &synchro[i])) - res = -1; - } - return res; -} - -PRE_PACKED_STRUCTURE -struct jack_atomic_counter { - union { - struct { - uint16_t short_val1; // Cur - uint16_t short_val2; // Next - } scounter; - uint32_t long_val; - } info; -} POST_PACKED_STRUCTURE; - -#define Counter(e) (e).info.long_val -#define CurIndex(e) (e).info.scounter.short_val1 -#define NextIndex(e) (e).info.scounter.short_val2 - -#define CurArrayIndex(e) (CurIndex(e) & 0x0001) -#define NextArrayIndex(e) ((CurIndex(e) + 1) & 0x0001) - -#define MAKE_ATOMIC_STATE(type) \ -PRE_PACKED_STRUCTURE \ -struct { \ - type state[2]; \ - volatile struct jack_atomic_counter counter; \ - int32_t call_write_counter; \ -} POST_PACKED_STRUCTURE - -PRE_PACKED_STRUCTURE -struct jack_atomic_array_counter { - union { - struct { - unsigned char byte_val[4]; - } scounter; - uint32_t long_val; - } info; -} POST_PACKED_STRUCTURE; - -#define MAKE_ATOMIC_ARRAY_STATE(type) \ -PRE_PACKED_STRUCTURE \ -struct { \ - type state[3]; \ - volatile struct jack_atomic_array_counter counter; \ -} POST_PACKED_STRUCTURE - -PRE_PACKED_STRUCTURE -struct jack_graph_manager { - jack_shm_info_t info; - MAKE_ATOMIC_STATE(struct jack_connection_manager) state; - unsigned int port_max; - struct jack_client_timing client_timing[CLIENT_NUM]; - struct jack_port port_array[0]; -} POST_PACKED_STRUCTURE; - -static inline struct jack_graph_manager * -jack_graph_manager_alloc(int port_max) -{ - struct jack_graph_manager *mgr; - jack_shm_info_t info; - size_t i, size; - - size = sizeof(struct jack_graph_manager) + port_max * sizeof(struct jack_port); - - if (jack_shm_alloc(size, &info, segment_num++) < 0) - return NULL; - - mgr = (struct jack_graph_manager *)jack_shm_addr(&info); - mgr->info = info; - Counter(mgr->state.counter) = 0; - mgr->state.call_write_counter = 0; - - jack_connection_manager_init(&mgr->state.state[0]); - jack_connection_manager_init(&mgr->state.state[1]); - mgr->port_max = port_max; - - for (i = 0; i < port_max; i++) { - mgr->port_array[i].in_use = false; - mgr->port_array[i].ref_num = -1; - } - return mgr; -} - -static inline jack_port_id_t -jack_graph_manager_allocate_port(struct jack_graph_manager *mgr, - int ref_num, const char* port_name, int type_id, - enum JackPortFlags flags) -{ - int i; - for (i = 1; i < mgr->port_max; i++) { - if (!mgr->port_array[i].in_use) { - jack_port_init(&mgr->port_array[i], ref_num, port_name, type_id, flags); - return i; - } - } - return NO_PORT; -} - -static inline void -jack_graph_manager_release_port(struct jack_graph_manager *mgr, jack_port_id_t port_id) -{ - jack_port_release(&mgr->port_array[port_id]); -} - -static inline struct jack_port * -jack_graph_manager_get_port(struct jack_graph_manager *mgr, jack_port_id_t port_index) -{ - if (port_index > 0 && port_index < mgr->port_max) - return &mgr->port_array[port_index]; - return NULL; -} - -static inline jack_port_id_t -jack_graph_manager_find_port(struct jack_graph_manager *mgr, const char *name) -{ - int i; - for (i = 0; i < mgr->port_max; i++) { - struct jack_port *port = &mgr->port_array[i]; - if (port->in_use && strcmp(port->name, name) == 0) - return i; - } - return NO_PORT; -} - -static inline struct jack_connection_manager * -jack_graph_manager_next_start(struct jack_graph_manager *manager) -{ - uint32_t next_index; - - if (manager->state.call_write_counter++ == 0) { - struct jack_atomic_counter old_val; - struct jack_atomic_counter new_val; - uint32_t cur_index; - bool need_copy; - do { - old_val = manager->state.counter; - new_val = old_val; - cur_index = CurArrayIndex(new_val); - next_index = NextArrayIndex(new_val); - need_copy = (CurIndex(new_val) == NextIndex(new_val)); - NextIndex(new_val) = CurIndex(new_val); // Invalidate next index - } - while (!__atomic_compare_exchange_n((uint32_t*)&manager->state.counter, - (uint32_t*)&Counter(old_val), - Counter(new_val), - false, - __ATOMIC_SEQ_CST, - __ATOMIC_SEQ_CST)); - - if (need_copy) - memcpy(&manager->state.state[next_index], - &manager->state.state[cur_index], - sizeof(struct jack_connection_manager)); - } - else { - next_index = NextArrayIndex(manager->state.counter); - } - return &manager->state.state[next_index]; -} - -static inline void -jack_graph_manager_next_stop(struct jack_graph_manager *manager) -{ - if (--manager->state.call_write_counter == 0) { - struct jack_atomic_counter old_val; - struct jack_atomic_counter new_val; - do { - old_val = manager->state.counter; - new_val = old_val; - NextIndex(new_val)++; // Set next index - } - while (!__atomic_compare_exchange_n((uint32_t*)&manager->state.counter, - (uint32_t*)&Counter(old_val), - Counter(new_val), - false, - __ATOMIC_SEQ_CST, - __ATOMIC_SEQ_CST)); - } -} - -static inline bool -jack_graph_manager_is_pending_change(struct jack_graph_manager *manager) -{ - return CurIndex(manager->state.counter) != NextIndex(manager->state.counter); -} - -static inline struct jack_connection_manager * -jack_graph_manager_get_current(struct jack_graph_manager *manager) -{ - return &manager->state.state[CurArrayIndex(manager->state.counter)]; -} - -static inline struct jack_connection_manager * -jack_graph_manager_try_switch(struct jack_graph_manager *manager, bool *res) -{ - struct jack_atomic_counter old_val; - struct jack_atomic_counter new_val; - do { - old_val = manager->state.counter; - new_val = old_val; - *res = CurIndex(new_val) != NextIndex(new_val); - CurIndex(new_val) = NextIndex(new_val); - } - while (!__atomic_compare_exchange_n((uint32_t*)&manager->state.counter, - (uint32_t*)&Counter(old_val), - Counter(new_val), - false, - __ATOMIC_SEQ_CST, - __ATOMIC_SEQ_CST)); - - return &manager->state.state[CurArrayIndex(manager->state.counter)]; -} - -typedef enum { - TransportCommandNone = 0, - TransportCommandStart = 1, - TransportCommandStop = 2, -} transport_command_t; - -PRE_PACKED_STRUCTURE -struct jack_transport_engine { - MAKE_ATOMIC_ARRAY_STATE(jack_position_t) state; - jack_transport_state_t transport_state; - volatile transport_command_t transport_cmd; - transport_command_t previous_cmd; /* previous transport_cmd */ - jack_time_t sync_timeout; - int sync_time_left; - int time_base_master; - bool pending_pos; - bool network_sync; - bool conditional; - int32_t write_counter; -} POST_PACKED_STRUCTURE; - -PRE_PACKED_STRUCTURE -struct jack_timer { - jack_nframes_t frames; - jack_time_t current_wakeup; - jack_time_t current_callback; - jack_time_t next_wakeup; - float period_usecs; - float filter_omega; /* set once, never altered */ - bool initialized; -} POST_PACKED_STRUCTURE; - -PRE_PACKED_STRUCTURE -struct jack_frame_timer { - MAKE_ATOMIC_STATE(struct jack_timer) state; - bool first_wakeup; -} POST_PACKED_STRUCTURE; - -#ifdef JACK_MONITOR -PRE_PACKED_STRUCTURE -struct jack_timing_measure_client { - int ref_num; - jack_time_t signaled_at; - jack_time_t awake_at; - jack_time_t finished_at; - jack_client_state_t status; -} POST_PACKED_STRUCTURE; - -PRE_PACKED_STRUCTURE -struct jack_timing_client_interval { - int ref_num; - char name[JACK_CLIENT_NAME_SIZE+1]; - int begin_interval; - int end_interval; -} POST_PACKED_STRUCTURE; - -PRE_PACKED_STRUCTURE -struct jack_timing_measure { - unsigned int audio_cycle; - jack_time_t period_usecs; - jack_time_t cur_cycle_begin; - jack_time_t prev_cycle_end; - struct jack_timing_measure_client client_table[CLIENT_NUM]; -} POST_PACKED_STRUCTURE; - -PRE_PACKED_STRUCTURE -struct jack_engine_profiling { - struct jack_timing_measure profile_table[TIME_POINTS]; - struct jack_timing_client_interval interval_table[MEASURED_CLIENTS]; - - unsigned int audio_cycle; - unsigned int measured_client; -} POST_PACKED_STRUCTURE; -#endif - -PRE_PACKED_STRUCTURE -struct jack_engine_control { - jack_shm_info_t info; - jack_nframes_t buffer_size; - jack_nframes_t sample_rate; - bool sync_mode; - bool temporary; - jack_time_t period_usecs; - jack_time_t timeout_usecs; - float max_delayed_usecs; - float xrun_delayed_usecs; - bool timeout; - bool real_time; - bool saved_real_time; - int server_priority; - int client_priority; - int max_client_priority; - char server_name[JACK_SERVER_NAME_SIZE]; - struct jack_transport_engine transport; - jack_timer_type_t clock_source; - int driver_num; - bool verbose; - - jack_time_t prev_cycle_time; - jack_time_t cur_cycle_time; - jack_time_t spare_usecs; - jack_time_t max_usecs; - jack_time_t rolling_client_usecs[JACK_ENGINE_ROLLING_COUNT]; - unsigned int rolling_client_usecs_cnt; - int rolling_client_usecs_index; - int rolling_interval; - float CPU_load; - - uint64_t period; - uint64_t computation; - uint64_t constraint; - - struct jack_frame_timer frame_timer; - -#ifdef JACK_MONITOR - struct jack_engine_profiling profiler; -#endif -} POST_PACKED_STRUCTURE; - -static inline void -jack_engine_control_reset_rolling_usecs(struct jack_engine_control *ctrl) -{ - memset(ctrl->rolling_client_usecs, 0, sizeof(ctrl->rolling_client_usecs)); - ctrl->rolling_client_usecs_index = 0; - ctrl->rolling_client_usecs_cnt = 0; - ctrl->spare_usecs = 0; - ctrl->rolling_interval = floor((JACK_ENGINE_ROLLING_INTERVAL * 1000.f) / ctrl->period_usecs); -} - -static inline uint64_t calc_computation(jack_nframes_t buffer_size) -{ - if (buffer_size < 128) - return 500; - else if (buffer_size < 256) - return 300; - else - return 100; -} - -static inline void -jack_engine_control_set_buffer_size(struct jack_engine_control *ctrl, jack_nframes_t buffer_size) -{ - ctrl->buffer_size = buffer_size; - ctrl->period_usecs = 1000000.f / ctrl->sample_rate * ctrl->buffer_size; - ctrl->period = ctrl->constraint = ctrl->period_usecs * 1000; - ctrl->computation = calc_computation(ctrl->buffer_size) * 1000; -} - -static inline struct jack_engine_control * -jack_engine_control_alloc(const char* name) -{ - struct jack_engine_control *ctrl; - jack_shm_info_t info; - size_t size; - - size = sizeof(struct jack_engine_control); - if (jack_shm_alloc(size, &info, segment_num++) < 0) - return NULL; - - ctrl = (struct jack_engine_control *)jack_shm_addr(&info); - ctrl->info = info; - - ctrl->sample_rate = 48000; - ctrl->sync_mode = false; - ctrl->temporary = false; - ctrl->timeout_usecs = 0; - ctrl->max_delayed_usecs = 0.f; - ctrl->xrun_delayed_usecs = 0.f; - ctrl->timeout = false; - ctrl->real_time = true; - ctrl->saved_real_time = false; - ctrl->server_priority = 20; - ctrl->client_priority = 15; - ctrl->max_client_priority = 19; - strcpy(ctrl->server_name, name); - ctrl->clock_source = 0; - ctrl->driver_num = 0; - ctrl->verbose = true; - - ctrl->prev_cycle_time = 0; - ctrl->cur_cycle_time = 0; - ctrl->spare_usecs = 0; - ctrl->max_usecs = 0; - jack_engine_control_reset_rolling_usecs(ctrl); - ctrl->CPU_load = 0.f; - - jack_engine_control_set_buffer_size(ctrl, 128); - - return ctrl; -} diff --git a/src/modules/module-jack/shm.c b/src/modules/module-jack/shm.c deleted file mode 100644 index c3989bcf9..000000000 --- a/src/modules/module-jack/shm.c +++ /dev/null @@ -1,1303 +0,0 @@ -/* This module provides a set of abstract shared memory interfaces - * with support using both System V and POSIX shared memory - * implementations. The code is divided into three sections: - * - * - common (interface-independent) code - * - POSIX implementation - * - System V implementation - * - Windows implementation - * - * The implementation used is determined by whether USE_POSIX_SHM was - * set in the ./configure step. - */ - -/* - Copyright (C) 2001-2003 Paul Davis - Copyright (C) 2005-2012 Grame - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - */ - -//#include "JackConstants.h" - -#ifdef WIN32 -#include -#include -#else - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#endif - -#include "defs.h" -#include "shm.h" - -static int GetUID() -{ -#ifdef WIN32 - return _getpid(); - //#error "No getuid function available" -#else - return getuid(); -#endif -} - -static int GetPID() -{ -#ifdef WIN32 - return _getpid(); -#else - return getpid(); -#endif -} - -#ifdef USE_POSIX_SHM -static jack_shmtype_t jack_shmtype = shm_POSIX; -#elif WIN32 -static jack_shmtype_t jack_shmtype = shm_WIN32; -#else -static jack_shmtype_t jack_shmtype = shm_SYSV; -#endif - -/* interface-dependent forward declarations */ -static int jack_access_registry (jack_shm_info_t *ri); -static int jack_create_registry (jack_shm_info_t *ri); -static void jack_remove_shm (jack_shm_id_t *id); - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * common interface-independent section - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -/* The JACK SHM registry is a chunk of memory for keeping track of the - * shared memory used by each active JACK server. This allows the - * server to clean up shared memory when it exits. To avoid memory - * leakage due to kill -9, crashes or debugger-driven exits, this - * cleanup is also done when a new instance of that server starts. - */ - -/* per-process global data for the SHM interfaces */ -static jack_shm_id_t registry_id; /* SHM id for the registry */ - -#ifdef WIN32 -static jack_shm_info_t registry_info = {/* SHM info for the registry */ - JACK_SHM_NULL_INDEX, - NULL -}; -#else -static jack_shm_info_t registry_info = { /* SHM info for the registry */ - .index = JACK_SHM_NULL_INDEX, - .ptr.attached_at = MAP_FAILED -}; -#endif - -/* pointers to registry header and array */ -static jack_shm_header_t *jack_shm_header = NULL; -static jack_shm_registry_t *jack_shm_registry = NULL; -static char jack_shm_server_prefix[JACK_SERVER_NAME_SIZE+1] = ""; - -/* jack_shm_lock_registry() serializes updates to the shared memory - * segment JACK uses to keep track of the SHM segments allocated to - * all its processes, including multiple servers. - * - * This is not a high-contention lock, but it does need to work across - * multiple processes. High transaction rates and realtime safety are - * not required. Any solution needs to at least be portable to POSIX - * and POSIX-like systems. - * - * We must be particularly careful to ensure that the lock be released - * if the owning process terminates abnormally. Otherwise, a segfault - * or kill -9 at the wrong moment could prevent JACK from ever running - * again on that machine until after a reboot. - */ - -#define JACK_SEMAPHORE_KEY 0x282929 -#ifndef USE_POSIX_SHM -#define JACK_SHM_REGISTRY_KEY JACK_SEMAPHORE_KEY -#endif - -static int semid = -1; - -#ifdef WIN32 - -#include -#include - -static BOOL check_process_running(DWORD process_id) -{ - DWORD aProcesses[2048], cbNeeded, cProcesses; - unsigned int i; - - // Enumerate all processes - if (!EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded)) { - return FALSE; - } - - // Calculate how many process identifiers were returned. - cProcesses = cbNeeded / sizeof(DWORD); - - for (i = 0; i < cProcesses; i++) { - if (aProcesses[i] == process_id) { - // Process process_id is running... - return TRUE; - } - } - return FALSE; -} - -static int -semaphore_init () {return 0;} - -static int -semaphore_add (int value) {return 0;} - -#else -/* all semaphore errors are fatal -- issue message, but do not return */ -static void -semaphore_error (char *msg) -{ - jack_error ("JACK semaphore error: %s (%s)", - msg, strerror (errno)); -} - -static int -semaphore_init () -{ - key_t semkey = JACK_SEMAPHORE_KEY; - struct sembuf sbuf; - int create_flags = IPC_CREAT | IPC_EXCL - | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; - - /* Get semaphore ID associated with this key. */ - if ((semid = semget(semkey, 0, 0)) == -1) { - - /* Semaphore does not exist - Create. */ - if ((semid = semget(semkey, 1, create_flags)) != -1) { - - /* Initialize the semaphore, allow one owner. */ - sbuf.sem_num = 0; - sbuf.sem_op = 1; - sbuf.sem_flg = 0; - if (semop(semid, &sbuf, 1) == -1) { - semaphore_error ("semop"); - return -1; - } - - } else if (errno == EEXIST) { - if ((semid = semget(semkey, 0, 0)) == -1) { - semaphore_error ("semget"); - return -1; - } - - } else { - semaphore_error ("semget creation"); - return -1; - } - } - - return 0; -} - -static inline int -semaphore_add (int value) -{ - struct sembuf sbuf; - - sbuf.sem_num = 0; - sbuf.sem_op = value; - sbuf.sem_flg = SEM_UNDO; - - if (semop(semid, &sbuf, 1) == -1) { - semaphore_error ("semop"); - return -1; - } - - return 0; -} - -#endif - -static int -jack_shm_lock_registry (void) -{ - if (semid == -1) { - if (semaphore_init () < 0) - return -1; - } - - return semaphore_add (-1); -} - -static void -jack_shm_unlock_registry (void) -{ - semaphore_add (1); -} - -static void -jack_shm_init_registry () -{ - /* registry must be locked */ - int i; - - memset (jack_shm_header, 0, JACK_SHM_REGISTRY_SIZE); - - jack_shm_header->magic = JACK_SHM_MAGIC; - //jack_shm_header->protocol = JACK_PROTOCOL_VERSION; - jack_shm_header->type = jack_shmtype; - jack_shm_header->size = JACK_SHM_REGISTRY_SIZE; - jack_shm_header->hdr_len = sizeof (jack_shm_header_t); - jack_shm_header->entry_len = sizeof (jack_shm_registry_t); - - for (i = 0; i < MAX_SHM_ID; ++i) { - jack_shm_registry[i].index = i; - } -} - -static int -jack_shm_validate_registry () -{ - /* registry must be locked */ - - if ((jack_shm_header->magic == JACK_SHM_MAGIC) - //&& (jack_shm_header->protocol == JACK_PROTOCOL_VERSION) - && (jack_shm_header->type == jack_shmtype) - && (jack_shm_header->size == JACK_SHM_REGISTRY_SIZE) - && (jack_shm_header->hdr_len == sizeof (jack_shm_header_t)) - && (jack_shm_header->entry_len == sizeof (jack_shm_registry_t))) { - - return 0; /* registry OK */ - } - - return -1; -} - -/* set a unique per-user, per-server shm prefix string - * - * According to the POSIX standard: - * - * "The name argument conforms to the construction rules for a - * pathname. If name begins with the slash character, then processes - * calling shm_open() with the same value of name refer to the same - * shared memory object, as long as that name has not been - * removed. If name does not begin with the slash character, the - * effect is implementation-defined. The interpretation of slash - * characters other than the leading slash character in name is - * implementation-defined." - * - * Since the Linux implementation does not allow slashes *within* the - * name, in the interest of portability we use colons instead. - */ -static void -jack_set_server_prefix (const char *server_name) -{ -#ifdef WIN32 - char buffer[UNLEN+1]={0}; - DWORD len = UNLEN+1; - GetUserName(buffer, &len); - snprintf (jack_shm_server_prefix, sizeof (jack_shm_server_prefix), - "jack-%s:%s:", buffer, server_name); -#else - snprintf (jack_shm_server_prefix, sizeof (jack_shm_server_prefix), - "jack-%d:%s:", GetUID(), server_name); -#endif -} - -/* gain server addressability to shared memory registration segment - * - * returns: 0 if successful - */ -static int -jack_server_initialize_shm (int new_registry) -{ - int rc; - - if (jack_shm_header) - return 0; /* already initialized */ - - if (jack_shm_lock_registry () < 0) { - jack_error ("jack_shm_lock_registry fails..."); - return -1; - } - - rc = jack_access_registry (®istry_info); - - if (new_registry) { - jack_remove_shm (®istry_id); - rc = ENOENT; - } - - switch (rc) { - case ENOENT: /* registry does not exist */ - rc = jack_create_registry (®istry_info); - break; - case 0: /* existing registry */ - if (jack_shm_validate_registry () == 0) - break; - /* else it was invalid, so fall through */ - case EINVAL: /* bad registry */ - /* Apparently, this registry was created by an older - * JACK version. Delete it so we can try again. */ - jack_release_shm (®istry_info); - jack_remove_shm (®istry_id); - if ((rc = jack_create_registry (®istry_info)) != 0) { - jack_error ("incompatible shm registry (%s)", - strerror (errno)); -#ifndef USE_POSIX_SHM - jack_error ("to delete, use `ipcrm -M 0x%8x'", - JACK_SHM_REGISTRY_KEY); -#endif - } - break; - default: /* failure return code */ - break; - } - - jack_shm_unlock_registry (); - return rc; -} - -/* gain client addressability to shared memory registration segment - * - * NOTE: this function is no longer used for server initialization, - * instead it calls jack_register_server(). - * - * returns: 0 if successful - */ -int -jack_initialize_shm (const char *server_name) -{ - int rc; - - if (jack_shm_header) - return 0; /* already initialized */ - - jack_set_server_prefix (server_name); - - if (jack_shm_lock_registry () < 0) { - jack_error ("jack_shm_lock_registry fails..."); - return -1; - } - - if ((rc = jack_access_registry (®istry_info)) == 0) { - if ((rc = jack_shm_validate_registry ()) != 0) { - jack_error ("Incompatible shm registry, " - "are jackd and libjack in sync?"); - } - } - jack_shm_unlock_registry (); - - return rc; -} - - -char* jack_shm_addr (jack_shm_info_t* si) -{ - return (char*)si->ptr.attached_at; -} - -void -jack_destroy_shm (jack_shm_info_t* si) -{ - /* must NOT have the registry locked */ - if (si->index == JACK_SHM_NULL_INDEX) - return; /* segment not allocated */ - - jack_remove_shm (&jack_shm_registry[si->index].id); - jack_release_shm_info (si->index); -} - -jack_shm_registry_t * -jack_get_free_shm_info () -{ - /* registry must be locked */ - jack_shm_registry_t* si = NULL; - int i; - - for (i = 0; i < MAX_SHM_ID; ++i) { - if (jack_shm_registry[i].size == 0) { - break; - } - } - - if (i < MAX_SHM_ID) { - si = &jack_shm_registry[i]; - } - - return si; -} - -static void -jack_release_shm_entry (jack_shm_registry_index_t index) -{ - /* the registry must be locked */ - jack_shm_registry[index].size = 0; - jack_shm_registry[index].allocator = 0; - memset (&jack_shm_registry[index].id, 0, - sizeof (jack_shm_registry[index].id)); -} - -int -jack_release_shm_info (jack_shm_registry_index_t index) -{ - /* must NOT have the registry locked */ - if (jack_shm_registry[index].allocator == GetPID()) { - if (jack_shm_lock_registry () < 0) { - jack_error ("jack_shm_lock_registry fails..."); - return -1; - } - jack_release_shm_entry (index); - jack_shm_unlock_registry (); - } - - return 0; -} - -/* Claim server_name for this process. - * - * returns 0 if successful - * EEXIST if server_name was already active for this user - * ENOSPC if server registration limit reached - * ENOMEM if unable to access shared memory registry - */ -int -jack_register_server (const char *server_name, int new_registry) -{ - int i, res = 0; - - jack_set_server_prefix (server_name); - - if (jack_server_initialize_shm (new_registry)) - return ENOMEM; - - if (jack_shm_lock_registry () < 0) { - jack_error ("jack_shm_lock_registry fails..."); - return -1; - } - - /* See if server_name already registered. Since server names - * are per-user, we register the unique server prefix string. - */ - for (i = 0; i < MAX_SERVERS; i++) { - - if (strncmp (jack_shm_header->server[i].name, - jack_shm_server_prefix, - JACK_SERVER_NAME_SIZE) != 0) - continue; /* no match */ - - if (jack_shm_header->server[i].pid == GetPID()){ - res = 0; /* it's me */ - goto unlock; - } - - /* see if server still exists */ - #ifdef WIN32 - if (check_process_running(jack_shm_header->server[i].pid)) { - res = EEXIST; /* other server running */ - goto unlock; - } - #else - if (kill (jack_shm_header->server[i].pid, 0) == 0) { - res = EEXIST; /* other server running */ - goto unlock; - } - #endif - - /* it's gone, reclaim this entry */ - memset (&jack_shm_header->server[i], 0, - sizeof (jack_shm_server_t)); - } - - /* find a free entry */ - for (i = 0; i < MAX_SERVERS; i++) { - if (jack_shm_header->server[i].pid == 0) - break; - } - - if (i >= MAX_SERVERS){ - res = ENOSPC; /* out of space */ - goto unlock; - } - - /* claim it */ - jack_shm_header->server[i].pid = GetPID(); - strncpy (jack_shm_header->server[i].name, - jack_shm_server_prefix, - JACK_SERVER_NAME_SIZE); - - unlock: - jack_shm_unlock_registry (); - return res; -} - -/* release server_name registration */ -int -jack_unregister_server (const char *server_name /* unused */) -{ - int i; - if (jack_shm_lock_registry () < 0) { - jack_error ("jack_shm_lock_registry fails..."); - return -1; - } - - for (i = 0; i < MAX_SERVERS; i++) { - if (jack_shm_header->server[i].pid == GetPID()) { - memset (&jack_shm_header->server[i], 0, - sizeof (jack_shm_server_t)); - } - } - - jack_shm_unlock_registry (); - return 0; -} - -/* called for server startup and termination */ -int -jack_cleanup_shm () -{ - int i; - int destroy; - jack_shm_info_t copy; - - if (jack_shm_lock_registry () < 0) { - jack_error ("jack_shm_lock_registry fails..."); - return -1; - } - - for (i = 0; i < MAX_SHM_ID; i++) { - jack_shm_registry_t* r; - - r = &jack_shm_registry[i]; - memcpy (©, r, sizeof (jack_shm_info_t)); - destroy = FALSE; - - /* ignore unused entries */ - if (r->allocator == 0) - continue; - - /* is this my shm segment? */ - if (r->allocator == GetPID()) { - - /* allocated by this process, so unattach - and destroy. */ - jack_release_shm (©); - destroy = TRUE; - - } else { - - /* see if allocator still exists */ - #ifdef WIN32 - //jack_info("TODO: kill API not available !!"); - #else - if (kill (r->allocator, 0)) { - if (errno == ESRCH) { - /* allocator no longer exists, - * so destroy */ - destroy = TRUE; - } - } - #endif - } - - if (destroy) { - - int index = copy.index; - - if ((index >= 0) && (index < MAX_SHM_ID)) { - jack_remove_shm (&jack_shm_registry[index].id); - jack_release_shm_entry (index); - } - r->size = 0; - r->allocator = 0; - } - } - - jack_shm_unlock_registry (); - return TRUE; -} - -/* resize a shared memory segment - * - * There is no way to resize a System V shm segment. Resizing is - * possible with POSIX shm, but not with the non-conformant Mac OS X - * implementation. Since POSIX shm is mainly used on that platform, - * it's simpler to treat them both the same. - * - * So, we always resize by deleting and reallocating. This is - * tricky, because the old segment will not disappear until - * all the clients have released it. We only do what we can - * from here. - * - * This is not done under a single lock. I don't even want to think - * about all the things that could possibly go wrong if multple - * processes tried to resize the same segment concurrently. That - * probably doesn't happen. - */ -int -jack_resize_shm (jack_shm_info_t* si, jack_shmsize_t size) -{ - jack_shm_id_t id; - - /* The underlying type of `id' differs for SYSV and POSIX */ - memcpy (&id, &jack_shm_registry[si->index].id, sizeof (id)); - - jack_release_shm (si); - jack_destroy_shm (si); - - if (jack_shmalloc ((char *) id, size, si)) { - return -1; - } - - return jack_attach_shm (si); -} - -int -jack_attach_lib_shm (jack_shm_info_t* si) -{ - int res = jack_attach_shm(si); - if (res == 0) - si->size = jack_shm_registry[si->index].size; // Keep size in si struct - return res; -} - -int -jack_attach_lib_shm_read (jack_shm_info_t* si) -{ - int res = jack_attach_shm_read(si); - if (res == 0) - si->size = jack_shm_registry[si->index].size; // Keep size in si struct - return res; -} - -#ifdef USE_POSIX_SHM - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * POSIX interface-dependent functions - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -/* gain addressability to existing SHM registry segment - * - * sets up global registry pointers, if successful - * - * returns: 0 if existing registry accessed successfully - * ENOENT if registry does not exist - * EINVAL if registry exists, but has the wrong size - */ -static int -jack_access_registry (jack_shm_info_t *ri) -{ - /* registry must be locked */ - int shm_fd; - - strncpy (registry_id, "/jack-shm-registry", sizeof (registry_id)); - - /* try to open an existing segment */ - if ((shm_fd = shm_open (registry_id, O_RDWR, 0666)) < 0) { - int rc = errno; - if (errno != ENOENT) { - jack_error ("Cannot open existing shm registry segment" - " (%s)", strerror (errno)); - } - close (shm_fd); - return rc; - } - - if ((ri->ptr.attached_at = mmap (0, JACK_SHM_REGISTRY_SIZE, - PROT_READ|PROT_WRITE, - MAP_SHARED, shm_fd, 0)) == MAP_FAILED) { - jack_error ("Cannot mmap shm registry segment (%s)", - strerror (errno)); - close (shm_fd); - return EINVAL; - } - - /* set up global pointers */ - ri->index = JACK_SHM_REGISTRY_INDEX; - jack_shm_header = ri->ptr.attached_at; - jack_shm_registry = (jack_shm_registry_t *) (jack_shm_header + 1); - - close (shm_fd); - return 0; -} - -/* create a new SHM registry segment - * - * sets up global registry pointers, if successful - * - * returns: 0 if registry created successfully - * nonzero error code if unable to allocate a new registry - */ -static int -jack_create_registry (jack_shm_info_t *ri) -{ - /* registry must be locked */ - int shm_fd; - - strncpy (registry_id, "/jack-shm-registry", sizeof (registry_id)); - - if ((shm_fd = shm_open (registry_id, O_RDWR|O_CREAT, 0666)) < 0) { - int rc = errno; - jack_error ("Cannot create shm registry segment (%s)", - strerror (errno)); - return rc; - } - - /* Previous shm_open result depends of the actual value of umask, force correct file permisssion here */ - if (fchmod(shm_fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) < 0) { - jack_log("Cannot chmod jack-shm-registry (%s)", strerror (errno)); - } - - /* Set the desired segment size. NOTE: the non-conformant Mac - * OS X POSIX shm only allows ftruncate() on segment creation. - */ - if (ftruncate (shm_fd, JACK_SHM_REGISTRY_SIZE) < 0) { - int rc = errno; - jack_error ("Cannot set registry size (%s)", strerror (errno)); - jack_remove_shm (®istry_id); - close (shm_fd); - return rc; - } - - if ((ri->ptr.attached_at = mmap (0, JACK_SHM_REGISTRY_SIZE, - PROT_READ|PROT_WRITE, - MAP_SHARED, shm_fd, 0)) == MAP_FAILED) { - jack_error ("Cannot mmap shm registry segment (%s)", - strerror (errno)); - jack_remove_shm (®istry_id); - close (shm_fd); - return EINVAL; - } - - /* set up global pointers */ - ri->index = JACK_SHM_REGISTRY_INDEX; - jack_shm_header = ri->ptr.attached_at; - jack_shm_registry = (jack_shm_registry_t *) (jack_shm_header + 1); - - /* initialize registry contents */ - jack_shm_init_registry (); - close (shm_fd); - return 0; -} - -static void -jack_remove_shm (jack_shm_id_t *id) -{ - /* registry may or may not be locked */ - shm_unlink ((char *) id); -} - -void -jack_release_shm (jack_shm_info_t* si) -{ - /* registry may or may not be locked */ - if (si->ptr.attached_at != MAP_FAILED) { - munmap (si->ptr.attached_at, jack_shm_registry[si->index].size); - } -} - -void -jack_release_lib_shm (jack_shm_info_t* si) -{ - /* registry may or may not be locked */ - if (si->ptr.attached_at != MAP_FAILED) { - munmap (si->ptr.attached_at, si->size); - } -} - -/* allocate a POSIX shared memory segment */ -int -jack_shmalloc (const char *shm_name, jack_shmsize_t size, jack_shm_info_t* si) -{ - jack_shm_registry_t* registry; - int shm_fd; - int rc = -1; - char name[SHM_NAME_MAX+1]; - - if (jack_shm_lock_registry () < 0) { - jack_error ("jack_shm_lock_registry fails..."); - return -1; - } - - if ((registry = jack_get_free_shm_info ()) == NULL) { - jack_error ("shm registry full"); - goto unlock; - } - - /* On Mac OS X, the maximum length of a shared memory segment - * name is SHM_NAME_MAX (instead of NAME_MAX or PATH_MAX as - * defined by the standard). Unfortunately, Apple sets this - * value so small (about 31 bytes) that it is useless for - * actual names. So, we construct a short name from the - * registry index for uniqueness and ignore the shm_name - * parameter. Bah! - */ - snprintf (name, sizeof (name), "/jack-%d-%d", GetUID(), registry->index); - - if (strlen (name) >= sizeof (registry->id)) { - jack_error ("shm segment name too long %s", name); - goto unlock; - } - - if ((shm_fd = shm_open (name, O_RDWR|O_CREAT, 0666)) < 0) { - jack_error ("Cannot create shm segment %s (%s)", - name, strerror (errno)); - goto unlock; - } - - if (ftruncate (shm_fd, size) < 0) { - jack_error ("Cannot set size of engine shm " - "registry 0 (%s)", - strerror (errno)); - close (shm_fd); - goto unlock; - } - - close (shm_fd); - registry->size = size; - strncpy (registry->id, name, sizeof (registry->id)); - registry->allocator = GetPID(); - si->index = registry->index; - si->ptr.attached_at = MAP_FAILED; /* not attached */ - rc = 0; /* success */ - - unlock: - jack_shm_unlock_registry (); - return rc; -} - -int -jack_attach_shm (jack_shm_info_t* si) -{ - int shm_fd; - jack_shm_registry_t *registry = &jack_shm_registry[si->index]; - - if ((shm_fd = shm_open (registry->id, - O_RDWR, 0666)) < 0) { - jack_error ("Cannot open shm segment %s (%s)", registry->id, - strerror (errno)); - return -1; - } - - if ((si->ptr.attached_at = mmap (0, registry->size, PROT_READ|PROT_WRITE, - MAP_SHARED, shm_fd, 0)) == MAP_FAILED) { - jack_error ("Cannot mmap shm segment %s (%s)", - registry->id, - strerror (errno)); - close (shm_fd); - return -1; - } - - close (shm_fd); - return 0; -} - -int -jack_attach_shm_read (jack_shm_info_t* si) -{ - int shm_fd; - jack_shm_registry_t *registry = &jack_shm_registry[si->index]; - - if ((shm_fd = shm_open (registry->id, - O_RDONLY, 0666)) < 0) { - jack_error ("Cannot open shm segment %s (%s)", registry->id, - strerror (errno)); - return -1; - } - - if ((si->ptr.attached_at = mmap (0, registry->size, PROT_READ, - MAP_SHARED, shm_fd, 0)) == MAP_FAILED) { - jack_error ("Cannot mmap shm segment %s (%s)", - registry->id, - strerror (errno)); - close (shm_fd); - return -1; - } - - close (shm_fd); - return 0; -} - -#elif WIN32 - -static int -jack_access_registry (jack_shm_info_t *ri) -{ - /* registry must be locked */ - HANDLE shm_fd; - strncpy (registry_id, "jack-shm-registry", sizeof (registry_id)); - - /* try to open an existing segment */ - - if ((shm_fd = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, registry_id)) == NULL) { - int rc = GetLastError(); - if (rc != ERROR_FILE_NOT_FOUND) { - jack_error ("Cannot open existing shm registry segment (%ld)", rc); - } - return rc; - } - - if ((ri->ptr.attached_at = MapViewOfFile (shm_fd, FILE_MAP_ALL_ACCESS, 0, 0, JACK_SHM_REGISTRY_SIZE)) == NULL) { - jack_error ("Cannot mmap shm registry segment (%ld)", GetLastError()); - jack_remove_shm (®istry_id); - CloseHandle (shm_fd); - return EINVAL; - } - - /* set up global pointers */ - ri->index = JACK_SHM_REGISTRY_INDEX; - jack_shm_header = ri->ptr.attached_at; - jack_shm_registry = (jack_shm_registry_t *) (jack_shm_header + 1); - - //CloseHandle(shm_fd); // TO CHECK - return 0; -} - -static int -jack_create_registry (jack_shm_info_t *ri) -{ - /* registry must be locked */ - HANDLE shm_fd; - - strncpy (registry_id, "jack-shm-registry", sizeof (registry_id)); - - if ((shm_fd = CreateFileMapping(INVALID_HANDLE_VALUE, - 0, PAGE_READWRITE, - 0, JACK_SHM_REGISTRY_SIZE, - registry_id)) == NULL || (shm_fd == INVALID_HANDLE_VALUE)) { - int rc = GetLastError(); - jack_error ("Cannot create shm registry segment (%ld)", rc); - return rc; - } - - if ((ri->ptr.attached_at = MapViewOfFile (shm_fd, FILE_MAP_ALL_ACCESS, 0, 0, JACK_SHM_REGISTRY_SIZE)) == NULL) { - jack_error ("Cannot mmap shm registry segment (%ld)", GetLastError()); - jack_remove_shm (®istry_id); - CloseHandle (shm_fd); - return EINVAL; - } - - /* set up global pointers */ - ri->index = JACK_SHM_REGISTRY_INDEX; - jack_shm_header = ri->ptr.attached_at; - jack_shm_registry = (jack_shm_registry_t *) (jack_shm_header + 1); - - /* initialize registry contents */ - jack_shm_init_registry (); - - //CloseHandle(shm_fd); // TO CHECK - return 0; -} - -static void -jack_remove_shm (jack_shm_id_t *id) -{ - /* nothing to do */ -} - -void -jack_release_shm (jack_shm_info_t* si) -{ - /* registry may or may not be locked */ - if (si->ptr.attached_at != NULL) { - UnmapViewOfFile (si->ptr.attached_at); - } -} - -void -jack_release_lib_shm (jack_shm_info_t* si) -{ - jack_release_shm(si); -} - -int -jack_shmalloc (const char *shm_name, jack_shmsize_t size, jack_shm_info_t* si) -{ - jack_shm_registry_t* registry; - HANDLE shm_fd; - int rc = -1; - char name[SHM_NAME_MAX+1]; - - if (jack_shm_lock_registry () < 0) { - jack_error ("jack_shm_lock_registry fails..."); - return -1; - } - - if ((registry = jack_get_free_shm_info ()) == NULL) { - jack_error ("shm registry full"); - goto unlock; - } - - snprintf (name, sizeof (name), "jack-%d-%d", GetUID(), registry->index); - - if (strlen (name) >= sizeof (registry->id)) { - jack_error ("shm segment name too long %s", name); - goto unlock; - } - - if ((shm_fd = CreateFileMapping(INVALID_HANDLE_VALUE, - 0, PAGE_READWRITE, - 0, size, - name)) == NULL || (shm_fd == INVALID_HANDLE_VALUE)) { - int rc = GetLastError(); - jack_error ("Cannot create shm segment (%ld)",rc); - goto unlock; - } - - //CloseHandle (shm_fd); // TO CHECK - - registry->size = size; - strncpy (registry->id, name, sizeof (registry->id)); - registry->allocator = _getpid(); - si->index = registry->index; - si->ptr.attached_at = NULL; /* not attached */ - rc = 0; /* success */ - - unlock: - jack_shm_unlock_registry (); - return rc; -} - -int -jack_attach_shm (jack_shm_info_t* si) -{ - HANDLE shm_fd; - jack_shm_registry_t *registry = &jack_shm_registry[si->index]; - - if ((shm_fd = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, registry->id)) == NULL) { - int rc = GetLastError(); - jack_error ("Cannot open shm segment (%ld)",rc); - return -1; - } - - if ((si->ptr.attached_at = MapViewOfFile (shm_fd, FILE_MAP_ALL_ACCESS, 0, 0, registry->size)) == NULL) { - jack_error ("Cannot mmap shm segment (%ld)", GetLastError()); - jack_remove_shm (®istry_id); - CloseHandle (shm_fd); - return -1; - } - - //CloseHandle (shm_fd); // TO CHECK - return 0; -} - -int -jack_attach_shm_read (jack_shm_info_t* si) -{ - HANDLE shm_fd; - jack_shm_registry_t *registry = &jack_shm_registry[si->index]; - - if ((shm_fd = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, registry->id)) == NULL) { - int rc = GetLastError(); - jack_error ("Cannot open shm segment (%ld)",rc); - return -1; - } - - if ((si->ptr.attached_at = MapViewOfFile (shm_fd, FILE_MAP_READ, 0, 0, registry->size)) == NULL) { - jack_error("Cannot mmap shm segment (%ld)", GetLastError()); - jack_remove_shm(®istry_id); - CloseHandle(shm_fd); - return -1; - } - - //CloseHandle (shm_fd); // TO CHECK - return 0; -} - -#else - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * System V interface-dependent functions - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -/* gain addressability to existing SHM registry segment - * - * sets up global registry pointers, if successful - * - * returns: 0 if existing registry accessed successfully - * ENOENT if registry does not exist - * EINVAL if registry exists, but has the wrong size - * other nonzero error code if unable to access registry - */ -static int -jack_access_registry (jack_shm_info_t *ri) -{ - /* registry must be locked */ - - /* try without IPC_CREAT to get existing segment */ - if ((registry_id = shmget (JACK_SHM_REGISTRY_KEY, - JACK_SHM_REGISTRY_SIZE, 0666)) < 0) { - - switch (errno) { - - case ENOENT: /* segment does not exist */ - return ENOENT; - - case EINVAL: /* segment exists, but too small */ - /* attempt minimum size access */ - registry_id = shmget (JACK_SHM_REGISTRY_KEY, 1, 0666); - return EINVAL; - - default: /* or other error */ - jack_error ("unable to access shm registry (%s)", - strerror (errno)); - return errno; - } - } - - if ((ri->ptr.attached_at = shmat (registry_id, 0, 0)) < 0) { - jack_error ("Cannot attach shm registry segment (%s)", - strerror (errno)); - return EINVAL; - } - - /* set up global pointers */ - ri->index = JACK_SHM_REGISTRY_INDEX; - jack_shm_header = ri->ptr.attached_at; - jack_shm_registry = (jack_shm_registry_t *) (jack_shm_header + 1); - return 0; -} - -/* create a new SHM registry segment - * - * sets up global registry pointers, if successful - * - * returns: 0 if registry created successfully - * nonzero error code if unable to allocate a new registry - */ -static int -jack_create_registry (jack_shm_info_t *ri) -{ - /* registry must be locked */ - if ((registry_id = shmget (JACK_SHM_REGISTRY_KEY, - JACK_SHM_REGISTRY_SIZE, - 0666|IPC_CREAT)) < 0) { - jack_error ("Cannot create shm registry segment (%s)", - strerror (errno)); - return errno; - } - - if ((ri->ptr.attached_at = shmat (registry_id, 0, 0)) < 0) { - jack_error ("Cannot attach shm registry segment (%s)", - strerror (errno)); - return EINVAL; - } - - /* set up global pointers */ - ri->index = JACK_SHM_REGISTRY_INDEX; - jack_shm_header = ri->ptr.attached_at; - jack_shm_registry = (jack_shm_registry_t *) (jack_shm_header + 1); - - /* initialize registry contents */ - jack_shm_init_registry (); - return 0; -} - -static void -jack_remove_shm (jack_shm_id_t *id) -{ - /* registry may or may not be locked */ - shmctl (*id, IPC_RMID, NULL); -} - -void -jack_release_shm (jack_shm_info_t* si) -{ - /* registry may or may not be locked */ - if (si->ptr.attached_at != MAP_FAILED) { - shmdt (si->ptr.attached_at); - } -} - -void -jack_release_lib_shm (jack_shm_info_t* si) -{ - jack_release_shm(si); -} - -int -jack_shmalloc (const char* name_not_used, jack_shmsize_t size, - jack_shm_info_t* si) -{ - int shmflags; - int shmid; - int rc = -1; - jack_shm_registry_t* registry; - - if (jack_shm_lock_registry () < 0) { - jack_error ("jack_shm_lock_registry fails..."); - return -1; - } - - if ((registry = jack_get_free_shm_info ())) { - - shmflags = 0666 | IPC_CREAT | IPC_EXCL; - - if ((shmid = shmget (IPC_PRIVATE, size, shmflags)) >= 0) { - - registry->size = size; - registry->id = shmid; - registry->allocator = getpid(); - si->index = registry->index; - si->ptr.attached_at = MAP_FAILED; /* not attached */ - rc = 0; - - } else { - jack_error ("Cannot create shm segment %s (%s)", - name_not_used, strerror (errno)); - } - } - - jack_shm_unlock_registry (); - return rc; -} - -int -jack_attach_shm (jack_shm_info_t* si) -{ - if ((si->ptr.attached_at = shmat (jack_shm_registry[si->index].id, 0, 0)) < 0) { - jack_error ("Cannot attach shm segment (%s)", - strerror (errno)); - jack_release_shm_info (si->index); - return -1; - } - return 0; -} - -int -jack_attach_shm_read (jack_shm_info_t* si) -{ - if ((si->ptr.attached_at = shmat (jack_shm_registry[si->index].id, 0, SHM_RDONLY)) < 0) { - jack_error ("Cannot attach shm segment (%s)", - strerror (errno)); - jack_release_shm_info (si->index); - return -1; - } - return 0; -} - -#endif /* !USE_POSIX_SHM */ diff --git a/src/modules/module-jack/shm.h b/src/modules/module-jack/shm.h deleted file mode 100644 index 90336eeaa..000000000 --- a/src/modules/module-jack/shm.h +++ /dev/null @@ -1,216 +0,0 @@ -/* This module provides a set of abstract shared memory interfaces - * with support using both System V and POSIX shared memory - * implementations. The code is divided into three sections: - * - * - common (interface-independent) code - * - POSIX implementation - * - System V implementation - * - Windows implementation - * - * The implementation used is determined by whether USE_POSIX_SHM was - * set in the ./configure step. - */ - -/* - Copyright (C) 2001-2003 Paul Davis - Copyright (C) 2005-2012 Grame - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - */ - -#ifndef __jack_shm_h__ -#define __jack_shm_h__ - -#include -#include - -#include - -#define TRUE 1 -#define FALSE 0 - -#ifdef __cplusplus -extern "C" -{ -#endif - -#define MAX_SERVERS 8 /* maximum concurrent servers */ -#define MAX_SHM_ID 256 /* generally about 16 per server */ -#define JACK_SHM_MAGIC 0x4a41434b /* shm magic number: "JACK" */ -#define JACK_SHM_NULL_INDEX -1 /* NULL SHM index */ -#define JACK_SHM_REGISTRY_INDEX -2 /* pseudo SHM index for registry */ - - - /* On Mac OS X, SHM_NAME_MAX is the maximum length of a shared memory - * segment name (instead of NAME_MAX or PATH_MAX as defined by the - * standard). - */ -#ifdef USE_POSIX_SHM - -#ifndef NAME_MAX -#define NAME_MAX 255 -#endif - -#ifndef SHM_NAME_MAX -#define SHM_NAME_MAX NAME_MAX -#endif - typedef char shm_name_t[SHM_NAME_MAX]; - typedef shm_name_t jack_shm_id_t; - -#elif WIN32 -#define NAME_MAX 255 -#ifndef SHM_NAME_MAX -#define SHM_NAME_MAX NAME_MAX -#endif - typedef char shm_name_t[SHM_NAME_MAX]; - typedef shm_name_t jack_shm_id_t; - -#elif __ANDROID__ - -#ifndef NAME_MAX -#define NAME_MAX 255 -#endif - -#ifndef SHM_NAME_MAX -#define SHM_NAME_MAX NAME_MAX -#endif - typedef char shm_name_t[SHM_NAME_MAX]; - typedef shm_name_t jack_shm_id_t; - typedef int jack_shm_fd_t; - -#else - /* System V SHM */ - typedef int jack_shm_id_t; -#endif /* SHM type */ - - /* shared memory type */ - typedef enum { - shm_POSIX = 1, /* POSIX shared memory */ - shm_SYSV = 2, /* System V shared memory */ - shm_WIN32 = 3, /* Windows 32 shared memory */ - shm_ANDROID = 4 /* Android shared memory */ - } jack_shmtype_t; - - typedef int16_t jack_shm_registry_index_t; - - /** - * A structure holding information about shared memory allocated by - * JACK. this persists across invocations of JACK, and can be used by - * multiple JACK servers. It contains no pointers and is valid across - * address spaces. - * - * The registry consists of two parts: a header including an array of - * server names, followed by an array of segment registry entries. - */ - typedef struct _jack_shm_server { -#ifdef WIN32 - int pid; /* process ID */ -#else - pid_t pid; /* process ID */ -#endif - - char name[JACK_SERVER_NAME_SIZE]; - } - jack_shm_server_t; - - typedef struct _jack_shm_header { - uint32_t magic; /* magic number */ - uint16_t protocol; /* JACK protocol version */ - jack_shmtype_t type; /* shm type */ - jack_shmsize_t size; /* total registry segment size */ - jack_shmsize_t hdr_len; /* size of header */ - jack_shmsize_t entry_len; /* size of registry entry */ - jack_shm_server_t server[MAX_SERVERS]; /* current server array */ - } - jack_shm_header_t; - - typedef struct _jack_shm_registry { - jack_shm_registry_index_t index; /* offset into the registry */ - -#ifdef WIN32 - int allocator; /* PID that created shm segment */ -#else - pid_t allocator; /* PID that created shm segment */ -#endif - - jack_shmsize_t size; /* for POSIX unattach */ - jack_shm_id_t id; /* API specific, see above */ -#ifdef __ANDROID__ - jack_shm_fd_t fd; -#endif - } - jack_shm_registry_t; - -#define JACK_SHM_REGISTRY_SIZE (sizeof (jack_shm_header_t) \ - + sizeof (jack_shm_registry_t) * MAX_SHM_ID) - - /** - * a structure holding information about shared memory - * allocated by JACK. this version is valid only - * for a given address space. It contains a pointer - * indicating where the shared memory has been - * attached to the address space. - */ - - PRE_PACKED_STRUCTURE - struct _jack_shm_info { - jack_shm_registry_index_t index; /* offset into the registry */ - uint32_t size; -#ifdef __ANDROID__ - jack_shm_fd_t fd; -#endif - union { - void *attached_at; /* address where attached */ - char ptr_size[8]; - } ptr; /* a "pointer" that has the same 8 bytes size when compling in 32 or 64 bits */ - } POST_PACKED_STRUCTURE; - - typedef struct _jack_shm_info jack_shm_info_t; - - /* utility functions used only within JACK */ - - void jack_shm_copy_from_registry (jack_shm_info_t*, - jack_shm_registry_index_t); - void jack_shm_copy_to_registry (jack_shm_info_t*, - jack_shm_registry_index_t*); - int jack_release_shm_info (jack_shm_registry_index_t); - char* jack_shm_addr (jack_shm_info_t* si); - - // here begin the API - int jack_register_server (const char *server_name, int new_registry); - int jack_unregister_server (const char *server_name); - - int jack_initialize_shm (const char *server_name); - int jack_initialize_shm_server (void); - int jack_initialize_shm_client (void); - int jack_cleanup_shm (void); - - int jack_shmalloc (const char *shm_name, jack_shmsize_t size, - jack_shm_info_t* result); - void jack_release_shm (jack_shm_info_t*); - void jack_release_lib_shm (jack_shm_info_t*); - void jack_destroy_shm (jack_shm_info_t*); - int jack_attach_shm (jack_shm_info_t*); - int jack_attach_lib_shm (jack_shm_info_t*); - int jack_attach_shm_read (jack_shm_info_t*); - int jack_attach_lib_shm_read (jack_shm_info_t*); - int jack_resize_shm (jack_shm_info_t*, jack_shmsize_t size); - -#ifdef __cplusplus -} -#endif - -#endif /* __jack_shm_h__ */ diff --git a/src/modules/module-jack/synchro.h b/src/modules/module-jack/synchro.h deleted file mode 100644 index 4aacc0a4f..000000000 --- a/src/modules/module-jack/synchro.h +++ /dev/null @@ -1,99 +0,0 @@ -/* PipeWire - * Copyright (C) 2017 Wim Taymans - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include - -struct jack_synchro { - char name[SYNC_MAX_NAME_SIZE]; - bool flush; - sem_t *semaphore; -}; - -#define JACK_SYNCHRO_INIT (struct jack_synchro) { { 0, }, false, NULL } - -static inline int -jack_synchro_init(struct jack_synchro *synchro, - const char *client_name, - const char *server_name, - int value, - bool promiscuous) -{ - char cname[SYNC_MAX_NAME_SIZE+1]; - int i; - for (i = 0; client_name[i] != '\0'; i++) { - if (client_name[i] == '/' || client_name[i] == '\\') - cname[i] = '_'; - else - cname[i] = client_name[i]; - } - cname[i] = client_name[i]; - - if (promiscuous) - snprintf(synchro->name, sizeof(synchro->name), - "jack_sem.%s_%s", server_name, cname); - else - snprintf(synchro->name, sizeof(synchro->name), - "jack_sem.%d_%s_%s", getuid(), server_name, cname); - - 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 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) -{ - int res; - if (synchro->flush) - return true; - if ((res = sem_post(synchro->semaphore)) < 0) - pw_log_error("semaphore %s post err = %s", synchro->name, strerror(errno)); - - return res == 0; -} - -static inline bool -jack_synchro_wait(struct jack_synchro *synchro) -{ - int res; - while ((res = sem_wait(synchro->semaphore)) < 0) { - if (errno != EINTR) - continue; - - pw_log_error("semaphore %s wait err = %s", synchro->name, strerror(errno)); - break; - } - return res == 0; -}