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

@ -23,6 +23,16 @@
typedef struct { 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); void (*set_parameter)(void *handle, size_t index, float value);
} plugin_ui_callbacks; } plugin_ui_callbacks;
@ -47,9 +57,9 @@ typedef struct {
#endif #endif
#ifdef DATA_UI #ifdef DATA_UI
# include "lv2/ui/ui.h" # include "lv2/ui/ui.h"
#endif
#include <string.h> #include <string.h>
#endif
#if defined(__i386__) || defined(__x86_64__) #if defined(__i386__) || defined(__x86_64__)
# include <xmmintrin.h> # include <xmmintrin.h>
@ -91,6 +101,7 @@ typedef struct {
float params[DATA_PRODUCT_CONTROL_INPUTS_N]; float params[DATA_PRODUCT_CONTROL_INPUTS_N];
#endif #endif
void * mem; void * mem;
char * bundle_path;
#if DATA_PRODUCT_MIDI_INPUTS_N + DATA_PRODUCT_MIDI_OUTPUT_N > 0 #if DATA_PRODUCT_MIDI_INPUTS_N + DATA_PRODUCT_MIDI_OUTPUT_N > 0
LV2_URID_Map * map; LV2_URID_Map * map;
LV2_Log_Logger logger; LV2_Log_Logger logger;
@ -98,13 +109,22 @@ typedef struct {
#endif #endif
} plugin_instance; } 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) { static LV2_Handle instantiate(const struct LV2_Descriptor * descriptor, double sample_rate, const char * bundle_path, const LV2_Feature * const * features) {
(void)descriptor; (void)descriptor;
(void)bundle_path; (void)bundle_path;
plugin_instance *instance = malloc(sizeof(plugin_instance)); plugin_instance *instance = malloc(sizeof(plugin_instance));
if (instance == NULL) 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 #if DATA_PRODUCT_MIDI_INPUTS_N + DATA_PRODUCT_MIDI_OUTPUT_N > 0
// from https://lv2plug.in/book // 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); lv2_log_logger_set_map(&instance->logger, instance->map);
if (missing) { if (missing) {
lv2_log_error(&instance->logger, "Missing feature <%s>\n", missing); lv2_log_error(&instance->logger, "Missing feature <%s>\n", missing);
free(instance); goto err_urid;
return NULL;
} }
instance->uri_midi_MidiEvent = instance->map->map(instance->map->handle, LV2_MIDI__MidiEvent); 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; (void)features;
#endif #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); plugin_set_sample_rate(&instance->p, sample_rate);
size_t req = plugin_mem_req(&instance->p); size_t 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) {
plugin_fini(&instance->p); lv2_log_error(&instance->logger, "Not enough memory\n");
return NULL; goto err_mem;
} }
plugin_mem_set(&instance->p, instance->mem); plugin_mem_set(&instance->p, instance->mem);
} else } else
@ -161,6 +186,15 @@ static LV2_Handle instantiate(const struct LV2_Descriptor * descriptor, double s
#endif #endif
return instance; 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) { 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); plugin_fini(&i->p);
if (i->mem) if (i->mem)
free(i->mem); free(i->mem);
free(i->bundle_path);
free(instance); free(instance);
} }
@ -307,6 +342,7 @@ LV2_SYMBOL_EXPORT const LV2_Descriptor * lv2_descriptor(uint32_t index) {
#ifdef DATA_UI #ifdef DATA_UI
typedef struct { typedef struct {
plugin_ui * ui; plugin_ui * ui;
char * bundle_path;
# if DATA_PRODUCT_CONTROL_INPUTS_N > 0 # if DATA_PRODUCT_CONTROL_INPUTS_N > 0
LV2UI_Write_Function write; LV2UI_Write_Function write;
LV2UI_Controller controller; LV2UI_Controller controller;
@ -320,6 +356,11 @@ typedef struct {
+ DATA_PRODUCT_MIDI_OUTPUTS_N ) + DATA_PRODUCT_MIDI_OUTPUTS_N )
# define CONTROL_OUTPUT_INDEX_OFFSET (CONTROL_INPUT_INDEX_OFFSET + DATA_PRODUCT_CONTROL_INPUTS_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 # if DATA_PRODUCT_CONTROL_INPUTS_N > 0
static void ui_set_parameter_cb(void *handle, size_t index, float value) { static void ui_set_parameter_cb(void *handle, size_t index, float value) {
ui_instance *instance = (ui_instance *)handle; 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)); ui_instance *instance = malloc(sizeof(ui_instance));
if (instance == NULL) { if (instance == NULL)
*widget = NULL; goto err_instance;
return NULL;
}
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 # if DATA_PRODUCT_CONTROL_INPUTS_N > 0
instance->write = write_function; instance->write = write_function;
instance->controller = controller; 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 # else
(void)write_function; (void)write_function;
(void)controller; (void)controller;
instance->ui = plugin_ui_create(has_parent, parent, NULL);
# endif # endif
if (instance->ui == NULL) { instance->ui = plugin_ui_create(has_parent, parent, &cbs);
free(instance); if (instance->ui == NULL)
*widget = NULL; goto err_create;
return NULL;
}
*widget = instance->ui->widget; *widget = instance->ui->widget;
return instance; 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) { static void ui_cleanup(LV2UI_Handle handle) {
ui_instance *instance = (ui_instance *)handle; ui_instance *instance = (ui_instance *)handle;
plugin_ui_free(instance->ui); plugin_ui_free(instance->ui);
free(instance->bundle_path);
free(instance); free(instance);
} }

View File

@ -18,17 +18,21 @@
* File author: Stefano D'Angelo, Paolo Marrone * File author: Stefano D'Angelo, Paolo Marrone
*/ */
#include <stddef.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <stdint.h>
#include <math.h>
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"
#include "vst3_c_api.h"
#pragma GCC diagnostic pop
typedef struct { 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); void (*set_parameter)(void *handle, size_t index, float value);
} plugin_ui_callbacks; } plugin_ui_callbacks;
@ -38,6 +42,17 @@ typedef struct {
# include "plugin_ui.h" # include "plugin_ui.h"
#endif #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__) #if defined(__i386__) || defined(__x86_64__)
#include <xmmintrin.h> #include <xmmintrin.h>
#include <pmmintrin.h> #include <pmmintrin.h>
@ -54,11 +69,6 @@ typedef struct {
# define TRACE(...) /* do nothing */ # define TRACE(...) /* do nothing */
#endif #endif
#if defined(__i386__) || defined(__x86_64__)
#include <xmmintrin.h>
#include <pmmintrin.h>
#endif
#ifdef DATA_UI #ifdef DATA_UI
# ifdef __linux__ # ifdef __linux__
// Why generate the C interface when you can just not give a fuck? Thank you Steinberg! // 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
#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) { static double clamp(double x, double m, double M) {
return x < m ? m : (x > M ? M : x); 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))); return pluginRelease((pluginInstance *)((char *)thisInterface - offsetof(pluginInstance, vtblIComponent)));
} }
//XXX
static Steinberg_tresult pluginInitialize(void *thisInterface, struct Steinberg_FUnknown *context) { static Steinberg_tresult pluginInitialize(void *thisInterface, struct Steinberg_FUnknown *context) {
TRACE("plugin initialize\n"); TRACE("plugin initialize\n");
pluginInstance *p = (pluginInstance *)((char *)thisInterface - offsetof(pluginInstance, vtblIComponent)); pluginInstance *p = (pluginInstance *)((char *)thisInterface - offsetof(pluginInstance, vtblIComponent));
if (p->context != NULL) if (p->context != NULL)
return Steinberg_kResultFalse; return Steinberg_kResultFalse;
p->context = context; p->context = context;
//XXX
plugin_init(&p->p); plugin_init(&p->p);
#if DATA_PRODUCT_PARAMETERS_N > 0 #if DATA_PRODUCT_PARAMETERS_N > 0
for (size_t i = 0; i < DATA_PRODUCT_PARAMETERS_N; i++) { 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/runtime.h>
# include <objc/message.h> # include <objc/message.h>
# elif defined(_WIN32) || defined(__CYGWIN__)
# include <windows.h>
# endif # endif
typedef struct plugView { typedef struct plugView {
@ -1072,6 +1097,8 @@ static void plugViewTimerCb(HWND p1, UINT p2, UINT_PTR p3, DWORD p4) {
} }
# endif # endif
//XXX
static Steinberg_tresult plugViewAttached(void* thisInterface, void* parent, Steinberg_FIDString type) { 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 // GUI needs to be created here, see https://forums.steinberg.net/t/vst-and-hidpi/201916/3
TRACE("plugView attached %p\n", thisInterface); 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)); plugView *v = (plugView *)((char *)thisInterface - offsetof(plugView, vtblIPlugView));
if (v->ui) if (v->ui)
return Steinberg_kInvalidArgument; return Steinberg_kInvalidArgument;
# if DATA_PRODUCT_PARAMETERS_N > 0
plugin_ui_callbacks cbs = { plugin_ui_callbacks cbs = {
/* .handle = */ (void *)v, /* .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 /* .set_parameter = */ plugViewSetParameterCb
};
v->ui = plugin_ui_create(1, parent, &cbs);
# else # else
v->ui = plugin_ui_create(1, parent, NULL); /* .set_parameter = */ NULL
# endif # endif
};
//XXX
v->ui = plugin_ui_create(1, parent, &cbs);
if (!v->ui) if (!v->ui)
return Steinberg_kResultFalse; return Steinberg_kResultFalse;
# ifdef __linux__ # ifdef __linux__
v->display = XOpenDisplay(NULL); v->display = XOpenDisplay(NULL);
if (v->display == NULL) { if (v->display == NULL) {
@ -2062,25 +2095,88 @@ Steinberg_IPluginFactory * GetPluginFactory(void) {
return (Steinberg_IPluginFactory *)&factory; return (Steinberg_IPluginFactory *)&factory;
} }
#if !defined(_WIN32) && !defined(__CYGWIN__) static int refs = 0;
# if defined(__APPLE__)
# define ENTRY bundleEntry static char exit() {
# define EXIT bundleExit 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 bundleEntry(CFBundleRef ref) {
(void)ref;
if (refs == 0) {
//XXX
}
refs++;
return 1;
}
EXPORT
char bundleExit(void) {
return exit();
}
#else #else
# define ENTRY ModuleEntry
# define EXIT ModuleExit
# endif
EXPORT EXPORT
char ENTRY(void *handle) { char ModuleEntry(void *handle) {
(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; return 1;
err_datadir:
free(bindir);
err_bindir:
free(file);
return 0;
} }
EXPORT EXPORT
char EXIT(void) { char ModuleExit(void) {
return 1; return exit();
} }
#endif #endif

View File

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