module-jack: fix jack scheduling

Our sink and source callbacks are called twice, once when the graph
starts and once when it completes, make sure we don't signal the jack
graph twice or we get corrupted output.

Fixes #3255
This commit is contained in:
Wim Taymans 2023-06-19 16:37:03 +02:00
parent 3dbb865d6d
commit 7805a454df

View file

@ -193,6 +193,7 @@ struct impl {
uint32_t jack_xrun;
unsigned int do_disconnect:1;
unsigned int triggered:1;
unsigned int done:1;
unsigned int new_xrun:1;
unsigned int fix_midi:1;
@ -323,6 +324,11 @@ static void sink_process(void *d, struct spa_io_position *position)
struct impl *impl = s->impl;
uint32_t i, n_samples = position->clock.duration;
if (impl->mode & MODE_SINK && impl->triggered) {
impl->triggered = false;
return;
}
for (i = 0; i < s->n_ports; i++) {
struct port *p = s->ports[i];
float *src, *dst;
@ -342,7 +348,7 @@ static void sink_process(void *d, struct spa_io_position *position)
else
do_volume(dst, src, &s->volume, i, n_samples);
}
pw_log_trace_fp("done %u", impl->frame_time);
pw_log_trace_fp("done %u %u", impl->frame_time, n_samples);
if (impl->mode & MODE_SINK) {
impl->done = true;
jack.cycle_signal(impl->client, 0);
@ -355,6 +361,14 @@ static void source_process(void *d, struct spa_io_position *position)
struct impl *impl = s->impl;
uint32_t i, n_samples = position->clock.duration;
if (impl->mode == MODE_SOURCE && !impl->triggered) {
pw_log_trace_fp("done %u", impl->frame_time);
impl->done = true;
jack.cycle_signal(impl->client, 0);
return;
}
impl->triggered = false;
for (i = 0; i < s->n_ports; i++) {
struct port *p = s->ports[i];
float *src, *dst;
@ -373,11 +387,6 @@ static void source_process(void *d, struct spa_io_position *position)
else
do_volume(dst, src, &s->volume, i, n_samples);
}
pw_log_trace_fp("done %u", impl->frame_time);
if (impl->mode == MODE_SOURCE) {
impl->done = true;
jack.cycle_signal(impl->client, 0);
}
}
static void stream_io_changed(void *data, void *port_data, uint32_t id, void *area, uint32_t size)
@ -701,11 +710,14 @@ static void *jack_process_thread(void *arg)
}
if (impl->mode & MODE_SINK && sink_running) {
impl->done = false;
impl->triggered = true;
pw_filter_trigger_process(impl->sink.filter);
} else if (impl->mode == MODE_SOURCE && source_running) {
impl->done = false;
impl->triggered = true;
pw_filter_trigger_process(impl->source.filter);
} else {
pw_log_trace_fp("done %d", nframes);
jack.cycle_signal(impl->client, 0);
}
}