diff --git a/pipewire-jack/src/pipewire-jack.c b/pipewire-jack/src/pipewire-jack.c index caeefd3a0..92e5af7fc 100644 --- a/pipewire-jack/src/pipewire-jack.c +++ b/pipewire-jack/src/pipewire-jack.c @@ -972,31 +972,32 @@ static inline void *get_buffer_output(struct port *p, uint32_t frames, uint32_t struct mix *mix; struct client *c = p->client; void *ptr = NULL; - - p->io.status = -EPIPE; - p->io.buffer_id = SPA_ID_INVALID; + struct buffer *b; if (frames == 0) return NULL; - if (SPA_LIKELY((mix = p->global_mix) != NULL)) { - struct buffer *b; + if (SPA_UNLIKELY((mix = p->global_mix) == NULL)) + return NULL; - if (SPA_UNLIKELY(mix->n_buffers == 0)) - goto done; + pw_log_trace_fp("%p: port %p %d get buffer %d n_buffers:%d", + c, p, p->id, frames, mix->n_buffers); - pw_log_trace_fp("%p: port %p %d get buffer %d n_buffers:%d", - c, p, p->id, frames, mix->n_buffers); + if (SPA_UNLIKELY(mix->n_buffers == 0)) + return NULL; - if (SPA_UNLIKELY((b = dequeue_buffer(mix)) == NULL)) { - pw_log_warn("port %p: out of buffers", p); - goto done; + if (p->io.status == SPA_STATUS_HAVE_DATA && + p->io.buffer_id < mix->n_buffers) { + b = &mix->buffers[p->io.buffer_id]; + } else { + if (p->io.buffer_id < mix->n_buffers) { + reuse_buffer(c, mix, p->io.buffer_id); + p->io.buffer_id = SPA_ID_INVALID; + } + if (SPA_UNLIKELY((b = dequeue_buffer(c, mix)) == NULL)) { + pw_log_warn("port %p: out of buffers", p); + return NULL; } - reuse_buffer(c, mix, b->id); - ptr = b->datas[0].data; - if (buf) - *buf = b; - b->datas[0].chunk->offset = 0; b->datas[0].chunk->size = frames * sizeof(float); b->datas[0].chunk->stride = stride; @@ -1004,48 +1005,58 @@ static inline void *get_buffer_output(struct port *p, uint32_t frames, uint32_t p->io.status = SPA_STATUS_HAVE_DATA; p->io.buffer_id = b->id; } -done: - spa_list_for_each(mix, &p->mix, port_link) { - struct spa_io_buffers *mio = mix->io; - if (SPA_UNLIKELY(mio == NULL)) - continue; - pw_log_trace_fp("%p: port %p tee %d.%d get buffer %d io:%p", - c, p, p->id, mix->id, frames, mio); - *mio = p->io; - } + ptr = b->datas[0].data; + if (buf) + *buf = b; return ptr; } -static void process_tee(struct client *c, uint32_t frames) +static inline void process_empty(struct port *p, uint32_t frames) +{ + void *ptr; + + switch (p->object->port.type_id) { + case TYPE_ID_AUDIO: + ptr = get_buffer_output(p, frames, sizeof(float), NULL); + if (SPA_LIKELY(ptr != NULL)) + memcpy(ptr, p->emptyptr, frames * sizeof(float)); + break; + case TYPE_ID_MIDI: + { + struct buffer *b; + ptr = get_buffer_output(p, MAX_BUFFER_FRAMES, 1, &b); + if (SPA_LIKELY(ptr != NULL)) { + b->datas[0].chunk->size = convert_from_midi(p->emptyptr, + ptr, MAX_BUFFER_FRAMES * sizeof(float)); + } + break; + } + default: + pw_log_warn("port %p: unhandled format %d", p, p->object->port.type_id); + break; + } +} + +static void complete_process(struct client *c, uint32_t frames) { struct port *p; + struct mix *mix; + spa_list_for_each(p, &c->ports[SPA_DIRECTION_INPUT], link) { + spa_list_for_each(mix, &p->mix, port_link) { + if (SPA_LIKELY(mix->io != NULL)) + mix->io->status = SPA_STATUS_NEED_DATA; + } + } spa_list_for_each(p, &c->ports[SPA_DIRECTION_OUTPUT], link) { - void *ptr; + if (SPA_UNLIKELY(p->empty_out)) + process_empty(p, frames); - if (SPA_LIKELY(!p->empty_out)) - continue; - - switch (p->object->port.type_id) { - case TYPE_ID_AUDIO: - ptr = get_buffer_output(p, frames, sizeof(float), NULL); - if (SPA_LIKELY(ptr != NULL)) - memcpy(ptr, p->emptyptr, frames * sizeof(float)); - break; - case TYPE_ID_MIDI: - { - struct buffer *b; - ptr = get_buffer_output(p, MAX_BUFFER_FRAMES, 1, &b); - if (SPA_LIKELY(ptr != NULL)) { - b->datas[0].chunk->size = convert_from_midi(p->emptyptr, - ptr, MAX_BUFFER_FRAMES * sizeof(float)); - } - break; - } - default: - pw_log_warn("port %p: unhandled format %d", p, p->object->port.type_id); - break; + spa_list_for_each(mix, &p->mix, port_link) { + if (SPA_LIKELY(mix->io != NULL)) + *mix->io = p->io; } + p->io.status = SPA_STATUS_NEED_DATA; } } @@ -1312,7 +1323,7 @@ static inline void signal_sync(struct client *c) struct link *l; struct pw_node_activation *activation = c->activation; - process_tee(c, c->buffer_frames); + complete_process(c, c->buffer_frames); clock_gettime(CLOCK_MONOTONIC, &ts); nsec = SPA_TIMESPEC_TO_NSEC(&ts); @@ -4086,7 +4097,6 @@ static void *get_buffer_input_float(struct port *p, jack_nframes_t frames) if ((b = get_mix_buffer(mix)) == NULL) continue; - mix->io->status = SPA_STATUS_NEED_DATA; if (layer++ == 0) ptr = b->datas[0].data; else { @@ -4103,7 +4113,6 @@ static void *get_buffer_input_float(struct port *p, jack_nframes_t frames) static void *get_buffer_input_midi(struct port *p, jack_nframes_t frames) { struct mix *mix; - struct spa_io_buffers *io; void *ptr = p->emptyptr; struct spa_pod_sequence *seq[CONNECTION_NUM_FOR_PORT]; uint32_t n_seq = 0; @@ -4112,19 +4121,16 @@ static void *get_buffer_input_midi(struct port *p, jack_nframes_t frames) spa_list_for_each(mix, &p->mix, port_link) { struct spa_data *d; + struct buffer *b; void *pod; pw_log_trace_fp("%p: port %p mix %d.%d get buffer %d", p->client, p, p->id, mix->id, frames); - io = mix->io; - if (io == NULL || - io->status != SPA_STATUS_HAVE_DATA || - io->buffer_id >= mix->n_buffers) + if ((b = get_mix_buffer(mix)) == NULL) continue; - io->status = SPA_STATUS_NEED_DATA; - d = &mix->buffers[io->buffer_id].datas[0]; + d = &b->datas[0]; if ((pod = spa_pod_from_data(d->data, d->maxsize, d->chunk->offset, d->chunk->size)) == NULL) continue;