From 010f52e1a7a35b4fc9af82f77058a307152b7751 Mon Sep 17 00:00:00 2001 From: falkTX Date: Thu, 30 Apr 2026 12:17:09 +0200 Subject: [PATCH 1/2] Make lv2 deactivate optional, WIP stub Signed-off-by: falkTX --- src/effects.c | 80 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 61 insertions(+), 19 deletions(-) diff --git a/src/effects.c b/src/effects.c index 2aadb75..ee69ad2 100644 --- a/src/effects.c +++ b/src/effects.c @@ -459,7 +459,8 @@ typedef struct EFFECT_T { jack_ringbuffer_t *events_out_buffer; char *events_in_buffer_helper; - bool activated; + bool jack_activated; + bool lv2_activated; // previous transport state bool transport_rolling; @@ -1147,11 +1148,13 @@ static int BufferSize(jack_nframes_t nframes, void* data) options[4].type = 0; options[4].value = NULL; - lilv_instance_deactivate(effect->lilv_instance); + if (effect->lv2_activated) + lilv_instance_deactivate(effect->lilv_instance); effect->options_interface->set(effect->lilv_instance->lv2_handle, options); - lilv_instance_activate(effect->lilv_instance); + if (effect->lv2_activated) + lilv_instance_activate(effect->lilv_instance); } } #ifdef HAVE_HYLIA @@ -5162,7 +5165,8 @@ int effects_add(const char *uri, int instance, int activate) /* Init the struct */ mod_memset(effect, 0, sizeof(effect_t)); effect->instance = instance; - effect->activated = activate; + effect->jack_activated = activate; + effect->lv2_activated = true; /* Init the pointers */ plugin_uri = NULL; @@ -6470,7 +6474,9 @@ static void effects_remove_inner_loop(int effect_id) if (effect->lilv_instance) { - lilv_instance_deactivate(effect->lilv_instance); + if (effect->lv2_activated) + lilv_instance_deactivate(effect->lilv_instance); + lilv_instance_free(effect->lilv_instance); } @@ -6662,7 +6668,7 @@ int effects_remove_multi(int num_effects, int *effects) if (effect->jack_client == NULL) continue; - if (effect->activated) + if (effect->jack_activated) { if (zix_thread_create(&threads[num_threads], sizeof(void*), effects_deactivate_thread, effect) == 0) ++num_threads; @@ -6724,9 +6730,15 @@ int effects_activate(int effect_id, int value) if (value) { - if (! effect->activated) + if (! effect->lv2_activated) { - effect->activated = true; + effect->lv2_activated = true; + lilv_instance_activate(effect->lilv_instance); + } + + if (! effect->jack_activated) + { + effect->jack_activated = true; if (jack_activate(effect->jack_client) != 0) { @@ -6737,9 +6749,9 @@ int effects_activate(int effect_id, int value) } else { - if (effect->activated) + if (effect->jack_activated) { - effect->activated = false; + effect->jack_activated = false; if (jack_deactivate(effect->jack_client) != 0) { @@ -6747,6 +6759,13 @@ int effects_activate(int effect_id, int value) return ERR_JACK_CLIENT_DEACTIVATION; } } + + // TODO only deactivate LV2 following some plugin hint + if (effect->lv2_activated) + { + effect->lv2_activated = false; + lilv_instance_deactivate(effect->lilv_instance); + } } return SUCCESS; @@ -6756,7 +6775,13 @@ static void* effects_activate_thread(void* arg) { effect_t *effect = arg; - effect->activated = true; + if (! effect->lv2_activated) + { + effect->lv2_activated = true; + lilv_instance_activate(effect->lilv_instance); + } + + effect->jack_activated = true; if (jack_activate(effect->jack_client) != 0) fprintf(stderr, "can't activate jack_client\n"); @@ -6771,7 +6796,14 @@ static void* effects_deactivate_thread(void* arg) if (jack_deactivate(effect->jack_client) != 0) fprintf(stderr, "can't deactivate jack_client\n"); - effect->activated = false; + // TODO only deactivate LV2 following some plugin hint + if (effect->lv2_activated) + { + effect->lv2_activated = false; + lilv_instance_deactivate(effect->lilv_instance); + } + + effect->jack_activated = false; return NULL; } @@ -6804,7 +6836,7 @@ int effects_activate_multi(int value, int num_effects, int *effects) if (value) { - if (! effect->activated) + if (! effect->jack_activated) { if (zix_thread_create(&threads[num_threads], sizeof(void*), effects_activate_thread, effect) == 0) ++num_threads; @@ -6814,7 +6846,7 @@ int effects_activate_multi(int value, int num_effects, int *effects) } else { - if (effect->activated) + if (effect->jack_activated) { if (zix_thread_create(&threads[num_threads], sizeof(void*), effects_deactivate_thread, effect) == 0) ++num_threads; @@ -7107,7 +7139,7 @@ int effects_flush_parameters_multi(int reset, int param_count, const flushed_par { effect = &(g_effects[effect_id]); - if (! effect->activated) + if (! effect->lv2_activated) { fprintf(stderr, "multi-param-flush attempted on non-activated plugin #%d\n", effect->instance); continue; @@ -7195,9 +7227,14 @@ int effects_pre_run(int effect_id, int reset, int param_count, const flushed_par effect_t *effect = &(g_effects[effect_id]); - if (effect->activated && ((effect->hints & HINT_IS_LIVE) != 0 || g_processing_enabled)) + if (effect->jack_activated && ((effect->hints & HINT_IS_LIVE) != 0 || g_processing_enabled)) { - fprintf(stderr, "pre-run attempted on activated plugin #%d\n", effect_id); + fprintf(stderr, "pre-run attempted on jack-activated instance #%d\n", effect_id); + return ERR_INVALID_OPERATION; + } + if (! effect->lv2_activated) + { + fprintf(stderr, "pre-run attempted on non lv2-activated instance #%d\n", effect_id); return ERR_INVALID_OPERATION; } @@ -7244,9 +7281,14 @@ int effects_pre_run_multi(int reset, int param_count, const flushed_param_t *par { effect = &(g_effects[effect_id]); - if (effect->activated && ((effect->hints & HINT_IS_LIVE) != 0 || g_processing_enabled)) + if (effect->jack_activated && ((effect->hints & HINT_IS_LIVE) != 0 || g_processing_enabled)) + { + fprintf(stderr, "multi-pre-run attempted on jack-activated instance #%d\n", effect->instance); + continue; + } + if (! effect->lv2_activated) { - fprintf(stderr, "multi-pre-run attempted on activated plugin #%d\n", effect->instance); + fprintf(stderr, "multi-pre-run attempted on non lv2-activated instance #%d\n", effect->instance); continue; } From 2b8048a3daceac29aaf3dd78459647116b12ca7c Mon Sep 17 00:00:00 2001 From: falkTX Date: Thu, 30 Apr 2026 15:26:05 +0200 Subject: [PATCH 2/2] read no-prerun feature from plugin Signed-off-by: falkTX --- src/effects.c | 64 +++++++++++++++++++++++++++++---------------------- 1 file changed, 37 insertions(+), 27 deletions(-) diff --git a/src/effects.c b/src/effects.c index ee69ad2..55c2d7e 100644 --- a/src/effects.c +++ b/src/effects.c @@ -263,6 +263,7 @@ enum PluginHints { HINT_HAS_STATE = 1 << 4, HINT_STATE_UNSAFE = 1 << 5, // state restore needs mutex protection HINT_IS_LIVE = 1 << 6, // needs to be always running, cannot have processing disabled + HINT_NO_PRE_RUN = 1 << 7, // do not keep plugin active for pre-run }; enum TransportSyncMode { @@ -521,6 +522,7 @@ typedef struct LILV_NODES_T { LilvNode *mod_default_custom; LilvNode *mod_maximum; LilvNode *mod_minimum; + LilvNode *noPreRun; LilvNode *options_interface; LilvNode *output; LilvNode *patch_readable; @@ -4721,6 +4723,7 @@ int effects_init(void* client) #endif g_lilv_nodes.mod_maximum = lilv_new_uri(g_lv2_data, LILV_NS_MOD "maximum"); g_lilv_nodes.mod_minimum = lilv_new_uri(g_lv2_data, LILV_NS_MOD "minimum"); + g_lilv_nodes.noPreRun = lilv_new_uri(g_lv2_data, "http://www.darkglass.com/lv2/ns#noPreRun"); g_lilv_nodes.options_interface = lilv_new_uri(g_lv2_data, LV2_OPTIONS__interface); g_lilv_nodes.output = lilv_new_uri(g_lv2_data, LILV_URI_OUTPUT_PORT); g_lilv_nodes.patch_writable = lilv_new_uri(g_lv2_data, LV2_PATCH__writable); @@ -5071,6 +5074,7 @@ int effects_finish(int close_client) lilv_node_free(g_lilv_nodes.mod_default_custom); lilv_node_free(g_lilv_nodes.mod_maximum); lilv_node_free(g_lilv_nodes.mod_minimum); + lilv_node_free(g_lilv_nodes.noPreRun); lilv_node_free(g_lilv_nodes.output); lilv_node_free(g_lilv_nodes.patch_readable); lilv_node_free(g_lilv_nodes.patch_writable); @@ -5258,6 +5262,9 @@ int effects_add(const char *uri, int instance, int activate) if (lilv_plugin_has_feature(effect->lilv_plugin, g_lilv_nodes.is_live)) effect->hints |= HINT_IS_LIVE; + if (lilv_plugin_has_feature(effect->lilv_plugin, g_lilv_nodes.noPreRun)) + effect->hints |= HINT_NO_PRE_RUN; + /* Query plugin extensions/interfaces */ if (lilv_plugin_has_extension_data(effect->lilv_plugin, g_lilv_nodes.worker_interface)) { @@ -6760,8 +6767,7 @@ int effects_activate(int effect_id, int value) } } - // TODO only deactivate LV2 following some plugin hint - if (effect->lv2_activated) + if (effect->lv2_activated && ((effect->hints & HINT_NO_PRE_RUN) != 0)) { effect->lv2_activated = false; lilv_instance_deactivate(effect->lilv_instance); @@ -6796,8 +6802,7 @@ static void* effects_deactivate_thread(void* arg) if (jack_deactivate(effect->jack_client) != 0) fprintf(stderr, "can't deactivate jack_client\n"); - // TODO only deactivate LV2 following some plugin hint - if (effect->lv2_activated) + if (effect->lv2_activated && ((effect->hints & HINT_NO_PRE_RUN) != 0)) { effect->lv2_activated = false; lilv_instance_deactivate(effect->lilv_instance); @@ -7226,18 +7231,6 @@ int effects_pre_run(int effect_id, int reset, int param_count, const flushed_par return ERR_INSTANCE_NON_EXISTS; effect_t *effect = &(g_effects[effect_id]); - - if (effect->jack_activated && ((effect->hints & HINT_IS_LIVE) != 0 || g_processing_enabled)) - { - fprintf(stderr, "pre-run attempted on jack-activated instance #%d\n", effect_id); - return ERR_INVALID_OPERATION; - } - if (! effect->lv2_activated) - { - fprintf(stderr, "pre-run attempted on non lv2-activated instance #%d\n", effect_id); - return ERR_INVALID_OPERATION; - } - port_t *port; for (int i = 0; i < param_count; i++) @@ -7258,6 +7251,20 @@ int effects_pre_run(int effect_id, int reset, int param_count, const flushed_par port->prev_value = *(port->buffer) = reset; } + if ((effect->hints & HINT_NO_PRE_RUN) != 0) + return SUCCESS; + + if (effect->jack_activated && ((effect->hints & HINT_IS_LIVE) != 0 || g_processing_enabled)) + { + fprintf(stderr, "pre-run attempted on jack-activated instance #%d\n", effect_id); + return ERR_INVALID_OPERATION; + } + if (! effect->lv2_activated) + { + fprintf(stderr, "pre-run attempted on non lv2-activated instance #%d\n", effect_id); + return ERR_INVALID_OPERATION; + } + PreRunPlugin(effect); return SUCCESS; @@ -7281,17 +7288,6 @@ int effects_pre_run_multi(int reset, int param_count, const flushed_param_t *par { effect = &(g_effects[effect_id]); - if (effect->jack_activated && ((effect->hints & HINT_IS_LIVE) != 0 || g_processing_enabled)) - { - fprintf(stderr, "multi-pre-run attempted on jack-activated instance #%d\n", effect->instance); - continue; - } - if (! effect->lv2_activated) - { - fprintf(stderr, "multi-pre-run attempted on non lv2-activated instance #%d\n", effect->instance); - continue; - } - for (int j = 0; j < param_count; j++) { port = FindEffectInputPortBySymbol(effect, params[j].symbol); @@ -7310,6 +7306,20 @@ int effects_pre_run_multi(int reset, int param_count, const flushed_param_t *par } } + if (effect->jack_activated && ((effect->hints & HINT_IS_LIVE) != 0 || g_processing_enabled)) + { + fprintf(stderr, "multi-pre-run attempted on jack-activated instance #%d\n", effect->instance); + continue; + } + if (! effect->lv2_activated) + { + fprintf(stderr, "multi-pre-run attempted on non lv2-activated instance #%d\n", effect->instance); + continue; + } + + if ((effect->hints & HINT_NO_PRE_RUN) != 0) + continue; + PreRunPlugin(effect); } }