jack: manage io areas better

This commit is contained in:
Wim Taymans 2018-05-25 12:48:23 +02:00
parent 5b05b21865
commit b4d2e47c34

View file

@ -52,6 +52,7 @@
#define MAX_BUFFER_DATAS 4u #define MAX_BUFFER_DATAS 4u
#define MAX_BUFFER_MEMS 4 #define MAX_BUFFER_MEMS 4
#define MAX_MIX 4096 #define MAX_MIX 4096
#define MAX_IO 32
#define DEFAULT_SAMPLE_RATE 44100 #define DEFAULT_SAMPLE_RATE 44100
#define DEFAULT_BUFFER_SIZE 1024 #define DEFAULT_BUFFER_SIZE 1024
@ -154,14 +155,20 @@ struct buffer {
uint32_t n_mem; uint32_t n_mem;
}; };
struct io {
uint32_t id;
uint32_t memid;
};
struct mix { struct mix {
struct spa_list link; struct spa_list link;
struct spa_list port_link; struct spa_list port_link;
uint32_t id; uint32_t id;
struct port *port; struct port *port;
struct io ios[MAX_IO];
struct spa_io_buffers *io; struct spa_io_buffers *io;
struct spa_io_control_range *ctrl;
struct buffer buffers[MAX_BUFFERS]; struct buffer buffers[MAX_BUFFERS];
uint32_t n_buffers; uint32_t n_buffers;
@ -320,6 +327,7 @@ static void free_object(struct client *c, struct object *o)
static struct mix *ensure_mix(struct client *c, struct port *port, uint32_t mix_id) static struct mix *ensure_mix(struct client *c, struct port *port, uint32_t mix_id)
{ {
struct mix *mix; struct mix *mix;
int i;
spa_list_for_each(mix, &port->mix, port_link) { spa_list_for_each(mix, &port->mix, port_link) {
if (mix->id == mix_id) if (mix->id == mix_id)
@ -338,6 +346,8 @@ static struct mix *ensure_mix(struct client *c, struct port *port, uint32_t mix_
mix->port = port; mix->port = port;
mix->io = NULL; mix->io = NULL;
mix->n_buffers = 0; mix->n_buffers = 0;
for (i = 0; i < MAX_IO; i++)
mix->ios[i].id = SPA_ID_INVALID;
return mix; return mix;
} }
@ -1100,6 +1110,41 @@ static void client_node_port_command(void *object,
{ {
} }
static void clear_io(struct client *c, struct io *io)
{
struct mem *m;
m = find_mem(&c->mems, io->memid);
if (--m->ref == 0)
clear_mem(c, m);
io->id = SPA_ID_INVALID;
}
static struct io *update_io(struct client *c, struct mix *mix,
uint32_t id, uint32_t memid)
{
int i;
struct io *io, *f = NULL;
for (i = 0; i < MAX_IO; i++) {
io = &mix->ios[i];
if (io->id == SPA_ID_INVALID)
f = io;
else if (io->id == id) {
if (io->memid != memid)
clear_io(c, io);
f = io;
break;
}
}
if (f == NULL)
return NULL;
io = f;
io->id = id;
io->memid = memid;
return io;
}
static void client_node_port_set_io(void *object, static void client_node_port_set_io(void *object,
uint32_t seq, uint32_t seq,
enum spa_direction direction, enum spa_direction direction,
@ -1118,6 +1163,11 @@ static void client_node_port_set_io(void *object,
void *ptr; void *ptr;
int res = 0; int res = 0;
if ((mix = ensure_mix(c, p, mix_id)) == NULL) {
res = -ENOMEM;
goto exit;
}
if (mem_id == SPA_ID_INVALID) { if (mem_id == SPA_ID_INVALID) {
ptr = NULL; ptr = NULL;
size = 0; size = 0;
@ -1133,19 +1183,14 @@ static void client_node_port_set_io(void *object,
res = -errno; res = -errno;
goto exit; goto exit;
} }
m->ref++;
} }
if ((mix = ensure_mix(c, p, mix_id)) == NULL) { update_io(c, mix, id, mem_id);
res = -ENOMEM;
goto exit;
}
if (id == t->io.Buffers) { if (id == t->io.Buffers)
mix->io = ptr; mix->io = ptr;
}
else if (id == t->io.ControlRange) {
mix->ctrl = ptr;
}
pw_log_debug("port %p: set io id %u %u %u %u %p", p, id, mem_id, offset, size, ptr); pw_log_debug("port %p: set io id %u %u %u %u %p", p, id, mem_id, offset, size, ptr);
exit: exit: