vst3: dsp->ui communication using a separated thread to handle allocation and notification
This commit is contained in:
parent
5f693136a8
commit
0aa6d08288
@ -68,7 +68,7 @@ BUILD_DATA_DIR := build/$(BUNDLE_DIR)/Contents/Resources
|
|||||||
|
|
||||||
-include $(MKINC_DIR)/vars-pre.mk
|
-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)
|
CFLAGS_ALL := -I$(DATA_DIR)/src -I$(PLUGIN_DIR) -I$(API_DIR) -fPIC -fvisibility=hidden $(CFLAGS_EXTRA) $(CFLAGS)
|
||||||
|
|
||||||
LDFLAGS :=
|
LDFLAGS :=
|
||||||
|
@ -270,4 +270,5 @@ static size_t parameterInfoToDataIndex[DATA_PRODUCT_PARAMETERS_N] = {
|
|||||||
|
|
||||||
{{?it.product.messaging}}
|
{{?it.product.messaging}}
|
||||||
#define DATA_MESSAGING 1
|
#define DATA_MESSAGING 1
|
||||||
|
#define DATA_MESSAGING_MAX {{=it.product.messaging.maxSize}}
|
||||||
{{?}}
|
{{?}}
|
@ -66,6 +66,10 @@
|
|||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef DATA_MESSAGING
|
||||||
|
# include <threads.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
// COM in C doc:
|
// COM in C doc:
|
||||||
// https://github.com/rubberduck-vba/Rubberduck/wiki/COM-in-plain-C
|
// https://github.com/rubberduck-vba/Rubberduck/wiki/COM-in-plain-C
|
||||||
// https://devblogs.microsoft.com/oldnewthing/20040205-00/?p=40733
|
// https://devblogs.microsoft.com/oldnewthing/20040205-00/?p=40733
|
||||||
@ -311,8 +315,18 @@ typedef struct pluginInstance {
|
|||||||
void * mem;
|
void * mem;
|
||||||
struct Steinberg_IBStream * state;
|
struct Steinberg_IBStream * state;
|
||||||
|
|
||||||
|
#ifdef DATA_MESSAGING
|
||||||
Steinberg_Vst_IConnectionPointVtbl *vtblIConnectionPoint;
|
Steinberg_Vst_IConnectionPointVtbl *vtblIConnectionPoint;
|
||||||
Steinberg_Vst_IConnectionPoint *connectedPoint;
|
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;
|
} pluginInstance;
|
||||||
|
|
||||||
static Steinberg_Vst_IComponentVtbl pluginVtblIComponent;
|
static Steinberg_Vst_IComponentVtbl pluginVtblIComponent;
|
||||||
@ -468,33 +482,13 @@ static Steinberg_Vst_IConnectionPointVtbl pluginVtblIConnectionPoint = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
# ifdef DATA_MESSAGING
|
# ifdef DATA_MESSAGING
|
||||||
|
// Assuming this gets called by audio thread only
|
||||||
static char send_to_ui (void *handle, const void *data, size_t bytes) {
|
static char send_to_ui (void *handle, const void *data, size_t bytes) {
|
||||||
pluginInstance *p = (pluginInstance *)handle;
|
pluginInstance *p = (pluginInstance *)handle;
|
||||||
|
|
||||||
Steinberg_Vst_IConnectionPointVtbl *ov = (Steinberg_Vst_IConnectionPointVtbl*) p->connectedPoint->lpVtbl;
|
memcpy(p->message_data, data, bytes);
|
||||||
|
p->message_data_size = bytes;
|
||||||
printf("gonna A ov: %p \n", (void*) ov);
|
p->message_data_tosend = 1;
|
||||||
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");
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
@ -514,6 +508,43 @@ static Steinberg_uint32 pluginIComponentRelease(void *thisInterface) {
|
|||||||
return pluginRelease((pluginInstance *)((char *)thisInterface - offsetof(pluginInstance, vtblIComponent)));
|
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) {
|
static Steinberg_tresult pluginInitialize(void *thisInterface, struct Steinberg_FUnknown *context) {
|
||||||
TRACE("plugin initialize\n");
|
TRACE("plugin initialize\n");
|
||||||
|
|
||||||
@ -570,6 +601,16 @@ static Steinberg_tresult pluginInitialize(void *thisInterface, struct Steinberg_
|
|||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
p->mem = NULL;
|
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;
|
return Steinberg_kResultOk;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -580,6 +621,15 @@ static Steinberg_tresult pluginTerminate(void *thisInterface) {
|
|||||||
plugin_fini(&p->p);
|
plugin_fini(&p->p);
|
||||||
if (p->mem)
|
if (p->mem)
|
||||||
free(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;
|
return Steinberg_kResultOk;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1196,6 +1246,17 @@ static Steinberg_tresult pluginProcess(void* thisInterface, struct Steinberg_Vst
|
|||||||
_MM_SET_DENORMALS_ZERO_MODE(denormals_zero_mode);
|
_MM_SET_DENORMALS_ZERO_MODE(denormals_zero_mode);
|
||||||
#endif
|
#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;
|
return Steinberg_kResultOk;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2476,6 +2537,25 @@ static Steinberg_tresult controllerIConnectionPointNotify(void* thisInterface, s
|
|||||||
(void)thisInterface;
|
(void)thisInterface;
|
||||||
(void)message;
|
(void)message;
|
||||||
printf("controllerIConnectionPointNotify \n"); fflush(stdout);
|
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;
|
return Steinberg_kResultOk;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2586,6 +2666,7 @@ static Steinberg_tresult factoryCreateInstance(void *thisInterface, Steinberg_FI
|
|||||||
#ifdef DATA_MESSAGING
|
#ifdef DATA_MESSAGING
|
||||||
p->vtblIConnectionPoint = &pluginVtblIConnectionPoint;
|
p->vtblIConnectionPoint = &pluginVtblIConnectionPoint;
|
||||||
p->connectedPoint = NULL;
|
p->connectedPoint = NULL;
|
||||||
|
p->message_data_tosend = 0;
|
||||||
#endif
|
#endif
|
||||||
*obj = p;
|
*obj = p;
|
||||||
TRACE(" instance: %p\n", (void *)p);
|
TRACE(" instance: %p\n", (void *)p);
|
||||||
|
@ -34,11 +34,30 @@ typedef struct plugin {
|
|||||||
float z1;
|
float z1;
|
||||||
float cutoff_k;
|
float cutoff_k;
|
||||||
float yz1;
|
float yz1;
|
||||||
|
|
||||||
|
int communication_state;
|
||||||
|
|
||||||
|
plugin_callbacks cbs;
|
||||||
} plugin;
|
} plugin;
|
||||||
|
|
||||||
|
#if TEMPLATE_SUPPORTS_MESSAGING
|
||||||
|
#include <stdio.h>
|
||||||
|
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) {
|
static void plugin_init(plugin *instance, const plugin_callbacks *cbs) {
|
||||||
(void)instance;
|
instance->cbs = *cbs;
|
||||||
(void)cbs;
|
instance->communication_state = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void plugin_fini(plugin *instance) {
|
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;
|
outputs[0][i] = instance->bypass ? inputs[0][i] : gain * y;
|
||||||
instance->yz1 = outputs[0][i];
|
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) {
|
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);
|
cbs->unlock(cbs->handle);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#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
|
|
||||||
|
@ -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");
|
printf("plugin_ui_receive_from_ui END \n");
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
#define RANDOM_DATA_SIZE 11
|
#define RANDOM_DATA_SIZE 11
|
||||||
const uint8_t random_data[RANDOM_DATA_SIZE] = { 2, 3, 4, 5, 6, 7, 8, 9, 6, 9, 6 };
|
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 WIDTH 600.0
|
||||||
#define HEIGHT 400.0
|
#define HEIGHT 400.0
|
||||||
|
Loading…
Reference in New Issue
Block a user