aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHanspeter Portner <dev@open-music-kontrollers.ch>2017-06-04 09:28:14 +0200
committerHanspeter Portner <dev@open-music-kontrollers.ch>2017-06-04 09:28:14 +0200
commit7b9de701df5a7a168f2ef2b790859ef2c05f904b (patch)
tree41ed86cd96cc3737f0482f870c9214dc4b89130f
parent5f1ebcef758ca2cce44278980f32fc08ce273f9b (diff)
downloadsynthpod-7b9de701df5a7a168f2ef2b790859ef2c05f904b.tar.xz
nk: prototype preset save.
-rw-r--r--VERSION2
-rw-r--r--app/synthpod_app_state.c94
-rw-r--r--app/synthpod_app_ui.c34
-rw-r--r--app/synthpod_app_worker.c22
-rw-r--r--plugins/synthpod_common_nk.c78
5 files changed, 175 insertions, 55 deletions
diff --git a/VERSION b/VERSION
index 4550b56e..e507ee6b 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.1.5001
+0.1.5003
diff --git a/app/synthpod_app_state.c b/app/synthpod_app_state.c
index c13831d6..1613dd62 100644
--- a/app/synthpod_app_state.c
+++ b/app/synthpod_app_state.c
@@ -286,57 +286,58 @@ _sp_app_state_preset_load(sp_app_t *app, mod_t *mod, const char *uri, bool async
}
int
-_sp_app_state_preset_save(sp_app_t *app, mod_t *mod, const char *target)
+_sp_app_state_preset_save(sp_app_t *app, mod_t *mod, const char *uri)
{
const LilvNode *name_node = lilv_plugin_get_name(mod->plug);
if(!name_node)
return -1;
- const char *name = lilv_node_as_string(name_node);
- char *dir = NULL;
- char *filename = NULL;
- char *bndl = NULL;
+ const char *mod_label = lilv_node_as_string(name_node);
+ char *prefix_path;
+ if(asprintf(&prefix_path, "file:///home/hp/.lv2/%s_", mod_label) == -1) //FIXME
+ prefix_path = NULL;
- // create bundle path
- asprintf(&dir, "%s/.lv2/%s_%s.preset.lv2", app->dir.home, name, target);
- if(!dir)
- return -1;
-
- // replace spaces with underscore
- for(char *c = strstr(dir, ".lv2"); *c; c++)
- if(isspace(*c))
+ if(prefix_path)
+ {
+ // replace white space with underline
+ const char *whitespace = " \t\r\n";
+ for(char *c = strpbrk(prefix_path, whitespace); c; c = strpbrk(c, whitespace))
*c = '_';
+ }
- mkpath(dir);
+ const char *bndl = !strncmp(uri, "file://", 7)
+ ? uri + 7
+ : uri;
- // create plugin state file name
- asprintf(&filename, "%s.ttl", target);
- if(!filename)
- {
- free(dir);
- return -1;
- }
-
- // create bundle path URI
- asprintf(&bndl, "%s/", dir);
- if(!bndl)
+ const char *target = prefix_path && !strncmp(uri, prefix_path, strlen(prefix_path))
+ ? uri + strlen(prefix_path)
+ : uri;
+
+ char *dest = strdup(target);
+ if(dest)
{
- free(dir);
- free(filename);
- return -1;
+ char *term = strstr(dest, ".preset.lv2");
+ if(term)
+ *term = '\0';
+
+ const char underline = '_';
+ for(char *c = strchr(dest, underline); c; c = strchr(c, underline))
+ *c = ' ';
}
-
- //printf("preset save: %s, %s, %s\n", dir, filename, bndl);
+
+ mkpath((char *)uri);
+
+ printf("preset save: <%s> as %s\n", uri, dest ? dest : target);
LilvState *const state = lilv_state_new_from_instance(mod->plug, mod->inst,
- app->driver->map, NULL, NULL, NULL, dir,
+ app->driver->map, NULL, NULL, NULL, bndl,
_state_get_value, mod, LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE,
NULL);
if(state)
{
- // actually save the state to disk
- lilv_state_set_label(state, target);
+ // set preset label
+ lilv_state_set_label(state, dest ? dest : target);
/*FIXME for lilv 0.24
const char *comment = "this is a comment";
@@ -356,33 +357,22 @@ _sp_app_state_preset_save(sp_app_t *app, mod_t *mod, const char *target)
LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE);
*/
+ // actually save the state to disk
lilv_state_save(app->world, app->driver->map, app->driver->unmap,
- state, NULL, dir, filename);
+ state, NULL, bndl, "state.ttl");
lilv_state_free(state);
// reload presets for this module
mod->presets = _preset_reload(app->world, &app->regs, mod->plug,
mod->presets, bndl);
-
-#if 0
- // signal ui to reload its presets, too
- size_t size = sizeof(transmit_module_preset_save_t)
- + lv2_atom_pad_size(strlen(bndl) + 1);
- transmit_module_preset_save_t *trans = _sp_app_to_ui_request(app, size);
- if(trans)
- {
- _sp_transmit_module_preset_save_fill(&app->regs, &app->forge, trans,
- size, mod->uid, bndl);
- _sp_app_to_ui_advance(app, size);
- }
-#endif
}
-
- // cleanup
- free(dir);
- free(filename);
- free(bndl);
+ // cleanup
+ if(prefix_path)
+ free(prefix_path);
+ if(dest)
+ free(dest);
+
return 0; // success
}
diff --git a/app/synthpod_app_ui.c b/app/synthpod_app_ui.c
index fd4237b6..5eeab854 100644
--- a/app/synthpod_app_ui.c
+++ b/app/synthpod_app_ui.c
@@ -1506,6 +1506,40 @@ _sp_app_from_ui_patch_copy(sp_app_t *app, const LV2_Atom *atom)
}
}
}
+ else if(subj && dest) // copy preset to dest
+ {
+ mod_t *mod = _mod_find_by_urn(app, subj);
+
+ if(app->block_state == BLOCKING_STATE_RUN)
+ {
+ // send request to worker thread
+ job_t *job = _sp_app_to_worker_request(app, sizeof(job_t));
+ 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, sizeof(job_t));
+ }
+ }
+ else if(app->block_state == BLOCKING_STATE_BLOCK)
+ {
+ // send request to worker thread
+ job_t *job = _sp_app_to_worker_request(app, sizeof(job_t));
+ if(job)
+ {
+ app->block_state = BLOCKING_STATE_WAIT; // wait for job
+
+ job->request = JOB_TYPE_REQUEST_PRESET_SAVE;
+ job->mod = mod;
+ job->urn = dest;
+ _sp_app_to_worker_advance(app, sizeof(job_t));
+
+ return true; // advance
+ }
+ }
+ }
return advance_ui[app->block_state];
}
diff --git a/app/synthpod_app_worker.c b/app/synthpod_app_worker.c
index 095a88b7..926b1693 100644
--- a/app/synthpod_app_worker.c
+++ b/app/synthpod_app_worker.c
@@ -178,7 +178,26 @@ sp_app_from_worker(sp_app_t *app, uint32_t len, const void *data)
assert(app->block_state == BLOCKING_STATE_WAIT);
app->block_state = BLOCKING_STATE_RUN; // release block
- //FIXME signal to UI
+ // signal to NK
+ size_t maximum;
+ LV2_Atom *answer = _sp_app_to_ui_request_atom(app);
+ if(answer)
+ {
+ LV2_Atom_Forge_Ref ref = synthpod_patcher_copy(&app->regs, &app->forge,
+ job->mod->urn, 0, job->urn);
+ if(ref)
+ {
+ _sp_app_to_ui_advance_atom(app, answer);
+ }
+ else
+ {
+ _sp_app_to_ui_overflow(app);
+ }
+ }
+ else
+ {
+ _sp_app_to_ui_overflow(app);
+ }
break;
}
@@ -329,6 +348,7 @@ sp_worker_from_app(sp_app_t *app, uint32_t len, const void *data)
{
job1->reply = JOB_TYPE_REPLY_PRESET_SAVE;
job1->mod = job->mod;
+ job1->urn = job->urn;
_sp_worker_to_app_advance(app, sizeof(job_t));
}
diff --git a/plugins/synthpod_common_nk.c b/plugins/synthpod_common_nk.c
index 29e3c5c7..88bdeb77 100644
--- a/plugins/synthpod_common_nk.c
+++ b/plugins/synthpod_common_nk.c
@@ -2288,6 +2288,47 @@ _patch_mod_preset_set(plughandle_t *handle, mod_t *mod, const LilvNode *preset)
}
}
+static void
+_patch_mod_preset_save(plughandle_t *handle)
+{
+ mod_t *mod = handle->module_selector;
+ if(!mod)
+ return;
+
+ LilvNode *name_node = lilv_plugin_get_name(mod->plug);
+ if(!name_node)
+ return;
+
+ const char *mod_label = lilv_node_as_string(name_node);
+ const char *preset_label = _textedit_const(&handle->preset_search_edit);
+
+ // create target URI
+ char *preset_path;
+ if(asprintf(&preset_path, "file:///home/hp/.lv2/%s_%s.preset.lv2", mod_label, preset_label) == -1) //FIXME
+ preset_path = NULL;
+
+ if(preset_path)
+ {
+ // replace white space with underline
+ const char *whitespace = " \t\r\n";
+ for(char *c = strpbrk(preset_path, whitespace); c; c = strpbrk(c, whitespace))
+ *c = '_';
+
+ const LV2_URID preset_urid = handle->map->map(handle->map->handle, preset_path);
+
+ if( _message_request(handle)
+ && synthpod_patcher_copy(&handle->regs, &handle->forge,
+ mod->urn, 0, preset_urid) )
+ {
+ _message_write(handle);
+ }
+
+ free(preset_path);
+ }
+
+ lilv_node_free(name_node);
+}
+
static mod_t *
_mod_find_by_subject(plughandle_t *handle, LV2_URID subj)
{
@@ -5392,7 +5433,9 @@ _expose_main_body(plughandle_t *handle, struct nk_context *ctx, float dh, float
const nk_flags args = NK_EDIT_FIELD | NK_EDIT_SIG_ENTER | NK_EDIT_AUTO_SELECT;
const nk_flags flags = nk_edit_buffer(ctx, args, &handle->preset_search_edit, nk_filter_default);
_textedit_zero_terminate(&handle->preset_search_edit);
- if( (flags & NK_EDIT_COMMITED) || (old_len != _textedit_len(&handle->preset_search_edit)) )
+ if(flags & NK_EDIT_COMMITED)
+ _patch_mod_preset_save(handle);
+ if(old_len != _textedit_len(&handle->preset_search_edit))
handle->preset_find_matches = true;
if( (flags & NK_EDIT_ACTIVE) && handle->has_control_a)
nk_textedit_select_all(&handle->preset_search_edit);
@@ -6487,6 +6530,39 @@ port_event(LV2UI_Handle instance, uint32_t port_index, uint32_t size,
}
}
}
+ else if(obj->body.otype == handle->regs.patch.copy.urid)
+ {
+ const LV2_Atom_URID *subject = NULL;
+ const LV2_Atom_URID *destination = NULL;
+
+ lv2_atom_object_get(obj,
+ handle->regs.patch.subject.urid, &subject,
+ handle->regs.patch.destination.urid, &destination,
+ 0);
+
+ const LV2_URID subj = subject && (subject->atom.type == handle->forge.URID)
+ ? subject->body
+ : 0;
+ const LV2_URID dest = destination && (destination->atom.type == handle->forge.URID)
+ ? destination->body
+ : 0;
+
+ if(subj && dest)
+ {
+ mod_t *mod = _mod_find_by_urn(handle, subj);
+ if(mod)
+ {
+ const char *bndl = handle->unmap->unmap(handle->unmap->handle, dest);
+ bndl = !strncmp(bndl, "file://", 7)
+ ? bndl + 7
+ : bndl;
+
+ // reload presets for this module
+ mod->presets = _preset_reload(handle->world, &handle->regs, mod->plug,
+ mod->presets, bndl);
+ }
+ }
+ }
}
}
}