made lv2 template and test plugin c++ friendly

This commit is contained in:
Stefano D'Angelo 2025-07-18 17:33:23 +02:00
parent 1e5d2b49da
commit 59838dda25
3 changed files with 81 additions and 47 deletions

View File

@ -71,7 +71,7 @@ LDFLAGS :=
LDFLAGS_ALL := -shared $(shell pkg-config --libs lv2) $(LDFLAGS_EXTRA) $(LDFLAGS) LDFLAGS_ALL := -shared $(shell pkg-config --libs lv2) $(LDFLAGS_EXTRA) $(LDFLAGS)
CXXFLAGS := $(CFLAGS) CXXFLAGS := $(CFLAGS)
CXXFLAGS_ALL := -I$(DATA_DIR)/src -I$(PLUGIN_DIR) -I$(API_DIR) -fPIC $(CXXFLAGS_EXTRA) $(CXXFLAGS) CXXFLAGS_ALL := -I$(DATA_DIR)/src -I$(PLUGIN_DIR) -I$(API_DIR) $(shell pkg-config --cflags lv2) -fPIC -fvisibility=hidden $(CXXFLAGS_EXTRA) $(CXXFLAGS)
ifeq ($(UNAME_S), Darwin) ifeq ($(UNAME_S), Darwin)
CFLAGS_ALL := $(CFLAGS_ALL) -arch arm64 -arch x86_64 CFLAGS_ALL := $(CFLAGS_ALL) -arch arm64 -arch x86_64

View File

@ -58,7 +58,11 @@
#endif #endif
#if (DATA_PRODUCT_CONTROL_INPUTS_N > 0) && defined(DATA_STATE_DSP_CUSTOM) #if (DATA_PRODUCT_CONTROL_INPUTS_N > 0) && defined(DATA_STATE_DSP_CUSTOM)
# include <stdatomic.h> # ifdef __cplusplus
# include <atomic>
# else
# include <stdatomic.h>
# endif
# if defined(_WIN32) || defined(__CYGWIN__) # if defined(_WIN32) || defined(__CYGWIN__)
# include <processthreadsapi.h> # include <processthreadsapi.h>
# define yield SwitchToThread # define yield SwitchToThread
@ -113,7 +117,11 @@ typedef struct {
float params[DATA_PRODUCT_CONTROL_INPUTS_N]; float params[DATA_PRODUCT_CONTROL_INPUTS_N];
# ifdef DATA_STATE_DSP_CUSTOM # ifdef DATA_STATE_DSP_CUSTOM
float params_sync[DATA_PRODUCT_CONTROL_INPUTS_N]; float params_sync[DATA_PRODUCT_CONTROL_INPUTS_N];
# ifdef __cplusplus
std::atomic_flag sync_lock_flag;
# else
atomic_flag sync_lock_flag; atomic_flag sync_lock_flag;
# endif
char synced; char synced;
char loaded; char loaded;
# endif # endif
@ -142,14 +150,22 @@ static const char * get_bundle_path_cb(void *handle) {
#ifdef DATA_STATE_DSP_CUSTOM #ifdef DATA_STATE_DSP_CUSTOM
static void state_lock_cb(void *handle) { static void state_lock_cb(void *handle) {
plugin_instance * i = (plugin_instance *)handle; plugin_instance * i = (plugin_instance *)handle;
# ifdef __cplusplus
while (i->sync_lock_flag.test_and_set())
# else
while (atomic_flag_test_and_set(&i->sync_lock_flag)) while (atomic_flag_test_and_set(&i->sync_lock_flag))
# endif
yield(); yield();
i->synced = 0; i->synced = 0;
} }
static void state_unlock_cb(void *handle) { static void state_unlock_cb(void *handle) {
plugin_instance * i = (plugin_instance *)handle; plugin_instance * i = (plugin_instance *)handle;
# ifdef __cplusplus
i->sync_lock_flag.clear();
# else
atomic_flag_clear(&i->sync_lock_flag); atomic_flag_clear(&i->sync_lock_flag);
# endif
} }
static int state_write_cb(void *handle, const char *data, size_t length) { static int state_write_cb(void *handle, const char *data, size_t length) {
@ -172,7 +188,12 @@ static LV2_Handle instantiate(const struct LV2_Descriptor * descriptor, double s
(void)descriptor; (void)descriptor;
(void)bundle_path; (void)bundle_path;
plugin_instance *instance = malloc(sizeof(plugin_instance)); // make C++ compilers happy
const char * missing;
plugin_callbacks cbs;
size_t req;
plugin_instance *instance = (plugin_instance *)malloc(sizeof(plugin_instance));
if (instance == NULL) if (instance == NULL)
goto err_instance; goto err_instance;
@ -181,7 +202,7 @@ static LV2_Handle instantiate(const struct LV2_Descriptor * descriptor, double s
goto err_bundle_path; goto err_bundle_path;
// from https://lv2plug.in/book // from https://lv2plug.in/book
const char * missing = lv2_features_query(features, missing = lv2_features_query(features,
LV2_LOG__log, &instance->logger.log, false, LV2_LOG__log, &instance->logger.log, false,
LV2_URID__map, &instance->map, true, LV2_URID__map, &instance->map, true,
NULL); NULL);
@ -205,17 +226,15 @@ static LV2_Handle instantiate(const struct LV2_Descriptor * descriptor, double s
} }
#endif #endif
plugin_callbacks cbs = { cbs.handle = (void *)instance;
/* .handle = */ (void *)instance, cbs.format = "lv2";
/* .format = */ "lv2", cbs.get_bindir = get_bundle_path_cb;
/* .get_bindir = */ get_bundle_path_cb, cbs.get_datadir = get_bundle_path_cb;
/* .get_datadir = */ get_bundle_path_cb
};
plugin_init(&instance->p, &cbs); plugin_init(&instance->p, &cbs);
instance->sample_rate = (float)sample_rate; instance->sample_rate = (float)sample_rate;
plugin_set_sample_rate(&instance->p, instance->sample_rate); plugin_set_sample_rate(&instance->p, instance->sample_rate);
size_t req = plugin_mem_req(&instance->p); req = plugin_mem_req(&instance->p);
if (req != 0) { if (req != 0) {
instance->mem = malloc(req); instance->mem = malloc(req);
if (instance->mem == NULL) { if (instance->mem == NULL) {
@ -265,34 +284,34 @@ static void connect_port(LV2_Handle instance, uint32_t port, void * data_locatio
plugin_instance * i = (plugin_instance *)instance; plugin_instance * i = (plugin_instance *)instance;
#if DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N > 0 #if DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N > 0
if (port < DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N) { if (port < DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N) {
i->x[port] = data_location; i->x[port] = (const float *)data_location;
return; return;
} }
port -= DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N; port -= DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N;
#endif #endif
#if DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N > 0 #if DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N > 0
if (port < DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N) { if (port < DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N) {
i->y[port] = data_location; i->y[port] = (float *)data_location;
return; return;
} }
port -= DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N; port -= DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N;
#endif #endif
#if DATA_PRODUCT_MIDI_INPUTS_N > 0 #if DATA_PRODUCT_MIDI_INPUTS_N > 0
if (port < DATA_PRODUCT_MIDI_INPUTS_N) { if (port < DATA_PRODUCT_MIDI_INPUTS_N) {
i->x_midi[port] = data_location; i->x_midi[port] = (const LV2_Atom_Sequence *)data_location;
return; return;
} }
port -= DATA_PRODUCT_MIDI_INPUTS_N; port -= DATA_PRODUCT_MIDI_INPUTS_N;
#endif #endif
#if DATA_PRODUCT_MIDI_OUTPUTS_N > 0 #if DATA_PRODUCT_MIDI_OUTPUTS_N > 0
if (port < DATA_PRODUCT_MIDI_OUTPUTS_N) { if (port < DATA_PRODUCT_MIDI_OUTPUTS_N) {
i->y_midi[port] = data_location; i->y_midi[port] = (LV2_Atom_Sequence *)data_location;
return; return;
} }
port -= DATA_PRODUCT_MIDI_OUTPUTS_N; port -= DATA_PRODUCT_MIDI_OUTPUTS_N;
#endif #endif
#if (DATA_PRODUCT_CONTROL_INPUTS_N + DATA_PRODUCT_CONTROL_OUTPUTS_N) > 0 #if (DATA_PRODUCT_CONTROL_INPUTS_N + DATA_PRODUCT_CONTROL_OUTPUTS_N) > 0
i->c[port] = data_location; i->c[port] = (float *)data_location;
#endif #endif
} }
@ -306,9 +325,13 @@ static void activate(LV2_Handle instance) {
# ifdef DATA_STATE_DSP_CUSTOM # ifdef DATA_STATE_DSP_CUSTOM
for (uint32_t j = 0; j < DATA_PRODUCT_CONTROL_INPUTS_N; j++) for (uint32_t j = 0; j < DATA_PRODUCT_CONTROL_INPUTS_N; j++)
i->params_sync[j] = i->params[j]; i->params_sync[j] = i->params[j];
# ifdef __cplusplus
i->sync_lock_flag.clear();
# else
// why is this not correct? // why is this not correct?
// i->sync_lock_flag = ATOMIC_FLAG_INIT; // i->sync_lock_flag = ATOMIC_FLAG_INIT;
atomic_flag_clear(&i->sync_lock_flag); atomic_flag_clear(&i->sync_lock_flag);
# endif
i->synced = 1; i->synced = 1;
i->loaded = 0; i->loaded = 0;
# endif # endif
@ -333,7 +356,11 @@ static void run(LV2_Handle instance, uint32_t sample_count) {
#if DATA_PRODUCT_CONTROL_INPUTS_N > 0 #if DATA_PRODUCT_CONTROL_INPUTS_N > 0
# ifdef DATA_STATE_DSP_CUSTOM # ifdef DATA_STATE_DSP_CUSTOM
# ifdef __cplusplus
_Bool locked = !i->sync_lock_flag.test_and_set();
# else
_Bool locked = !atomic_flag_test_and_set(&i->sync_lock_flag); _Bool locked = !atomic_flag_test_and_set(&i->sync_lock_flag);
# endif
if (locked) { if (locked) {
if (!i->synced) { if (!i->synced) {
if (i->loaded) { if (i->loaded) {
@ -373,7 +400,11 @@ static void run(LV2_Handle instance, uint32_t sample_count) {
# ifdef DATA_STATE_DSP_CUSTOM # ifdef DATA_STATE_DSP_CUSTOM
if (locked) if (locked)
# ifdef __cplusplus
i->sync_lock_flag.clear();
# else
atomic_flag_clear(&i->sync_lock_flag); atomic_flag_clear(&i->sync_lock_flag);
# endif
# endif # endif
#endif #endif
@ -467,7 +498,7 @@ static LV2_State_Status state_restore(LV2_Handle instance, LV2_State_Retrieve_Fu
} }
size_t length; size_t length;
uint32_t type, xflags; // jalv 1.6.6 crashes using NULL as per spec, so we have these two uint32_t type, xflags; // jalv 1.6.6 crashes using NULL as per spec, so we have these two
const char * data = retrieve(handle, i->uri_state_data, &length, &type, &xflags); const char * data = (const char *)retrieve(handle, i->uri_state_data, &length, &type, &xflags);
if (data == NULL) { if (data == NULL) {
lv2_log_error(&i->logger, "Cannot restore state since property <%s> could not be retrieved\n", DATA_LV2_URI "#state_data"); lv2_log_error(&i->logger, "Cannot restore state since property <%s> could not be retrieved\n", DATA_LV2_URI "#state_data");
return LV2_STATE_ERR_NO_PROPERTY; return LV2_STATE_ERR_NO_PROPERTY;
@ -561,7 +592,12 @@ static LV2UI_Handle ui_instantiate(const LV2UI_Descriptor * descriptor, const ch
(void)descriptor; (void)descriptor;
(void)plugin_uri; (void)plugin_uri;
ui_instance *instance = malloc(sizeof(ui_instance)); // make C++ compilers happy;
char has_parent;
void *parent;
plugin_ui_callbacks cbs;
ui_instance *instance = (ui_instance *)malloc(sizeof(ui_instance));
if (instance == NULL) if (instance == NULL)
goto err_instance; goto err_instance;
@ -569,8 +605,8 @@ static LV2UI_Handle ui_instantiate(const LV2UI_Descriptor * descriptor, const ch
if (instance->bundle_path == NULL) if (instance->bundle_path == NULL)
goto err_bundle_path; goto err_bundle_path;
char has_parent = 0; has_parent = 0;
void *parent = NULL; parent = NULL;
# if DATA_PRODUCT_CONTROL_INPUTS_N > 0 # if DATA_PRODUCT_CONTROL_INPUTS_N > 0
instance->has_touch = 0; instance->has_touch = 0;
# endif # endif
@ -587,17 +623,15 @@ static LV2UI_Handle ui_instantiate(const LV2UI_Descriptor * descriptor, const ch
# endif # endif
} }
plugin_ui_callbacks cbs = { cbs.handle = (void *)instance;
/* .handle = */ (void *)instance, cbs.format = "lv2";
/* .format = */ "lv2", cbs.get_bindir = ui_get_bundle_path_cb;
/* .get_bindir = */ ui_get_bundle_path_cb, cbs.get_datadir = ui_get_bundle_path_cb;
/* .get_datadir = */ ui_get_bundle_path_cb,
# if DATA_PRODUCT_CONTROL_INPUTS_N > 0 # if DATA_PRODUCT_CONTROL_INPUTS_N > 0
/* .set_parameter_begin = */ ui_set_parameter_begin_cb, cbs.set_parameter_begin = ui_set_parameter_begin_cb;
/* .set_parameter = */ ui_set_parameter_cb, cbs.set_parameter = ui_set_parameter_cb;
/* .set_parameter_end = */ ui_set_parameter_end_cb, cbs.set_parameter_end = ui_set_parameter_end_cb;
# endif # endif
};
# if DATA_PRODUCT_CONTROL_INPUTS_N > 0 # if DATA_PRODUCT_CONTROL_INPUTS_N > 0
instance->write = write_function; instance->write = write_function;
instance->controller = controller; instance->controller = controller;

View File

@ -25,8 +25,8 @@
typedef struct { typedef struct {
void *widget; void *widget;
vinci *vinci; vinci *ui;
window *window; window *w;
int param_down; int param_down;
float gain; float gain;
@ -57,16 +57,16 @@ static void draw_rect(window *w, uint32_t x, uint32_t y, uint32_t width, uint32_
} }
static void draw_slider(plugin_ui *pui, int id, float value) { static void draw_slider(plugin_ui *pui, int id, float value) {
const int w = window_get_width(pui->window); const int w = window_get_width(pui->w);
const int h = window_get_height(pui->window); const int h = window_get_height(pui->w);
draw_rect(pui->window, 0.1 * w, 0.15 * (id + 1) * h, 0.8 * w * value, 0.1 * h, 0x6789ab); draw_rect(pui->w, 0.1 * w, 0.15 * (id + 1) * h, 0.8 * w * value, 0.1 * h, 0x6789ab);
draw_rect(pui->window, 0.1 * w + 0.8 * w * value, 0.15 * (id + 1) * h, 0.8 * w * (1.f - value), 0.1 * h, 0x1223bc); draw_rect(pui->w, 0.1 * w + 0.8 * w * value, 0.15 * (id + 1) * h, 0.8 * w * (1.f - value), 0.1 * h, 0x1223bc);
} }
static void draw_button(plugin_ui *pui, int id, char value) { static void draw_button(plugin_ui *pui, int id, char value) {
const int w = window_get_width(pui->window); const int w = window_get_width(pui->w);
const int h = window_get_height(pui->window); const int h = window_get_height(pui->w);
draw_rect(pui->window, 0.4 * w, 0.15 * (id + 1) * h, 0.2 * w, 0.1 * h, value ? 0x6789ab : 0x1223bc); draw_rect(pui->w, 0.4 * w, 0.15 * (id + 1) * h, 0.2 * w, 0.1 * h, value ? 0x6789ab : 0x1223bc);
} }
static void on_close(window *w) { static void on_close(window *w) {
@ -191,11 +191,11 @@ static plugin_ui *plugin_ui_create(char has_parent, void *parent, plugin_ui_call
wcbs.on_window_resize = on_window_resize; wcbs.on_window_resize = on_window_resize;
instance->param_down = -1; instance->param_down = -1;
instance->vinci = vinci_new(); instance->ui = vinci_new();
instance->window = window_new(instance->vinci, has_parent ? parent : NULL, WIDTH, HEIGHT, &wcbs); instance->w = window_new(instance->ui, has_parent ? parent : NULL, WIDTH, HEIGHT, &wcbs);
instance->widget = window_get_handle(instance->window); instance->widget = window_get_handle(instance->w);
window_set_data(instance->window, (void*) instance); window_set_data(instance->w, (void*) instance);
window_show(instance->window); window_show(instance->w);
// just some valid values to allow drawing // just some valid values to allow drawing
instance->gain = 0.f; instance->gain = 0.f;
@ -204,20 +204,20 @@ static plugin_ui *plugin_ui_create(char has_parent, void *parent, plugin_ui_call
instance->bypass = 0; instance->bypass = 0;
instance->y_z1 = 0.f; instance->y_z1 = 0.f;
on_window_resize(instance->window, window_get_width(instance->window), window_get_height(instance->window)); on_window_resize(instance->w, window_get_width(instance->w), window_get_height(instance->w));
instance->cbs = *cbs; instance->cbs = *cbs;
return instance; return instance;
} }
static void plugin_ui_free(plugin_ui *instance) { static void plugin_ui_free(plugin_ui *instance) {
window_free(instance->window); window_free(instance->w);
vinci_destroy(instance->vinci); vinci_destroy(instance->ui);
free(instance); free(instance);
} }
static void plugin_ui_idle(plugin_ui *instance) { static void plugin_ui_idle(plugin_ui *instance) {
vinci_idle(instance->vinci); vinci_idle(instance->ui);
} }
static void plugin_ui_set_parameter(plugin_ui *instance, size_t index, float value) { static void plugin_ui_set_parameter(plugin_ui *instance, size_t index, float value) {