diff --git a/configure.in b/configure.in index 0736fdf..d50a77c 100644 --- a/configure.in +++ b/configure.in @@ -14,7 +14,7 @@ dnl changes are made dnl --- JACK_MAJOR_VERSION=0 JACK_MINOR_VERSION=83 -JACK_MICRO_VERSION=0 +JACK_MICRO_VERSION=1 dnl --- dnl HOWTO: updating the jack protocal version diff --git a/jack/engine.h b/jack/engine.h index 72bfeac..433803d 100644 --- a/jack/engine.h +++ b/jack/engine.h @@ -38,6 +38,7 @@ typedef struct { jack_shmsize_t offset; } jack_port_buffer_info_t; +/* The engine keeps an array of these in its local memory. */ typedef struct _jack_port_internal { struct _jack_port_shared *shared; JSList *connections; diff --git a/jack/port.h b/jack/port.h index 23dae16..c8761e6 100644 --- a/jack/port.h +++ b/jack/port.h @@ -46,24 +46,22 @@ typedef int32_t jack_port_type_id_t; typedef struct { shm_name_t shm_name; - char *address; /* JOQ: no longer set globally */ jack_shmsize_t size; } jack_port_segment_info_t; -/* Port type structure. Has several uses: +/* Port type structure. * * (1) One for each port type is part of the engine's jack_control_t * shared memory structure. * * (2) One for each port type is appended to the engine's - * jack_client_connect_result_t response. - * - * (3) The client reads these into its local memory, and uses them to - * attach the corresponding shared memory segments. + * jack_client_connect_result_t response. The client reads them into + * its local memory, using them to attach the corresponding shared + * memory segments. */ typedef struct _jack_port_type_info { - jack_port_type_id_t type_id; + jack_port_type_id_t ptype_id; const char type_name[JACK_PORT_TYPE_SIZE]; /* If == 1, then a buffer to handle nframes worth of data has @@ -82,17 +80,12 @@ typedef struct _jack_port_type_info { } jack_port_type_info_t; -/* This is the data structure allocated in shared memory - * by the engine. - */ +/* Allocated by the engine in shared memory. */ typedef struct _jack_port_shared { - jack_port_type_info_t type_info; - /* location of buffer as an offset from the start of the port's - * type-specific shared memory region. */ - jack_shmsize_t offset; - /* index into engine port array for this port */ - jack_port_id_t id; - int8_t has_mixdown; /* port has a mixdown function */ + + jack_port_type_id_t ptype_id; /* index into port type array */ + jack_shmsize_t offset; /* buffer offset in shm segment */ + jack_port_id_t id; /* index into engine port array */ enum JackPortFlags flags; char name[JACK_CLIENT_NAME_SIZE+JACK_PORT_NAME_SIZE+2]; jack_client_id_t client_id; /* who owns me */ @@ -101,6 +94,7 @@ typedef struct _jack_port_shared { volatile jack_nframes_t total_latency; volatile uint8_t monitor_requests; + int8_t has_mixdown; /* port has a mixdown function */ char in_use : 1; char locked : 1; @@ -115,20 +109,27 @@ typedef struct _jack_port_functions { } jack_port_functions_t; -/* This port structure is allocated by the client in local memory. */ +/* Allocated by the client in local memory. */ struct _jack_port { - char *client_segment_base; + void **client_segment_base; + void *mix_buffer; + jack_port_type_info_t *type_info; /* shared memory type info */ struct _jack_port_shared *shared; /* corresponding shm struct */ struct _jack_port *tied; /* locally tied source port */ - jack_port_functions_t fptr; /* local port functions */ - pthread_mutex_t connection_lock; + jack_port_functions_t fptr; + pthread_mutex_t connection_lock; JSList *connections; }; -/* Inline would be cleaner, but it needs to be fast even in - * non-optimized code. */ +/* Inline would be cleaner, but it needs to be fast even in + * non-optimized code. jack_output_port_buffer() only handles output + * ports. jack_port_buffer() works for both input and output ports. + */ #define jack_port_buffer(p) \ - ((void *) ((p)->client_segment_base + (p)->shared->offset)) + ((void *) ((p)->mix_buffer? (p)->mix_buffer: \ + *(p)->client_segment_base + (p)->shared->offset)) +#define jack_output_port_buffer(p) \ + ((void *) (*(p)->client_segment_base + (p)->shared->offset)) #endif /* __jack_port_h__ */ diff --git a/jackd/engine.c b/jackd/engine.c index 871d35d..aa11c4b 100644 --- a/jackd/engine.c +++ b/jackd/engine.c @@ -171,14 +171,14 @@ jack_global_port_type_info (jack_engine_t *engine, jack_port_internal_t *port) { /* Returns a pointer to the port type information in the engine's shared control structure. */ - return &engine->control->port_types[port->shared->type_info.type_id]; + return &engine->control->port_types[port->shared->ptype_id]; } static inline jack_port_type_internal_t * jack_local_port_type_info (jack_engine_t *engine, jack_port_internal_t *port) { /* Points to the engine's private port type struct. */ - return &engine->port_type[port->shared->type_info.type_id]; + return &engine->port_type[port->shared->ptype_id]; } static int @@ -311,8 +311,9 @@ jack_resize_port_segment (jack_engine_t *engine, int shmid; int perm; jack_port_buffer_info_t *bi; - jack_port_type_id_t ptid = port_type->type_id; + jack_port_type_id_t ptid = port_type->ptype_id; jack_port_type_internal_t *pti = &engine->port_type[ptid]; + jack_port_id_t i; if (port_type->buffer_scale_factor < 0) { one_buffer = port_type->buffer_size; @@ -369,8 +370,8 @@ jack_resize_port_segment (jack_engine_t *engine, pthread_mutex_unlock (&pti->buffer_lock); } else { - /* resize existing buffer segment */ + if ((addr = jack_resize_shm (port_type->shm_info.shm_name, size, perm, 0666, PROT_READ|PROT_WRITE)) @@ -391,6 +392,15 @@ jack_resize_port_segment (jack_engine_t *engine, offset += one_buffer; ++bi; } + + /* update any existing output port offsets */ + for (i = 0; i < engine->port_max; i++) { + if (engine->control->ports[i].flags|JackPortIsOutput && + engine->control->ports[i].ptype_id == ptid) { + bi = engine->internal_ports[i].buffer_info; + engine->control->ports[i].offset = bi->offset; + } + } pthread_mutex_unlock (&pti->buffer_lock); } @@ -401,7 +411,7 @@ jack_resize_port_segment (jack_engine_t *engine, event.type = AttachPortSegment; strcpy (event.x.shm_name, port_type->shm_info.shm_name); event.y.ptid = ptid; - event.z.size = size; /* JOQ: why wasn't this set before? */ + event.z.size = size; jack_deliver_event_to_all (engine, &event); } @@ -2025,8 +2035,8 @@ jack_engine_new (int realtime, int rtpriority, int verbose, int client_timeout) &jack_builtin_port_types[i], sizeof (jack_port_type_info_t)); - /* set offset into port_types array */ - engine->control->port_types[i].type_id = i; + /* the port type id is index into port_types array */ + engine->control->port_types[i].ptype_id = i; /* be sure to initialize mutex correctly */ pthread_mutex_init (&engine->port_type[i].buffer_lock, NULL); @@ -3388,7 +3398,7 @@ void jack_dump_configuration(jack_engine_t *engine, int take_lock) jack_slist_length(client->fed_by), client->subgraph_start_fd, client->subgraph_wait_fd); - + for(m = 0, portnode = client->ports; portnode; portnode = jack_slist_next (portnode)) { port = (jack_port_internal_t *) portnode->data; @@ -3472,8 +3482,7 @@ jack_port_do_connect (jack_engine_t *engine, return -1; } - if (srcport->shared->type_info.type_id - != dstport->shared->type_info.type_id) { + if (srcport->shared->ptype_id != dstport->shared->ptype_id) { jack_error ("ports used in attemped connection are not of " "the same data type"); return -1; @@ -3508,7 +3517,8 @@ jack_port_do_connect (jack_engine_t *engine, } for (it = srcport->connections; it; it = it->next) { - if (((jack_connection_internal_t *)it->data)->destination == dstport) { + if (((jack_connection_internal_t *)it->data)->destination + == dstport) { return EEXIST; } } @@ -3524,11 +3534,11 @@ jack_port_do_connect (jack_engine_t *engine, jack_lock_graph (engine); - if (dstport->connections && - !dstport->shared->has_mixdown) { + if (dstport->connections && !dstport->shared->has_mixdown) { + jack_port_type_info_t *port_type = + jack_global_port_type_info (engine, dstport); jack_error ("cannot make multiple connections to a port of" - " type [%s]", - dstport->shared->type_info.type_name); + " type [%s]", port_type->type_name); free (connection); jack_unlock_graph (engine); return -1; @@ -3900,8 +3910,7 @@ jack_port_do_register (jack_engine_t *engine, jack_request_t *req) shared = &engine->control->ports[port_id]; strcpy (shared->name, req->x.port_info.name); - memcpy (&shared->type_info, &engine->control->port_types[i], - sizeof (jack_port_type_info_t)); + shared->ptype_id = engine->control->port_types[i].ptype_id; shared->client_id = req->x.port_info.client_id; shared->flags = req->x.port_info.flags; shared->latency = 0; diff --git a/libjack/client.c b/libjack/client.c index aa73c50..e719a95 100644 --- a/libjack/client.c +++ b/libjack/client.c @@ -202,11 +202,9 @@ jack_client_invalidate_port_buffers (jack_client_t *client) port = (jack_port_t *) node->data; if (port->shared->flags & JackPortIsInput) { - if (port->client_segment_base == 0) { - jack_pool_release ( - (void *) port->shared->offset); - port->client_segment_base = 0; - port->shared->offset = 0; + if (port->mix_buffer) { + jack_pool_release (port->mix_buffer); + port->mix_buffer = NULL; } } } @@ -1527,16 +1525,19 @@ jack_get_ports (jack_client_t *client, engine = client->engine; if (port_name_pattern && port_name_pattern[0]) { - regcomp (&port_regex, port_name_pattern, REG_EXTENDED|REG_NOSUB); + regcomp (&port_regex, port_name_pattern, + REG_EXTENDED|REG_NOSUB); } if (type_name_pattern && type_name_pattern[0]) { - regcomp (&type_regex, type_name_pattern, REG_EXTENDED|REG_NOSUB); + regcomp (&type_regex, type_name_pattern, + REG_EXTENDED|REG_NOSUB); } psp = engine->ports; match_cnt = 0; - matching_ports = (const char **) malloc (sizeof (char *) * engine->port_max); + matching_ports = (const char **) + malloc (sizeof (char *) * engine->port_max); for (i = 0; i < engine->port_max; i++) { matching = 1; @@ -1558,7 +1559,10 @@ jack_get_ports (jack_client_t *client, } if (matching && type_name_pattern && type_name_pattern[0]) { - if (regexec (&type_regex, psp[i].type_info.type_name, 0, NULL, 0)) { + jack_port_type_id_t ptid = psp[i].ptype_id; + if (regexec (&type_regex, + engine->port_types[ptid].type_name, + 0, NULL, 0)) { matching = 0; } } diff --git a/libjack/local.h b/libjack/local.h index 509f54b..0473de4 100644 --- a/libjack/local.h +++ b/libjack/local.h @@ -10,9 +10,15 @@ struct _jack_client { int pollmax; int graph_next_fd; int request_fd; + jack_port_type_id_t n_port_types; - jack_port_segment_info_t port_segment[JACK_MAX_PORT_TYPES]; + struct { + shm_name_t shm_name; + void *address; + jack_shmsize_t size; + } port_segment[JACK_MAX_PORT_TYPES]; JSList *ports; + pthread_t thread; char fifo_prefix[PATH_MAX+1]; void (*on_shutdown)(void *arg); diff --git a/libjack/port.c b/libjack/port.c index f95d022..cc9af6d 100644 --- a/libjack/port.c +++ b/libjack/port.c @@ -61,11 +61,13 @@ jack_port_new (const jack_client_t *client, jack_port_id_t port_id, jack_control_t *control) { jack_port_shared_t *shared = &control->ports[port_id]; - jack_port_type_id_t ptid = shared->type_info.type_id; + jack_port_type_id_t ptid = shared->ptype_id; jack_port_t *port = (jack_port_t *) malloc (sizeof (jack_port_t)); - port->client_segment_base = 0; + port->mix_buffer = NULL; + port->client_segment_base = NULL; port->shared = shared; + port->type_info = &client->engine->port_types[ptid]; pthread_mutex_init (&port->connection_lock, NULL); port->connections = 0; port->tied = NULL; @@ -76,7 +78,7 @@ jack_port_new (const jack_client_t *client, jack_port_id_t port_id, * functions within this address space. These builtin * definitions can be overridden by the client. */ - if (port->shared->type_info.type_id == JACK_AUDIO_PORT_TYPE) { + if (ptid == JACK_AUDIO_PORT_TYPE) { port->fptr = jack_builtin_audio_functions; port->shared->has_mixdown = TRUE; @@ -94,7 +96,8 @@ jack_port_new (const jack_client_t *client, jack_port_id_t port_id, port->offset can change if the buffer size or port counts are changed. */ - port->client_segment_base = client->port_segment[ptid].address; + port->client_segment_base = + (void *) &client->port_segment[ptid].address; return port; } @@ -371,7 +374,7 @@ jack_port_get_buffer (jack_port_t *port, jack_nframes_t nframes) if (port->tied) { return jack_port_get_buffer (port->tied, nframes); } - return jack_port_buffer (port); + return jack_output_port_buffer (port); } /* Input port. Since this can only be called from the @@ -394,28 +397,20 @@ jack_port_get_buffer (jack_port_t *port, jack_nframes_t nframes) nframes); } - /* Multiple connections. Use a local buffer and mixdown the - incoming data to that buffer. we have already established - the existence of a mixdown function during the connection - process. - - No port can have an offset of 0, that offset refers to the - zero-filled area at the start of a shared port segment - area. So, use the offset to store the location of a - locally allocated buffer, and reset the client_segment_base - so that the jack_port_buffer() computation works correctly. + /* Multiple connections. Use a local buffer and mix the + incoming data into that buffer. We have already + established the existence of a mixdown function during the + connection process. */ - - if (port->shared->offset == 0) { - port->shared->offset = (size_t) + if (port->mix_buffer == NULL) { + port->mix_buffer = jack_pool_alloc ( - port->shared->type_info.buffer_scale_factor + port->type_info->buffer_scale_factor * sizeof (jack_default_audio_sample_t) * nframes); - port->client_segment_base = 0; } port->fptr.mixdown (port, nframes); - return (jack_default_audio_sample_t *) port->shared->offset; + return (jack_default_audio_sample_t *) port->mix_buffer; } int @@ -565,7 +560,7 @@ jack_port_flags (const jack_port_t *port) const char * jack_port_type (const jack_port_t *port) { - return port->shared->type_info.type_name; + return port->type_info->type_name; } int @@ -604,7 +599,8 @@ jack_audio_port_mixdown (jack_port_t *port, jack_nframes_t nframes) jack_default_audio_sample_t *dst, *src; /* by the time we've called this, we've already established - the existence of more than 1 connection to this input port. + the existence of more than one connection to this input + port and allocated a mix_buffer. */ /* no need to take connection lock, since this is called @@ -615,9 +611,9 @@ jack_audio_port_mixdown (jack_port_t *port, jack_nframes_t nframes) node = port->connections; input = (jack_port_t *) node->data; - buffer = jack_port_buffer (port); + buffer = port->mix_buffer; - memcpy (buffer, jack_port_buffer (input), + memcpy (buffer, jack_output_port_buffer (input), sizeof (jack_default_audio_sample_t) * nframes); for (node = jack_slist_next (node); node; @@ -627,7 +623,7 @@ jack_audio_port_mixdown (jack_port_t *port, jack_nframes_t nframes) n = nframes; dst = buffer; - src = jack_port_buffer (input); + src = jack_output_port_buffer (input); while (n--) { *dst++ += *src++;