diff --git a/dep/lglw/lglw_linux.c b/dep/lglw/lglw_linux.c index bb7974ac..90d988e1 100644 --- a/dep/lglw/lglw_linux.c +++ b/dep/lglw/lglw_linux.c @@ -24,7 +24,7 @@ * ---- info : This is part of the "lglw" package. * ---- * ---- created: 04Aug2018 - * ---- changed: 05Aug2018, 06Aug2018, 07Aug2018, 08Aug2018, 09Aug2018, 18Aug2018, 10Oct2018 + * ---- changed: 05Aug2018, 06Aug2018, 07Aug2018, 08Aug2018, 09Aug2018, 18Aug2018, 10Oct2018, 16Oct2018 * ---- * ---- */ @@ -35,6 +35,13 @@ #include #include +#include +#include +#include + +#include +#include + #define Dprintf if(0);else printf // #define Dprintf if(1);else printf @@ -57,18 +64,29 @@ // ---------------------------------------------------------------------------- structs and typedefs typedef struct lglw_int_s { - void *user_data; // arbitrary user data + void *user_data; // arbitrary user data + Display *xdsp; + XVisualInfo *vi; + Colormap cmap; + Window parent_xwnd; // created by host struct { lglw_vec2i_t size; + Window xwnd; } hidden; struct { lglw_vec2i_t size; + Window xwnd; + lglw_bool_t mapped; int32_t swap_interval; } win; + GLXContext ctx; + struct { + GLXContext ctx; + GLXDrawable drw; } prev; struct { @@ -142,27 +160,56 @@ static void loc_enable_dropfiles (lglw_int_t *lglw, lglw_bool_t _bEnable); static lglw_int_t *khook_lglw = NULL; // currently key-hooked lglw instance (one at a time) +// TODO: remove and/or improve debug logging for a debug build +// ---------------------------------------------------------------------------- lglw_log +static FILE *logfile; + +void lglw_log(const char *logData, ...) { + fprintf(logfile, logData); + fflush(logfile); +} + + +// TODO: remove, or maybe not in some specific use cases +// ---------------------------------------------------------------------------- xerror_log +static int xerror_handler(Display *display, XErrorEvent *error) { + char error_text[1024]; + XGetErrorText(display, error->error_code, error_text, 1024); + lglw_log("XERROR (%d): %s, %d, %d\n", error->error_code, error_text, error->request_code, error->minor_code); + return 0; +} + + // ---------------------------------------------------------------------------- lglw_init lglw_t lglw_init(int32_t _w, int32_t _h) { lglw_int_t *lglw = malloc(sizeof(lglw_int_t)); + // TODO: remove/improve + logfile = fopen("/home/cameron/src/VeeSeeVSTRack/other/log.txt", "w"); + XSetErrorHandler(xerror_handler); + if(NULL != lglw) { memset(lglw, 0, sizeof(lglw_int_t)); + lglw_log("lglw:lglw_init: 1\n"); if(_w <= 16) _w = LGLW_DEFAULT_HIDDEN_W; if(_h <= 16) _h = LGLW_DEFAULT_HIDDEN_H; + lglw_log("lglw:lglw_init: 2\n"); if(!loc_create_hidden_window(lglw, _w, _h)) { free(lglw); lglw = NULL; } + lglw_log("lglw:lglw_init: 3\n"); } + lglw_log("lglw:lglw_init: EXIT\n"); + return lglw; } @@ -173,8 +220,13 @@ void lglw_exit(lglw_t _lglw) { if(NULL != lglw) { + lglw_log("lglw:lglw_exit: 1\n"); + loc_destroy_hidden_window(lglw); + lglw_log("lglw:lglw_exit: 2\n"); + + fclose(logfile); free(lglw); } } @@ -186,6 +238,7 @@ void lglw_userdata_set(lglw_t _lglw, void *_userData) { if(NULL != lglw) { + lglw_log("lglw:lglw_userdata_set: 1\n"); lglw->user_data = _userData; } } @@ -196,6 +249,7 @@ void *lglw_userdata_get(lglw_t _lglw) { if(NULL != lglw) { + lglw_log("lglw:lglw_userdata_get: 1\n"); return lglw->user_data; } @@ -206,40 +260,232 @@ void *lglw_userdata_get(lglw_t _lglw) { // ---------------------------------------------------------------------------- loc_create_hidden_window static lglw_bool_t loc_create_hidden_window(lglw_int_t *lglw, int32_t _w, int32_t _h) { - // (todo) implement me + // TODO: compare to 'WindowClass' from Windows implementation + + lglw_log("lglw:loc_create_hidden_window: 1\n"); + XSetWindowAttributes swa; + int attrib[] = { GLX_RGBA, GLX_DOUBLEBUFFER, GLX_DEPTH_SIZE, 24, None }; + int screen; + + lglw_log("lglw:loc_create_hidden_window: 2\n"); + lglw->xdsp = XOpenDisplay(NULL); + screen = DefaultScreen(lglw->xdsp); + + lglw_log("lglw:loc_create_hidden_window: 3\n"); + lglw->vi = glXChooseVisual(lglw->xdsp, screen, attrib); + + lglw_log("lglw:loc_create_hidden_window: 4\n"); + if(NULL == lglw->vi) + { + lglw_log("[---] lglw: failed to find GLX Visual for hidden window\n"); + return LGLW_FALSE; + } + + lglw_log("lglw:loc_create_hidden_window: 5\n"); + lglw->ctx = glXCreateContext(lglw->xdsp, lglw->vi, None, True); + + lglw_log("lglw:loc_create_hidden_window: 6\n"); + if(NULL == lglw->ctx) + { + lglw_log("[---] lglw: failed to create GLX Context for hidden window\n"); + return LGLW_FALSE; + } + lglw_log("lglw:loc_create_hidden_window: 7\n"); + lglw->cmap = XCreateColormap(lglw->xdsp, RootWindow(lglw->xdsp, lglw->vi->screen), + lglw->vi->visual, AllocNone); + + lglw_log("lglw:loc_create_hidden_window: 8\n"); + swa.border_pixel = 0; + swa.colormap = lglw->cmap; + lglw->hidden.xwnd = XCreateWindow(lglw->xdsp, DefaultRootWindow(lglw->xdsp), + 0, 0, LGLW_DEFAULT_HIDDEN_W, LGLW_DEFAULT_HIDDEN_H, 0, CopyFromParent, InputOutput, + lglw->vi->visual, CWBorderPixel | CWColormap, &swa); + + lglw_log("lglw:loc_create_hidden_window: 9\n"); + XSetStandardProperties(lglw->xdsp, lglw->hidden.xwnd, "LGLW_hidden", "LGLW_hidden", None, NULL, 0, NULL); + XSync(lglw->xdsp, False); + + lglw_log("lglw:loc_create_hidden_window: EXIT\n"); lglw->hidden.size.x = _w; lglw->hidden.size.y = _h; - return LGLW_FALSE; + return LGLW_TRUE; } // ---------------------------------------------------------------------------- loc_destroy_hidden_window static void loc_destroy_hidden_window(lglw_int_t *lglw) { - // (todo) implement me + lglw_log("lglw:loc_destroy_hidden_window: 1\n"); + if(NULL != lglw->xdsp && NULL != lglw->ctx) + { + glXMakeCurrent(lglw->xdsp, None, NULL); + glXDestroyContext(lglw->xdsp, lglw->ctx); + } + lglw_log("lglw:loc_destroy_hidden_window: 2\n"); + if(NULL != lglw->xdsp && 0 != lglw->hidden.xwnd) XDestroyWindow(lglw->xdsp, lglw->hidden.xwnd); + lglw_log("lglw:loc_destroy_hidden_window: 3\n"); + if(NULL != lglw->xdsp && 0 != lglw->cmap) XFreeColormap(lglw->xdsp, lglw->cmap); + lglw_log("lglw:loc_destroy_hidden_window: 4\n"); + if(NULL != lglw->vi) XFree(lglw->vi); + + lglw_log("lglw:loc_destroy_hidden_window: 5\n"); + XSync(lglw->xdsp, False); + if(NULL != lglw->xdsp) XCloseDisplay(lglw->xdsp); +} + + +// ---------------------------------------------------------------------------- loc_setEventProc +// https://www.kvraudio.com/forum/viewtopic.php?t=387924 +// https://github.com/Ardour/ardour/blob/master/gtk2_ardour/linux_vst_gui_support.cc +// https://discourse.ardour.org/t/overtonedsp-plugins/90115/22 +// https://github.com/amsynth/amsynth/blob/4a87798e650c6d71d70274a961c9b8d98fc6da7e/src/amsynth_vst.cpp +// https://github.com/rsenn/eXT2/blob/7f00a09561ded8175ffed2f4912dad74e466a1c7/vstplugins/vstgui/vstgui.cpp +// https://github.com/COx2/DistortionFilter/blob/c6a34fb56b503a6e95bf0975e00f438bbf4ff52a/juce/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp + +// Very simple function to test _XEventProc is properly called +void loc_eventProc(void *xevent) { + // lglw_log("XEventProc"); + printf("XEventProc\n"); +} + +// Pulled from the Renoise 64-bit callback example +// Unsure what data was supposed to be, but swapping it to a function name did not work +// This does nothing, no event proc found +// TODO: 32-bit support +// void loc_setEventProc (Display *display, Window window) { +// size_t data = (size_t)loc_eventProc; +// long temp[2]; + +// // Split the 64 bit pointer into a little-endian long array +// temp[0] = (long)(data & 0xffffffffUL); +// temp[1] = (long)(data >> 32L); + +// Atom atom = XInternAtom(display, "_XEventProc", False); +// XChangeProperty(display, window, atom, atom, 32, +// PropModeReplace, (unsigned char*)temp, 2); +// } + +// Pulled from the eXT2 example +// TODO: 32-bit support +void loc_setEventProc (Display *display, Window window) { + void* data = (void*)&loc_eventProc; // swapped the function name here + + Atom atom = XInternAtom(display, "_XEventProc", False); + XChangeProperty(display, window, atom, atom, 32, + PropModeReplace, (unsigned char*)&data, 1); // 1 instead of 2 will crash Ardour, 2 will not do anything } +// Pulled from the amsynth example +// Simply swapped out the function names, crashes Ardour in the same was as the others +// void loc_setEventProc (Display *display, Window window) { +// #ifdef BUILD_64 +// // +// // JUCE calls XGetWindowProperty with long_length = 1 which means it only fetches the lower 32 bits of the address. +// // Therefore we need to ensure we return an address in the lower 32-bits of address space. +// // + +// // based on mach_override +// static const unsigned char kJumpInstructions[] = { +// 0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, +// 0x00, 0x00, 0x00, 0x00, +// 0x00, 0x00, 0x00, 0x00 +// }; +// static const int kJumpAddress = 6; + +// static char *ptr; +// if (!ptr) { +// ptr = (char *)mmap(0, +// PAGE_SIZE, +// PROT_READ | PROT_WRITE | PROT_EXEC, +// MAP_ANONYMOUS | MAP_PRIVATE | MAP_32BIT, +// 0, 0); +// if (ptr == MAP_FAILED) { +// perror("mmap"); +// ptr = 0; +// return; +// } else { +// memcpy(ptr, kJumpInstructions, sizeof(kJumpInstructions)); +// *((uint64_t *)(ptr + kJumpAddress)) = (uint64_t)(&loc_eventProc); +// msync(ptr, sizeof(kJumpInstructions), MS_INVALIDATE); +// } +// } + +// long temp[2] = {(long)ptr, 0}; +// Atom atom = XInternAtom(display, "_XEventProc", False); +// XChangeProperty(display, window, atom, atom, 32, PropModeReplace, (unsigned char *)temp, 2); +// #else +// long temp[1] = {(long)(void *)(&loc_eventProc)}; +// Atom atom = XInternAtom(display, "_XEventProc", False); +// XChangeProperty(display, window, atom, atom, 32, PropModeReplace, (unsigned char *)temp, 1); +// #endif +// } + // ---------------------------------------------------------------------------- lglw_window_open lglw_bool_t lglw_window_open (lglw_t _lglw, void *_parentHWNDOrNull, int32_t _x, int32_t _y, int32_t _w, int32_t _h) { lglw_bool_t r = LGLW_FALSE; LGLW(_lglw); - // (todo) implement me - if(NULL != lglw) { + lglw_log("lglw:lglw_window_open: 1, %p, %i\n", (Window)_parentHWNDOrNull, (Window)_parentHWNDOrNull); + lglw->parent_xwnd = (0 == _parentHWNDOrNull) ? DefaultRootWindow(lglw->xdsp) : (Window)_parentHWNDOrNull; + + lglw_log("lglw:lglw_window_open: 2\n"); if(_w <= 16) _w = lglw->hidden.size.x; + lglw_log("lglw:lglw_window_open: 3\n"); if(_h <= 16) _h = lglw->hidden.size.y; + // TODO: compare to 'WindowClass' from Windows implementation + + lglw_log("lglw:lglw_window_open: 4\n"); + XSetWindowAttributes swa; + XEvent event; + XSync(lglw->xdsp, False); + + lglw_log("lglw:lglw_window_open: 5\n"); + swa.border_pixel = 0; + swa.colormap = lglw->cmap; + swa.event_mask = EnterWindowMask | LeaveWindowMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask; + lglw->win.xwnd = XCreateWindow(lglw->xdsp, DefaultRootWindow(lglw->xdsp), + 0, 0, _w, _h, 0, CopyFromParent, InputOutput, + lglw->vi->visual, CWBorderPixel | CWColormap | CWEventMask, &swa); + + lglw_log("lglw:lglw_window_open: 6\n"); + XSetStandardProperties(lglw->xdsp, lglw->win.xwnd, "LGLW", "LGLW", None, NULL, 0, NULL); + + // Setup the event proc now, on the parent window as well just for the debug host + // It was simpler to do this than check in the debug host for the reparent event + lglw_log("lglw:lglw_window_open: 7\n"); + loc_setEventProc(lglw->xdsp, lglw->win.xwnd); + loc_setEventProc(lglw->xdsp, lglw->parent_xwnd); + + // Some hosts only check and store the callback when the Window is reparented + // Since creating the Window with a Parent may or may not do that, but the callback is not set, + // ... it's created as a root window, the callback is set, and then it's reparented + if (0 != _parentHWNDOrNull) + { + lglw_log("lglw:lglw_window_open: 8\n"); + XReparentWindow(lglw->xdsp, lglw->win.xwnd, lglw->parent_xwnd, 0, 0); + } + + lglw_log("lglw:lglw_window_open: 9\n"); + XMapRaised(lglw->xdsp, lglw->win.xwnd); + XSync(lglw->xdsp, False); + lglw->win.mapped = LGLW_TRUE; + + lglw_log("lglw:lglw_window_open: 10\n"); lglw->win.size.x = _w; lglw->win.size.y = _h; + lglw_log("lglw:lglw_window_open: 11\n"); loc_enable_dropfiles(lglw, (NULL != lglw->dropfiles.cbk)); + + lglw_log("lglw:lglw_window_open: EXIT\n"); } return r; } @@ -250,10 +496,56 @@ lglw_bool_t lglw_window_resize (lglw_t _lglw, int32_t _w, int32_t _h) { lglw_bool_t r = LGLW_FALSE; LGLW(_lglw); - // (todo) implement me - if(NULL != lglw) { + if(0 != lglw->win.xwnd) + { + lglw_log("lglw:lglw_window_resize: 1\n"); + r = LGLW_TRUE; + + lglw_log("lglw:lglw_window_resize: 2\n"); + XResizeWindow(lglw->xdsp, lglw->win.xwnd, _w, _h); + XRaiseWindow(lglw->xdsp, lglw->win.xwnd); + + lglw_log("lglw:lglw_window_resize: 3\n"); + int deltaW = _w - lglw->win.size.x; + int deltaH = _h - lglw->win.size.y; + + lglw_log("lglw:lglw_window_resize: 4\n"); + lglw->win.size.x = _w; + lglw->win.size.y = _h; + + lglw_log("lglw:lglw_window_resize: 5\n"); + Window root, parent, *children = NULL; + unsigned int num_children; + + lglw_log("lglw:lglw_window_resize: 6\n"); + if(!XQueryTree(lglw->xdsp, lglw->win.xwnd, &root, &parent, &children, &num_children)) + return r; + + lglw_log("lglw:lglw_window_resize: 7\n"); + if(children) + XFree((char *)children); + + lglw_log("lglw:lglw_window_resize: 8\n"); + // Resize parent window (if any) + if(0 != parent) + { + lglw_log("lglw:lglw_window_resize: 8.1\n"); + int x, y; + unsigned int width, height; + unsigned int border_width; + unsigned int depth; + + lglw_log("lglw:lglw_window_resize: 8.2\n"); + if(!XGetGeometry(lglw->xdsp, lglw->win.xwnd, &root, &x, &y, &width, &height, &border_width, &depth)) + return r; + + lglw_log("lglw:lglw_window_resize: 8.3\n"); + XResizeWindow(lglw->xdsp, parent, width + deltaW, height + deltaH); + } + lglw_log("lglw:lglw_window_resize: EXIT\n"); + } } return r; @@ -264,17 +556,27 @@ lglw_bool_t lglw_window_resize (lglw_t _lglw, int32_t _w, int32_t _h) { void lglw_window_close (lglw_t _lglw) { LGLW(_lglw); - // (todo) implement me - if(NULL != lglw) { - // if(NULL != lglw->win.hwnd) + if(0 != lglw->win.xwnd) { + lglw_log("lglw:lglw_window_close: 1\n"); lglw_timer_stop(_lglw); + lglw_log("lglw:lglw_window_close: 2\n"); loc_key_unhook(lglw); + + lglw_log("lglw:lglw_window_close: 3\n"); + glXMakeCurrent(lglw->xdsp, None, NULL); + + lglw_log("lglw:lglw_window_close: 4\n"); + XDestroyWindow(lglw->xdsp, lglw->win.xwnd); + XSync(lglw->xdsp, False); + lglw->win.xwnd = 0; + lglw->win.mapped = LGLW_FALSE; } } + lglw_log("lglw:lglw_window_close: EXIT\n"); } @@ -282,11 +584,14 @@ void lglw_window_close (lglw_t _lglw) { void lglw_window_show(lglw_t _lglw) { LGLW(_lglw); - // (todo) implement me - if(NULL != lglw) { + lglw_log("lglw:lglw_window_show: 1\n"); + XMapRaised(lglw->xdsp, lglw->win.xwnd); + + lglw->win.mapped = LGLW_TRUE; } + lglw_log("lglw:lglw_window_show: EXIT\n"); } @@ -294,11 +599,14 @@ void lglw_window_show(lglw_t _lglw) { void lglw_window_hide(lglw_t _lglw) { LGLW(_lglw); - // (todo) implement me - if(NULL != lglw) { + lglw_log("lglw:lglw_window_hide: 1\n"); + XUnmapWindow(lglw->xdsp, lglw->win.xwnd); + + lglw->win.mapped = LGLW_FALSE; } + lglw_log("lglw:lglw_window_hide: EXIT\n"); } @@ -307,12 +615,14 @@ lglw_bool_t lglw_window_is_visible(lglw_t _lglw) { lglw_bool_t r = LGLW_FALSE; LGLW(_lglw); - // (todo) implement me - - if(NULL != lglw) + // lglw_log("lglw:lglw_window_is_visible: 1\n"); + if(NULL != lglw && 0 != lglw->win.xwnd) { + // lglw_log("lglw:lglw_window_is_visible: 2\n"); + r = lglw->win.mapped; } + // lglw_log("lglw:lglw_window_is_visible: EXIT\n"); return r; } @@ -321,11 +631,19 @@ lglw_bool_t lglw_window_is_visible(lglw_t _lglw) { void lglw_window_size_get(lglw_t _lglw, int32_t *_retX, int32_t *_retY) { LGLW(_lglw); - // (todo) implement me - + lglw_log("lglw:lglw_window_size_get: 1\n"); if(NULL != lglw) { + if(0 != lglw->win.xwnd) + { + if(NULL != _retX) + *_retX = lglw->win.size.x; + + if(NULL != _retY) + *_retY = lglw->win.size.y; + } } + lglw_log("lglw:lglw_window_size_get: EXIT\n"); } @@ -337,6 +655,13 @@ void lglw_redraw(lglw_t _lglw) { if(NULL != lglw) { + if(0 != lglw->win.xwnd) + { + // TODO Event Loop + lglw_log("lglw:lglw_redraw: 1\n"); + XClearArea(lglw->xdsp, lglw->win.xwnd, 0, 0, 1, 1, True); // clear tiny area for exposing + XFlush(lglw->xdsp); + } } } @@ -355,11 +680,18 @@ void lglw_redraw_callback_set(lglw_t _lglw, lglw_redraw_fxn_t _cbk) { // ---------------------------------------------------------------------------- lglw_glcontext_push void lglw_glcontext_push(lglw_t _lglw) { LGLW(_lglw); - - // (todo) implement me if(NULL != lglw) { + lglw->prev.drw = glXGetCurrentDrawable(); + lglw->prev.ctx = glXGetCurrentContext(); + + // lglw_log("lglw:lglw_glcontext_push: win.xwnd=%p hidden.xwnd=%p ctx=%p\n", + // lglw->win.xwnd, lglw->hidden.xwnd, lglw->ctx); + if(!glXMakeCurrent(lglw->xdsp, (0 == lglw->win.xwnd) ? lglw->hidden.xwnd : lglw->win.xwnd, lglw->ctx)) + { + lglw_log("[---] lglw_glcontext_push: glXMakeCurrent() failed. win.xwnd=%p hidden.xwnd=%p ctx=%p glGetError()=%d\n", lglw->win.xwnd, lglw->hidden.xwnd, lglw->ctx, glGetError()); + } } } @@ -367,11 +699,15 @@ void lglw_glcontext_push(lglw_t _lglw) { // ---------------------------------------------------------------------------- lglw_glcontext_pop void lglw_glcontext_pop(lglw_t _lglw) { LGLW(_lglw); - - // (todo) implement me if(NULL != lglw) { + // lglw_log("lglw:lglw_glcontext_pop: prev.drw=%p prev.ctx=%p\n", + // lglw->prev.drw, lglw->prev.ctx); + if(!glXMakeCurrent(lglw->xdsp, lglw->prev.drw, lglw->prev.ctx)) + { + lglw_log("[---] lglw_glcontext_pop: glXMakeCurrent() failed. prev.drw=%p ctx=%p glGetError()=%d\n", lglw->prev.drw, lglw->prev.ctx, glGetError()); + } } } @@ -380,22 +716,33 @@ void lglw_glcontext_pop(lglw_t _lglw) { void lglw_swap_buffers(lglw_t _lglw) { LGLW(_lglw); - // (todo) implement me - if(NULL != lglw) { + if(0 != lglw->win.xwnd) + { + // lglw_log("lglw:lglw_swap_buffers: 1\n"); + glXSwapBuffers(lglw->xdsp, lglw->win.xwnd); + } } } // ---------------------------------------------------------------------------- lglw_swap_interval_set +typedef void (APIENTRY *PFNWGLEXTSWAPINTERVALPROC) (int); void lglw_swap_interval_set(lglw_t _lglw, int32_t _ival) { LGLW(_lglw); - // (todo) implement me - if(NULL != lglw) { + lglw_log("lglw:lglw_swap_interval_set: 1\n"); + PFNWGLEXTSWAPINTERVALPROC glXSwapIntervalEXT; + glXSwapIntervalEXT = (PFNWGLEXTSWAPINTERVALPROC) glXGetProcAddress("glXSwapIntervalEXT"); + if(NULL != glXSwapIntervalEXT) + { + lglw_log("lglw:lglw_swap_interval_set: 2\n"); + glXSwapIntervalEXT(_ival); + lglw->win.swap_interval = _ival; + } } } @@ -444,7 +791,7 @@ static void loc_handle_mouseleave(lglw_int_t *lglw) { lglw->focus.cbk(lglw, lglw->focus.state, LGLW_FOCUS_MOUSE); } - Dprintf("xxx lglw:loc_handle_mouseleave: LEAVE\n"); + lglw_log("xxx lglw:loc_handle_mouseleave: LEAVE\n"); } @@ -460,7 +807,7 @@ static void loc_handle_mouseenter(lglw_int_t *lglw) { lglw->focus.cbk(lglw, lglw->focus.state, LGLW_FOCUS_MOUSE); } - Dprintf("xxx lglw:loc_handle_mouseenter: LEAVE\n"); + lglw_log("xxx lglw:loc_handle_mouseenter: LEAVE\n"); } diff --git a/other/vst2_debug_host/makefile.linux b/other/vst2_debug_host/makefile.linux index b1d0be67..be388019 100644 --- a/other/vst2_debug_host/makefile.linux +++ b/other/vst2_debug_host/makefile.linux @@ -6,7 +6,7 @@ include ../../dep/yac/install_linux.mk .PHONY: bin bin: vst2_debug_host.o - $(CPP) -o vst2_debug_host vst2_debug_host.o -ldl + $(CPP) -o vst2_debug_host vst2_debug_host.o -ldl -L/usr/lib -lpthread -lX11 .PHONY: clean clean: diff --git a/other/vst2_debug_host/vst2_debug_host.cpp b/other/vst2_debug_host/vst2_debug_host.cpp index 2561f4b6..5672c411 100644 --- a/other/vst2_debug_host/vst2_debug_host.cpp +++ b/other/vst2_debug_host/vst2_debug_host.cpp @@ -2,7 +2,8 @@ // #define DLL_PATH "../../vst2_bin/veeseevstrack_effect.dll" -#define SO_PATH "../../vst2_bin/veeseevstrack_effect.so" +// #define SO_PATH "../../vst2_bin/veeseevstrack_effect.so" +#define SO_PATH "../vst2_lglw_debug_plugin/debug_lglw.so" #include @@ -12,6 +13,11 @@ #include #else #include +#include +#include +#include +#include +#include #endif #include @@ -19,6 +25,49 @@ typedef AEffect* (*PluginEntryProc) (audioMasterCallback audioMaster); +#ifndef YAC_WIN32 +// https://github.com/Ardour/ardour/blob/master/gtk2_ardour/linux_vst_gui_support.cc +long getXWindowProperty(Display* display, Window window, Atom atom) +{ + long result = 0; + int userSize; + unsigned long bytes; + unsigned long userCount; + unsigned char *data; + Atom userType; + // LXVST_xerror = false; + + /*Use our own Xerror handler while we're in here - in an + attempt to stop the brain dead default Xerror behaviour of + qutting the entire application because of e.g. an invalid + window ID*/ + + // XErrorHandler olderrorhandler = XSetErrorHandler(TempErrorHandler); + + XGetWindowProperty(display, + window, + atom, + 0, + 2, + false, + AnyPropertyType, + &userType, + &userSize, + &userCount, + &bytes, + &data); + + if(userCount == 1) + result = *(long*)data; + + // XSetErrorHandler(olderrorhandler); + + /*Hopefully this will return zero if the property is not set*/ + + return result; +} +#endif + static VstIntPtr VSTCALLBACK HostCallback(AEffect* effect, VstInt32 opcode, VstInt32 index, VstIntPtr value, void* ptr, float opt) { static VstInt32 lastOpcode = -1; @@ -48,6 +97,15 @@ void open_and_close(void) { } #endif +#ifndef YAC_WIN32 + Display *d; + Window w; + int s; + + d = XOpenDisplay(NULL); + s = DefaultScreen(d); +#endif + for(int i = 0; i < 48; i++) { inputBuffers[i] = new float[4096]; @@ -79,18 +137,75 @@ void open_and_close(void) { if(NULL != effect) { + +#ifndef YAC_WIN32 + w = XCreateSimpleWindow(d, RootWindow(d, s), 10, 10, 100, 100, 1, + BlackPixel(d, s), WhitePixel(d, s)); + XSelectInput(d, w, ExposureMask | KeyPressMask); + XMapRaised(d, w); + XFlush(d); +#endif + printf("xxx calling effect->dispatcher\n"); effect->dispatcher(effect, effOpen, 0, 0, NULL, 0.0f); printf("xxx effect->dispatcher returned\n"); +#ifdef YAC_WIN32 VstIntPtr ip = effect->dispatcher(effect, effEditOpen, 0, 0, NULL/*hWnd*/, 0.0f); +#else + VstIntPtr ip = effect->dispatcher(effect, effEditOpen, 0, 0, (void*)(w)/*hWnd*/, 0.0f); +#endif (void)ip; + sleep(2); + +#ifndef YAC_WIN32 + long result = getXWindowProperty(d, w, XInternAtom(d, "_XEventProc", false)); + if(result == 0) + { + printf("xxx no XEventProc found\n"); + } + else + { + printf("xxx XEventProc found... calling\n"); + void (* eventProc) (void * event); + eventProc = (void (*) (void* event))result; + eventProc(NULL); + } +#endif + + printf("xxx calling effect->dispatcher\n"); + effect->dispatcher(effect, effEditIdle, 0, 0, NULL, 0.0f); + sleep(1); + printf("xxx calling effect->dispatcher\n"); + effect->dispatcher(effect, effEditIdle, 0, 0, NULL, 0.0f); + sleep(1); + printf("xxx calling effect->dispatcher\n"); + effect->dispatcher(effect, effEditClose, 0, 0, NULL, 0.0f); + sleep(1); + printf("xxx calling effect->dispatcher again\n"); +#ifdef YAC_WIN32 + effect->dispatcher(effect, effEditOpen, 0, 0, NULL/*hWnd*/, 0.0f); +#else + effect->dispatcher(effect, effEditOpen, 0, 0, (void*)(w)/*hWnd*/, 0.0f); +#endif + sleep(1); + printf("xxx calling effect->dispatcher\n"); + effect->dispatcher(effect, effEditIdle, 0, 0, NULL, 0.0f); + sleep(1); printf("xxx call processreplacing\n"); for(int i = 0; i < 1024; i++) { effect->processReplacing(effect, inputBuffers, outputBuffers, (VstInt32)64); } + printf("xxx calling effect->dispatcher\n"); effect->dispatcher(effect, effEditClose, 0, 0, NULL, 0.0f); + sleep(1); + printf("xxx calling effect->dispatcher\n"); effect->dispatcher(effect, effClose, 0, 0, NULL, 0.0f); + sleep(1); + +#ifndef YAC_WIN32 + XDestroyWindow(d, w); +#endif } } else @@ -110,10 +225,14 @@ void open_and_close(void) { delete [] inputBuffers[i]; delete [] outputBuffers[i]; } + +#ifndef YAC_WIN32 + XCloseDisplay(d); +#endif } int main() { - for(;;) + for(int i = 0; i < 5; i++) { open_and_close(); } diff --git a/other/vst2_lglw_debug_plugin/.gitignore b/other/vst2_lglw_debug_plugin/.gitignore new file mode 100644 index 00000000..3b06a9a8 --- /dev/null +++ b/other/vst2_lglw_debug_plugin/.gitignore @@ -0,0 +1,4 @@ +.DS_Store +M3dB/.idea +vst2.x/aeffect.h +vst2.x/aeffectx.h diff --git a/other/vst2_lglw_debug_plugin/M3dB.xcodeproj/project.pbxproj b/other/vst2_lglw_debug_plugin/M3dB.xcodeproj/project.pbxproj new file mode 100644 index 00000000..373b90a6 --- /dev/null +++ b/other/vst2_lglw_debug_plugin/M3dB.xcodeproj/project.pbxproj @@ -0,0 +1,266 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + BD2A1F5751BB6465EFEB5889 /* plugin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BD2A144C3B32EFA5180A38F5 /* plugin.cpp */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + BD2A1226DD4B6ED23F230900 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.info; path = Info.plist; sourceTree = ""; }; + BD2A144C3B32EFA5180A38F5 /* plugin.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = plugin.cpp; sourceTree = ""; }; + BD2A17C571405D51496892C4 /* M3dB.___VARIABLE_bundleExtension___ */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "M3dB.___VARIABLE_bundleExtension___"; sourceTree = BUILT_PRODUCTS_DIR; }; + BD2A18D6CA1C93179E40396A /* aeffect.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = aeffect.h; path = ../vst2.x/aeffect.h; sourceTree = ""; }; + BD2A1CFE51F03D1B40DA1230 /* aeffectx.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = aeffectx.h; path = ../vst2.x/aeffectx.h; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + BD2A17410135F1BFA2BB6503 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + BD2A15554318E7C2EF2CD5DC /* Products */ = { + isa = PBXGroup; + children = ( + BD2A17C571405D51496892C4 /* M3dB.___VARIABLE_bundleExtension___ */, + ); + name = Products; + sourceTree = ""; + }; + BD2A1DCFA27E77A6603B70A2 = { + isa = PBXGroup; + children = ( + BD2A15554318E7C2EF2CD5DC /* Products */, + BD2A1F10D41E35E7FCDFA898 /* M3dB */, + BD2A144C3B32EFA5180A38F5 /* plugin.cpp */, + BD2A18D6CA1C93179E40396A /* aeffect.h */, + BD2A1CFE51F03D1B40DA1230 /* aeffectx.h */, + ); + sourceTree = ""; + }; + BD2A1F10D41E35E7FCDFA898 /* M3dB */ = { + isa = PBXGroup; + children = ( + BD2A1226DD4B6ED23F230900 /* Info.plist */, + ); + path = M3dB; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + BD2A186B82B2C6E8A0E9022C /* M3dB */ = { + isa = PBXNativeTarget; + buildConfigurationList = BD2A12A4CFEA12B6C7A8873E /* Build configuration list for PBXNativeTarget "M3dB" */; + buildPhases = ( + BD2A15C927C3AD450E2DD52C /* Sources */, + BD2A17410135F1BFA2BB6503 /* Frameworks */, + BD2A175E365F9ED8C1C35C6F /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = M3dB; + productName = M3dB; + productReference = BD2A17C571405D51496892C4 /* M3dB.___VARIABLE_bundleExtension___ */; + productType = "com.apple.product-type.bundle"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + BD2A116B4EC711555868B9BA /* Project object */ = { + isa = PBXProject; + attributes = { + ORGANIZATIONNAME = pongasoft; + }; + buildConfigurationList = BD2A1B7627DAA8FF541E84EC /* Build configuration list for PBXProject "M3dB" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = BD2A1DCFA27E77A6603B70A2; + productRefGroup = BD2A15554318E7C2EF2CD5DC /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + BD2A186B82B2C6E8A0E9022C /* M3dB */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + BD2A175E365F9ED8C1C35C6F /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + BD2A15C927C3AD450E2DD52C /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + BD2A1F5751BB6465EFEB5889 /* plugin.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + BD2A1223BF2A633FEE5D6099 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = M3dB/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles"; + PRODUCT_BUNDLE_IDENTIFIER = org.pongasoft.vst24.M3dB; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + WRAPPER_EXTENSION = vst; + }; + name = Debug; + }; + BD2A17437E006499CC8685D1 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVES = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + }; + name = Debug; + }; + BD2A186609800B3BD0ECFF98 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + DEPLOYMENT_POSTPROCESSING = YES; + INFOPLIST_FILE = M3dB/Info.plist; + INSTALL_PATH = "$(HOME)/Library/Audio/Plug-Ins/VST"; + PRODUCT_BUNDLE_IDENTIFIER = org.pongasoft.vst24.M3dB; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = NO; + WRAPPER_EXTENSION = vst; + }; + name = Release; + }; + BD2A1D1EC28D17DC43ACBA09 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVES = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEPLOYMENT_LOCATION = NO; + DEPLOYMENT_POSTPROCESSING = NO; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INSTALL_PATH = ""; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + BD2A12A4CFEA12B6C7A8873E /* Build configuration list for PBXNativeTarget "M3dB" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + BD2A1223BF2A633FEE5D6099 /* Debug */, + BD2A186609800B3BD0ECFF98 /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; + BD2A1B7627DAA8FF541E84EC /* Build configuration list for PBXProject "M3dB" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + BD2A17437E006499CC8685D1 /* Debug */, + BD2A1D1EC28D17DC43ACBA09 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = BD2A116B4EC711555868B9BA /* Project object */; +} diff --git a/other/vst2_lglw_debug_plugin/M3dB.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/other/vst2_lglw_debug_plugin/M3dB.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..919434a6 --- /dev/null +++ b/other/vst2_lglw_debug_plugin/M3dB.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/other/vst2_lglw_debug_plugin/M3dB.xcodeproj/project.xcworkspace/xcuserdata/ypujante.xcuserdatad/xcschemes/xcschememanagement.plist b/other/vst2_lglw_debug_plugin/M3dB.xcodeproj/project.xcworkspace/xcuserdata/ypujante.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 00000000..ee3458dd --- /dev/null +++ b/other/vst2_lglw_debug_plugin/M3dB.xcodeproj/project.xcworkspace/xcuserdata/ypujante.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,5 @@ + + + + + diff --git a/other/vst2_lglw_debug_plugin/M3dB.xcodeproj/xcuserdata/ypujante.xcuserdatad/xcschemes/M3dB - Debug.xcscheme b/other/vst2_lglw_debug_plugin/M3dB.xcodeproj/xcuserdata/ypujante.xcuserdatad/xcschemes/M3dB - Debug.xcscheme new file mode 100644 index 00000000..c936e04d --- /dev/null +++ b/other/vst2_lglw_debug_plugin/M3dB.xcodeproj/xcuserdata/ypujante.xcuserdatad/xcschemes/M3dB - Debug.xcscheme @@ -0,0 +1,22 @@ + + + + + + + + + + + + + diff --git a/other/vst2_lglw_debug_plugin/M3dB.xcodeproj/xcuserdata/ypujante.xcuserdatad/xcschemes/M3dB - Release.xcscheme b/other/vst2_lglw_debug_plugin/M3dB.xcodeproj/xcuserdata/ypujante.xcuserdatad/xcschemes/M3dB - Release.xcscheme new file mode 100644 index 00000000..5512455c --- /dev/null +++ b/other/vst2_lglw_debug_plugin/M3dB.xcodeproj/xcuserdata/ypujante.xcuserdatad/xcschemes/M3dB - Release.xcscheme @@ -0,0 +1,22 @@ + + + + + + + + + + + + + diff --git a/other/vst2_lglw_debug_plugin/M3dB.xcodeproj/xcuserdata/ypujante.xcuserdatad/xcschemes/xcschememanagement.plist b/other/vst2_lglw_debug_plugin/M3dB.xcodeproj/xcuserdata/ypujante.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 00000000..bd480195 --- /dev/null +++ b/other/vst2_lglw_debug_plugin/M3dB.xcodeproj/xcuserdata/ypujante.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,19 @@ + + + + + SchemeUserState + + M3dB - Debug.xcscheme + + orderHint + 0 + + M3dB - Release.xcscheme + + orderHint + 1 + + + + diff --git a/other/vst2_lglw_debug_plugin/M3dB/Info.plist b/other/vst2_lglw_debug_plugin/M3dB/Info.plist new file mode 100644 index 00000000..28986ba7 --- /dev/null +++ b/other/vst2_lglw_debug_plugin/M3dB/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + NSHumanReadableCopyright + Copyright © 2017 pongasoft. All rights reserved. + NSPrincipalClass + + + diff --git a/other/vst2_lglw_debug_plugin/makefile.linux b/other/vst2_lglw_debug_plugin/makefile.linux new file mode 100644 index 00000000..ed51b7f4 --- /dev/null +++ b/other/vst2_lglw_debug_plugin/makefile.linux @@ -0,0 +1,19 @@ + +include ../../dep/yac/install_linux.mk + +.cpp.o: + $(CPP) $(CPPFLAGS) $(OPTFLAGS_PLUGIN) -I"$(VSVR_BASE_DIR)/dep/yac/" -I"$(VST2_SDK_DIR)" -I"$(VSVR_BASE_DIR)/dep/lglw/" -shared -fPIC -c "$<" -o"$@" + +.PHONY: bin +bin: plugin.o + $(CPP) -shared -o debug_lglw.so -Wl,-soname,debug_lglw.so -mtls-dialect=gnu2 plugin.o "$(VSVR_BASE_DIR)/dep/lglw/lglw_linux.o" -ldl -lGL -L/usr/lib -lm -lpthread + +.PHONY: clean +clean: + rm -f plugin plugin.o + +.PHONY: all +all: + make -f makefile.linux clean + make -f makefile.linux bin + cp debug_lglw.so /home/cameron/.local/share/VST/ \ No newline at end of file diff --git a/other/vst2_lglw_debug_plugin/plugin.cpp b/other/vst2_lglw_debug_plugin/plugin.cpp new file mode 100644 index 00000000..fa0c5808 --- /dev/null +++ b/other/vst2_lglw_debug_plugin/plugin.cpp @@ -0,0 +1,458 @@ + + +#include +#include +#include + +#if defined(_WIN32) || defined(_WIN64) + #include + #include + #define VST_EXPORT extern "C" __declspec(dllexport) +#else + #include + #include + #include + #include + #define VST_EXPORT extern +#endif + +#include "lglw.h" + +#define EDITWIN_X 20 +#define EDITWIN_Y 20 +#define EDITWIN_W 640 +#define EDITWIN_H 480 + +/* + * I find the naming a bit confusing so I decided to use more meaningful names instead. + */ + +/** + * The VSTHostCallback is a function pointer so that the plugin can communicate with the host (not used in this small example) + */ +typedef audioMasterCallback VSTHostCallback; + +/** + * The VSTPlugin structure (AEffect) contains information about the plugin (like version, number of inputs, ...) and + * callbacks so that the host can call the plugin to do its work. The primary callback will be `processReplacing` for + * single precision (float) sample processing (or `processDoubleReplacing` for double precision (double)). + */ +typedef AEffect VSTPlugin; + + +// Since the host is expecting a very specific API we need to make sure it has C linkage (not C++) +extern "C" { + +/* + * This is the main entry point to the VST plugin. + * + * The host (DAW like Maschine, Ableton Live, Reason, ...) will look for this function with this exact API. + * + * It is the equivalent to `int main(int argc, char *argv[])` for a C executable. + * + * @param vstHostCallback is a callback so that the plugin can communicate with the host (not used in this small example) + * @return a pointer to the AEffect structure + */ +VST_EXPORT VSTPlugin *VSTPluginMain(VSTHostCallback vstHostCallback); + +// note this looks like this without the type aliases (and is obviously 100% equivalent) +// extern AEffect *VSTPluginMain(audioMasterCallback audioMaster); + +} + +/* + * Constant for the version of the plugin. For example 1100 for version 1.1.0.0 + */ +const VstInt32 PLUGIN_VERSION = 1000; + +// extern "C" LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); + +void loc_mouse_cbk(lglw_t _lglw, int32_t _x, int32_t _y, uint32_t _buttonState, uint32_t _changedButtonState) { + printf("xxx lglw_mouse_cbk: lglw=%p p=(%d; %d) bt=0x%08x changedBt=0x%08x\n", _lglw, _x, _y, _buttonState, _changedButtonState); + + if(LGLW_IS_MOUSE_LBUTTON_DOWN()) + { + // lglw_mouse_grab(_lglw, LGLW_MOUSE_GRAB_CAPTURE); + lglw_mouse_grab(_lglw, LGLW_MOUSE_GRAB_WARP); + } + else if(LGLW_IS_MOUSE_LBUTTON_UP()) + { + lglw_mouse_ungrab(_lglw); + } +} + +void loc_focus_cbk(lglw_t _lglw, uint32_t _focusState, uint32_t _changedFocusState) { + printf("xxx lglw_focus_cbk: lglw=%p focusState=0x%08x changedFocusState=0x%08x\n", _lglw, _focusState, _changedFocusState); +} + +lglw_bool_t loc_keyboard_cbk(lglw_t _lglw, uint32_t _vkey, uint32_t _kmod, lglw_bool_t _bPressed) { + printf("xxx lglw_keyboard_cbk: lglw=%p vkey=0x%08x (\'%c\') kmod=0x%08x bPressed=%d\n", _lglw, _vkey, _vkey, _kmod, _bPressed); + return LGLW_FALSE; +} + +void loc_timer_cbk(lglw_t _lglw) { + printf("xxx lglw_timer_cbk: tick\n"); +} + +/** + * Encapsulates the plugin as a C++ class. It will keep both the host callback and the structure required by the + * host (VSTPlugin). This class will be stored in the `VSTPlugin.object` field (circular reference) so that it can + * be accessed when the host calls the plugin back (for example in `processDoubleReplacing`). + */ +class VSTPluginWrapper +{ +public: + ERect editor_rect; + + lglw_t lglw; + + float clear_color = 0.0f; + + static VSTPluginWrapper *window_to_wrapper; + +public: + VSTPluginWrapper(VSTHostCallback vstHostCallback, + VstInt32 vendorUniqueID, + VstInt32 vendorVersion, + VstInt32 numParams, + VstInt32 numPrograms, + VstInt32 numInputs, + VstInt32 numOutputs); + + ~VSTPluginWrapper(); + + inline VSTPlugin *getVSTPlugin() + { + return &_vstPlugin; + } + + inline VstInt32 getNumInputs() const + { + return _vstPlugin.numInputs; + } + + inline VstInt32 getNumOutputs() const + { + return _vstPlugin.numOutputs; + } + + void openEditor(void *_hwnd) { + + (void)lglw_window_open(lglw, _hwnd, 0/*x*/, 0/*y*/, EDITWIN_W, EDITWIN_H); + + lglw_mouse_callback_set(lglw, &loc_mouse_cbk); + lglw_focus_callback_set(lglw, &loc_focus_cbk); + lglw_keyboard_callback_set(lglw, &loc_keyboard_cbk); + lglw_timer_callback_set(lglw, &loc_timer_cbk); + + lglw_timer_start(lglw, 200); + + window_to_wrapper = this; + } + + void closeEditor(void) { + if(NULL != window_to_wrapper) + { + lglw_window_close(lglw); + + window_to_wrapper = NULL; + } + } + + static VSTPluginWrapper *FindWrapperByWindow(Window hwnd) { + return window_to_wrapper; + } + + void redrawWindow(void) { + // Save host GL context + lglw_glcontext_push(lglw); + + // Draw something + ::glClearColor(0.0, 1.0, clear_color, 1.0); + clear_color += 0.05f; + if(clear_color >= 1.0f) + clear_color -= 1.0f; + ::glClear(GL_COLOR_BUFFER_BIT); + + ::glFlush(); + lglw_swap_buffers(lglw); + + // Restore host GL context + lglw_glcontext_pop(lglw); + } + +private: + // the host callback (a function pointer) + VSTHostCallback _vstHostCallback; + + // the actual structure required by the host + VSTPlugin _vstPlugin; +}; + +VSTPluginWrapper *VSTPluginWrapper::window_to_wrapper = NULL; + + +/******************************************* + * Callbacks: Host -> Plugin + * + * Defined here because they are used in the rest of the code later + */ + +/** + * This is the callback that will be called to process the samples in the case of single precision. This is where the + * meat of the logic happens! + * + * @param vstPlugin the object returned by VSTPluginMain + * @param inputs an array of array of input samples. You read from it. First dimension is for inputs, second dimension is for samples: inputs[numInputs][sampleFrames] + * @param outputs an array of array of output samples. You write to it. First dimension is for outputs, second dimension is for samples: outputs[numOuputs][sampleFrames] + * @param sampleFrames the number of samples (second dimension in both arrays) + */ +void VSTPluginProcessSamplesFloat32(VSTPlugin *vstPlugin, float **inputs, float **outputs, VstInt32 sampleFrames) +{ + // we can get a hold to our C++ class since we stored it in the `object` field (see constructor) + VSTPluginWrapper *wrapper = static_cast(vstPlugin->object); + + // code speaks for itself: for each input (2 when stereo input), iterating over every sample and writing the + // result in the outputs array after multiplying by 0.5 (which result in a 3dB attenuation of the sound) + for(int i = 0; i < wrapper->getNumInputs(); i++) + { + auto inputSamples = inputs[i]; + auto outputSamples = outputs[i]; + for(int j = 0; j < sampleFrames; j++) + { + outputSamples[j] = inputSamples[j] * 0.5f; + } + } +} + +/** + * This is the callback that will be called to process the samples in the case of double precision. This is where the + * meat of the logic happens! + * + * @param vstPlugin the object returned by VSTPluginMain + * @param inputs an array of array of input samples. You read from it. First dimension is for inputs, second dimension is for samples: inputs[numInputs][sampleFrames] + * @param outputs an array of array of output samples. You write to it. First dimension is for outputs, second dimension is for samples: outputs[numOuputs][sampleFrames] + * @param sampleFrames the number of samples (second dimension in both arrays) + */ +void VSTPluginProcessSamplesFloat64(VSTPlugin *vstPlugin, double **inputs, double **outputs, VstInt32 sampleFrames) +{ + // we can get a hold to our C++ class since we stored it in the `object` field (see constructor) + VSTPluginWrapper *wrapper = static_cast(vstPlugin->object); + + // code speaks for itself: for each input (2 when stereo input), iterating over every sample and writing the + // result in the outputs array after multiplying by 0.5 (which result in a 3dB attenuation of the sound) + for(int i = 0; i < wrapper->getNumInputs(); i++) + { + auto inputSamples = inputs[i]; + auto outputSamples = outputs[i]; + for(int j = 0; j < sampleFrames; j++) + { + outputSamples[j] = inputSamples[j] * 0.5; + } + } +} + +/** + * This is the plugin called by the host to communicate with the plugin, mainly to request information (like the + * vendor string, the plugin category...) or communicate state/changes (like open/close, frame rate...) + * + * @param vstPlugin the object returned by VSTPluginMain + * @param opCode defined in aeffect.h/AEffectOpcodes and which continues in aeffectx.h/AEffectXOpcodes for a grand + * total of 79 of them! Only a few of them are implemented in this small plugin. + * @param index depend on the opcode + * @param value depend on the opcode + * @param ptr depend on the opcode + * @param opt depend on the opcode + * @return depend on the opcode (0 is ok when you don't implement an opcode...) + */ +VstIntPtr VSTPluginDispatcher(VSTPlugin *vstPlugin, VstInt32 opCode, VstInt32 index, VstIntPtr value, void *ptr, float opt) +{ + // printf("vstgltest: called VSTPluginDispatcher(%d)\n", opCode); + + VstIntPtr r = 0; + + // we can get a hold to our C++ class since we stored it in the `object` field (see constructor) + VSTPluginWrapper *wrapper = static_cast(vstPlugin->object); + // see aeffect.h/AEffectOpcodes and aeffectx.h/AEffectXOpcodes for details on all of them + switch(opCode) + { + // request for the category of the plugin: in this case it is an effect since it is modifying the input (as opposed + // to generating sound) + case effGetPlugCategory: + return kPlugCategEffect; + + // called by the host when the plugin was called... time to reclaim memory! + case effClose: + delete wrapper; + break; + + case effGetEffectName: + ::strncpy((char*)ptr, "VST GL Test", kVstMaxEffectNameLen); + r = 1; + break; + + // request for the vendor string (usually used in the UI for plugin grouping) + case effGetVendorString: + strncpy(static_cast(ptr), "bsp", kVstMaxVendorStrLen); + r = 1; + break; + + // request for the version + case effGetVendorVersion: + return PLUGIN_VERSION; + + case effGetParamName: + strncpy(static_cast(ptr), "myparam", kVstMaxParamStrLen); + r = 1; + break; + + case effEditIdle: + printf("xxx vstgltest: redraw window\n"); + // (void)::RedrawWindow(wrapper->hwnd, NULL, NULL, RDW_INTERNALPAINT); + //(void)::UpdateWindow(wrapper->hwnd); + if(lglw_window_is_visible(wrapper->lglw)) + { + wrapper->redrawWindow(); + } + break; + + case effEditGetRect: + // Query editor window geometry + // ptr: ERect* (on Windows) + if(NULL != ptr) // yeah, this should never be NULL + { + // ... + wrapper->editor_rect.left = EDITWIN_X; + wrapper->editor_rect.top = EDITWIN_Y; + wrapper->editor_rect.right = EDITWIN_X + EDITWIN_W; + wrapper->editor_rect.bottom = EDITWIN_Y + EDITWIN_H; + *(void**)ptr = (void*) &wrapper->editor_rect; + r = 1; + } + else + { + r = 0; + } + break; + +#if 0 + case effEditTop: + // deprecated in vst2.4 + r = 0; + break; +#endif + + case effEditOpen: + // Show editor window + // ptr: native window handle (hWnd on Windows) + wrapper->openEditor(ptr); + r = 1; + break; + + case effEditClose: + // Hide editor window + wrapper->closeEditor(); + r = 1; + break; + + // ignoring all other opcodes + default: + // printf("Unknown opCode %d [ignored] \n", opCode); + break; + } + + return r; +} + +/** + * Used for parameter setting (not used by this plugin) + */ +void VSTPluginSetParameter(VSTPlugin *vstPlugin, VstInt32 index, float parameter) +{ + printf("called VSTPluginSetParameter(%d, %f)\n", index, parameter); + // we can get a hold to our C++ class since we stored it in the `object` field (see constructor) + VSTPluginWrapper *wrapper = static_cast(vstPlugin->object); +} + +/** + * Used for parameter (not used by this plugin) + */ +float VSTPluginGetParameter(VSTPlugin *vstPlugin, VstInt32 index) +{ + printf("called VSTPluginGetParameter(%d)\n", index); + // we can get a hold to our C++ class since we stored it in the `object` field (see constructor) + VSTPluginWrapper *wrapper = static_cast(vstPlugin->object); + return 0; +} + +/** + * Main constructor for our C++ class + */ +VSTPluginWrapper::VSTPluginWrapper(audioMasterCallback vstHostCallback, + VstInt32 vendorUniqueID, + VstInt32 vendorVersion, + VstInt32 numParams, + VstInt32 numPrograms, + VstInt32 numInputs, + VstInt32 numOutputs) : + _vstHostCallback(vstHostCallback) +{ + // Make sure that the memory is properly initialized + memset(&_vstPlugin, 0, sizeof(_vstPlugin)); + + // this field must be set with this constant... + _vstPlugin.magic = kEffectMagic; + + // storing this object into the VSTPlugin so that it can be retrieved when called back (see callbacks for use) + _vstPlugin.object = this; + + // specifying that we handle both single and double precision (there are other flags see aeffect.h/VstAEffectFlags) + _vstPlugin.flags = effFlagsCanReplacing | effFlagsCanDoubleReplacing | effFlagsHasEditor; + + // initializing the plugin with the various values + _vstPlugin.uniqueID = vendorUniqueID; + _vstPlugin.version = vendorVersion; + _vstPlugin.numParams = numParams; + _vstPlugin.numPrograms = numPrograms; + _vstPlugin.numInputs = numInputs; + _vstPlugin.numOutputs = numOutputs; + + // setting the callbacks to the previously defined functions + _vstPlugin.dispatcher = VSTPluginDispatcher; + _vstPlugin.getParameter = VSTPluginGetParameter; + _vstPlugin.setParameter = VSTPluginSetParameter; + _vstPlugin.processReplacing = VSTPluginProcessSamplesFloat32; + _vstPlugin.processDoubleReplacing = VSTPluginProcessSamplesFloat64; + + lglw = lglw_init(EDITWIN_W, EDITWIN_H); +} + +/** + * Destructor called when the plugin is closed (see VSTPluginDispatcher with effClose opCode). In this very simply plugin + * there is nothing to do but in general the memory that gets allocated MUST be freed here otherwise there might be a + * memory leak which may end up slowing down and/or crashing the host + */ +VSTPluginWrapper::~VSTPluginWrapper() { + lglw_exit(lglw); +} + +/** + * Implementation of the main entry point of the plugin + */ +VST_EXPORT VSTPlugin *VSTPluginMain(VSTHostCallback vstHostCallback) +{ + printf("called VSTPluginMain... \n"); + + // simply create our plugin C++ class + VSTPluginWrapper *plugin = + new VSTPluginWrapper(vstHostCallback, + CCONST('u', 's', 'a', '§'), // registered with Steinberg (http://service.steinberg.de/databases/plugin.nsf/plugIn?openForm) + PLUGIN_VERSION, // version + 2, // no params + 0, // no programs + 2, // 2 inputs + 2); // 2 outputs + + // return the plugin per the contract of the API + return plugin->getVSTPlugin(); +} diff --git a/other/vst2_lglw_debug_plugin/plugin.cpp__DUAL_WIN_CONTEXT_OK b/other/vst2_lglw_debug_plugin/plugin.cpp__DUAL_WIN_CONTEXT_OK new file mode 100644 index 00000000..39f84b89 --- /dev/null +++ b/other/vst2_lglw_debug_plugin/plugin.cpp__DUAL_WIN_CONTEXT_OK @@ -0,0 +1,615 @@ + + +#include +#include +#include + +#if defined(_WIN32) || defined(_WIN64) +#include +#include + #define VST_EXPORT extern "C" __declspec(dllexport) +#else + #define VST_EXPORT extern +#endif + +#include + +#define EDITWIN_X 20 +#define EDITWIN_Y 20 +#define EDITWIN_W 640 +#define EDITWIN_H 480 +#define EDITWIN_CLASS_NAME "VeeSeeVSTWindow" +#define EDITWIN_HIDDEN_CLASS_NAME "hidden_VeeSeeVSTWindow" + +/* + * I find the naming a bit confusing so I decided to use more meaningful names instead. + */ + +/** + * The VSTHostCallback is a function pointer so that the plugin can communicate with the host (not used in this small example) + */ +typedef audioMasterCallback VSTHostCallback; + +/** + * The VSTPlugin structure (AEffect) contains information about the plugin (like version, number of inputs, ...) and + * callbacks so that the host can call the plugin to do its work. The primary callback will be `processReplacing` for + * single precision (float) sample processing (or `processDoubleReplacing` for double precision (double)). + */ +typedef AEffect VSTPlugin; + + +// Since the host is expecting a very specific API we need to make sure it has C linkage (not C++) +extern "C" { + +/* + * This is the main entry point to the VST plugin. + * + * The host (DAW like Maschine, Ableton Live, Reason, ...) will look for this function with this exact API. + * + * It is the equivalent to `int main(int argc, char *argv[])` for a C executable. + * + * @param vstHostCallback is a callback so that the plugin can communicate with the host (not used in this small example) + * @return a pointer to the AEffect structure + */ +VST_EXPORT VSTPlugin *VSTPluginMain(VSTHostCallback vstHostCallback); + +// note this looks like this without the type aliases (and is obviously 100% equivalent) +// extern AEffect *VSTPluginMain(audioMasterCallback audioMaster); + +} + +/* + * Constant for the version of the plugin. For example 1100 for version 1.1.0.0 + */ +const VstInt32 PLUGIN_VERSION = 1000; + +extern "C" LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); + +/** + * Encapsulates the plugin as a C++ class. It will keep both the host callback and the structure required by the + * host (VSTPlugin). This class will be stored in the `VSTPlugin.object` field (circular reference) so that it can + * be accessed when the host calls the plugin back (for example in `processDoubleReplacing`). + */ +class VSTPluginWrapper +{ +public: + ERect editor_rect; + HWND parent_hwnd; // created by host + + struct { + HWND hwnd; + HDC hdc; + } hidden; + + struct { + HWND hwnd; + HDC hdc; + } editor; + + HGLRC hglrc; + + float clear_color = 0.0f; + + static const char *registered_class_name; + static VSTPluginWrapper *window_to_wrapper; + +public: + VSTPluginWrapper(VSTHostCallback vstHostCallback, + VstInt32 vendorUniqueID, + VstInt32 vendorVersion, + VstInt32 numParams, + VstInt32 numPrograms, + VstInt32 numInputs, + VstInt32 numOutputs); + + ~VSTPluginWrapper(); + + inline VSTPlugin *getVSTPlugin() + { + return &_vstPlugin; + } + + inline VstInt32 getNumInputs() const + { + return _vstPlugin.numInputs; + } + + inline VstInt32 getNumOutputs() const + { + return _vstPlugin.numOutputs; + } + + void createHiddenWindow(void) { + WNDCLASS wc; + ::ZeroMemory(&wc, sizeof(wc)); + wc.style = CS_OWNDC; + wc.lpfnWndProc = (WNDPROC) WndProc; + wc.hInstance = ::GetModuleHandle(NULL); + wc.hCursor = ::LoadCursor(NULL, IDC_ARROW); + wc.lpszClassName = EDITWIN_HIDDEN_CLASS_NAME; + + if(!::RegisterClass(&wc)) + { + // something went terribly wrong + printf("[---] vstgltest: failed to register hidden window class\n"); + return; + } + + DWORD dwExStyle = 0; + DWORD dwStyle = 0; + + hidden.hwnd = ::CreateWindowEx(dwExStyle, + EDITWIN_HIDDEN_CLASS_NAME, + "Test", + dwStyle, + 0/*xpos*/, 0/*ypos*/, + EDITWIN_W, EDITWIN_H, + NULL/*parentHWND*/, + NULL, // window menu + ::GetModuleHandle(NULL), + NULL + ); + + PIXELFORMATDESCRIPTOR pfd = { + sizeof(PIXELFORMATDESCRIPTOR), + 1, + PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, //Flags + PFD_TYPE_RGBA, // The kind of framebuffer. RGBA or palette. + 32, // Colordepth of the framebuffer. + 0, 0, 0, 0, 0, 0, + 0, + 0, + 0, + 0, 0, 0, 0, + 24, // Number of bits for the depthbuffer + 8, // Number of bits for the stencilbuffer + 0, // Number of Aux buffers in the framebuffer. + PFD_MAIN_PLANE, + 0, + 0, 0, 0 + }; + + hidden.hdc = ::GetDC(hidden.hwnd); + printf("xxx vstgltest: hidden hdc=%p\n", hidden.hdc); + + int pfmt = ::ChoosePixelFormat(hidden.hdc, &pfd); + printf("xxx vstgltest: hidden pfmt=%d\n", pfmt); + ::SetPixelFormat(hidden.hdc, pfmt, &pfd); + + hglrc = ::wglCreateContext(hidden.hdc); + printf("xxx vstgltest: hidden hglrc=%p\n", hglrc); + } + + void destroyHiddenWindow(void) { + if(NULL != hidden.hwnd) + { + ::wglDeleteContext(hglrc); + ::DestroyWindow(hidden.hwnd); + + ::UnregisterClass(EDITWIN_HIDDEN_CLASS_NAME, ::GetModuleHandle(NULL)); + } + } + + void openEditor(HWND _hwnd) { + parent_hwnd = _hwnd; + + if(NULL == registered_class_name) + { + WNDCLASS wc; + ::ZeroMemory(&wc, sizeof(wc)); + wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; + wc.lpfnWndProc = (WNDPROC) WndProc; + wc.hInstance = ::GetModuleHandle(NULL); + wc.hCursor = ::LoadCursor(NULL, IDC_ARROW); + wc.lpszClassName = EDITWIN_CLASS_NAME; + + if(!::RegisterClass(&wc)) + { + // something went terribly wrong + printf("[---] vstgltest: failed to register window class\n"); + return; + } + + registered_class_name = EDITWIN_CLASS_NAME; + } + + DWORD dwExStyle = 0; + DWORD dwStyle = WS_CHILD | WS_VISIBLE; + + editor.hwnd = ::CreateWindowEx(dwExStyle, + EDITWIN_CLASS_NAME, + "Test", + dwStyle, + 0/*xpos*/, 0/*ypos*/, + EDITWIN_W, EDITWIN_H, + parent_hwnd, + NULL, // window menu + ::GetModuleHandle(NULL), + NULL + ); + + window_to_wrapper = this; + + PIXELFORMATDESCRIPTOR pfd = { + sizeof(PIXELFORMATDESCRIPTOR), + 1, + PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, //Flags + PFD_TYPE_RGBA, // The kind of framebuffer. RGBA or palette. + 32, // Colordepth of the framebuffer. + 0, 0, 0, 0, 0, 0, + 0, + 0, + 0, + 0, 0, 0, 0, + 24, // Number of bits for the depthbuffer + 8, // Number of bits for the stencilbuffer + 0, // Number of Aux buffers in the framebuffer. + PFD_MAIN_PLANE, + 0, + 0, 0, 0 + }; + + editor.hdc = ::GetDC(editor.hwnd); + + int pfmt = ::ChoosePixelFormat(editor.hdc, &pfd); + printf("xxx vstgltest: editor pfmt=%d\n", pfmt); + ::SetPixelFormat(editor.hdc, pfmt, &pfd); + + // // hglrc = ::wglCreateContext(hdc); + } + + void closeEditor(void) { + if(NULL != editor.hwnd) + { + ::DestroyWindow(editor.hwnd); + editor.hwnd = NULL; + + // (todo) unregister when last window is closed + ::UnregisterClass(EDITWIN_CLASS_NAME, ::GetModuleHandle(NULL)); + registered_class_name = NULL; + + window_to_wrapper = NULL; + } + } + + static VSTPluginWrapper *FindWrapperByWindow(HWND hwnd) { + return window_to_wrapper; + } + + void redrawWindow(void) { + // Save host GL context + HDC hostHDC = ::wglGetCurrentDC(); + HGLRC hostHGLRC = ::wglGetCurrentContext(); + printf("xxx vstgltest: WM_PAINT: hostHDC=%p hostGLRC=%p\n", hostHDC, hostHGLRC); + + // Bind plugin GL context + printf("xxx vstgltest: WM_PAINT: pluginHDC=%p pluginGLRC=%p\n", editor.hdc, hglrc); + ::wglMakeCurrent(editor.hdc, hglrc); + + // Draw something + ::glClearColor(0.0, 1.0, clear_color, 1.0); + clear_color += 0.05f; + if(clear_color >= 1.0f) + clear_color -= 1.0f; + ::glClear(GL_COLOR_BUFFER_BIT); + ::glFlush(); + ::wglSwapLayerBuffers(editor.hdc, WGL_SWAP_MAIN_PLANE); + + // Restore host GL context + ::wglMakeCurrent(hostHDC, hostHGLRC); + } + +private: + // the host callback (a function pointer) + VSTHostCallback _vstHostCallback; + + // the actual structure required by the host + VSTPlugin _vstPlugin; +}; + +const char *VSTPluginWrapper::registered_class_name = NULL; +VSTPluginWrapper *VSTPluginWrapper::window_to_wrapper = NULL; + +extern "C" LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { + + switch(message) + { + case WM_CREATE: + printf("xxx vstgltest: WM_CREATE\n"); + break; + + case WM_DESTROY: + printf("xxx vstgltest: WM_DESTROY\n"); + break; + + case WM_LBUTTONDOWN: + printf("xxx vstgltest: WM_LBUTTONDOWN\n"); + break; + + case WM_LBUTTONUP: + printf("xxx vstgltest: WM_LBUTTONUP\n"); + break; + + case WM_PAINT: + // https://docs.microsoft.com/en-us/windows/desktop/api/Winuser/nf-winuser-redrawwindow + printf("xxx vstgltest: WM_PAINT\n"); + VSTPluginWrapper *wrapper = VSTPluginWrapper::FindWrapperByWindow(hWnd); + wrapper->redrawWindow(); + break; + } + + return DefWindowProc(hWnd, message, wParam, lParam); +} + +/******************************************* + * Callbacks: Host -> Plugin + * + * Defined here because they are used in the rest of the code later + */ + +/** + * This is the callback that will be called to process the samples in the case of single precision. This is where the + * meat of the logic happens! + * + * @param vstPlugin the object returned by VSTPluginMain + * @param inputs an array of array of input samples. You read from it. First dimension is for inputs, second dimension is for samples: inputs[numInputs][sampleFrames] + * @param outputs an array of array of output samples. You write to it. First dimension is for outputs, second dimension is for samples: outputs[numOuputs][sampleFrames] + * @param sampleFrames the number of samples (second dimension in both arrays) + */ +void VSTPluginProcessSamplesFloat32(VSTPlugin *vstPlugin, float **inputs, float **outputs, VstInt32 sampleFrames) +{ + // we can get a hold to our C++ class since we stored it in the `object` field (see constructor) + VSTPluginWrapper *wrapper = static_cast(vstPlugin->object); + + // code speaks for itself: for each input (2 when stereo input), iterating over every sample and writing the + // result in the outputs array after multiplying by 0.5 (which result in a 3dB attenuation of the sound) + for(int i = 0; i < wrapper->getNumInputs(); i++) + { + auto inputSamples = inputs[i]; + auto outputSamples = outputs[i]; + for(int j = 0; j < sampleFrames; j++) + { + outputSamples[j] = inputSamples[j] * 0.5f; + } + } +} + +/** + * This is the callback that will be called to process the samples in the case of double precision. This is where the + * meat of the logic happens! + * + * @param vstPlugin the object returned by VSTPluginMain + * @param inputs an array of array of input samples. You read from it. First dimension is for inputs, second dimension is for samples: inputs[numInputs][sampleFrames] + * @param outputs an array of array of output samples. You write to it. First dimension is for outputs, second dimension is for samples: outputs[numOuputs][sampleFrames] + * @param sampleFrames the number of samples (second dimension in both arrays) + */ +void VSTPluginProcessSamplesFloat64(VSTPlugin *vstPlugin, double **inputs, double **outputs, VstInt32 sampleFrames) +{ + // we can get a hold to our C++ class since we stored it in the `object` field (see constructor) + VSTPluginWrapper *wrapper = static_cast(vstPlugin->object); + + // code speaks for itself: for each input (2 when stereo input), iterating over every sample and writing the + // result in the outputs array after multiplying by 0.5 (which result in a 3dB attenuation of the sound) + for(int i = 0; i < wrapper->getNumInputs(); i++) + { + auto inputSamples = inputs[i]; + auto outputSamples = outputs[i]; + for(int j = 0; j < sampleFrames; j++) + { + outputSamples[j] = inputSamples[j] * 0.5; + } + } +} + +/** + * This is the plugin called by the host to communicate with the plugin, mainly to request information (like the + * vendor string, the plugin category...) or communicate state/changes (like open/close, frame rate...) + * + * @param vstPlugin the object returned by VSTPluginMain + * @param opCode defined in aeffect.h/AEffectOpcodes and which continues in aeffectx.h/AEffectXOpcodes for a grand + * total of 79 of them! Only a few of them are implemented in this small plugin. + * @param index depend on the opcode + * @param value depend on the opcode + * @param ptr depend on the opcode + * @param opt depend on the opcode + * @return depend on the opcode (0 is ok when you don't implement an opcode...) + */ +VstIntPtr VSTPluginDispatcher(VSTPlugin *vstPlugin, VstInt32 opCode, VstInt32 index, VstIntPtr value, void *ptr, float opt) +{ + printf("vstgltest: called VSTPluginDispatcher(%d)\n", opCode); + + VstIntPtr r = 0; + + // we can get a hold to our C++ class since we stored it in the `object` field (see constructor) + VSTPluginWrapper *wrapper = static_cast(vstPlugin->object); + // see aeffect.h/AEffectOpcodes and aeffectx.h/AEffectXOpcodes for details on all of them + switch(opCode) + { + // request for the category of the plugin: in this case it is an effect since it is modifying the input (as opposed + // to generating sound) + case effGetPlugCategory: + return kPlugCategEffect; + + // called by the host when the plugin was called... time to reclaim memory! + case effClose: + delete wrapper; + break; + + case effGetEffectName: + ::strncpy((char*)ptr, "VST GL Test", kVstMaxEffectNameLen); + r = 1; + break; + + // request for the vendor string (usually used in the UI for plugin grouping) + case effGetVendorString: + strncpy(static_cast(ptr), "bsp", kVstMaxVendorStrLen); + r = 1; + break; + + // request for the version + case effGetVendorVersion: + return PLUGIN_VERSION; + + case effEditIdle: + if(NULL != wrapper->editor.hwnd) + { + printf("xxx vstgltest: redraw window\n"); + // (void)::RedrawWindow(wrapper->hwnd, NULL, NULL, RDW_INTERNALPAINT); + //(void)::UpdateWindow(wrapper->hwnd); + if(::IsWindowVisible(wrapper->editor.hwnd)) + { + wrapper->redrawWindow(); + } + } + break; + + case effEditGetRect: + // Query editor window geometry + // ptr: ERect* (on Windows) + if(NULL != ptr) // yeah, this should never be NULL + { + // ... + wrapper->editor_rect.left = EDITWIN_X; + wrapper->editor_rect.top = EDITWIN_Y; + wrapper->editor_rect.right = EDITWIN_X + EDITWIN_W; + wrapper->editor_rect.bottom = EDITWIN_Y + EDITWIN_H; + *(void**)ptr = (void*) &wrapper->editor_rect; + r = 1; + } + else + { + r = 0; + } + break; + +#if 0 + case effEditTop: + // deprecated in vst2.4 + r = 0; + break; +#endif + + case effEditOpen: + // Show editor window + // ptr: native window handle (hWnd on Windows) + wrapper->openEditor((HWND)ptr); + r = 1; + break; + + case effEditClose: + // Hide editor window + wrapper->closeEditor(); + r = 1; + break; + + // ignoring all other opcodes + default: + printf("Unknown opCode %d [ignored] \n", opCode); + break; + } + + return r; +} + +/** + * Used for parameter setting (not used by this plugin) + */ +void VSTPluginSetParameter(VSTPlugin *vstPlugin, VstInt32 index, float parameter) +{ + printf("called VSTPluginSetParameter(%d, %f)\n", index, parameter); + // we can get a hold to our C++ class since we stored it in the `object` field (see constructor) + VSTPluginWrapper *wrapper = static_cast(vstPlugin->object); +} + +/** + * Used for parameter (not used by this plugin) + */ +float VSTPluginGetParameter(VSTPlugin *vstPlugin, VstInt32 index) +{ + printf("called VSTPluginGetParameter(%d)\n", index); + // we can get a hold to our C++ class since we stored it in the `object` field (see constructor) + VSTPluginWrapper *wrapper = static_cast(vstPlugin->object); + return 0; +} + +/** + * Main constructor for our C++ class + */ +VSTPluginWrapper::VSTPluginWrapper(audioMasterCallback vstHostCallback, + VstInt32 vendorUniqueID, + VstInt32 vendorVersion, + VstInt32 numParams, + VstInt32 numPrograms, + VstInt32 numInputs, + VstInt32 numOutputs) : + _vstHostCallback(vstHostCallback) +{ + // Make sure that the memory is properly initialized + memset(&_vstPlugin, 0, sizeof(_vstPlugin)); + + // this field must be set with this constant... + _vstPlugin.magic = kEffectMagic; + + // storing this object into the VSTPlugin so that it can be retrieved when called back (see callbacks for use) + _vstPlugin.object = this; + + // specifying that we handle both single and double precision (there are other flags see aeffect.h/VstAEffectFlags) + _vstPlugin.flags = effFlagsCanReplacing | effFlagsCanDoubleReplacing | effFlagsHasEditor; + + // initializing the plugin with the various values + _vstPlugin.uniqueID = vendorUniqueID; + _vstPlugin.version = vendorVersion; + _vstPlugin.numParams = numParams; + _vstPlugin.numPrograms = numPrograms; + _vstPlugin.numInputs = numInputs; + _vstPlugin.numOutputs = numOutputs; + + // setting the callbacks to the previously defined functions + _vstPlugin.dispatcher = VSTPluginDispatcher; + _vstPlugin.getParameter = VSTPluginGetParameter; + _vstPlugin.setParameter = VSTPluginSetParameter; + _vstPlugin.processReplacing = VSTPluginProcessSamplesFloat32; + _vstPlugin.processDoubleReplacing = VSTPluginProcessSamplesFloat64; + + parent_hwnd = NULL; + + hidden.hwnd = NULL; + hidden.hdc = NULL; + + editor.hwnd = NULL; + editor.hdc = NULL; + + hglrc = NULL; + + createHiddenWindow(); +} + +/** + * Destructor called when the plugin is closed (see VSTPluginDispatcher with effClose opCode). In this very simply plugin + * there is nothing to do but in general the memory that gets allocated MUST be freed here otherwise there might be a + * memory leak which may end up slowing down and/or crashing the host + */ +VSTPluginWrapper::~VSTPluginWrapper() { + destroyHiddenWindow(); +} + +/** + * Implementation of the main entry point of the plugin + */ +VST_EXPORT VSTPlugin *VSTPluginMain(VSTHostCallback vstHostCallback) +{ + printf("called VSTPluginMain... \n"); + + // simply create our plugin C++ class + VSTPluginWrapper *plugin = + new VSTPluginWrapper(vstHostCallback, + CCONST('u', 's', 'a', '§'), // registered with Steinberg (http://service.steinberg.de/databases/plugin.nsf/plugIn?openForm) + PLUGIN_VERSION, // version + 0, // no params + 0, // no programs + 2, // 2 inputs + 2); // 2 outputs + + // return the plugin per the contract of the API + return plugin->getVSTPlugin(); +} diff --git a/other/vst2_lglw_debug_plugin/plugin.cpp__SIMPLE b/other/vst2_lglw_debug_plugin/plugin.cpp__SIMPLE new file mode 100644 index 00000000..5af8e7ba --- /dev/null +++ b/other/vst2_lglw_debug_plugin/plugin.cpp__SIMPLE @@ -0,0 +1,527 @@ + + +#include +#include +#include + +#if defined(_WIN32) || defined(_WIN64) +#include +#include + #define VST_EXPORT extern "C" __declspec(dllexport) +#else + #define VST_EXPORT extern +#endif + +#include + +#define EDITWIN_X 20 +#define EDITWIN_Y 20 +#define EDITWIN_W 640 +#define EDITWIN_H 480 +#define EDITWIN_CLASS_NAME "VeeSeeVSTWindow" + +/* + * I find the naming a bit confusing so I decided to use more meaningful names instead. + */ + +/** + * The VSTHostCallback is a function pointer so that the plugin can communicate with the host (not used in this small example) + */ +typedef audioMasterCallback VSTHostCallback; + +/** + * The VSTPlugin structure (AEffect) contains information about the plugin (like version, number of inputs, ...) and + * callbacks so that the host can call the plugin to do its work. The primary callback will be `processReplacing` for + * single precision (float) sample processing (or `processDoubleReplacing` for double precision (double)). + */ +typedef AEffect VSTPlugin; + + +// Since the host is expecting a very specific API we need to make sure it has C linkage (not C++) +extern "C" { + +/* + * This is the main entry point to the VST plugin. + * + * The host (DAW like Maschine, Ableton Live, Reason, ...) will look for this function with this exact API. + * + * It is the equivalent to `int main(int argc, char *argv[])` for a C executable. + * + * @param vstHostCallback is a callback so that the plugin can communicate with the host (not used in this small example) + * @return a pointer to the AEffect structure + */ +VST_EXPORT VSTPlugin *VSTPluginMain(VSTHostCallback vstHostCallback); + +// note this looks like this without the type aliases (and is obviously 100% equivalent) +// extern AEffect *VSTPluginMain(audioMasterCallback audioMaster); + +} + +/* + * Constant for the version of the plugin. For example 1100 for version 1.1.0.0 + */ +const VstInt32 PLUGIN_VERSION = 1000; + +extern "C" LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); + +/** + * Encapsulates the plugin as a C++ class. It will keep both the host callback and the structure required by the + * host (VSTPlugin). This class will be stored in the `VSTPlugin.object` field (circular reference) so that it can + * be accessed when the host calls the plugin back (for example in `processDoubleReplacing`). + */ +class VSTPluginWrapper +{ +public: + ERect editor_rect; + HWND parent_hwnd; // created by host + HWND hwnd; + HDC hdc; + HGLRC hglrc; + + float clear_color = 0.0f; + + static const char *registered_class_name; + static VSTPluginWrapper *window_to_wrapper; + +public: + VSTPluginWrapper(VSTHostCallback vstHostCallback, + VstInt32 vendorUniqueID, + VstInt32 vendorVersion, + VstInt32 numParams, + VstInt32 numPrograms, + VstInt32 numInputs, + VstInt32 numOutputs); + + ~VSTPluginWrapper(); + + inline VSTPlugin *getVSTPlugin() + { + return &_vstPlugin; + } + + inline VstInt32 getNumInputs() const + { + return _vstPlugin.numInputs; + } + + inline VstInt32 getNumOutputs() const + { + return _vstPlugin.numOutputs; + } + + void openEditor(HWND _hwnd) { + parent_hwnd = _hwnd; + + if(NULL == registered_class_name) + { + WNDCLASS wc; + ::ZeroMemory(&wc, sizeof(wc)); + wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; + wc.lpfnWndProc = (WNDPROC) WndProc; + wc.hInstance = ::GetModuleHandle(NULL); + wc.hCursor = ::LoadCursor(NULL, IDC_ARROW); + wc.lpszClassName = EDITWIN_CLASS_NAME; + + if(!::RegisterClass(&wc)) + { + // something went terribly wrong + printf("[---] vstgltest: failed to register window class\n"); + return; + } + + registered_class_name = EDITWIN_CLASS_NAME; + } + + DWORD dwExStyle = 0; + DWORD dwStyle = WS_CHILD | WS_VISIBLE; + + hwnd = ::CreateWindowEx(dwExStyle, + EDITWIN_CLASS_NAME, + "Test", + dwStyle, + 0/*xpos*/, 0/*ypos*/, + EDITWIN_W, EDITWIN_H, + parent_hwnd, + NULL, // window menu + ::GetModuleHandle(NULL), + NULL + ); + + window_to_wrapper = this; + + PIXELFORMATDESCRIPTOR pfd = { + sizeof(PIXELFORMATDESCRIPTOR), + 1, + PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, //Flags + PFD_TYPE_RGBA, // The kind of framebuffer. RGBA or palette. + 32, // Colordepth of the framebuffer. + 0, 0, 0, 0, 0, 0, + 0, + 0, + 0, + 0, 0, 0, 0, + 24, // Number of bits for the depthbuffer + 8, // Number of bits for the stencilbuffer + 0, // Number of Aux buffers in the framebuffer. + PFD_MAIN_PLANE, + 0, + 0, 0, 0 + }; + + hdc = ::GetDC(hwnd); + + int pfmt = ::ChoosePixelFormat(hdc, &pfd); + printf("xxx vstgltest: pfmt=%d", pfmt); + ::SetPixelFormat(hdc, pfmt, &pfd); + + hglrc = ::wglCreateContext(hdc); + } + + void closeEditor(void) { + if(NULL != hwnd) + { + ::wglDeleteContext(hglrc); + ::DestroyWindow(hwnd); + + // (todo) unregister when last window is closed + ::UnregisterClass(EDITWIN_CLASS_NAME, ::GetModuleHandle(NULL)); + registered_class_name = NULL; + + window_to_wrapper = NULL; + } + } + + static VSTPluginWrapper *FindWrapperByWindow(HWND hwnd) { + return window_to_wrapper; + } + + void redrawWindow(void) { + // Save host GL context + HDC hostHDC = ::wglGetCurrentDC(); + HGLRC hostHGLRC = ::wglGetCurrentContext(); + printf("xxx vstgltest: WM_PAINT: hostHDC=%p hostGLRC=%p\n", hostHDC, hostHGLRC); + + // Bind plugin GL context + printf("xxx vstgltest: WM_PAINT: pluginHDC=%p pluginGLRC=%p\n", hdc, hglrc); + ::wglMakeCurrent(hdc, hglrc); + + // Draw something + ::glClearColor(0.0, 1.0, clear_color, 1.0); + clear_color += 0.05f; + if(clear_color >= 1.0f) + clear_color -= 1.0f; + ::glClear(GL_COLOR_BUFFER_BIT); + ::glFlush(); + ::wglSwapLayerBuffers(hdc, WGL_SWAP_MAIN_PLANE); + + // Restore host GL context + ::wglMakeCurrent(hostHDC, hostHGLRC); + } + +private: + // the host callback (a function pointer) + VSTHostCallback _vstHostCallback; + + // the actual structure required by the host + VSTPlugin _vstPlugin; +}; + +const char *VSTPluginWrapper::registered_class_name = NULL; +VSTPluginWrapper *VSTPluginWrapper::window_to_wrapper = NULL; + +extern "C" LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { + + switch(message) + { + case WM_CREATE: + printf("xxx vstgltest: WM_CREATE\n"); + break; + + case WM_DESTROY: + printf("xxx vstgltest: WM_DESTROY\n"); + break; + + case WM_LBUTTONDOWN: + printf("xxx vstgltest: WM_LBUTTONDOWN\n"); + break; + + case WM_LBUTTONUP: + printf("xxx vstgltest: WM_LBUTTONUP\n"); + break; + + case WM_PAINT: + // https://docs.microsoft.com/en-us/windows/desktop/api/Winuser/nf-winuser-redrawwindow + printf("xxx vstgltest: WM_PAINT\n"); + VSTPluginWrapper *wrapper = VSTPluginWrapper::FindWrapperByWindow(hWnd); + wrapper->redrawWindow(); + break; + } + + return DefWindowProc(hWnd, message, wParam, lParam); +} + +/******************************************* + * Callbacks: Host -> Plugin + * + * Defined here because they are used in the rest of the code later + */ + +/** + * This is the callback that will be called to process the samples in the case of single precision. This is where the + * meat of the logic happens! + * + * @param vstPlugin the object returned by VSTPluginMain + * @param inputs an array of array of input samples. You read from it. First dimension is for inputs, second dimension is for samples: inputs[numInputs][sampleFrames] + * @param outputs an array of array of output samples. You write to it. First dimension is for outputs, second dimension is for samples: outputs[numOuputs][sampleFrames] + * @param sampleFrames the number of samples (second dimension in both arrays) + */ +void VSTPluginProcessSamplesFloat32(VSTPlugin *vstPlugin, float **inputs, float **outputs, VstInt32 sampleFrames) +{ + // we can get a hold to our C++ class since we stored it in the `object` field (see constructor) + VSTPluginWrapper *wrapper = static_cast(vstPlugin->object); + + // code speaks for itself: for each input (2 when stereo input), iterating over every sample and writing the + // result in the outputs array after multiplying by 0.5 (which result in a 3dB attenuation of the sound) + for(int i = 0; i < wrapper->getNumInputs(); i++) + { + auto inputSamples = inputs[i]; + auto outputSamples = outputs[i]; + for(int j = 0; j < sampleFrames; j++) + { + outputSamples[j] = inputSamples[j] * 0.5f; + } + } +} + +/** + * This is the callback that will be called to process the samples in the case of double precision. This is where the + * meat of the logic happens! + * + * @param vstPlugin the object returned by VSTPluginMain + * @param inputs an array of array of input samples. You read from it. First dimension is for inputs, second dimension is for samples: inputs[numInputs][sampleFrames] + * @param outputs an array of array of output samples. You write to it. First dimension is for outputs, second dimension is for samples: outputs[numOuputs][sampleFrames] + * @param sampleFrames the number of samples (second dimension in both arrays) + */ +void VSTPluginProcessSamplesFloat64(VSTPlugin *vstPlugin, double **inputs, double **outputs, VstInt32 sampleFrames) +{ + // we can get a hold to our C++ class since we stored it in the `object` field (see constructor) + VSTPluginWrapper *wrapper = static_cast(vstPlugin->object); + + // code speaks for itself: for each input (2 when stereo input), iterating over every sample and writing the + // result in the outputs array after multiplying by 0.5 (which result in a 3dB attenuation of the sound) + for(int i = 0; i < wrapper->getNumInputs(); i++) + { + auto inputSamples = inputs[i]; + auto outputSamples = outputs[i]; + for(int j = 0; j < sampleFrames; j++) + { + outputSamples[j] = inputSamples[j] * 0.5; + } + } +} + +/** + * This is the plugin called by the host to communicate with the plugin, mainly to request information (like the + * vendor string, the plugin category...) or communicate state/changes (like open/close, frame rate...) + * + * @param vstPlugin the object returned by VSTPluginMain + * @param opCode defined in aeffect.h/AEffectOpcodes and which continues in aeffectx.h/AEffectXOpcodes for a grand + * total of 79 of them! Only a few of them are implemented in this small plugin. + * @param index depend on the opcode + * @param value depend on the opcode + * @param ptr depend on the opcode + * @param opt depend on the opcode + * @return depend on the opcode (0 is ok when you don't implement an opcode...) + */ +VstIntPtr VSTPluginDispatcher(VSTPlugin *vstPlugin, VstInt32 opCode, VstInt32 index, VstIntPtr value, void *ptr, float opt) +{ + printf("vstgltest: called VSTPluginDispatcher(%d)\n", opCode); + + VstIntPtr r = 0; + + // we can get a hold to our C++ class since we stored it in the `object` field (see constructor) + VSTPluginWrapper *wrapper = static_cast(vstPlugin->object); + // see aeffect.h/AEffectOpcodes and aeffectx.h/AEffectXOpcodes for details on all of them + switch(opCode) + { + // request for the category of the plugin: in this case it is an effect since it is modifying the input (as opposed + // to generating sound) + case effGetPlugCategory: + return kPlugCategEffect; + + // called by the host when the plugin was called... time to reclaim memory! + case effClose: + delete wrapper; + break; + + case effGetEffectName: + ::strncpy((char*)ptr, "VST GL Test", kVstMaxEffectNameLen); + r = 1; + break; + + // request for the vendor string (usually used in the UI for plugin grouping) + case effGetVendorString: + strncpy(static_cast(ptr), "bsp", kVstMaxVendorStrLen); + r = 1; + break; + + // request for the version + case effGetVendorVersion: + return PLUGIN_VERSION; + + case effEditIdle: + if(NULL != wrapper->hwnd) + { + printf("xxx vstgltest: redraw window\n"); + // (void)::RedrawWindow(wrapper->hwnd, NULL, NULL, RDW_INTERNALPAINT); + //(void)::UpdateWindow(wrapper->hwnd); + if(::IsWindowVisible(wrapper->hwnd)) + { + wrapper->redrawWindow(); + } + } + break; + + case effEditGetRect: + // Query editor window geometry + // ptr: ERect* (on Windows) + if(NULL != ptr) // yeah, this should never be NULL + { + // ... + wrapper->editor_rect.left = EDITWIN_X; + wrapper->editor_rect.top = EDITWIN_Y; + wrapper->editor_rect.right = EDITWIN_X + EDITWIN_W; + wrapper->editor_rect.bottom = EDITWIN_Y + EDITWIN_H; + *(void**)ptr = (void*) &wrapper->editor_rect; + r = 1; + } + else + { + r = 0; + } + break; + +#if 0 + case effEditTop: + // deprecated in vst2.4 + r = 0; + break; +#endif + + case effEditOpen: + // Show editor window + // ptr: native window handle (hWnd on Windows) + wrapper->openEditor((HWND)ptr); + r = 1; + break; + + case effEditClose: + // Hide editor window + wrapper->closeEditor(); + r = 1; + break; + + // ignoring all other opcodes + default: + printf("Unknown opCode %d [ignored] \n", opCode); + break; + } + + return r; +} + +/** + * Used for parameter setting (not used by this plugin) + */ +void VSTPluginSetParameter(VSTPlugin *vstPlugin, VstInt32 index, float parameter) +{ + printf("called VSTPluginSetParameter(%d, %f)\n", index, parameter); + // we can get a hold to our C++ class since we stored it in the `object` field (see constructor) + VSTPluginWrapper *wrapper = static_cast(vstPlugin->object); +} + +/** + * Used for parameter (not used by this plugin) + */ +float VSTPluginGetParameter(VSTPlugin *vstPlugin, VstInt32 index) +{ + printf("called VSTPluginGetParameter(%d)\n", index); + // we can get a hold to our C++ class since we stored it in the `object` field (see constructor) + VSTPluginWrapper *wrapper = static_cast(vstPlugin->object); + return 0; +} + +/** + * Main constructor for our C++ class + */ +VSTPluginWrapper::VSTPluginWrapper(audioMasterCallback vstHostCallback, + VstInt32 vendorUniqueID, + VstInt32 vendorVersion, + VstInt32 numParams, + VstInt32 numPrograms, + VstInt32 numInputs, + VstInt32 numOutputs) : + _vstHostCallback(vstHostCallback) +{ + // Make sure that the memory is properly initialized + memset(&_vstPlugin, 0, sizeof(_vstPlugin)); + + // this field must be set with this constant... + _vstPlugin.magic = kEffectMagic; + + // storing this object into the VSTPlugin so that it can be retrieved when called back (see callbacks for use) + _vstPlugin.object = this; + + // specifying that we handle both single and double precision (there are other flags see aeffect.h/VstAEffectFlags) + _vstPlugin.flags = effFlagsCanReplacing | effFlagsCanDoubleReplacing | effFlagsHasEditor; + + // initializing the plugin with the various values + _vstPlugin.uniqueID = vendorUniqueID; + _vstPlugin.version = vendorVersion; + _vstPlugin.numParams = numParams; + _vstPlugin.numPrograms = numPrograms; + _vstPlugin.numInputs = numInputs; + _vstPlugin.numOutputs = numOutputs; + + // setting the callbacks to the previously defined functions + _vstPlugin.dispatcher = VSTPluginDispatcher; + _vstPlugin.getParameter = VSTPluginGetParameter; + _vstPlugin.setParameter = VSTPluginSetParameter; + _vstPlugin.processReplacing = VSTPluginProcessSamplesFloat32; + _vstPlugin.processDoubleReplacing = VSTPluginProcessSamplesFloat64; + + parent_hwnd = NULL; + hwnd = NULL; + hdc = NULL; + hglrc = NULL; +} + +/** + * Destructor called when the plugin is closed (see VSTPluginDispatcher with effClose opCode). In this very simply plugin + * there is nothing to do but in general the memory that gets allocated MUST be freed here otherwise there might be a + * memory leak which may end up slowing down and/or crashing the host + */ +VSTPluginWrapper::~VSTPluginWrapper() +{ +} + +/** + * Implementation of the main entry point of the plugin + */ +VST_EXPORT VSTPlugin *VSTPluginMain(VSTHostCallback vstHostCallback) +{ + printf("called VSTPluginMain... \n"); + + // simply create our plugin C++ class + VSTPluginWrapper *plugin = + new VSTPluginWrapper(vstHostCallback, + CCONST('u', 's', 'a', '§'), // registered with Steinberg (http://service.steinberg.de/databases/plugin.nsf/plugIn?openForm) + PLUGIN_VERSION, // version + 0, // no params + 0, // no programs + 2, // 2 inputs + 2); // 2 outputs + + // return the plugin per the contract of the API + return plugin->getVSTPlugin(); +} diff --git a/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db.sln b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db.sln new file mode 100644 index 00000000..b963cfb1 --- /dev/null +++ b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.27130.2024 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "m3db", "m3db\m3db.vcxproj", "{ADEB3292-4BBF-4B20-9A11-3D8076423F16}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {ADEB3292-4BBF-4B20-9A11-3D8076423F16}.Debug|x64.ActiveCfg = Debug|x64 + {ADEB3292-4BBF-4B20-9A11-3D8076423F16}.Debug|x64.Build.0 = Debug|x64 + {ADEB3292-4BBF-4B20-9A11-3D8076423F16}.Debug|x86.ActiveCfg = Debug|Win32 + {ADEB3292-4BBF-4B20-9A11-3D8076423F16}.Debug|x86.Build.0 = Debug|Win32 + {ADEB3292-4BBF-4B20-9A11-3D8076423F16}.Release|x64.ActiveCfg = Release|x64 + {ADEB3292-4BBF-4B20-9A11-3D8076423F16}.Release|x64.Build.0 = Release|x64 + {ADEB3292-4BBF-4B20-9A11-3D8076423F16}.Release|x86.ActiveCfg = Release|Win32 + {ADEB3292-4BBF-4B20-9A11-3D8076423F16}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {A1B75069-8782-4AB1-A661-12FED71250D4} + EndGlobalSection +EndGlobal diff --git a/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/dllmain.cpp b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/dllmain.cpp new file mode 100644 index 00000000..16373032 Binary files /dev/null and b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/dllmain.cpp differ diff --git a/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/m3db.cpp b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/m3db.cpp new file mode 100644 index 00000000..c7ab7b7a Binary files /dev/null and b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/m3db.cpp differ diff --git a/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/m3db.vcxproj b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/m3db.vcxproj new file mode 100644 index 00000000..402899c1 --- /dev/null +++ b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/m3db.vcxproj @@ -0,0 +1,167 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {ADEB3292-4BBF-4B20-9A11-3D8076423F16} + Win32Proj + m3db + 10.0.16299.0 + + + + DynamicLibrary + true + v141 + Unicode + + + DynamicLibrary + false + v141 + true + Unicode + + + DynamicLibrary + true + v141 + Unicode + + + DynamicLibrary + false + v141 + true + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + NotUsing + Level3 + Disabled + true + WIN32;_DEBUG;M3DB_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + f:\dev\vstsdk2.4 + + + Windows + true + + + + + NotUsing + Level3 + Disabled + true + _DEBUG;M3DB_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + + + Windows + true + + + + + NotUsing + Level3 + MaxSpeed + true + true + true + WIN32;NDEBUG;M3DB_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + f:\dev\vstsdk2.4 + None + + + + + Windows + true + true + false + + + + + NotUsing + Level3 + MaxSpeed + true + true + true + NDEBUG;M3DB_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions);_CRT_SECURE_NO_DEPRECATE + true + F:\git\VeeSeeVSTRack\dep\lglw;f:\dev\vstsdk2.4\pluginterfaces\vst2.x\ + None + + + Windows + true + true + false + opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + + + + + + + + + + \ No newline at end of file diff --git a/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/m3db.vcxproj.filters b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/m3db.vcxproj.filters new file mode 100644 index 00000000..abfd8b6a --- /dev/null +++ b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/m3db.vcxproj.filters @@ -0,0 +1,33 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + Source Files + + + Source Files + + + + + Source Files + + + \ No newline at end of file diff --git a/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/m3db.vcxproj.user b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/m3db.vcxproj.user new file mode 100644 index 00000000..6e2aec7a --- /dev/null +++ b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/m3db.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/stdafx.cpp b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/stdafx.cpp new file mode 100644 index 00000000..64433cdd Binary files /dev/null and b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/stdafx.cpp differ diff --git a/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/stdafx.h b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/stdafx.h new file mode 100644 index 00000000..b937b12c Binary files /dev/null and b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/stdafx.h differ diff --git a/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/targetver.h b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/targetver.h new file mode 100644 index 00000000..567cd346 Binary files /dev/null and b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/targetver.h differ diff --git a/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Debug/m3db.Build.CppClean.log b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Debug/m3db.Build.CppClean.log new file mode 100644 index 00000000..3b09514e --- /dev/null +++ b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Debug/m3db.Build.CppClean.log @@ -0,0 +1,5 @@ +f:\projects\research\pongasoft_vst24-hello-world-master\m3db\vs2017\m3db\m3db\x64\debug\vc141.pdb +f:\projects\research\pongasoft_vst24-hello-world-master\m3db\vs2017\m3db\m3db\x64\debug\vc141.idb +f:\projects\research\pongasoft_vst24-hello-world-master\m3db\vs2017\m3db\m3db\x64\debug\m3db.tlog\cl.command.1.tlog +f:\projects\research\pongasoft_vst24-hello-world-master\m3db\vs2017\m3db\m3db\x64\debug\m3db.tlog\cl.read.1.tlog +f:\projects\research\pongasoft_vst24-hello-world-master\m3db\vs2017\m3db\m3db\x64\debug\m3db.tlog\cl.write.1.tlog diff --git a/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Debug/m3db.log b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Debug/m3db.log new file mode 100644 index 00000000..61f69062 --- /dev/null +++ b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Debug/m3db.log @@ -0,0 +1,2 @@ + plugin.cpp +f:\projects\research\pongasoft_vst24-hello-world-master\m3db\plugin.cpp(3): fatal error C1083: Cannot open include file: 'aeffect.h': No such file or directory diff --git a/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Debug/m3db.tlog/CL.command.1.tlog b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Debug/m3db.tlog/CL.command.1.tlog new file mode 100644 index 00000000..953482d8 Binary files /dev/null and b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Debug/m3db.tlog/CL.command.1.tlog differ diff --git a/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Debug/m3db.tlog/CL.read.1.tlog b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Debug/m3db.tlog/CL.read.1.tlog new file mode 100644 index 00000000..f667ffbe Binary files /dev/null and b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Debug/m3db.tlog/CL.read.1.tlog differ diff --git a/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Debug/m3db.tlog/CL.write.1.tlog b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Debug/m3db.tlog/CL.write.1.tlog new file mode 100644 index 00000000..ac9a2c4d Binary files /dev/null and b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Debug/m3db.tlog/CL.write.1.tlog differ diff --git a/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Debug/m3db.tlog/m3db.lastbuildstate b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Debug/m3db.tlog/m3db.lastbuildstate new file mode 100644 index 00000000..8639be57 --- /dev/null +++ b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Debug/m3db.tlog/m3db.lastbuildstate @@ -0,0 +1,2 @@ +#TargetFrameworkVersion=v4.0:PlatformToolSet=v141:EnableManagedIncrementalBuild=false:VCToolArchitecture=Native32Bit:WindowsTargetPlatformVersion=10.0.16299.0 +Debug|x64|F:\Projects\research\pongasoft_vst24-hello-world-master\M3dB\vs2017\m3db\| diff --git a/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Debug/m3db.tlog/unsuccessfulbuild b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Debug/m3db.tlog/unsuccessfulbuild new file mode 100644 index 00000000..e69de29b diff --git a/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Debug/vc141.idb b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Debug/vc141.idb new file mode 100644 index 00000000..6c9d354e Binary files /dev/null and b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Debug/vc141.idb differ diff --git a/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Debug/vc141.pdb b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Debug/vc141.pdb new file mode 100644 index 00000000..37d52c35 Binary files /dev/null and b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Debug/vc141.pdb differ diff --git a/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Release/lglw_windows.obj b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Release/lglw_windows.obj new file mode 100644 index 00000000..de8cdca0 Binary files /dev/null and b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Release/lglw_windows.obj differ diff --git a/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Release/lglw_windows_cpp.obj b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Release/lglw_windows_cpp.obj new file mode 100644 index 00000000..9089efd7 Binary files /dev/null and b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Release/lglw_windows_cpp.obj differ diff --git a/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Release/m3db.Build.CppClean.log b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Release/m3db.Build.CppClean.log new file mode 100644 index 00000000..1b92334d --- /dev/null +++ b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Release/m3db.Build.CppClean.log @@ -0,0 +1,15 @@ +f:\projects\research\vst24_gl_test\m3db\vs2017\m3db\m3db\x64\release\plugin.obj +f:\projects\research\vst24_gl_test\m3db\vs2017\m3db\m3db\x64\release\lglw_windows.obj +f:\projects\research\vst24_gl_test\m3db\vs2017\m3db\m3db\x64\release\lglw_windows_cpp.obj +f:\projects\research\vst24_gl_test\m3db\vs2017\m3db\x64\release\m3db.dll +f:\projects\research\vst24_gl_test\m3db\vs2017\m3db\x64\release\m3db.lib +f:\projects\research\vst24_gl_test\m3db\vs2017\m3db\x64\release\m3db.exp +f:\projects\research\vst24_gl_test\m3db\vs2017\m3db\x64\release\m3db.ipdb +f:\projects\research\vst24_gl_test\m3db\vs2017\m3db\x64\release\m3db.iobj +f:\projects\research\vst24_gl_test\m3db\vs2017\m3db\m3db\x64\release\m3db.tlog\cl.command.1.tlog +f:\projects\research\vst24_gl_test\m3db\vs2017\m3db\m3db\x64\release\m3db.tlog\cl.read.1.tlog +f:\projects\research\vst24_gl_test\m3db\vs2017\m3db\m3db\x64\release\m3db.tlog\cl.write.1.tlog +f:\projects\research\vst24_gl_test\m3db\vs2017\m3db\m3db\x64\release\m3db.tlog\link.command.1.tlog +f:\projects\research\vst24_gl_test\m3db\vs2017\m3db\m3db\x64\release\m3db.tlog\link.read.1.tlog +f:\projects\research\vst24_gl_test\m3db\vs2017\m3db\m3db\x64\release\m3db.tlog\link.write.1.tlog +f:\projects\research\vst24_gl_test\m3db\vs2017\m3db\m3db\x64\release\m3db.tlog\m3db.write.1u.tlog diff --git a/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Release/m3db.log b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Release/m3db.log new file mode 100644 index 00000000..342b7676 --- /dev/null +++ b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Release/m3db.log @@ -0,0 +1,8 @@ + lglw_windows.c + lglw_windows_cpp.cpp + plugin.cpp + Creating library F:\Projects\research\vst24_gl_test\M3dB\vs2017\m3db\x64\Release\m3db.lib and object F:\Projects\research\vst24_gl_test\M3dB\vs2017\m3db\x64\Release\m3db.exp + Generating code + All 57 functions were compiled because no usable IPDB/IOBJ from previous compilation was found. + Finished generating code + m3db.vcxproj -> F:\Projects\research\vst24_gl_test\M3dB\vs2017\m3db\x64\Release\m3db.dll diff --git a/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Release/m3db.tlog/CL.command.1.tlog b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Release/m3db.tlog/CL.command.1.tlog new file mode 100644 index 00000000..d000e258 Binary files /dev/null and b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Release/m3db.tlog/CL.command.1.tlog differ diff --git a/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Release/m3db.tlog/CL.read.1.tlog b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Release/m3db.tlog/CL.read.1.tlog new file mode 100644 index 00000000..a1e3d7fc Binary files /dev/null and b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Release/m3db.tlog/CL.read.1.tlog differ diff --git a/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Release/m3db.tlog/CL.write.1.tlog b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Release/m3db.tlog/CL.write.1.tlog new file mode 100644 index 00000000..0553d180 Binary files /dev/null and b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Release/m3db.tlog/CL.write.1.tlog differ diff --git a/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Release/m3db.tlog/link.command.1.tlog b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Release/m3db.tlog/link.command.1.tlog new file mode 100644 index 00000000..2b6c0106 Binary files /dev/null and b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Release/m3db.tlog/link.command.1.tlog differ diff --git a/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Release/m3db.tlog/link.read.1.tlog b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Release/m3db.tlog/link.read.1.tlog new file mode 100644 index 00000000..6033d935 Binary files /dev/null and b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Release/m3db.tlog/link.read.1.tlog differ diff --git a/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Release/m3db.tlog/link.write.1.tlog b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Release/m3db.tlog/link.write.1.tlog new file mode 100644 index 00000000..8be0409e Binary files /dev/null and b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Release/m3db.tlog/link.write.1.tlog differ diff --git a/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Release/m3db.tlog/m3db.lastbuildstate b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Release/m3db.tlog/m3db.lastbuildstate new file mode 100644 index 00000000..fb547569 --- /dev/null +++ b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Release/m3db.tlog/m3db.lastbuildstate @@ -0,0 +1,2 @@ +#TargetFrameworkVersion=v4.0:PlatformToolSet=v141:EnableManagedIncrementalBuild=false:VCToolArchitecture=Native32Bit:WindowsTargetPlatformVersion=10.0.16299.0 +Release|x64|F:\Projects\research\vst24_gl_test\M3dB\vs2017\m3db\| diff --git a/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Release/m3db.tlog/m3db.write.1u.tlog b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Release/m3db.tlog/m3db.write.1u.tlog new file mode 100644 index 00000000..da989482 Binary files /dev/null and b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Release/m3db.tlog/m3db.write.1u.tlog differ diff --git a/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Release/plugin.obj b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Release/plugin.obj new file mode 100644 index 00000000..676e6ae0 Binary files /dev/null and b/other/vst2_lglw_debug_plugin/vs2017/m3db/m3db/x64/Release/plugin.obj differ diff --git a/other/vst2_lglw_debug_plugin/vs2017/m3db/x64/Release/m3db.iobj b/other/vst2_lglw_debug_plugin/vs2017/m3db/x64/Release/m3db.iobj new file mode 100644 index 00000000..133f593b Binary files /dev/null and b/other/vst2_lglw_debug_plugin/vs2017/m3db/x64/Release/m3db.iobj differ diff --git a/other/vst2_lglw_debug_plugin/vs2017/m3db/x64/Release/m3db.ipdb b/other/vst2_lglw_debug_plugin/vs2017/m3db/x64/Release/m3db.ipdb new file mode 100644 index 00000000..82d2507e Binary files /dev/null and b/other/vst2_lglw_debug_plugin/vs2017/m3db/x64/Release/m3db.ipdb differ diff --git a/src/util/logger.cpp b/src/util/logger.cpp index 3caa4e06..68f14bd3 100644 --- a/src/util/logger.cpp +++ b/src/util/logger.cpp @@ -56,7 +56,11 @@ static void loggerLogVa(LoggerLevel level, const char *file, int line, const cha if (global->logger.logFile == LOG_STDFILE) fprintf(global->logger.logFile, "\x1B[0m"); vfprintf(global->logger.logFile, format, args); - vprintf(format, args); // xxx + + // TODO + // At least for me, this will cause a complete crash from __strlen_avx512 + // vprintf(format, args); // xxx + printf("\n"); // xxx fprintf(global->logger.logFile, "\n"); fflush(global->logger.logFile);