make vst3 gui optional and beginning of lv2 gui

This commit is contained in:
Stefano D'Angelo 2024-05-08 15:08:11 +02:00
parent 6d31776d56
commit b529435748
7 changed files with 154 additions and 91 deletions

View File

@ -22,6 +22,7 @@ include vars.mk
ifeq ($(OS), Windows_NT)
DLL_SUFFIX = .dll
UI_TYPE = WindowsUI
LV2DIR = $(shell echo '${COMMONPROGRAMFILES}' | sed 's:\\:/:g')/LV2
LV2DIR_USER = $(shell echo '${APPDATA}' | sed 's:\\:/:g')/LV2
CC = gcc
@ -30,12 +31,14 @@ else
UNAME_S = $(shell uname -s)
ifeq ($(UNAME_S), Darwin)
DLL_SUFFIX = .dylib
UI_TYPE = CocoaUI
LV2DIR = /Library/Audio/Plug-Ins/LV2
LV2DIR_USER = ${HOME}/Library/Audio/Plug-Ins/LV2
CC = clang
CXX = clang++
else
DLL_SUFFIX = .so
UI_TYPE = X11UI
PREFIX = /usr/local
LV2DIR = ${PREFIX}/lib/lv2
LV2DIR_USER = ${HOME}/.lv2
@ -76,7 +79,7 @@ CXX_OBJS = $(addprefix build/obj/, $(notdir $(CXX_SRCS:.cpp=.o)))
all: build/${BUNDLE_DIR}/manifest.ttl build/${BUNDLE_DIR}/${DLL_FILE}
build/${BUNDLE_DIR}/manifest.ttl: ${DATA_DIR}/data/manifest.ttl.in | build/${BUNDLE_DIR}
cat $^ | sed s/@DLL_SUFFIX@/${DLL_SUFFIX}/g > $@
cat $^ | sed s/@DLL_SUFFIX@/${DLL_SUFFIX}/g | sed s/@UI_TYPE@/${UI_TYPE}/g > $@
ifeq ($(CXX_OBJS),)
build/${BUNDLE_DIR}/${DLL_FILE}: ${C_OBJS} | build/${BUNDLE_DIR}

View File

@ -25,6 +25,9 @@
lv2:optionalFeature log:log ;
{{?}}
lv2:optionalFeature lv2:hardRTCapable ;
{{?it.lv2.ui}}
ui:ui {{=it.tibia.lv2.ttlURI(it.lv2.ui.uri)}} ;
{{?}}
lv2:port [
{{~it.tibia.lv2.ports :p:i}}
{{?p.isBypass}}
@ -117,3 +120,9 @@
] .
{{?}}
{{~}}
{{?it.lv2.ui}}
{{=it.tibia.lv2.ttlURI(it.lv2.ui.uri)}}
a ui:@UI_TYPE@ ;
ui:binary <{{=it.product.bundleName}}@DLL_SUFFIX@> .
{{?}}

View File

@ -64,3 +64,7 @@ static uint32_t param_out_index[DATA_PRODUCT_CONTROL_OUTPUTS_N] = {
{{~it.tibia.lv2.ports.filter(x => x.type == "control" && x.direction == "output") :p}}{{=p.paramIndex}}, {{~}}
};
#endif
{{?it.lv2.ui}}
#define DATA_LV2_UI_URI "{{=it.tibia.CGetUTF8StringLiteral(it.tibia.lv2.expandURI(it.lv2.ui.uri))}}"
{{?}}

View File

@ -34,6 +34,9 @@
#include "lv2/midi/midi.h"
#include "lv2/urid/urid.h"
#endif
#ifdef PLUGIN_UI
#include "lv2/ui/ui.h"
#endif
#if defined(__i386__) || defined(__x86_64__)
#include <xmmintrin.h>
@ -288,3 +291,35 @@ static const LV2_Descriptor descriptor = {
LV2_SYMBOL_EXPORT const LV2_Descriptor * lv2_descriptor(uint32_t index) {
return index == 0 ? &descriptor : NULL;
}
#ifdef PLUGIN_UI
static LV2UI_Handle ui_instantiate(const LV2UI_Descriptor * descriptor, const char * plugin_uri, const char * bundle_path, LV2UI_Write_Function write_function, LV2UI_Controller controller, LV2UI_Widget * widget, const LV2_Feature * const * features) {
//TODO
*widget = NULL;
return NULL;
}
static void ui_cleanup(LV2UI_Handle handle) {
//TODO
}
static void ui_port_event(LV2UI_Handle handle, uint32_t port_index, uint32_t buffer_size, uint32_t format, const void * buffer) {
//TODO
}
static const void * extension_data(const char * uri) {
//TODO
}
static const LV2UI_Descriptor ui_descriptor = {
/* .URI = */ DATA_LV2_UI_URI,
/* .instantiate = */ ui_instantiate,
/* .cleanup = */ ui_cleanup,
/* .port_event = */ ui_port_event,
/* .extension_data = */ ui_extension_data
};
LV2_SYMBOL_EXPORT const LV2UI_Descriptor * lv2ui_descriptor(uint32_t index) {
return index == 0 ? &ui_descriptor : NULL;
}
#endif

View File

@ -34,6 +34,7 @@ module.exports = function (data, api, outputCommon, outputData) {
{ id: "pprops", uri: "http://lv2plug.in/ns/ext/port-props#" },
{ id: "rdf", uri: "http://www.w3.org/1999/02/22-rdf-syntax-ns#" },
{ id: "rdfs", uri: "http://www.w3.org/2000/01/rdf-schema#" },
{ id: "ui", uri: "http://lv2plug.in/ns/extensions/ui#" },
{ id: "units", uri: "http://lv2plug.in/ns/extensions/units#" },
{ id: "urid", uri: "http://lv2plug.in/ns/ext/urid#" }
],

View File

@ -50,6 +50,69 @@
#include <pmmintrin.h>
#endif
#ifdef PLUGIN_UI
# ifdef __linux__
// Why generate the C interface when you can just not give a fuck? Thank you Steinberg!
typedef struct Steinberg_ITimerHandlerVtbl
{
/* methods derived from "Steinberg_FUnknown": */
Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj);
Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface);
Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface);
/* methods derived from "Steinberg_ITimerHandler": */
Steinberg_tresult (SMTG_STDMETHODCALLTYPE* onTimer) (void* thisInterface);
} Steinberg_ITimerHandlerVtbl;
typedef struct Steinberg_ITimerHandler
{
struct Steinberg_ITimerHandlerVtbl* lpVtbl;
} Steinberg_ITimerHandler;
static const Steinberg_TUID Steinberg_ITimerHandler_iid = SMTG_INLINE_UID (0x10BDD94F, 0x41424774, 0x821FAD8F, 0xECA72CA9);
typedef struct Steinberg_IEventHandlerVtbl
{
/* methods derived from "Steinberg_FUnknown": */
Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj);
Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface);
Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface);
/* methods derived from "Steinberg_IEventHandler": */
Steinberg_tresult (SMTG_STDMETHODCALLTYPE* onFDIsSet) (void* thisInterface, int fd);
} Steinberg_IEventHandlerVtbl;
typedef struct Steinberg_IEventHandler
{
struct Steinberg_IEventHandlerVtbl* lpVtbl;
} Steinberg_IEventHandler;
static const Steinberg_TUID Steinberg_IEventHandler_iid = SMTG_INLINE_UID (0x561E65C9, 0x13A0496F, 0x813A2C35, 0x654D7983);
typedef struct Steinberg_IRunLoopVtbl
{
/* methods derived from "Steinberg_FUnknown": */
Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj);
Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface);
Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface);
/* methods derived from "Steinberg_IRunLoop": */
Steinberg_tresult (SMTG_STDMETHODCALLTYPE* registerEventHandler) (void* thisInterface, struct Steinberg_IEventHandler* handler, int fd);
Steinberg_tresult (SMTG_STDMETHODCALLTYPE* unregisterEventHandler) (void* thisInterface, struct Steinberg_IEventHandler* handler);
Steinberg_tresult (SMTG_STDMETHODCALLTYPE* registerTimer) (void* thisInterface, struct Steinberg_ITimerHandler* handler, uint64_t milliseconds);
Steinberg_tresult (SMTG_STDMETHODCALLTYPE* unregisterTimer) (void* thisInterface, struct Steinberg_ITimerHandler* handler);
} Steinberg_IRunLoopVtbl;
typedef struct Steinberg_IRunLoop
{
struct Steinberg_IRunLoopVtbl* lpVtbl;
} Steinberg_IRunLoop;
static const Steinberg_TUID Steinberg_IRunLoop_iid = SMTG_INLINE_UID (0x18C35366, 0x97764F1A, 0x9C5B8385, 0x7A871389);
# endif
#endif
static double clamp(double x, double m, double M) {
return x < m ? m : (x > M ? M : x);
}
@ -771,12 +834,12 @@ static Steinberg_Vst_IProcessContextRequirementsVtbl pluginVtblIProcessContextRe
/* .getProcessContextRequirements = */ pluginGetProcessContextRequirements
};
#ifdef PLUGIN_UI
typedef struct plugView {
Steinberg_IPlugViewVtbl * vtblIPlugView;
Steinberg_uint32 refs;
Steinberg_IPlugFrame * frame;
} plugView;
//static Steinberg_IPlugViewVtbl plugViewVtblIPlugView;
static Steinberg_tresult plugViewQueryInterface(void *thisInterface, const Steinberg_TUID iid, void ** obj) {
TRACE("plugView IEditController queryInterface %p\n", thisInterface);
@ -906,29 +969,32 @@ static Steinberg_tresult plugViewCheckSizeConstraint(void* thisInterface, struct
static Steinberg_IPlugViewVtbl plugViewVtblIPlugView = {
/* FUnknown */
/* .queryInterface = */ plugViewQueryInterface,
/* .addRef = */ plugViewAddRef,
/* .release = */ plugViewRelease,
/* .queryInterface = */ plugViewQueryInterface,
/* .addRef = */ plugViewAddRef,
/* .release = */ plugViewRelease,
/* IPlugView */
/* .isPlatformTypeSupported = */ plugViewIsPlatformTypeSupported,
/* .attached = */ plugViewAttached,
/* .removed = */ plugViewRemoved,
/* .onWheel = */ plugViewOnWheel,
/* .onKeyDown = */ plugViewOnKeyDown,
/* .onKeyUp = */ plugViewOnKeyUp,
/* .getSize = */ plugViewGetSize,
/* .onSize = */ plugViewOnSize,
/* .onFocus = */ plugViewOnFocus,
/* .setFrame = */ plugViewSetFrame,
/* .canResize = */ plugViewCanResize,
/* .checkSizeConstraint = */ plugViewCheckSizeConstraint
/* .isPlatformTypeSupported = */ plugViewIsPlatformTypeSupported,
/* .attached = */ plugViewAttached,
/* .removed = */ plugViewRemoved,
/* .onWheel = */ plugViewOnWheel,
/* .onKeyDown = */ plugViewOnKeyDown,
/* .onKeyUp = */ plugViewOnKeyUp,
/* .getSize = */ plugViewGetSize,
/* .onSize = */ plugViewOnSize,
/* .onFocus = */ plugViewOnFocus,
/* .setFrame = */ plugViewSetFrame,
/* .canResize = */ plugViewCanResize,
/* .checkSizeConstraint = */ plugViewCheckSizeConstraint
};
#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
@ -939,7 +1005,9 @@ typedef struct controller {
static Steinberg_Vst_IEditControllerVtbl controllerVtblIEditController;
static Steinberg_Vst_IMidiMappingVtbl controllerVtblIMidiMapping;
#ifdef PLUGIN_UI
//static Steinberg_Vst_IConnectionPointVtbl controllerVtblIConnectionPoint;
#endif
static Steinberg_tresult controllerQueryInterface(controller *c, const Steinberg_TUID iid, void ** obj) {
// Same as above (pluginQueryInterface)
@ -950,8 +1018,10 @@ static Steinberg_tresult controllerQueryInterface(controller *c, const Steinberg
offset = offsetof(controller, vtblIEditController);
else if (memcmp(iid, Steinberg_Vst_IMidiMapping_iid, sizeof(Steinberg_TUID)) == 0)
offset = offsetof(controller, vtblIMidiMapping);
#ifdef PLUGIN_UI
/*else if (memcmp(iid, Steinberg_Vst_IConnectionPoint_iid, sizeof(Steinberg_TUID)) == 0)
offset = offsetof(controller, vtblIConnectionPoint);*/
#endif
else {
TRACE(" not supported\n");
for (int i = 0; i < 16; i++)
@ -1240,6 +1310,7 @@ static struct Steinberg_IPlugView* controllerCreateView(void* thisInterface, Ste
TRACE("controller create view %s\n", name);
#ifdef PLUGIN_UI
if (strcmp(name, "editor"))
return NULL;
@ -1252,6 +1323,11 @@ static struct Steinberg_IPlugView* controllerCreateView(void* thisInterface, Ste
view->frame = NULL;
return (struct Steinberg_IPlugView *)view;
#else
(void)name;
return NULL;
#endif
}
static Steinberg_Vst_IEditControllerVtbl controllerVtblIEditController = {
@ -1331,7 +1407,8 @@ static Steinberg_Vst_IMidiMappingVtbl controllerVtblIMidiMapping = {
/* .getMidiControllerAssignment = */ controllerGetMidiControllerAssignment
};
#if 0
#ifdef PLUGIN_UI
# if 0
static Steinberg_tresult controllerIConnectionPointQueryInterface(void* thisInterface, const Steinberg_TUID iid, void** obj) {
TRACE("controller IConnectionPoint queryInterface %p\n", thisInterface);
return controllerQueryInterface((controller *)((char *)thisInterface - offsetof(controller, vtblIConnectionPoint)), iid, obj);
@ -1378,6 +1455,7 @@ static Steinberg_Vst_IConnectionPointVtbl controllerVtblIConnectionPoint = {
/* .disconnect = */ controllerIConnectionPointDisconnect,
/* .notify = */ controllerIConnectionPointNotify
};
# endif
#endif
static Steinberg_tresult factoryQueryInterface(void *thisInterface, const Steinberg_TUID iid, void ** obj) {
@ -1498,7 +1576,9 @@ static Steinberg_tresult factoryCreateInstance(void *thisInterface, Steinberg_FI
return Steinberg_kOutOfMemory;
c->vtblIEditController = &controllerVtblIEditController;
c->vtblIMidiMapping = &controllerVtblIMidiMapping;
#ifdef PLUGIN_UI
//c->vtblIConnectionPoint = &controllerVtblIConnectionPoint;
#endif
c->refs = 1;
c->context = NULL;
c->componentHandler = NULL;
@ -1583,85 +1663,13 @@ static Steinberg_tresult factoryGetClassInfoUnicode(void* thisInterface, Steinbe
return Steinberg_kResultOk;
}
#ifdef __linux__
// Why generate the C interface when you can just not give a fuck? Thank you Steinberg!
typedef struct Steinberg_ITimerHandlerVtbl
{
/* methods derived from "Steinberg_FUnknown": */
Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj);
Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface);
Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface);
/* methods derived from "Steinberg_ITimerHandler": */
Steinberg_tresult (SMTG_STDMETHODCALLTYPE* onTimer) (void* thisInterface);
} Steinberg_ITimerHandlerVtbl;
typedef struct Steinberg_ITimerHandler
{
struct Steinberg_ITimerHandlerVtbl* lpVtbl;
} Steinberg_ITimerHandler;
static const Steinberg_TUID Steinberg_ITimerHandler_iid = SMTG_INLINE_UID (0x10BDD94F, 0x41424774, 0x821FAD8F, 0xECA72CA9);
typedef struct Steinberg_IEventHandlerVtbl
{
/* methods derived from "Steinberg_FUnknown": */
Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj);
Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface);
Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface);
/* methods derived from "Steinberg_IEventHandler": */
Steinberg_tresult (SMTG_STDMETHODCALLTYPE* onFDIsSet) (void* thisInterface, int fd);
} Steinberg_IEventHandlerVtbl;
typedef struct Steinberg_IEventHandler
{
struct Steinberg_IEventHandlerVtbl* lpVtbl;
} Steinberg_IEventHandler;
static const Steinberg_TUID Steinberg_IEventHandler_iid = SMTG_INLINE_UID (0x561E65C9, 0x13A0496F, 0x813A2C35, 0x654D7983);
typedef struct Steinberg_IRunLoopVtbl
{
/* methods derived from "Steinberg_FUnknown": */
Steinberg_tresult (SMTG_STDMETHODCALLTYPE* queryInterface) (void* thisInterface, const Steinberg_TUID iid, void** obj);
Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* addRef) (void* thisInterface);
Steinberg_uint32 (SMTG_STDMETHODCALLTYPE* release) (void* thisInterface);
/* methods derived from "Steinberg_IRunLoop": */
Steinberg_tresult (SMTG_STDMETHODCALLTYPE* registerEventHandler) (void* thisInterface, struct Steinberg_IEventHandler* handler, int fd);
Steinberg_tresult (SMTG_STDMETHODCALLTYPE* unregisterEventHandler) (void* thisInterface, struct Steinberg_IEventHandler* handler);
Steinberg_tresult (SMTG_STDMETHODCALLTYPE* registerTimer) (void* thisInterface, struct Steinberg_ITimerHandler* handler, uint64_t milliseconds);
Steinberg_tresult (SMTG_STDMETHODCALLTYPE* unregisterTimer) (void* thisInterface, struct Steinberg_ITimerHandler* handler);
} Steinberg_IRunLoopVtbl;
typedef struct Steinberg_IRunLoop
{
struct Steinberg_IRunLoopVtbl* lpVtbl;
} Steinberg_IRunLoop;
static const Steinberg_TUID Steinberg_IRunLoop_iid = SMTG_INLINE_UID (0x18C35366, 0x97764F1A, 0x9C5B8385, 0x7A871389);
struct Steinberg_IRunLoop* IRunLoop = NULL;
#endif
static Steinberg_tresult factorySetHostContext(void* thisInterface, struct Steinberg_FUnknown* context) {
(void)thisInterface;
(void)context;
TRACE("factory set host context %p %p\n", thisInterface, context);
#ifdef __linux__
if (context->lpVtbl->queryInterface(context, Steinberg_IRunLoop_iid, (void **)&IRunLoop) == Steinberg_kResultOk) {
TRACE(" IRunLoop %p\n", IRunLoop);
context->lpVtbl->release(context);
} else
IRunLoop = NULL;
return Steinberg_kResultTrue;
#else
return Steinberg_kNotImplemented;
#endif
}
static Steinberg_IPluginFactory3Vtbl factoryVtbl = {

View File

@ -8,6 +8,9 @@
"types": [ "@lv2:AmplifierPlugin" ],
"version": "1.0",
"busSymbols": [ "input", "output", "midi_in", "midi_out" ],
"parameterSymbols": [ "gain", "delay", "cutoff", "enabled", "yz1" ]
"parameterSymbols": [ "gain", "delay", "cutoff", "enabled", "yz1" ],
"ui": {
"uri": "@example:tibia_test_ui"
}
}
}