diff options
author | Hanspeter Portner <dev@open-music-kontrollers.ch> | 2017-06-04 09:28:14 +0200 |
---|---|---|
committer | Hanspeter Portner <dev@open-music-kontrollers.ch> | 2017-06-04 09:28:14 +0200 |
commit | 7b9de701df5a7a168f2ef2b790859ef2c05f904b (patch) | |
tree | 41ed86cd96cc3737f0482f870c9214dc4b89130f | |
parent | 5f1ebcef758ca2cce44278980f32fc08ce273f9b (diff) | |
download | synthpod-7b9de701df5a7a168f2ef2b790859ef2c05f904b.tar.xz |
nk: prototype preset save.
-rw-r--r-- | VERSION | 2 | ||||
-rw-r--r-- | app/synthpod_app_state.c | 94 | ||||
-rw-r--r-- | app/synthpod_app_ui.c | 34 | ||||
-rw-r--r-- | app/synthpod_app_worker.c | 22 | ||||
-rw-r--r-- | plugins/synthpod_common_nk.c | 78 |
5 files changed, 175 insertions, 55 deletions
@@ -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); + } + } + } } } } |