vst3 linux gui should be ok now
This commit is contained in:
parent
001bfe11da
commit
94ab135050
@ -26,10 +26,10 @@ typedef struct {
|
|||||||
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;
|
||||||
|
|
||||||
#define TEMPLATE_HAS_UI
|
|
||||||
#include "data.h"
|
#include "data.h"
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
#pragma GCC diagnostic ignored "-Wunused-function"
|
#pragma GCC diagnostic ignored "-Wunused-function"
|
||||||
|
#define TEMPLATE_HAS_UI
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
|
|
||||||
|
@ -27,6 +27,11 @@
|
|||||||
#include "vst3_c_api.h"
|
#include "vst3_c_api.h"
|
||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
void * handle;
|
||||||
|
void (*set_parameter)(void *handle, size_t index, float value);
|
||||||
|
} plugin_ui_callbacks;
|
||||||
|
|
||||||
#include "data.h"
|
#include "data.h"
|
||||||
#define TEMPLATE_HAS_UI
|
#define TEMPLATE_HAS_UI
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
@ -837,6 +842,27 @@ static Steinberg_Vst_IProcessContextRequirementsVtbl pluginVtblIProcessContextRe
|
|||||||
/* .getProcessContextRequirements = */ pluginGetProcessContextRequirements
|
/* .getProcessContextRequirements = */ pluginGetProcessContextRequirements
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct plugView plugView;
|
||||||
|
|
||||||
|
typedef struct controller {
|
||||||
|
Steinberg_Vst_IEditControllerVtbl * vtblIEditController;
|
||||||
|
Steinberg_Vst_IMidiMappingVtbl * vtblIMidiMapping;
|
||||||
|
#ifdef PLUGIN_UI
|
||||||
|
//Steinberg_Vst_IConnectionPointVtbl * vtblIConnectionPoint;
|
||||||
|
#endif
|
||||||
|
Steinberg_uint32 refs;
|
||||||
|
Steinberg_FUnknown * context;
|
||||||
|
#if DATA_PRODUCT_PARAMETERS_N + DATA_PRODUCT_BUSES_MIDI_INPUT_N > 0
|
||||||
|
double parameters[DATA_PRODUCT_PARAMETERS_N + 3 * DATA_PRODUCT_BUSES_MIDI_INPUT_N];
|
||||||
|
#endif
|
||||||
|
struct Steinberg_Vst_IComponentHandler * componentHandler;
|
||||||
|
#ifdef PLUGIN_UI
|
||||||
|
plugView ** views;
|
||||||
|
size_t viewsCount;
|
||||||
|
#endif
|
||||||
|
} controller;
|
||||||
|
|
||||||
|
static Steinberg_Vst_IEditControllerVtbl controllerVtblIEditController;
|
||||||
#ifdef PLUGIN_UI
|
#ifdef PLUGIN_UI
|
||||||
# ifdef __linux__
|
# ifdef __linux__
|
||||||
# include <X11/Xlib.h>
|
# include <X11/Xlib.h>
|
||||||
@ -910,6 +936,7 @@ typedef struct plugView {
|
|||||||
Steinberg_uint32 refs;
|
Steinberg_uint32 refs;
|
||||||
Steinberg_IPlugFrame * frame;
|
Steinberg_IPlugFrame * frame;
|
||||||
plugin_ui * ui;
|
plugin_ui * ui;
|
||||||
|
controller * ctrl;
|
||||||
# ifdef __linux__
|
# ifdef __linux__
|
||||||
Steinberg_IRunLoop * runLoop;
|
Steinberg_IRunLoop * runLoop;
|
||||||
timerHandler timer;
|
timerHandler timer;
|
||||||
@ -917,6 +944,8 @@ typedef struct plugView {
|
|||||||
# endif
|
# endif
|
||||||
} plugView;
|
} plugView;
|
||||||
|
|
||||||
|
static Steinberg_tresult plugViewRemoved(void* thisInterface);
|
||||||
|
|
||||||
static Steinberg_tresult plugViewQueryInterface(void *thisInterface, const Steinberg_TUID iid, void ** obj) {
|
static Steinberg_tresult plugViewQueryInterface(void *thisInterface, const Steinberg_TUID iid, void ** obj) {
|
||||||
TRACE("plugView queryInterface %p\n", thisInterface);
|
TRACE("plugView queryInterface %p\n", thisInterface);
|
||||||
// Same as above (pluginQueryInterface)
|
// Same as above (pluginQueryInterface)
|
||||||
@ -951,9 +980,13 @@ static Steinberg_uint32 plugViewRelease(void *thisInterface) {
|
|||||||
v->refs--;
|
v->refs--;
|
||||||
if (v->refs == 0) {
|
if (v->refs == 0) {
|
||||||
TRACE(" free %p\n", (void *)v);
|
TRACE(" free %p\n", (void *)v);
|
||||||
# ifdef __linux__
|
if (v->ui)
|
||||||
XCloseDisplay(v->display);
|
plugViewRemoved(thisInterface);
|
||||||
# endif
|
for (size_t i = 0; i < v->ctrl->viewsCount; i++)
|
||||||
|
if (v->ctrl->views[i] == v) {
|
||||||
|
v->ctrl->views[i] = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
free(v);
|
free(v);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -977,17 +1010,67 @@ static Steinberg_tresult plugViewIsPlatformTypeSupported(void* thisInterface, St
|
|||||||
# endif
|
# endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# if DATA_PRODUCT_PARAMETERS_N > 0
|
||||||
|
static void plugViewUpdateParameter(plugView *view, size_t index) {
|
||||||
|
if (view->ui)
|
||||||
|
plugin_ui_set_parameter(view->ui, parameterData[index].index, view->ctrl->parameters[index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void plugViewUpdateAllParameters(plugView *view) {
|
||||||
|
if (view->ui == NULL)
|
||||||
|
return;
|
||||||
|
for (size_t i = 0; i < DATA_PRODUCT_PARAMETERS_N; i++)
|
||||||
|
plugin_ui_set_parameter(view->ui, parameterData[i].index, view->ctrl->parameters[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void plugViewSetParameterCb(void *handle, size_t index, float value) {
|
||||||
|
plugView *v = (plugView *)handle;
|
||||||
|
# ifdef DATA_PARAM_LATENCY_INDEX
|
||||||
|
index = index >= DATA_PARAM_LATENCY_INDEX ? index - 1 : index;
|
||||||
|
# endif
|
||||||
|
v->ctrl->componentHandler->lpVtbl->beginEdit(v->ctrl->componentHandler, parameterInfo[index].id);
|
||||||
|
v->ctrl->componentHandler->lpVtbl->performEdit(v->ctrl->componentHandler, parameterInfo[index].id, parameterUnmap(index, parameterAdjust(index, value)));
|
||||||
|
v->ctrl->componentHandler->lpVtbl->endEdit(v->ctrl->componentHandler, parameterInfo[index].id);
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
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
|
||||||
TRACE("plugView attached %p\n", thisInterface);
|
TRACE("plugView attached %p\n", thisInterface);
|
||||||
|
|
||||||
|
if (plugViewIsPlatformTypeSupported(thisInterface, type) != Steinberg_kResultOk)
|
||||||
|
return Steinberg_kInvalidArgument;
|
||||||
|
|
||||||
plugView *v = (plugView *)((char *)thisInterface - offsetof(plugView, vtblIPlugView));
|
plugView *v = (plugView *)((char *)thisInterface - offsetof(plugView, vtblIPlugView));
|
||||||
v->ui = plugin_ui_create(1, parent);
|
if (v->ui)
|
||||||
|
return Steinberg_kInvalidArgument;
|
||||||
|
# if DATA_PRODUCT_PARAMETERS_N > 0
|
||||||
|
plugin_ui_callbacks cbs = {
|
||||||
|
/* .handle = */ (void *)v,
|
||||||
|
/* .set_parameter = */ plugViewSetParameterCb
|
||||||
|
};
|
||||||
|
v->ui = plugin_ui_create(1, parent, &cbs);
|
||||||
|
# else
|
||||||
|
v->ui = plugin_ui_create(1, parent, NULL);
|
||||||
|
# endif
|
||||||
if (!v->ui)
|
if (!v->ui)
|
||||||
return Steinberg_kResultFalse;
|
return Steinberg_kResultFalse;
|
||||||
# ifdef __linux
|
# ifdef __linux__
|
||||||
if (v->runLoop->lpVtbl->registerTimer(v->runLoop, (struct Steinberg_ITimerHandler *)&v->timer, 20) != Steinberg_kResultOk) {
|
v->display = XOpenDisplay(NULL);
|
||||||
|
if (v->display == NULL) {
|
||||||
plugin_ui_free(v->ui);
|
plugin_ui_free(v->ui);
|
||||||
|
v->ui = NULL;
|
||||||
return Steinberg_kResultFalse;
|
return Steinberg_kResultFalse;
|
||||||
}
|
}
|
||||||
|
if (v->runLoop->lpVtbl->registerTimer(v->runLoop, (struct Steinberg_ITimerHandler *)&v->timer, 20) != Steinberg_kResultOk) {
|
||||||
|
XCloseDisplay(v->display);
|
||||||
|
plugin_ui_free(v->ui);
|
||||||
|
v->ui = NULL;
|
||||||
|
return Steinberg_kResultFalse;
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
# if DATA_PRODUCT_PARAMETERS_N > 0
|
||||||
|
plugViewUpdateAllParameters(v);
|
||||||
# endif
|
# endif
|
||||||
return Steinberg_kResultTrue;
|
return Steinberg_kResultTrue;
|
||||||
}
|
}
|
||||||
@ -995,7 +1078,10 @@ static Steinberg_tresult plugViewAttached(void* thisInterface, void* parent, Ste
|
|||||||
static Steinberg_tresult plugViewRemoved(void* thisInterface) {
|
static Steinberg_tresult plugViewRemoved(void* thisInterface) {
|
||||||
TRACE("plugView removed %p\n", thisInterface);
|
TRACE("plugView removed %p\n", thisInterface);
|
||||||
plugView *v = (plugView *)((char *)thisInterface - offsetof(plugView, vtblIPlugView));
|
plugView *v = (plugView *)((char *)thisInterface - offsetof(plugView, vtblIPlugView));
|
||||||
|
# ifdef __linux__
|
||||||
v->runLoop->lpVtbl->unregisterTimer(v->runLoop, (struct Steinberg_ITimerHandler *)&v->timer);
|
v->runLoop->lpVtbl->unregisterTimer(v->runLoop, (struct Steinberg_ITimerHandler *)&v->timer);
|
||||||
|
XCloseDisplay(v->display);
|
||||||
|
# endif
|
||||||
plugin_ui_free(v->ui);
|
plugin_ui_free(v->ui);
|
||||||
v->ui = NULL;
|
v->ui = NULL;
|
||||||
return Steinberg_kResultTrue;
|
return Steinberg_kResultTrue;
|
||||||
@ -1077,6 +1163,8 @@ static Steinberg_tresult plugViewSetFrame(void* thisInterface, struct Steinberg_
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Steinberg_tresult plugViewCanResize(void* thisInterface) {
|
static Steinberg_tresult plugViewCanResize(void* thisInterface) {
|
||||||
|
(void) thisInterface;
|
||||||
|
|
||||||
TRACE("plugView canResize %p\n", thisInterface);
|
TRACE("plugView canResize %p\n", thisInterface);
|
||||||
# if DATA_UI_USER_RESIZABLE
|
# if DATA_UI_USER_RESIZABLE
|
||||||
return Steinberg_kResultTrue;
|
return Steinberg_kResultTrue;
|
||||||
@ -1121,21 +1209,6 @@ static Steinberg_IPlugViewVtbl plugViewVtblIPlugView = {
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct controller {
|
|
||||||
Steinberg_Vst_IEditControllerVtbl * vtblIEditController;
|
|
||||||
Steinberg_Vst_IMidiMappingVtbl * vtblIMidiMapping;
|
|
||||||
#ifdef PLUGIN_UI
|
|
||||||
//Steinberg_Vst_IConnectionPointVtbl * vtblIConnectionPoint;
|
|
||||||
#endif
|
|
||||||
Steinberg_uint32 refs;
|
|
||||||
Steinberg_FUnknown * context;
|
|
||||||
#if DATA_PRODUCT_PARAMETERS_N + DATA_PRODUCT_BUSES_MIDI_INPUT_N > 0
|
|
||||||
double parameters[DATA_PRODUCT_PARAMETERS_N + 3 * DATA_PRODUCT_BUSES_MIDI_INPUT_N];
|
|
||||||
#endif
|
|
||||||
struct Steinberg_Vst_IComponentHandler* componentHandler;
|
|
||||||
} controller;
|
|
||||||
|
|
||||||
static Steinberg_Vst_IEditControllerVtbl controllerVtblIEditController;
|
|
||||||
static Steinberg_Vst_IMidiMappingVtbl controllerVtblIMidiMapping;
|
static Steinberg_Vst_IMidiMappingVtbl controllerVtblIMidiMapping;
|
||||||
#ifdef PLUGIN_UI
|
#ifdef PLUGIN_UI
|
||||||
//static Steinberg_Vst_IConnectionPointVtbl controllerVtblIConnectionPoint;
|
//static Steinberg_Vst_IConnectionPointVtbl controllerVtblIConnectionPoint;
|
||||||
@ -1176,6 +1249,12 @@ static Steinberg_uint32 controllerRelease(controller *c) {
|
|||||||
c->refs--;
|
c->refs--;
|
||||||
if (c->refs == 0) {
|
if (c->refs == 0) {
|
||||||
TRACE(" free %p\n", (void *)c);
|
TRACE(" free %p\n", (void *)c);
|
||||||
|
if (c->views) {
|
||||||
|
for (size_t i = 0; i < c->viewsCount; i++)
|
||||||
|
if (c->views[i]) // this should not happen but you never know
|
||||||
|
plugViewRelease(c->views[i]);
|
||||||
|
free(c->views);
|
||||||
|
}
|
||||||
free(c);
|
free(c);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1415,6 +1494,11 @@ static Steinberg_tresult controllerSetParamNormalized(void* thisInterface, Stein
|
|||||||
return Steinberg_kResultFalse;
|
return Steinberg_kResultFalse;
|
||||||
controller *c = (controller *)((char *)thisInterface - offsetof(controller, vtblIEditController));
|
controller *c = (controller *)((char *)thisInterface - offsetof(controller, vtblIEditController));
|
||||||
c->parameters[pi] = pi >= DATA_PRODUCT_PARAMETERS_N ? value : parameterAdjust(pi, parameterMap(pi, value));
|
c->parameters[pi] = pi >= DATA_PRODUCT_PARAMETERS_N ? value : parameterAdjust(pi, parameterMap(pi, value));
|
||||||
|
# ifdef PLUGIN_UI
|
||||||
|
for (size_t i = 0; i < c->viewsCount; i++)
|
||||||
|
if(c->views[i])
|
||||||
|
plugViewUpdateParameter(c->views[i], pi);
|
||||||
|
# endif
|
||||||
return Steinberg_kResultTrue;
|
return Steinberg_kResultTrue;
|
||||||
#else
|
#else
|
||||||
(void)thisInterface;
|
(void)thisInterface;
|
||||||
@ -1438,8 +1522,6 @@ static Steinberg_tresult controllerSetComponentHandler(void* thisInterface, stru
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct Steinberg_IPlugView* controllerCreateView(void* thisInterface, Steinberg_FIDString name) {
|
static struct Steinberg_IPlugView* controllerCreateView(void* thisInterface, Steinberg_FIDString name) {
|
||||||
(void)thisInterface;
|
|
||||||
|
|
||||||
TRACE("controller create view %s\n", name);
|
TRACE("controller create view %s\n", name);
|
||||||
|
|
||||||
#ifdef PLUGIN_UI
|
#ifdef PLUGIN_UI
|
||||||
@ -1450,24 +1532,38 @@ static struct Steinberg_IPlugView* controllerCreateView(void* thisInterface, Ste
|
|||||||
if (view == NULL)
|
if (view == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
controller *c = (controller *)((char *)thisInterface - offsetof(controller, vtblIEditController));
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; i < c->viewsCount; c++)
|
||||||
|
if (c->views[i] == NULL)
|
||||||
|
break;
|
||||||
|
if (i == c->viewsCount) {
|
||||||
|
size_t cnt = i + 1;
|
||||||
|
plugView **views = realloc(c->views, cnt * sizeof(plugView **));
|
||||||
|
if (views == NULL) {
|
||||||
|
free(view);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
c->views = views;
|
||||||
|
c->viewsCount = cnt;
|
||||||
|
}
|
||||||
|
c->views[i] = view;
|
||||||
|
|
||||||
view->vtblIPlugView = &plugViewVtblIPlugView;
|
view->vtblIPlugView = &plugViewVtblIPlugView;
|
||||||
view->refs = 1;
|
view->refs = 1;
|
||||||
view->frame = NULL;
|
view->frame = NULL;
|
||||||
view->ui = NULL;
|
view->ui = NULL;
|
||||||
|
view->ctrl = c;
|
||||||
# ifdef __linux__
|
# ifdef __linux__
|
||||||
view->timer.vtblITimerHandler = &timerHandlerVtblITimerHandler;
|
view->timer.vtblITimerHandler = &timerHandlerVtblITimerHandler;
|
||||||
view->timer.refs = 1;
|
view->timer.refs = 1;
|
||||||
view->timer.cb = plugViewOnTimer;
|
view->timer.cb = plugViewOnTimer;
|
||||||
view->timer.data = view;
|
view->timer.data = view;
|
||||||
view->display = XOpenDisplay(NULL);
|
|
||||||
if (view->display == NULL) {
|
|
||||||
free(view);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
return (struct Steinberg_IPlugView *)view;
|
return (struct Steinberg_IPlugView *)view;
|
||||||
#else
|
#else
|
||||||
|
(void)thisInterface;
|
||||||
(void)name;
|
(void)name;
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -1726,6 +1822,8 @@ static Steinberg_tresult factoryCreateInstance(void *thisInterface, Steinberg_FI
|
|||||||
c->refs = 1;
|
c->refs = 1;
|
||||||
c->context = NULL;
|
c->context = NULL;
|
||||||
c->componentHandler = NULL;
|
c->componentHandler = NULL;
|
||||||
|
c->views = NULL;
|
||||||
|
c->viewsCount = 0;
|
||||||
*obj = c;
|
*obj = c;
|
||||||
TRACE(" instance: %p\n", (void *)c);
|
TRACE(" instance: %p\n", (void *)c);
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
Reference in New Issue
Block a user