git-svn-id: svn+ssh://jackaudio.org/trunk/jack@353 0c269be4-1314-0410-8aa9-9f06e86f4224tags/0.109.0
| @@ -13,7 +13,7 @@ dnl micro version = incremented when implementation-only | |||
| dnl changes are made | |||
| dnl --- | |||
| JACK_MAJOR_VERSION=0 | |||
| JACK_MINOR_VERSION=63 | |||
| JACK_MINOR_VERSION=64 | |||
| JACK_MICRO_VERSION=0 | |||
| dnl --- | |||
| @@ -24,7 +24,7 @@ dnl made to the way libjack communicates with jackd | |||
| dnl that would break applications linked with an older | |||
| dnl version of libjack. | |||
| dnl --- | |||
| JACK_PROTOCOL_VERSION=3 | |||
| JACK_PROTOCOL_VERSION=4 | |||
| dnl --- | |||
| dnl HOWTO: updating the libjack interface version | |||
| @@ -41,7 +41,7 @@ dnl slacker than this, and closer to those for the JACK version | |||
| dnl number. | |||
| dnl --- | |||
| JACK_API_CURRENT=0 | |||
| JACK_API_REVISION=11 | |||
| JACK_API_REVISION=12 | |||
| JACK_API_AGE=0 | |||
| AC_SUBST(JACK_MAJOR_VERSION) | |||
| @@ -95,6 +95,12 @@ AC_ARG_ENABLE(optimize, | |||
| AC_SUBST(JACK_CFLAGS) | |||
| dnl | |||
| dnl use JACK_CFLAGS for jackd compilation | |||
| dnl | |||
| CFLAGS=$JACK_CFLAGS | |||
| AC_ARG_ENABLE(debug, | |||
| [ --enable-debug enable debugging messages in jackd and libjack], | |||
| [ if test "x$enable_debug" != "xno" ; then | |||
| @@ -45,48 +45,48 @@ AM_CFLAGS = -I.. $(JACK_CFLAGS) $(sndfile_cflags) | |||
| AM_CXXFLAGS = -I.. $(JACK_CFLAGS) $(sndfile_cflags) | |||
| jack_simple_client_SOURCES = simple_client.c | |||
| jack_simple_client_LDFLAGS = -ldl -lpthread | |||
| jack_simple_client_LDFLAGS = -lrt -ldl -lpthread | |||
| jack_simple_client_LDADD = ../libjack/libjack.la | |||
| jack_connect_SOURCES = connect.c | |||
| jack_connect_LDFLAGS = -ldl -lpthread | |||
| jack_connect_LDFLAGS = -lrt -ldl -lpthread | |||
| jack_connect_LDADD = ../libjack/libjack.la | |||
| jack_disconnect_SOURCES = connect.c | |||
| jack_disconnect_LDFLAGS = -ldl -lpthread | |||
| jack_disconnect_LDFLAGS = -lrt -ldl -lpthread | |||
| jack_disconnect_LDADD = ../libjack/libjack.la | |||
| jack_monitor_client_SOURCES = monitor_client.c | |||
| jack_monitor_client_LDFLAGS = -ldl -lpthread | |||
| jack_monitor_client_LDFLAGS = -lrt -ldl -lpthread | |||
| jack_monitor_client_LDADD = ../libjack/libjack.la | |||
| jack_metro_SOURCES = metro.c | |||
| jack_metro_LDFLAGS = -ldl -lpthread | |||
| jack_metro_LDFLAGS = -lrt -ldl -lpthread | |||
| jack_metro_LDADD = ../libjack/libjack.la | |||
| jack_lsp_SOURCES = lsp.c | |||
| jack_lsp_LDFLAGS = -ldl -lpthread | |||
| jack_lsp_LDFLAGS = -lrt -ldl -lpthread | |||
| jack_lsp_LDADD = ../libjack/libjack.la | |||
| jack_showtime_SOURCES = showtime.c | |||
| jack_showtime_LDFLAGS = -ldl -lpthread | |||
| jack_showtime_LDFLAGS = -lrt -ldl -lpthread | |||
| jack_showtime_LDADD = ../libjack/libjack.la | |||
| if HAVE_FLTK | |||
| jack_fltk_client_SOURCES = fltk_client.cc | |||
| jack_fltk_client_LDFLAGS = -L/usr/X11R6/lib -lfltk -lX11 -lXext -ldl -lpthread | |||
| jack_fltk_client_LDFLAGS = -L/usr/X11R6/lib -lfltk -lX11 -lXext -lrt -ldl -lpthread | |||
| jack_fltk_client_LDADD = ../libjack/libjack.la | |||
| endif | |||
| if HAVE_SNDFILE | |||
| jackrec_SOURCES = capture_client.c | |||
| jackrec_LDFLAGS = @SNDFILE_LIBS@ -ldl -lpthread | |||
| jackrec_LDFLAGS = @SNDFILE_LIBS@ -lrt -ldl -lpthread | |||
| jackrec_LDADD = ../libjack/libjack.la | |||
| endif | |||
| jack_impulse_grabber_SOURCES = impulse_grabber.c | |||
| jack_impulse_grabber_LDFLAGS = -ldl -lpthread -lm | |||
| jack_impulse_grabber_LDFLAGS = -lrt -ldl -lpthread -lm | |||
| jack_impulse_grabber_LDADD = ../libjack/libjack.la | |||
| # | |||
| @@ -94,11 +94,11 @@ jack_impulse_grabber_LDADD = ../libjack/libjack.la | |||
| # | |||
| jack_load_SOURCES = ipload.c | |||
| jack_load_LDFLAGS = -ldl -lpthread -lm | |||
| jack_load_LDFLAGS = -lrt -ldl -lpthread -lm | |||
| jack_load_LDADD = ../libjack/libjack.la | |||
| jack_unload_SOURCES = ipunload.c | |||
| jack_unload_LDFLAGS = -ldl -lpthread -lm | |||
| jack_unload_LDFLAGS = -lrt -ldl -lpthread -lm | |||
| jack_unload_LDADD = ../libjack/libjack.la | |||
| # | |||
| @@ -98,7 +98,9 @@ main (int argc, char *argv[]) | |||
| /* create two ports */ | |||
| input_port = jack_port_register (client, "input", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); | |||
| fprintf (stderr, "got ip\n"); | |||
| output_port = jack_port_register (client, "output", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); | |||
| fprintf (stderr, "got op\n"); | |||
| /* tell the JACK server that we are ready to roll */ | |||
| @@ -107,6 +109,8 @@ main (int argc, char *argv[]) | |||
| return 1; | |||
| } | |||
| fprintf (stderr, "activated\n"); | |||
| /* connect the ports. Note: you can't do this before | |||
| the client is activated, because we can't allow | |||
| connections to be made to clients that aren't | |||
| @@ -6,5 +6,5 @@ includedir=@includedir@ | |||
| Name: jack | |||
| Description: the Jack Audio Connection Kit: a low-latency synchronous callback-based media server | |||
| Version: @JACK_VERSION@ | |||
| Libs: -L${libdir} -ljack -lpthread -ldl | |||
| Libs: -L${libdir} -ljack -lpthread -ldl -lrt | |||
| Cflags: -I${includedir} | |||
| @@ -50,9 +50,11 @@ struct _jack_engine { | |||
| int process_errors; | |||
| int period_msecs; | |||
| unsigned int port_max; | |||
| int control_shm_id; | |||
| key_t control_key; | |||
| key_t port_segment_key; /* XXX fix me */ | |||
| int control_shm_fd; | |||
| shm_name_t control_shm_name; | |||
| size_t control_size; | |||
| shm_name_t port_segment_name; /* XXX fix me */ | |||
| size_t port_segment_size; /* XXX fix me */ | |||
| void *port_segment_address; /* XXX fix me */ | |||
| pthread_t main_thread; | |||
| pthread_t server_thread; | |||
| @@ -56,13 +56,14 @@ typedef struct _jack_request jack_request_t; | |||
| typedef void * dlhandle; | |||
| typedef struct { | |||
| int shm_key; | |||
| shm_name_t shm_name; | |||
| size_t offset; | |||
| } jack_port_buffer_info_t; | |||
| typedef struct { | |||
| int shm_key; | |||
| char *address; | |||
| shm_name_t shm_name; | |||
| char *address; | |||
| size_t size; | |||
| } jack_port_segment_info_t; | |||
| typedef struct _time_info | |||
| @@ -136,13 +137,16 @@ typedef struct { | |||
| unsigned long n; | |||
| jack_port_id_t port_id; | |||
| jack_port_id_t self_id; | |||
| int key; | |||
| shm_name_t shm_name; | |||
| } x; | |||
| union { | |||
| unsigned long n; | |||
| jack_port_id_t other_id; | |||
| void* addr; | |||
| } y; | |||
| union { | |||
| size_t size; | |||
| } z; | |||
| } jack_event_t; | |||
| typedef enum { | |||
| @@ -216,10 +220,10 @@ typedef struct { | |||
| int status; | |||
| unsigned int protocol_v; | |||
| unsigned int protocol_v; | |||
| int client_key; | |||
| int control_key; | |||
| shm_name_t client_shm_name; | |||
| shm_name_t control_shm_name; | |||
| char fifo_prefix[PATH_MAX+1]; | |||
| @@ -231,11 +235,13 @@ typedef struct { | |||
| */ | |||
| jack_client_control_t *client_control; | |||
| jack_control_t *engine_control; | |||
| jack_control_t *engine_control; | |||
| size_t control_size; | |||
| /* XXX need to be able to use more than one port segment key */ | |||
| /* XXX need to be able to use more than one port segment */ | |||
| key_t port_segment_key; | |||
| shm_name_t port_segment_name; | |||
| size_t port_segment_size; | |||
| } jack_client_connect_result_t; | |||
| @@ -291,7 +297,7 @@ extern void jack_cleanup_shm (); | |||
| extern void jack_cleanup_files (); | |||
| extern int jack_client_handle_port_connection (jack_client_t *client, jack_event_t *event); | |||
| extern void jack_client_handle_new_port_segment (jack_client_t *client, int key, void* addr); | |||
| extern void jack_client_handle_new_port_segment (jack_client_t *client, shm_name_t, size_t, void* addr); | |||
| extern jack_client_t *jack_driver_client_new (jack_engine_t *, const char *client_name); | |||
| jack_client_t *jack_client_alloc_internal (jack_client_control_t*, jack_control_t*); | |||
| @@ -304,6 +310,8 @@ extern char *jack_server_dir; | |||
| extern void jack_error (const char *fmt, ...); | |||
| extern char *jack_get_shm (const char *shm_name, size_t size, int perm, int mode, int prot); | |||
| #endif /* __jack_internal_h__ */ | |||
| @@ -202,6 +202,8 @@ int jack_port_unregister (jack_client_t *, jack_port_t *); | |||
| * zero-filled. if there are multiple inbound connections, the data | |||
| * will be mixed appropriately. | |||
| * | |||
| * FOR OUTPUT PORTS ONLY | |||
| * --------------------- | |||
| * You may cache the value returned, but only between calls to | |||
| * your "blocksize" callback. For this reason alone, you should | |||
| * either never cache the return value or ensure you have | |||
| @@ -72,7 +72,7 @@ typedef struct _jack_port_type_info { | |||
| */ | |||
| typedef struct _jack_port_shared { | |||
| int shm_key; | |||
| shm_name_t shm_name; | |||
| size_t offset; | |||
| unsigned long flags; | |||
| @@ -23,6 +23,8 @@ | |||
| #include <limits.h> /* ULONG_MAX */ | |||
| typedef char shm_name_t[64]; | |||
| /** | |||
| * Type used to represent sample frame counts. | |||
| */ | |||
| @@ -24,7 +24,7 @@ bin_PROGRAMS = jackd $(CAP_PROGS) | |||
| AM_CFLAGS = $(JACK_CFLAGS) -DJACKD_LOCATION=\"$(bindir)/jackd\" | |||
| jackd_SOURCES = jackd.c engine.c | |||
| jackd_LDADD = ../libjack/libjack.la -lm -ldl -lpthread $(CAP_LIBS) | |||
| jackd_LDADD = ../libjack/libjack.la -lm -ldl -lrt -lpthread $(CAP_LIBS) | |||
| noinst_HEADERS = jack_md5.h md5.h md5_loc.h | |||
| @@ -23,11 +23,10 @@ | |||
| #include <sys/socket.h> | |||
| #include <sys/poll.h> | |||
| #include <sys/un.h> | |||
| #include <sys/shm.h> | |||
| #include <sys/mman.h> | |||
| #include <sys/stat.h> | |||
| #include <errno.h> | |||
| #include <fcntl.h> | |||
| #include <sys/shm.h> | |||
| #include <stdio.h> | |||
| #include <stdarg.h> | |||
| #include <dirent.h> | |||
| @@ -36,7 +35,6 @@ | |||
| #include <sys/types.h> | |||
| #include <string.h> | |||
| #include <limits.h> | |||
| #include <sys/mman.h> | |||
| #include <config.h> | |||
| @@ -73,20 +71,20 @@ typedef struct _jack_client_internal { | |||
| jack_client_control_t *control; | |||
| int request_fd; | |||
| int event_fd; | |||
| int subgraph_start_fd; | |||
| int subgraph_wait_fd; | |||
| JSList *ports; /* protected by engine->client_lock */ | |||
| JSList *fed_by; /* protected by engine->client_lock */ | |||
| int shm_id; | |||
| int shm_key; | |||
| unsigned long execution_order; | |||
| struct _jack_client_internal *next_client; /* not a linked list! */ | |||
| dlhandle handle; | |||
| int (*initialize)(jack_client_t*, const char*); /* for internal clients only */ | |||
| void (*finish)(void); /* for internal clients only */ | |||
| int error; | |||
| int request_fd; | |||
| int event_fd; | |||
| int subgraph_start_fd; | |||
| int subgraph_wait_fd; | |||
| JSList *ports; /* protected by engine->client_lock */ | |||
| JSList *fed_by; /* protected by engine->client_lock */ | |||
| int shm_fd; | |||
| shm_name_t shm_name; | |||
| unsigned long execution_order; | |||
| struct _jack_client_internal *next_client; /* not a linked list! */ | |||
| dlhandle handle; | |||
| int (*initialize)(jack_client_t*, const char*); /* for internal clients only */ | |||
| void (*finish)(void); /* for internal clients only */ | |||
| int error; | |||
| } jack_client_internal_t; | |||
| @@ -137,8 +135,8 @@ static int internal_client_request (void*, jack_request_t *); | |||
| static int jack_use_driver (jack_engine_t *engine, jack_driver_t *driver); | |||
| static int *jack_shm_registry; | |||
| static int jack_shm_id_cnt; | |||
| static shm_name_t *jack_shm_registry; | |||
| static int jack_shm_id_cnt; | |||
| static char *client_state_names[] = { | |||
| "Not triggered", | |||
| @@ -261,7 +259,6 @@ make_sockets (int fd[2]) | |||
| static int | |||
| jack_initialize_shm () | |||
| { | |||
| int shmid_id; | |||
| void *addr; | |||
| if (jack_shm_registry != NULL) { | |||
| @@ -274,31 +271,24 @@ jack_initialize_shm () | |||
| or debugger driven exits. | |||
| */ | |||
| if ((shmid_id = shmget (random(), sizeof(int) * MAX_SHM_ID, IPC_CREAT|0600)) < 0) { | |||
| jack_error ("cannot create engine shm ID registry (%s)", strerror (errno)); | |||
| return -1; | |||
| } | |||
| if ((addr = shmat (shmid_id, 0, 0)) == (void *) -1) { | |||
| jack_error ("cannot attach shm ID registry (%s)", strerror (errno)); | |||
| shmctl (shmid_id, IPC_RMID, 0); | |||
| return -1; | |||
| } | |||
| if (shmctl (shmid_id, IPC_RMID, NULL)) { | |||
| jack_error ("cannot mark shm ID registry as destroyed (%s)", strerror (errno)); | |||
| if ((addr = jack_get_shm ("/jack-shm-registry", sizeof (shm_name_t) * MAX_SHM_ID, | |||
| O_RDWR|O_CREAT|O_TRUNC, 0600, PROT_READ|PROT_WRITE)) == MAP_FAILED) { | |||
| return -1; | |||
| } | |||
| jack_shm_registry = (int *) addr; | |||
| jack_shm_registry = (shm_name_t *) addr; | |||
| jack_shm_id_cnt = 0; | |||
| sprintf (jack_shm_registry[0], "hello"); | |||
| return 0; | |||
| } | |||
| static void | |||
| jack_register_shm (int shmid) | |||
| jack_register_shm (char *shm_name) | |||
| { | |||
| if (jack_shm_id_cnt < MAX_SHM_ID) { | |||
| jack_shm_registry[jack_shm_id_cnt++] = shmid; | |||
| snprintf (jack_shm_registry[jack_shm_id_cnt++], sizeof (shm_name_t), shm_name); | |||
| } | |||
| } | |||
| @@ -308,7 +298,7 @@ jack_cleanup_shm () | |||
| int i; | |||
| for (i = 0; i < jack_shm_id_cnt; i++) { | |||
| shmctl (jack_shm_registry[i], IPC_RMID, NULL); | |||
| shm_unlink (jack_shm_registry[i]); | |||
| } | |||
| } | |||
| @@ -344,36 +334,35 @@ jack_add_port_segment (jack_engine_t *engine, unsigned long nports) | |||
| { | |||
| jack_event_t event; | |||
| jack_port_segment_info_t *si; | |||
| key_t key; | |||
| int id; | |||
| char *addr; | |||
| size_t offset; | |||
| size_t size; | |||
| size_t step; | |||
| shm_name_t shm_name; | |||
| key = random(); | |||
| snprintf (shm_name, sizeof(shm_name), "/jack-port-segment-%d", jack_slist_length (engine->port_segments)); | |||
| size = nports * sizeof (jack_default_audio_sample_t) * engine->control->buffer_size; | |||
| if ((id = shmget (key, size, IPC_CREAT|0666)) < 0) { | |||
| jack_error ("cannot create new port segment of %d bytes, key = 0x%x (%s)", size, key, strerror (errno)); | |||
| if ((addr = jack_get_shm (shm_name, size, (O_RDWR|O_CREAT|O_TRUNC), 0666, PROT_READ|PROT_WRITE)) == MAP_FAILED) { | |||
| jack_error ("cannot create new port segment of %d bytes, shm_name = %s (%s)", size, shm_name, strerror (errno)); | |||
| return -1; | |||
| } | |||
| jack_register_shm (id); | |||
| if ((addr = shmat (id, 0, 0)) == (char *) -1) { | |||
| jack_error ("cannot attach new port segment (%s)", strerror (errno)); | |||
| shmctl (id, IPC_RMID, 0); | |||
| return -1; | |||
| } | |||
| jack_register_shm (shm_name); | |||
| si = (jack_port_segment_info_t *) malloc (sizeof (jack_port_segment_info_t)); | |||
| si->shm_key = key; | |||
| strcpy (si->shm_name, shm_name); | |||
| si->address = addr; | |||
| engine->port_segments = jack_slist_prepend (engine->port_segments, si); | |||
| engine->port_segment_key = key; /* XXX fix me */ | |||
| engine->port_segment_address = addr; /* XXX fix me */ | |||
| /* XXXX this needs fixing so that we can support multiple port segments. | |||
| or does it? | |||
| */ | |||
| strcpy (engine->port_segment_name, shm_name); | |||
| engine->port_segment_address = addr; | |||
| engine->port_segment_size = size; | |||
| pthread_mutex_lock (&engine->buffer_lock); | |||
| @@ -385,7 +374,7 @@ jack_add_port_segment (jack_engine_t *engine, unsigned long nports) | |||
| jack_port_buffer_info_t *bi; | |||
| bi = (jack_port_buffer_info_t *) malloc (sizeof (jack_port_buffer_info_t)); | |||
| bi->shm_key = key; | |||
| strcpy (bi->shm_name, si->shm_name); | |||
| bi->offset = offset; | |||
| /* we append because we want the list to be in memory-address order */ | |||
| @@ -411,7 +400,7 @@ jack_add_port_segment (jack_engine_t *engine, unsigned long nports) | |||
| /* tell everybody about it */ | |||
| event.type = NewPortBufferSegment; | |||
| event.x.key = key; | |||
| strcpy (event.x.shm_name, shm_name); | |||
| event.y.addr = addr; | |||
| jack_deliver_event_to_all (engine, &event); | |||
| @@ -789,9 +778,11 @@ setup_client (jack_engine_t *engine, int client_fd, jack_client_connect_request_ | |||
| } | |||
| res->protocol_v = jack_protocol_version; | |||
| res->client_key = client->shm_key; | |||
| res->control_key = engine->control_key; | |||
| res->port_segment_key = engine->port_segment_key; | |||
| strcpy (res->client_shm_name, client->shm_name); | |||
| strcpy (res->control_shm_name, engine->control_shm_name); | |||
| strcpy (res->port_segment_name, engine->port_segment_name); | |||
| res->port_segment_size = engine->port_segment_size; | |||
| res->control_size = engine->control_size; | |||
| res->realtime = engine->control->real_time; | |||
| res->realtime_priority = engine->rtpriority - 1; | |||
| @@ -808,7 +799,7 @@ setup_client (jack_engine_t *engine, int client_fd, jack_client_connect_request_ | |||
| res->client_control = client->control; | |||
| res->engine_control = engine->control; | |||
| } else { | |||
| strcpy (res->fifo_prefix, engine->fifo_prefix); | |||
| } | |||
| @@ -839,7 +830,8 @@ setup_client (jack_engine_t *engine, int client_fd, jack_client_connect_request_ | |||
| /* tell it about the port segment. XXX fix to work with multiples */ | |||
| jack_client_handle_new_port_segment (client->control->private_client, | |||
| engine->port_segment_key, | |||
| engine->port_segment_name, | |||
| engine->port_segment_size, | |||
| engine->port_segment_address); | |||
| if (client->initialize (client->control->private_client, req->object_data)) { | |||
| @@ -982,7 +974,6 @@ handle_unload_client (jack_engine_t *engine, int client_fd, jack_client_connect_ | |||
| for (node = engine->clients; node; node = jack_slist_next (node)) { | |||
| if (strcmp ((char *) ((jack_client_internal_t *) node->data)->control->name, req->name) == 0) { | |||
| jack_remove_client (engine, (jack_client_internal_t *) node->data); | |||
| fprintf (stderr, "found it\n"); | |||
| res.status = 0; | |||
| break; | |||
| } | |||
| @@ -1191,7 +1182,7 @@ jack_client_activate (jack_engine_t *engine, jack_client_id_t id) | |||
| jack_client_internal_t *client; | |||
| JSList *node; | |||
| int ret = -1; | |||
| jack_lock_graph (engine); | |||
| for (node = engine->clients; node; node = jack_slist_next (node)) { | |||
| @@ -1581,7 +1572,6 @@ jack_engine_t * | |||
| jack_engine_new (int realtime, int rtpriority, int verbose) | |||
| { | |||
| jack_engine_t *engine; | |||
| size_t control_size; | |||
| void *addr; | |||
| unsigned int i; | |||
| #ifdef USE_CAPABILITIES | |||
| @@ -1633,26 +1623,21 @@ jack_engine_new (int realtime, int rtpriority, int verbose) | |||
| srandom (time ((time_t *) 0)); | |||
| engine->control_key = random(); | |||
| control_size = sizeof (jack_control_t) + (sizeof (jack_port_shared_t) * engine->port_max); | |||
| snprintf (engine->control_shm_name, sizeof (engine->control_shm_name), "/jack-engine"); | |||
| engine->control_size = sizeof (jack_control_t) + (sizeof (jack_port_shared_t) * engine->port_max); | |||
| if (jack_initialize_shm (engine)) { | |||
| return 0; | |||
| } | |||
| if ((engine->control_shm_id = shmget (engine->control_key, control_size, IPC_CREAT|0644)) < 0) { | |||
| if ((addr = jack_get_shm (engine->control_shm_name, engine->control_size, | |||
| O_RDWR|O_CREAT|O_TRUNC, 0644, PROT_READ|PROT_WRITE)) == MAP_FAILED) { | |||
| jack_error ("cannot create engine control shared memory segment (%s)", strerror (errno)); | |||
| return 0; | |||
| } | |||
| jack_register_shm (engine->control_shm_id); | |||
| jack_register_shm (engine->control_shm_name); | |||
| if ((addr = shmat (engine->control_shm_id, 0, 0)) == (void *) -1) { | |||
| jack_error ("cannot attach control shared memory segment (%s)", strerror (errno)); | |||
| shmctl (engine->control_shm_id, IPC_RMID, 0); | |||
| return 0; | |||
| } | |||
| engine->control = (jack_control_t *) addr; | |||
| engine->control->engine = engine; | |||
| @@ -2041,8 +2026,10 @@ jack_engine_delete (jack_engine_t *engine) | |||
| { | |||
| if (engine) { | |||
| close (engine->control_shm_fd); | |||
| return pthread_cancel (engine->main_thread); | |||
| } | |||
| return 0; | |||
| } | |||
| @@ -2051,8 +2038,8 @@ jack_client_internal_new (jack_engine_t *engine, int fd, jack_client_connect_req | |||
| { | |||
| jack_client_internal_t *client; | |||
| key_t shm_key = 0; | |||
| int shm_id = 0; | |||
| shm_name_t shm_name; | |||
| int shm_fd = 0; | |||
| void *addr = 0; | |||
| switch (req->type) { | |||
| @@ -2062,21 +2049,13 @@ jack_client_internal_new (jack_engine_t *engine, int fd, jack_client_connect_req | |||
| case ClientExternal: | |||
| shm_key = random(); | |||
| if ((shm_id = shmget (shm_key, sizeof (jack_client_control_t), IPC_CREAT|0666)) < 0) { | |||
| jack_error ("cannot create client control block"); | |||
| snprintf (shm_name, sizeof (shm_name), "/jack-c-%s", req->name); | |||
| if ((addr = jack_get_shm (shm_name, sizeof (jack_client_control_t), | |||
| (O_RDWR|O_CREAT|O_TRUNC), 0666, PROT_READ|PROT_WRITE)) == MAP_FAILED) { | |||
| jack_error ("cannot create client control block for %s", req->name); | |||
| return 0; | |||
| } | |||
| jack_register_shm (shm_id); | |||
| if ((addr = shmat (shm_id, 0, 0)) == (void *) -1) { | |||
| jack_error ("cannot attach new client control block"); | |||
| shmctl (shm_id, IPC_RMID, 0); | |||
| return 0; | |||
| } | |||
| jack_register_shm (shm_name); | |||
| break; | |||
| } | |||
| @@ -2098,8 +2077,8 @@ jack_client_internal_new (jack_engine_t *engine, int fd, jack_client_connect_req | |||
| } else { | |||
| client->shm_id = shm_id; | |||
| client->shm_key = shm_key; | |||
| client->shm_fd = shm_fd; | |||
| strcpy (client->shm_name, shm_name); | |||
| client->control = (jack_client_control_t *) addr; | |||
| } | |||
| @@ -2236,8 +2215,9 @@ jack_client_delete (jack_engine_t *engine, jack_client_internal_t *client) | |||
| jack_client_unload (client); | |||
| free ((char *) client->control); | |||
| } else { | |||
| shmdt ((void *) client->control); | |||
| shmctl(client->shm_id,IPC_RMID,0); | |||
| munmap ((void*) client->control, sizeof (*client->control)); | |||
| shm_unlink (client->shm_name); | |||
| close (client->shm_fd); | |||
| } | |||
| free (client); | |||
| @@ -2309,8 +2289,6 @@ jack_deliver_event (jack_engine_t *engine, jack_client_internal_t *client, jack_ | |||
| if (jack_client_is_internal (client)) { | |||
| fprintf (stderr, "delivering event %d to IP client %s\n", event->type, client->control->name); | |||
| switch (event->type) { | |||
| case PortConnected: | |||
| case PortDisconnected: | |||
| @@ -2342,7 +2320,8 @@ jack_deliver_event (jack_engine_t *engine, jack_client_internal_t *client, jack_ | |||
| break; | |||
| case NewPortBufferSegment: | |||
| jack_client_handle_new_port_segment (client->control->private_client, event->x.key, event->y.addr); | |||
| jack_client_handle_new_port_segment (client->control->private_client, | |||
| event->x.shm_name, event->z.size, event->y.addr); | |||
| break; | |||
| default: | |||
| @@ -2841,8 +2820,6 @@ jack_port_do_connect (jack_engine_t *engine, | |||
| jack_port_internal_t *srcport, *dstport; | |||
| jack_port_id_t src_id, dst_id; | |||
| fprintf (stderr, "got connect request\n"); | |||
| if ((srcport = jack_get_port_by_name (engine, source_port)) == NULL) { | |||
| jack_error ("unknown source port in attempted connection [%s]", source_port); | |||
| return -1; | |||
| @@ -3392,7 +3369,7 @@ jack_port_assign_buffer (jack_engine_t *engine, jack_port_internal_t *port) | |||
| jack_port_segment_info_t *psi = 0; | |||
| jack_port_buffer_info_t *bi; | |||
| port->shared->shm_key = -1; | |||
| port->shared->shm_name[0] = '\0'; | |||
| if (port->shared->flags & JackPortIsInput) { | |||
| port->shared->offset = 0; | |||
| @@ -3413,8 +3390,8 @@ jack_port_assign_buffer (jack_engine_t *engine, jack_port_internal_t *port) | |||
| psi = (jack_port_segment_info_t *) node->data; | |||
| if (bi->shm_key == psi->shm_key) { | |||
| port->shared->shm_key = psi->shm_key; | |||
| if (strcmp (bi->shm_name, psi->shm_name) == 0) { | |||
| strcpy (port->shared->shm_name, psi->shm_name); | |||
| port->shared->offset = bi->offset; | |||
| port->buffer_info = bi; | |||
| break; | |||
| @@ -3422,23 +3399,23 @@ jack_port_assign_buffer (jack_engine_t *engine, jack_port_internal_t *port) | |||
| } | |||
| if (engine->verbose) { | |||
| fprintf (stderr, "port %s buf shm key 0x%x at offset %d bi = %p\n", | |||
| fprintf (stderr, "port %s buf shm name %s at offset %d bi = %p\n", | |||
| port->shared->name, | |||
| port->shared->shm_key, | |||
| port->shared->shm_name, | |||
| (int)port->shared->offset, | |||
| port->buffer_info); | |||
| } | |||
| if (port->shared->shm_key >= 0) { | |||
| if (port->shared->shm_name[0] != '\0') { | |||
| engine->port_buffer_freelist = jack_slist_remove (engine->port_buffer_freelist, bi); | |||
| } else { | |||
| jack_error ("port segment info for 0x%x:%d not found!", bi->shm_key, bi->offset); | |||
| jack_error ("port segment info for %s:%d not found!", bi->shm_name, bi->offset); | |||
| } | |||
| pthread_mutex_unlock (&engine->buffer_lock); | |||
| if (port->shared->shm_key < 0) { | |||
| if (port->shared->shm_name[0] == '\0') { | |||
| return -1; | |||
| } else { | |||
| return 0; | |||
| @@ -25,7 +25,6 @@ | |||
| #include <fcntl.h> | |||
| #include <sys/types.h> | |||
| #include <sys/ipc.h> | |||
| #include <sys/shm.h> | |||
| #include <sys/mman.h> | |||
| #include <sys/poll.h> | |||
| #include <stdarg.h> | |||
| @@ -74,6 +73,32 @@ typedef struct { | |||
| const char *client_name; | |||
| } client_info; | |||
| char * | |||
| jack_get_shm (const char *shm_name, size_t size, int perm, int mode, int prot) | |||
| { | |||
| int shm_fd; | |||
| char *addr; | |||
| if ((shm_fd = shm_open (shm_name, perm, mode)) < 0) { | |||
| jack_error ("cannot create shm segment %s (%s)", shm_name, strerror (errno)); | |||
| return MAP_FAILED; | |||
| } | |||
| if (ftruncate (shm_fd, size) < 0) { | |||
| jack_error ("cannot set size of engine shm registry (%s)", strerror (errno)); | |||
| return MAP_FAILED; | |||
| } | |||
| if ((addr = mmap (0, size, prot, MAP_SHARED, shm_fd, 0)) == MAP_FAILED) { | |||
| jack_error ("cannot mmap shm segment %s (%s)", shm_name, strerror (errno)); | |||
| shm_unlink (shm_name); | |||
| close (shm_fd); | |||
| return MAP_FAILED; | |||
| } | |||
| return addr; | |||
| } | |||
| void | |||
| jack_error (const char *fmt, ...) | |||
| { | |||
| @@ -446,8 +471,6 @@ jack_client_new (const char *client_name) | |||
| int ev_fd = -1; | |||
| jack_client_connect_result_t res; | |||
| jack_client_t *client; | |||
| int client_shm_id; | |||
| int control_shm_id; | |||
| void *addr; | |||
| /* external clients need this initialized; internal clients | |||
| @@ -470,12 +493,8 @@ jack_client_new (const char *client_name) | |||
| /* attach the engine control/info block */ | |||
| if ((control_shm_id = shmget (res.control_key, 0, 0)) < 0) { | |||
| jack_error ("cannot determine shared memory segment for control key 0x%x", res.control_key); | |||
| goto fail; | |||
| } | |||
| if ((addr = shmat (control_shm_id, 0, 0)) == (void *) -1) { | |||
| if ((addr = jack_get_shm (res.control_shm_name, res.control_size, O_RDWR, | |||
| 0, (PROT_READ|PROT_WRITE))) == MAP_FAILED) { | |||
| jack_error ("cannot attached engine control shared memory segment"); | |||
| goto fail; | |||
| } | |||
| @@ -484,19 +503,15 @@ jack_client_new (const char *client_name) | |||
| /* now attach the client control block */ | |||
| if ((client_shm_id = shmget (res.client_key, 0, 0)) < 0) { | |||
| jack_error ("cannot determine shared memory segment for client key 0x%x", res.client_key); | |||
| goto fail; | |||
| } | |||
| if ((addr = shmat (client_shm_id, 0, 0)) == (void *) -1) { | |||
| if ((addr = jack_get_shm (res.client_shm_name, sizeof (jack_client_control_t), O_RDWR, | |||
| 0, (PROT_READ|PROT_WRITE))) == MAP_FAILED) { | |||
| jack_error ("cannot attached client control shared memory segment"); | |||
| goto fail; | |||
| } | |||
| client->control = (jack_client_control_t *) addr; | |||
| jack_client_handle_new_port_segment (client, res.port_segment_key, 0); | |||
| jack_client_handle_new_port_segment (client, res.port_segment_name, res.port_segment_size, 0); | |||
| /* set up the client so that it does the right thing for an external client */ | |||
| @@ -514,10 +529,10 @@ jack_client_new (const char *client_name) | |||
| fail: | |||
| if (client->engine) { | |||
| shmdt (client->engine); | |||
| munmap ((char *) client->engine, sizeof (jack_control_t)); | |||
| } | |||
| if (client->control) { | |||
| shmdt ((char *) client->control); | |||
| munmap ((char *) client->control, sizeof (jack_client_control_t)); | |||
| } | |||
| if (req_fd >= 0) { | |||
| close (req_fd); | |||
| @@ -563,10 +578,9 @@ jack_internal_client_close (const char *client_name) | |||
| } | |||
| void | |||
| jack_client_handle_new_port_segment (jack_client_t *client, int key, void* addr) | |||
| jack_client_handle_new_port_segment (jack_client_t *client, shm_name_t shm_name, size_t size, void* addr) | |||
| { | |||
| jack_port_segment_info_t *si; | |||
| int port_segment_shm_id; | |||
| /* Lookup, attach and register the port/buffer segments in use | |||
| right now. | |||
| @@ -574,15 +588,8 @@ jack_client_handle_new_port_segment (jack_client_t *client, int key, void* addr) | |||
| if (client->control->type == ClientExternal) { | |||
| /* map shared memory */ | |||
| if ((port_segment_shm_id = shmget (key, 0, 0)) < 0) { | |||
| jack_error ("cannot determine shared memory segment for port segment key 0x%x (%s)", | |||
| key, strerror (errno)); | |||
| return; | |||
| } | |||
| if ((addr = shmat (port_segment_shm_id, 0, 0)) == (void *) -1) { | |||
| if ((addr = jack_get_shm(shm_name, size, O_RDWR, 0, (PROT_READ|PROT_WRITE))) == MAP_FAILED) { | |||
| jack_error ("cannot attached port segment shared memory (%s)", strerror (errno)); | |||
| return; | |||
| } | |||
| @@ -593,8 +600,9 @@ jack_client_handle_new_port_segment (jack_client_t *client, int key, void* addr) | |||
| } | |||
| si = (jack_port_segment_info_t *) malloc (sizeof (jack_port_segment_info_t)); | |||
| si->shm_key = key; | |||
| strcpy (si->shm_name, shm_name); | |||
| si->address = addr; | |||
| si->size = size; | |||
| /* the first chunk of the first port segment is always set by the engine | |||
| to be a conveniently-sized, zero-filled lump of memory. | |||
| @@ -626,10 +634,6 @@ jack_client_thread (void *arg) | |||
| pthread_cond_signal (&client_ready); | |||
| pthread_mutex_unlock (&client_lock); | |||
| /* XXX reset the PID to be the actual client thread. Kai and Fernando know | |||
| about this and it needs fixing. | |||
| */ | |||
| client->control->pid = getpid(); | |||
| DEBUG ("client thread is now running"); | |||
| @@ -725,7 +729,7 @@ jack_client_thread (void *arg) | |||
| break; | |||
| case NewPortBufferSegment: | |||
| jack_client_handle_new_port_segment (client, event.x.key, event.y.addr); | |||
| jack_client_handle_new_port_segment (client, event.x.shm_name, event.z.size, event.y.addr); | |||
| break; | |||
| } | |||
| @@ -1044,7 +1048,7 @@ jack_activate (jack_client_t *client) | |||
| pthread_mutex_unlock (&client_lock); | |||
| return -1; | |||
| } | |||
| pthread_cond_wait (&client_ready, &client_lock); | |||
| pthread_mutex_unlock (&client_lock); | |||
| @@ -1091,11 +1095,12 @@ jack_client_close (jack_client_t *client) | |||
| pthread_cancel (client->thread); | |||
| pthread_join (client->thread, &status); | |||
| shmdt ((char *) client->control); | |||
| shmdt (client->engine); | |||
| munmap ((char *) client->control, sizeof (jack_client_control_t)); | |||
| munmap ((char *) client->engine, sizeof (jack_control_t)); | |||
| for (node = client->port_segments; node; node = jack_slist_next (node)) { | |||
| shmdt (((jack_port_segment_info_t *) node->data)->address); | |||
| jack_port_segment_info_t *si = (jack_port_segment_info_t *) node->data; | |||
| munmap ((char *) si->address, si->size); | |||
| free (node->data); | |||
| } | |||
| jack_slist_free (client->port_segments); | |||
| @@ -60,8 +60,9 @@ jack_port_new (const jack_client_t *client, jack_port_id_t port_id, jack_control | |||
| for (node = client->port_segments; node; node = jack_slist_next (node)) { | |||
| si = (jack_port_segment_info_t *) node->data; | |||
| if (si->shm_key == port->shared->shm_key) { | |||
| if (strcmp (si->shm_name, port->shared->shm_name) == 0) { | |||
| fprintf (stderr, "found port segment for %s\n", port->shared->name); | |||
| break; | |||
| } | |||
| } | |||