From fbc364e68e284e24a39e56062d752f9ebe6734b3 Mon Sep 17 00:00:00 2001 From: Krzysztof Foltman Date: Sun, 19 Sep 2010 23:14:40 +0100 Subject: [PATCH] Add a crude incomplete implementation of persist extension support. (cherry picked from commit 3ec11c04799fc08fd408c4ef2350df65f88ccfde) --- plugins/ladspa_effect/calf/src/calf/giface.h | 10 ++ plugins/ladspa_effect/calf/src/calf/lv2wrap.h | 96 ++++++++++++++++--- plugins/ladspa_effect/calf/src/plugin.cpp | 3 + src/calf/lv2_persist.h | 18 ++-- 4 files changed, 107 insertions(+), 20 deletions(-) diff --git a/plugins/ladspa_effect/calf/src/calf/giface.h b/plugins/ladspa_effect/calf/src/calf/giface.h index 08954c695..752519753 100644 --- a/plugins/ladspa_effect/calf/src/calf/giface.h +++ b/plugins/ladspa_effect/calf/src/calf/giface.h @@ -28,6 +28,8 @@ #include #include +// #define USE_PERSIST_EXTENSION 1 + namespace osctl { struct osc_client; } @@ -299,6 +301,8 @@ struct plugin_metadata_iface virtual const char *get_label() const = 0; /// @return total number of parameters virtual int get_param_count() const = 0; + /// @return total number of parameters that aren't configure variables + virtual int get_nonstring_param_count() const = 0; /// Return custom XML virtual const char *get_gui_xml() const = 0; /// @return number of audio inputs @@ -633,6 +637,12 @@ public: ports.push_back(i); } } + int get_nonstring_param_count() const { + int i = Metadata::param_count; + while(i > 0 && (param_props[i - 1].flags & PF_TYPEMASK) == PF_STRING) + i--; + return i; + } }; #define CALF_PORT_NAMES(name) template<> const char *::plugin_metadata::port_names[] diff --git a/plugins/ladspa_effect/calf/src/calf/lv2wrap.h b/plugins/ladspa_effect/calf/src/calf/lv2wrap.h index 6a9bc40d0..d38b8eaf6 100644 --- a/plugins/ladspa_effect/calf/src/calf/lv2wrap.h +++ b/plugins/ladspa_effect/calf/src/calf/lv2wrap.h @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -52,6 +53,7 @@ struct lv2_instance: public plugin_ctl_iface, public progress_report_iface LV2_Progress *progress_report_feature; float **ins, **outs, **params; int out_count; + int real_param_count; lv2_instance(audio_module_iface *_module) { module = _module; @@ -59,6 +61,11 @@ struct lv2_instance: public plugin_ctl_iface, public progress_report_iface metadata = module->get_metadata_iface(); metadata->get_message_context_parameters(message_params); out_count = metadata->get_output_count(); +#if USE_PERSIST_EXTENSION + real_param_count = metadata->get_nonstring_param_count(); +#else + real_param_count = metadata->get_param_count(); +#endif uri_map = NULL; midi_data = NULL; @@ -107,6 +114,27 @@ struct lv2_instance: public plugin_ctl_iface, public progress_report_iface } return module->message_run(valid_inputs, output_ports); } +#if USE_PERSIST_EXTENSION + void impl_restore(LV2_Persist_Retrieve_Function retrieve, void *callback_data) + { + for (unsigned int i = 0; i < message_params.size(); i++) + { + int pn = message_params[i]; + const parameter_properties &pp = *metadata->get_param_props(pn); + if ((pp.flags & PF_TYPEMASK) == PF_STRING) { + size_t len = 0; + const void *ptr = (*retrieve)(callback_data, pp.short_name, &len); + if (ptr) + { + printf("Calling configure on %s\n", pp.short_name); + configure(pp.short_name, std::string((const char *)ptr, len).c_str()); + } + else + configure(pp.short_name, pp.choices[0]); + } + } + } +#endif char *configure(const char *key, const char *value) { // disambiguation - the plugin_ctl_iface version is just a stub, so don't use it return module->configure(key, value); @@ -150,14 +178,14 @@ struct lv2_instance: public plugin_ctl_iface, public progress_report_iface virtual float get_param_value(int param_no) { // XXXKF hack - if (param_no >= metadata->get_param_count()) + if (param_no >= real_param_count) return 0; return (*params)[param_no]; } virtual void set_param_value(int param_no, float value) { // XXXKF hack - if (param_no >= metadata->get_param_count()) + if (param_no >= real_param_count) return; *params[param_no] = value; } @@ -177,6 +205,7 @@ struct lv2_wrapper static LV2_Descriptor descriptor; static LV2_Calf_Descriptor calf_descriptor; static LV2MessageContext message_context; + static LV2_Persist persist; std::string uri; lv2_wrapper() @@ -191,17 +220,26 @@ struct lv2_wrapper descriptor.deactivate = cb_deactivate; descriptor.cleanup = cb_cleanup; descriptor.extension_data = cb_ext_data; +#if USE_PERSIST_EXTENSION + persist.save = cb_persist_save; + persist.restore = cb_persist_restore; +#endif calf_descriptor.get_pci = cb_get_pci; message_context.message_connect_port = cb_connect; message_context.message_run = cb_message_run; } - static void cb_connect(LV2_Handle Instance, uint32_t port, void *DataLocation) { + static void cb_connect(LV2_Handle Instance, uint32_t port, void *DataLocation) + { instance *const mod = (instance *)Instance; const plugin_metadata_iface *md = mod->metadata; unsigned long ins = md->get_input_count(); unsigned long outs = md->get_output_count(); +#if USE_PERSIST_EXTENSION + unsigned long params = md->get_nonstring_param_count(); +#else unsigned long params = md->get_param_count(); +#endif if (port < ins) mod->ins[port] = (float *)DataLocation; else if (port < ins + outs) @@ -215,12 +253,14 @@ struct lv2_wrapper } } - static void cb_activate(LV2_Handle Instance) { + static void cb_activate(LV2_Handle Instance) + { instance *const mod = (instance *)Instance; mod->set_srate = true; } - static void cb_deactivate(LV2_Handle Instance) { + static void cb_deactivate(LV2_Handle Instance) + { instance *const mod = (instance *)Instance; mod->module->deactivate(); } @@ -259,11 +299,13 @@ struct lv2_wrapper return static_cast(Instance); } - static uint32_t cb_message_run(LV2_Handle Instance, const void *valid_inputs, void *outputs_written) { + static uint32_t cb_message_run(LV2_Handle Instance, const void *valid_inputs, void *outputs_written) + { instance *mod = (instance *)Instance; return mod->impl_message_run(valid_inputs, outputs_written); } - static void cb_run(LV2_Handle Instance, uint32_t SampleCount) { + static void cb_run(LV2_Handle Instance, uint32_t SampleCount) + { instance *const inst = (instance *)Instance; audio_module_iface *mod = inst->module; if (inst->set_srate) { @@ -279,20 +321,52 @@ struct lv2_wrapper } inst->module->process_slice(offset, SampleCount); } - static void cb_cleanup(LV2_Handle Instance) { + static void cb_cleanup(LV2_Handle Instance) + { instance *const mod = (instance *)Instance; delete mod; } - static const void *cb_ext_data(const char *URI) { + static const void *cb_ext_data(const char *URI) + { if (!strcmp(URI, "http://foltman.com/ns/calf-plugin-instance")) return &calf_descriptor; if (!strcmp(URI, LV2_CONTEXT_MESSAGE)) return &message_context; +#if USE_PERSIST_EXTENSION + if (!strcmp(URI, LV2_PERSIST_URI)) + return &persist; +#endif return NULL; } +#if USE_PERSIST_EXTENSION + static void cb_persist_save(LV2_Handle Instance, LV2_Persist_Store_Function store, void *callback_data) + { + instance *const inst = (instance *)Instance; + struct store_state: public send_configure_iface + { + LV2_Persist_Store_Function store; + void *callback_data; + + virtual void send_configure(const char *key, const char *value) + { + (*store)(callback_data, key, value, strlen(value)); + } + }; + store_state s; + s.store = store; + s.callback_data = callback_data; + inst->send_configures(&s); + } + static void cb_persist_restore(LV2_Handle Instance, LV2_Persist_Retrieve_Function retrieve, void *callback_data) + { + instance *const inst = (instance *)Instance; + inst->impl_restore(retrieve, callback_data); + } +#endif + static lv2_wrapper &get() { - static lv2_wrapper instance; - return instance; + static lv2_wrapper *instance = new lv2_wrapper; + return *instance; } }; diff --git a/plugins/ladspa_effect/calf/src/plugin.cpp b/plugins/ladspa_effect/calf/src/plugin.cpp index 9a4b97615..6588f67c6 100644 --- a/plugins/ladspa_effect/calf/src/plugin.cpp +++ b/plugins/ladspa_effect/calf/src/plugin.cpp @@ -485,6 +485,9 @@ ladspa_plugin_metadata_set::~ladspa_plugin_metadata_set() template LV2_Descriptor calf_plugins::lv2_wrapper::descriptor; template LV2_Calf_Descriptor calf_plugins::lv2_wrapper::calf_descriptor; template LV2MessageContext calf_plugins::lv2_wrapper::message_context; +#if USE_PERSIST_EXTENSION +template LV2_Persist calf_plugins::lv2_wrapper::persist; +#endif extern "C" { diff --git a/src/calf/lv2_persist.h b/src/calf/lv2_persist.h index 56b9990d9..86ac86596 100644 --- a/src/calf/lv2_persist.h +++ b/src/calf/lv2_persist.h @@ -17,7 +17,6 @@ extern "C" { The plugin should always expose this feature as optional. */ #define LV2_PERSIST_URI "http://paniq.org/lv2/persist" - /* Causes the host to store a binary blob in a map. @@ -28,22 +27,23 @@ extern "C" { the binary blob to be stored. 'size' is the size of the binary blob in bytes. - The host must store a copy of the blob under the provided key in a map - until returning from the save() call. + The host is expected store a copy of the blob under the provided key. - A size of 0 indicates that value points to a zero-terminated string. + A 'size' of 0 is valid. The host may choose to store nothing. + + A 'size' of -1 indicates that 'value' points to a zero-terminated string. This is a convenience function which requires the host to calculate the - length as strlen(value)+1. + size from strlen(value)+1. */ typedef void (*LV2_Persist_Store_Function)(void *callback_data, const char *key, - const void *value, size_t size); + const void *value, ssize_t size); /* Causes the host to retrieve a binary blob from the map. A callback provided by the host to LV2_Persist.restore(). 'callback_data' must be the callback_data argument passed to restore(). 'key' is a private - string or UI under which a blob has been previously stored. + string or URI under which a blob has been previously stored. When the blob could be successfully retrieved, retrieve() must return a pointer to the blob and set 'size' to the length of value in bytes. @@ -91,7 +91,7 @@ struct LV2_Persist { The map on which save() operates must always be empty before the first call to store(). The plugin is expected to store all - blobs of interests. + blobs of interest. The callback data pointer and store function may not be used beyond the scope of save(). @@ -127,4 +127,4 @@ struct LV2_Persist { } /* extern "C" */ #endif -#endif /* __LV2_PERSIST_H__ */ +#endif /* __LV2_PERSIST_H__ */ \ No newline at end of file