changing plugin callbacks, breaking everything

This commit is contained in:
Stefano D'Angelo 2024-06-17 08:18:37 +02:00
parent b8a16c226c
commit e01043d24e
3 changed files with 210 additions and 59 deletions

View File

@ -22,7 +22,17 @@
#include <stdint.h>
typedef struct {
void * handle;
void * handle;
const char * format;
const char * (*get_bindir)(void *handle);
const char * (*get_datadir)(void *handle);
} plugin_callbacks;
typedef struct {
void * handle;
const char * format;
const char * (*get_bindir)(void *handle);
const char * (*get_datadir)(void *handle);
void (*set_parameter)(void *handle, size_t index, float value);
} plugin_ui_callbacks;
@ -47,10 +57,10 @@ typedef struct {
#endif
#ifdef DATA_UI
# include "lv2/ui/ui.h"
# include <string.h>
#endif
#include <string.h>
#if defined(__i386__) || defined(__x86_64__)
# include <xmmintrin.h>
# include <pmmintrin.h>
@ -91,6 +101,7 @@ typedef struct {
float params[DATA_PRODUCT_CONTROL_INPUTS_N];
#endif
void * mem;
char * bundle_path;
#if DATA_PRODUCT_MIDI_INPUTS_N + DATA_PRODUCT_MIDI_OUTPUT_N > 0
LV2_URID_Map * map;
LV2_Log_Logger logger;
@ -98,13 +109,22 @@ typedef struct {
#endif
} plugin_instance;
static const char * get_bundle_path_cb(void *handle) {
plugin_instance *instance = (plugin_instance *)handle;
return instance->bundle_path;
}
static LV2_Handle instantiate(const struct LV2_Descriptor * descriptor, double sample_rate, const char * bundle_path, const LV2_Feature * const * features) {
(void)descriptor;
(void)bundle_path;
plugin_instance *instance = malloc(sizeof(plugin_instance));
if (instance == NULL)
return NULL;
goto err_instance;
instance->bundle_path = strdup(bundle_path);
if (instance->bundle_path == NULL)
goto err_bundle_path;
#if DATA_PRODUCT_MIDI_INPUTS_N + DATA_PRODUCT_MIDI_OUTPUT_N > 0
// from https://lv2plug.in/book
@ -116,8 +136,7 @@ static LV2_Handle instantiate(const struct LV2_Descriptor * descriptor, double s
lv2_log_logger_set_map(&instance->logger, instance->map);
if (missing) {
lv2_log_error(&instance->logger, "Missing feature <%s>\n", missing);
free(instance);
return NULL;
goto err_urid;
}
instance->uri_midi_MidiEvent = instance->map->map(instance->map->handle, LV2_MIDI__MidiEvent);
@ -125,15 +144,21 @@ static LV2_Handle instantiate(const struct LV2_Descriptor * descriptor, double s
(void)features;
#endif
plugin_init(&instance->p);
plugin_callbacks cbs = {
/* .handle = */ (void *)instance,
/* .format = */ "lv2",
/* .get_bindir = */ get_bundle_path_cb,
/* .get_datadir = */ get_bundle_path_cb
};
plugin_init(&instance->p, &cbs);
plugin_set_sample_rate(&instance->p, sample_rate);
size_t req = plugin_mem_req(&instance->p);
if (req != 0) {
instance->mem = malloc(req);
if (instance->mem == NULL) {
plugin_fini(&instance->p);
return NULL;
lv2_log_error(&instance->logger, "Not enough memory\n");
goto err_mem;
}
plugin_mem_set(&instance->p, instance->mem);
} else
@ -161,6 +186,15 @@ static LV2_Handle instantiate(const struct LV2_Descriptor * descriptor, double s
#endif
return instance;
err_mem:
plugin_fini(&instance->p);
err_urid:
free(instance->bundle_path);
err_bundle_path:
free(instance);
err_instance:
return NULL;
}
static void connect_port(LV2_Handle instance, uint32_t port, void * data_location) {
@ -286,6 +320,7 @@ static void cleanup(LV2_Handle instance) {
plugin_fini(&i->p);
if (i->mem)
free(i->mem);
free(i->bundle_path);
free(instance);
}
@ -307,6 +342,7 @@ LV2_SYMBOL_EXPORT const LV2_Descriptor * lv2_descriptor(uint32_t index) {
#ifdef DATA_UI
typedef struct {
plugin_ui * ui;
char * bundle_path;
# if DATA_PRODUCT_CONTROL_INPUTS_N > 0
LV2UI_Write_Function write;
LV2UI_Controller controller;
@ -320,6 +356,11 @@ typedef struct {
+ DATA_PRODUCT_MIDI_OUTPUTS_N )
# define CONTROL_OUTPUT_INDEX_OFFSET (CONTROL_INPUT_INDEX_OFFSET + DATA_PRODUCT_CONTROL_INPUTS_N)
static const char * ui_get_bundle_path_cb(void *handle) {
ui_instance *instance = (ui_instance *)handle;
return instance->bundle_path;
}
# if DATA_PRODUCT_CONTROL_INPUTS_N > 0
static void ui_set_parameter_cb(void *handle, size_t index, float value) {
ui_instance *instance = (ui_instance *)handle;
@ -343,38 +384,51 @@ static LV2UI_Handle ui_instantiate(const LV2UI_Descriptor * descriptor, const ch
}
ui_instance *instance = malloc(sizeof(ui_instance));
if (instance == NULL) {
*widget = NULL;
return NULL;
}
if (instance == NULL)
goto err_instance;
instance->bundle_path = strdup(bundle_path);
if (instance->bundle_path == NULL)
goto err_bundle_path;
plugin_ui_callbacks cbs = {
/* .handle = */ (void *)instance,
/* .format = */ "lv2",
/* .get_bindir = */ ui_get_bundle_path_cb,
/* .get_datadir = */ ui_get_bundle_path_cb,
# if DATA_PRODUCT_CONTROL_INPUTS_N > 0
/* .set_parameter = */ ui_set_parameter_cb
# else
/* .set_parameter = */ NULL
# endif
};
# if DATA_PRODUCT_CONTROL_INPUTS_N > 0
instance->write = write_function;
instance->controller = controller;
plugin_ui_callbacks cbs = {
/* .handle = */ (void *)instance,
/* .set_parameter = */ ui_set_parameter_cb
};
instance->ui = plugin_ui_create(has_parent, parent, &cbs);
# else
(void)write_function;
(void)controller;
instance->ui = plugin_ui_create(has_parent, parent, NULL);
# endif
if (instance->ui == NULL) {
free(instance);
*widget = NULL;
return NULL;
}
instance->ui = plugin_ui_create(has_parent, parent, &cbs);
if (instance->ui == NULL)
goto err_create;
*widget = instance->ui->widget;
return instance;
err_create:
free(instance->bundle_path);
err_bundle_path:
free(instance);
err_instance:
*widget = NULL;
return NULL;
}
static void ui_cleanup(LV2UI_Handle handle) {
ui_instance *instance = (ui_instance *)handle;
plugin_ui_free(instance->ui);
free(instance->bundle_path);
free(instance);
}

View File

@ -18,17 +18,21 @@
* File author: Stefano D'Angelo, Paolo Marrone
*/
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"
#include "vst3_c_api.h"
#pragma GCC diagnostic pop
#include <stdint.h>
typedef struct {
void * handle;
void * handle;
const char * format;
const char * (*get_bindir)(void *handle);
const char * (*get_datadir)(void *handle);
} plugin_callbacks;
typedef struct {
void * handle;
const char * format;
const char * (*get_bindir)(void *handle);
const char * (*get_datadir)(void *handle);
void (*set_parameter)(void *handle, size_t index, float value);
} plugin_ui_callbacks;
@ -38,6 +42,17 @@ typedef struct {
# include "plugin_ui.h"
#endif
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"
#include "vst3_c_api.h"
#pragma GCC diagnostic pop
#include <string.h>
#include <math.h>
#if defined(_WIN32) || defined(__CYGWIN__)
# include <windows.h>
#endif
#if defined(__i386__) || defined(__x86_64__)
#include <xmmintrin.h>
#include <pmmintrin.h>
@ -54,11 +69,6 @@ typedef struct {
# define TRACE(...) /* do nothing */
#endif
#if defined(__i386__) || defined(__x86_64__)
#include <xmmintrin.h>
#include <pmmintrin.h>
#endif
#ifdef DATA_UI
# ifdef __linux__
// Why generate the C interface when you can just not give a fuck? Thank you Steinberg!
@ -123,6 +133,22 @@ static const Steinberg_TUID Steinberg_IRunLoop_iid = SMTG_INLINE_UID (0x18C35366
# endif
#endif
static char *x_asprintf(const char * restrict format, ...) {
va_list args, tmp;
va_start(args, format);
va_copy(tmp, args);
int len = vsprintf(NULL, format, tmp);
va_end(tmp);
char *s = malloc(len + 1);
if (s != NULL)
vsprintf(s, format, args);
va_end(args);
return s;
}
static char *bindir;
static char *datadir;
static double clamp(double x, double m, double M) {
return x < m ? m : (x > M ? M : x);
}
@ -237,12 +263,15 @@ static Steinberg_uint32 pluginIComponentRelease(void *thisInterface) {
return pluginRelease((pluginInstance *)((char *)thisInterface - offsetof(pluginInstance, vtblIComponent)));
}
//XXX
static Steinberg_tresult pluginInitialize(void *thisInterface, struct Steinberg_FUnknown *context) {
TRACE("plugin initialize\n");
pluginInstance *p = (pluginInstance *)((char *)thisInterface - offsetof(pluginInstance, vtblIComponent));
if (p->context != NULL)
return Steinberg_kResultFalse;
p->context = context;
//XXX
plugin_init(&p->p);
#if DATA_PRODUCT_PARAMETERS_N > 0
for (size_t i = 0; i < DATA_PRODUCT_PARAMETERS_N; i++) {
@ -943,10 +972,6 @@ static Steinberg_ITimerHandlerVtbl timerHandlerVtblITimerHandler = {
# include <objc/runtime.h>
# include <objc/message.h>
# elif defined(_WIN32) || defined(__CYGWIN__)
# include <windows.h>
# endif
typedef struct plugView {
@ -1072,6 +1097,8 @@ static void plugViewTimerCb(HWND p1, UINT p2, UINT_PTR p3, DWORD p4) {
}
# endif
//XXX
static Steinberg_tresult plugViewAttached(void* thisInterface, void* parent, Steinberg_FIDString type) {
// GUI needs to be created here, see https://forums.steinberg.net/t/vst-and-hidpi/201916/3
TRACE("plugView attached %p\n", thisInterface);
@ -1082,17 +1109,23 @@ static Steinberg_tresult plugViewAttached(void* thisInterface, void* parent, Ste
plugView *v = (plugView *)((char *)thisInterface - offsetof(plugView, vtblIPlugView));
if (v->ui)
return Steinberg_kInvalidArgument;
# if DATA_PRODUCT_PARAMETERS_N > 0
plugin_ui_callbacks cbs = {
/* .handle = */ (void *)v,
/* .format = */ "vst3",
/* .get_bindir = */ ui_get_bindir_cb,
/* .get_datadir = */ ui_get_datadir_cb,
# if DATA_PRODUCT_PARAMETERS_N > 0
/* .set_parameter = */ plugViewSetParameterCb
};
v->ui = plugin_ui_create(1, parent, &cbs);
# else
v->ui = plugin_ui_create(1, parent, NULL);
/* .set_parameter = */ NULL
# endif
};
//XXX
v->ui = plugin_ui_create(1, parent, &cbs);
if (!v->ui)
return Steinberg_kResultFalse;
# ifdef __linux__
v->display = XOpenDisplay(NULL);
if (v->display == NULL) {
@ -2062,25 +2095,88 @@ Steinberg_IPluginFactory * GetPluginFactory(void) {
return (Steinberg_IPluginFactory *)&factory;
}
#if !defined(_WIN32) && !defined(__CYGWIN__)
# if defined(__APPLE__)
# define ENTRY bundleEntry
# define EXIT bundleExit
# else
# define ENTRY ModuleEntry
# define EXIT ModuleExit
# endif
static int refs = 0;
static char exit() {
refs--;
if (refs == 0) {
free(bindir);
free(datadir);
return 0;
}
return 1;
}
#if defined(_WIN32) || defined(__CYGWIN__)
XXX int APIENTRY
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) {
(void)hInstance;
(void)lpReserved;
if (dwReason == DLL_PROCESS_ATTACH) {
if (refs == 0) {
//XXX
}
refs++;
} else if (dwReason == DLL_PROCESS_DETACH)
exit();
return 1;
}
#elif defined(__APPLE__)
EXPORT
char ENTRY(void *handle) {
(void)handle;
char bundleEntry(CFBundleRef ref) {
(void)ref;
if (refs == 0) {
//XXX
}
refs++;
return 1;
}
EXPORT
char EXIT(void) {
char bundleExit(void) {
return exit();
}
#else
EXPORT
char ModuleEntry(void *handle) {
(void)handle;
if (refs == 0) {
Dl_info info;
if (dladdr((void *)ModuleEntry, &info) == 0)
return 0;
char *file = realpath(info.dli_fname, NULL);
if (file == NULL)
return 0;
char *c = strrchr(file, '/');
*c = '\0';
bindir = strdup(file);
if (bindir == NULL)
goto err_bindir;
char *c = strrchr(file, '/');
*c = '\0';
datadir = x_asprintf("%s/Resources", file);
if (datadir == NULL)
goto err_datadir;
free(file);
}
refs++;
return 1;
err_datadir:
free(bindir);
err_bindir:
free(file);
return 0;
}
EXPORT
char ModuleExit(void) {
return exit();
}
#endif

View File

@ -34,8 +34,9 @@ typedef struct plugin {
float yz1;
} plugin;
static void plugin_init(plugin *instance) {
static void plugin_init(plugin *instance, plugin_callbacks *cbs) {
(void)instance;
(void)cbs;
}
static void plugin_fini(plugin *instance) {