Add a crude incomplete implementation of persist extension support.

(cherry picked from commit 3ec11c04799fc08fd408c4ef2350df65f88ccfde)
This commit is contained in:
Krzysztof Foltman
2010-09-19 23:14:40 +01:00
committed by Tobias Doerffel
parent 48f9008f42
commit fbc364e68e
4 changed files with 107 additions and 20 deletions

View File

@@ -28,6 +28,8 @@
#include <string>
#include <vector>
// #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<name##_metadata>::port_names[]

View File

@@ -30,6 +30,7 @@
#include <calf/lv2-midiport.h>
#include <calf/lv2_contexts.h>
#include <calf/lv2_event.h>
#include <calf/lv2_persist.h>
#include <calf/lv2_progress.h>
#include <calf/lv2_string_port.h>
#include <calf/lv2_uri_map.h>
@@ -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<plugin_ctl_iface *>(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;
}
};

View File

@@ -485,6 +485,9 @@ ladspa_plugin_metadata_set::~ladspa_plugin_metadata_set()
template<class Module> LV2_Descriptor calf_plugins::lv2_wrapper<Module>::descriptor;
template<class Module> LV2_Calf_Descriptor calf_plugins::lv2_wrapper<Module>::calf_descriptor;
template<class Module> LV2MessageContext calf_plugins::lv2_wrapper<Module>::message_context;
#if USE_PERSIST_EXTENSION
template<class Module> LV2_Persist calf_plugins::lv2_wrapper<Module>::persist;
#endif
extern "C" {

View File

@@ -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__ */