diff --git a/src/modules/module-filter-chain.c b/src/modules/module-filter-chain.c index 23e7dc4ac..3bc1ef7de 100644 --- a/src/modules/module-filter-chain.c +++ b/src/modules/module-filter-chain.c @@ -1041,6 +1041,7 @@ struct impl { struct spa_hook graph_listener; uint32_t n_inputs; uint32_t n_outputs; + bool graph_active; struct spa_latency_info latency[2]; struct spa_process_latency_info process_latency; @@ -1131,7 +1132,8 @@ static void playback_process(void *d) pw_log_trace_fp("%p: stride:%d size:%d requested:%"PRIu64" (%"PRIu64")", impl, stride, data_size, out->requested, out->requested * stride); - spa_filter_graph_process(impl->graph, cin, cout, data_size / sizeof(float)); + if (impl->graph_active) + spa_filter_graph_process(impl->graph, cin, cout, data_size / sizeof(float)); done: if (in != NULL) @@ -1140,6 +1142,62 @@ done: pw_stream_queue_buffer(impl->playback, out); } +static int activate_graph(struct impl *impl) +{ + char rate[64]; + int res; + + if (impl->graph_active) + return 0; + + snprintf(rate, sizeof(rate), "%lu", impl->rate); + res = spa_filter_graph_activate(impl->graph, &SPA_DICT_ITEMS( + SPA_DICT_ITEM(SPA_KEY_AUDIO_RATE, rate))); + + if (res >= 0) { + struct pw_loop *data_loop = pw_stream_get_data_loop(impl->playback); + pw_loop_lock(data_loop); + impl->graph_active = true; + pw_loop_unlock(data_loop); + } + return res; +} + +static int deactivate_graph(struct impl *impl) +{ + struct pw_loop *data_loop; + + if (!impl->graph_active) + return 0; + + data_loop = pw_stream_get_data_loop(impl->playback); + + pw_loop_lock(data_loop); + impl->graph_active = false; + pw_loop_unlock(data_loop); + + return spa_filter_graph_deactivate(impl->graph); +} + +static int reset_graph(struct impl *impl) +{ + struct pw_loop *data_loop = pw_stream_get_data_loop(impl->playback); + int res; + bool old_active = impl->graph_active; + + pw_loop_lock(data_loop); + impl->graph_active = false; + pw_loop_unlock(data_loop); + + res = spa_filter_graph_reset(impl->graph); + + pw_loop_lock(data_loop); + impl->graph_active = old_active; + pw_loop_unlock(data_loop); + + return res; +} + static void update_latencies(struct impl *impl) { struct spa_latency_info latency; @@ -1249,7 +1307,6 @@ static void io_changed(void *data, uint32_t id, void *area, uint32_t size) static void param_changed(struct impl *impl, uint32_t id, const struct spa_pod *param, enum spa_direction direction, struct pw_stream *stream, struct pw_stream *other) { - struct spa_filter_graph *graph = impl->graph; int res; switch (id) { @@ -1260,7 +1317,7 @@ static void param_changed(struct impl *impl, uint32_t id, const struct spa_pod * if (param == NULL) { pw_log_info("module %p: filter deactivate", impl); if (direction == SPA_DIRECTION_INPUT) - spa_filter_graph_deactivate(graph); + deactivate_graph(impl); impl->rate = 0; } else { if ((res = spa_format_audio_raw_parse(param, &info)) < 0) @@ -1309,13 +1366,12 @@ static void playback_state_changed(void *data, enum pw_stream_state old, enum pw_stream_state state, const char *error) { struct impl *impl = data; - struct spa_filter_graph *graph = impl->graph; int res; switch (state) { case PW_STREAM_STATE_PAUSED: pw_stream_flush(impl->playback, false); - spa_filter_graph_reset(graph); + reset_graph(impl); break; case PW_STREAM_STATE_UNCONNECTED: pw_log_info("module %p: unconnected", impl); @@ -1335,15 +1391,11 @@ static void playback_state_changed(void *data, enum pw_stream_state old, goto error; } if (impl->rate != target) { - char rate[64]; impl->rate = target; - snprintf(rate, sizeof(rate), "%lu", impl->rate); - spa_filter_graph_deactivate(graph); - if ((res = spa_filter_graph_activate(graph, - &SPA_DICT_ITEMS( - SPA_DICT_ITEM(SPA_KEY_AUDIO_RATE, rate)))) < 0) - goto error; + deactivate_graph(impl); } + if ((res = activate_graph(impl)) < 0) + goto error; break; } default: