aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHanspeter Portner <dev@open-music-kontrollers.ch>2018-03-18 22:00:52 +0100
committerHanspeter Portner <dev@open-music-kontrollers.ch>2018-03-18 22:00:52 +0100
commit8f504cedbee2b73753d8f177b990faec3251338c (patch)
treea475087daca77fce5ca6bf39e392b84b72e4a5a6
parent307af11cc7df6c9284b0c77cb1669e6ec542a3ef (diff)
downloadsynthpod-8f504cedbee2b73753d8f177b990faec3251338c.tar.xz
app/nk: prototype plugin reinstantiation.
-rw-r--r--VERSION2
-rw-r--r--app/synthpod_app_mod.c46
-rw-r--r--app/synthpod_app_private.h12
-rw-r--r--app/synthpod_app_state.c27
-rw-r--r--app/synthpod_app_ui.c52
-rw-r--r--app/synthpod_app_worker.c58
-rw-r--r--include/synthpod_private.h3
-rw-r--r--plugins/synthpod_common_nk.c42
8 files changed, 232 insertions, 10 deletions
diff --git a/VERSION b/VERSION
index 364045d4..da04da05 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.1.5571
+0.1.5573
diff --git a/app/synthpod_app_mod.c b/app/synthpod_app_mod.c
index 22ca0742..ed01bd7b 100644
--- a/app/synthpod_app_mod.c
+++ b/app/synthpod_app_mod.c
@@ -226,7 +226,7 @@ _sp_app_mod_reinitialize(mod_t *mod)
// mod->features should be up-to-date
mod->inst = lilv_plugin_instantiate(mod->plug, app->driver->sample_rate, mod->features);
- mod->handle = lilv_instance_get_handle(mod->inst),
+ mod->handle = lilv_instance_get_handle(mod->inst);
//TODO should we re-get extension_data?
@@ -1116,3 +1116,47 @@ _sp_app_mod_eject(sp_app_t *app, mod_t *mod)
}
#endif
}
+
+static void
+_sp_app_mod_reinitialize_soft(mod_t *mod)
+{
+ sp_app_t *app = mod->app;
+
+ // reinitialize all modules,
+ lilv_instance_deactivate(mod->inst);
+ lilv_instance_free(mod->inst);
+
+ mod->inst = NULL;
+ mod->handle = NULL;
+
+ // mod->features should be up-to-date
+ mod->inst = lilv_plugin_instantiate(mod->plug, app->driver->sample_rate, mod->features);
+ mod->handle = lilv_instance_get_handle(mod->inst);
+
+ // refresh all connections
+ for(unsigned i=0; i<mod->num_ports - 2; i++)
+ {
+ port_t *tar = &mod->ports[i];
+
+ // set port buffer
+ lilv_instance_connect_port(mod->inst, i, tar->base);
+ }
+}
+
+void
+_sp_app_mod_reinstantiate(sp_app_t *app, mod_t *mod)
+{
+ LilvState *const state = _sp_app_state_preset_create(app, mod,
+ "file:///tmp/stash.preset.lv2");
+
+ if(state)
+ {
+ _sp_app_mod_reinitialize_soft(mod);
+
+ _sp_app_state_preset_restore(app, mod, state, false);
+
+ lilv_instance_activate(mod->inst);
+
+ lilv_state_free(state);
+ }
+}
diff --git a/app/synthpod_app_private.h b/app/synthpod_app_private.h
index 2cb03742..6efa0428 100644
--- a/app/synthpod_app_private.h
+++ b/app/synthpod_app_private.h
@@ -120,6 +120,7 @@ enum _job_type_request_t {
JOB_TYPE_REQUEST_MODULE_SUPPORTED,
JOB_TYPE_REQUEST_MODULE_ADD,
JOB_TYPE_REQUEST_MODULE_DEL,
+ JOB_TYPE_REQUEST_MODULE_REINSTANTIATE,
JOB_TYPE_REQUEST_PRESET_LOAD,
JOB_TYPE_REQUEST_PRESET_SAVE,
JOB_TYPE_REQUEST_BUNDLE_LOAD,
@@ -131,6 +132,7 @@ enum _job_type_reply_t {
JOB_TYPE_REPLY_MODULE_SUPPORTED,
JOB_TYPE_REPLY_MODULE_ADD,
JOB_TYPE_REPLY_MODULE_DEL,
+ JOB_TYPE_REPLY_MODULE_REINSTANTIATE,
JOB_TYPE_REPLY_PRESET_LOAD,
JOB_TYPE_REPLY_PRESET_SAVE,
JOB_TYPE_REPLY_BUNDLE_LOAD,
@@ -627,9 +629,16 @@ _sp_app_populate(sp_app_t *app);
/*
* State
*/
+void
+_sp_app_state_preset_restore(sp_app_t *app, mod_t *mod, LilvState *const state,
+ bool async);
+
int
_sp_app_state_preset_load(sp_app_t *app, mod_t *mod, const char *uri, bool async);
+LilvState *
+_sp_app_state_preset_create(sp_app_t *app, mod_t *mod, const char *bndl);
+
int
_sp_app_state_preset_save(sp_app_t *app, mod_t *mod, const char *target);
@@ -663,6 +672,9 @@ _sp_app_mod_worker_work_sync(mod_t *mod, size_t size, const void *payload);
void
_sp_app_mod_queue_draw(mod_t *mod);
+void
+_sp_app_mod_reinstantiate(sp_app_t *app, mod_t *mod);
+
/*
* Port
*/
diff --git a/app/synthpod_app_state.c b/app/synthpod_app_state.c
index b1813bd9..7d10167d 100644
--- a/app/synthpod_app_state.c
+++ b/app/synthpod_app_state.c
@@ -284,6 +284,14 @@ fail:
return NULL;
}
+void
+_sp_app_state_preset_restore(sp_app_t *app, mod_t *mod, LilvState *const state,
+ bool async)
+{
+ lilv_state_restore(state, mod->inst, _state_set_value, mod,
+ LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE, _preset_features(mod, async));
+}
+
int
_sp_app_state_preset_load(sp_app_t *app, mod_t *mod, const char *uri, bool async)
{
@@ -314,14 +322,24 @@ _sp_app_state_preset_load(sp_app_t *app, mod_t *mod, const char *uri, bool async
return -1;
}
- lilv_state_restore(state, mod->inst, _state_set_value, mod,
- LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE, _preset_features(mod, async));
+ _sp_app_state_preset_restore(app, mod, state, async);
lilv_state_free(state);
return 0; // success
}
+LilvState *
+_sp_app_state_preset_create(sp_app_t *app, mod_t *mod, const char *bndl)
+{
+ LilvState *const state = lilv_state_new_from_instance(mod->plug, mod->inst,
+ app->driver->map, NULL, NULL, NULL, bndl,
+ _state_get_value, mod, LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE,
+ NULL);
+
+ return state;
+}
+
int
_sp_app_state_preset_save(sp_app_t *app, mod_t *mod, const char *uri)
{
@@ -370,10 +388,7 @@ _sp_app_state_preset_save(sp_app_t *app, mod_t *mod, const char *uri)
sp_app_log_note(app, "%s: preset save: <%s> as %s\n",
__func__, uri, dest ? dest : target);
- LilvState *const state = lilv_state_new_from_instance(mod->plug, mod->inst,
- app->driver->map, NULL, NULL, NULL, bndl,
- _state_get_value, mod, LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE,
- NULL);
+ LilvState *const state = _sp_app_state_preset_create(app, mod, bndl);
if(state)
{
diff --git a/app/synthpod_app_ui.c b/app/synthpod_app_ui.c
index a40df4ea..372a52f0 100644
--- a/app/synthpod_app_ui.c
+++ b/app/synthpod_app_ui.c
@@ -842,6 +842,58 @@ _sp_app_from_ui_patch_set(sp_app_t *app, const LV2_Atom *atom)
_sp_app_mod_queue_draw(mod); // trigger update
}
}
+ else if( (prop == app->regs.synthpod.module_reinstantiate.urid)
+ && (value->type == app->forge.Bool) )
+ {
+ if(app->block_state == BLOCKING_STATE_RUN)
+ {
+ const bool needs_ramping = _mod_needs_ramping(mod, RAMP_STATE_DOWN_DRAIN, true);
+ app->silence_state = !needs_ramping
+ ? SILENCING_STATE_RUN
+ : SILENCING_STATE_BLOCK;
+
+ // send request to worker thread
+ size_t size = sizeof(job_t);
+ job_t *job = _sp_app_to_worker_request(app, size);
+ if(job)
+ {
+ app->block_state = BLOCKING_STATE_DRAIN; // wait for drain
+
+ job->request = JOB_TYPE_REQUEST_DRAIN;
+ job->status = 0;
+ _sp_app_to_worker_advance(app, size);
+ }
+ else
+ {
+ sp_app_log_trace(app, "%s: buffer request failed\n", __func__);
+ }
+ }
+ else if(app->block_state == BLOCKING_STATE_BLOCK)
+ {
+ if(app->silence_state == SILENCING_STATE_BLOCK)
+ return false; // not fully silenced yet, wait
+
+ // send request to worker thread
+ const LV2_URID pset_urn = ((const LV2_Atom_URID *)value)->body;
+ size_t size = sizeof(job_t);
+ job_t *job = _sp_app_to_worker_request(app, size);
+ if(job)
+ {
+ app->block_state = BLOCKING_STATE_WAIT; // wait for job
+ mod->bypassed = mod->needs_bypassing;
+
+ job->request = JOB_TYPE_REQUEST_MODULE_REINSTANTIATE;
+ job->mod = mod;
+ _sp_app_to_worker_advance(app, size);
+
+ return true; // advance
+ }
+ else
+ {
+ sp_app_log_trace(app, "%s: buffer request failed\n", __func__);
+ }
+ }
+ }
}
//TODO handle more properties
diff --git a/app/synthpod_app_worker.c b/app/synthpod_app_worker.c
index e19b146e..e53952ce 100644
--- a/app/synthpod_app_worker.c
+++ b/app/synthpod_app_worker.c
@@ -133,6 +133,38 @@ sp_app_from_worker(sp_app_t *app, uint32_t len, const void *data)
break;
}
+ case JOB_TYPE_REPLY_MODULE_REINSTANTIATE:
+ {
+ mod_t *mod = job->mod;
+
+ assert(app->block_state == BLOCKING_STATE_WAIT);
+ app->block_state = BLOCKING_STATE_RUN; // release block
+ mod->bypassed = false;
+
+ if(app->silence_state == SILENCING_STATE_WAIT)
+ {
+ app->silence_state = SILENCING_STATE_RUN;
+
+ // ramping
+ for(unsigned p1=0; p1<mod->num_ports; p1++)
+ {
+ port_t *port = &mod->ports[p1];
+
+ // desilence sinks
+ for(unsigned m=0; m<app->num_mods; m++)
+ {
+ for(unsigned p2=0; p2<app->mods[m]->num_ports; p2++)
+ {
+ _sp_app_port_desilence(app, port, &app->mods[m]->ports[p2]);
+ }
+ }
+ }
+ }
+
+ //FIXME signal to ui
+
+ break;
+ }
case JOB_TYPE_REPLY_PRESET_LOAD:
{
//printf("app: preset loaded\n");
@@ -332,11 +364,33 @@ sp_worker_from_app(sp_app_t *app, uint32_t len, const void *data)
break;
}
+ case JOB_TYPE_REQUEST_MODULE_REINSTANTIATE:
+ {
+ mod_t *mod = job->mod;
+ if(!mod)
+ break; //TODO report
+
+ _sp_app_mod_reinstantiate(app, mod);
+
+ // signal to app
+ job_t *job1 = _sp_worker_to_app_request(app, sizeof(job_t));
+ if(job1)
+ {
+ job1->reply = JOB_TYPE_REPLY_MODULE_REINSTANTIATE;
+ job1->mod = job->mod;
+ _sp_worker_to_app_advance(app, sizeof(job_t));
+ }
+ else
+ {
+ sp_app_log_error(app, "%s: buffer request failed\n", __func__);
+ }
+
+ break;
+ }
case JOB_TYPE_REQUEST_PRESET_LOAD:
{
const char *uri = app->driver->unmap->unmap(app->driver->unmap->handle, job->urn);
- int status = _sp_app_state_preset_load(app, job->mod, uri, true);
- (void)status; //FIXME check this
+ int status = _sp_app_state_preset_load(app, job->mod, uri, true); (void)status; //FIXME check this
// signal to app
job_t *job1 = _sp_worker_to_app_request(app, sizeof(job_t));
diff --git a/include/synthpod_private.h b/include/synthpod_private.h
index 9e727f79..d7a432f1 100644
--- a/include/synthpod_private.h
+++ b/include/synthpod_private.h
@@ -356,6 +356,7 @@ struct _reg_t {
reg_item_t module_position_x;
reg_item_t module_position_y;
reg_item_t module_alias;
+ reg_item_t module_reinstantiate;
reg_item_t node_position_x;
reg_item_t node_position_y;
reg_item_t port_refresh;
@@ -643,6 +644,7 @@ sp_regs_init(reg_t *regs, LilvWorld *world, LV2_URID_Map *map)
_register(&regs->synthpod.module_position_x, world, map, SYNTHPOD_PREFIX"modulePositionX");
_register(&regs->synthpod.module_position_y, world, map, SYNTHPOD_PREFIX"modulePositionY");
_register(&regs->synthpod.module_alias, world, map, SYNTHPOD_PREFIX"moduleAlias");
+ _register(&regs->synthpod.module_reinstantiate, world, map, SYNTHPOD_PREFIX"moduleReinstantiate");
_register(&regs->synthpod.node_position_x, world, map, SYNTHPOD_PREFIX"nodePositionX");
_register(&regs->synthpod.node_position_y, world, map, SYNTHPOD_PREFIX"nodePositionY");
_register(&regs->synthpod.port_refresh, world, map, SYNTHPOD_PREFIX"portRefresh");
@@ -895,6 +897,7 @@ sp_regs_deinit(reg_t *regs)
_unregister(&regs->synthpod.module_position_x);
_unregister(&regs->synthpod.module_position_y);
_unregister(&regs->synthpod.module_alias);
+ _unregister(&regs->synthpod.module_reinstantiate);
_unregister(&regs->synthpod.node_position_x);
_unregister(&regs->synthpod.node_position_y);
_unregister(&regs->synthpod.port_refresh);
diff --git a/plugins/synthpod_common_nk.c b/plugins/synthpod_common_nk.c
index be221fbe..da78404c 100644
--- a/plugins/synthpod_common_nk.c
+++ b/plugins/synthpod_common_nk.c
@@ -2965,6 +2965,20 @@ _patch_mod_preset_set(plughandle_t *handle, mod_t *mod, const LilvNode *preset)
}
static void
+_patch_mod_reinstantiate_set(plughandle_t *handle, mod_t *mod, int32_t state)
+{
+ DBG;
+
+ if( _message_request(handle)
+ && synthpod_patcher_set(&handle->regs, &handle->forge,
+ mod->urn, 0, handle->regs.synthpod.module_reinstantiate.urid,
+ sizeof(int32_t), handle->forge.Bool, &state) )
+ {
+ _message_write(handle);
+ }
+}
+
+static void
_patch_mod_preset_save(plughandle_t *handle)
{
DBG;
@@ -5790,6 +5804,30 @@ _remove_selected_nodes(plughandle_t *handle)
}
static inline void
+_reinstantiate_selected_nodes(plughandle_t *handle)
+{
+ DBG;
+ // reinstantiate all modules
+ HASH_FOREACH(&handle->mods, mod_itr)
+ {
+ mod_t *mod = *mod_itr;
+
+ if(mod->selected)
+ {
+ const LilvPlugin *plug = mod->plug;
+ const LilvNode *uri_node = lilv_plugin_get_uri(plug);
+ const char *mod_uri = lilv_node_as_string(uri_node);
+
+ if( strcmp(mod_uri, SYNTHPOD_PREFIX"source")
+ && strcmp(mod_uri, SYNTHPOD_PREFIX"sink") )
+ {
+ _patch_mod_reinstantiate_set(handle, mod, 1);
+ }
+ }
+ }
+}
+
+static inline void
_show_selected_nodes(plughandle_t *handle)
{
DBG;
@@ -6670,6 +6708,10 @@ _expose_main_body(plughandle_t *handle, struct nk_context *ctx, float dh, float
{
_remove_selected_nodes(handle);
} break;
+ case 'i':
+ {
+ _reinstantiate_selected_nodes(handle);
+ } break;
}
in->keyboard.text_len = 0; // consume character if mouse over canvas