diff --git a/templates/lv2-make/Makefile b/templates/lv2-make/Makefile index 399c810..6806cb8 100644 --- a/templates/lv2-make/Makefile +++ b/templates/lv2-make/Makefile @@ -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} diff --git a/templates/lv2/data/manifest.ttl.in b/templates/lv2/data/manifest.ttl.in index 8a8d772..4dfa814 100644 --- a/templates/lv2/data/manifest.ttl.in +++ b/templates/lv2/data/manifest.ttl.in @@ -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@> . +{{?}} diff --git a/templates/lv2/src/data.h b/templates/lv2/src/data.h index 6916f6a..158f1e7 100644 --- a/templates/lv2/src/data.h +++ b/templates/lv2/src/data.h @@ -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))}}" +{{?}} diff --git a/templates/lv2/src/lv2.c b/templates/lv2/src/lv2.c index 9a4d87c..091aa7a 100644 --- a/templates/lv2/src/lv2.c +++ b/templates/lv2/src/lv2.c @@ -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 @@ -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 diff --git a/templates/lv2/tibia-index.js b/templates/lv2/tibia-index.js index 8c630a0..d2ec15f 100644 --- a/templates/lv2/tibia-index.js +++ b/templates/lv2/tibia-index.js @@ -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#" } ], diff --git a/templates/vst3/src/vst3.c b/templates/vst3/src/vst3.c index 6550373..4268dab 100644 --- a/templates/vst3/src/vst3.c +++ b/templates/vst3/src/vst3.c @@ -50,6 +50,69 @@ #include #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 = { diff --git a/test/lv2.json b/test/lv2.json index 4f2d9bc..7220a3b 100644 --- a/test/lv2.json +++ b/test/lv2.json @@ -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" + } } }