diff --git a/templates/vst3-make/Makefile b/templates/vst3-make/Makefile index 9a96121..94e2a4b 100644 --- a/templates/vst3-make/Makefile +++ b/templates/vst3-make/Makefile @@ -68,7 +68,7 @@ BUILD_DATA_DIR := build/$(BUNDLE_DIR)/Contents/Resources -include $(MKINC_DIR)/vars-pre.mk -CFLAGS := -O3 -Wall -Wpedantic -Wextra +CFLAGS := -O3 -std=c11 -Wall -Wpedantic -Wextra CFLAGS_ALL := -I$(DATA_DIR)/src -I$(PLUGIN_DIR) -I$(API_DIR) -fPIC -fvisibility=hidden $(CFLAGS_EXTRA) $(CFLAGS) LDFLAGS := diff --git a/templates/vst3/src/data.h b/templates/vst3/src/data.h index 7597f48..b8d1dbf 100644 --- a/templates/vst3/src/data.h +++ b/templates/vst3/src/data.h @@ -270,4 +270,5 @@ static size_t parameterInfoToDataIndex[DATA_PRODUCT_PARAMETERS_N] = { {{?it.product.messaging}} #define DATA_MESSAGING 1 +#define DATA_MESSAGING_MAX {{=it.product.messaging.maxSize}} {{?}} \ No newline at end of file diff --git a/templates/vst3/src/vst3.c b/templates/vst3/src/vst3.c index 663e932..6b297dd 100644 --- a/templates/vst3/src/vst3.c +++ b/templates/vst3/src/vst3.c @@ -66,6 +66,10 @@ # endif #endif +#ifdef DATA_MESSAGING +# include +#endif + // COM in C doc: // https://github.com/rubberduck-vba/Rubberduck/wiki/COM-in-plain-C // https://devblogs.microsoft.com/oldnewthing/20040205-00/?p=40733 @@ -311,8 +315,18 @@ typedef struct pluginInstance { void * mem; struct Steinberg_IBStream * state; +#ifdef DATA_MESSAGING Steinberg_Vst_IConnectionPointVtbl *vtblIConnectionPoint; Steinberg_Vst_IConnectionPoint *connectedPoint; + uint8_t message_data[DATA_MESSAGING_MAX]; + size_t message_data_size; + char message_data_tosend; // This is to tell message_thread to send data + thrd_t message_thread; + int message_flag; + mtx_t message_mutex; + cnd_t message_cond; + +#endif } pluginInstance; static Steinberg_Vst_IComponentVtbl pluginVtblIComponent; @@ -468,33 +482,13 @@ static Steinberg_Vst_IConnectionPointVtbl pluginVtblIConnectionPoint = { }; # ifdef DATA_MESSAGING +// Assuming this gets called by audio thread only static char send_to_ui (void *handle, const void *data, size_t bytes) { pluginInstance *p = (pluginInstance *)handle; - Steinberg_Vst_IConnectionPointVtbl *ov = (Steinberg_Vst_IConnectionPointVtbl*) p->connectedPoint->lpVtbl; - - printf("gonna A ov: %p \n", (void*) ov); - printf("gonna AA ctx: %p \n", (void*) p->context); - - Steinberg_Vst_IHostApplication *app = (Steinberg_Vst_IHostApplication*) p->context; - Steinberg_Vst_IMessage *msg = NULL; - app->lpVtbl->createInstance(app, (char*) Steinberg_Vst_IMessage_iid, (char*) Steinberg_Vst_IMessage_iid, (void**)&msg); - - printf("gonna AB msgp: %p \n", (void*) msg); - - printf("gonna B \n"); - msg->lpVtbl->setMessageID(msg, "HelloMessage"); - printf("gonna C Message ID: %s \n", msg->lpVtbl->getMessageID(msg)); - - Steinberg_Vst_IAttributeList *alist = msg->lpVtbl->getAttributes(msg); - - printf("gonna CA alist %p \n", (void*) alist); - - alist->lpVtbl->setBinary(alist, "yoyoyo", data, bytes); - - ov->notify(p->connectedPoint, msg); - printf("gonna Z \n"); - + memcpy(p->message_data, data, bytes); + p->message_data_size = bytes; + p->message_data_tosend = 1; return 0; } # endif @@ -514,6 +508,43 @@ static Steinberg_uint32 pluginIComponentRelease(void *thisInterface) { return pluginRelease((pluginInstance *)((char *)thisInterface - offsetof(pluginInstance, vtblIComponent))); } +int message_thread_f(void *arg) { + pluginInstance *p = (pluginInstance *) arg; + + while (1) { + mtx_lock(&p->message_mutex); + + while (p->message_flag == 0) { + cnd_wait(&p->message_cond, &p->message_mutex); + } + + if (p->message_flag == 1) { + printf("message_thread_f: got flag 1...\n"); + + Steinberg_Vst_IConnectionPointVtbl *ov = (Steinberg_Vst_IConnectionPointVtbl*) p->connectedPoint->lpVtbl; + Steinberg_Vst_IHostApplication *app = (Steinberg_Vst_IHostApplication*) p->context; + Steinberg_Vst_IMessage *msg = NULL; + + app->lpVtbl->createInstance(app, (char*) Steinberg_Vst_IMessage_iid, (char*) Steinberg_Vst_IMessage_iid, (void**)&msg); + msg->lpVtbl->setMessageID(msg, "HelloMessage"); + Steinberg_Vst_IAttributeList *alist = msg->lpVtbl->getAttributes(msg); + alist->lpVtbl->setBinary(alist, "yoyoyo", p->message_data, p->message_data_size); + ov->notify(p->connectedPoint, msg); + + p->message_flag = 0; + + } else if (p->message_flag == 2) { + printf("message_thread_f: got flag 2: Exiting.\n"); + mtx_unlock(&p->message_mutex); + break; + } + + mtx_unlock(&p->message_mutex); + } + + return 0; +} + static Steinberg_tresult pluginInitialize(void *thisInterface, struct Steinberg_FUnknown *context) { TRACE("plugin initialize\n"); @@ -570,6 +601,16 @@ static Steinberg_tresult pluginInitialize(void *thisInterface, struct Steinberg_ # endif #endif p->mem = NULL; + +#ifdef DATA_MESSAGING + mtx_init(&p->message_mutex, mtx_plain); + cnd_init(&p->message_cond); + if (thrd_create(&p->message_thread, message_thread_f, p) != thrd_success) { + fprintf(stderr, "Failed to create message_thread\n"); + return Steinberg_kResultFalse; + } +#endif + return Steinberg_kResultOk; } @@ -580,6 +621,15 @@ static Steinberg_tresult pluginTerminate(void *thisInterface) { plugin_fini(&p->p); if (p->mem) free(p->mem); + + mtx_lock(&p->message_mutex); + p->message_flag = 2; + cnd_signal(&p->message_cond); + mtx_unlock(&p->message_mutex); + thrd_join(p->message_thread, NULL); + mtx_destroy(&p->message_mutex); + cnd_destroy(&p->message_cond); + return Steinberg_kResultOk; } @@ -1196,6 +1246,17 @@ static Steinberg_tresult pluginProcess(void* thisInterface, struct Steinberg_Vst _MM_SET_DENORMALS_ZERO_MODE(denormals_zero_mode); #endif +#ifdef DATA_MESSAGING + if (p->message_data_tosend) { // message_data_tosend is manipulated by audio thread only + if (mtx_trylock(&p->message_mutex) == thrd_success) { + p->message_flag = 1; + cnd_signal(&p->message_cond); + mtx_unlock(&p->message_mutex); + p->message_data_tosend = 0; + } + } +#endif + return Steinberg_kResultOk; } @@ -2476,6 +2537,25 @@ static Steinberg_tresult controllerIConnectionPointNotify(void* thisInterface, s (void)thisInterface; (void)message; printf("controllerIConnectionPointNotify \n"); fflush(stdout); + + controller *c = (controller *)((char *)thisInterface - offsetof(controller, vtblIConnectionPoint)); + + printf("controllerIConnectionPointNotify A \n"); fflush(stdout); + printf("controllerIConnectionPointNotify B Message ID: %s\n", message->lpVtbl->getMessageID(message)); fflush(stdout); + + Steinberg_Vst_IAttributeList *alist = message->lpVtbl->getAttributes(message); + printf("controllerIConnectionPointNotify C alist: %p\n", (void*) alist); fflush(stdout); + + const void *data = NULL; + unsigned int size = 0; + alist->lpVtbl->getBinary(alist, "yoyoyo", &data, &size); + + // This is tmp, TODO: fix + for (size_t i = 0; i < c->viewsCount; i++) { + plugView *v = c->views[i]; + plugin_ui_receive_from_dsp(v->ui, data, size); + } + return Steinberg_kResultOk; } @@ -2586,6 +2666,7 @@ static Steinberg_tresult factoryCreateInstance(void *thisInterface, Steinberg_FI #ifdef DATA_MESSAGING p->vtblIConnectionPoint = &pluginVtblIConnectionPoint; p->connectedPoint = NULL; + p->message_data_tosend = 0; #endif *obj = p; TRACE(" instance: %p\n", (void *)p); diff --git a/test/plugin.h b/test/plugin.h index 4274ca1..6a3ce73 100644 --- a/test/plugin.h +++ b/test/plugin.h @@ -34,11 +34,30 @@ typedef struct plugin { float z1; float cutoff_k; float yz1; + + int communication_state; + + plugin_callbacks cbs; } plugin; +#if TEMPLATE_SUPPORTS_MESSAGING +#include +static void plugin_receive_from_ui (plugin *instance, const void *data, size_t bytes) { + printf("plugin_receive_from_ui %ld bytes at %p: \n", bytes, data); + for (size_t i = 0; i < bytes; i++) { + printf("%d ", ((uint8_t*) data)[i]); + } + instance->communication_state = 1; + printf("\nplugin_receive_from_ui END - going to reply at next proc \n"); +} +#define RANDOM_DATA_UI_SIZE 13 +const uint8_t random_ui_data[RANDOM_DATA_UI_SIZE] = { 66, 69, 2, 3, 4, 5, 6, 7, 8, 9, 6, 9, 6 }; +#endif + + static void plugin_init(plugin *instance, const plugin_callbacks *cbs) { - (void)instance; - (void)cbs; + instance->cbs = *cbs; + instance->communication_state = 0; } static void plugin_fini(plugin *instance) { @@ -111,6 +130,12 @@ static void plugin_process(plugin *instance, const float **inputs, float **outpu outputs[0][i] = instance->bypass ? inputs[0][i] : gain * y; instance->yz1 = outputs[0][i]; } +#ifdef TEMPLATE_SUPPORTS_MESSAGING + if (instance->communication_state == 1) { + instance->cbs.send_to_ui(instance->cbs.handle, random_ui_data, RANDOM_DATA_UI_SIZE); + instance->communication_state = 2; + } +#endif } static void plugin_midi_msg_in(plugin *instance, size_t index, const uint8_t * data) { @@ -179,15 +204,3 @@ static int plugin_state_load(const plugin_state_callbacks *cbs, float cur_sample cbs->unlock(cbs->handle); return 0; } - -#include -#if TEMPLATE_SUPPORTS_MESSAGING -static void plugin_receive_from_ui (plugin *instance, const void *data, size_t bytes) { - (void) instance; - printf("plugin_receive_from_ui %ld bytes at %p: \n", bytes, data); - for (size_t i = 0; i < bytes; i++) { - printf("%d ", ((uint8_t*) data)[i]); - } - printf("plugin_receive_from_ui END \n"); -} -#endif diff --git a/test/plugin_ui.h b/test/plugin_ui.h index f37acbf..24a398f 100644 --- a/test/plugin_ui.h +++ b/test/plugin_ui.h @@ -47,9 +47,9 @@ static void plugin_ui_receive_from_dsp (plugin_ui *instance, const void *data, s } printf("plugin_ui_receive_from_ui END \n"); } -#endif #define RANDOM_DATA_SIZE 11 const uint8_t random_data[RANDOM_DATA_SIZE] = { 2, 3, 4, 5, 6, 7, 8, 9, 6, 9, 6 }; +#endif #define WIDTH 600.0 #define HEIGHT 400.0